[Bug debug/13231] New: Bad DWARF2 CFI when there is no frame pointer

kettenis at gnu dot org gcc-bugzilla@gcc.gnu.org
Sat Nov 29 11:50:00 GMT 2003


It seems there is a serious problem with the DWARF2 CFI generated by
GCC on architectures without a frame pointer.  The problem arises when
GCC emits code similar to:

	# basic block 0
        prologue
        ...
        jmp .L2
.L1:
	# basic block 1
	epilogue
	ret
.L2:
	# basic block 2
	...
	jmp .L1

where "prologue" and "epilogue" typically are bits of code that adjust
the stack pointer.  Since, in the absence of a frame pointer, the CFA
is calculated relative to the stack pointer, GCC generates CFI for the
prologue and the epilogue.  In particular, GCC will generate CFI for
the epilogue that takes into account the adjustments that are made to
the stack pointer to restore it to its state on entry of the function.
Unfortunately, the way DWARF2 CFI works, this means that that same
state will be used for the code in "basic block 2" too.  This of
course is wrong, and makes unwinding within that bit of code fail
miserably.  This can be seen on x86-64, and also on i386 with
-fomit-frame-pointer.

For architectures with a frame pointer there usually is no problem
since GCC doesn't generated CFI for the epilogue in that case.

I assume this has some serious impact on exception handling too.

Here's a testcase:

$ gcc33 -g -O2 -c -fomit-frame-pointer badcfi.c
$ gcc33 -g -o testcfi testcfi.c badcfi.o
$ gdb testcfi
GNU gdb 2003-11-14-cvs
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-unknown-freebsd4.7"...
(gdb) b bar
Breakpoint 1 at 0x8048478: file testcfi.c, line 10.
(gdb) r
Starting program: /home/kettenis/tmp/testcfi 

Breakpoint 1, 0x08048478 in bar () at testcfi.c:10
10      {
(gdb) bt
#0  0x08048478 in bar () at testcfi.c:10
#1  0x080484b1 in foobar () at badcfi.c:10
#2  0x00000001 in ?? ()
#3  0xbfbff784 in ?? ()
#4  0xbfbff78c in ?? ()
#5  0x0804848f in main () at testcfi.c:16
(gdb) 

This is on i386-unknown-freebsd4.7 with:

$ gcc33 --version
gcc33 (GCC) 3.3.3 20031103 (prerelease) [FreeBSD]
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

which has been compiled from FreeBSD's package system.  While this
version has a small number of FreeBSD-specific patches, I'm pretty
sure they don't affect the problem I'm seeing.

Anyway, if you look at the output generated by

$ gcc33 -S -dA -g -O2 -fomit-frame-pointer badcfi.c

[snip]

.globl foobar
        .type   foobar, @function
foobar:
.LFB3:
        # badcfi.c:6
        .loc 1 6 0
        # basic block 0
        subl    $12, %esp
.LCFI0:
        # badcfi.c:7
        .loc 1 7 0
        call    foo
        testl   %eax, %eax
        je      .L4
        # badcfi.c:16
        .loc 1 16 0
.L1:
        # basic block 1
        movl    $1, %eax
        addl    $12, %esp
.LCFI1:
        ret
        # badcfi.c:10
        .loc 1 10 0
        .p2align 2,,3
.L4:
        # basic block 2
        call    bar
        # badcfi.c:12
        .loc 1 12 0
        call    foo
        jmp     .L1
.LFE3:
        .size   foobar, .-foobar

[snip]

you'll notice the .LCFI1 label used to generate CFI for the "ret"
instruction.  The same state gets used for "basic block 2" for which
it isn't right.

While this example is for i386-unknown-freebsd4.7, I see similar
behaviour on x86_64-unknownd-freebsd5.1.  Here it isn't necessary to
specify -fomit-frame-pointer, since it's the default.

-- 
           Summary: Bad DWARF2 CFI when there is no frame pointer
           Product: gcc
           Version: 3.3.3
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: debug
        AssignedTo: rth at redhat dot com
        ReportedBy: kettenis at gnu dot org
                CC: gcc-bugs at gcc dot gnu dot org
 GCC build triplet: i386-unknown-freebsd4.7
  GCC host triplet: i386-unknown-freebsd4.7
GCC target triplet: i386-unknown-freebsd4.7


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13231



More information about the Gcc-bugs mailing list