* elf32-ppc.c: Include dwarf2.h.
authorAlan Modra <amodra@gmail.com>
Fri, 5 Aug 2011 02:24:08 +0000 (02:24 +0000)
committerAlan Modra <amodra@gmail.com>
Fri, 5 Aug 2011 02:24:08 +0000 (02:24 +0000)
(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.

bfd/ChangeLog
bfd/elf32-ppc.c

index 85ef26018c5311bcc137b69980b7f0d0214afbf9..f6ccd5452d65b6b2846acb970d3063541a4b8996 100644 (file)
@@ -1,3 +1,12 @@
+2011-08-05  Alan Modra  <amodra@gmail.com>
+
+       * 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.
+
 2011-08-04  Tristan Gingold  <gingold@adacore.com>
 
        * vms-alpha.c (_bfd_vms_write_eeom): Round vms_linkage_index.
 
 2011-07-26  Alan Modra  <amodra@gmail.com>
 
-       * 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.
-       * elf64-ppc.c: Include dwarg2.h.
+       * elf64-ppc.c: Include dwarf2.h.
        (struct ppc_link_hash_table): Add glink_eh_frame.
        (create_linkage_sections): Create .eh_frame section.
        (ppc64_elf_size_dynamic_sections): Arrange to drop unneeded
index 4dd193a56cd7685c0440bb126f1b64ce896e49a7..7e66134e366ac9c10c9650df499c86e8dc3c13b5 100644 (file)
@@ -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;
 }
 \f