如何在 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 时,btmylabel 显示为函数名称,而我希望它改为 _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 是不是可以在函数上以非交互方式有条件地中断?

如何在 Windows 上构建 GDB

gnu ld/gdb:单独的调试文件。当需要链接的调试信息过多时如何生成调试文件?

GNU 汇编器中的本地标签; gdb 打印回溯,就好像标签是函数一样

GDB 在函数结束处中断而不是指定断点

使用GNU/gdb调试Linux C/C++可执行程序查看出错源代码、设置断点