public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Follow-up to November's .eh_frame optimisations (1/3)
@ 2005-01-13 23:12 Richard Sandiford
  2005-01-13 23:20 ` Follow-up to November's .eh_frame optimisations (2/3) Richard Sandiford
  2005-01-17 16:49 ` Follow-up to November's .eh_frame optimisations (1/3) Nick Clifton
  0 siblings, 2 replies; 6+ messages in thread
From: Richard Sandiford @ 2005-01-13 23:12 UTC (permalink / raw)
  To: binutils

A couple of months ago, I submitted a patch to extend the linker
.eh_frame optimisations:

    http://sources.redhat.com/ml/binutils/2004-11/msg00226.html

The idea was to change FDEs from an absolute to a PC-relative encoding
in cases where the original CIEs had no 'R' augmentation.  Doing that
increased the size of the CIEs and FDEs (because of the new augmentation
info) but reduced the number of relocs needed.

At the time, I promised to extend the patch so that it would only grow
the CIEs and FDEs if there wasn't enough padding to hold the new data.
I've finally got around to doing that.

The full patch needs to parse the CFA instructions, so that means
more sanity checks in _bfd_elf_discard_section_eh_frame.  Most of
the existing tests have the form:

        if (something_that_shouldn't_happen)
          goto free_no_table;

but for one particular type of test, the goto is wrapped up in an
assert-like macro called ENSURE_NO_RELOCS().

I tried just using gotos for the new checks, but I thought it made
the code quite a bit harder to follow.  Things seemed much more
readable when using assert-like statements instead.

This first patch therefore paves the way by adding a new assert-like
macro called REQUIRE() and, for consistency, uses it for the existing
goto-based tests.

Tested on mips64-linux-gnu (gas, ld and binutils) and with a gcc
bootstrap and regression test on mips-sgi-irix6.5.  OK to install?

Richard


	* elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Use an
	assert-style REQUIRE() macro to handle sanity checks.

*** bfd/elf-eh-frame.c.1	2005-01-07 10:36:19.000000000 +0000
--- bfd/elf-eh-frame.c	2005-01-07 10:44:35.000000000 +0000
*************** _bfd_elf_discard_section_eh_frame
*** 265,270 ****
--- 265,276 ----
      bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
      struct elf_reloc_cookie *cookie)
  {
+ #define REQUIRE(COND)					\
+   do							\
+     if (!(COND))					\
+       goto free_no_table;				\
+   while (0)
+ 
    bfd_byte *ehbuf = NULL, *buf;
    bfd_byte *last_cie, *last_fde;
    struct eh_cie_fde *ent, *last_cie_inf, *this_inf;
*************** _bfd_elf_discard_section_eh_frame
*** 296,303 ****
  
    /* Read the frame unwind information from abfd.  */
  
!   if (!bfd_malloc_and_get_section (abfd, sec, &ehbuf))
!     goto free_no_table;
  
    if (sec->size >= 4
        && bfd_get_32 (abfd, ehbuf) == 0
--- 302,308 ----
  
    /* Read the frame unwind information from abfd.  */
  
!   REQUIRE (bfd_malloc_and_get_section (abfd, sec, &ehbuf));
  
    if (sec->size >= 4
        && bfd_get_32 (abfd, ehbuf) == 0
*************** _bfd_elf_discard_section_eh_frame
*** 310,317 ****
  
    /* If .eh_frame section size doesn't fit into int, we cannot handle
       it (it would need to use 64-bit .eh_frame format anyway).  */
!   if (sec->size != (unsigned int) sec->size)
!     goto free_no_table;
  
    ptr_size = (elf_elfheader (abfd)->e_ident[EI_CLASS]
  	      == ELFCLASS64) ? 8 : 4;
--- 315,321 ----
  
    /* If .eh_frame section size doesn't fit into int, we cannot handle
       it (it would need to use 64-bit .eh_frame format anyway).  */
!   REQUIRE (sec->size == (unsigned int) sec->size);
  
    ptr_size = (elf_elfheader (abfd)->e_ident[EI_CLASS]
  	      == ELFCLASS64) ? 8 : 4;
*************** _bfd_elf_discard_section_eh_frame
*** 322,338 ****
    cie_usage_count = 0;
    sec_info = bfd_zmalloc (sizeof (struct eh_frame_sec_info)
  			  + 99 * sizeof (struct eh_cie_fde));
!   if (sec_info == NULL)
!     goto free_no_table;
  
    sec_info->alloced = 100;
  
  #define ENSURE_NO_RELOCS(buf)				\
!   if (cookie->rel < cookie->relend			\
!       && (cookie->rel->r_offset				\
! 	  < (bfd_size_type) ((buf) - ehbuf))		\
!       && cookie->rel->r_info != 0)			\
!     goto free_no_table
  
  #define SKIP_RELOCS(buf)				\
    while (cookie->rel < cookie->relend			\
--- 326,340 ----
    cie_usage_count = 0;
    sec_info = bfd_zmalloc (sizeof (struct eh_frame_sec_info)
  			  + 99 * sizeof (struct eh_cie_fde));
!   REQUIRE (sec_info);
  
    sec_info->alloced = 100;
  
  #define ENSURE_NO_RELOCS(buf)				\
!   REQUIRE (!(cookie->rel < cookie->relend		\
! 	     && (cookie->rel->r_offset			\
! 		 < (bfd_size_type) ((buf) - ehbuf))	\
! 	     && cookie->rel->r_info != 0))
  
  #define SKIP_RELOCS(buf)				\
    while (cookie->rel < cookie->relend			\
*************** _bfd_elf_discard_section_eh_frame
*** 357,364 ****
  				  sizeof (struct eh_frame_sec_info)
  				  + ((sec_info->alloced + 99)
  				     * sizeof (struct eh_cie_fde)));
! 	  if (sec_info == NULL)
! 	    goto free_no_table;
  
  	  memset (&sec_info->entry[sec_info->alloced], 0,
  		  100 * sizeof (struct eh_cie_fde));
--- 359,365 ----
  				  sizeof (struct eh_frame_sec_info)
  				  + ((sec_info->alloced + 99)
  				     * sizeof (struct eh_cie_fde)));
! 	  REQUIRE (sec_info);
  
  	  memset (&sec_info->entry[sec_info->alloced], 0,
  		  100 * sizeof (struct eh_cie_fde));
*************** _bfd_elf_discard_section_eh_frame
*** 378,404 ****
  	hdr.id = (unsigned int) -1;
        else
  	{
! 	  if ((bfd_size_type) (buf + 4 - ehbuf) > sec->size)
! 	    /* No space for CIE/FDE header length.  */
! 	    goto free_no_table;
! 
  	  hdr.length = bfd_get_32 (abfd, buf);
- 	  if (hdr.length == 0xffffffff)
- 	    /* 64-bit .eh_frame is not supported.  */
- 	    goto free_no_table;
  	  buf += 4;
! 	  if ((bfd_size_type) (buf - ehbuf) + hdr.length > sec->size)
! 	    /* CIE/FDE not contained fully in this .eh_frame input section.  */
! 	    goto free_no_table;
  
  	  this_inf->offset = last_fde - ehbuf;
  	  this_inf->size = 4 + hdr.length;
  
  	  if (hdr.length == 0)
  	    {
! 	      /* CIE with length 0 must be only the last in the section.  */
! 	      if ((bfd_size_type) (buf - ehbuf) < sec->size)
! 		goto free_no_table;
  	      ENSURE_NO_RELOCS (buf);
  	      sec_info->count++;
  	      /* Now just finish last encountered CIE processing and break
--- 379,403 ----
  	hdr.id = (unsigned int) -1;
        else
  	{
! 	  /* Read the length of the entry.  */
! 	  REQUIRE ((bfd_size_type) (buf - ehbuf) + 4 <= sec->size);
  	  hdr.length = bfd_get_32 (abfd, buf);
  	  buf += 4;
! 
! 	  /* 64-bit .eh_frame is not supported.  */
! 	  REQUIRE (hdr.length != 0xffffffff);
! 
! 	  /* The CIE/FDE must be fully contained in this input section.  */
! 	  REQUIRE ((bfd_size_type) (buf - ehbuf) + hdr.length <= sec->size);
  
  	  this_inf->offset = last_fde - ehbuf;
  	  this_inf->size = 4 + hdr.length;
  
  	  if (hdr.length == 0)
  	    {
! 	      /* A zero-length CIE should only be found at the end of
! 		 the section.  */
! 	      REQUIRE ((bfd_size_type) (buf - ehbuf) == sec->size);
  	      ENSURE_NO_RELOCS (buf);
  	      sec_info->count++;
  	      /* Now just finish last encountered CIE processing and break
*************** _bfd_elf_discard_section_eh_frame
*** 409,416 ****
  	    {
  	      hdr.id = bfd_get_32 (abfd, buf);
  	      buf += 4;
! 	      if (hdr.id == (unsigned int) -1)
! 		goto free_no_table;
  	    }
  	}
  
--- 408,414 ----
  	    {
  	      hdr.id = bfd_get_32 (abfd, buf);
  	      buf += 4;
! 	      REQUIRE (hdr.id != (unsigned int) -1);
  	    }
  	}
  
*************** _bfd_elf_discard_section_eh_frame
*** 455,464 ****
  	  cie.version = *buf++;
  
  	  /* Cannot handle unknown versions.  */
! 	  if (cie.version != 1 && cie.version != 3)
! 	    goto free_no_table;
! 	  if (strlen (buf) > sizeof (cie.augmentation) - 1)
! 	    goto free_no_table;
  
  	  strcpy (cie.augmentation, buf);
  	  buf = strchr (buf, '\0') + 1;
--- 453,460 ----
  	  cie.version = *buf++;
  
  	  /* Cannot handle unknown versions.  */
! 	  REQUIRE (cie.version == 1 || cie.version == 3);
! 	  REQUIRE (strlen (buf) < sizeof (cie.augmentation));
  
  	  strcpy (cie.augmentation, buf);
  	  buf = strchr (buf, '\0') + 1;
*************** _bfd_elf_discard_section_eh_frame
*** 498,511 ****
  		  case 'L':
  		    cie.lsda_encoding = *buf++;
  		    ENSURE_NO_RELOCS (buf);
! 		    if (get_DW_EH_PE_width (cie.lsda_encoding, ptr_size) == 0)
! 		      goto free_no_table;
  		    break;
  		  case 'R':
  		    cie.fde_encoding = *buf++;
  		    ENSURE_NO_RELOCS (buf);
! 		    if (get_DW_EH_PE_width (cie.fde_encoding, ptr_size) == 0)
! 		      goto free_no_table;
  		    break;
  		  case 'P':
  		    {
--- 494,505 ----
  		  case 'L':
  		    cie.lsda_encoding = *buf++;
  		    ENSURE_NO_RELOCS (buf);
! 		    REQUIRE (get_DW_EH_PE_width (cie.lsda_encoding, ptr_size));
  		    break;
  		  case 'R':
  		    cie.fde_encoding = *buf++;
  		    ENSURE_NO_RELOCS (buf);
! 		    REQUIRE (get_DW_EH_PE_width (cie.fde_encoding, ptr_size));
  		    break;
  		  case 'P':
  		    {
*************** _bfd_elf_discard_section_eh_frame
*** 514,521 ****
  		      cie.per_encoding = *buf++;
  		      per_width = get_DW_EH_PE_width (cie.per_encoding,
  						      ptr_size);
! 		      if (per_width == 0)
! 			goto free_no_table;
  		      if ((cie.per_encoding & 0xf0) == DW_EH_PE_aligned)
  			buf = (ehbuf
  			       + ((buf - ehbuf + per_width - 1)
--- 508,514 ----
  		      cie.per_encoding = *buf++;
  		      per_width = get_DW_EH_PE_width (cie.per_encoding,
  						      ptr_size);
! 		      REQUIRE (per_width);
  		      if ((cie.per_encoding & 0xf0) == DW_EH_PE_aligned)
  			buf = (ehbuf
  			       + ((buf - ehbuf + per_width - 1)
*************** _bfd_elf_discard_section_eh_frame
*** 608,621 ****
        else
  	{
  	  /* Ensure this FDE uses the last CIE encountered.  */
! 	  if (last_cie == NULL
! 	      || hdr.id != (unsigned int) (buf - 4 - last_cie))
! 	    goto free_no_table;
  
  	  ENSURE_NO_RELOCS (buf);
! 	  if (GET_RELOC (buf) == NULL)
! 	    /* This should not happen.  */
! 	    goto free_no_table;
  
  	  if ((*reloc_symbol_deleted_p) (buf - ehbuf, cookie))
  	    /* This is a FDE against a discarded section.  It should
--- 601,611 ----
        else
  	{
  	  /* Ensure this FDE uses the last CIE encountered.  */
! 	  REQUIRE (last_cie);
! 	  REQUIRE (hdr.id == (unsigned int) (buf - 4 - last_cie));
  
  	  ENSURE_NO_RELOCS (buf);
! 	  REQUIRE (GET_RELOC (buf));
  
  	  if ((*reloc_symbol_deleted_p) (buf - ehbuf, cookie))
  	    /* This is a FDE against a discarded section.  It should
*************** free_no_table:
*** 693,698 ****
--- 683,690 ----
    hdr_info->table = FALSE;
    hdr_info->last_cie.hdr.length = 0;
    return FALSE;
+ 
+ #undef REQUIRE
  }
  
  /* This function is called for .eh_frame_hdr section after

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Follow-up to November's .eh_frame optimisations (2/3)
  2005-01-13 23:12 Follow-up to November's .eh_frame optimisations (1/3) Richard Sandiford
@ 2005-01-13 23:20 ` Richard Sandiford
  2005-01-13 23:28   ` Follow-up to November's .eh_frame optimisations (3/3) Richard Sandiford
  2005-01-17 16:51   ` Follow-up to November's .eh_frame optimisations (2/3) Nick Clifton
  2005-01-17 16:49 ` Follow-up to November's .eh_frame optimisations (1/3) Nick Clifton
  1 sibling, 2 replies; 6+ messages in thread
From: Richard Sandiford @ 2005-01-13 23:20 UTC (permalink / raw)
  To: binutils

This patch follows on from:

    http://sources.redhat.com/ml/binutils/2005-01/msg00133.html

and is the second of the three.

The final patch will need to interpret CFA instructions, some of which
have variable length fields, and some of which contain leb128s, which
themselves have a variable length.  So, the question was, should we just
assume that these instructions are valid, or should we take care not to
read past the end of the CIE/FDE?  I thought it would be better to do
the latter.

_bfd_elf_discard_section_eh_frame already does many bounds checks, such
as making sure that the reported CIE length is within the bounds of the
input section.  However, once it's tested that, it doesn't usually check
whether there are N bytes left in the CIE/FDE before doing "buf += N",
or whether an leb128 actually fits within the CIE/FDE.  Since the final
optimisation needs to do both these things, the patch below adds some
helper routines and converts the existing code to use them.  I guess
this might seem a teensy bit anal ;), but it should make things more
robust in the face of true garbage, should anyone care.

Tested in the same way as the first patch.  OK to install?

(BTW, there's a potential conflict with the patch that H.J. posted
yesterday, which moved read_*_leb128 to libbfd.c.  It should be
easy enough to adapt this patch if his goes in first.)

Richard


	* elf-bfd.h (struct cie): Use bfd_vmas for code_align, ra_column and
	augmentation_size.  Use bfd_signed_vmas for data_align.
	* elf-eh-frame.c (read_unsigned_leb128, read_signed_leb128)
	(read_uleb128, read_sleb128): Delete in favor of...
	(read_byte, skip_leb128, read_uleb128, read_sleb128): ...these new
	functions.  Don't read past the end of the enclosing CIE or FDE.
	(skip_bytes): New utility function.
	(_bfd_elf_discard_section_eh_frame): Use new functions, adding more
	sanity checking.
	(_bfd_elf_write_section_eh_frame): Use new functions.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.166
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.166 elf-bfd.h
*** bfd/elf-bfd.h	10 Dec 2004 14:04:56 -0000	1.166
--- bfd/elf-bfd.h	10 Jan 2005 13:09:50 -0000
*************** struct cie
*** 270,279 ****
    struct cie_header hdr;
    unsigned char version;
    unsigned char augmentation[20];
!   unsigned int code_align;
!   int data_align;
!   unsigned int ra_column;
!   unsigned int augmentation_size;
    struct elf_link_hash_entry *personality;
    unsigned char per_encoding;
    unsigned char lsda_encoding;
--- 270,279 ----
    struct cie_header hdr;
    unsigned char version;
    unsigned char augmentation[20];
!   bfd_vma code_align;
!   bfd_signed_vma data_align;
!   bfd_vma ra_column;
!   bfd_vma augmentation_size;
    struct elf_link_hash_entry *personality;
    unsigned char per_encoding;
    unsigned char lsda_encoding;
*** bfd/elf-eh-frame.c.2	2005-01-07 10:44:35.000000000 +0000
--- bfd/elf-eh-frame.c	2005-01-07 11:12:01.423299862 +0000
***************
*** 26,104 ****
  
  #define EH_FRAME_HDR_SIZE 8
  
! /* Helper function for reading uleb128 encoded data.  */
  
! static bfd_vma
! read_unsigned_leb128 (bfd *abfd ATTRIBUTE_UNUSED,
! 		      char *buf,
! 		      unsigned int *bytes_read_ptr)
  {
!   bfd_vma result;
!   unsigned int num_read;
!   int shift;
!   unsigned char byte;
  
!   result = 0;
!   shift = 0;
!   num_read = 0;
!   do
      {
!       byte = bfd_get_8 (abfd, (bfd_byte *) buf);
!       buf++;
!       num_read++;
!       result |= (((bfd_vma) byte & 0x7f) << shift);
!       shift += 7;
      }
!   while (byte & 0x80);
!   *bytes_read_ptr = num_read;
!   return result;
  }
  
! /* Helper function for reading sleb128 encoded data.  */
  
! static bfd_signed_vma
! read_signed_leb128 (bfd *abfd ATTRIBUTE_UNUSED,
! 		    char *buf,
! 		    unsigned int * bytes_read_ptr)
  {
-   bfd_vma result;
-   int shift;
-   int num_read;
    unsigned char byte;
- 
-   result = 0;
-   shift = 0;
-   num_read = 0;
    do
!     {
!       byte = bfd_get_8 (abfd, (bfd_byte *) buf);
!       buf ++;
!       num_read ++;
!       result |= (((bfd_vma) byte & 0x7f) << shift);
!       shift += 7;
!     }
    while (byte & 0x80);
!   if (byte & 0x40)
!     result |= (((bfd_vma) -1) << (shift - 7)) << 7;
!   *bytes_read_ptr = num_read;
!   return result;
  }
  
! #define read_uleb128(VAR, BUF)					\
! do								\
!   {								\
!     (VAR) = read_unsigned_leb128 (abfd, buf, &leb128_tmp);	\
!     (BUF) += leb128_tmp;					\
!   }								\
! while (0)
  
! #define read_sleb128(VAR, BUF)					\
! do								\
!   {								\
!     (VAR) = read_signed_leb128 (abfd, buf, &leb128_tmp);	\
!     (BUF) += leb128_tmp;					\
!   }								\
! while (0)
  
  /* Return 0 if either encoding is variable width, or not yet known to bfd.  */
  
--- 26,110 ----
  
  #define EH_FRAME_HDR_SIZE 8
  
! /* If *ITER hasn't reached END yet, read the next byte into *RESULT and
!    move onto the next byte.  Return true on success.  */
  
! static inline bfd_boolean
! read_byte (bfd_byte **iter, bfd_byte *end, unsigned char *result)
  {
!   if (*iter >= end)
!     return FALSE;
!   *result = *((*iter)++);
!   return TRUE;
! }
  
! /* Move *ITER over LENGTH bytes, or up to END, whichever is closer.
!    Return true it was possible to move LENGTH bytes.  */
! 
! static inline bfd_boolean
! skip_bytes (bfd_byte **iter, bfd_byte *end, bfd_size_type length)
! {
!   if ((bfd_size_type) (end - *iter) < length)
      {
!       *iter = end;
!       return FALSE;
      }
!   *iter += length;
!   return TRUE;
  }
  
! /* Move *ITER over an leb128, stopping at END.  Return true if the end
!    of the leb128 was found.  */
  
! static bfd_boolean
! skip_leb128 (bfd_byte **iter, bfd_byte *end)
  {
    unsigned char byte;
    do
!     if (!read_byte (iter, end, &byte))
!       return FALSE;
    while (byte & 0x80);
!   return TRUE;
  }
  
! /* Like skip_leb128, but treat the leb128 as an unsigned value and
!    store it in *VALUE.  */
  
! static bfd_boolean
! read_uleb128 (bfd_byte **iter, bfd_byte *end, bfd_vma *value)
! {
!   bfd_byte *start, *p;
! 
!   start = *iter;
!   if (!skip_leb128 (iter, end))
!     return FALSE;
! 
!   p = *iter;
!   *value = *--p;
!   while (p > start)
!     *value = (*value << 7) | (*--p & 0x7f);
! 
!   return TRUE;
! }
! 
! /* Like read_uleb128, but for signed values.  */
! 
! static bfd_boolean
! read_sleb128 (bfd_byte **iter, bfd_byte *end, bfd_signed_vma *value)
! {
!   bfd_byte *start, *p;
! 
!   start = *iter;
!   if (!skip_leb128 (iter, end))
!     return FALSE;
! 
!   p = *iter;
!   *value = ((*--p & 0x7f) ^ 0x40) - 0x40;
!   while (p > start)
!     *value = (*value << 7) | (*--p & 0x7f);
! 
!   return TRUE;
! }
  
  /* Return 0 if either encoding is variable width, or not yet known to bfd.  */
  
*************** _bfd_elf_discard_section_eh_frame
*** 279,285 ****
    struct elf_link_hash_table *htab;
    struct eh_frame_hdr_info *hdr_info;
    struct eh_frame_sec_info *sec_info = NULL;
-   unsigned int leb128_tmp;
    unsigned int cie_usage_count, offset;
    unsigned int ptr_size;
  
--- 285,290 ----
*************** _bfd_elf_discard_section_eh_frame
*** 351,356 ****
--- 356,363 ----
    for (;;)
      {
        unsigned char *aug;
+       bfd_byte *start, *end;
+       bfd_size_type length;
  
        if (sec_info->count == sec_info->alloced)
  	{
*************** _bfd_elf_discard_section_eh_frame
*** 376,394 ****
        /* If we are at the end of the section, we still need to decide
  	 on whether to output or discard last encountered CIE (if any).  */
        if ((bfd_size_type) (buf - ehbuf) == sec->size)
! 	hdr.id = (unsigned int) -1;
        else
  	{
  	  /* Read the length of the entry.  */
! 	  REQUIRE ((bfd_size_type) (buf - ehbuf) + 4 <= sec->size);
! 	  hdr.length = bfd_get_32 (abfd, buf);
! 	  buf += 4;
  
  	  /* 64-bit .eh_frame is not supported.  */
  	  REQUIRE (hdr.length != 0xffffffff);
  
  	  /* The CIE/FDE must be fully contained in this input section.  */
  	  REQUIRE ((bfd_size_type) (buf - ehbuf) + hdr.length <= sec->size);
  
  	  this_inf->offset = last_fde - ehbuf;
  	  this_inf->size = 4 + hdr.length;
--- 383,404 ----
        /* If we are at the end of the section, we still need to decide
  	 on whether to output or discard last encountered CIE (if any).  */
        if ((bfd_size_type) (buf - ehbuf) == sec->size)
! 	{
! 	  hdr.id = (unsigned int) -1;
! 	  end = buf;
! 	}
        else
  	{
  	  /* Read the length of the entry.  */
! 	  REQUIRE (skip_bytes (&buf, ehbuf + sec->size, 4));
! 	  hdr.length = bfd_get_32 (abfd, buf - 4);
  
  	  /* 64-bit .eh_frame is not supported.  */
  	  REQUIRE (hdr.length != 0xffffffff);
  
  	  /* The CIE/FDE must be fully contained in this input section.  */
  	  REQUIRE ((bfd_size_type) (buf - ehbuf) + hdr.length <= sec->size);
+ 	  end = buf + hdr.length;
  
  	  this_inf->offset = last_fde - ehbuf;
  	  this_inf->size = 4 + hdr.length;
*************** _bfd_elf_discard_section_eh_frame
*** 406,413 ****
  	    }
  	  else
  	    {
! 	      hdr.id = bfd_get_32 (abfd, buf);
! 	      buf += 4;
  	      REQUIRE (hdr.id != (unsigned int) -1);
  	    }
  	}
--- 416,423 ----
  	    }
  	  else
  	    {
! 	      REQUIRE (skip_bytes (&buf, end, 4));
! 	      hdr.id = bfd_get_32 (abfd, buf - 4);
  	      REQUIRE (hdr.id != (unsigned int) -1);
  	    }
  	}
*************** _bfd_elf_discard_section_eh_frame
*** 450,456 ****
  	  cie_usage_count = 0;
  	  memset (&cie, 0, sizeof (cie));
  	  cie.hdr = hdr;
! 	  cie.version = *buf++;
  
  	  /* Cannot handle unknown versions.  */
  	  REQUIRE (cie.version == 1 || cie.version == 3);
--- 460,466 ----
  	  cie_usage_count = 0;
  	  memset (&cie, 0, sizeof (cie));
  	  cie.hdr = hdr;
! 	  REQUIRE (read_byte (&buf, end, &cie.version));
  
  	  /* Cannot handle unknown versions.  */
  	  REQUIRE (cie.version == 1 || cie.version == 3);
*************** _bfd_elf_discard_section_eh_frame
*** 465,479 ****
  	      /* We cannot merge "eh" CIEs because __EXCEPTION_TABLE__
  		 is private to each CIE, so we don't need it for anything.
  		 Just skip it.  */
! 	      buf += ptr_size;
  	      SKIP_RELOCS (buf);
  	    }
! 	  read_uleb128 (cie.code_align, buf);
! 	  read_sleb128 (cie.data_align, buf);
  	  if (cie.version == 1)
! 	    cie.ra_column = *buf++;
  	  else
! 	    read_uleb128 (cie.ra_column, buf);
  	  ENSURE_NO_RELOCS (buf);
  	  cie.lsda_encoding = DW_EH_PE_omit;
  	  cie.fde_encoding = DW_EH_PE_omit;
--- 475,492 ----
  	      /* We cannot merge "eh" CIEs because __EXCEPTION_TABLE__
  		 is private to each CIE, so we don't need it for anything.
  		 Just skip it.  */
! 	      REQUIRE (skip_bytes (&buf, end, ptr_size));
  	      SKIP_RELOCS (buf);
  	    }
! 	  REQUIRE (read_uleb128 (&buf, end, &cie.code_align));
! 	  REQUIRE (read_sleb128 (&buf, end, &cie.data_align));
  	  if (cie.version == 1)
! 	    {
! 	      REQUIRE (buf < end);
! 	      cie.ra_column = *buf++;
! 	    }
  	  else
! 	    REQUIRE (read_uleb128 (&buf, end, &cie.ra_column));
  	  ENSURE_NO_RELOCS (buf);
  	  cie.lsda_encoding = DW_EH_PE_omit;
  	  cie.fde_encoding = DW_EH_PE_omit;
*************** _bfd_elf_discard_section_eh_frame
*** 484,490 ****
  	      if (*aug == 'z')
  		{
  		  aug++;
! 		  read_uleb128 (cie.augmentation_size, buf);
  	  	  ENSURE_NO_RELOCS (buf);
  		}
  
--- 497,503 ----
  	      if (*aug == 'z')
  		{
  		  aug++;
! 		  REQUIRE (read_uleb128 (&buf, end, &cie.augmentation_size));
  	  	  ENSURE_NO_RELOCS (buf);
  		}
  
*************** _bfd_elf_discard_section_eh_frame
*** 492,503 ****
  		switch (*aug++)
  		  {
  		  case 'L':
! 		    cie.lsda_encoding = *buf++;
  		    ENSURE_NO_RELOCS (buf);
  		    REQUIRE (get_DW_EH_PE_width (cie.lsda_encoding, ptr_size));
  		    break;
  		  case 'R':
! 		    cie.fde_encoding = *buf++;
  		    ENSURE_NO_RELOCS (buf);
  		    REQUIRE (get_DW_EH_PE_width (cie.fde_encoding, ptr_size));
  		    break;
--- 505,516 ----
  		switch (*aug++)
  		  {
  		  case 'L':
! 		    REQUIRE (read_byte (&buf, end, &cie.lsda_encoding));
  		    ENSURE_NO_RELOCS (buf);
  		    REQUIRE (get_DW_EH_PE_width (cie.lsda_encoding, ptr_size));
  		    break;
  		  case 'R':
! 		    REQUIRE (read_byte (&buf, end, &cie.fde_encoding));
  		    ENSURE_NO_RELOCS (buf);
  		    REQUIRE (get_DW_EH_PE_width (cie.fde_encoding, ptr_size));
  		    break;
*************** _bfd_elf_discard_section_eh_frame
*** 505,518 ****
  		    {
  		      int per_width;
  
! 		      cie.per_encoding = *buf++;
  		      per_width = get_DW_EH_PE_width (cie.per_encoding,
  						      ptr_size);
  		      REQUIRE (per_width);
  		      if ((cie.per_encoding & 0xf0) == DW_EH_PE_aligned)
! 			buf = (ehbuf
! 			       + ((buf - ehbuf + per_width - 1)
! 				  & ~((bfd_size_type) per_width - 1)));
  		      ENSURE_NO_RELOCS (buf);
  		      /* Ensure we have a reloc here, against
  			 a global symbol.  */
--- 518,532 ----
  		    {
  		      int per_width;
  
! 		      REQUIRE (read_byte (&buf, end, &cie.per_encoding));
  		      per_width = get_DW_EH_PE_width (cie.per_encoding,
  						      ptr_size);
  		      REQUIRE (per_width);
  		      if ((cie.per_encoding & 0xf0) == DW_EH_PE_aligned)
! 			{
! 			  length = -(buf - ehbuf) & (per_width - 1);
! 			  REQUIRE (skip_bytes (&buf, end, length));
! 			}
  		      ENSURE_NO_RELOCS (buf);
  		      /* Ensure we have a reloc here, against
  			 a global symbol.  */
*************** _bfd_elf_discard_section_eh_frame
*** 545,551 ****
  			    cookie->rel++;
  			  while (GET_RELOC (buf) != NULL);
  			}
! 		      buf += per_width;
  		    }
  		    break;
  		  default:
--- 559,565 ----
  			    cookie->rel++;
  			  while (GET_RELOC (buf) != NULL);
  			}
! 		      REQUIRE (skip_bytes (&buf, end, per_width));
  		    }
  		    break;
  		  default:
*************** _bfd_elf_discard_section_eh_frame
*** 627,644 ****
  	      cie_usage_count++;
  	      hdr_info->fde_count++;
  	    }
  	  if (cie.lsda_encoding != DW_EH_PE_omit)
! 	    {
! 	      unsigned int dummy;
  
- 	      aug = buf;
- 	      buf += 2 * get_DW_EH_PE_width (cie.fde_encoding, ptr_size);
- 	      if (cie.augmentation[0] == 'z')
- 		read_uleb128 (dummy, buf);
- 	      /* If some new augmentation data is added before LSDA
- 		 in FDE augmentation area, this need to be adjusted.  */
- 	      this_inf->lsda_offset = (buf - aug);
- 	    }
  	  buf = last_fde + 4 + hdr.length;
  	  SKIP_RELOCS (buf);
  	}
--- 641,661 ----
  	      cie_usage_count++;
  	      hdr_info->fde_count++;
  	    }
+ 	  /* Skip the initial location and address range.  */
+ 	  start = buf;
+ 	  length = get_DW_EH_PE_width (cie.fde_encoding, ptr_size);
+ 	  REQUIRE (skip_bytes (&buf, end, 2 * length));
+ 
+ 	  /* Skip the augmentation size, if present.  */
+ 	  if (cie.augmentation[0] == 'z')
+ 	    REQUIRE (skip_leb128 (&buf, end));
+ 
+ 	  /* Of the supported augmentation characters above, only 'L'
+ 	     adds augmentation data to the FDE.  This code would need to
+ 	     be adjusted if any future augmentations do the same thing.  */
  	  if (cie.lsda_encoding != DW_EH_PE_omit)
! 	    this_inf->lsda_offset = buf - start;
  
  	  buf = last_fde + 4 + hdr.length;
  	  SKIP_RELOCS (buf);
  	}
*************** _bfd_elf_write_section_eh_frame (bfd *ab
*** 850,856 ****
    struct eh_frame_sec_info *sec_info;
    struct elf_link_hash_table *htab;
    struct eh_frame_hdr_info *hdr_info;
-   unsigned int leb128_tmp;
    unsigned int ptr_size;
    struct eh_cie_fde *ent;
  
--- 867,872 ----
*************** _bfd_elf_write_section_eh_frame (bfd *ab
*** 952,958 ****
  	    {
  	      unsigned char *aug;
  	      unsigned int action, extra_string, extra_data;
! 	      unsigned int dummy, per_width, per_encoding;
  
  	      /* Need to find 'R' or 'L' augmentation's argument and modify
  		 DW_EH_PE_* value.  */
--- 968,974 ----
  	    {
  	      unsigned char *aug;
  	      unsigned int action, extra_string, extra_data;
! 	      unsigned int per_width, per_encoding;
  
  	      /* Need to find 'R' or 'L' augmentation's argument and modify
  		 DW_EH_PE_* value.  */
*************** _bfd_elf_write_section_eh_frame (bfd *ab
*** 966,974 ****
  	      buf += 9;
  	      aug = buf;
  	      buf = strchr (buf, '\0') + 1;
! 	      read_uleb128 (dummy, buf);
! 	      read_sleb128 (dummy, buf);
! 	      read_uleb128 (dummy, buf);
  	      if (*aug == 'z')
  		{
  		  /* The uleb128 will always be a single byte for the kind
--- 982,990 ----
  	      buf += 9;
  	      aug = buf;
  	      buf = strchr (buf, '\0') + 1;
! 	      skip_leb128 (&buf, end);
! 	      skip_leb128 (&buf, end);
! 	      skip_leb128 (&buf, end);
  	      if (*aug == 'z')
  		{
  		  /* The uleb128 will always be a single byte for the kind
*************** _bfd_elf_write_section_eh_frame (bfd *ab
*** 981,986 ****
--- 997,1003 ----
  	      memmove (buf + extra_string + extra_data, buf, end - buf);
  	      memmove (aug + extra_string, aug, buf - aug);
  	      buf += extra_string;
+ 	      end += extra_string + extra_data;
  
  	      if (ent->add_augmentation_size)
  		{

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Follow-up to November's .eh_frame optimisations (3/3)
  2005-01-13 23:20 ` Follow-up to November's .eh_frame optimisations (2/3) Richard Sandiford
@ 2005-01-13 23:28   ` Richard Sandiford
  2005-01-17 16:52     ` Nick Clifton
  2005-01-17 16:51   ` Follow-up to November's .eh_frame optimisations (2/3) Nick Clifton
  1 sibling, 1 reply; 6+ messages in thread
From: Richard Sandiford @ 2005-01-13 23:28 UTC (permalink / raw)
  To: binutils

This patch follows on from:

    http://sources.redhat.com/ml/binutils/2005-01/msg00133.html
    http://sources.redhat.com/ml/binutils/2005-01/msg00134.html

and implements the optimisation itself.

The original code was written so that an eh_cie_fde's size could be
shrunk by the amount of padding.  All the patch below does is calculate
the appropriate shrink value.  It leaves the size as-is if it can't
understand the CFA instructions.

The test case I added last November was parameterised so that the CIEs
and FDEs could be padded either with nops or with non-nop instructions.
The existing test just pads with non-nop instructions, but the one below
pads with nops instead, and checks that we don't grow a CIE or FDE if
it already has room for the new data.

Tested in the same way as previous patches.  OK to install?

Richard


bfd/
	* elf-eh-frame.c (skip_cfa_op, skip_non_nops): New functions.
	(_bfd_elf_discard_section_eh_frame): Use them to interpret the CFA
	instructions.  If the amount of padding is known, reduce the size
	of the CIE or FDE by that amount.

ld/testsuite/
	* ld-mips-elf/eh-frame2-{n32,n64}.d: New tests.
	* ld-mips-elf/mips-elf.exp: Run them.

*** bfd/elf-eh-frame.c.3	2005-01-07 11:12:01.423299000 +0000
--- bfd/elf-eh-frame.c	2005-01-07 11:41:02.311356990 +0000
*************** size_of_output_cie_fde (struct eh_cie_fd
*** 260,265 ****
--- 260,361 ----
  	  + alignment - 1) & -alignment;
  }
  
+ /* Assume that the bytes between *ITER and END are CFA instructions.
+    Try to move *ITER past the first instruction and return true on
+    success.  ENCODED_PTR_WIDTH gives the width of pointer entries.  */
+ 
+ static bfd_boolean
+ skip_cfa_op (bfd_byte **iter, bfd_byte *end, unsigned int encoded_ptr_width)
+ {
+   bfd_byte op;
+   bfd_vma length;
+ 
+   if (!read_byte (iter, end, &op))
+     return FALSE;
+ 
+   switch (op & 0x80 ? op & 0xc0 : op)
+     {
+     case DW_CFA_nop:
+     case DW_CFA_advance_loc:
+     case DW_CFA_restore:
+       /* No arguments.  */
+       return TRUE;
+ 
+     case DW_CFA_offset:
+     case DW_CFA_restore_extended:
+     case DW_CFA_undefined:
+     case DW_CFA_same_value:
+     case DW_CFA_def_cfa_register:
+     case DW_CFA_def_cfa_offset:
+     case DW_CFA_def_cfa_offset_sf:
+     case DW_CFA_GNU_args_size:
+       /* One leb128 argument.  */
+       return skip_leb128 (iter, end);
+ 
+     case DW_CFA_offset_extended:
+     case DW_CFA_register:
+     case DW_CFA_def_cfa:
+     case DW_CFA_offset_extended_sf:
+     case DW_CFA_GNU_negative_offset_extended:
+     case DW_CFA_def_cfa_sf:
+       /* Two leb128 arguments.  */
+       return (skip_leb128 (iter, end)
+ 	      && skip_leb128 (iter, end));
+ 
+     case DW_CFA_def_cfa_expression:
+       /* A variable-length argument.  */
+       return (read_uleb128 (iter, end, &length)
+ 	      && skip_bytes (iter, end, length));
+ 
+     case DW_CFA_expression:
+       /* A leb128 followed by a variable-length argument.  */
+       return (skip_leb128 (iter, end)
+ 	      && read_uleb128 (iter, end, &length)
+ 	      && skip_bytes (iter, end, length));
+ 
+     case DW_CFA_set_loc:
+       return skip_bytes (iter, end, encoded_ptr_width);
+ 
+     case DW_CFA_advance_loc1:
+       return skip_bytes (iter, end, 1);
+ 
+     case DW_CFA_advance_loc2:
+       return skip_bytes (iter, end, 2);
+ 
+     case DW_CFA_advance_loc4:
+       return skip_bytes (iter, end, 4);
+ 
+     case DW_CFA_MIPS_advance_loc8:
+       return skip_bytes (iter, end, 8);
+ 
+     default:
+       return FALSE;
+     }
+ }
+ 
+ /* Try to interpret the bytes between BUF and END as CFA instructions.
+    If every byte makes sense, return a pointer to the first DW_CFA_nop
+    padding byte, or END if there is no padding.  Return null otherwise.
+    ENCODED_PTR_WIDTH is as for skip_cfa_op.  */
+ 
+ static bfd_byte *
+ skip_non_nops (bfd_byte *buf, bfd_byte *end, unsigned int encoded_ptr_width)
+ {
+   bfd_byte *last;
+ 
+   last = buf;
+   while (buf < end)
+     if (*buf == DW_CFA_nop)
+       buf++;
+     else
+       {
+ 	if (!skip_cfa_op (&buf, end, encoded_ptr_width))
+ 	  return 0;
+ 	last = buf;
+       }
+   return last;
+ }
+ 
  /* This function is called for each input file before the .eh_frame
     section is relocated.  It discards duplicate CIEs and FDEs for discarded
     functions.  The function returns TRUE iff any entries have been
*************** _bfd_elf_discard_section_eh_frame
*** 356,362 ****
    for (;;)
      {
        unsigned char *aug;
!       bfd_byte *start, *end;
        bfd_size_type length;
  
        if (sec_info->count == sec_info->alloced)
--- 452,458 ----
    for (;;)
      {
        unsigned char *aug;
!       bfd_byte *start, *end, *insns;
        bfd_size_type length;
  
        if (sec_info->count == sec_info->alloced)
*************** _bfd_elf_discard_section_eh_frame
*** 602,613 ****
  	  if (cie.fde_encoding == DW_EH_PE_omit)
  	    cie.fde_encoding = DW_EH_PE_absptr;
  
! 	  initial_insn_length = cie.hdr.length - (buf - last_fde - 4);
  	  if (initial_insn_length <= 50)
  	    {
  	      cie.initial_insn_length = initial_insn_length;
  	      memcpy (cie.initial_instructions, buf, initial_insn_length);
  	    }
  	  buf += initial_insn_length;
  	  ENSURE_NO_RELOCS (buf);
  	  last_cie = last_fde;
--- 698,710 ----
  	  if (cie.fde_encoding == DW_EH_PE_omit)
  	    cie.fde_encoding = DW_EH_PE_absptr;
  
! 	  initial_insn_length = end - buf;
  	  if (initial_insn_length <= 50)
  	    {
  	      cie.initial_insn_length = initial_insn_length;
  	      memcpy (cie.initial_instructions, buf, initial_insn_length);
  	    }
+ 	  insns = buf;
  	  buf += initial_insn_length;
  	  ENSURE_NO_RELOCS (buf);
  	  last_cie = last_fde;
*************** _bfd_elf_discard_section_eh_frame
*** 648,665 ****
  
  	  /* Skip the augmentation size, if present.  */
  	  if (cie.augmentation[0] == 'z')
! 	    REQUIRE (skip_leb128 (&buf, end));
  
  	  /* Of the supported augmentation characters above, only 'L'
  	     adds augmentation data to the FDE.  This code would need to
  	     be adjusted if any future augmentations do the same thing.  */
  	  if (cie.lsda_encoding != DW_EH_PE_omit)
! 	    this_inf->lsda_offset = buf - start;
  
  	  buf = last_fde + 4 + hdr.length;
  	  SKIP_RELOCS (buf);
  	}
  
        this_inf->fde_encoding = cie.fde_encoding;
        this_inf->lsda_encoding = cie.lsda_encoding;
        sec_info->count++;
--- 745,782 ----
  
  	  /* Skip the augmentation size, if present.  */
  	  if (cie.augmentation[0] == 'z')
! 	    REQUIRE (read_uleb128 (&buf, end, &length));
! 	  else
! 	    length = 0;
  
  	  /* Of the supported augmentation characters above, only 'L'
  	     adds augmentation data to the FDE.  This code would need to
  	     be adjusted if any future augmentations do the same thing.  */
  	  if (cie.lsda_encoding != DW_EH_PE_omit)
! 	    {
! 	      this_inf->lsda_offset = buf - start;
! 	      /* If there's no 'z' augmentation, we don't know where the
! 		 CFA insns begin.  Assume no padding.  */
! 	      if (cie.augmentation[0] != 'z')
! 		length = end - buf;
! 	    }
! 
! 	  /* Skip over the augmentation data.  */
! 	  REQUIRE (skip_bytes (&buf, end, length));
! 	  insns = buf;
  
  	  buf = last_fde + 4 + hdr.length;
  	  SKIP_RELOCS (buf);
  	}
  
+       /* Try to interpret the CFA instructions and find the first
+ 	 padding nop.  Shrink this_inf's size so that it doesn't
+ 	 including the padding.  */
+       length = get_DW_EH_PE_width (cie.fde_encoding, ptr_size);
+       insns = skip_non_nops (insns, end, length);
+       if (insns != 0)
+ 	this_inf->size -= end - insns;
+ 
        this_inf->fde_encoding = cie.fde_encoding;
        this_inf->lsda_encoding = cie.lsda_encoding;
        sec_info->count++;
Index: ld/testsuite/ld-mips-elf/mips-elf.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-mips-elf/mips-elf.exp,v
retrieving revision 1.23
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.23 mips-elf.exp
*** ld/testsuite/ld-mips-elf/mips-elf.exp	14 Dec 2004 09:48:20 -0000	1.23
--- ld/testsuite/ld-mips-elf/mips-elf.exp	7 Jan 2005 12:19:22 -0000
*************** run_dump_test "reloc-merge-lo16"
*** 78,83 ****
--- 78,85 ----
  if {$has_newabi && $linux_gnu} {
      run_dump_test "eh-frame1-n32"
      run_dump_test "eh-frame1-n64"
+     run_dump_test "eh-frame2-n32"
+     run_dump_test "eh-frame2-n64"
  }
  
  run_dump_test "jaloverflow"
diff -c /dev/null ld/testsuite/ld-mips-elf/eh-frame2-n32.d
*** /dev/null	2004-12-03 11:50:38.225654048 +0000
--- ld/testsuite/ld-mips-elf/eh-frame2-n32.d	2005-01-07 12:19:05.517449557 +0000
***************
*** 0 ****
--- 1,255 ----
+ #name: MIPS eh-frame 2, n32
+ #source: eh-frame1.s
+ #source: eh-frame1.s
+ #as: -EB -n32 --defsym alignment=2 --defsym fill=0
+ #readelf: --relocs -wf
+ #ld: -shared -melf32btsmipn32 -Teh-frame1.ld
+ 
+ Relocation section '\.rel\.dyn' .*:
+  *Offset .*
+ 00000000  00000000 R_MIPS_NONE *
+ # Initial PCs for the FDEs attached to CIE 0xb8
+ 000300d8  00000003 R_MIPS_REL32 *
+ 000300ec  00000003 R_MIPS_REL32 *
+ # Likewise CIE 0x218
+ 00030238  00000003 R_MIPS_REL32 *
+ 0003024c  00000003 R_MIPS_REL32 *
+ 0003008b  00000503 R_MIPS_REL32      00000000   foo
+ 000300cc  00000503 R_MIPS_REL32      00000000   foo
+ 0003010a  00000503 R_MIPS_REL32      00000000   foo
+ 000301eb  00000503 R_MIPS_REL32      00000000   foo
+ 0003022c  00000503 R_MIPS_REL32      00000000   foo
+ 0003026a  00000503 R_MIPS_REL32      00000000   foo
+ #...
+ The section \.eh_frame contains:
+ 
+ 00000000 00000010 00000000 CIE
+   Version:               1
+   Augmentation:          "zR"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     10
+ 
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000014 00000010 00000018 FDE cie=00000000 pc=00020000..00020010
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000028 00000010 0000002c FDE cie=00000000 pc=00020010..00020030
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ # basic2 removed
+ 0000003c 00000010 00000040 FDE cie=00000000 pc=00020030..00020060
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ # basic3 removed
+ 00000050 00000010 00000054 FDE cie=00000000 pc=00020060..000200a0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ # basic4 removed
+ 00000064 00000010 00000068 FDE cie=00000000 pc=000200a0..000200f0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000078 00000014 00000000 CIE
+   Version:               1
+   Augmentation:          "zRP"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     10 00 00 00 00 00
+ 
+   DW_CFA_nop
+ 
+ 00000090 00000010 0000001c FDE cie=00000078 pc=000200f0..00020100
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000000a4 00000010 00000030 FDE cie=00000078 pc=00020100..00020120
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000000b8 00000014 00000000 CIE
+   Version:               1
+   Augmentation:          "zP"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     50 00 00 00 00 00 00 00
+ 
+ 
+ 000000d0 00000010 0000001c FDE cie=000000b8 pc=00020120..00020130
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000000e4 00000010 00000030 FDE cie=000000b8 pc=00020130..00020150
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000000f8 00000014 00000000 CIE
+   Version:               1
+   Augmentation:          "zPR"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     00 00 00 00 00 10
+ 
+   DW_CFA_nop
+ 
+ 00000110 00000010 0000001c FDE cie=000000f8 pc=00020150..00020160
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ # FDE for .discard removed
+ # zPR2 removed
+ 00000124 00000010 00000030 FDE cie=000000f8 pc=00020160..00020190
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000138 00000010 00000044 FDE cie=000000f8 pc=00020190..000201d0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 0000014c 00000010 00000000 CIE
+   Version:               1
+   Augmentation:          "zR"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     10
+ 
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000160 00000010 00000018 FDE cie=0000014c pc=000201d0..000201e0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ # basic1 removed, followed by repeat of above
+ 00000174 00000010 0000002c FDE cie=0000014c pc=000201e0..000201f0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000188 00000010 00000040 FDE cie=0000014c pc=000201f0..00020210
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 0000019c 00000010 00000054 FDE cie=0000014c pc=00020210..00020240
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000001b0 00000010 00000068 FDE cie=0000014c pc=00020240..00020280
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000001c4 00000010 0000007c FDE cie=0000014c pc=00020280..000202d0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000001d8 00000014 00000000 CIE
+   Version:               1
+   Augmentation:          "zRP"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     10 00 00 00 00 00
+ 
+   DW_CFA_nop
+ 
+ 000001f0 00000010 0000001c FDE cie=000001d8 pc=000202d0..000202e0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000204 00000010 00000030 FDE cie=000001d8 pc=000202e0..00020300
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000218 00000014 00000000 CIE
+   Version:               1
+   Augmentation:          "zP"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     50 00 00 00 00 00 00 00
+ 
+ 
+ 00000230 00000010 0000001c FDE cie=00000218 pc=00020300..00020310
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000244 00000010 00000030 FDE cie=00000218 pc=00020310..00020330
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000258 00000014 00000000 CIE
+   Version:               1
+   Augmentation:          "zPR"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     00 00 00 00 00 10
+ 
+   DW_CFA_nop
+ 
+ 00000270 00000010 0000001c FDE cie=00000258 pc=00020330..00020340
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000284 00000010 00000030 FDE cie=00000258 pc=00020340..00020370
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000298 00000010 00000044 FDE cie=00000258 pc=00020370..000203b0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000002ac 00000010 00000000 CIE
+   Version:               1
+   Augmentation:          "zR"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     10
+ 
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000002c0 00000010 00000018 FDE cie=000002ac pc=000203b0..000203c0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
diff -c /dev/null ld/testsuite/ld-mips-elf/eh-frame2-n64.d
*** /dev/null	2004-12-03 11:50:38.225654048 +0000
--- ld/testsuite/ld-mips-elf/eh-frame2-n64.d	2005-01-07 12:18:53.819199714 +0000
***************
*** 0 ****
--- 1,409 ----
+ #name: MIPS eh-frame 2, n64
+ #source: eh-frame1.s
+ #source: eh-frame1.s
+ #as: -EB -64 --defsym alignment=3 --defsym fill=0
+ #readelf: --relocs -wf
+ #ld: -shared -melf64btsmip -Teh-frame1.ld
+ 
+ Relocation section '\.rel\.dyn' .*:
+  *Offset .*
+ 000000000000  000000000000 R_MIPS_NONE *
+  *Type2: R_MIPS_NONE *
+  *Type3: R_MIPS_NONE *
+ # Initial PCs for the FDEs attached to CIE 0x118
+ 000000030140  000000001203 R_MIPS_REL32 *
+  *Type2: R_MIPS_64 *
+  *Type3: R_MIPS_NONE *
+ 000000030160  000000001203 R_MIPS_REL32 *
+  *Type2: R_MIPS_64 *
+  *Type3: R_MIPS_NONE *
+ # Likewise CIE 0x330
+ 000000030358  000000001203 R_MIPS_REL32 *
+  *Type2: R_MIPS_64 *
+  *Type3: R_MIPS_NONE *
+ 000000030378  000000001203 R_MIPS_REL32 *
+  *Type2: R_MIPS_64 *
+  *Type3: R_MIPS_NONE *
+ 0000000300cb  000500001203 R_MIPS_REL32      0000000000000000 foo
+  *Type2: R_MIPS_64 *
+  *Type3: R_MIPS_NONE *
+ 000000030130  000500001203 R_MIPS_REL32      0000000000000000 foo
+  *Type2: R_MIPS_64 *
+  *Type3: R_MIPS_NONE *
+ 00000003018a  000500001203 R_MIPS_REL32      0000000000000000 foo
+  *Type2: R_MIPS_64 *
+  *Type3: R_MIPS_NONE *
+ 0000000302e3  000500001203 R_MIPS_REL32      0000000000000000 foo
+  *Type2: R_MIPS_64 *
+  *Type3: R_MIPS_NONE *
+ 000000030348  000500001203 R_MIPS_REL32      0000000000000000 foo
+  *Type2: R_MIPS_64 *
+  *Type3: R_MIPS_NONE *
+ 0000000303a2  000500001203 R_MIPS_REL32      0000000000000000 foo
+  *Type2: R_MIPS_64 *
+  *Type3: R_MIPS_NONE *
+ #...
+ The section \.eh_frame contains:
+ 
+ 00000000 00000014 00000000 CIE
+   Version:               1
+   Augmentation:          "zR"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     10
+ 
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000018 0000001c 0000001c FDE cie=00000000 pc=00020000..00020010
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000038 0000001c 0000003c FDE cie=00000000 pc=00020010..00020030
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ # basic2 removed
+ 00000058 0000001c 0000005c FDE cie=00000000 pc=00020030..00020060
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ # basic3 removed
+ 00000078 0000001c 0000007c FDE cie=00000000 pc=00020060..000200a0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ # basic4 removed
+ 00000098 0000001c 0000009c FDE cie=00000000 pc=000200a0..000200f0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000000b8 0000001c 00000000 CIE
+   Version:               1
+   Augmentation:          "zRP"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     10 00 00 00 00 00 00 00 00 00
+ 
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000000d8 0000001c 00000024 FDE cie=000000b8 pc=000200f0..00020100
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000000f8 0000001c 00000044 FDE cie=000000b8 pc=00020100..00020120
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000118 0000001c 00000000 CIE
+   Version:               1
+   Augmentation:          "zP"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 
+ 
+ 00000138 0000001c 00000024 FDE cie=00000118 pc=00020120..00020130
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000158 0000001c 00000044 FDE cie=00000118 pc=00020130..00020150
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000178 0000001c 00000000 CIE
+   Version:               1
+   Augmentation:          "zPR"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     00 00 00 00 00 00 00 00 00 10
+ 
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000198 0000001c 00000024 FDE cie=00000178 pc=00020150..00020160
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ # FDE for .discard removed
+ # zPR2 removed
+ 000001b8 0000001c 00000044 FDE cie=00000178 pc=00020160..00020190
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000001d8 0000001c 00000064 FDE cie=00000178 pc=00020190..000201d0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000001f8 00000014 00000000 CIE
+   Version:               1
+   Augmentation:          "zR"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     10
+ 
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000210 0000001c 0000001c FDE cie=000001f8 pc=000201d0..000201e0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ # basic1 removed, followed by repeat of above
+ 00000230 0000001c 0000003c FDE cie=000001f8 pc=000201e0..000201f0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000250 0000001c 0000005c FDE cie=000001f8 pc=000201f0..00020210
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000270 0000001c 0000007c FDE cie=000001f8 pc=00020210..00020240
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000290 0000001c 0000009c FDE cie=000001f8 pc=00020240..00020280
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000002b0 0000001c 000000bc FDE cie=000001f8 pc=00020280..000202d0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000002d0 0000001c 00000000 CIE
+   Version:               1
+   Augmentation:          "zRP"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     10 00 00 00 00 00 00 00 00 00
+ 
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000002f0 0000001c 00000024 FDE cie=000002d0 pc=000202d0..000202e0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000310 0000001c 00000044 FDE cie=000002d0 pc=000202e0..00020300
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000330 0000001c 00000000 CIE
+   Version:               1
+   Augmentation:          "zP"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 
+ 
+ 00000350 0000001c 00000024 FDE cie=00000330 pc=00020300..00020310
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000370 0000001c 00000044 FDE cie=00000330 pc=00020310..00020330
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000390 0000001c 00000000 CIE
+   Version:               1
+   Augmentation:          "zPR"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     00 00 00 00 00 00 00 00 00 10
+ 
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000003b0 0000001c 00000024 FDE cie=00000390 pc=00020330..00020340
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000003d0 0000001c 00000044 FDE cie=00000390 pc=00020340..00020370
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 000003f0 0000001c 00000064 FDE cie=00000390 pc=00020370..000203b0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000410 00000014 00000000 CIE
+   Version:               1
+   Augmentation:          "zR"
+   Code alignment factor: 1
+   Data alignment factor: 4
+   Return address column: 31
+   Augmentation data:     10
+ 
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 
+ 00000428 0000001c 0000001c FDE cie=00000410 pc=000203b0..000203c0
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+   DW_CFA_nop
+ 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Follow-up to November's .eh_frame optimisations (1/3)
  2005-01-13 23:12 Follow-up to November's .eh_frame optimisations (1/3) Richard Sandiford
  2005-01-13 23:20 ` Follow-up to November's .eh_frame optimisations (2/3) Richard Sandiford
@ 2005-01-17 16:49 ` Nick Clifton
  1 sibling, 0 replies; 6+ messages in thread
From: Nick Clifton @ 2005-01-17 16:49 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: binutils

Hi Richard,

> 	* elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Use an
> 	assert-style REQUIRE() macro to handle sanity checks.

Approved - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Follow-up to November's .eh_frame optimisations (2/3)
  2005-01-13 23:20 ` Follow-up to November's .eh_frame optimisations (2/3) Richard Sandiford
  2005-01-13 23:28   ` Follow-up to November's .eh_frame optimisations (3/3) Richard Sandiford
@ 2005-01-17 16:51   ` Nick Clifton
  1 sibling, 0 replies; 6+ messages in thread
From: Nick Clifton @ 2005-01-17 16:51 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: binutils

Hi Richard,

> 	* elf-bfd.h (struct cie): Use bfd_vmas for code_align, ra_column and
> 	augmentation_size.  Use bfd_signed_vmas for data_align.
> 	* elf-eh-frame.c (read_unsigned_leb128, read_signed_leb128)
> 	(read_uleb128, read_sleb128): Delete in favor of...
> 	(read_byte, skip_leb128, read_uleb128, read_sleb128): ...these new
> 	functions.  Don't read past the end of the enclosing CIE or FDE.
> 	(skip_bytes): New utility function.
> 	(_bfd_elf_discard_section_eh_frame): Use new functions, adding more
> 	sanity checking.
> 	(_bfd_elf_write_section_eh_frame): Use new functions.

Approved - please apply.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Follow-up to November's .eh_frame optimisations (3/3)
  2005-01-13 23:28   ` Follow-up to November's .eh_frame optimisations (3/3) Richard Sandiford
@ 2005-01-17 16:52     ` Nick Clifton
  0 siblings, 0 replies; 6+ messages in thread
From: Nick Clifton @ 2005-01-17 16:52 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: binutils

Hi Richard,

> bfd/
> 	* elf-eh-frame.c (skip_cfa_op, skip_non_nops): New functions.
> 	(_bfd_elf_discard_section_eh_frame): Use them to interpret the CFA
> 	instructions.  If the amount of padding is known, reduce the size
> 	of the CIE or FDE by that amount.
> 
> ld/testsuite/
> 	* ld-mips-elf/eh-frame2-{n32,n64}.d: New tests.
> 	* ld-mips-elf/mips-elf.exp: Run them.

Approved - please apply.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2005-01-17 16:52 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-01-13 23:12 Follow-up to November's .eh_frame optimisations (1/3) Richard Sandiford
2005-01-13 23:20 ` Follow-up to November's .eh_frame optimisations (2/3) Richard Sandiford
2005-01-13 23:28   ` Follow-up to November's .eh_frame optimisations (3/3) Richard Sandiford
2005-01-17 16:52     ` Nick Clifton
2005-01-17 16:51   ` Follow-up to November's .eh_frame optimisations (2/3) Nick Clifton
2005-01-17 16:49 ` Follow-up to November's .eh_frame optimisations (1/3) Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).