【问题标题】:Understanding output of gdb `where` command了解 gdb `where` 命令的输出
【发布时间】:2019-04-13 20:11:58
【问题描述】:

我正在调试以下程序(这是正确的)。

[OP@localhost 04]$ cat factorial.s
    .section .text
    .globl _start
    .globl _factorial
_start:
    push $4
    call factorial
    add $8, %rsp

    mov %rax, %rdi
    mov $60, %rax
    syscall

    .type factorial, @function
factorial:
    # Parameters
    #   n : int
    #       Number to take factorial of
    push %rbp
    mov %rsp, %rbp

    mov 0x10(%rbp), %rax
if: 
    cmp $1, %rax
    jne else

    jmp end_if
else:
    dec %rax
    push %rax
    call factorial
    add $8, %rsp

    imul 0x10(%rbp), %rax
end_if: 
    pop %rbp
    ret

我在阶乘函数处设置了一个断点,并继续了两次。检查%rsp的值,发现是

(gdb) print/$rsp
$1 = 0x7fffffffd698

检查周围的区域,我发现

(gdb) x /10xg 0x7fffffffd690
0x7fffffffd690: 0x0000000000000000  0x00007fffffffd6b0
0x7fffffffd6a0: 0x0000000000401030  0x0000000000000002
0x7fffffffd6b0: 0x00007fffffffd6c8  0x0000000000401030
0x7fffffffd6c0: 0x0000000000000003  0x0000000000000000
0x7fffffffd6d0: 0x0000000000401007  0x0000000000000004

大致上,这是人们所期望的。但是,where 的输出如下:

(gdb) where
#0  0x000000000040101b in factorial ()
#1  0x0000000000401030 in else ()
#2  0x0000000000000002 in ?? ()
#3  0x00007fffffffd6c8 in ?? ()
#4  0x0000000000401030 in else ()
#5  0x0000000000000003 in ?? ()
#6  0x0000000000000000 in ?? ()

我似乎无法理解。它似乎是按顺序读取堆栈,但我不知道数字 0x40101b 来自哪里(该数字不在堆栈上),我不确定它为什么停在那里,因为它没有打印出对factorial 的初始函数调用的堆栈帧。

【问题讨论】:

    标签: gdb x86-64


    【解决方案1】:

    但是 where 的输出如下:

    x86_64 上,GDB 期望程序具有正确的DWARF 展开信息(您的程序完全缺少该信息)。 (Documentation 关于如何使用 .cfi 指令插入此类信息。)

    没有DWARF 信息,GDB 会使用某些启发式方法进行猜测。这里 GDB 将else 视为一个函数,并试图找到它的调用者,结果是灾难性的。实际上,where 不适用于没有 DWARF 展开信息的程序,除非该程序仅使用 C 函数标签并使用帧指针。

    【讨论】:

    • 你的意思是只在实际的 C 函数上加上外部标签?即使用 .Lif 而不是 if 用于 GAS 根本不会放入目标文件的文件范围标签。 (因为避免 .globl if 不足以阻止 GAS 将它们放在 GDB 可以看到的地方。)
    猜你喜欢
    • 2012-02-07
    • 1970-01-01
    • 1970-01-01
    • 2011-05-10
    • 2015-01-18
    • 2021-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多