我正在调试以下程序(这是正确的)。
[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
的初始函数。
但是,输出的位置如下:
在x86_64
,GDB希望程序有适当的DWARF
展开信息(你的程序完全缺乏)。 (Documentation关于如何使用.cfi
指令插入此类信息。)
没有DWARF
信息,GDB使用某些启发式猜测。在这里,GDB将else
视为一个函数,并试图找到它的调用者,带来灾难性的结果。实际上,where
对于没有DWARF
展开信息的程序效果不佳,除非该程序仅使用C
函数标签并使用帧指针。