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


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

Re: RFA: Extensions to the .eh_frame linker code


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


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