Search code examples
x86-64nasmelfdwarf

Usage of %line directive in NASM with dwarf debug format does not result in expected line numbers


I'm compiling the following code with NASM (nasm -g -F dwarf -f elf64 test.asm && gcc -g3 test.o).

global main

section .text

main:

%line 1 test.txt
PUSH 1337

%line 2 test.txt
PUSH 1338

%line 3 test.txt
PUSH 1339
%line 8 test.txt
POP RAX
%line 9 test.txt
POP RAX
%line 10 test.txt
POP RAX

RET

I would expect this to add the lines 1, 2, 3, 8, 9 and 10 to the dwarf data, however when I explore the file (using DWARF explorer, readelf or own code) I instead get the following lines:

test.txt                                       2              0x1130 (PUSH 1337)
test.txt                                       3              0x1135 (PUSH 1338)
test.txt                                       4              0x113a (PUSH 1339)
test.txt                                       9              0x113f (POP RAX)
test.txt                                      10              0x1140 (POP RAX)
test.txt                                      11              0x1141 (POP RAX)
test.txt                                      13              0x1142 (RET)

Every line number is one higher than what I provided in the assembly and in addition there is an extra line #13 situated at the ret statement. Could anyone explain what is going on here, and what I should do to get the expected result?


Solution

  • PUSH 1337 is on the line after the line you made line 1. So it seems %line sets the number of this line, and NASM's normal mechanism for counting line numbers continues to operate as normal. (Unlike GAS's deprecated .line which sets the line number of the next line.)

    The RET is 2 lines after the last POP RAX, so that makes sense.

    According to the manual, the full syntax includes an optional parameter to control line-number incrementing; apparently mmm defaults to 1:

    %line nnn[+mmm] filename
    

    So possibly (untested)

    %line 1+0  test.txt
    

    NASM -g is designed to make debug info for the asm source itself, not for the line numbers of some higher-level source file that was compiled to a .asm NASM file. The manual says it's intended for use with a macro-preprocessor (other than NASM's built-in macros), where it would make sense to have source line numbers increment.

    But if you want to hack up that functionality, if +0 doesn't work, I guess you could keep resetting the %line before every instruction, with the same line number repeatedly for ones in a block that all came from the same higher-level source line.

    And use the number before the one you want NASM to use. So I guess use %line 0 test.txt if you want the instruction on the next line to be reported as line 1 of test.txt, because 0 is the number before 1.

    (Assuming NASM supports using 0 as a line number, and rewinding the line number to have the same line twice.)

    I don't know of NASM directives equivalent in design to GAS's .loc which is intended for generating debug info for a C or other high-level source which compiled to a .s.