public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* RFA: Extensions to the .eh_frame linker code
@ 2004-11-13 12:12 Richard Sandiford
  2004-11-15  2:07 ` Alan Modra
  0 siblings, 1 reply; 6+ messages in thread
From: Richard Sandiford @ 2004-11-13 12:12 UTC (permalink / raw)
  To: binutils

The patch below lets the linker convert from absolute to relative
FDE encodings in cases where the original CIEs have no explicit 'R'
augmentation.  I've been meaning to do this for a while now, but finally
got spurred into action after having a glibc change rejected. ;)

This feature is useful on MIPS targets because every relocatable object
uses the default DW_EH_PE_absptr FDE encoding.  Although it would be
nice if relocatable PIC objects could use DW_EH_PE_pcrel from the
outset, the ABIs don't define a suitable relocation.


The idea of the patch is pretty simple.  First of all, we need to allow
the final CIEs and FDEs to be bigger than the originals.  The patch
supports this by adding two new eh_cie_fde fields: "growth", the number
of extra useful bytes, and "new_size", the properly-rounded size of the
output CIE or FDE.

Second, it must be possible for _bfd_elf_discard_section_eh_frame to
decide once and for all whether the FDE encoding will change or not.
At the moment, the function simply sets "make_relative" if the
transformation would be useful and leaves the final decision to
_bfd_elf_eh_frame_section_offset.

The make_relative/need_relative distinction was a result of Alan's
fix for ld/418.  As I understand it, the important part of that change
was really the make_lsda_relative/need_lsda_relative split (because we
don't know for sure what the LSDA actually contains).  It looks like
the make_relative/need_relative part was done more for consistency
than anything.

Since the meaning of the "initial PC" field is fixed, I hope it's
OK to go back to having just make_relative for the FDE encoding.

With those two changes, we can extend the following code:

	  if (info->shared
	      && (get_elf_backend_data (abfd)
		  ->elf_backend_can_make_relative_eh_frame
		  (abfd, info, sec))
	      && (cie.fde_encoding & 0xf0) == DW_EH_PE_absptr)
	    cie.make_relative = 1;

to include CIEs that have no 'R' augmentation (cie.fde_encoding ==
DW_EH_PE_omit at this point).  We then need to reserve space for the
new 'R' augmentation and FDE encoding byte.  If the augmentation string
was originally empty, we also need to add a 'z' augmentation and
associated length.  Adding a 'z' augmentation will affect the FDEs
as well, of course.

The patch records this information in two new eh_cie_fde fields:
"add_augmentation_size", which says whether a new 'z' augmentation
is needed, and "add_fde_encoding", which says whether a new 'R'
augmentation is needed.

Some other notes:

  (1) I've moved the block starting:

          if (cie.lsda_encoding != DW_EH_PE_omit)

      into the preceding else clause so that it only applies to FDEs
      that are not being removed.  This is because the following code:

          else if (last_cie_inf->add_augmentation_size)
            this_inf->growth += 1;

      must not be run in that case.

      The patch gets a bit unreadable here, but it's really just
      reindentation followed by the new "else if" quoted above.

  (2) At the moment, _bfd_elf_write_section_eh_frame makes a single pass
      over the section data.  This pass updates the contents of each
      entry and then moves it to its final offset.

      Since offsets can now grow as well as shrink, we need to move the
      entries in two passes, one forward, one backward.  It's also easier
      to adjust the contents of growing entries if we know that everything
      already starts at its final offset.  The patch therefore moves all
      the entries before doing any detailed updates.

  (3) The new "add_augmentation_size" field is logically separate from
      the "add_fde_encoding" field, and we might want to set it when
      adding other types of augmentation in future.  Until that happens
      though, it seems more natural for _bfd_elf_write_section_eh_frame
      to handle the two together, as per the following block:

              if (ent->add_fde_encoding)
                {
                  BFD_ASSERT (action & 1);
                  if (ent->add_augmentation_size)
                    ...
                  else
                    ...
                  *aug++ = 'R';
                  *buf++ = DW_EH_PE_pcrel;
                  action &= ~1;
                }

      I wasn't sure what structure the code would have if we ever tried
      to add several non-'z' augmentations and I didn't want to generalise
      things too far.

  (4) There's a missed optimisation opportunity:

          /* Round the size up the next alignment boundary and adjust
             the section size accordingly.

             ??? It would be better to trim any existing padding first.  */

      I hope to implement this soon, but I thought the patch was already
      getting to the difficult-to-review stage as it was.

      I've tried to bullet-proof the testcase against such an optimisation
      by padding each CIE and FDE with non-nops.  The type of padding is
      parameterised, so once the optimisation is implemented, it should
      just be a case of attaching new .d files to the same .s file
      and setting "fill" to 0.

Patch tested by bootstrapping & regression testing gcc on
i686-pc-linux-gnu and mips64-linux-gnu.  Also tested against
the gas/ld/binutils testsuite for:

    sparc-linux-gnu
    sparc64-linux-gnu
    i386-linux-gnu
    x86_64-linux-gnu
    powerpc-linux-gnu
    powerpc64-linux-gnu
    sh-linux-gnu
    mips64-elf
    mipsisa64-elf
    mips64-linux-gnu

OK to install?

Richard


bfd/
	* elf-bfd.h (eh_cie_fde): Add new fields: growth, new_size,
	add_augmentation_size and add_fde_encoding.  Remove need_relative.
	* elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Allow the CIEs
	and FDEs to grow as well as shrink.  Consider changing the FDE encoding
	in cases where the CIE has no explicit 'R' augmentation.
	(_bfd_elf_eh_frame_section_offset): Remove need_relative handling.
	Add the growth field to the returned offset.
	(_bfd_elf_write_section_eh_frame): Rework so that the entries are
	moved before being modified.  Pad growing entries with DW_CFA_nops.
	Add 'z' and 'R' augmentations as directed by add_augmentation_size
	and add_fde_encoding.

ld/testsuite
	* ld-mips-elf/eh-frame1.{s,ld},
	* ld-mips-elf/eh-frame1-{n32,n64},d: New test.
	* ld-mips-elf/mips-elf.exp: Run it.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.162
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.162 elf-bfd.h
--- bfd/elf-bfd.h	14 Oct 2004 23:38:08 -0000	1.162
+++ bfd/elf-bfd.h	13 Nov 2004 09:55:38 -0000
@@ -289,6 +289,8 @@ struct eh_cie_fde
   /* For FDEs, this points to the CIE used.  */
   struct eh_cie_fde *cie_inf;
   unsigned int size;
+  unsigned int growth;
+  unsigned int new_size;
   unsigned int offset;
   unsigned int new_offset;
   unsigned char fde_encoding;
@@ -296,9 +298,10 @@ struct eh_cie_fde
   unsigned char lsda_offset;
   unsigned int cie : 1;
   unsigned int removed : 1;
+  unsigned int add_augmentation_size : 1;
+  unsigned int add_fde_encoding : 1;
   unsigned int make_relative : 1;
   unsigned int make_lsda_relative : 1;
-  unsigned int need_relative : 1;
   unsigned int need_lsda_relative : 1;
   unsigned int per_encoding_relative : 1;
 };
Index: bfd/elf-eh-frame.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-eh-frame.c,v
retrieving revision 1.35
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.35 elf-eh-frame.c
--- bfd/elf-eh-frame.c	14 Oct 2004 23:38:08 -0000	1.35
+++ bfd/elf-eh-frame.c	13 Nov 2004 09:55:38 -0000
@@ -380,7 +380,7 @@ #define GET_RELOC(buf)					\
 		   && cie_compare (&cie, &hdr_info->last_cie) == 0)
 		  || cie_usage_count == 0)
 		{
-		  new_size -= cie.hdr.length + 4;
+		  new_size -= last_cie_inf->new_size;
 		  last_cie_inf->removed = 1;
 		}
 	      else
@@ -514,9 +514,33 @@ #define GET_RELOC(buf)					\
 	  if (info->shared
 	      && (get_elf_backend_data (abfd)
 		  ->elf_backend_can_make_relative_eh_frame
-		  (abfd, info, sec))
-	      && (cie.fde_encoding & 0xf0) == DW_EH_PE_absptr)
-	    cie.make_relative = 1;
+		  (abfd, info, sec)))
+	    {
+	      if ((cie.fde_encoding & 0xf0) == DW_EH_PE_absptr)
+		cie.make_relative = 1;
+	      /* If the CIE doesn't already have an 'R' entry, it's fairly
+		 easy to add one, provided that there's no aligned data
+		 after the augmentation string.  */
+	      else if (cie.fde_encoding == DW_EH_PE_omit
+		       && (cie.per_encoding & 0xf0) != DW_EH_PE_aligned)
+		{
+		  cie.make_relative = 1;
+
+		  /* If the augmentation string is currently empty, record
+		     that we want to add 'z' to it and a length byte to the
+		     associated data.  */
+		  if (*cie.augmentation == 0)
+		    {
+		      this_inf->add_augmentation_size = 1;
+		      this_inf->growth += 2;
+		    }
+
+		  /* Record that we need to add 'R' to the augmentation
+		     string and an FDE encoding to the augmentation data.  */
+		  this_inf->add_fde_encoding = 1;
+		  this_inf->growth += 2;
+		}
+	    }
 
 	  if (info->shared
 	      && (get_elf_backend_data (abfd)
@@ -574,23 +598,36 @@ #define GET_RELOC(buf)					\
 		}
 	      cie_usage_count++;
 	      hdr_info->fde_count++;
-	    }
-	  if (cie.lsda_encoding != DW_EH_PE_omit)
-	    {
-	      unsigned int dummy;
+	      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);
+		  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);
+		}
+	      else if (last_cie_inf->add_augmentation_size)
+		this_inf->growth += 1;
 	    }
 	  buf = last_fde + 4 + hdr.length;
 	  SKIP_RELOCS (buf);
 	}
 
+      this_inf->new_size = this_inf->size + this_inf->growth;
+      if (this_inf->growth > 0)
+	{
+	  /* Round the size up the next alignment boundary and adjust
+	     the section size accordingly.
+
+	     ??? It would be better to trim any existing padding first.  */
+	  this_inf->new_size = (this_inf->new_size + ptr_size - 1) & -ptr_size;
+	  new_size += this_inf->new_size - this_inf->size;
+	}
+
       this_inf->fde_encoding = cie.fde_encoding;
       this_inf->lsda_encoding = cie.lsda_encoding;
       sec_info->count++;
@@ -606,7 +643,7 @@ #define GET_RELOC(buf)					\
     if (!ent->removed)
       {
 	ent->new_offset = offset;
-	offset += ent->size;
+	offset += ent->new_size;
 	if (ent->cie)
 	  last_cie_inf = ent;
 	else
@@ -614,7 +651,7 @@ #define GET_RELOC(buf)					\
       }
   hdr_info->last_cie_inf = last_cie_inf;
 
-  /* Shrink the sec as needed.  */
+  /* Resize the sec as needed.  */
   sec->rawsize = sec->size;
   sec->size = new_size;
   if (sec->size == 0)
@@ -759,13 +796,8 @@ _bfd_elf_eh_frame_section_offset (bfd *o
      relocation against FDE's initial_location field.  */
   if (!sec_info->entry[mid].cie
       && sec_info->entry[mid].cie_inf->make_relative
-      && offset == sec_info->entry[mid].offset + 8
-      && (sec_info->entry[mid].cie_inf->need_relative
-	  || !hdr_info->offsets_adjusted))
-    {
-      sec_info->entry[mid].cie_inf->need_relative = 1;
-      return (bfd_vma) -2;
-    }
+      && offset == sec_info->entry[mid].offset + 8)
+    return (bfd_vma) -2;
 
   /* If converting LSDA pointers to DW_EH_PE_pcrel, there will be no need
      for run-time relocation against LSDA field.  */
@@ -782,8 +814,11 @@ _bfd_elf_eh_frame_section_offset (bfd *o
 
   if (hdr_info->offsets_adjusted)
     offset -= sec->output_offset;
+  /* If the new entry is bigger than the original, all the new bytes
+     will be inserted before the first relocation.  */
   return (offset + sec_info->entry[mid].new_offset
-	  - sec_info->entry[mid].offset);
+	  - sec_info->entry[mid].offset
+	  + sec_info->entry[mid].growth);
 }
 
 /* Write out .eh_frame section.  This is called with the relocated
@@ -798,7 +833,6 @@ _bfd_elf_write_section_eh_frame (bfd *ab
   struct eh_frame_sec_info *sec_info;
   struct elf_link_hash_table *htab;
   struct eh_frame_hdr_info *hdr_info;
-  bfd_byte *p, *buf;
   unsigned int leb128_tmp;
   unsigned int ptr_size;
   struct eh_cie_fde *ent;
@@ -851,7 +885,21 @@ _bfd_elf_write_section_eh_frame (bfd *ab
   if (hdr_info->array == NULL)
     hdr_info = NULL;
 
-  p = contents;
+  /* The new offsets can be bigger or smaller than the original offsets.
+     We therefore need to make two passes over the section: one backward
+     pass to move entries up and one forward pass to move entries down.
+     The two passes won't interfere with each other because the entries
+     are not reordered  */
+  for (ent = sec_info->entry + sec_info->count; ent-- != sec_info->entry;)
+    if (!ent->removed && ent->new_offset > ent->offset)
+      memmove (contents + ent->new_offset - sec->output_offset,
+	       contents + ent->offset - sec->output_offset, ent->size);
+
+  for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
+    if (!ent->removed && ent->new_offset < ent->offset)
+      memmove (contents + ent->new_offset - sec->output_offset,
+	       contents + ent->offset - sec->output_offset, ent->size);
+
   for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
     {
       if (ent->removed)
@@ -860,20 +908,27 @@ _bfd_elf_write_section_eh_frame (bfd *ab
       if (ent->cie)
 	{
 	  /* CIE */
-	  if (ent->need_relative
+	  if (ent->make_relative
 	      || ent->need_lsda_relative
 	      || ent->per_encoding_relative)
 	    {
-	      unsigned char *aug;
+	      unsigned char *buf, *aug, *end;
 	      unsigned int action;
 	      unsigned int dummy, per_width, per_encoding;
 
 	      /* Need to find 'R' or 'L' augmentation's argument and modify
 		 DW_EH_PE_* value.  */
-	      action = ((ent->need_relative ? 1 : 0)
+	      action = ((ent->make_relative ? 1 : 0)
 			| (ent->need_lsda_relative ? 2 : 0)
 			| (ent->per_encoding_relative ? 4 : 0));
-	      buf = contents + ent->offset - sec->output_offset;
+	      buf = contents + ent->new_offset - sec->output_offset;
+	      end = buf + ent->size;
+
+	      /* Install the new size, filling the extra bytes with
+		 DW_CFA_nops.  */
+	      memset (end, 0, ent->new_size - ent->size);
+	      bfd_put_32 (abfd, ent->new_size - 4, buf);
+
 	      /* Skip length, id and version.  */
 	      buf += 9;
 	      aug = buf;
@@ -883,10 +938,46 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 	      read_uleb128 (dummy, buf);
 	      if (*aug == 'z')
 		{
+		  /* Bump the size if we're adding an FDE encoding byte.
+		     The uleb128 will always be a single byte for the
+		     kind of augmentation strings that we're prepared
+		     to handle.  */
+		  if (ent->add_fde_encoding)
+		    *buf += 1;
 		  read_uleb128 (dummy, buf);
 		  aug++;
 		}
 
+	      if (ent->add_fde_encoding)
+		{
+		  BFD_ASSERT (action & 1);
+		  if (ent->add_augmentation_size)
+		    {
+		      /* We need to insert 'zR' into the augmentation
+			 string and add two bytes to the augmentation data.
+			 Shuffle everything appropriately and move BUF to
+			 account for the new string length.  */
+		      memmove (buf + 4, buf, end - buf);
+		      memmove (aug + 2, aug, buf - aug);
+		      buf += 2;
+
+		      *aug++ = 'z';
+		      *buf++ = 1;
+		    }
+		  else
+		    {
+		      /* As above, but we only need to insert 'R' into
+			 the augmentation string and we only need to
+			 add one byte to the data.  */
+		      memmove (buf + 2, buf, end - buf);
+		      memmove (aug + 1, aug, buf - aug);
+		      buf++;
+		    }
+		  *aug++ = 'R';
+		  *buf++ = DW_EH_PE_pcrel;
+		  action &= ~1;
+		}
+
 	      while (action)
 		switch (*aug++)
 		  {
@@ -915,7 +1006,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 
 			val = read_value (abfd, buf, per_width,
 					  get_DW_EH_PE_signed (per_encoding));
-			val += ent->offset - ent->new_offset;
+			val += ent->offset - ent->new_offset - ent->growth;
 			write_value (abfd, buf, val, per_width);
 			action &= ~4;
 		      }
@@ -938,10 +1029,18 @@ _bfd_elf_write_section_eh_frame (bfd *ab
       else if (ent->size > 4)
 	{
 	  /* FDE */
+	  bfd_byte *buf, *end;
 	  bfd_vma value, address;
 	  unsigned int width;
 
-	  buf = contents + ent->offset - sec->output_offset;
+	  buf = contents + ent->new_offset - sec->output_offset;
+	  end = buf + ent->size;
+
+	  /* Install the new size, filling the extra bytes with
+	     DW_CFA_nops.  */
+	  memset (end, 0, ent->new_size - ent->size);
+	  bfd_put_32 (abfd, ent->new_size - 4, buf);
+
 	  /* Skip length.  */
 	  buf += 4;
 	  value = ent->new_offset + 4 - ent->cie_inf->new_offset;
@@ -972,7 +1071,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 		  address += sec->output_section->vma + ent->offset + 8;
 		  break;
 		}
-	      if (ent->cie_inf->need_relative)
+	      if (ent->cie_inf->make_relative)
 		value -= sec->output_section->vma + ent->new_offset + 8;
 	      write_value (abfd, buf, value, width);
 	    }
@@ -1001,14 +1100,18 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 		  write_value (abfd, buf, value, width);
 		}
 	    }
+	  else if (ent->cie_inf->add_augmentation_size)
+	    {
+	      /* Skip the PC and length and insert a zero byte for the
+		 augmentation size.  */
+	      buf += width * 2;
+	      memmove (buf + 1, buf, end - buf);
+	      *buf = 0;
+	    }
 	}
       else
 	/* Terminating FDE must be at the end of .eh_frame section only.  */
 	BFD_ASSERT (ent == sec_info->entry + sec_info->count - 1);
-
-      BFD_ASSERT (p == contents + ent->new_offset - sec->output_offset);
-      memmove (p, contents + ent->offset - sec->output_offset, ent->size);
-      p += ent->size;
     }
 
     {
@@ -1021,6 +1124,8 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 	  && ((sec->output_offset + sec->size + pad)
 	      <= sec->output_section->size))
 	{
+	  bfd_byte *buf;
+
 	  /* Find the last CIE/FDE.  */
 	  ent = sec_info->entry + sec_info->count;
 	  while (--ent != sec_info->entry)
@@ -1035,20 +1140,17 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 
 	  buf = contents + ent->new_offset - sec->output_offset;
 
-	  /* Update length.  */
-	  ent->size += pad;
-	  bfd_put_32 (abfd, ent->size - 4, buf);
-
 	  /* Pad it with DW_CFA_nop  */
-	  memset (p, 0, pad);
-	  p += pad;
+	  memset (buf + ent->new_size, 0, pad);
+
+	  /* Update length.  */
+	  ent->new_size += pad;
+	  bfd_put_32 (abfd, ent->new_size - 4, buf);
 
 	  sec->size += pad;
 	}
     }
 
-  BFD_ASSERT ((bfd_size_type) (p - contents) == sec->size);
-
   return bfd_set_section_contents (abfd, sec->output_section,
 				   contents, (file_ptr) sec->output_offset,
 				   sec->size);
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.18
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.18 mips-elf.exp
--- ld/testsuite/ld-mips-elf/mips-elf.exp	8 Jul 2004 15:43:00 -0000	1.18
+++ ld/testsuite/ld-mips-elf/mips-elf.exp	13 Nov 2004 09:55:38 -0000
@@ -75,3 +75,7 @@ if $has_newabi {
 }
 run_dump_test "reloc-2"
 run_dump_test "reloc-merge-lo16"
+if {$has_newabi && $linux_gnu} {
+    run_dump_test "eh-frame1-n32"
+    run_dump_test "eh-frame1-n64"
+}
diff -u /dev/null ld/testsuite/ld-mips-elf/eh-frame1-n32.d
--- /dev/null	Fri Apr 23 00:21:55 2004
+++ ld/testsuite/ld-mips-elf/eh-frame1-n32.d	Sat Nov 13 09:43:09 2004
@@ -0,0 +1,263 @@
+#name: MIPS eh-frame 1, n32
+#source: eh-frame1.s
+#source: eh-frame1.s
+#as: -EB -n32 --defsym alignment=2 --defsym fill=0x40
+#readelf: --relocs -wf
+#ld: -shared -melf32btsmipn32 -Teh-frame1.ld
+
+Relocation section '\.rel\.dyn' .*:
+# Initial PCs for the FDEs attached to CIE 0xbc
+#...
+000300dc  00000003 R_MIPS_REL32     
+000300f0  00000003 R_MIPS_REL32     
+# Likewise CIE 0x220
+#...
+00030240  00000003 R_MIPS_REL32     
+00030254  00000003 R_MIPS_REL32     
+#...
+0003008b  00000503 R_MIPS_REL32      00000000   foo
+000300d0  00000503 R_MIPS_REL32      00000000   foo
+0003010e  00000503 R_MIPS_REL32      00000000   foo
+000301ef  00000503 R_MIPS_REL32      00000000   foo
+00030234  00000503 R_MIPS_REL32      00000000   foo
+00030272  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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+
+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 00000018 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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000094 00000010 00000020 FDE cie=00000078 pc=000200f0..00020100
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+
+000000a8 00000010 00000034 FDE cie=00000078 pc=00020100..00020120
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+
+000000bc 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
+
+
+000000d4 00000010 0000001c FDE cie=000000bc pc=00020120..00020130
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+
+000000e8 00000010 00000030 FDE cie=000000bc pc=00020130..00020150
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+
+000000fc 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_advance_loc: 0 to 00000000
+
+00000114 00000010 0000001c FDE cie=000000fc pc=00020150..00020160
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+
+# FDE for .discard removed
+# zPR2 removed
+00000128 00000010 00000030 FDE cie=000000fc pc=00020160..00020190
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+
+0000013c 00000010 00000044 FDE cie=000000fc pc=00020190..000201d0
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+
+00000150 00000010 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 1
+  Data alignment factor: 4
+  Return address column: 31
+  Augmentation data:     10
+
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+
+00000164 00000010 00000018 FDE cie=00000150 pc=000201d0..000201e0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+# basic1 removed, followed by repeat of above
+00000178 00000010 0000002c FDE cie=00000150 pc=000201e0..000201f0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+0000018c 00000010 00000040 FDE cie=00000150 pc=000201f0..00020210
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000001a0 00000010 00000054 FDE cie=00000150 pc=00020210..00020240
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000001b4 00000010 00000068 FDE cie=00000150 pc=00020240..00020280
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000001c8 00000010 0000007c FDE cie=00000150 pc=00020280..000202d0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000001dc 00000018 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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_nop
+  DW_CFA_nop
+
+000001f8 00000010 00000020 FDE cie=000001dc pc=000202d0..000202e0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+
+0000020c 00000010 00000034 FDE cie=000001dc pc=000202e0..00020300
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+
+00000220 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
+
+
+00000238 00000010 0000001c FDE cie=00000220 pc=00020300..00020310
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+
+0000024c 00000010 00000030 FDE cie=00000220 pc=00020310..00020330
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+
+00000260 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_advance_loc: 0 to 00000000
+
+00000278 00000010 0000001c FDE cie=00000260 pc=00020330..00020340
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+
+0000028c 00000010 00000030 FDE cie=00000260 pc=00020340..00020370
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+
+000002a0 00000010 00000044 FDE cie=00000260 pc=00020370..000203b0
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+
+000002b4 00000010 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 1
+  Data alignment factor: 4
+  Return address column: 31
+  Augmentation data:     10
+
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+
+000002c8 00000010 00000018 FDE cie=000002b4 pc=000203b0..000203c0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
diff -u /dev/null ld/testsuite/ld-mips-elf/eh-frame1-n64.d
--- /dev/null	Fri Apr 23 00:21:55 2004
+++ ld/testsuite/ld-mips-elf/eh-frame1-n64.d	Sat Nov 13 09:43:09 2004
@@ -0,0 +1,423 @@
+#name: MIPS eh-frame 1, n64
+#source: eh-frame1.s
+#source: eh-frame1.s
+#as: -EB -64 --defsym alignment=3 --defsym fill=0x40
+#readelf: --relocs -wf
+#ld: -shared -melf64btsmip -Teh-frame1.ld
+
+Relocation section '\.rel\.dyn' .*:
+# Initial PCs for the FDEs attached to CIE 0x120
+#...
+000000030148  000000001203 R_MIPS_REL32 *
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+000000030168  000000001203 R_MIPS_REL32 *
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+# Likewise CIE 0x340
+#...
+000000030368  000000001203 R_MIPS_REL32 *
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+000000030388  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 *
+000000030138  000500001203 R_MIPS_REL32      0000000000000000 foo
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+000000030192  000500001203 R_MIPS_REL32      0000000000000000 foo
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+0000000302eb  000500001203 R_MIPS_REL32      0000000000000000 foo
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+000000030358  000500001203 R_MIPS_REL32      0000000000000000 foo
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+0000000303b2  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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  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 00000024 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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000000e0 0000001c 0000002c FDE cie=000000b8 pc=000200f0..00020100
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+
+00000100 0000001c 0000004c FDE cie=000000b8 pc=00020100..00020120
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+
+00000120 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
+
+
+00000140 0000001c 00000024 FDE cie=00000120 pc=00020120..00020130
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+
+00000160 0000001c 00000044 FDE cie=00000120 pc=00020130..00020150
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+
+00000180 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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+
+000001a0 0000001c 00000024 FDE cie=00000180 pc=00020150..00020160
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+
+# FDE for .discard removed
+# zPR2 removed
+000001c0 0000001c 00000044 FDE cie=00000180 pc=00020160..00020190
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+
+000001e0 0000001c 00000064 FDE cie=00000180 pc=00020190..000201d0
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+
+00000200 00000014 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 1
+  Data alignment factor: 4
+  Return address column: 31
+  Augmentation data:     10
+
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000218 0000001c 0000001c FDE cie=00000200 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
+00000238 0000001c 0000003c FDE cie=00000200 pc=000201e0..000201f0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000258 0000001c 0000005c FDE cie=00000200 pc=000201f0..00020210
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000278 0000001c 0000007c FDE cie=00000200 pc=00020210..00020240
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000298 0000001c 0000009c FDE cie=00000200 pc=00020240..00020280
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000002b8 0000001c 000000bc FDE cie=00000200 pc=00020280..000202d0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000002d8 00000024 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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000300 0000001c 0000002c FDE cie=000002d8 pc=000202d0..000202e0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+
+00000320 0000001c 0000004c FDE cie=000002d8 pc=000202e0..00020300
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+
+00000340 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
+
+
+00000360 0000001c 00000024 FDE cie=00000340 pc=00020300..00020310
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+
+00000380 0000001c 00000044 FDE cie=00000340 pc=00020310..00020330
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+
+000003a0 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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+
+000003c0 0000001c 00000024 FDE cie=000003a0 pc=00020330..00020340
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+
+000003e0 0000001c 00000044 FDE cie=000003a0 pc=00020340..00020370
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+
+00000400 0000001c 00000064 FDE cie=000003a0 pc=00020370..000203b0
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+
+00000420 00000014 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 1
+  Data alignment factor: 4
+  Return address column: 31
+  Augmentation data:     10
+
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000438 0000001c 0000001c FDE cie=00000420 pc=000203b0..000203c0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
diff -u /dev/null ld/testsuite/ld-mips-elf/eh-frame1.ld
--- /dev/null	Fri Apr 23 00:21:55 2004
+++ ld/testsuite/ld-mips-elf/eh-frame1.ld	Sat Nov 13 09:43:09 2004
@@ -0,0 +1,18 @@
+SECTIONS
+{
+  . = 0x10000;
+  .dynamic : { *(.dynamic) }
+  .hash : { *(.hash) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+  .rel.dyn : { *(.rel.dyn) }
+
+  . = 0x20000;
+  .text : { *(.text) }
+
+  . = 0x30000;
+  .eh_frame : { *(.eh_frame) }
+  .got : { *(.got) }
+
+  /DISCARD/ : { *(*) }
+}
diff -u /dev/null ld/testsuite/ld-mips-elf/eh-frame1.s
--- /dev/null	Fri Apr 23 00:21:55 2004
+++ ld/testsuite/ld-mips-elf/eh-frame1.s	Sat Nov 13 09:43:09 2004
@@ -0,0 +1,148 @@
+#----------------------------------------------------------------------------
+# Macros
+#----------------------------------------------------------------------------
+
+	mask = (1 << alignment) - 1
+
+	# Output VALUE as an unaligned pointer-sized quantity.
+	.macro pbyte value
+	.if alignment == 2
+	.4byte		\value
+	.else
+	.8byte		\value
+	.endif
+	.endm
+
+
+	# Start a new CIE, and emit everything up to the augmentation data.
+	# Use LABEL to mark the start of the entry and AUG as the augmentation
+	# string.
+	.macro start_cie label,aug
+	.section	.eh_frame,"aw",@progbits
+\label:
+	.word		2f-1f		# Length
+1:
+	.word		0		# Identifier
+	.byte		1		# Version
+	.string		"\aug"		# Augmentation
+	.byte		1		# Code alignment
+	.byte		4		# Data alignment
+	.byte		31		# Return address column
+	.endm
+
+
+	# Create a dummy function of SIZE bytes in SECTION and emit the
+	# first four entries of an FDE for it (total 16 bytes).
+	.macro start_fde cie,section,size
+	.section	\section,"ax",@progbits
+3:
+	.rept		\size / 4
+	nop
+	.endr
+4:
+	.section	.eh_frame,"aw",@progbits
+	.word		2f-1f		# Length
+1:
+	.word		.-\cie		# CIE offset
+	pbyte		3b		# Initial PC
+	pbyte		4b-3b		# Size of code
+	.endm
+
+
+	# Finish a CIE or FDE entry.
+	.macro end_entry
+	.p2align	alignment,fill
+2:
+	.endm
+
+
+	# Start the augmentation data for a CIE that has a 'P' entry
+	# followed by EXTRA bytes.  AUGLEN is the length of augmentation
+	# string (including zero terminator), ENCODING is the encoding to
+	# use for the personality routine and VALUE is the value it
+	# should have.
+	.macro		persaug auglen,extra,encoding,value
+	.if (\encoding & 0xf0) == 0x50
+	.byte		(-(9 + \auglen + 3 + 2) & mask) + 2 + mask + \extra
+	.byte		\encoding
+	.fill		-(9 + \auglen + 3 + 2) & mask,1,0
+	.else
+	.byte		2 + mask + \extra
+	.byte		\encoding
+	.endif
+	pbyte		\value
+	.endm
+
+
+	.macro cie_basic label
+	start_cie	\label,""
+	end_entry
+	.endm
+
+	.macro fde_basic cie,section,size
+	start_fde	\cie,\section,\size
+	end_entry
+	.endm
+
+
+	.macro cie_zP label,encoding,value
+	start_cie	 \label,"zP"
+	persaug		3,0,\encoding,\value
+	end_entry
+	.endm
+
+	.macro fde_zP cie,section,size
+	start_fde	 \cie,\section,\size
+	.byte		 0		# Augmentation length
+	end_entry
+	.endm
+
+
+	.macro cie_zPR label,encoding,value
+	start_cie	 \label,"zPR"
+	persaug		4,1,\encoding,\value
+	.byte		0		# FDE enconding
+	end_entry
+	.endm
+
+	.macro fde_zPR cie,section,size
+	start_fde	\cie,\section,\size
+	.byte		0		# Augmentation length
+	end_entry
+	.endm
+
+#----------------------------------------------------------------------------
+# Test code
+#----------------------------------------------------------------------------
+
+	cie_basic	basic1
+	fde_basic	basic1,.text,0x10
+	fde_basic	basic1,.text,0x20
+
+	cie_basic	basic2
+	fde_basic	basic2,.text,0x30
+
+	cie_basic	basic3
+	fde_basic	basic3,.text,0x40
+
+	cie_basic	basic4
+	fde_basic	basic4,.text,0x50
+
+	cie_zP		zP_unalign1,0x00,foo
+	fde_zP		zP_unalign1,.text,0x10
+	fde_zP		zP_unalign1,.text,0x20
+
+	cie_zP		zP_align1,0x50,foo
+	fde_zP		zP_align1,.text,0x10
+	fde_zP		zP_align1,.text,0x20
+
+	cie_zPR		zPR1,0x00,foo
+	fde_zPR		zPR1,.text,0x10
+	fde_zPR		zPR1,.discard,0x20
+
+	cie_zPR		zPR2,0x00,foo
+	fde_zPR		zPR2,.text,0x30
+	fde_zPR		zPR2,.text,0x40
+
+	cie_basic	basic5
+	fde_basic	basic5,.text,0x10

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

* Re: RFA: Extensions to the .eh_frame linker code
  2004-11-13 12:12 RFA: Extensions to the .eh_frame linker code Richard Sandiford
@ 2004-11-15  2:07 ` Alan Modra
  2004-11-15  9:07   ` Richard Sandiford
  0 siblings, 1 reply; 6+ messages in thread
From: Alan Modra @ 2004-11-15  2:07 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: binutils

On Sat, Nov 13, 2004 at 12:12:24PM +0000, Richard Sandiford wrote:
> The make_relative/need_relative distinction was a result of Alan's
> fix for ld/418.  As I understand it, the important part of that change
> was really the make_lsda_relative/need_lsda_relative split (because we
> don't know for sure what the LSDA actually contains).  It looks like
> the make_relative/need_relative part was done more for consistency
> than anything.

True enough.  I can't think of any situation where need_relative won't
be set if make_relative isn't set, except for FDEs that are discarded.

> @@ -289,6 +289,8 @@ struct eh_cie_fde
>    /* For FDEs, this points to the CIE used.  */
>    struct eh_cie_fde *cie_inf;
>    unsigned int size;
> +  unsigned int growth;
> +  unsigned int new_size;
>    unsigned int offset;
>    unsigned int new_offset;
>    unsigned char fde_encoding;

Can you do without these extra fields?  It seems a waste of memory to
have them in a struct kept for all FDEs.  Perhaps you could split this
struct into two variants, one for CIEs and one for FDEs.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

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

* Re: RFA: Extensions to the .eh_frame linker code
  2004-11-15  2:07 ` Alan Modra
@ 2004-11-15  9:07   ` Richard Sandiford
  2004-11-15 12:40     ` Alan Modra
  0 siblings, 1 reply; 6+ messages in thread
From: Richard Sandiford @ 2004-11-15  9:07 UTC (permalink / raw)
  To: binutils

Alan Modra <amodra@bigpond.net.au> writes:
>> @@ -289,6 +289,8 @@ struct eh_cie_fde
>>    /* For FDEs, this points to the CIE used.  */
>>    struct eh_cie_fde *cie_inf;
>>    unsigned int size;
>> +  unsigned int growth;
>> +  unsigned int new_size;
>>    unsigned int offset;
>>    unsigned int new_offset;
>>    unsigned char fde_encoding;
>
> Can you do without these extra fields?  It seems a waste of memory to
> have them in a struct kept for all FDEs.  Perhaps you could split this
> struct into two variants, one for CIEs and one for FDEs.

Well, if we're adding a 'z' augmentation, both CIEs and FDEs can grow,
so the fields aren't fully redundant for FDEs.  If space is a concern,
would it be OK to have:

     unsigned char growth : 4;
     unsigned char rounded_growth : 4;

(I'll try to think of better names ;) after the three existing
"unsigned char" fields?  The old "new_size" field would then
be "size + rounded_growth".

(Although at the moment it's easy to work out rounded_growth from
growth, I'll need the two fields for the "eat existing padding"
optimisation).

Richard

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

* Re: RFA: Extensions to the .eh_frame linker code
  2004-11-15  9:07   ` Richard Sandiford
@ 2004-11-15 12:40     ` Alan Modra
  2004-11-15 20:33       ` Richard Sandiford
  0 siblings, 1 reply; 6+ messages in thread
From: Alan Modra @ 2004-11-15 12:40 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: binutils

On Mon, Nov 15, 2004 at 09:06:51AM +0000, Richard Sandiford wrote:
> Well, if we're adding a 'z' augmentation, both CIEs and FDEs can grow,
> so the fields aren't fully redundant for FDEs. [snip]

Perhaps I should have explained myself better.  I'm a little
uncomfortable with the way this struct is evolving.  We have "size"
which is the size of the FDE or CIE, "offset" and "new_offset" which
index the old and new section contents, plus assorted flags and other
data.  Now you want to add some new size and offset related fields that
to me look redundant.  I think you should be able to manage with your
new add_* flags and set new_offset in _bfd_elf_discard_section_eh_frame
to reflect any needed growth.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

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

* Re: RFA: Extensions to the .eh_frame linker code
  2004-11-15 12:40     ` Alan Modra
@ 2004-11-15 20:33       ` Richard Sandiford
  2004-11-15 22:41         ` Alan Modra
  0 siblings, 1 reply; 6+ messages in thread
From: Richard Sandiford @ 2004-11-15 20:33 UTC (permalink / raw)
  To: binutils

Alan Modra <amodra@bigpond.net.au> writes:
> On Mon, Nov 15, 2004 at 09:06:51AM +0000, Richard Sandiford wrote:
>> Well, if we're adding a 'z' augmentation, both CIEs and FDEs can grow,
>> so the fields aren't fully redundant for FDEs. [snip]
>
> Perhaps I should have explained myself better.  I'm a little
> uncomfortable with the way this struct is evolving.  We have "size"
> which is the size of the FDE or CIE, "offset" and "new_offset" which
> index the old and new section contents, plus assorted flags and other
> data.  Now you want to add some new size and offset related fields that
> to me look redundant.  I think you should be able to manage with your
> new add_* flags and set new_offset in _bfd_elf_discard_section_eh_frame
> to reflect any needed growth.

OK, how about the patch below?  It uses functions to calculate the
growth in the augmentation string, the growth in the augmentation data,
and the size of the output CIE or FDE.  I'm not sure whether it really
addresses your concerns, but I have to admit that I like it better than
yesterday's patch, so thanks for pushing back. ;)

At first, I was worried that this would make it harder to do the
padding optimisation I mentioned (i.e. eating existing DW_CFA_nop
padding before growing an entry).  I'm now wondering if that can
be done by redefining "size" to be the size of the unpadded entry.
Will look into that if the patch is OK.

Anyway, patch tested against mips64-linux-gnu.  OK to install?

Richard


bfd/
	* elf-bfd.h (eh_cie_fde): Add new fields: add_augmentation_size and
	add_fde_encoding.  Remove need_relative.
	* elf-eh-frame.c (extra_augmentation_string_bytes)
	(extra_augmentation_data_bytes, size_of_output_cie_fde): New functions.
	(_bfd_elf_discard_section_eh_frame): Consider changing the FDE encoding
	in cases where the CIE has no existing 'R' augmentation.  Use
	size_of_output_cie_fde when assigning offsets.  Use the final offset
	as the new section size.
	(_bfd_elf_eh_frame_section_offset): Remove need_relative handling.
	Account for any extra augmentation bytes in the returned offset.
	(_bfd_elf_write_section_eh_frame): Rework so that the entries are
	moved before being modified.  Pad growing entries with DW_CFA_nops.
	Add 'z' and 'R' augmentations as directed by add_augmentation_size
	and add_fde_encoding.

ld/testsuite
	* ld-mips-elf/eh-frame1.{s,ld},
	* ld-mips-elf/eh-frame1-{n32,n64},d: New test.
	* ld-mips-elf/mips-elf.exp: Run it.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.162
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.162 elf-bfd.h
--- bfd/elf-bfd.h	14 Oct 2004 23:38:08 -0000	1.162
+++ bfd/elf-bfd.h	15 Nov 2004 20:16:24 -0000
@@ -296,9 +296,10 @@ struct eh_cie_fde
   unsigned char lsda_offset;
   unsigned int cie : 1;
   unsigned int removed : 1;
+  unsigned int add_augmentation_size : 1;
+  unsigned int add_fde_encoding : 1;
   unsigned int make_relative : 1;
   unsigned int make_lsda_relative : 1;
-  unsigned int need_relative : 1;
   unsigned int need_lsda_relative : 1;
   unsigned int per_encoding_relative : 1;
 };
Index: bfd/elf-eh-frame.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-eh-frame.c,v
retrieving revision 1.36
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.36 elf-eh-frame.c
--- bfd/elf-eh-frame.c	15 Nov 2004 09:09:13 -0000	1.36
+++ bfd/elf-eh-frame.c	15 Nov 2004 20:16:24 -0000
@@ -200,6 +200,60 @@ int cie_compare (struct cie *c1, struct 
   return 1;
 }
 
+/* Return the number of extra bytes that we'll be inserting into
+   ENTRY's augmentation string.  */
+
+static INLINE unsigned int
+extra_augmentation_string_bytes (struct eh_cie_fde *entry)
+{
+  unsigned int size = 0;
+  if (entry->cie)
+    {
+      if (entry->add_augmentation_size)
+	size++;
+      if (entry->add_fde_encoding)
+	size++;
+    }
+  return size;
+}
+
+/* Likewise ENTRY's augmentation data.  */
+
+static INLINE unsigned int
+extra_augmentation_data_bytes (struct eh_cie_fde *entry)
+{
+  unsigned int size = 0;
+  if (entry->cie)
+    {
+      if (entry->add_augmentation_size)
+	size++;
+      if (entry->add_fde_encoding)
+	size++;
+    }
+  else
+    {
+      if (entry->cie_inf->add_augmentation_size)
+	size++;
+    }
+  return size;
+}
+
+/* Return the size that ENTRY will have in the output.  ALIGNMENT is the
+   required alignment of ENTRY in bytes.  */
+
+static unsigned int
+size_of_output_cie_fde (struct eh_cie_fde *entry, unsigned int alignment)
+{
+  if (entry->removed)
+    return 0;
+  if (entry->size == 4)
+    return 4;
+  return (entry->size
+	  + extra_augmentation_string_bytes (entry)
+	  + extra_augmentation_data_bytes (entry)
+	  + alignment - 1) & -alignment;
+}
+
 /* 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
@@ -221,7 +275,6 @@ _bfd_elf_discard_section_eh_frame
   struct eh_frame_sec_info *sec_info = NULL;
   unsigned int leb128_tmp;
   unsigned int cie_usage_count, offset;
-  bfd_size_type new_size;
   unsigned int ptr_size;
 
   if (sec->size == 0)
@@ -267,7 +320,6 @@ _bfd_elf_discard_section_eh_frame
   last_cie_inf = NULL;
   memset (&cie, 0, sizeof (cie));
   cie_usage_count = 0;
-  new_size = sec->size;
   sec_info = bfd_zmalloc (sizeof (struct eh_frame_sec_info)
 			  + 99 * sizeof (struct eh_cie_fde));
   if (sec_info == NULL)
@@ -379,10 +431,7 @@ #define GET_RELOC(buf)					\
 		       == hdr_info->last_cie_sec->output_section)
 		   && cie_compare (&cie, &hdr_info->last_cie) == 0)
 		  || cie_usage_count == 0)
-		{
-		  new_size -= cie.hdr.length + 4;
-		  last_cie_inf->removed = 1;
-		}
+		last_cie_inf->removed = 1;
 	      else
 		{
 		  hdr_info->last_cie = cie;
@@ -517,9 +566,22 @@ #define GET_RELOC(buf)					\
 	  if (info->shared
 	      && (get_elf_backend_data (abfd)
 		  ->elf_backend_can_make_relative_eh_frame
-		  (abfd, info, sec))
-	      && (cie.fde_encoding & 0xf0) == DW_EH_PE_absptr)
-	    cie.make_relative = 1;
+		  (abfd, info, sec)))
+	    {
+	      if ((cie.fde_encoding & 0xf0) == DW_EH_PE_absptr)
+		cie.make_relative = 1;
+	      /* If the CIE doesn't already have an 'R' entry, it's fairly
+		 easy to add one, provided that there's no aligned data
+		 after the augmentation string.  */
+	      else if (cie.fde_encoding == DW_EH_PE_omit
+		       && (cie.per_encoding & 0xf0) != DW_EH_PE_aligned)
+		{
+		  if (*cie.augmentation == 0)
+		    this_inf->add_augmentation_size = 1;
+		  this_inf->add_fde_encoding = 1;
+		  cie.make_relative = 1;
+		}
+	    }
 
 	  if (info->shared
 	      && (get_elf_backend_data (abfd)
@@ -556,12 +618,9 @@ #define GET_RELOC(buf)					\
 	    goto free_no_table;
 
 	  if ((*reloc_symbol_deleted_p) (buf - ehbuf, cookie))
-	    {
-	      /* This is a FDE against a discarded section.  It should
-		 be deleted.  */
-	      new_size -= hdr.length + 4;
-	      this_inf->removed = 1;
-	    }
+	    /* This is a FDE against a discarded section.  It should
+	       be deleted.  */
+	    this_inf->removed = 1;
 	  else
 	    {
 	      if (info->shared
@@ -608,23 +667,23 @@ #define GET_RELOC(buf)					\
   for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
     if (!ent->removed)
       {
-	ent->new_offset = offset;
-	offset += ent->size;
 	if (ent->cie)
 	  last_cie_inf = ent;
 	else
 	  ent->cie_inf = last_cie_inf;
+	ent->new_offset = offset;
+	offset += size_of_output_cie_fde (ent, ptr_size);
       }
   hdr_info->last_cie_inf = last_cie_inf;
 
-  /* Shrink the sec as needed.  */
+  /* Resize the sec as needed.  */
   sec->rawsize = sec->size;
-  sec->size = new_size;
+  sec->size = offset;
   if (sec->size == 0)
     sec->flags |= SEC_EXCLUDE;
 
   free (ehbuf);
-  return new_size != sec->rawsize;
+  return offset != sec->rawsize;
 
 free_no_table:
   if (ehbuf)
@@ -762,13 +821,8 @@ _bfd_elf_eh_frame_section_offset (bfd *o
      relocation against FDE's initial_location field.  */
   if (!sec_info->entry[mid].cie
       && sec_info->entry[mid].cie_inf->make_relative
-      && offset == sec_info->entry[mid].offset + 8
-      && (sec_info->entry[mid].cie_inf->need_relative
-	  || !hdr_info->offsets_adjusted))
-    {
-      sec_info->entry[mid].cie_inf->need_relative = 1;
-      return (bfd_vma) -2;
-    }
+      && offset == sec_info->entry[mid].offset + 8)
+    return (bfd_vma) -2;
 
   /* If converting LSDA pointers to DW_EH_PE_pcrel, there will be no need
      for run-time relocation against LSDA field.  */
@@ -785,8 +839,11 @@ _bfd_elf_eh_frame_section_offset (bfd *o
 
   if (hdr_info->offsets_adjusted)
     offset -= sec->output_offset;
+  /* Any new augmentation bytes go before the first relocation.  */
   return (offset + sec_info->entry[mid].new_offset
-	  - sec_info->entry[mid].offset);
+	  - sec_info->entry[mid].offset
+	  + extra_augmentation_string_bytes (sec_info->entry + mid)
+	  + extra_augmentation_data_bytes (sec_info->entry + mid));
 }
 
 /* Write out .eh_frame section.  This is called with the relocated
@@ -801,7 +858,6 @@ _bfd_elf_write_section_eh_frame (bfd *ab
   struct eh_frame_sec_info *sec_info;
   struct elf_link_hash_table *htab;
   struct eh_frame_hdr_info *hdr_info;
-  bfd_byte *p, *buf;
   unsigned int leb128_tmp;
   unsigned int ptr_size;
   struct eh_cie_fde *ent;
@@ -854,29 +910,66 @@ _bfd_elf_write_section_eh_frame (bfd *ab
   if (hdr_info->array == NULL)
     hdr_info = NULL;
 
-  p = contents;
+  /* The new offsets can be bigger or smaller than the original offsets.
+     We therefore need to make two passes over the section: one backward
+     pass to move entries up and one forward pass to move entries down.
+     The two passes won't interfere with each other because entries are
+     not reordered  */
+  for (ent = sec_info->entry + sec_info->count; ent-- != sec_info->entry;)
+    if (!ent->removed && ent->new_offset > ent->offset)
+      memmove (contents + ent->new_offset - sec->output_offset,
+	       contents + ent->offset - sec->output_offset, ent->size);
+
+  for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
+    if (!ent->removed && ent->new_offset < ent->offset)
+      memmove (contents + ent->new_offset - sec->output_offset,
+	       contents + ent->offset - sec->output_offset, ent->size);
+
   for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent)
     {
+      unsigned char *buf, *end;
+      unsigned int new_size;
+
       if (ent->removed)
 	continue;
 
+      if (ent->size == 4)
+	{
+	  /* Any terminating FDE must be at the end of the section.  */
+	  BFD_ASSERT (ent == sec_info->entry + sec_info->count - 1);
+	  continue;
+	}
+
+      buf = contents + ent->new_offset - sec->output_offset;
+      end = buf + ent->size;
+      new_size = size_of_output_cie_fde (ent, ptr_size);
+
+      /* Install the new size, filling the extra bytes with DW_CFA_nops.  */
+      if (new_size != ent->size)
+	{
+	  memset (end, 0, new_size - ent->size);
+	  bfd_put_32 (abfd, new_size - 4, buf);
+	}
+
       if (ent->cie)
 	{
 	  /* CIE */
-	  if (ent->need_relative
+	  if (ent->make_relative
 	      || ent->need_lsda_relative
 	      || ent->per_encoding_relative)
 	    {
 	      unsigned char *aug;
-	      unsigned int action;
+	      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.  */
-	      action = ((ent->need_relative ? 1 : 0)
+	      action = ((ent->make_relative ? 1 : 0)
 			| (ent->need_lsda_relative ? 2 : 0)
 			| (ent->per_encoding_relative ? 4 : 0));
-	      buf = contents + ent->offset - sec->output_offset;
+	      extra_string = extra_augmentation_string_bytes (ent);
+	      extra_data = extra_augmentation_data_bytes (ent);
+
 	      /* Skip length, id and version.  */
 	      buf += 9;
 	      aug = buf;
@@ -886,10 +979,30 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 	      read_uleb128 (dummy, buf);
 	      if (*aug == 'z')
 		{
-		  read_uleb128 (dummy, buf);
+		  /* The uleb128 will always be a single byte for the kind
+		     of augmentation strings that we're prepared to handle.  */
+		  *buf++ += extra_data;
 		  aug++;
 		}
 
+	      /* Make room for the new augmentation string and data bytes.  */
+	      memmove (buf + extra_string + extra_data, buf, end - buf);
+	      memmove (aug + extra_string, aug, buf - aug);
+	      buf += extra_string;
+
+	      if (ent->add_augmentation_size)
+		{
+		  *aug++ = 'z';
+		  *buf++ = extra_data - 1;
+		}
+	      if (ent->add_fde_encoding)
+		{
+		  BFD_ASSERT (action & 1);
+		  *aug++ = 'R';
+		  *buf++ = DW_EH_PE_pcrel;
+		  action &= ~1;
+		}
+
 	      while (action)
 		switch (*aug++)
 		  {
@@ -919,6 +1032,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 			val = read_value (abfd, buf, per_width,
 					  get_DW_EH_PE_signed (per_encoding));
 			val += ent->offset - ent->new_offset;
+			val -= extra_string + extra_data;
 			write_value (abfd, buf, val, per_width);
 			action &= ~4;
 		      }
@@ -938,13 +1052,12 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 		  }
 	    }
 	}
-      else if (ent->size > 4)
+      else
 	{
 	  /* FDE */
 	  bfd_vma value, address;
 	  unsigned int width;
 
-	  buf = contents + ent->offset - sec->output_offset;
 	  /* Skip length.  */
 	  buf += 4;
 	  value = ent->new_offset + 4 - ent->cie_inf->new_offset;
@@ -975,7 +1088,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 		  address += sec->output_section->vma + ent->offset + 8;
 		  break;
 		}
-	      if (ent->cie_inf->need_relative)
+	      if (ent->cie_inf->make_relative)
 		value -= sec->output_section->vma + ent->new_offset + 8;
 	      write_value (abfd, buf, value, width);
 	    }
@@ -1004,14 +1117,15 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 		  write_value (abfd, buf, value, width);
 		}
 	    }
+	  else if (ent->cie_inf->add_augmentation_size)
+	    {
+	      /* Skip the PC and length and insert a zero byte for the
+		 augmentation size.  */
+	      buf += width * 2;
+	      memmove (buf + 1, buf, end - buf);
+	      *buf = 0;
+	    }
 	}
-      else
-	/* Terminating FDE must be at the end of .eh_frame section only.  */
-	BFD_ASSERT (ent == sec_info->entry + sec_info->count - 1);
-
-      BFD_ASSERT (p == contents + ent->new_offset - sec->output_offset);
-      memmove (p, contents + ent->offset - sec->output_offset, ent->size);
-      p += ent->size;
     }
 
     {
@@ -1024,6 +1138,9 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 	  && ((sec->output_offset + sec->size + pad)
 	      <= sec->output_section->size))
 	{
+	  bfd_byte *buf;
+	  unsigned int new_size;
+
 	  /* Find the last CIE/FDE.  */
 	  ent = sec_info->entry + sec_info->count;
 	  while (--ent != sec_info->entry)
@@ -1035,23 +1152,17 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 	    abort ();
 
 	  pad = alignment - pad;
-
 	  buf = contents + ent->new_offset - sec->output_offset;
-
-	  /* Update length.  */
-	  ent->size += pad;
-	  bfd_put_32 (abfd, ent->size - 4, buf);
+	  new_size = size_of_output_cie_fde (ent, ptr_size);
 
 	  /* Pad it with DW_CFA_nop  */
-	  memset (p, 0, pad);
-	  p += pad;
+	  memset (buf + new_size, 0, pad);
+	  bfd_put_32 (abfd, new_size + pad - 4, buf);
 
 	  sec->size += pad;
 	}
     }
 
-  BFD_ASSERT ((bfd_size_type) (p - contents) == sec->size);
-
   return bfd_set_section_contents (abfd, sec->output_section,
 				   contents, (file_ptr) sec->output_offset,
 				   sec->size);
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.18
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.18 mips-elf.exp
--- ld/testsuite/ld-mips-elf/mips-elf.exp	8 Jul 2004 15:43:00 -0000	1.18
+++ ld/testsuite/ld-mips-elf/mips-elf.exp	13 Nov 2004 09:55:38 -0000
@@ -75,3 +75,7 @@ if $has_newabi {
 }
 run_dump_test "reloc-2"
 run_dump_test "reloc-merge-lo16"
+if {$has_newabi && $linux_gnu} {
+    run_dump_test "eh-frame1-n32"
+    run_dump_test "eh-frame1-n64"
+}
diff -u /dev/null ld/testsuite/ld-mips-elf/eh-frame1-n32.d
--- /dev/null	Fri Apr 23 00:21:55 2004
+++ ld/testsuite/ld-mips-elf/eh-frame1-n32.d	Sat Nov 13 09:43:09 2004
@@ -0,0 +1,263 @@
+#name: MIPS eh-frame 1, n32
+#source: eh-frame1.s
+#source: eh-frame1.s
+#as: -EB -n32 --defsym alignment=2 --defsym fill=0x40
+#readelf: --relocs -wf
+#ld: -shared -melf32btsmipn32 -Teh-frame1.ld
+
+Relocation section '\.rel\.dyn' .*:
+# Initial PCs for the FDEs attached to CIE 0xbc
+#...
+000300dc  00000003 R_MIPS_REL32     
+000300f0  00000003 R_MIPS_REL32     
+# Likewise CIE 0x220
+#...
+00030240  00000003 R_MIPS_REL32     
+00030254  00000003 R_MIPS_REL32     
+#...
+0003008b  00000503 R_MIPS_REL32      00000000   foo
+000300d0  00000503 R_MIPS_REL32      00000000   foo
+0003010e  00000503 R_MIPS_REL32      00000000   foo
+000301ef  00000503 R_MIPS_REL32      00000000   foo
+00030234  00000503 R_MIPS_REL32      00000000   foo
+00030272  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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+
+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 00000018 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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000094 00000010 00000020 FDE cie=00000078 pc=000200f0..00020100
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+
+000000a8 00000010 00000034 FDE cie=00000078 pc=00020100..00020120
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+
+000000bc 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
+
+
+000000d4 00000010 0000001c FDE cie=000000bc pc=00020120..00020130
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+
+000000e8 00000010 00000030 FDE cie=000000bc pc=00020130..00020150
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+
+000000fc 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_advance_loc: 0 to 00000000
+
+00000114 00000010 0000001c FDE cie=000000fc pc=00020150..00020160
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+
+# FDE for .discard removed
+# zPR2 removed
+00000128 00000010 00000030 FDE cie=000000fc pc=00020160..00020190
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+
+0000013c 00000010 00000044 FDE cie=000000fc pc=00020190..000201d0
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+
+00000150 00000010 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 1
+  Data alignment factor: 4
+  Return address column: 31
+  Augmentation data:     10
+
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+
+00000164 00000010 00000018 FDE cie=00000150 pc=000201d0..000201e0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+# basic1 removed, followed by repeat of above
+00000178 00000010 0000002c FDE cie=00000150 pc=000201e0..000201f0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+0000018c 00000010 00000040 FDE cie=00000150 pc=000201f0..00020210
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000001a0 00000010 00000054 FDE cie=00000150 pc=00020210..00020240
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000001b4 00000010 00000068 FDE cie=00000150 pc=00020240..00020280
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000001c8 00000010 0000007c FDE cie=00000150 pc=00020280..000202d0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000001dc 00000018 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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_nop
+  DW_CFA_nop
+
+000001f8 00000010 00000020 FDE cie=000001dc pc=000202d0..000202e0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+
+0000020c 00000010 00000034 FDE cie=000001dc pc=000202e0..00020300
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+
+00000220 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
+
+
+00000238 00000010 0000001c FDE cie=00000220 pc=00020300..00020310
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+
+0000024c 00000010 00000030 FDE cie=00000220 pc=00020310..00020330
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+
+00000260 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_advance_loc: 0 to 00000000
+
+00000278 00000010 0000001c FDE cie=00000260 pc=00020330..00020340
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+
+0000028c 00000010 00000030 FDE cie=00000260 pc=00020340..00020370
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+
+000002a0 00000010 00000044 FDE cie=00000260 pc=00020370..000203b0
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+
+000002b4 00000010 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 1
+  Data alignment factor: 4
+  Return address column: 31
+  Augmentation data:     10
+
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+
+000002c8 00000010 00000018 FDE cie=000002b4 pc=000203b0..000203c0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
diff -u /dev/null ld/testsuite/ld-mips-elf/eh-frame1-n64.d
--- /dev/null	Fri Apr 23 00:21:55 2004
+++ ld/testsuite/ld-mips-elf/eh-frame1-n64.d	Sat Nov 13 09:43:09 2004
@@ -0,0 +1,423 @@
+#name: MIPS eh-frame 1, n64
+#source: eh-frame1.s
+#source: eh-frame1.s
+#as: -EB -64 --defsym alignment=3 --defsym fill=0x40
+#readelf: --relocs -wf
+#ld: -shared -melf64btsmip -Teh-frame1.ld
+
+Relocation section '\.rel\.dyn' .*:
+# Initial PCs for the FDEs attached to CIE 0x120
+#...
+000000030148  000000001203 R_MIPS_REL32 *
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+000000030168  000000001203 R_MIPS_REL32 *
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+# Likewise CIE 0x340
+#...
+000000030368  000000001203 R_MIPS_REL32 *
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+000000030388  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 *
+000000030138  000500001203 R_MIPS_REL32      0000000000000000 foo
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+000000030192  000500001203 R_MIPS_REL32      0000000000000000 foo
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+0000000302eb  000500001203 R_MIPS_REL32      0000000000000000 foo
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+000000030358  000500001203 R_MIPS_REL32      0000000000000000 foo
+ *Type2: R_MIPS_64 *
+ *Type3: R_MIPS_NONE *
+0000000303b2  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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  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 00000024 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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000000e0 0000001c 0000002c FDE cie=000000b8 pc=000200f0..00020100
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+  DW_CFA_advance_loc: 0 to 000200f0
+
+00000100 0000001c 0000004c FDE cie=000000b8 pc=00020100..00020120
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+  DW_CFA_advance_loc: 0 to 00020100
+
+00000120 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
+
+
+00000140 0000001c 00000024 FDE cie=00000120 pc=00020120..00020130
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+  DW_CFA_advance_loc: 0 to 00020120
+
+00000160 0000001c 00000044 FDE cie=00000120 pc=00020130..00020150
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+  DW_CFA_advance_loc: 0 to 00020130
+
+00000180 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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+
+000001a0 0000001c 00000024 FDE cie=00000180 pc=00020150..00020160
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+  DW_CFA_advance_loc: 0 to 00020150
+
+# FDE for .discard removed
+# zPR2 removed
+000001c0 0000001c 00000044 FDE cie=00000180 pc=00020160..00020190
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+  DW_CFA_advance_loc: 0 to 00020160
+
+000001e0 0000001c 00000064 FDE cie=00000180 pc=00020190..000201d0
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+  DW_CFA_advance_loc: 0 to 00020190
+
+00000200 00000014 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 1
+  Data alignment factor: 4
+  Return address column: 31
+  Augmentation data:     10
+
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000218 0000001c 0000001c FDE cie=00000200 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
+00000238 0000001c 0000003c FDE cie=00000200 pc=000201e0..000201f0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000258 0000001c 0000005c FDE cie=00000200 pc=000201f0..00020210
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000278 0000001c 0000007c FDE cie=00000200 pc=00020210..00020240
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000298 0000001c 0000009c FDE cie=00000200 pc=00020240..00020280
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000002b8 0000001c 000000bc FDE cie=00000200 pc=00020280..000202d0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+000002d8 00000024 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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000300 0000001c 0000002c FDE cie=000002d8 pc=000202d0..000202e0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+  DW_CFA_advance_loc: 0 to 000202d0
+
+00000320 0000001c 0000004c FDE cie=000002d8 pc=000202e0..00020300
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+  DW_CFA_advance_loc: 0 to 000202e0
+
+00000340 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
+
+
+00000360 0000001c 00000024 FDE cie=00000340 pc=00020300..00020310
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+  DW_CFA_advance_loc: 0 to 00020300
+
+00000380 0000001c 00000044 FDE cie=00000340 pc=00020310..00020330
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+  DW_CFA_advance_loc: 0 to 00020310
+
+000003a0 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_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+
+000003c0 0000001c 00000024 FDE cie=000003a0 pc=00020330..00020340
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+  DW_CFA_advance_loc: 0 to 00020330
+
+000003e0 0000001c 00000044 FDE cie=000003a0 pc=00020340..00020370
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+  DW_CFA_advance_loc: 0 to 00020340
+
+00000400 0000001c 00000064 FDE cie=000003a0 pc=00020370..000203b0
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+  DW_CFA_advance_loc: 0 to 00020370
+
+00000420 00000014 00000000 CIE
+  Version:               1
+  Augmentation:          "zR"
+  Code alignment factor: 1
+  Data alignment factor: 4
+  Return address column: 31
+  Augmentation data:     10
+
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_advance_loc: 0 to 00000000
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000438 0000001c 0000001c FDE cie=00000420 pc=000203b0..000203c0
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
diff -u /dev/null ld/testsuite/ld-mips-elf/eh-frame1.ld
--- /dev/null	Fri Apr 23 00:21:55 2004
+++ ld/testsuite/ld-mips-elf/eh-frame1.ld	Sat Nov 13 09:43:09 2004
@@ -0,0 +1,18 @@
+SECTIONS
+{
+  . = 0x10000;
+  .dynamic : { *(.dynamic) }
+  .hash : { *(.hash) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+  .rel.dyn : { *(.rel.dyn) }
+
+  . = 0x20000;
+  .text : { *(.text) }
+
+  . = 0x30000;
+  .eh_frame : { *(.eh_frame) }
+  .got : { *(.got) }
+
+  /DISCARD/ : { *(*) }
+}
diff -u /dev/null ld/testsuite/ld-mips-elf/eh-frame1.s
--- /dev/null	Fri Apr 23 00:21:55 2004
+++ ld/testsuite/ld-mips-elf/eh-frame1.s	Sat Nov 13 09:43:09 2004
@@ -0,0 +1,148 @@
+#----------------------------------------------------------------------------
+# Macros
+#----------------------------------------------------------------------------
+
+	mask = (1 << alignment) - 1
+
+	# Output VALUE as an unaligned pointer-sized quantity.
+	.macro pbyte value
+	.if alignment == 2
+	.4byte		\value
+	.else
+	.8byte		\value
+	.endif
+	.endm
+
+
+	# Start a new CIE, and emit everything up to the augmentation data.
+	# Use LABEL to mark the start of the entry and AUG as the augmentation
+	# string.
+	.macro start_cie label,aug
+	.section	.eh_frame,"aw",@progbits
+\label:
+	.word		2f-1f		# Length
+1:
+	.word		0		# Identifier
+	.byte		1		# Version
+	.string		"\aug"		# Augmentation
+	.byte		1		# Code alignment
+	.byte		4		# Data alignment
+	.byte		31		# Return address column
+	.endm
+
+
+	# Create a dummy function of SIZE bytes in SECTION and emit the
+	# first four entries of an FDE for it (total 16 bytes).
+	.macro start_fde cie,section,size
+	.section	\section,"ax",@progbits
+3:
+	.rept		\size / 4
+	nop
+	.endr
+4:
+	.section	.eh_frame,"aw",@progbits
+	.word		2f-1f		# Length
+1:
+	.word		.-\cie		# CIE offset
+	pbyte		3b		# Initial PC
+	pbyte		4b-3b		# Size of code
+	.endm
+
+
+	# Finish a CIE or FDE entry.
+	.macro end_entry
+	.p2align	alignment,fill
+2:
+	.endm
+
+
+	# Start the augmentation data for a CIE that has a 'P' entry
+	# followed by EXTRA bytes.  AUGLEN is the length of augmentation
+	# string (including zero terminator), ENCODING is the encoding to
+	# use for the personality routine and VALUE is the value it
+	# should have.
+	.macro		persaug auglen,extra,encoding,value
+	.if (\encoding & 0xf0) == 0x50
+	.byte		(-(9 + \auglen + 3 + 2) & mask) + 2 + mask + \extra
+	.byte		\encoding
+	.fill		-(9 + \auglen + 3 + 2) & mask,1,0
+	.else
+	.byte		2 + mask + \extra
+	.byte		\encoding
+	.endif
+	pbyte		\value
+	.endm
+
+
+	.macro cie_basic label
+	start_cie	\label,""
+	end_entry
+	.endm
+
+	.macro fde_basic cie,section,size
+	start_fde	\cie,\section,\size
+	end_entry
+	.endm
+
+
+	.macro cie_zP label,encoding,value
+	start_cie	 \label,"zP"
+	persaug		3,0,\encoding,\value
+	end_entry
+	.endm
+
+	.macro fde_zP cie,section,size
+	start_fde	 \cie,\section,\size
+	.byte		 0		# Augmentation length
+	end_entry
+	.endm
+
+
+	.macro cie_zPR label,encoding,value
+	start_cie	 \label,"zPR"
+	persaug		4,1,\encoding,\value
+	.byte		0		# FDE enconding
+	end_entry
+	.endm
+
+	.macro fde_zPR cie,section,size
+	start_fde	\cie,\section,\size
+	.byte		0		# Augmentation length
+	end_entry
+	.endm
+
+#----------------------------------------------------------------------------
+# Test code
+#----------------------------------------------------------------------------
+
+	cie_basic	basic1
+	fde_basic	basic1,.text,0x10
+	fde_basic	basic1,.text,0x20
+
+	cie_basic	basic2
+	fde_basic	basic2,.text,0x30
+
+	cie_basic	basic3
+	fde_basic	basic3,.text,0x40
+
+	cie_basic	basic4
+	fde_basic	basic4,.text,0x50
+
+	cie_zP		zP_unalign1,0x00,foo
+	fde_zP		zP_unalign1,.text,0x10
+	fde_zP		zP_unalign1,.text,0x20
+
+	cie_zP		zP_align1,0x50,foo
+	fde_zP		zP_align1,.text,0x10
+	fde_zP		zP_align1,.text,0x20
+
+	cie_zPR		zPR1,0x00,foo
+	fde_zPR		zPR1,.text,0x10
+	fde_zPR		zPR1,.discard,0x20
+
+	cie_zPR		zPR2,0x00,foo
+	fde_zPR		zPR2,.text,0x30
+	fde_zPR		zPR2,.text,0x40
+
+	cie_basic	basic5
+	fde_basic	basic5,.text,0x10

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

* Re: RFA: Extensions to the .eh_frame linker code
  2004-11-15 20:33       ` Richard Sandiford
@ 2004-11-15 22:41         ` Alan Modra
  0 siblings, 0 replies; 6+ messages in thread
From: Alan Modra @ 2004-11-15 22:41 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: binutils

On Mon, Nov 15, 2004 at 08:32:31PM +0000, Richard Sandiford wrote:
> Anyway, patch tested against mips64-linux-gnu.  OK to install?

Yes, thanks.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

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

end of thread, other threads:[~2004-11-15 22:41 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-11-13 12:12 RFA: Extensions to the .eh_frame linker code Richard Sandiford
2004-11-15  2:07 ` Alan Modra
2004-11-15  9:07   ` Richard Sandiford
2004-11-15 12:40     ` Alan Modra
2004-11-15 20:33       ` Richard Sandiford
2004-11-15 22:41         ` Alan Modra

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