bfd/
authorAlan Modra <amodra@gmail.com>
Mon, 21 Mar 2005 13:23:15 +0000 (13:23 +0000)
committerAlan Modra <amodra@gmail.com>
Mon, 21 Mar 2005 13:23:15 +0000 (13:23 +0000)
* elf32-ppc.c (struct elf_linker_section): Remove sym_hash and
sym_offset.  Add name, bss_name, sym_name, sym_val.
(struct ppc_elf_link_hash_table): Remove sdata and sdata2 pointers.
Add sdata array of elf_linker_section_t.
(ppc_elf_link_hash_table_create): Set name, sym_name, and bss_name.
(enum elf_linker_section_enum): Delete.
(ppc_elf_create_linker_section): Rewrite.  Don't create syms here.
(ppc_elf_check_relocs): Delay ppc_elf_create_linker_section until
the special sections are needed.  Adjust htab->sdata refs.
Ensure dynobj is set in sreloc code.
(ppc_elf_size_dynamic_sections): Strip sdata sections.
(ppc_elf_set_sdata_syms): New function.
(elf_finish_pointer_linker_section): Use 0x8000 for sym_offset.
(ppc_elf_relocate_section): Adjust references to htab->sdata.  Use
sym_val instead of sym_hash.
* elf32-ppc.h (ppc_elf_set_sdata_syms): Declare.
ld/
* emultempl/ppc32elf.em (gld${EMULATION_NAME}_after_allocation): New
function.
(LDEMUL_AFTER_ALLOCATION): Define.

bfd/ChangeLog
bfd/elf32-ppc.c
bfd/elf32-ppc.h
ld/ChangeLog
ld/emultempl/ppc32elf.em

index fb5ddf9..014759d 100644 (file)
@@ -1,5 +1,24 @@
 2005-03-21  Alan Modra  <amodra@bigpond.net.au>
 
+       * elf32-ppc.c (struct elf_linker_section): Remove sym_hash and
+       sym_offset.  Add name, bss_name, sym_name, sym_val.
+       (struct ppc_elf_link_hash_table): Remove sdata and sdata2 pointers.
+       Add sdata array of elf_linker_section_t.
+       (ppc_elf_link_hash_table_create): Set name, sym_name, and bss_name.
+       (enum elf_linker_section_enum): Delete.
+       (ppc_elf_create_linker_section): Rewrite.  Don't create syms here.
+       (ppc_elf_check_relocs): Delay ppc_elf_create_linker_section until
+       the special sections are needed.  Adjust htab->sdata refs.
+       Ensure dynobj is set in sreloc code.
+       (ppc_elf_size_dynamic_sections): Strip sdata sections.
+       (ppc_elf_set_sdata_syms): New function.
+       (elf_finish_pointer_linker_section): Use 0x8000 for sym_offset.
+       (ppc_elf_relocate_section): Adjust references to htab->sdata.  Use
+       sym_val instead of sym_hash.
+       * elf32-ppc.h (ppc_elf_set_sdata_syms): Declare.
+
+2005-03-21  Alan Modra  <amodra@bigpond.net.au>
+
        * elf32-ppc.c (is_ppc_elf_target): Move to linker part of file.
        (ppc_elf_merge_private_bfd_data): Likewise.
 
index 4050759..2e9b549 100644 (file)
@@ -1506,12 +1506,16 @@ ppc_elf_unhandled_reloc (bfd *abfd,
 
 typedef struct elf_linker_section
 {
-  /* pointer to the section */
+  /* Pointer to the bfd section.  */
   asection *section;
-  /* pointer to the created symbol hash value */
-  struct elf_link_hash_entry *sym_hash;
-  /* offset of symbol from beginning of section */
-  bfd_vma sym_offset;
+  /* Section name.  */
+  const char *name;
+  /* Associated bss section name.  */
+  const char *bss_name;
+  /* Associated symbol name.  */
+  const char *sym_name;
+  /* Value of symbol.  */
+  bfd_vma sym_val;
 } elf_linker_section_t;
 
 /* Linked list of allocated pointer entries.  This hangs off of the
@@ -2117,8 +2121,7 @@ struct ppc_elf_link_hash_table
   asection *relbss;
   asection *dynsbss;
   asection *relsbss;
-  elf_linker_section_t *sdata;
-  elf_linker_section_t *sdata2;
+  elf_linker_section_t sdata[2];
   asection *sbss;
 
   /* Shortcut to .__tls_get_addr.  */
@@ -2186,6 +2189,14 @@ ppc_elf_link_hash_table_create (bfd *abfd)
       return NULL;
     }
 
+  ret->sdata[0].name = ".sdata";
+  ret->sdata[0].sym_name = "_SDA_BASE_";
+  ret->sdata[0].bss_name = ".sbss";
+
+  ret->sdata[1].name = ".sdata2";
+  ret->sdata[1].sym_name = "_SDA2_BASE_";
+  ret->sdata[1].bss_name = ".sbss2";
+
   return &ret->elf.root;
 }
 
@@ -2385,121 +2396,47 @@ ppc_elf_add_symbol_hook (bfd *abfd,
   return TRUE;
 }
 \f
-/* Enumeration to specify the special section.  */
-enum elf_linker_section_enum
-{
-  LINKER_SECTION_SDATA,
-  LINKER_SECTION_SDATA2
-};
+/* Create a special linker section.  */
 
-/* Create a special linker section */
-static elf_linker_section_t *
+static bfd_boolean
 ppc_elf_create_linker_section (bfd *abfd,
                               struct bfd_link_info *info,
-                              enum elf_linker_section_enum which)
+                              flagword flags,
+                              elf_linker_section_t *lsect)
 {
-  elf_linker_section_t *lsect;
   struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
-  asection *s, *sym_sec;
-  bfd_size_type amt;
-  flagword flags;
-  const char *name;
-  const char *rel_name;
-  const char *sym_name;
-  bfd_vma sym_offset;
-
-  /* The linker creates these sections so it has somewhere to attach
-     their respective symbols.  Startup code (crt1.o) uses these symbols
-     to initialize a register pointing to the section.  If the output
-     sections corresponding to these input sections were empty it would
-     be OK to set the symbol to 0 (or any random number), because the
-     associated register should never be used.
-     FIXME: Setting a symbol this way is silly.  The symbols ought to 
-     be set the same way other backends set gp.  */
-  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
-          | SEC_LINKER_CREATED);
-  sym_offset = 32768;
-
-  switch (which)
-    {
-    default:
-      abort ();
-      return NULL;
-
-    case LINKER_SECTION_SDATA: /* .sdata/.sbss section */
-      name     = ".sdata";
-      rel_name = ".rela.sdata";
-      sym_name = "_SDA_BASE_";
-      break;
+  asection *s;
 
-    case LINKER_SECTION_SDATA2:        /* .sdata2/.sbss2 section */
-      name     = ".sdata2";
-      rel_name = ".rela.sdata2";
-      sym_name = "_SDA2_BASE_";
-      flags    |= SEC_READONLY;
-      break;
-    }
+  flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+           | SEC_LINKER_CREATED);
 
   /* Record the first bfd that needs the special sections.  */
   if (!htab->elf.dynobj)
     htab->elf.dynobj = abfd;
 
-  amt = sizeof (elf_linker_section_t);
-  lsect = bfd_zalloc (htab->elf.dynobj, amt);
-
-  lsect->sym_offset = sym_offset;
-
-  /* See if the sections already exist.  */
-  sym_sec = s = bfd_get_section_by_name (htab->elf.dynobj, name);
+  /* 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, name);
+      s = bfd_make_section_anyway (htab->elf.dynobj, lsect->name);
       if (s == NULL
          || !bfd_set_section_flags (htab->elf.dynobj, s, flags))
-       return NULL;
-      if (sym_sec == NULL)
-       sym_sec = s;
+       return FALSE;
     }
   lsect->section = s;
 
   if (bfd_get_section_alignment (htab->elf.dynobj, s) < 2
       && !bfd_set_section_alignment (htab->elf.dynobj, s, 2))
-    return NULL;
+    return FALSE;
 
   s->size = align_power (s->size, 2);
 
 #ifdef DEBUG
   fprintf (stderr, "Creating section %s, current size = %ld\n",
-          name, (long) s->size);
+          lsect->name, (long) s->size);
 #endif
 
-  if (sym_name)
-    {
-      struct elf_link_hash_entry *h;
-      struct bfd_link_hash_entry *bh;
-
-#ifdef DEBUG
-      fprintf (stderr, "Adding %s to section %s\n", sym_name, name);
-#endif
-      bh = bfd_link_hash_lookup (info->hash, sym_name,
-                                FALSE, FALSE, FALSE);
-
-      if ((bh == NULL || bh->type == bfd_link_hash_undefined)
-         && !(_bfd_generic_link_add_one_symbol
-              (info, abfd, sym_name, BSF_GLOBAL, sym_sec, sym_offset, NULL,
-               FALSE, get_elf_backend_data (abfd)->collect, &bh)))
-       return NULL;
-      h = (struct elf_link_hash_entry *) bh;
-
-      h->type = STT_OBJECT;
-      lsect->sym_hash = h;
-
-      if (info->shared
-         && ! bfd_elf_link_record_dynamic_symbol (info, h))
-       return NULL;
-    }
-
-  return lsect;
+  return TRUE;
 }
 
 /* Find a linker generated pointer with a given addend and type.  */
@@ -2675,25 +2612,7 @@ ppc_elf_check_relocs (bfd *abfd,
   if (!ppc_elf_howto_table[R_PPC_ADDR32])
     ppc_elf_howto_init ();
 
-  /* Create the linker generated sections all the time so that the
-     special symbols are created.  */
   htab = ppc_elf_hash_table (info);
-  if (htab->sdata == NULL)
-    {
-      htab->sdata = ppc_elf_create_linker_section (abfd, info,
-                                                  LINKER_SECTION_SDATA);
-      if (htab->sdata == NULL)
-       return FALSE;
-    }
-
-  if (htab->sdata2 == NULL)
-    {
-      htab->sdata2 = ppc_elf_create_linker_section (abfd, info,
-                                                   LINKER_SECTION_SDATA2);
-      if (htab->sdata2 == NULL)
-       return FALSE;
-    }
-
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
   sreloc = NULL;
@@ -2793,8 +2712,12 @@ ppc_elf_check_relocs (bfd *abfd,
              bad_shared_reloc (abfd, r_type);
              return FALSE;
            }
+         if (htab->sdata[0].section == NULL
+             && !ppc_elf_create_linker_section (abfd, info, 0,
+                                                &htab->sdata[0]))
+           return FALSE;
          if (!elf_create_pointer_linker_section (abfd, info,
-                                                 htab->sdata, h, rel))
+                                                 &htab->sdata[0], h, rel))
            return FALSE;
          break;
 
@@ -2805,8 +2728,12 @@ ppc_elf_check_relocs (bfd *abfd,
              bad_shared_reloc (abfd, r_type);
              return FALSE;
            }
+         if (htab->sdata[1].section == NULL
+             && !ppc_elf_create_linker_section (abfd, info, SEC_READONLY,
+                                                &htab->sdata[1]))
+           return FALSE;
          if (!elf_create_pointer_linker_section (abfd, info,
-                                                 htab->sdata2, h, rel))
+                                                 &htab->sdata[1], h, rel))
            return FALSE;
          break;
 
@@ -3027,6 +2954,8 @@ ppc_elf_check_relocs (bfd *abfd,
                              && strcmp (bfd_get_section_name (abfd, sec),
                                         name + 5) == 0);
 
+                 if (htab->elf.dynobj == NULL)
+                   htab->elf.dynobj = abfd;
                  sreloc = bfd_get_section_by_name (htab->elf.dynobj, name);
                  if (sreloc == NULL)
                    {
@@ -4129,14 +4058,10 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
          /* Strip this section if we don't need it; see the
             comment below.  */
        }
-      else if ((htab->sdata != NULL && s == htab->sdata->section)
-              || (htab->sdata2 != NULL && s == htab->sdata2->section))
+      else if (s == htab->sdata[0].section
+              || s == htab->sdata[1].section)
        {
-         if (s->size == 0)
-           /* Don't strip these sections.  We need them because they
-              define _SDA_BASE_ and _SDA2_BASE_.  crt1.o makes a
-              reference to _SDA_BASE_ to set up r13.  */
-           continue;
+         /* Strip these too.  */
        }
       else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
        {
@@ -4638,6 +4563,51 @@ ppc_elf_relax_section (bfd *abfd,
   return FALSE;
 }
 \f
+/* Set _SDA_BASE_ and _SDA2_BASE.  */
+
+bfd_boolean
+ppc_elf_set_sdata_syms (bfd *obfd, struct bfd_link_info *info)
+{
+  struct ppc_elf_link_hash_table *htab;
+  unsigned i;
+
+  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)
+       s = s->output_section;
+      if (s == NULL)
+       s = bfd_get_section_by_name (obfd, lsect->name);
+      if (s == NULL)
+       s = bfd_get_section_by_name (obfd, lsect->bss_name);
+
+      val = 0;
+      if (s != NULL)
+       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;
+       }
+    }
+  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.  */
@@ -4715,7 +4685,7 @@ elf_finish_pointer_linker_section (bfd *output_bfd,
 
   relocation = (lsect->section->output_offset
                + linker_section_ptr->offset
-               - lsect->sym_offset);
+               - 0x8000);
 
 #ifdef DEBUG
   fprintf (stderr,
@@ -5598,20 +5568,20 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
          /* Indirect .sdata relocation.  */
        case R_PPC_EMB_SDAI16:
-         BFD_ASSERT (htab->sdata != NULL);
+         BFD_ASSERT (htab->sdata[0].section != NULL);
          relocation
            = elf_finish_pointer_linker_section (output_bfd, input_bfd, info,
-                                                htab->sdata, h, relocation,
-                                                rel);
+                                                &htab->sdata[0], h,
+                                                relocation, rel);
          break;
 
          /* Indirect .sdata2 relocation.  */
        case R_PPC_EMB_SDA2I16:
-         BFD_ASSERT (htab->sdata2 != NULL);
+         BFD_ASSERT (htab->sdata[1].section != NULL);
          relocation
            = elf_finish_pointer_linker_section (output_bfd, input_bfd, info,
-                                                htab->sdata2, h, relocation,
-                                                rel);
+                                                &htab->sdata[1], h,
+                                                relocation, rel);
          break;
 
          /* Handle the TOC16 reloc.  We want to use the offset within the .got
@@ -5651,7 +5621,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_SDAREL16:
          {
            const char *name;
-           const struct elf_link_hash_entry *sh;
 
            BFD_ASSERT (sec != NULL);
            name = bfd_get_section_name (abfd, sec->output_section);
@@ -5668,10 +5637,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                   howto->name,
                   name);
              }
-           sh = htab->sdata->sym_hash;
-           addend -= (sh->root.u.def.value
-                      + sh->root.u.def.section->output_section->vma
-                      + sh->root.u.def.section->output_offset);
+           addend -= htab->sdata[0].sym_val;
          }
          break;
 
@@ -5679,7 +5645,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_EMB_SDA2REL:
          {
            const char *name;
-           const struct elf_link_hash_entry *sh;
 
            BFD_ASSERT (sec != NULL);
            name = bfd_get_section_name (abfd, sec->output_section);
@@ -5698,10 +5663,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                ret = FALSE;
                continue;
              }
-           sh = htab->sdata2->sym_hash;
-           addend -= (sh->root.u.def.value
-                      + sh->root.u.def.section->output_section->vma
-                      + sh->root.u.def.section->output_offset);
+           addend -= htab->sdata[1].sym_val;
          }
          break;
 
@@ -5710,7 +5672,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_EMB_RELSDA:
          {
            const char *name;
-           const struct elf_link_hash_entry *sh;
            int reg;
 
            BFD_ASSERT (sec != NULL);
@@ -5721,20 +5682,14 @@ ppc_elf_relocate_section (bfd *output_bfd,
                     && (name[5] == 0 || name[5] == '.'))))
              {
                reg = 13;
-               sh = htab->sdata->sym_hash;
-               addend -= (sh->root.u.def.value
-                          + sh->root.u.def.section->output_section->vma
-                          + sh->root.u.def.section->output_offset);
+               addend -= htab->sdata[0].sym_val;
              }
 
            else if (strncmp (name, ".sdata2", 7) == 0
                     || strncmp (name, ".sbss2", 6) == 0)
              {
                reg = 2;
-               sh = htab->sdata2->sym_hash;
-               addend -= (sh->root.u.def.value
-                          + sh->root.u.def.section->output_section->vma
-                          + sh->root.u.def.section->output_offset);
+               addend -= htab->sdata[1].sym_val;
              }
 
            else if (strcmp (name, ".PPC.EMB.sdata0") == 0
index fa2c585..da8c8f9 100644 (file)
@@ -1,5 +1,5 @@
 /* PowerPC-specific support for 64-bit ELF.
-   Copyright 2003 Free Software Foundation, Inc.
+   Copyright 2003, 2005 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -19,3 +19,4 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *);
 bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *);
+bfd_boolean ppc_elf_set_sdata_syms (bfd *, struct bfd_link_info *);
index 95c97a3..b704d66 100644 (file)
@@ -1,5 +1,11 @@
 2005-03-21  Alan Modra  <amodra@bigpond.net.au>
 
+       * emultempl/ppc32elf.em (gld${EMULATION_NAME}_after_allocation): New
+       function.
+       (LDEMUL_AFTER_ALLOCATION): Define.
+
+2005-03-21  Alan Modra  <amodra@bigpond.net.au>
+
        * emultempl/ppc64elf.em (ppc_finish): Rename from
        gld${EMULATION_NAME}_finish.  Call gld${EMULATION_NAME}_finish.
        (LDEMUL_FINISH): Update.
index 4614593..710160d 100644 (file)
@@ -1,5 +1,5 @@
 # This shell script emits a C file. -*- C -*-
-#   Copyright 2003 Free Software Foundation, Inc.
+#   Copyright 2003, 2005 Free Software Foundation, Inc.
 #
 # This file is part of GLD, the Gnu Linker.
 #
@@ -18,7 +18,7 @@
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #
 
-# This file is sourced from elf32.em, and defines extra powerpc64-elf
+# This file is sourced from elf32.em, and defines extra powerpc32-elf
 # specific routines.
 #
 cat >>e${EMULATION_NAME}.c <<EOF
@@ -26,15 +26,15 @@ cat >>e${EMULATION_NAME}.c <<EOF
 #include "libbfd.h"
 #include "elf32-ppc.h"
 
+extern const bfd_target bfd_elf32_powerpc_vec;
+extern const bfd_target bfd_elf32_powerpcle_vec;
+
 /* Whether to run tls optimization.  */
 static int notlsopt = 0;
 
 static void
 ppc_before_allocation (void)
 {
-  extern const bfd_target bfd_elf32_powerpc_vec;
-  extern const bfd_target bfd_elf32_powerpcle_vec;
-
   if (link_info.hash->creator == &bfd_elf32_powerpc_vec
       || link_info.hash->creator == &bfd_elf32_powerpcle_vec)
     {
@@ -50,6 +50,17 @@ ppc_before_allocation (void)
   gld${EMULATION_NAME}_before_allocation ();
 }
 
+static void
+gld${EMULATION_NAME}_after_allocation (void)
+{
+  if (link_info.hash->creator == &bfd_elf32_powerpc_vec
+      || link_info.hash->creator == &bfd_elf32_powerpcle_vec)
+    {
+      if (!ppc_elf_set_sdata_syms (output_bfd, &link_info))
+       einfo ("%X%P: cannot set sdata syms %E\n");
+    }
+}
+
 EOF
 
 # Define some shell vars to insert bits of code into the standard elf
@@ -75,6 +86,7 @@ PARSE_AND_LIST_ARGS_CASES='
       break;
 '
 
-# Put these extra ppc64elf routines in ld_${EMULATION_NAME}_emulation
+# Put these extra ppc32elf routines in ld_${EMULATION_NAME}_emulation
 #
 LDEMUL_BEFORE_ALLOCATION=ppc_before_allocation
+LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation