为什么 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
我试图在 运行 程序的源代码中找到所有使用特定系统调用的地方。我将断点设置为:
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