如何在 GDB 可以中断但不能算作函数的 GNU GAS ELF 输出中制作本地标签?
Posted
技术标签:
【中文标题】如何在 GDB 可以中断但不能算作函数的 GNU GAS ELF 输出中制作本地标签?【英文标题】:How to make local labels in GNU GAS ELF output that GDB can break on but not count as functions? 【发布时间】:2019-08-09 03:24:38 【问题描述】:当使用 GNU GAS 手动编写程序集时,我想在一个函数中设置一个标签:
GDB 不会将该标签视为函数名 我可以使用b mylabel
打破标签
nasm
的类似问题已在 Break at local label using GDB for NASM assembly 提出,但我想在这里更准确地说,我需要 GNU GAS 和 ELF 输出。
例如如果我定义了一个普通标签mylabel
,如下所示:
main.S
.text
.global _start
_start:
/* exit */
mov $60, %rax
mylabel:
mov $0, %rdi
syscall
这并不让我满意,因为当 GDB 到达 mov $0, %rdi
时,bt
将 mylabel
显示为函数名称,而我希望它改为 _start
。特别是,这可能会破坏回溯,因为 GDB 找不到堆栈帧:How gdb reconstructs stacktrace for C++?
但是,如果我将 mylabel
替换为 .Lmylabel
,如下所述:Local labels in GNU assembler; gdb printing backtrace as though labels are functions 则 _start
是所需的函数名称,但 b .Lmylabel
失败。 nm
也根本不显示符号。
ELF / DWARF 格式是否支持任何可以使用的东西,有没有办法通过 GNU GAS 来公开它?
在 Ubuntu 18.10、GDB 8.2、GNU GAS 2.31.1 中测试。
【问题讨论】:
【参考方案1】:我不确定这是否符合您的需求,但您可以这样做(对于非 PIE 二进制文件,请使用 -no-pie
链接):
.text
.global _start
_start:
/* exit */
mov $60, %rax
.Lmylabel:
mov $0, %rdi
syscall
.section .rodata
mylabel:
.long .Lmylabel
然后,您可以使用break *mylabel
设置断点(注意*
):
(gdb) break *mylabel
Breakpoint 2 at 0x401007: file t.S, line 7.
由于mylabel
或多或少是一个函数指针,GDB 对此一无所知,将忽略它:
Breakpoint 1, _start () at t.S:5
5 mov $60, %rax
(gdb) si
7 mov $0, %rdi
使用链接器脚本,应该可以将mylabel
符号放入未加载的部分,以减少运行时开销。
【讨论】:
嗨,弗洛里安,我会记住这个提示,但它太老套了,我可能会让我的堆栈跟踪爆炸:-)(我的目标只是调试的用户友好性)。以上是关于如何在 GDB 可以中断但不能算作函数的 GNU GAS ELF 输出中制作本地标签?的主要内容,如果未能解决你的问题,请参考以下文章
仅当函数的返回值等于“Value”时,gdb 是不是可以在函数上以非交互方式有条件地中断?
gnu ld/gdb:单独的调试文件。当需要链接的调试信息过多时如何生成调试文件?