Bug 12253 - .eh_frame_hdr not properly sorted with mixed .eh_frame encodings
Summary: .eh_frame_hdr not properly sorted with mixed .eh_frame encodings
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Alan Modra
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-11-22 17:49 UTC by Rainer Orth
Modified: 2010-11-25 16:31 UTC (History)
2 users (show)

See Also:
Host: i386-pc-solaris2.11
Target: i386-pc-solaris2.11
Build: i386-pc-solaris2.11
Last reconfirmed:


Attachments
testcase (2.91 KB, application/x-gzip)
2010-11-22 17:52 UTC, Rainer Orth
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Rainer Orth 2010-11-22 17:49:33 UTC
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.
Comment 1 Rainer Orth 2010-11-22 17:52:07 UTC
Created attachment 5134 [details]
testcase
Comment 2 Alan Modra 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.
Comment 3 Rainer Orth 2010-11-23 16:01:49 UTC
> --- 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
Comment 4 Alan Modra 2010-11-23 22:27:53 UTC
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!
Comment 6 Rainer Orth 2010-11-25 16:31:44 UTC
> --- 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