GDB 不会从 NASM 加载源行

GDB does not load source lines from NASM

提问人:Joey Shepard 提问时间:6/21/2022 更新时间:2/5/2023 访问量:1118

问:

我正在使用 NASM 在 Ubuntu 上组装一个 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 调试程序不会显示指令来自哪个文件或行号。例如,显示“0x401000处的断点 1”,而不是“0x400080处的断点 1:文件 foo.asm,第 4 行”,如本博客文章所示。切换到显示“无可用源”,而不是在源中找到当前指令的位置。 确实显示源,但在单步执行下一条指令时,它会切换回“无可用源”。break _startlayout regslist

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

程序集 GDB x86-64 NASM

评论

0赞 Michael Petch 6/21/2022
您使用什么确切的命令在调试器中运行程序?
0赞 xiver77 6/21/2022
为什么需要查看源代码行来调试汇编程序?调试器已可以通过其反汇编程序显示程序的程序集指令。
0赞 Jester 6/21/2022
显然,最近的 gnu 工具切换到了 nasm 还不能产生的更新的矮化格式。
0赞 Joey Shepard 6/21/2022
@MichaelPetch,然后运行.@xiver77,是的,gdb 可以在您执行每一行时显示反汇编,但由于您丢失了符号名称,因此很难跟踪反汇编中的原始数字。此外,当您需要逐步执行一些指令以找到您关心的指令时,在执行时能够看到整个源代码会快得多。b _startrun
0赞 Joey Shepard 6/21/2022
@Jester,谢谢。那么,也许降级 gdb 并等待 NASM 赶上?

答:

3赞 Peter Cordes 6/21/2022 #1

debug-info 生成中存在一个长期存在的 NASM 错误,已在 2.16 中修复。从 NASM 文档中的发行说明中:

  • 修复了 ELF 输出格式的 DWARF 调试格式(字段中的信息不正确)中的代码范围生成错误。这个错误碰巧被旧版本的 GNU binutils 链接器中的一个错误所抵消,但与其他链接器和更新的或其他期望遵循规范的链接器一起中断。DW_AT_high_pc

老答案:调试机器码,忘源码。或使用 STABS

IIRC,GDB 可以很好地与 NASM 的默认 STABS 输出配合使用,所以让它使用它而不是 DWARF。Jester说,GNU工具使用一种更新的DWARF格式,NASM不知道如何制作。但它们仍然支持 DWARF 取代的 STABS 格式。STABS 对于将源行映射到地址的简单任务来说绰绰有余,这就是像 NASM 这样的简单源语言所需要的全部内容。

无需任何选项即可使用。nasm -g-F

或者也省略 -g:您仍然可以获得符号名称,除了基本的标签名称之外,我在手写的 asm 中从未对调试信息有太多用处。(当然还有节头,在可执行文件中也不需要,只需要程序头。如果您尝试在 FASM 直接创建的可执行文件上使用 GDB,就会发现这一点。


我总是在布局注册后使用布局 n,以切换到寄存器 + 反汇编。过去就是这样;我不确定当前的行为是 GDB 错误还是什么。(在以前的某个版本中,两者都是必需的,就像它认为配置设置与 UI 实际显示的内容不同步一样)。layout reglayout nextprev

无论如何,我基本上从不希望 GDB 显示源代码,我希望它显示我正在运行的任何内容的规范反汇编,以防我编写一些与外观不同的组装内容。.asm

在 asm 源中使用有意义的标签名称将导致 GDB 显示执行或其他内容。尽管有很多条件分支不太好,因为每个分支目标看起来都像是 GDB 的完整标签。sieve.crossout

评论

1赞 Joey Shepard 6/21/2022
GDB 对我来说也不适用于刺伤。您是否尝试过使用最新版本的 NASM 和 GDB?也许是什么导致他们停止支持旧版本的矮人,导致他们也删除了刺伤支持。感谢您的提示,这是一个很好的临时解决方案。就我而言,我绝对需要查看行使用了哪些变量和常量,为此,我需要原始源而不是反汇编。layout n.
0赞 Peter Cordes 6/21/2022
@JoeyShepard:不,我没有尝试,对不起。回复:变量定义需要行号:我想它们的名称不够唯一,无法在编辑器中搜索?否则,这将是不太方便的工作流程。很公平。
1赞 Peter Cordes 6/21/2022
@JoeyShepard:刚刚尝试过 / / ,是的,我在源窗格中显示源,是的,打印文件名和行号。我已经有几个月没有更新我的 Arch Linux,所以我使用的是 GDB 11.2 和 NASM 2.15.05。(GNU Binutils 版本 2.36.1)nasm -felf64 -g foo.asmld -o foo foo.ogdb foolayout regb sym
0赞 Peter Cordes 8/28/2022
半相关回复:错误的调试信息:在使用 YASM -g dwarf2 构建的程序构建的 GDB 中设置断点会更改程序行为和段错误,或者 SIGILL 有关于 YASM 错误的详细信息,但 NASM 2.15.05 也不起作用。与安德鲁在他们的回答中报告的相同。
6赞 Andrew 6/21/2022 #2

我设置了一个 Ubuntu 22.04 VM,发现我可以重现您在那里看到的问题,但是,在我的本地计算机上,我无法重现该问题。

我注意到在我的本地机器上我使用的是 nasm 2.14.02,而在 Ubuntu 机器上我使用的是 2.15.05。

如果我们检查两个可执行文件的输出,以下是我从工作可执行文件中看到的部分内容:objdump -g

Contents of the .debug_info section (loaded from foo):

  Compilation Unit @ offset 0x0:
   Length:        0x45 (32-bit)
   Version:       3
   Abbrev Offset: 0x0
   Pointer Size:  8
 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <c>   DW_AT_low_pc      : 0x401000
    <14>   DW_AT_high_pc     : 0x40100c
    <1c>   DW_AT_stmt_list   : 0x0
    <20>   DW_AT_name        : foo.asm
    <28>   DW_AT_producer    : NASM 2.14.02
    <35>   DW_AT_language    : 32769    (MIPS assembler)
 <1><37>: Abbrev Number: 2 (DW_TAG_subprogram)
    <38>   DW_AT_low_pc      : 0x401000
    <40>   DW_AT_frame_base  : 0x0 (location list)
 <1><44>: Abbrev Number: 0

这是损坏的可执行文件中的相同部分:

Contents of the .debug_info section (loaded from foo):

  Compilation Unit @ offset 0x0:
   Length:        0x45 (32-bit)
   Version:       3
   Abbrev Offset: 0x0
   Pointer Size:  8
 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <c>   DW_AT_low_pc      : 0x401000
    <14>   DW_AT_high_pc     : 0x401000
    <1c>   DW_AT_stmt_list   : 0x0
    <20>   DW_AT_name        : foo.asm
    <28>   DW_AT_producer    : NASM 2.15.05
    <35>   DW_AT_language    : 32769    (MIPS assembler)
 <1><37>: Abbrev Number: 2 (DW_TAG_subprogram)
    <38>   DW_AT_low_pc      : 0x401000
    <40>   DW_AT_frame_base  : 0x0 (location list)
 <1><44>: Abbrev Number: 0

关键区别在于 ,这似乎与 2.15.05 nasm 有关。我手动进入并编辑了这个值,突然间,我可以很好地调试以前损坏的可执行文件。DW_AT_high_pc

这似乎是 nasm 2.15.05 中的回归,您应该考虑降级 nasm(我认为 2.15.05 是当前的最新版本),或者可能提交 nasm 错误。

评论

0赞 Christian Singer 1/9/2023
我认为这很简单,但是您如何在 Ubuntu 上降级 nasm ?
0赞 Peter Cordes 2/5/2023
事实证明,它实际上是一个长期存在的 NASM 错误(在 2.16.01:nasm.us/doc/nasmdocc.html 中修复),但被最近修复的 GNU Binutils 中的一个错误所抵消。因此,降级 NASM 无济于事,而且您可能不想降级系统的 .ldld
2赞 mega 8/28/2022 #3

正如安德鲁所指出的,这确实是nasm(https://bugzilla.nasm.us/show_bug.cgi?id=3392798)中的一个错误。它不会通过降级来修复,因为据我所知,这个错误已经很老了。

该错误现在是父错误,因为旧版本的 GNU ld 有一个补充这个问题的问题(使其难以察觉)。LLD 和 gold 的 AFAIK 用户很久以前就遇到了这个问题。

好的部分是我发送了一个非常简单的小补丁(在阅读了 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

4赞 Ian 1/28/2023 #4

我有同样的情况“单步执行直到退出函数 main,它没有行号信息。我检查了 gcc 和 gdb 版本,但需要记住 nasm。 我在 2.15.05 版中遇到了这个问题。所以我将 nasm 升级到 2.16.01 版本,没关系。

评论

1赞 Peter Cordes 1/28/2023
是的,发行说明提到了 DWARF 调试信息的相关错误修复。nasm.us/doc/nasmdocc.html
0赞 Peter Cordes 2/5/2023
请不要在其他人清理后将“非常感谢”之类的绒毛编辑回您的帖子中。请参阅编辑问题时是否应该删除“绒毛”(如问候语、签名、“谢谢”等)以及为什么其他用户从我的问题中删除了谢谢? / 是否应该从帖子中删除“嗨”、“谢谢”、标语和称呼? 回复:编辑掉这样的东西是 SO 的标准做法。以后,请保持技术性,为大家省去麻烦。