This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
PATCH: Re: EH frame optimization bug
- From: "H. J. Lu" <hjl at lucon dot org>
- To: binutils at sources dot redhat dot com
- Date: Thu, 2 Oct 2003 18:05:03 -0700
- Subject: PATCH: Re: EH frame optimization bug
- References: <20030930190559.GA4994@nevyn.them.org> <20031002184345.GA10386@nevyn.them.org>
On Thu, Oct 02, 2003 at 02:43:45PM -0400, Daniel Jacobowitz wrote:
> On Tue, Sep 30, 2003 at 03:05:59PM -0400, Daniel Jacobowitz wrote:
> > Testcase derived from glibc. Take the attached files and link them:
> > ld -o bin connect.o send.o dumb.o
> >
> > readelf -wf bin -> segfault.
> >
> > The problem is that we've got GAS-produced .eh_frame sections that look like
> > this:
> > [ 5] .eh_frame PROGBITS 00000000 000098 000040 00 A 0 0 4
> >
> > 00000000 00000012 00000000 CIE
> >
> > 00000016 00000026 0000001a FDE cie=00000000 pc=0000001e..00000074
> >
> > Then we have two almost identical object files (built from the same source
> > file, actually). We optimize them to share a CIE.
> >
> > 00000000 00000012 00000000 CIE
> > 00000016 00000026 0000001a FDE cie=00000000 pc=08048080..080480d6
> > 00000040 00000026 00000044 FDE cie=00000000 pc=080480e0..08048136
> >
> > That second FDE now ends at 0x6a. The next .eh_frame section is align-4.
> > Two bytes padding get added, and everything blows up.
> >
> > Something similar came up a few months ago but I can't find the reference
> > now. What's the right thing to do here? My instinct says, grow the last
> > FDE before the padding, but I have no idea how to do that. Is the alignment
> > of a .eh_frame section mandated?
>
How about this patch?
H.J.
---
2003-10-02 H.J. Lu <hongjiu.lu@intel.com>
* elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Pad the
last FDE if needed.
--- bfd/elf-eh-frame.c.pad 2003-08-07 09:04:30.000000000 -0700
+++ bfd/elf-eh-frame.c 2003-10-02 18:03:43.000000000 -0700
@@ -1026,6 +1026,38 @@ _bfd_elf_write_section_eh_frame (bfd *ab
and 3xDW_CFA_nop as pad */
p += 16;
}
+ else
+ {
+ int old_fill = (sec->_raw_size
+ & ((1 << sec->alignment_power) - 1));
+ int new_fill = (sec->_cooked_size
+ & ((1 << sec->alignment_power) - 1));
+ int needed = old_fill - new_fill;
+
+ if (needed)
+ {
+ unsigned long length;
+
+ if (sec_info->entry[sec_info->count - 1].cie)
+ abort ();
+
+ needed = (((1 << sec->alignment_power) + needed)
+ & ((1 << sec->alignment_power) - 1));
+
+ buf = contents + sec_info->entry[sec_info->count - 1].new_offset;
+
+ /* Update length. */
+ length = bfd_get_32 (abfd, buf) + needed;
+ bfd_put_32 (abfd, length, buf);
+
+ /* Pad it with DW_CFA_nop */
+ memset (p, 0, needed);
+ p += needed;
+
+ sec_info->entry[sec_info->count - 1].size += needed;
+ sec->_cooked_size += needed;
+ }
+ }
BFD_ASSERT ((bfd_size_type) (p - contents) == sec->_cooked_size);