了解gdb where命令的输出

时间:2019-04-13 20:11:58

标签: gdb x86-64

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

[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的堆栈帧。

1 个答案:

答案 0 :(得分:1)

  

但是,where的输出如下:

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

在没有DWARF信息的情况下,GDB会使用某些启发式方法进行猜测。 GDB在这里将else视为函数,并尝试找到其调用方,结果很糟糕。实际上,where在没有DWARF展开信息的情况下不适用于程序,除非该程序仅使用C功能标签并使用帧指针。