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 <[EMAIL PROTECTED]>
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
_______________________________________________
bug-binutils mailing list
bug-binutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-binutils