backtrace/2024: backtrace fails when function ends with call to abort

wilson@tuliptree.org wilson@tuliptree.org
Tue Nov 1 23:08:00 GMT 2005


>Number:         2024
>Category:       backtrace
>Synopsis:       backtrace fails when function ends with call to abort
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Nov 01 23:08:01 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     wilson@tuliptree.org
>Release:        gdb-6.x
>Organization:
>Environment:
x86-linux/x86_64-linux
>Description:
This is GCC PR 24490, which I am cross filing as a gdb bug because I think it needs a gdb fix.

The problem is that if we use gcc-4.x to compile a simple testcase that calls abort, run it under gdb, and use the bt command, we get an incomplete backtrace.  The program is compiled with -O0 -g.  The testcase is

#include <stdlib.h>

int main( int argc, char** argv )
{   abort( );
    return 0;
}

The backtrace is
#0  0xffffe410 in __kernel_vsyscall ()
#1  0x00afa118 in raise () from /lib/libc.so.6
#2  0x00afb888 in abort () from /lib/libc.so.6
#3  0x080483a5 in main (argc=Could not find the frame base for "main".) at test.c:4

The backtrace failed because a number of things happened here.

Gcc notices that the main function ends with a call to a function that does not return, and optimizes away the epilogue.  This happens even with -O0.  Thus the call to abort is the last instruction in main.

Gcc emits a location list to describe the frame base, since it varies during the function.  This location list specifies the frame base for every PC in the function.

Gdb uses the return address to generate the backtrace of the caller.  On x86, the return address is one byte past the end of the call instruction.  In this case, this is 1 byte past the end of the function.  So gdb is trying to find the frame base for an address outside the function, and is failing, because the location list emitted by gcc only covers addresses inside the function.

The problem can be seen by running nm -S a.out to get the start address and size of main, and comparing against the address that gdb gave in the backtrace.  We see that gdb is using an address immediately after the end of the function.

I see a number of solutions here:
1) Gdb can be modified to subtract one from the return address, to ensure we get an address inside the function.  Gcc already effectively does this in the dwarf2 unwind support.
2) Gcc can pad the function with a nop or trap instruction, to ensure that the return address is always a valid function address.  The down side here is that this unnecessarily increases code size, which is bad.  Gcc already does this for the IA-64 port, but only because this is required by the IA-64 unwind info ABI.
3) gcc can emit location list info that covers the first byte past the end of the function.  This seems wrong, and may lead to trouble if we have two functions without any padding between them.
>How-To-Repeat:

>Fix:

>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the Gdb-prs mailing list