This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: PATCH: Re: EH frame optimization bug
On Fri, Oct 03, 2003 at 01:05:11PM -0700, H. J. Lu wrote:
> On Fri, Oct 03, 2003 at 04:23:54PM +0200, Jakub Jelinek wrote:
> > On Fri, Oct 03, 2003 at 08:01:28AM -0700, H. J. Lu wrote:
> > > I think it is too late to remove paddings in _bfd_elf_write_section_eh_frame.
> > > The only thing we can do at this point is to pad the current section
> > > for the next section, which is aligned.
> >
> > At write_section_eh_frame time it is too late, sure.
> > But at _bfd_elf_discard_section_eh_frame time it is not.
> > I meant something like:
> >
> > 2003-10-03 Jakub Jelinek <jakub@redhat.com>
> >
> > * elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): If .eh_frame
> > section doesn't use "eh" CIEs nor DW_EH_PE_aligned encoding,
> > decrease section alignment to byte alignment.
> >
>
> If the first .eh_frame section is changed to byte alignment, will
> that be a problem for unwind routine? Does unwind routine have
> any alignment requirement?
>
>
Here is a new patch. It preserves the section alignment and removes
padding if needed.
H.J.
---
2003-10-03 H.J. Lu <hongjiu.lu@intel.com>
* elf-bfd.h (eh_cie_fde): Add update_length.
* elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Remove
padding in the last CIE/FDE if needed.
(_bfd_elf_write_section_eh_frame): Pad or update length for
the last CIE/FDE if needed.
--- bfd/elf-bfd.h.pad 2003-09-23 08:16:43.000000000 -0700
+++ bfd/elf-bfd.h 2003-10-03 13:10:57.000000000 -0700
@@ -277,6 +277,7 @@ struct eh_cie_fde
unsigned char lsda_offset;
unsigned char cie : 1;
unsigned char removed : 1;
+ unsigned char update_length : 1;
unsigned char make_relative : 1;
unsigned char make_lsda_relative : 1;
unsigned char per_encoding_relative : 1;
--- bfd/elf-eh-frame.c.pad 2003-08-07 09:04:30.000000000 -0700
+++ bfd/elf-eh-frame.c 2003-10-03 13:14:31.000000000 -0700
@@ -219,7 +219,7 @@ _bfd_elf_discard_section_eh_frame
struct eh_frame_hdr_info *hdr_info;
struct eh_frame_sec_info *sec_info = NULL;
unsigned int leb128_tmp;
- unsigned int cie_usage_count, last_cie_ndx, i, offset;
+ unsigned int cie_usage_count, last_cie_ndx, last_ndx, i, offset;
unsigned int make_relative, make_lsda_relative;
bfd_size_type new_size;
unsigned int ptr_size;
@@ -598,10 +598,12 @@ _bfd_elf_discard_section_eh_frame
/* Ok, now we can assign new offsets. */
offset = 0;
last_cie_ndx = 0;
+ last_ndx = 0;
for (i = 0; i < sec_info->count; i++)
{
if (! sec_info->entry[i].removed)
{
+ last_ndx = i;
sec_info->entry[i].new_offset = offset;
offset += sec_info->entry[i].size;
if (sec_info->entry[i].cie)
@@ -637,6 +639,37 @@ _bfd_elf_discard_section_eh_frame
this point, so build a fake minimal CIE. */
if (new_size == 0)
new_size = 16;
+ else
+ {
+ unsigned int pad = new_size % (1 << sec->alignment_power);
+
+ /* The size of the last CIE/FDE must be at least 4. */
+ if (pad
+ && !sec_info->entry[last_ndx].removed
+ && sec_info->entry[last_ndx].size >= 4)
+ {
+ /* Check if we can remove some padding. */
+ bfd_boolean remove_padding = TRUE;
+ bfd_byte *p;
+
+ buf = (ehbuf
+ + sec_info->entry[last_ndx].offset
+ + sec_info->entry[last_ndx].size);
+ for (p = buf - pad; p < buf; p++)
+ if (*p != 0)
+ {
+ remove_padding = FALSE;
+ break;
+ }
+
+ if (remove_padding)
+ {
+ sec_info->entry[last_ndx].size -= pad;
+ new_size -= pad;
+ sec_info->entry[last_ndx].update_length = 1;
+ }
+ }
+ }
/* Shrink the sec as needed. */
sec->_cooked_size = new_size;
@@ -1026,6 +1059,47 @@ _bfd_elf_write_section_eh_frame (bfd *ab
and 3xDW_CFA_nop as pad */
p += 16;
}
+ else
+ {
+ unsigned int new_fill;
+
+ /* Find the last CIE/FDE. */
+ for (i = sec_info->count - 1; i > 0; i--)
+ if (! sec_info->entry[i].removed)
+ break;
+
+ new_fill = sec->_cooked_size % (1 << sec->alignment_power);
+
+ if (new_fill)
+ {
+
+ /* The size of the last CIE/FDE must be at least 4. */
+ if (sec_info->entry[i].removed
+ || sec_info->entry[i].size < 4)
+ abort ();
+
+ new_fill = (1 << sec->alignment_power) - new_fill;
+
+ buf = contents + sec_info->entry[i].new_offset;
+
+ /* Update length. */
+ sec_info->entry[i].size += new_fill;
+ bfd_put_32 (abfd, sec_info->entry[i].size - 4, buf);
+
+ /* Pad it with DW_CFA_nop */
+ memset (p, 0, new_fill);
+ p += new_fill;
+
+ sec->_cooked_size += new_fill;
+ }
+ else if (sec_info->entry[i].update_length)
+ {
+ /* Check if we need to update length. */
+ buf = contents + sec_info->entry[i].new_offset;
+
+ bfd_put_32 (abfd, sec_info->entry[i].size - 4, buf);
+ }
+ }
BFD_ASSERT ((bfd_size_type) (p - contents) == sec->_cooked_size);