为什么 gdb backtrace 在捕获系统调用时只显示一帧?

Why does gdb backtrace show only one frame when catching syscall?

我试图在 运行 程序的源代码中找到所有使用特定系统调用的地方。我将断点设置为:

catch syscall socketcall

...工作正常。然而,当其中一个断点实际命中时,回溯看起来总是一样的:

(gdb) bt
#0  __cp_end () at src/thread/i386/syscall_cp.s:25

这就是她写的全部内容!为什么 GDB 不能遍历堆栈并显示一直到 main 的完整堆栈跟踪?

Why can't GCC walk the stack and show a full stacktrace going all the way up to main?

很可能是因为 syscall_cp.s 中的手写程序集缺少展开描述符,并且没有使用帧指针。 GDB 需要 一个或另一个。另见 this answer

特别是对于 MIPS,我必须将以下补丁应用于 musl 以获得有意义的堆栈跟踪。请记住,我真的不知道自己在做什么,但这对我有用。我本来希望有时间向上游提交这个,但它很老套,不完整,而且我不知道自己在做什么。不过,这里是:

diff --git a/src/internal/mips/syscall.s b/src/internal/mips/syscall.s
index 5d0def52..f9bc599d 100644
--- a/src/internal/mips/syscall.s
+++ b/src/internal/mips/syscall.s
@@ -4,6 +4,7 @@
 .hidden __syscall
 .type   __syscall,@function
 __syscall:
+    .cfi_startproc
    move    , 
    move    , 
    move    , 
@@ -13,6 +14,7 @@ __syscall:
    lw      , 24($sp)
    lw      ,28($sp)
    subu    $sp, $sp, 32
+   .cfi_adjust_cfa_offset 32
    sw      , 16($sp)
    sw      , 20($sp)
    sw      ,24($sp)
@@ -21,6 +23,8 @@ __syscall:
    syscall
    beq     , [=10=], 1f
    addu    $sp, $sp, 32
+    .cfi_adjust_cfa_offset -32
    subu    , [=10=], 
 1: jr      $ra
    nop
+   .cfi_endproc
diff --git a/src/ldso/mips/dlsym.s b/src/ldso/mips/dlsym.s
index 1573e519..f1036621 100644
--- a/src/ldso/mips/dlsym.s
+++ b/src/ldso/mips/dlsym.s
@@ -3,15 +3,21 @@
 .hidden __dlsym
 .type dlsym,@function
 dlsym:
+    .cfi_startproc
    lui $gp, %hi(_gp_disp)
    addiu $gp, %lo(_gp_disp)
    addu $gp, $gp, 
    move , $ra
    lw , %call16(__dlsym)($gp)
    addiu $sp, $sp, -16
+   .cfi_adjust_cfa_offset 16
    sw $ra, 12($sp)
+    .cfi_rel_offset $ra, 12
    jalr 
    nop
    lw $ra, 12($sp)
+    .cfi_restore $ra
    jr $ra
    addiu $sp, $sp, 16
+   .cfi_adjust_cfa_offset -16
+   .cfi_endproc
diff --git a/src/thread/mips/syscall_cp.s b/src/thread/mips/syscall_cp.s
index d2846264..ab173496 100644
--- a/src/thread/mips/syscall_cp.s
+++ b/src/thread/mips/syscall_cp.s
@@ -14,9 +14,12 @@
 .hidden __syscall_cp_asm
 .type   __syscall_cp_asm,@function
 __syscall_cp_asm:
+    .cfi_startproc
    subu    $sp, $sp, 32
+   .cfi_adjust_cfa_offset 32
 __cp_begin:
    lw      , 0()
+   .cfi_remember_state
    bne     , [=10=], __cp_cancel
    move    , 
    move    , 
@@ -35,14 +38,18 @@ __cp_begin:
 __cp_end:
    beq     , [=10=], 1f
    addu    $sp, $sp, 32
+   .cfi_adjust_cfa_offset -32
    subu    , [=10=], 
 1: jr      $ra
    nop

 __cp_cancel:
+    .cfi_restore_state
    move    , $ra
+   .cfi_register $ra, 
    bal     1f
    addu    $sp, $sp, 32
+   .cfi_adjust_cfa_offset -32
    .gpword .
    .gpword __cancel
 1: lw      , ($ra)
@@ -51,3 +58,5 @@ __cp_cancel:
    addu    , , 
    jr      
    move    $ra, 
+   .cfi_restore $ra
+   .cfi_endproc
-- 
2.24.0