#550 Wrong or incomplete debug information in Linux

open
nobody
None
5
2011-09-20
2011-09-20
Anonymous
No

NASM produces now wrong or incomplete (I don't know) debug information for ELF32 and ELF64 executable formats in Linux.
I have tested 3 versions of NASM:
1) version 0.99.06-20071101 compiled on Sep 16 2008
2) version 2.09.04 compiled on Nov 26 2010
3) version 2.10rc8 compiled on Sep 20 2011
Only the oldest (1) produces a debug info that is fully readable for gdb.
Including -g flag in versions (2) or (3) produces some kind of debug information, but it is not "visible" to gdb! I can't "step into" the assembly language source code.

objdump -g some_file.o <or>
objdump -S some_file.o

shows that some kind of debug info is actually included, but it looks like it is not enough or even wrong(!) for gdb.
I have also observed that the size of *.o file produced in version (1) is somewhat bigger than one in versions (2) or (3) for the same *.asm source file and using exactly (literally) the same input flags.
I have tested this for many source files (always with the same result). The extremely simple sample files are included.

Building instructions:
nasm -f elf32 -g -F stabs test.asm (I explicitly specified output and debug format just to be sure, DWARF debug format was tested as well)
gcc -m32 -g -o test test.c test.o (or gcc -g -o test test.c test.o in 32 bit Linux)

I've included (maybe for comprison) my generated object files for test.asm:
test.o.1 - 992 bytes, file generated by version (1) of NASM, this file is OK
test.o.23 - 880 bytes, generated by version (2) or (3), this file is NOT OK

Running gdb.

version (1):
bogdan@bogdan-desktop:~/Pulpit/debug (kopia)$ gdb test
GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
<...>
Reading symbols from /home/bogdan/Pulpit/debug (kopia)/test...done.
(gdb) break main
Breakpoint 1 at 0x804839d: file test.c, line 6.
(gdb) run
Starting program: /home/bogdan/Pulpit/debug (kopia)/test

Breakpoint 1, main (argc=1, argv=0xffffd3c4) at test.c:6
6 d = dummy(12345);
(gdb) step
dummy () at test.asm:19
19 mov eax, param1
(gdb)

version (2) or (3):
bogdan@bogdan-desktop:~/Pulpit/debug (kopia)$ gdb test
GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
<...>
Reading symbols from /home/bogdan/Pulpit/debug (kopia)/test...done.
(gdb) break main
Breakpoint 1 at 0x804839d: file test.c, line 6.
(gdb) run
Starting program: /home/bogdan/Pulpit/debug (kopia)/test

Breakpoint 1, main (argc=1, argv=0xffffd3c4) at test.c:6
6 d = dummy(12345);
(gdb) step
8 return 0;
(gdb)

Discussion

  • source and object files helpful in diagnosing the problem

     
    Attachments
  • Bogdan O.
    Bogdan O.
    2011-09-26

    I walked a little bit trough the NASM source tree and found that the last version that seems to work (as I expect it to do) is v2.07 however the *.o file size is the same as that produced by the latest version. I didn't check all commits...
    Anyway I hope this bug report won't go to /dev/null :)

     
  • Bogdan O.
    Bogdan O.
    2011-10-04

    It's me again :/
    Here is the commit that somehow broke the normal behavior of debugging on ELF systems:

    Author: Cyrill Gorcunov <gorcunov@gmail.com> 2009-09-14 20:10:08
    Committer: Cyrill Gorcunov <gorcunov@gmail.com> 2009-09-14 20:43:30
    Parent: 28032a027c1739bcee8fcaa26257f842a4945408 (output/elfcommon.h: tab/space cleanup)
    Child: 2726889ece207fa8d5601d4c6baacaca4d1856e6 (New NSIS script)
    Branches: master, remotes/origin/insns, remotes/origin/master, remotes/origin/nasm-2.08.xx, remotes/origin/nasm-2.09.xx, remotes/origin/nsis2, remotes/origin/owc, remotes/origin/path, remotes/origin/pragma, remotes/origin/preproc-paste-fix, remotes/origin/preproc-rewrite
    Follows: nasm-2.07
    Precedes: nasm-2.08rc1

    elf,stabs: stabs32/64_generate -- append ending token

    This represent "end of compilation unit" token.
    Since gcc does (almost) the same lets be on the
    same side.

    Though to be precise gcc puts offset which points
    to the first byte right after the last instruction
    issued but in fact string index is analyzed only
    so we may safely write zero here (without relocation
    as well).

    Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>

    ------------------------------ output/outelf32.c ------------------------------
    index 23d576e..47c9d10 100644
    @@ -1689,19 +1689,16 @@ static void stabs32_generate(void)
    /*
    * worst case size of the stab buffer would be:
    * the sourcefiles changes each line, which would mean 1 SOL, 1 SYMLIN per line
    + * plus one "ending" entry
    */
    - sbuf =
    - (uint8_t *)nasm_malloc((numlinestabs * 2 + 3) *
    - sizeof(struct stabentry));
    -
    + sbuf = (uint8_t *)nasm_malloc((numlinestabs * 2 + 4) *
    + sizeof(struct stabentry));
    ssbuf = (uint8_t *)nasm_malloc(strsize);
    -
    rbuf = (uint8_t *)nasm_malloc(numlinestabs * 8 * (2 + 3));
    rptr = rbuf;

    - for (i = 0; i < numfiles; i++) {
    + for (i = 0; i < numfiles; i++)
    strcpy((char *)ssbuf + fileidx[i], allfiles[i]);
    - }
    ssbuf[0] = 0;

    stabstrlen = strsize; /* set global variable for length of stab strings */
    @@ -1764,6 +1761,10 @@ static void stabs32_generate(void)

    }

    + /* this is an "ending" token */
    + WRITE_STAB(sptr, 0, N_SO, 0, 0, 0);
    + numstabs++;
    +
    ((struct stabentry *)sbuf)->n_desc = numstabs;

    nasm_free(allfiles);

    ------------------------------ output/outelf64.c ------------------------------
    index 53bc4c5..b005693 100644
    @@ -1763,21 +1763,19 @@ static void stabs64_generate(void)
    }
    }

    - /* worst case size of the stab buffer would be:
    - the sourcefiles changes each line, which would mean 1 SOL, 1 SYMLIN per line
    + /*
    + * worst case size of the stab buffer would be:
    + * the sourcefiles changes each line, which would mean 1 SOL, 1 SYMLIN per line
    + * plus one "ending" entry
    */
    - sbuf =
    - (uint8_t *)nasm_malloc((numlinestabs * 2 + 3) *
    - sizeof(struct stabentry));
    -
    + sbuf = (uint8_t *)nasm_malloc((numlinestabs * 2 + 4) *
    + sizeof(struct stabentry));
    ssbuf = (uint8_t *)nasm_malloc(strsize);
    -
    rbuf = (uint8_t *)nasm_malloc(numlinestabs * 16 * (2 + 3));
    rptr = rbuf;

    - for (i = 0; i < numfiles; i++) {
    + for (i = 0; i < numfiles; i++)
    strcpy((char *)ssbuf + fileidx[i], allfiles[i]);
    - }
    ssbuf[0] = 0;

    stabstrlen = strsize; /* set global variable for length of stab strings */
    @@ -1841,6 +1839,10 @@ static void stabs64_generate(void)

    }

    + /* this is an "ending" token */
    + WRITE_STAB(sptr, 0, N_SO, 0, 0, 0);
    + numstabs++;
    +
    ((struct stabentry *)sbuf)->n_desc = numstabs;

    nasm_free(allfiles);

     
  • So, if you drop the snippet below it becomes fine again?

    + /* this is an "ending" token */
    + WRITE_STAB(sptr, 0, N_SO, 0, 0, 0);
    + numstabs++;
    +

     
  • And no, this report wont go to /dev/null, we're simply a bit busy at moment, sorry for inconvenience

     
  • Bogdan O.
    Bogdan O.
    2011-10-04

    Yes, when this code snippet is deleted, debugging works fine again :) But I must mention that my tests were just quick and not deep.

     
  • OK, thanks for testing! Actually there were a reason while I've pushed this snipped in. But I'll re-check as soon as I get spare time to. Thanks again!

     
  • Bogdan O.
    Bogdan O.
    2011-10-04

    No problem :)