PR 6844
authorAlan Modra <amodra@gmail.com>
Tue, 16 Sep 2008 13:43:36 +0000 (13:43 +0000)
committerAlan Modra <amodra@gmail.com>
Tue, 16 Sep 2008 13:43:36 +0000 (13:43 +0000)
* elf32-ppc.c (SYM_VAL): Define.  Use throughout to find symbol vma.
(ppc_elf_relocate_section): Correct GOT offset calculation.
(ppc_elf_finish_dynamic_symbol): Use PPC_HA and PPC_LO.
(ppc_elf_finish_dynamic_sections): Likewise.  Error if
htab->elf.hgot symbol is not defined in htab->got section.

bfd/ChangeLog
bfd/elf32-ppc.c

index c9cbe0c4a4dcbe6c7dfda496a89a5eb88c708a77..6a2e8f38b1ae3e9914a5e814751f7b324ea56186 100644 (file)
@@ -1,3 +1,12 @@
+2008-09-16  Alan Modra  <amodra@bigpond.net.au>
+
+       PR 6844
+       * elf32-ppc.c (SYM_VAL): Define.  Use throughout to find symbol vma.
+       (ppc_elf_relocate_section): Correct GOT offset calculation.
+       (ppc_elf_finish_dynamic_symbol): Use PPC_HA and PPC_LO.
+       (ppc_elf_finish_dynamic_sections): Likewise.  Error if
+       htab->elf.hgot symbol is not defined in htab->got section.
+
 2008-09-16  Alan Modra  <amodra@bigpond.net.au>
 
        PR 6888
index 8720b0b68bccbaff9de6cb68237c0652de4b956d..10828209b2ee1c8bd237a2bd38c6edee50d25d12 100644 (file)
@@ -157,6 +157,12 @@ static const bfd_vma ppc_elf_vxworks_pic_plt0_entry
 /* Offset of tp and dtp pointers from start of TLS block.  */
 #define TP_OFFSET      0x7000
 #define DTP_OFFSET     0x8000
+
+/* The value of a defined global symbol.  */
+#define SYM_VAL(SYM) \
+  ((SYM)->root.u.def.section->output_section->vma      \
+   + (SYM)->root.u.def.section->output_offset          \
+   + (SYM)->root.u.def.value)
 \f
 static reloc_howto_type *ppc_elf_howto_table[R_PPC_max];
 
@@ -6656,8 +6662,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  }
              }
 
-           relocation = htab->got->output_offset + off;
-           relocation -= htab->elf.hgot->root.u.def.value;
+           relocation = (htab->got->output_section->vma
+                         + htab->got->output_offset
+                         + off
+                         - SYM_VAL (htab->elf.hgot));
 
            /* Addends on got relocations don't make much sense.
               x+off@got is actually x@got+off, and since the got is
@@ -7014,7 +7022,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_SDAREL16:
          {
            const char *name;
-           struct elf_link_hash_entry *sh;
 
            if (sec == NULL || sec->output_section == NULL)
              {
@@ -7036,10 +7043,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                   howto->name,
                   name);
              }
-           sh = htab->sdata[0].sym;
-           addend -= (sh->root.u.def.value
-                      + sh->root.u.def.section->output_offset
-                      + sh->root.u.def.section->output_section->vma);
+           addend -= SYM_VAL (htab->sdata[0].sym);
          }
          break;
 
@@ -7047,7 +7051,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_EMB_SDA2REL:
          {
            const char *name;
-           struct elf_link_hash_entry *sh;
 
            if (sec == NULL || sec->output_section == NULL)
              {
@@ -7071,10 +7074,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                ret = FALSE;
                continue;
              }
-           sh = htab->sdata[1].sym;
-           addend -= (sh->root.u.def.value
-                      + sh->root.u.def.section->output_offset
-                      + sh->root.u.def.section->output_section->vma);
+           addend -= SYM_VAL (htab->sdata[1].sym);
          }
          break;
 
@@ -7084,7 +7084,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
          {
            const char *name;
            int reg;
-           struct elf_link_hash_entry *sh;
 
            if (sec == NULL || sec->output_section == NULL)
              {
@@ -7099,19 +7098,13 @@ ppc_elf_relocate_section (bfd *output_bfd,
                     && (name[5] == 0 || name[5] == '.'))))
              {
                reg = 13;
-               sh = htab->sdata[0].sym;
-               addend -= (sh->root.u.def.value
-                          + sh->root.u.def.section->output_offset
-                          + sh->root.u.def.section->output_section->vma);
+               addend -= SYM_VAL (htab->sdata[0].sym);
              }
            else if (CONST_STRNEQ (name, ".sdata2")
                     || CONST_STRNEQ (name, ".sbss2"))
              {
                reg = 2;
-               sh = htab->sdata[1].sym;
-               addend -= (sh->root.u.def.value
-                          + sh->root.u.def.section->output_offset
-                          + sh->root.u.def.section->output_section->vma);
+               addend -= SYM_VAL (htab->sdata[1].sym);
              }
            else if (strcmp (name, ".PPC.EMB.sdata0") == 0
                     || strcmp (name, ".PPC.EMB.sbss0") == 0)
@@ -7366,31 +7359,22 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
                /* Fill in the .plt on VxWorks.  */
                if (info->shared)
                  {
-                   bfd_vma got_offset_hi = (got_offset >> 16)
-                                           + ((got_offset & 0x8000) >> 15);
-
                    bfd_put_32 (output_bfd,
-                               plt_entry[0] | (got_offset_hi & 0xffff),
+                               plt_entry[0] | PPC_HA (got_offset),
                                htab->plt->contents + ent->plt.offset + 0);
                    bfd_put_32 (output_bfd,
-                               plt_entry[1] | (got_offset & 0xffff),
+                               plt_entry[1] | PPC_LO (got_offset),
                                htab->plt->contents + ent->plt.offset + 4);
                  }
                else
                  {
-                   bfd_vma got_loc
-                     = (got_offset
-                        + htab->elf.hgot->root.u.def.value
-                        + htab->elf.hgot->root.u.def.section->output_offset
-                        + htab->elf.hgot->root.u.def.section->output_section->vma);
-                   bfd_vma got_loc_hi = (got_loc >> 16)
-                                        + ((got_loc & 0x8000) >> 15);
+                   bfd_vma got_loc = got_offset + SYM_VAL (htab->elf.hgot);
 
                    bfd_put_32 (output_bfd,
-                               plt_entry[0] | (got_loc_hi & 0xffff),
+                               plt_entry[0] | PPC_HA (got_loc),
                                htab->plt->contents + ent->plt.offset + 0);
                    bfd_put_32 (output_bfd,
-                               plt_entry[1] | (got_loc & 0xffff),
+                               plt_entry[1] | PPC_LO (got_loc),
                                htab->plt->contents + ent->plt.offset + 4);
                  }
 
@@ -7550,9 +7534,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
                         + ent->sec->output_section->vma
                         + ent->sec->output_offset);
                else if (htab->elf.hgot != NULL)
-                 got = (htab->elf.hgot->root.u.def.value
-                        + htab->elf.hgot->root.u.def.section->output_section->vma
-                        + htab->elf.hgot->root.u.def.section->output_offset);
+                 got = SYM_VAL (htab->elf.hgot);
 
                plt -= got;
 
@@ -7618,9 +7600,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
        s = htab->relbss;
       BFD_ASSERT (s != NULL);
 
-      rela.r_offset = (h->root.u.def.value
-                      + h->root.u.def.section->output_section->vma
-                      + h->root.u.def.section->output_offset);
+      rela.r_offset = SYM_VAL (h);
       rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY);
       rela.r_addend = 0;
       loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
@@ -7670,7 +7650,8 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
   asection *splt;
   struct ppc_elf_link_hash_table *htab;
   bfd_vma got;
-  bfd * dynobj;
+  bfd *dynobj;
+  bfd_boolean ret = TRUE;
 
 #ifdef DEBUG
   fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n");
@@ -7686,9 +7667,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 
   got = 0;
   if (htab->elf.hgot != NULL)
-    got = (htab->elf.hgot->root.u.def.value
-          + htab->elf.hgot->root.u.def.section->output_section->vma
-          + htab->elf.hgot->root.u.def.section->output_offset);
+    got = SYM_VAL (htab->elf.hgot);
 
   if (htab->elf.dynamic_sections_created)
     {
@@ -7752,17 +7731,28 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
      easily find the address of the _GLOBAL_OFFSET_TABLE_.  */
   if (htab->got != NULL)
     {
-      unsigned char *p = htab->got->contents;
-      bfd_vma val;
+      if (htab->elf.hgot->root.u.def.section == htab->got)
+       {
+         unsigned char *p = htab->got->contents;
+         bfd_vma val;
 
-      p += htab->elf.hgot->root.u.def.value;
-      if (htab->plt_type == PLT_OLD)
-       bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4);
+         p += htab->elf.hgot->root.u.def.value;
+         if (htab->plt_type == PLT_OLD)
+           bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4);
 
-      val = 0;
-      if (sdyn != NULL)
-       val = sdyn->output_section->vma + sdyn->output_offset;
-      bfd_put_32 (output_bfd, val, p);
+         val = 0;
+         if (sdyn != NULL)
+           val = sdyn->output_section->vma + sdyn->output_offset;
+         bfd_put_32 (output_bfd, val, p);
+       }
+      else
+       {
+         (*_bfd_error_handler) (_("%s not defined in linker created %s"),
+                                htab->elf.hgot->root.root.string,
+                                htab->got->name);
+         bfd_set_error (bfd_error_bad_value);
+         ret = FALSE;
+       }
 
       elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 4;
     }
@@ -7777,15 +7767,11 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 
       if (!info->shared)
        {
-         bfd_vma got_value =
-           (htab->elf.hgot->root.u.def.section->output_section->vma
-            + htab->elf.hgot->root.u.def.section->output_offset
-            + htab->elf.hgot->root.u.def.value);
-         bfd_vma got_hi = (got_value >> 16) + ((got_value & 0x8000) >> 15);
+         bfd_vma got_value = SYM_VAL (htab->elf.hgot);
 
-         bfd_put_32 (output_bfd, plt_entry[0] | (got_hi & 0xffff),
+         bfd_put_32 (output_bfd, plt_entry[0] | PPC_HA (got_value),
                      splt->contents +  0);
-         bfd_put_32 (output_bfd, plt_entry[1] | (got_value & 0xffff),
+         bfd_put_32 (output_bfd, plt_entry[1] | PPC_LO (got_value),
                      splt->contents +  4);
        }
       else
@@ -8050,7 +8036,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
        }
     }
 
-  return TRUE;
+  return ret;
 }
 \f
 #define TARGET_LITTLE_SYM      bfd_elf32_powerpcle_vec