I'm currently working to have the libgcc unwinder use dl_iterate_phdr which was introduced in Solaris 11 build 135. When trying a GCC mainline bootstrap with CVS gas and ld, I saw that the 32-bit libffi unwind tests and all 32-bit libjava execution tests failed. Ultimately, I found that both failures have the same root cause: gld creates a .eh_frame_hdr section where the search table isn't properly sorted, which breaks unwind-dw2-fde-glibc.c which does a binary search of that table. The problem can be illustrated with the following example: $ cat func.cc extern int i; void func (void) { i++; } $ gcc -c -O2 -fPIC -Dfunc=datarel func.cc -o datarel.o $ gcc -c -O2 -Dfunc=pcrel func.cc -o pcrel.o $ elfdump -u datarel.o|grep enc code pointer encoding: 0x30 [ datarel ] $ elfdump -u pcrel.o|grep enc code pointer encoding: 0x1b [ sdata4 pcrel ] $ gcc -shared -o shlib.so datarel.o pcrel.o $ elfdump -u shlib.o shlib.so: .eh_frame_hdr: index[1]: invalid sort order Unwind Section: .eh_frame_hdr Frame Header: Version: 1 FramePtrEnc: [ sdata4 pcrel ] FramePtr: 0x1458 FdeCntEnc: [ udata4 ] FdeCnt: 2 TableEnc: [ sdata4 datarel ] Binary Search Table: InitialLoc FdeLoc 0x000003d0 0x0000149c 0x000003c5 0x00001470 I'm using the Solaris elfdump command since it both shows the search table, which readelf cannot currently do, and even complains about the unsorted .eh_frame_hdr. While I can workaround the issue in libffi where the pcrel encoding only occurs in a single handwritten assembler file (libffi/src/x86/sysv.S), this should be fixed.
Created attachment 5134 [details] testcase
I took a look at this today. Besides the sorting problem, elf-eh-frame.c gets DW_EH_PE_datarel wrong. datarel is quite horrible, with behaviour varying from one architecture to another, unspecified on most. For x86, datarel offsets are supposed to be relative to .got.plt rather than .got. On ia64, datarel is relative to __gp.
> --- Comment #2 from Alan Modra <amodra at gmail dot com> 2010-11-23 13:34:02 UTC --- > I took a look at this today. Besides the sorting problem, elf-eh-frame.c gets > DW_EH_PE_datarel wrong. datarel is quite horrible, with behaviour varying from > one architecture to another, unspecified on most. For x86, datarel offsets are > supposed to be relative to .got.plt rather than .got. On ia64, datarel is > relative to __gp. Do you have an idea where this is specified? I've only found Table 11.6 in the LSB 4.0.0: http://refspecs.freestandards.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html which says DW_EH_PE_datarel 0x30 Value is relative to the beginning of the .got or .eh_frame_hdr section. A spec which says `do A or B' with no indication when to do one or the other seems like a joke to me. I've looked into the architecture extensions for advise, but found nothing. I ran into this when trying to get the libgcc unwinder to work with dl_iterate_phdr on Solaris 11. While the function works, Sun ld interpreted DW_EH_PE_datarel relative to .eh_frame_hdr on i386 (apart from other problems). It would be good to have a spec to point to for this, rather than saying `GCC has been doing this' instead. Thanks. Rainer
Specs can't be trusted, sadly. Look for dbase in gcc/unwind-dw2-fde-glibc.c to see the initialisation for datarel base, used by x86 and frv. Look for ia64 in gcc/unwind-generic.h to see how ia64 sets up datarel base. A datarel value is relative to this base address. Except to muddy the waters further, DW_EH_PE_datarel when used in .eh_frame_hdr takes its base to be the address of the .eh_frame_hdr section!
http://sourceware.org/ml/binutils/2010-11/msg00431.html http://sourceware.org/ml/binutils-cvs/2010-11/msg00150.html
> --- Comment #5 from Alan Modra <amodra at gmail dot com> 2010-11-24 05:34:22 UTC --- > http://sourceware.org/ml/binutils/2010-11/msg00431.html > http://sourceware.org/ml/binutils-cvs/2010-11/msg00150.html Excellent, thanks. It would be good to have this backported to the 2.21 branch, although I plan to work around the issue I've found in libffi for the benefit of older versions. Rainer