aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2004-11-16 10:16:30 +0000
committerRichard Sandiford <rdsandiford@googlemail.com>2004-11-16 10:16:30 +0000
commit353057a53cee99996317c9038f7de664a7d38b4c (patch)
treec4574abd52e50daa44e8f5460740c47f0ac48cbf
parentb32d3aa2a05c297fcc8fa04c6b4c1345c6c291ad (diff)
downloadfsf-binutils-gdb-353057a53cee99996317c9038f7de664a7d38b4c.zip
fsf-binutils-gdb-353057a53cee99996317c9038f7de664a7d38b4c.tar.gz
fsf-binutils-gdb-353057a53cee99996317c9038f7de664a7d38b4c.tar.bz2
* 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.
-rw-r--r--bfd/ChangeLog17
-rw-r--r--bfd/elf-bfd.h3
-rw-r--r--bfd/elf-eh-frame.c219
-rw-r--r--ld/testsuite/ChangeLog6
-rw-r--r--ld/testsuite/ld-mips-elf/eh-frame1-n32.d263
-rw-r--r--ld/testsuite/ld-mips-elf/eh-frame1-n64.d425
-rw-r--r--ld/testsuite/ld-mips-elf/eh-frame1.ld18
-rw-r--r--ld/testsuite/ld-mips-elf/eh-frame1.s148
-rw-r--r--ld/testsuite/ld-mips-elf/mips-elf.exp4
9 files changed, 1048 insertions, 55 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index cfebb8c..1295b03 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,20 @@
+2004-11-16 Richard Sandiford <rsandifo@redhat.com>
+
+ * 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.
+
2004-11-15 Mark Mitchell <mark@codesourcery.com>
* elf32-arm.c (elf32_arm_relocate_section): Use
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 541ad25..5367ad6 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -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;
};
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index 7468eef..0c0b32c 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -200,6 +200,60 @@ int cie_compare (struct cie *c1, struct cie *c2)
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 @@ _bfd_elf_discard_section_eh_frame
== 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 @@ _bfd_elf_discard_section_eh_frame
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 @@ _bfd_elf_discard_section_eh_frame
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 @@ _bfd_elf_discard_section_eh_frame
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 *output_bfd ATTRIBUTE_UNUSED,
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 *output_bfd ATTRIBUTE_UNUSED,
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 *abfd,
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 *abfd,
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 *abfd,
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 *abfd,
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 *abfd,
}
}
}
- 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 *abfd,
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 *abfd,
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 *abfd,
&& ((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 *abfd,
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);
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 2851668..094fe60 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2004-11-16 Richard Sandiford <rsandifo@redhat.com>
+
+ * 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.
+
2004-11-10 Alan Modra <amodra@bigpond.net.au>
* ld-d10v/reloc-003.d: Update for changed error message.
diff --git a/ld/testsuite/ld-mips-elf/eh-frame1-n32.d b/ld/testsuite/ld-mips-elf/eh-frame1-n32.d
new file mode 100644
index 0000000..4e33219
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/eh-frame1-n32.d
@@ -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' .*:
+ *Offset .*
+00000000 00000000 R_MIPS_NONE *
+# 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 --git a/ld/testsuite/ld-mips-elf/eh-frame1-n64.d b/ld/testsuite/ld-mips-elf/eh-frame1-n64.d
new file mode 100644
index 0000000..2b175e0
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/eh-frame1-n64.d
@@ -0,0 +1,425 @@
+#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' .*:
+ *Offset .*
+000000000000 000000000000 R_MIPS_NONE *
+ *Type2: R_MIPS_NONE *
+ *Type3: R_MIPS_NONE *
+# 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 --git a/ld/testsuite/ld-mips-elf/eh-frame1.ld b/ld/testsuite/ld-mips-elf/eh-frame1.ld
new file mode 100644
index 0000000..910a84e
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/eh-frame1.ld
@@ -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 --git a/ld/testsuite/ld-mips-elf/eh-frame1.s b/ld/testsuite/ld-mips-elf/eh-frame1.s
new file mode 100644
index 0000000..c8413db
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/eh-frame1.s
@@ -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.
+ .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
diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp
index f0c2b84..c3417bc 100644
--- a/ld/testsuite/ld-mips-elf/mips-elf.exp
+++ b/ld/testsuite/ld-mips-elf/mips-elf.exp
@@ -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"
+}