summaryrefslogtreecommitdiff
path: root/bfd/elf32-ppc.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2011-08-05 02:24:08 +0000
committerAlan Modra <amodra@bigpond.net.au>2011-08-05 02:24:08 +0000
commit87cc8c51d2f419a34e7728e02b1803e2a3beba52 (patch)
tree573488d35475d0dc809f5d4b06c5a2d9af7323e5 /bfd/elf32-ppc.c
parentb51e3070444b1a45caf98d22778c3b26fbc46a90 (diff)
downloadbinutils-redhat-87cc8c51d2f419a34e7728e02b1803e2a3beba52.tar.gz
* elf32-ppc.c: Include dwarf2.h.
(struct ppc_elf_link_hash_table): Add glink_eh_frame. (ppc_elf_create_glink): Create .eh_frame section. (glink_eh_frame_cie): New array. (ppc_elf_size_dynamic_sections): Size glink_eh_frame. (ppc_elf_finish_dynamic_sections): Write glink_eh_frame.
Diffstat (limited to 'bfd/elf32-ppc.c')
-rw-r--r--bfd/elf32-ppc.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 4dd193a56c..7e66134e36 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -36,6 +36,7 @@
#include "elf/ppc.h"
#include "elf32-ppc.h"
#include "elf-vxworks.h"
+#include "dwarf2.h"
/* RELA relocations are used here. */
@@ -2679,6 +2680,7 @@ struct ppc_elf_link_hash_table
asection *relsbss;
elf_linker_section_t sdata[2];
asection *sbss;
+ asection *glink_eh_frame;
/* The (unloaded but important) .rela.plt.unloaded on VxWorks. */
asection *srelplt2;
@@ -2869,6 +2871,17 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info)
|| !bfd_set_section_alignment (abfd, s, 4))
return FALSE;
+ if (!info->no_ld_generated_unwind_info)
+ {
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+ s = bfd_make_section_anyway_with_flags (abfd, ".eh_frame", flags);
+ htab->glink_eh_frame = s;
+ if (s == NULL
+ || !bfd_set_section_alignment (abfd, s, 2))
+ return FALSE;
+ }
+
flags = SEC_ALLOC | SEC_LINKER_CREATED;
s = bfd_make_section_anyway_with_flags (abfd, ".iplt", flags);
htab->iplt = s;
@@ -5508,6 +5521,20 @@ maybe_set_textrel (struct elf_link_hash_entry *h, void *info)
return TRUE;
}
+static const unsigned char glink_eh_frame_cie[] =
+{
+ 0, 0, 0, 16, /* length. */
+ 0, 0, 0, 0, /* id. */
+ 1, /* CIE version. */
+ 'z', 'R', 0, /* Augmentation string. */
+ 4, /* Code alignment. */
+ 0x7c, /* Data alignment. */
+ 65, /* RA reg. */
+ 1, /* Augmentation size. */
+ DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding. */
+ DW_CFA_def_cfa, 1, 0 /* def_cfa: r1 offset 0. */
+};
+
/* Set the sizes of the dynamic sections. */
static bfd_boolean
@@ -5768,6 +5795,21 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
}
}
+ if (htab->glink != NULL
+ && htab->glink->size != 0
+ && htab->glink_eh_frame != NULL
+ && !bfd_is_abs_section (htab->glink_eh_frame->output_section))
+ {
+ s = htab->glink_eh_frame;
+ s->size = sizeof (glink_eh_frame_cie) + 20;
+ if (info->shared)
+ {
+ s->size += 4;
+ if (htab->glink->size - GLINK_PLTRESOLVE + 8 >= 256)
+ s->size += 4;
+ }
+ }
+
/* We've now determined the sizes of the various dynamic sections.
Allocate memory for them. */
relocs = FALSE;
@@ -5791,6 +5833,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
}
else if (s == htab->iplt
|| s == htab->glink
+ || s == htab->glink_eh_frame
|| s == htab->sgotplt
|| s == htab->sbss
|| s == htab->dynbss
@@ -8915,6 +8958,78 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
}
}
+ if (htab->glink_eh_frame != NULL
+ && htab->glink_eh_frame->contents != NULL)
+ {
+ unsigned char *p = htab->glink_eh_frame->contents;
+ bfd_vma val;
+
+ memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
+ /* CIE length (rewrite in case little-endian). */
+ bfd_put_32 (htab->elf.dynobj, sizeof (glink_eh_frame_cie) - 4, p);
+ p += sizeof (glink_eh_frame_cie);
+ /* FDE length. */
+ val = htab->glink_eh_frame->size - 4 - sizeof (glink_eh_frame_cie);
+ bfd_put_32 (htab->elf.dynobj, val, p);
+ p += 4;
+ /* CIE pointer. */
+ val = p - htab->glink_eh_frame->contents;
+ bfd_put_32 (htab->elf.dynobj, val, p);
+ p += 4;
+ /* Offset to .glink. */
+ val = (htab->glink->output_section->vma
+ + htab->glink->output_offset);
+ val -= (htab->glink_eh_frame->output_section->vma
+ + htab->glink_eh_frame->output_offset);
+ val -= p - htab->glink_eh_frame->contents;
+ bfd_put_32 (htab->elf.dynobj, val, p);
+ p += 4;
+ /* .glink size. */
+ bfd_put_32 (htab->elf.dynobj, htab->glink->size, p);
+ p += 4;
+ /* Augmentation. */
+ p += 1;
+
+ if (info->shared
+ && htab->elf.dynamic_sections_created)
+ {
+ bfd_vma adv = (htab->glink->size - GLINK_PLTRESOLVE + 8) >> 2;
+ if (adv < 64)
+ *p++ = DW_CFA_advance_loc + adv;
+ else if (adv < 256)
+ {
+ *p++ = DW_CFA_advance_loc1;
+ *p++ = adv;
+ }
+ else if (adv < 65536)
+ {
+ *p++ = DW_CFA_advance_loc2;
+ bfd_put_16 (htab->elf.dynobj, adv, p);
+ p += 2;
+ }
+ else
+ {
+ *p++ = DW_CFA_advance_loc4;
+ bfd_put_32 (htab->elf.dynobj, adv, p);
+ p += 4;
+ }
+ *p++ = DW_CFA_register;
+ *p++ = 65;
+ p++;
+ *p++ = DW_CFA_advance_loc + 4;
+ *p++ = DW_CFA_restore_extended;
+ *p++ = 65;
+ }
+ BFD_ASSERT ((bfd_vma) ((p + 3 - htab->glink_eh_frame->contents) & -4)
+ == htab->glink_eh_frame->size);
+
+ if (htab->glink_eh_frame->sec_info_type == ELF_INFO_TYPE_EH_FRAME
+ && !_bfd_elf_write_section_eh_frame (output_bfd, info,
+ htab->glink_eh_frame,
+ htab->glink_eh_frame->contents))
+ return FALSE;
+ }
+
return ret;
}