RFH/RFC: libgcc _Unwind_Backtrace falling off the end of FDE list...

David Daney ddaney@avtrex.com
Tue Feb 1 21:23:00 GMT 2005


I am running gcc-3.4.3/binutils-2.15 with target=mipsel-linux and 
glibc-2.3.3 compiled with the same.

Note that with gcc-3.3.1/binutils-2.15 glibc-2.3.3 I don't see the 
problem.  Which is a bit puzzling.

Here is the setup:

My program (a java program via the libgcj runtime) calls 
_Unwind_Backtrace.  Everything works find until the unwinding gets to 
the stack frame in glibc that calls my main().  The PC for the frame in 
question is not covered by the .eh_frame data for glibc, so at this 
point I get a SIGSEGV because linear_search_fdes iterates through all 
the FDEs in the .eh_frame and then falls off the end of the list and 
starts processing garbage from the following sections.

#0  linear_search_fdes (ob=0x7fff6858, this_fde=0x2b939538, pc=0x2b7c0e23)
     at unwind-dw2-fde.c:828
#1  0x2b2233b8 in _Unwind_IteratePhdrCallback (info=0x7fff68c8, size=16,
     ptr=0x7fff6918) at ../../gcc-3.4.3/gcc/unwind-dw2-fde-glibc.c:253
#2  0x2b8d6690 in *__GI___dl_iterate_phdr (
     callback=0x2b222df8 <_Unwind_IteratePhdrCallback>, data=0x7fff6918)
     at dl-iteratephdr.c:51
#3  0x2b223524 in _Unwind_Find_FDE (pc=0x2b7c0e23, bases=0x7fff6c78)
     at ../../gcc-3.4.3/gcc/unwind-dw2-fde-glibc.c:281
#4  0x2b21cc0c in uw_frame_state_for (context=0x7fff69a8, fs=0x7fff6c90)
     at ../../gcc-3.4.3/gcc/unwind-dw2.c:1020
#5  0x2b21f798 in _Unwind_Backtrace (trace=0x2b556cc0 <my_trace_fn>,
     trace_argument=0x7fff7290) at unwind.inc:296
#6  0x2b556dac in backtrace (locations=0x0, len=2147444824)
     at ../../../gcc-3.4.3/libjava/sysdep/dwarf2-backtrace.cc:84
#7  0x2b3ddee4 in gnu::gcj::runtime::StackTrace::fillInStackTrace (
     this=0x101f1ca0, maxlen=2147444824, offset=2)
     at ../../../gcc-3.4.3/libjava/gnu/gcj/runtime/natStackTrace.cc:55
.
.
.
.


In unwind-dw2-fde.c linear_search_fdes() we have this loop:

   for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
     {
.
.
.
     }

And in unwind-dw2-fde.h:

static inline int
last_fde (struct object *obj __attribute__ ((__unused__)), const fde *f)
{
   return f->length == 0;
}

The loop is terminated when a zero is found at the end of the FDE list.

The .eh_frame section of my libc-2.3.3.so is not terminated with a zero.

And now the question:

I am thinking that the proper fix for the problem is to change the 
linker scripts so that a word of 0 is placed at the end of the .eh_frame 
section.  Perhaps something like this:

.
.
.
   .tbss           : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
   .eh_frame       : { KEEP (*(.eh_frame)) }
   . += 4;  /* Place a word of zero to terminate the .eh_frame.*/
   .gcc_except_table   : { *(.gcc_except_table) }
.
.
.

Q1: Does this seem like the proper thing to do?
Q2: Does ld fill with zeros so that I get what I want.
Q3: Am I out of my mind?

Thanks in advance for any insight,
David Daney.



More information about the Binutils mailing list