Bug 24490 - [4.1 Regression] gcc / gdb backtrace problem
Summary: [4.1 Regression] gcc / gdb backtrace problem
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: debug (show other bugs)
Version: 4.1.0
: P2 normal
Target Milestone: 4.1.0
Assignee: Jim Wilson
URL:
Keywords: wrong-debug
Depends on:
Blocks:
 
Reported: 2005-10-23 04:08 UTC by Kevin Gilbert
Modified: 2005-11-14 21:09 UTC (History)
2 users (show)

See Also:
Host:
Target: i?86-*-* with dwarf2
Build:
Known to work: 4.0.0 3.4.0
Known to fail: 4.1.0
Last reconfirmed: 2005-11-01 23:22:23


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Kevin Gilbert 2005-10-23 04:08:31 UTC
Environment:

gcc -v
Using built-in specs.
Target: i686-pc-linux-gnu
Configured with: ./configure  : (reconfigured) ./configure --enable-languages=c,c++,fortran,java,objc --no-create --no-recursion
Thread model: posix
gcc version 4.1.0 20051022 (experimental)

====

Program:

#include <stdlib.h>

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

====

Compile command:

gcc -O0 -ggdb -o test test.c

====

When run under 'gdb' then using the 'bt' commands results in

#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

====

Works correctly with:

gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,java,f95,ada --enable-java-awt=gtk --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --host=i386-redhat-linux
Thread model: posix
gcc version 4.0.1 20050727 (Red Hat 4.0.1-5)

====

backtrace then gives:

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
Comment 1 Andrew Pinski 2005-10-23 14:12:05 UTC
What OS is this on, what kind of processor is this on also?
Comment 2 Andrew Pinski 2005-10-23 14:34:55 UTC
(In reply to comment #1)
> What OS is this on, what kind of processor is this on also?

Never mind, I cannot read.

Anyways confirmed, a regression from 4.0.0.
Comment 3 Kevin Gilbert 2005-10-23 22:13:26 UTC
Just for the record, I've pasted the incorrect gdb output for the second backtrace. It is as follows:

#0  0x00240402 in __kernel_vsyscall ()
#1  0x00726118 in raise () from /lib/libc.so.6
#2  0x00727888 in abort () from /lib/libc.so.6
#3  0x0804839d in main (argc=1, argv=0xbfa69a14) at office/test.c:4

Sorry. And, yes, I should have added the OS & hardware platform. Noted for future reference.
Comment 4 Mark Mitchell 2005-10-31 06:40:19 UTC
Leaving as P2.
Comment 5 Jim Wilson 2005-11-01 02:44:57 UTC
Even at -O0, we notice that main ends with a call to a function that does not return, so the epilogue gets optimized away, and the last instruction in the main function is the call to abort.

gdb is naively using return addresses to generate the backtraces.  The return address from abort is one past the end of the call to abort, which is past the end of main.

We are generating a location list for the frame base, since it differs between the prologue and the function body.  This location list defines the value of the frame base at every point between function start and function end, and its value depends on the PC address you have.

So gdb is taking a PC address from outside the main function, noticing that this address isn't covered by the frame base location list for main, and generating an error.

Possible solutions:
1) Fix gdb to subtract one from a return address before processing the location list.  This will ensure that we have an address inside the function, and thus an  address for which we have a valid frame base.  This is essentially what we do in the dwarf2 unwinder.
2) Pad the function with a nop, so that a return address always points to a valid instruction inside the function.  This is what we do in the IA-64 port, to make IA-64 unwinding info work in this case.
3) Extend the location list info to run 1 byte past the end of the function.  I don't know if this is safe.  If the following function starts immediately after main, then we have two functions with debug info for the same byte of code.  This may result in even more confusion than we already have.

I think solution 1 should be investigated first, which means we need to get the gdb team to look at this.

The problem with the return address can be seen by running "nm -S a.out | grep main" on the compiled testcase which gives you the starting address and size of main, and then comparing this against the PC address in the gdb backtrace.  This shows that gdb is using an address 1 byte past the end of main for the backtrace.
Comment 6 Jim Wilson 2005-11-01 23:22:23 UTC
I filed this as gdb PR 2024 in order to get a gdb opinion.
Comment 7 Kevin Gilbert 2005-11-01 23:55:26 UTC
I've just had a look at gdb PR 2024 and disagree with the comment "backtrace fails when function ends with call to abort". The following code also ehibits the problem noted here.

==========

#include <stdio.h>
#include <stdlib.h>

int main( int argc, char** argv )
{   printf( "hello world!\n" );
    abort( );
    int i = 0;
    int j = 1;
    printf( "i = %d, j = %d, total = %d\n", i, j, i + j );
    return 0;
}

===========

I have not posted this comment on the gdb database as it may or may not be relevent to them but I think the point needs to be made.
Comment 8 Andrew Pinski 2005-11-02 00:00:28 UTC
(In reply to comment #7)
> I've just had a look at gdb PR 2024 and disagree with the comment "backtrace
> fails when function ends with call to abort". The following code also ehibits
> the problem noted here.
Well by the time we get to expand to RTL, the rest of the function has already deleted from the CFG as there is no way to get to the code (as it is unreachable code).
Comment 9 Jim Wilson 2005-11-14 21:09:54 UTC
Not a gcc bug.  This is a gdb bug, and I already have an approved patch for gdb that will be checked in shortly.