【问题标题】:Why does gdb backtrace show only one frame when catching syscall?为什么 gdb 回溯在捕获系统调用时只显示一帧?
【发布时间】:2015-04-21 06:52:52
【问题描述】:

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

catch syscall socketcall

...运行良好。但是,当实际命中某个断点时,回溯看起来总是一样的:

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

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

【问题讨论】:

    标签: debugging gdb system-calls


    【解决方案1】:

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

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

    【讨论】:

    • 我已经确认手写 asm 不使用帧指针——因为有 6 个参数的系统调用的第 6 个参数需要 EBP(在 x86-32 Linux 上)。
    • 我用 CFI 指令添加了所需的堆栈帧信息,现在 GDB 可以显示这个汇编函数的回溯!刚刚向 musl libc 开发人员发送了一个补丁,希望他们能合并它。
    • 事实证明,这对于其他架构也是如此,尤其是在我的情况下是 MIPS,即使是来自 git 的最新 musl(截至 2020 年 1 月)。关于如何为 MIPS 添加 CFI 指令的任何建议?
    • 我添加了几个从示例中复制的 .cfi_def_cfa_offset 指令,仅在我观察问题的地方,我终于可以得到回溯,但我对 MIPS asm 或 abi 不太熟悉将它们添加到任何地方。
    • @DanielSantos 没有链接,它在我的笔记本电脑和我们公司的私人仓库中......但如果你愿意,我很确定我可以在这里发布这个作为“答案”
    【解决方案2】:

    特别是对于 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
    

    【讨论】:

    • 你是我的英雄!我会在上游得到这个。根据您的选择,请将您的全名、公司名称和/或电子邮件发送至 daniel@gsat.us,我会适当地注明信用。或者,我将在 cmets 中包含此链接。当我不得不跳到别的东西上时,我只是在深入研究这个(试图记住 .cfi 语法)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    • 2017-01-28
    相关资源
    最近更新 更多