This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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);
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]