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 04:04:53PM -0700, Richard Henderson wrote:
> On Fri, Oct 03, 2003 at 01:05:11PM -0700, H. J. Lu wrote:
> > Does unwind routine have any alignment requirement?
>
> No.
>
Then. Can we apply this patch?
H.J.
---
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.
2003-10-03 H.J. Lu <hongjiu.lu@intel.com>
* elf-eh-frame.c (_bfd_elf_write_section_eh_frame): Pad the
last CIE/FDE if needed.
--- bfd/elf-eh-frame.c.pad 2003-08-07 09:04:30.000000000 -0700
+++ bfd/elf-eh-frame.c 2003-10-03 16:38:17.000000000 -0700
@@ -223,6 +223,7 @@ _bfd_elf_discard_section_eh_frame
unsigned int make_relative, make_lsda_relative;
bfd_size_type new_size;
unsigned int ptr_size;
+ bfd_boolean needs_alignment = FALSE;
if (sec->_raw_size == 0)
{
@@ -256,6 +257,11 @@ _bfd_elf_discard_section_eh_frame
{
/* Empty .eh_frame section. */
free (ehbuf);
+ if (hdr_info->table && sec->alignment_power)
+ {
+ sec->alignment_power = 0;
+ return TRUE;
+ }
return FALSE;
}
@@ -423,6 +429,7 @@ _bfd_elf_discard_section_eh_frame
Just skip it. */
buf += ptr_size;
SKIP_RELOCS (buf);
+ needs_alignment = TRUE;
}
read_uleb128 (cie.code_align, buf);
read_sleb128 (cie.data_align, buf);
@@ -527,6 +534,11 @@ _bfd_elf_discard_section_eh_frame
if (cie.fde_encoding == DW_EH_PE_omit)
cie.fde_encoding = DW_EH_PE_absptr;
+ if (cie.fde_encoding == DW_EH_PE_aligned
+ || cie.lsda_encoding == DW_EH_PE_aligned
+ || cie.per_encoding == DW_EH_PE_aligned)
+ needs_alignment = TRUE;
+
initial_insn_length = cie.hdr.length - (buf - last_fde - 4);
if (initial_insn_length <= 50)
{
@@ -644,6 +656,11 @@ _bfd_elf_discard_section_eh_frame
sec->flags |= SEC_EXCLUDE;
free (ehbuf);
+ if (!needs_alignment && sec->alignment_power)
+ {
+ sec->alignment_power = 0;
+ return TRUE;
+ }
return new_size != sec->_raw_size;
free_no_table:
@@ -1026,6 +1043,38 @@ _bfd_elf_write_section_eh_frame (bfd *ab
and 3xDW_CFA_nop as pad */
p += 16;
}
+ else
+ {
+ unsigned int alignment = 1 << sec->alignment_power;
+ unsigned int pad = sec->_cooked_size % alignment;
+
+ if (pad)
+ {
+ /* Find the last CIE/FDE. */
+ for (i = sec_info->count - 1; i > 0; i--)
+ if (! sec_info->entry[i].removed)
+ break;
+
+ /* 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 ();
+
+ pad = alignment - pad;
+
+ buf = contents + sec_info->entry[i].new_offset;
+
+ /* Update length. */
+ sec_info->entry[i].size += pad;
+ bfd_put_32 (abfd, sec_info->entry[i].size - 4, buf);
+
+ /* Pad it with DW_CFA_nop */
+ memset (p, 0, pad);
+ p += pad;
+
+ sec->_cooked_size += pad;
+ }
+ }
BFD_ASSERT ((bfd_size_type) (p - contents) == sec->_cooked_size);