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



我正在尝试查找正在运行的程序源代码中使用某些系统调用的所有位置。我设置断点如下:

catch syscall socketcall

。哪个工作正常。但是,当实际命中其中一个断点时,回溯看起来始终相同:

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

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

为什么 GCC 不能遍历堆栈并显示一直到主堆栈的完整堆栈跟踪?

很可能是因为 syscall_cp.s 中的手写程序集缺少展开描述符,并且不使用帧指针。GDB需要其中之一。另请参阅此答案。

特别是对于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    $2, $4
    move    $4, $5
    move    $5, $6
@@ -13,6 +14,7 @@ __syscall:
    lw      $9, 24($sp)
    lw      $10,28($sp)
    subu    $sp, $sp, 32
+   .cfi_adjust_cfa_offset 32
    sw      $8, 16($sp)
    sw      $9, 20($sp)
    sw      $10,24($sp)
@@ -21,6 +23,8 @@ __syscall:
    syscall
    beq     $7, $0, 1f
    addu    $sp, $sp, 32
+    .cfi_adjust_cfa_offset -32
    subu    $2, $0, $2
 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, $25
    move $6, $ra
    lw $25, %call16(__dlsym)($gp)
    addiu $sp, $sp, -16
+   .cfi_adjust_cfa_offset 16
    sw $ra, 12($sp)
+    .cfi_rel_offset $ra, 12
    jalr $25
    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      $4, 0($4)
+   .cfi_remember_state
    bne     $4, $0, __cp_cancel
    move    $2, $5
    move    $4, $6
@@ -35,14 +38,18 @@ __cp_begin:
 __cp_end:
    beq     $7, $0, 1f
    addu    $sp, $sp, 32
+   .cfi_adjust_cfa_offset -32
    subu    $2, $0, $2
 1: jr      $ra
    nop
 __cp_cancel:
+    .cfi_restore_state
    move    $2, $ra
+   .cfi_register $ra, $2
    bal     1f
    addu    $sp, $sp, 32
+   .cfi_adjust_cfa_offset -32
    .gpword .
    .gpword __cancel
 1: lw      $3, ($ra)
@@ -51,3 +58,5 @@ __cp_cancel:
    addu    $25, $25, $3
    jr      $25
    move    $ra, $2
+   .cfi_restore $ra
+   .cfi_endproc
-- 
2.24.0

最新更新