PR ld/10406
authorAlan Modra <amodra@gmail.com>
Fri, 18 Sep 2009 12:41:52 +0000 (12:41 +0000)
committerAlan Modra <amodra@gmail.com>
Fri, 18 Sep 2009 12:41:52 +0000 (12:41 +0000)
* elf32-ppc.c (ppc_elf_howto_raw): Make R_PPC_EMB_SDAI16 and
R_PPC_EMB_SDA2I16 complain_overflow_signed.
(create_sdata_sym): Pass info rather than htab.
Update all callers.  Ensure symbols are hidden.
(ppc_elf_check_relocs): Allow SDAREL16 when shared.
(ppc_elf_size_dynamic_sections): When shared, equate _SDA_BASE_ to
_GLOBAL_OFFSET_TABLE_.
(elf_finish_pointer_linker_section): Don't assume that sdata base
symbol is always at 0x8000 offset.  Don't subtract the addend here.
(is_static_defined): New function.
(ppc_elf_relocate_section): Verify symbol base used in SDA relocs
is statically defined.  Clear addend for EMB_SDAI16 and EMB_SDA2I16
relocs.  Downgrade error on unexpected section for EMB_SDA2REL
reloc symbols to a warning.

bfd/ChangeLog
bfd/elf32-ppc.c

index 9a8e9bc8b90425c2f6e5eaf60e19186cdf93f4d5..a00939905690bcb91c8c2f2260ecad52db2bf161 100644 (file)
@@ -1,3 +1,21 @@
+2009-09-18  Alan Modra  <amodra@bigpond.net.au>
+
+       PR ld/10406
+       * elf32-ppc.c (ppc_elf_howto_raw): Make R_PPC_EMB_SDAI16 and
+       R_PPC_EMB_SDA2I16 complain_overflow_signed.
+       (create_sdata_sym): Pass info rather than htab.
+       Update all callers.  Ensure symbols are hidden.
+       (ppc_elf_check_relocs): Allow SDAREL16 when shared.
+       (ppc_elf_size_dynamic_sections): When shared, equate _SDA_BASE_ to
+       _GLOBAL_OFFSET_TABLE_.
+       (elf_finish_pointer_linker_section): Don't assume that sdata base
+       symbol is always at 0x8000 offset.  Don't subtract the addend here.
+       (is_static_defined): New function.
+       (ppc_elf_relocate_section): Verify symbol base used in SDA relocs
+       is statically defined.  Clear addend for EMB_SDAI16 and EMB_SDA2I16
+       relocs.  Downgrade error on unexpected section for EMB_SDA2REL
+       reloc symbols to a warning.
+
 2009-09-18  Nick Clifton  <nickc@redhat.com>
 
        * po/es.po: Updated Spanish translation.
index ae031df477f939a401182e0585626af340f4ca30..bbe94dba987cb5434ab963acc16c74ef1210c27c 100644 (file)
@@ -1300,7 +1300,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         16,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
+        complain_overflow_signed, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_PPC_EMB_SDAI16",    /* name */
         FALSE,                 /* partial_inplace */
@@ -1317,7 +1317,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
         16,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
+        complain_overflow_signed, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_PPC_EMB_SDA2I16",   /* name */
         FALSE,                 /* partial_inplace */
@@ -3129,9 +3129,10 @@ ppc_elf_add_symbol_hook (bfd *abfd,
 }
 \f
 static bfd_boolean
-create_sdata_sym (struct ppc_elf_link_hash_table *htab,
-                 elf_linker_section_t *lsect)
+create_sdata_sym (struct bfd_link_info *info, elf_linker_section_t *lsect)
 {
+  struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
+
   lsect->sym = elf_link_hash_lookup (&htab->elf, lsect->sym_name,
                                     TRUE, FALSE, TRUE);
   if (lsect->sym == NULL)
@@ -3139,6 +3140,7 @@ create_sdata_sym (struct ppc_elf_link_hash_table *htab,
   if (lsect->sym->root.type == bfd_link_hash_new)
     lsect->sym->non_elf = 0;
   lsect->sym->ref_regular = 1;
+  _bfd_elf_link_hash_hide_symbol (info, lsect->sym, TRUE);
   return TRUE;
 }
 
@@ -3168,7 +3170,7 @@ ppc_elf_create_linker_section (bfd *abfd,
     return FALSE;
   lsect->section = s;
 
-  return create_sdata_sym (htab, lsect);
+  return create_sdata_sym (info, lsect);
 }
 
 /* Find a linker generated pointer with a given addend and type.  */
@@ -3633,13 +3635,8 @@ ppc_elf_check_relocs (bfd *abfd,
          break;
 
        case R_PPC_SDAREL16:
-         if (info->shared)
-           {
-             bad_shared_reloc (abfd, r_type);
-             return FALSE;
-           }
          if (htab->sdata[0].sym == NULL
-             && !create_sdata_sym (htab, &htab->sdata[0]))
+             && !create_sdata_sym (info, &htab->sdata[0]))
            return FALSE;
          if (h != NULL)
            {
@@ -3655,7 +3652,7 @@ ppc_elf_check_relocs (bfd *abfd,
              return FALSE;
            }
          if (htab->sdata[1].sym == NULL
-             && !create_sdata_sym (htab, &htab->sdata[1]))
+             && !create_sdata_sym (info, &htab->sdata[1]))
            return FALSE;
          if (h != NULL)
            {
@@ -3672,10 +3669,10 @@ ppc_elf_check_relocs (bfd *abfd,
              return FALSE;
            }
          if (htab->sdata[0].sym == NULL
-             && !create_sdata_sym (htab, &htab->sdata[0]))
+             && !create_sdata_sym (info, &htab->sdata[0]))
            return FALSE;
          if (htab->sdata[1].sym == NULL
-             && !create_sdata_sym (htab, &htab->sdata[1]))
+             && !create_sdata_sym (info, &htab->sdata[1]))
            return FALSE;
          if (h != NULL)
            {
@@ -5660,6 +5657,18 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
       htab->elf.hgot->root.u.def.value = g_o_t;
     }
+  if (info->shared)
+    {
+      struct elf_link_hash_entry *sda = htab->sdata[0].sym;
+      if (sda != NULL
+         && !(sda->root.type == bfd_link_hash_defined
+              || sda->root.type == bfd_link_hash_defweak))
+       {
+         sda->root.type = bfd_link_hash_defined;
+         sda->root.u.def.section = htab->elf.hgot->root.u.def.section;
+         sda->root.u.def.value = htab->elf.hgot->root.u.def.value;
+       }
+    }
 
   if (htab->glink != NULL
       && htab->glink->size != 0
@@ -6446,9 +6455,10 @@ elf_finish_pointer_linker_section (bfd *input_bfd,
       linker_section_ptr->offset += 1;
     }
 
-  relocation = (lsect->section->output_offset
+  relocation = (lsect->section->output_section->vma
+               + lsect->section->output_offset
                + linker_section_ptr->offset - 1
-               - 0x8000);
+               - SYM_VAL (lsect->sym));
 
 #ifdef DEBUG
   fprintf (stderr,
@@ -6456,9 +6466,7 @@ elf_finish_pointer_linker_section (bfd *input_bfd,
           lsect->name, (long) relocation, (long) relocation);
 #endif
 
-  /* Subtract out the addend, because it will get added back in by the normal
-     processing.  */
-  return relocation - linker_section_ptr->addend;
+  return relocation;
 }
 
 #define PPC_LO(v) ((v) & 0xffff)
@@ -6528,6 +6536,17 @@ write_glink_stub (struct plt_entry *ent, asection *plt_sec,
     }
 }
 
+/* Return true if symbol is defined statically.  */
+
+static bfd_boolean
+is_static_defined (struct elf_link_hash_entry *h)
+{
+  return ((h->root.type == bfd_link_hash_defined
+          || h->root.type == bfd_link_hash_defweak)
+         && h->root.u.def.section != NULL
+         && h->root.u.def.section->output_section != NULL);
+}
+
 /* The RELOCATE_SECTION function is called by the ELF backend linker
    to handle the relocations for a section.
 
@@ -7629,17 +7648,29 @@ ppc_elf_relocate_section (bfd *output_bfd,
          /* Indirect .sdata relocation.  */
        case R_PPC_EMB_SDAI16:
          BFD_ASSERT (htab->sdata[0].section != NULL);
+         if (!is_static_defined (htab->sdata[0].sym))
+           {
+             unresolved_reloc = TRUE;
+             break;
+           }
          relocation
            = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[0],
                                                 h, relocation, rel);
+         addend = 0;
          break;
 
          /* Indirect .sdata2 relocation.  */
        case R_PPC_EMB_SDA2I16:
          BFD_ASSERT (htab->sdata[1].section != NULL);
+         if (!is_static_defined (htab->sdata[1].sym))
+           {
+             unresolved_reloc = TRUE;
+             break;
+           }
          relocation
            = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[1],
                                                 h, relocation, rel);
+         addend = 0;
          break;
 
          /* Handle the TOC16 reloc.  We want to use the offset within the .got
@@ -7692,12 +7723,16 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_SDAREL16:
          {
            const char *name;
+           struct elf_link_hash_entry *sda = htab->sdata[0].sym;
 
-           if (sec == NULL || sec->output_section == NULL)
+           if (sec == NULL
+               || sec->output_section == NULL
+               || !is_static_defined (sda))
              {
                unresolved_reloc = TRUE;
                break;
              }
+           addend -= SYM_VAL (sda);
 
            name = bfd_get_section_name (abfd, sec->output_section);
            if (! ((CONST_STRNEQ (name, ".sdata")
@@ -7713,7 +7748,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
                   howto->name,
                   name);
              }
-           addend -= SYM_VAL (htab->sdata[0].sym);
          }
          break;
 
@@ -7721,12 +7755,16 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_EMB_SDA2REL:
          {
            const char *name;
+           struct elf_link_hash_entry *sda = htab->sdata[1].sym;
 
-           if (sec == NULL || sec->output_section == NULL)
+           if (sec == NULL
+               || sec->output_section == NULL
+               || !is_static_defined (sda))
              {
                unresolved_reloc = TRUE;
                break;
              }
+           addend -= SYM_VAL (sda);
 
            name = bfd_get_section_name (abfd, sec->output_section);
            if (! (CONST_STRNEQ (name, ".sdata2")
@@ -7739,12 +7777,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                   sym_name,
                   howto->name,
                   name);
-
-               bfd_set_error (bfd_error_bad_value);
-               ret = FALSE;
-               continue;
              }
-           addend -= SYM_VAL (htab->sdata[1].sym);
          }
          break;
 
@@ -7754,6 +7787,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
          {
            const char *name;
            int reg;
+           struct elf_link_hash_entry *sda = NULL;
 
            if (sec == NULL || sec->output_section == NULL)
              {
@@ -7768,13 +7802,13 @@ ppc_elf_relocate_section (bfd *output_bfd,
                     && (name[5] == 0 || name[5] == '.'))))
              {
                reg = 13;
-               addend -= SYM_VAL (htab->sdata[0].sym);
+               sda = htab->sdata[0].sym;
              }
            else if (CONST_STRNEQ (name, ".sdata2")
                     || CONST_STRNEQ (name, ".sbss2"))
              {
                reg = 2;
-               addend -= SYM_VAL (htab->sdata[1].sym);
+               sda = htab->sdata[1].sym;
              }
            else if (strcmp (name, ".PPC.EMB.sdata0") == 0
                     || strcmp (name, ".PPC.EMB.sbss0") == 0)
@@ -7796,6 +7830,16 @@ ppc_elf_relocate_section (bfd *output_bfd,
                continue;
              }
 
+           if (sda != NULL)
+             {
+               if (!is_static_defined (sda))
+                 {
+                   unresolved_reloc = TRUE;
+                   break;
+                 }
+               addend -= SYM_VAL (sda);
+             }
+
            if (r_type == R_PPC_EMB_SDA21)
              {                 /* fill in register field */
                insn = bfd_get_32 (output_bfd, contents + rel->r_offset);