bfd/
[deliverable/binutils-gdb.git] / bfd / elf32-ppc.c
index a80cfa440a21430adc1d6afafd620eaff9c2542c..6f572da2c39328cd87ef54f3b17e91693e6fe021 100644 (file)
@@ -18,7 +18,7 @@
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the
    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Boston, MA 02110-1301, USA.  */
 
 /* This file is based on a preliminary PowerPC ELF ABI.  The
    information may not match the final PowerPC ELF ABI.  It includes
@@ -1532,8 +1532,6 @@ typedef struct elf_linker_section_pointers
   bfd_vma addend;
   /* which linker section this is */
   elf_linker_section_t *lsect;
-  /* whether address was written yet */
-  bfd_boolean written_address_p;
 } elf_linker_section_pointers_t;
 
 struct ppc_elf_obj_tdata
@@ -2417,27 +2415,12 @@ ppc_elf_create_linker_section (bfd *abfd,
   if (!htab->elf.dynobj)
     htab->elf.dynobj = abfd;
 
-  /* See if the section already exists.  */
-  s = bfd_get_section_by_name (htab->elf.dynobj, lsect->name);
-  if (s == NULL || (s->flags & flags) != flags)
-    {
-      s = bfd_make_section_anyway (htab->elf.dynobj, lsect->name);
-      if (s == NULL
-         || !bfd_set_section_flags (htab->elf.dynobj, s, flags))
-       return FALSE;
-    }
-  lsect->section = s;
-
-  if (bfd_get_section_alignment (htab->elf.dynobj, s) < 2
-      && !bfd_set_section_alignment (htab->elf.dynobj, s, 2))
+  s = bfd_make_section_anyway (htab->elf.dynobj, lsect->name);
+  if (s == NULL
+      || !bfd_set_section_flags (htab->elf.dynobj, s, flags)
+      || !bfd_set_section_alignment (htab->elf.dynobj, s, 2))
     return FALSE;
-
-  s->size = align_power (s->size, 2);
-
-#ifdef DEBUG
-  fprintf (stderr, "Creating section %s, current size = %ld\n",
-          lsect->name, (long) s->size);
-#endif
+  lsect->section = s;
 
   return TRUE;
 }
@@ -2461,7 +2444,6 @@ elf_find_pointer_linker_section
 
 static bfd_boolean
 elf_create_pointer_linker_section (bfd *abfd,
-                                  struct bfd_link_info *info,
                                   elf_linker_section_t *lsect,
                                   struct elf_link_hash_entry *h,
                                   const Elf_Internal_Rela *rel)
@@ -2486,12 +2468,6 @@ elf_create_pointer_linker_section (bfd *abfd,
        return TRUE;
 
       ptr_linker_section_ptr = &eh->linker_section_pointer;
-      /* Make sure this symbol is output as a dynamic symbol.  */
-      if (h->dynindx == -1)
-       {
-         if (! bfd_elf_link_record_dynamic_symbol (info, h))
-           return FALSE;
-       }
     }
   else
     {
@@ -2534,7 +2510,6 @@ elf_create_pointer_linker_section (bfd *abfd,
   linker_section_ptr->next = *ptr_linker_section_ptr;
   linker_section_ptr->addend = rel->r_addend;
   linker_section_ptr->lsect = lsect;
-  linker_section_ptr->written_address_p = FALSE;
   *ptr_linker_section_ptr = linker_section_ptr;
 
   linker_section_ptr->offset = lsect->section->size;
@@ -2606,6 +2581,15 @@ ppc_elf_check_relocs (bfd *abfd,
   if (info->relocatable)
     return TRUE;
 
+  /* Don't do anything special with non-loaded, non-alloced sections.
+     In particular, any relocs in such sections should not affect GOT
+     and PLT reference counting (ie. we don't allow them to create GOT
+     or PLT entries), there's no possibility or desire to optimize TLS
+     relocs, and there's not much point in propagating relocs to shared
+     libs that the dynamic linker won't relocate.  */
+  if ((sec->flags & SEC_ALLOC) == 0)
+    return TRUE;
+
 #ifdef DEBUG
   _bfd_error_handler ("ppc_elf_check_relocs called for section %A in %B",
                      sec, abfd);
@@ -2719,8 +2703,8 @@ ppc_elf_check_relocs (bfd *abfd,
              && !ppc_elf_create_linker_section (abfd, info, 0,
                                                 &htab->sdata[0]))
            return FALSE;
-         if (!elf_create_pointer_linker_section (abfd, info,
-                                                 &htab->sdata[0], h, rel))
+         if (!elf_create_pointer_linker_section (abfd, &htab->sdata[0],
+                                                 h, rel))
            return FALSE;
          break;
 
@@ -2735,8 +2719,8 @@ ppc_elf_check_relocs (bfd *abfd,
              && !ppc_elf_create_linker_section (abfd, info, SEC_READONLY,
                                                 &htab->sdata[1]))
            return FALSE;
-         if (!elf_create_pointer_linker_section (abfd, info,
-                                                 &htab->sdata[1], h, rel))
+         if (!elf_create_pointer_linker_section (abfd, &htab->sdata[1],
+                                                 h, rel))
            return FALSE;
          break;
 
@@ -2927,7 +2911,6 @@ ppc_elf_check_relocs (bfd *abfd,
                           || !h->def_regular))))
              || (ELIMINATE_COPY_RELOCS
                  && !info->shared
-                 && (sec->flags & SEC_ALLOC) != 0
                  && h != NULL
                  && (h->root.type == bfd_link_hash_defweak
                      || !h->def_regular)))
@@ -2966,9 +2949,8 @@ ppc_elf_check_relocs (bfd *abfd,
 
                      sreloc = bfd_make_section (htab->elf.dynobj, name);
                      flags = (SEC_HAS_CONTENTS | SEC_READONLY
-                              | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-                     if ((sec->flags & SEC_ALLOC) != 0)
-                       flags |= SEC_ALLOC | SEC_LOAD;
+                              | SEC_IN_MEMORY | SEC_LINKER_CREATED
+                              | SEC_ALLOC | SEC_LOAD);
                      if (sreloc == NULL
                          || ! bfd_set_section_flags (htab->elf.dynobj,
                                                      sreloc, flags)
@@ -3172,6 +3154,9 @@ ppc_elf_gc_sweep_hook (bfd *abfd,
   bfd_signed_vma *local_got_refcounts;
   const Elf_Internal_Rela *rel, *relend;
 
+  if ((sec->flags & SEC_ALLOC) == 0)
+    return TRUE;
+
   elf_section_data (sec)->local_dynrel = NULL;
 
   htab = ppc_elf_hash_table (info);
@@ -4099,7 +4084,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
       if (s->size == 0)
        {
-         _bfd_strip_section_from_output (info, s);
+         s->flags |= SEC_EXCLUDE;
          continue;
        }
 
@@ -4210,8 +4195,11 @@ ppc_elf_relax_section (bfd *abfd,
 
   *again = FALSE;
 
-  /* Nothing to do if there are no relocations.  */
-  if ((isec->flags & SEC_RELOC) == 0 || isec->reloc_count == 0)
+  /* Nothing to do if there are no relocations, and no need to do
+     anything with non-alloc sections.  */
+  if ((isec->flags & SEC_ALLOC) == 0
+      || (isec->flags & SEC_RELOC) == 0
+      || isec->reloc_count == 0)
     return TRUE;
 
   trampoff = (isec->size + 3) & (bfd_vma) -4;
@@ -4570,22 +4558,26 @@ ppc_elf_relax_section (bfd *abfd,
   return FALSE;
 }
 \f
-/* Set _SDA_BASE_ and _SDA2_BASE.  */
+/* Set _SDA_BASE_, _SDA2_BASE, and sbss start and end syms.  They are
+   set here rather than via PROVIDE in the default linker script,
+   because using PROVIDE inside an output section statement results in
+   unnecessary output sections.  Using PROVIDE outside an output section
+   statement runs the risk of section alignment affecting where the
+   section starts.  */
 
 bfd_boolean
 ppc_elf_set_sdata_syms (bfd *obfd, struct bfd_link_info *info)
 {
   struct ppc_elf_link_hash_table *htab;
   unsigned i;
+  asection *s;
+  bfd_vma val;
 
   htab = ppc_elf_hash_table (info);
 
   for (i = 0; i < 2; i++)
     {
       elf_linker_section_t *lsect = &htab->sdata[i];
-      asection *s;
-      bfd_vma val;
-      struct elf_link_hash_entry *h;
 
       s = lsect->section;
       if (s != NULL)
@@ -4600,29 +4592,26 @@ ppc_elf_set_sdata_syms (bfd *obfd, struct bfd_link_info *info)
        val = s->vma + 32768;
       lsect->sym_val = val;
 
-      h = elf_link_hash_lookup (&htab->elf, lsect->sym_name,
-                               FALSE, FALSE, FALSE);
-      if (h != NULL && h->root.type == bfd_link_hash_undefined)
-       {
-         h->root.type = bfd_link_hash_defined;
-         h->root.u.def.section = bfd_abs_section_ptr;
-         h->root.u.def.value = val;
-         h->def_regular = 1;
-         h->type = STT_OBJECT;
-         h->other = STV_HIDDEN;
-       }
+      _bfd_elf_provide_symbol (info, lsect->sym_name, val);
     }
+
+  s = bfd_get_section_by_name (obfd, ".sbss");
+  val = 0;
+  if (s != NULL)
+    val = s->vma;
+  _bfd_elf_provide_symbol (info, "__sbss_start", val);
+  _bfd_elf_provide_symbol (info, "___sbss_start", val);
+  if (s != NULL)
+    val += s->size;
+  _bfd_elf_provide_symbol (info, "__sbss_end", val);
+  _bfd_elf_provide_symbol (info, "___sbss_end", val);
   return TRUE;
 }
 \f
-#define bfd_put_ptr(BFD, VAL, ADDR) bfd_put_32 (BFD, VAL, ADDR)
-
 /* Fill in the address for a pointer generated in a linker section.  */
 
 static bfd_vma
-elf_finish_pointer_linker_section (bfd *output_bfd,
-                                  bfd *input_bfd,
-                                  struct bfd_link_info *info,
+elf_finish_pointer_linker_section (bfd *input_bfd,
                                   elf_linker_section_t *lsect,
                                   struct elf_link_hash_entry *h,
                                   bfd_vma relocation,
@@ -4638,60 +4627,35 @@ elf_finish_pointer_linker_section (bfd *output_bfd,
       struct ppc_elf_link_hash_entry *eh;
 
       eh = (struct ppc_elf_link_hash_entry *) h;
-      linker_section_ptr
-       = elf_find_pointer_linker_section (eh->linker_section_pointer,
-                                          rel->r_addend,
-                                          lsect);
-
-      BFD_ASSERT (linker_section_ptr != NULL);
-
-      if (! elf_hash_table (info)->dynamic_sections_created
-         || (info->shared
-             && info->symbolic
-             && h->def_regular))
-       {
-         /* This is actually a static link, or it is a
-            -Bsymbolic link and the symbol is defined
-            locally.  We must initialize this entry in the
-            global section.
-
-            When doing a dynamic link, we create a .rela.<xxx>
-            relocation entry to initialize the value.  This
-            is done in the finish_dynamic_symbol routine.  */
-         if (!linker_section_ptr->written_address_p)
-           {
-             linker_section_ptr->written_address_p = TRUE;
-             bfd_put_ptr (output_bfd,
-                          relocation + linker_section_ptr->addend,
-                          (lsect->section->contents
-                           + linker_section_ptr->offset));
-           }
-       }
+      BFD_ASSERT (eh->elf.def_regular);
+      linker_section_ptr = eh->linker_section_pointer;
     }
   else
     {
       /* Handle local symbol.  */
       unsigned long r_symndx = ELF32_R_SYM (rel->r_info);
+
       BFD_ASSERT (elf_local_ptr_offsets (input_bfd) != NULL);
-      BFD_ASSERT (elf_local_ptr_offsets (input_bfd)[r_symndx] != NULL);
-      linker_section_ptr = (elf_find_pointer_linker_section
-                           (elf_local_ptr_offsets (input_bfd)[r_symndx],
-                            rel->r_addend,
-                            lsect));
+      linker_section_ptr = elf_local_ptr_offsets (input_bfd)[r_symndx];
+    }
 
-      BFD_ASSERT (linker_section_ptr != NULL);
+  linker_section_ptr = elf_find_pointer_linker_section (linker_section_ptr,
+                                                       rel->r_addend,
+                                                       lsect);
+  BFD_ASSERT (linker_section_ptr != NULL);
 
-      /* Write out pointer if it hasn't been rewritten out before.  */
-      if (!linker_section_ptr->written_address_p)
-       {
-         linker_section_ptr->written_address_p = TRUE;
-         bfd_put_ptr (output_bfd, relocation + linker_section_ptr->addend,
-                      lsect->section->contents + linker_section_ptr->offset);
-       }
+  /* Offset will always be a multiple of four, so use the bottom bit
+     as a "written" flag.  */
+  if ((linker_section_ptr->offset & 1) == 0)
+    {
+      bfd_put_32 (lsect->section->owner,
+                 relocation + linker_section_ptr->addend,
+                 lsect->section->contents + linker_section_ptr->offset);
+      linker_section_ptr->offset += 1;
     }
 
   relocation = (lsect->section->output_offset
-               + linker_section_ptr->offset
+               + linker_section_ptr->offset - 1
                - 0x8000);
 
 #ifdef DEBUG
@@ -4805,7 +4769,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
        {
          sym = local_syms + r_symndx;
          sec = local_sections[r_symndx];
-         sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym);
+         sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
 
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
        }
@@ -5403,6 +5367,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
            break;
          /* Fall thru.  */
 
+         if ((input_section->flags & SEC_ALLOC) == 0)
+           break;
+         /* Fall thru.  */
+
          if ((info->shared
               && (h == NULL
                   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
@@ -5411,7 +5379,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
                   || !SYMBOL_CALLS_LOCAL (info, h)))
              || (ELIMINATE_COPY_RELOCS
                  && !info->shared
-                 && (input_section->flags & SEC_ALLOC) != 0
                  && h != NULL
                  && h->dynindx != -1
                  && !h->non_got_ref
@@ -5577,18 +5544,16 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_EMB_SDAI16:
          BFD_ASSERT (htab->sdata[0].section != NULL);
          relocation
-           = elf_finish_pointer_linker_section (output_bfd, input_bfd, info,
-                                                &htab->sdata[0], h,
-                                                relocation, rel);
+           = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[0],
+                                                h, relocation, rel);
          break;
 
          /* Indirect .sdata2 relocation.  */
        case R_PPC_EMB_SDA2I16:
          BFD_ASSERT (htab->sdata[1].section != NULL);
          relocation
-           = elf_finish_pointer_linker_section (output_bfd, input_bfd, info,
-                                                &htab->sdata[1], h,
-                                                relocation, rel);
+           = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[1],
+                                                h, relocation, rel);
          break;
 
          /* Handle the TOC16 reloc.  We want to use the offset within the .got
@@ -5837,8 +5802,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
       if (r != bfd_reloc_ok)
        {
-         if (sym_name == NULL)
-           sym_name = "(null)";
          if (r == bfd_reloc_overflow)
            {
              if (warned)
This page took 0.030999 seconds and 4 git commands to generate.