了解进入标签时 'stack' 在 gdb 中显示的内容
Understanding what the 'stack' is showing in gdb when going into a label
我有以下程序集:
_start:
mov $strings, %rbx
mov , %r12d
print_loop:
mov %rbx, %rdi
这很简单,但是下面是它在 gdb
中针对这三个 lines/instructions 中的每一个显示的内容:
mov $strings, %rbx
0x00000000004000c4 ? mov [=12=]x6000ea,%rbx # memory address of 'strings'
─── Stack ──────────────────────────────────────────────────────────────────────────────────────────────────────
[0] from 0x00000000004000c4 in _start
mov , %r12d
0x00000000004000cb ? mov [=13=]x1,%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
What does that mean exactly,
这意味着 GDB 认为您在 print_loop
函数内部执行,并且它认为该函数是从地址 0x1
的某些代码调用的,而地址是从地址 0x7fffffffe5aa
调用的], 等等
and why does it show things like that?
一头雾水
It seems like the stack should still show one line:
正确。
现在,您的下一个问题可能是“为什么 GDB 会混淆?”。
答案有点复杂。
在不使用专用帧指针寄存器的平台上,例如x86_64
,GDB 没有一般 方法展开堆栈,它需要编译器的帮助。编译器创建“展开表”,GDB 将其解释为执行堆栈展开。
由于您是用汇编语言编写的,并且没有使用 .cfi_...
指令,因此您的代码没有任何展开描述符。
在没有展开描述符的情况下,GDB只能猜测,这里猜错了。
要解决此问题,您可以提供展开描述符,如下所示(未经测试):
_start:
.cfi_startproc
.cfi_undefined(rip) # no unwinding past this function
mov $strings, %rbx
mov , %r12d
print_loop:
mov %rbx, %rdi
...
.cfi_endproc
这应该不会混淆 GDB。可以找到各种 .cfi
指令的文档 here.
我有以下程序集:
_start:
mov $strings, %rbx
mov , %r12d
print_loop:
mov %rbx, %rdi
这很简单,但是下面是它在 gdb
中针对这三个 lines/instructions 中的每一个显示的内容:
mov $strings, %rbx
0x00000000004000c4 ? mov [=12=]x6000ea,%rbx # memory address of 'strings' ─── Stack ────────────────────────────────────────────────────────────────────────────────────────────────────── [0] from 0x00000000004000c4 in _start
mov , %r12d
0x00000000004000cb ? mov [=13=]x1,%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
What does that mean exactly,
这意味着 GDB 认为您在 print_loop
函数内部执行,并且它认为该函数是从地址 0x1
的某些代码调用的,而地址是从地址 0x7fffffffe5aa
调用的], 等等
and why does it show things like that?
一头雾水
It seems like the stack should still show one line:
正确。
现在,您的下一个问题可能是“为什么 GDB 会混淆?”。
答案有点复杂。
在不使用专用帧指针寄存器的平台上,例如x86_64
,GDB 没有一般 方法展开堆栈,它需要编译器的帮助。编译器创建“展开表”,GDB 将其解释为执行堆栈展开。
由于您是用汇编语言编写的,并且没有使用 .cfi_...
指令,因此您的代码没有任何展开描述符。
在没有展开描述符的情况下,GDB只能猜测,这里猜错了。
要解决此问题,您可以提供展开描述符,如下所示(未经测试):
_start:
.cfi_startproc
.cfi_undefined(rip) # no unwinding past this function
mov $strings, %rbx
mov , %r12d
print_loop:
mov %rbx, %rdi
...
.cfi_endproc
这应该不会混淆 GDB。可以找到各种 .cfi
指令的文档 here.