* elf-hppa.h (elf_hppa_final_link): Use gp val of zero when none
[deliverable/binutils-gdb.git] / bfd / elf64-ppc.c
index 04fcdc916697eff4b6933df14affc769901b3cbf..402e859756fe974acb90d7d8dbebd7195bd95a18 100644 (file)
@@ -2117,8 +2117,13 @@ ppc64_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
     ppc_howto_init ();
 
   type = ELF64_R_TYPE (dst->r_info);
-  BFD_ASSERT (type < (sizeof (ppc64_elf_howto_table)
-                     / sizeof (ppc64_elf_howto_table[0])));
+  if (type >= (sizeof (ppc64_elf_howto_table)
+              / sizeof (ppc64_elf_howto_table[0])))
+    {
+      (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
+                            abfd, (int) type);
+      type = R_PPC64_NONE;
+    }
   cache_ptr->howto = ppc64_elf_howto_table[type];
 }
 
@@ -2508,62 +2513,17 @@ ppc64_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 
 /* Add extra PPC sections.  */
 
-static struct bfd_elf_special_section const
-  ppc64_special_sections_p[]=
+static const struct bfd_elf_special_section ppc64_elf_special_sections[]=
 {
   { ".plt",     4,  0, SHT_NOBITS,   0 },
-  { NULL,        0, 0, 0,            0 }
-};
-
-static struct bfd_elf_special_section const
-  ppc64_special_sections_s[]=
-{
-  { ".sdata",   6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
   { ".sbss",    5, -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
-  { NULL,        0, 0, 0,            0 }
-};
-
-static struct bfd_elf_special_section const
-  ppc64_special_sections_t[]=
-{
+  { ".sdata",   6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
   { ".toc",     4,  0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
   { ".toc1",    5,  0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
   { ".tocbss",  7,  0, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
   { NULL,       0,  0, 0,            0 }
 };
 
-static struct bfd_elf_special_section const *
-  ppc64_elf_special_sections[27]=
-{
-  NULL,                                /* 'a' */
-  NULL,                                /* 'b' */
-  NULL,                                /* 'c' */
-  NULL,                                /* 'd' */
-  NULL,                                /* 'e' */
-  NULL,                                /* 'f' */
-  NULL,                                /* 'g' */
-  NULL,                                /* 'h' */
-  NULL,                                /* 'i' */
-  NULL,                                /* 'j' */
-  NULL,                                /* 'k' */
-  NULL,                                /* 'l' */
-  NULL,                                /* 'm' */
-  NULL,                                /* 'n' */
-  NULL,                                /* 'o' */
-  ppc64_special_sections_p,    /* 'p' */
-  NULL,                                /* 'q' */
-  NULL,                                /* 'r' */
-  ppc64_special_sections_s,    /* 's' */
-  ppc64_special_sections_t,    /* 't' */
-  NULL,                                /* 'u' */
-  NULL,                                /* 'v' */
-  NULL,                                /* 'w' */
-  NULL,                                /* 'x' */
-  NULL,                                /* 'y' */
-  NULL,                                /* 'z' */
-  NULL                         /* other */
-};
-
 struct _ppc64_elf_section_data
 {
   struct bfd_elf_section_data elf;
@@ -3235,7 +3195,7 @@ struct ppc_branch_hash_entry {
   /* Base hash table entry structure.  */
   struct bfd_hash_entry root;
 
-  /* Offset within .branch_lt.  */
+  /* Offset within branch lookup table.  */
   unsigned int offset;
 
   /* Generation marker.  */
@@ -3581,26 +3541,26 @@ ppc_stub_name (const asection *input_section,
     {
       len = 8 + 1 + strlen (h->elf.root.root.string) + 1 + 8 + 1;
       stub_name = bfd_malloc (len);
-      if (stub_name != NULL)
-       {
-         sprintf (stub_name, "%08x.%s+%x",
-                  input_section->id & 0xffffffff,
-                  h->elf.root.root.string,
-                  (int) rel->r_addend & 0xffffffff);
-       }
+      if (stub_name == NULL)
+       return stub_name;
+
+      sprintf (stub_name, "%08x.%s+%x",
+              input_section->id & 0xffffffff,
+              h->elf.root.root.string,
+              (int) rel->r_addend & 0xffffffff);
     }
   else
     {
       len = 8 + 1 + 8 + 1 + 8 + 1 + 8 + 1;
       stub_name = bfd_malloc (len);
-      if (stub_name != NULL)
-       {
-         sprintf (stub_name, "%08x.%x:%x+%x",
-                  input_section->id & 0xffffffff,
-                  sym_sec->id & 0xffffffff,
-                  (int) ELF64_R_SYM (rel->r_info) & 0xffffffff,
-                  (int) rel->r_addend & 0xffffffff);
-       }
+      if (stub_name == NULL)
+       return stub_name;
+
+      sprintf (stub_name, "%08x.%x:%x+%x",
+              input_section->id & 0xffffffff,
+              sym_sec->id & 0xffffffff,
+              (int) ELF64_R_SYM (rel->r_info) & 0xffffffff,
+              (int) rel->r_addend & 0xffffffff);
     }
   if (stub_name[len - 2] == '+' && stub_name[len - 1] == '0')
     stub_name[len - 2] = 0;
@@ -3733,26 +3693,50 @@ create_linkage_sections (bfd *dynobj, struct bfd_link_info *info)
       || ! bfd_set_section_alignment (dynobj, htab->glink, 2))
     return FALSE;
 
-  /* Create .branch_lt for plt_branch stubs.  */
-  flags = (SEC_ALLOC | SEC_LOAD
-          | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-  htab->brlt = bfd_make_section_anyway_with_flags (dynobj, ".branch_lt",
-                                                  flags);
+  /* Create branch lookup table for plt_branch stubs.  */
+  if (info->shared)
+    {
+      flags = (SEC_ALLOC | SEC_LOAD
+              | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+      htab->brlt
+       = bfd_make_section_anyway_with_flags (dynobj, ".data.rel.ro.brlt",
+                                             flags);
+    }
+  else
+    {
+      flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+              | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+      htab->brlt
+       = bfd_make_section_anyway_with_flags (dynobj, ".rodata.brlt", flags);
+    }
+
   if (htab->brlt == NULL
       || ! bfd_set_section_alignment (dynobj, htab->brlt, 3))
     return FALSE;
 
-  if (info->shared || info->emitrelocations)
+  if (info->shared)
     {
       flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
               | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-      htab->relbrlt = bfd_make_section_anyway_with_flags (dynobj,
-                                                         ".rela.branch_lt",
-                                                         flags);
-      if (!htab->relbrlt
-         || ! bfd_set_section_alignment (dynobj, htab->relbrlt, 3))
-       return FALSE;
+      htab->relbrlt
+       = bfd_make_section_anyway_with_flags (dynobj, ".rela.data.rel.ro.brlt",
+                                             flags);
     }
+  else if (info->emitrelocations)
+    {
+      flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+              | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+      htab->relbrlt
+       = bfd_make_section_anyway_with_flags (dynobj, ".rela.rodata.brlt",
+                                             flags);
+    }
+  else
+    return TRUE;
+
+  if (!htab->relbrlt
+      || ! bfd_set_section_alignment (dynobj, htab->relbrlt, 3))
+    return FALSE;
+
   return TRUE;
 }
 
@@ -3779,13 +3763,13 @@ create_got_section (bfd *abfd, struct bfd_link_info *info)
   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
           | SEC_LINKER_CREATED);
 
-  got = bfd_make_section_with_flags (abfd, ".got", flags);
+  got = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
   if (!got
       || !bfd_set_section_alignment (abfd, got, 3))
     return FALSE;
 
-  relgot = bfd_make_section_with_flags (abfd, ".rela.got",
-                                       flags | SEC_READONLY);
+  relgot = bfd_make_section_anyway_with_flags (abfd, ".rela.got",
+                                              flags | SEC_READONLY);
   if (!relgot
       || ! bfd_set_section_alignment (abfd, relgot, 3))
     return FALSE;
@@ -4365,7 +4349,12 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       if (r_symndx < symtab_hdr->sh_info)
        h = NULL;
       else
-       h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+       {
+         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+         while (h->root.type == bfd_link_hash_indirect
+                || h->root.type == bfd_link_hash_warning)
+           h = (struct elf_link_hash_entry *) h->root.u.i.link;
+       }
 
       r_type = ELF64_R_TYPE (rel->r_info);
       switch (r_type)
@@ -5064,7 +5053,7 @@ ppc64_elf_gc_mark_hook (asection *sec,
          if (!rsec->gc_mark)
            _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook);
 
-         rsec = opd_sym_section[sym->st_value / 8];
+         rsec = opd_sym_section[(sym->st_value + rel->r_addend) / 8];
        }
     }
 
@@ -6155,6 +6144,7 @@ dec_dynrel_count (bfd_vma r_info,
 
 bfd_boolean
 ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
+                   bfd_boolean no_opd_opt,
                    bfd_boolean non_overlapping)
 {
   bfd *ibfd;
@@ -6175,7 +6165,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
       bfd_size_type cnt_16b = 0;
 
       sec = bfd_get_section_by_name (ibfd, ".opd");
-      if (sec == NULL)
+      if (sec == NULL || sec->size == 0)
        continue;
 
       amt = sec->size * sizeof (long) / 8;
@@ -6184,11 +6174,16 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
        {
          /* check_relocs hasn't been called.  Must be a ld -r link
             or --just-symbols object.   */
-         opd_adjust = bfd_zalloc (obfd, amt);
+         opd_adjust = bfd_alloc (obfd, amt);
+         if (opd_adjust == NULL)
+           return FALSE;
          ppc64_elf_section_data (sec)->opd.adjust = opd_adjust;
        }
       memset (opd_adjust, 0, amt);
 
+      if (no_opd_opt)
+       continue;
+
       if (sec->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
        continue;
 
@@ -6358,18 +6353,16 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
 
          elf_section_data (sec)->relocs = relstart;
 
-         wptr = sec->contents;
-         rptr = sec->contents;
          new_contents = sec->contents;
-
          if (add_aux_fields)
            {
              new_contents = bfd_malloc (sec->size + cnt_16b * 8);
              if (new_contents == NULL)
                return FALSE;
              need_pad = FALSE;
-             wptr = new_contents;
            }
+         wptr = new_contents;
+         rptr = sec->contents;
 
          write_rel = relstart;
          skip = FALSE;
@@ -7727,26 +7720,15 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        continue;
       else if (s == htab->got
               || s == htab->plt
-              || s == htab->glink)
+              || s == htab->glink
+              || s == htab->dynbss)
        {
          /* Strip this section if we don't need it; see the
             comment below.  */
        }
       else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
        {
-         if (s->size == 0)
-           {
-             /* If we don't need this section, strip it from the
-                output file.  This is mostly to handle .rela.bss and
-                .rela.plt.  We must create both sections in
-                create_dynamic_sections, because they must be created
-                before the linker maps input sections to output
-                sections.  The linker does that before
-                adjust_dynamic_symbol is called, and it is that
-                function which decides whether anything needs to go
-                into these sections.  */
-           }
-         else
+         if (s->size != 0)
            {
              if (s != htab->relplt)
                relocs = TRUE;
@@ -7764,12 +7746,20 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
       if (s->size == 0)
        {
+         /* If we don't need this section, strip it from the
+            output file.  This is mostly to handle .rela.bss and
+            .rela.plt.  We must create both sections in
+            create_dynamic_sections, because they must be created
+            before the linker maps input sections to output
+            sections.  The linker does that before
+            adjust_dynamic_symbol is called, and it is that
+            function which decides whether anything needs to go
+            into these sections.  */
          s->flags |= SEC_EXCLUDE;
          continue;
        }
 
-      /* .plt is in the bss section.  We don't initialise it.  */
-      if (s == htab->plt)
+      if ((s->flags & SEC_HAS_CONTENTS) == 0)
        continue;
 
       /* Allocate memory for the section contents.  We use bfd_zalloc
@@ -9151,7 +9141,7 @@ ppc64_elf_size_stubs (bfd *output_bfd,
       (*htab->layout_sections_again) ();
     }
 
-  /* It would be nice to strip .branch_lt from the output if the
+  /* It would be nice to strip htab->brlt from the output if the
      section is empty, but it's too late.  If we strip sections here,
      the dynamic symbol table is corrupted since the section symbol
      for the stripped section isn't written.  */
This page took 0.031069 seconds and 4 git commands to generate.