我正在Ubuntu上用NASM组装一个x86-64程序:
nasm -f elf64 -g -F dwarf -o foo.o foo.asm
ld -o foo foo.o
资料来源:
section .text
global _start
_start:
mov rax, 60 ;SYS_exit
mov rdi, 0 ;EXIT_SUCCESS
syscall
用GDB调试程序并不显示指令来自哪个文件或行号。例如,break _start
显示“断点1在0x 401000”而不是“断点1在0x 400080:file foo.asm,line 4.”,如blog post中所示。切换到layout regs
会显示“No Source Available”,而不是在源代码中找到当前指令的位置。list
确实会显示源代码,但在单步执行下一条指令时会切换回“No Source Available”。objdump -g foo
似乎显示所需的调试信息已存在:
foo: file format elf64-x86-64
...
The File Name Table (offset 0x1c):
Entry Dir Time Size Name
1 0 0 0 foo.asm
Line Number Statements:
[0x00000028] Extended opcode 2: set Address to 0x401000
[0x00000033] Special opcode 8: advance Address by 0 to 0x401000 and Line by 3 to 4
[0x00000034] Special opcode 76: advance Address by 5 to 0x401005 and Line by 1 to 5
[0x00000035] Special opcode 76: advance Address by 5 to 0x40100a and Line by 1 to 6
[0x00000036] Advance PC by 2 to 0x40100c
[0x00000038] Extended opcode 1: End of Sequence
Ubuntu 22.04、NASM 2.15.05、GDB 12.09版本
3条答案
按热度按时间6ie5vjzr1#
我安装了一个Ubuntu 22.04 VM,发现我可以重现您在那里看到的问题,但是,在我的本地计算机上,我无法重现该问题。
我注意到在我的本地机器上我使用的是nasm 2.14.02,而在Ubuntu机器上我使用的是2.15.05。
如果我们检查两个可执行文件的
objdump -g
输出,下面是我从工作的可执行文件中看到的部分内容:下面是损坏的可执行文件中的相同部分:
关键的区别是
DW_AT_high_pc
,这似乎是2.15.05 nasm的错误。我手动编辑了这个值,突然之间,我可以调试以前损坏的可执行文件了。这似乎是nasm的2.15.05中的一个回归,您应该考虑降级nasm(我认为2.15.05是当前的最新版本),或者可能提交一个nasm bug。
w1jd8yoj2#
正如Andrew所指出的,这确实是nasm(https://bugzilla.nasm.us/show_bug.cgi?id=3392798)中的一个bug。它不会通过降级来修复,因为据我所知,这个bug已经很老了。
这个bug现在已经很明显了,因为旧版本的GNU ld有一个问题补充了这个问题(使它不易察觉)。
好的部分是,我已经发送了一个非常简单和小的补丁(我觉得很舒服的想法是正确的阅读后,通过ld-nasm的互动和为什么它没有被发现之前)。
如果您想阅读该补丁(如果您发现问题,甚至可以留下有用的评论),请访问:https://github.com/netwide-assembler/nasm/pull/35
此外,如果你使用Ubuntu 22.04,我已经构建了一个补丁.deb,它应该相对容易安装https://github.com/iglosiggio/nasm/releases/tag/nasm-2.15.05-2。
ybzsozfc3#
IIRC,GDB可以很好地使用NASM的默认STABS输出,所以让它使用它来代替DWARF。Jester说GNU工具使用了一种新的DWARF格式,NASM不知道如何制作。但是它们仍然支持被DWARF取代的STABS格式。STABS对于Map源代码行到地址的简单任务来说非常好,这是像NASM这样简单的源代码语言所需要的全部。
只需使用不带
-F
选项的nasm -g
即可。或者也可以省略
-g
,您仍然可以得到符号名,而且除了基本的标签名之外,我在手工编写的asm中对调试信息没有太多的用处。(当然,节头文件也不需要在可执行文件中使用,只需要程序头文件。如果您尝试在FASM直接创建的可执行文件上使用GDB,您就会发现这一点。)我总是在
layout reg
之后使用layout n
,来切换到寄存器+反汇编。我不确定当前的行为是否是GDB的bug或什么。(在一些以前的版本中,layout next
/prev
都是必需的,就像它认为配置设置与UI实际显示的内容不同步一样)。无论如何,我基本上不希望GDB显示
.asm
源代码,我希望它显示我正在运行的任何东西的规范反汇编,以防我写的东西与它看起来不同。在asm源代码中使用有意义的标签名称将导致GDB显示以
sieve.crossout
或其他方式执行。尽管这对于大量的条件分支来说不太好,因为每个分支目标看起来都像是GDB的完整标签。