bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: addr2line reports wrong line number for abort(), gdb reports correct


From: Nick Clifton
Subject: Re: addr2line reports wrong line number for abort(), gdb reports correctly
Date: Tue, 08 Aug 2006 12:50:12 +0100
User-agent: Thunderbird 1.5.0.4 (X11/20060516)

Hi Sam,

gdb reports:
(gdb) bt
#0  0xffffe410 in __kernel_vsyscall ()
#1  0xb7e989a1 in raise () from /lib/tls/i686/cmov/libc.so.6
#2  0xb7e9a2b9 in abort () from /lib/tls/i686/cmov/libc.so.6
#3  0x0804836b in level_aa () at ab.c:5
#4  0x0804838c in main () at ab.c:10

% addr2line -e ab 0x0804836b
/home/sroberts/s/segv/ab.c:9

% cat ab.c
#include <stdlib.h>

void level_aa()
{
        abort(); /* <- this is line 5, gdb is correct */
}

int main()
{
        level_aa();
        return 0;
}

Actually there is no bug here, it is just that GDB is being extra clever. The problem is that the abort() call never returns, so GCC does not generate any function epilogue code at the end of level_aa(). Thus the return address on the stack for call frame #3 does not actually point to any code in level_aa() at all, it points to whatever follows level_aa in memory. Which in this case happens to be main().

Take a look at this disassembly of main and level_aa:

00000000004004a8 <level_aa>:
  4004a8:       55                      push   %rbp
  4004a9:       48 89 e5                mov    %rsp,%rbp
  4004ac:       e8 2f ff ff ff          callq  4003e0 <address@hidden>

00000000004004b1 <main>:
  4004b1:       55                      push   %rbp
  4004b2:       48 89 e5                mov    %rsp,%rbp
  4004b5:       b8 00 00 00 00          mov    $0x0,%eax
  4004ba:       e8 e9 ff ff ff          callq  4004a8 <level_aa>
  4004bf:       b8 00 00 00 00          mov    $0x0,%eax
  4004c4:       c9                      leaveq
  4004c5:       c3                      retq

The addresses are different because I am using a different machine to you, but the principle is the same. Notice how the CALLQ instruction at 0x4004ac is not followed by any code to return from the level_aa function.

Now have a look at the stack backtrace as displayed by GDB after the abort function has been called:

 #0  0x0000003378b2e2ed in raise () from /lib64/tls/libc.so.6
 #1  0x0000003378b2fa3e in abort () from /lib64/tls/libc.so.6
 #2  0x00000000004004b1 in level_aa () at ab.c:5
 #3  0x00000000004004bf in main () at ab.c:10

The return address in frame #2 (0x4004b1) is actually the address of the first instruction of main(). GDB realises what has happened somehow and so it prints the source code line as being from 0x4004b0. Addr2line has no way of knowing this, so it can only follow what the debugging information says. Running "readelf -wl ab" shows this as:

 Special opcode 8: advance Address by 0 to 0x4004a8 and Line by 3 to 4
 Special opcode 62: advance Address by 4 to 0x4004ac and Line by 1 to 5
 Special opcode 79: advance Address by 5 to 0x4004b1 and Line by 4 to 9
 Special opcode 62: advance Address by 4 to 0x4004b5 and Line by 1 to 10
 Special opcode 146: advance Address by 10 to 0x4004bf and Line by 1 to 11
 Special opcode 76: advance Address by 5 to 0x4004c4 and Line by 1 to 12

Thus it displays address 0x4004b1 as being from line 9, which essentially is correct.

Cheers
  Nick




reply via email to

[Prev in Thread] Current Thread [Next in Thread]