assembly - 了解进入标签时 gdb 中“堆栈”显示的内容
问题描述
我有以下程序集:
_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
函数,并且它认为该函数是从 address 处的某些代码调用的0x1
,该代码是从 address 调用的0x7fffffffe5aa
,等等。
为什么它会显示这样的东西?
它很困惑。
似乎堆栈仍应显示一行:
正确的。
现在,您的下一个问题可能是“为什么 GDB 会感到困惑?”。
答案有些复杂。
在不使用专用帧指针寄存器的平台上,例如GDBx86_64
没有通用的方法来展开堆栈,它需要编译器的帮助才能这样做。编译器创建“展开表”,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
可以在此处找到各种指令的文档。
推荐阅读
- php - Laravel\Lumen 获取预加载参数并发送到另一个预加载
- java - 如何在带有 Bazel 的 Android 中使用房间数据库?
- html - 如何通过最后带有“/index.html”的“url”访问反应应用程序?
- excel - 如何使用特定标题合并多个工作簿
- cocoapods - 将 cocoapods-art 插件添加到 podspec 以实现私有 repo 依赖
- spring-mvc - 如何将从客户端上传的文件存储到 jboss 独立目录?
- javascript - 从嵌套数组聚合数据
- python - 如何使用多个变量发送到 Impala 用于 Python 中的 SQL 语句
- tcp - 使用 Node-RED 获取 TCP/IP 连接
- angular - 将 Angular 4 升级到 7 时服务不起作用