Reputation: 145
I'm assembling an x86-64 program on Ubuntu with NASM:
nasm -f elf64 -g -F dwarf -o foo.o foo.asm
ld -o foo foo.o
Source:
section .text
global _start
_start:
mov rax, 60 ;SYS_exit
mov rdi, 0 ;EXIT_SUCCESS
syscall
Debugging the program with GDB does not show what file or line number an instruction comes from. For example, break _start
shows "Breakpoint 1 at 0x401000" rather than "Breakpoint 1 at 0x400080: file foo.asm, line 4." as shown in this blog post. Switching to layout regs
shows "No Source Available" rather than where in the source the current instruction is found. list
does show the source, but it switches back to "No Source Available" upon stepping to the next instruction.
objdump -g foo
seems to show that the required debug information is there:
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
Upvotes: 11
Views: 1884
Reputation: 41
I have the same situation 'Single stepping until exit from function main, which has no line number information.' I checked the gcc and gdb versions but needed to remember the nasm. I have this problem in version 2.15.05. So I upgrade the nasm to version 2.16.01, and it's okay.
Upvotes: 4
Reputation: 364210
There was a longstanding NASM bug in debug-info generation, fixed in 2.16. From the release notes in the NASM docs:
- Fix a code range generation bug in the DWARF debug format (incorrect information in the
DW_AT_high_pc
field) for the ELF output formats. This bug happened to cancel out with a bug in older versions of the GNU binutils linker, but breaks with other linkers and updated or other linkers that expect the spec to be followed.
IIRC, GDB works fine with NASM's default STABS output, so let it use that instead of DWARF. Jester says GNU tools use a newer DWARF format that NASM doesn't know how to make. But they still support the STABS format that DWARF replaced. STABS is more than fine for the simple task for mapping source lines to addresses, which is all that's needed for a simple source language like NASM.
Just use nasm -g
without a -F
option.
Or leave out -g
as well: you still get symbol names, and I've never had much use for debug info in hand-written asm beyond basic label names. (And of course section headers, which are also not needed in an executable, just the program headers. As you'll find out if you try to use GDB on an executable created directly by FASM.)
I always use layout n
after layout reg
, to switch to registers + disassembly. That used to be what layout reg
was; I'm not sure if the current behaviour is a GDB bug or what. (In some previous version, both layout next
/ prev
were required, like it thought the config setting was out of sync with what the UI was actually displaying).
Anyway, I basically never want GDB displaying the .asm
source, I want it to show canonical disassembly of whatever I'm running, in case I wrote something that assembled differently from how it looks.
Using meaningful label names in your asm source will lead to GDB showing execution in sieve.crossout
or whatever. Although it's less nice with lots of conditional branching, since every branch target looks like a full label for GDB.
Upvotes: 6
Reputation: 21
As pointed by Andrew this is indeed a bug in nasm (https://bugzilla.nasm.us/show_bug.cgi?id=3392798). It will not be fixed by downgrading as the bug is pretty old from what I understand.
The bug is aparent right now because older version of GNU ld had an issue that complemented this one (making it imperceptible). AFAIK users of lld and gold were experiencing this issue long ago.
The nice part is that I've sent a really simple and small patch (and that I feel comfortable thinking is correct after reading through the ld-nasm interaction and why it wasn't discovered before).
If you are inclined to read the patch (maybe even leave helpful comments if you find an issue) it's here: https://github.com/netwide-assembler/nasm/pull/35
Also, if you use Ubuntu 22.04 I've built a patched .deb that should be relatively easy to install https://github.com/iglosiggio/nasm/releases/tag/nasm-2.15.05-2.
Upvotes: 2
Reputation: 4751
I setup an Ubuntu 22.04 VM and found that I could reproduce the issue that you are seeing there, however, on my local machine, I could not reproduce the problem.
I noticed that on my local machine I was using nasm 2.14.02, while on the Ubuntu machine I was using 2.15.05.
If we check the objdump -g
output on the two executables, here's part of what I see from the working executable:
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
And here's the same part from the broken executable:
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
The critical difference is the DW_AT_high_pc
, this appears to be wrong with the 2.15.05 nasm. I manually went in and edited this value, and suddenly, I can debug the previously broken executable just fine.
This appears to be a regression in 2.15.05 of nasm, you should consider downgrading nasm (I think 2.15.05 is the current latest release), or maybe file a nasm bug.
Upvotes: 7