我有以下程序集:
_start:
mov $strings, %rbx
mov $1, %r12d
print_loop:
mov %rbx, %rdi
它很简单,但以下是它在gdb
中为这三行/指令中的每一行显示的内容:
mov $strings, %rbx
0x00000000004000c4 ? mov $0x6000ea,%rbx # memory address of 'strings' ─── Stack ────────────────────────────────────────────────────────────────────────────────────────────────────── [0] from 0x00000000004000c4 in _start
mov $1, %r12d
0x00000000004000cb ? mov $0x1,%r12d ─── Stack ─────────────────────────────────────────────────────────────────────────────────────────────────────── [0] from 0x00000000004000cb in _start
但在第三条指令上——标签后的第一条指令上,情况看起来很不稳定:
0x00000000004000d1 ? mov %rbx,%rdi ─── Stack ─────────────────────────────────────────────────────────────────────────────────────────────────────── [0] from 0x00000000004000d1 in print_loop [1] from 0x0000000000000001 [2] from 0x00007fffffffe5aa [3] from 0x0000000000000000
这到底意味着什么,为什么它会显示这样的东西?堆栈似乎仍然应该显示一行:
[0] from 0x00000000004000d1 in print_loop
- or -
[0] from 0x00000000004000d1 in _start
这到底意味着什么,
这意味着GDB认为您正在print_loop
函数内部执行,并且它认为此函数是从地址0x1
的某些代码调用的,而地址0x7fffffffe5aa
等则是从
为什么它会显示这样的东西?
它很混乱。
堆栈似乎仍然应该显示一行:
正确。
现在,你的下一个问题可能是";为什么GDB会感到困惑&";。
答案有些复杂。
在不使用专用帧指针寄存器的平台上,如x86_64
,GDB没有通用的方法来展开堆栈,需要编译器的帮助;展开台";,GDB将其解释为执行堆叠展开。
由于您是在程序集中编写的,并且没有使用.cfi_...
指令,因此您的代码没有任何展开描述符。
在没有展开描述符的情况下,GDB只能猜测,而这里的猜测是错误的。
要解决此问题,可以提供展开描述符,类似于以下内容(未经测试(:
_start:
.cfi_startproc
.cfi_undefined(rip) # no unwinding past this function
mov $strings, %rbx
mov $1, %r12d
print_loop:
mov %rbx, %rdi
...
.cfi_endproc
这应该会解开GDB。可以在此处找到各种.cfi
指令的文档。