bfd/
[deliverable/binutils-gdb.git] / bfd / elf64-ppc.c
index 9b107c8a8d79bb48d7b0b8972a9ea4838bea2aea..98af624baf5c2aaddabaaa9452c83778a152edb4 100644 (file)
@@ -2541,6 +2541,12 @@ struct plt_entry
    && (RTYPE) != R_PPC64_REL64                 \
    && (RTYPE) != R_PPC64_REL30)
 
+/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
+   copying dynamic variables from a shared lib into an app's dynbss
+   section, and instead use a dynamic relocation to point into the
+   shared lib.  */
+#define ELIMINATE_COPY_RELOCS 1
+
 /* Section name for stubs is the associated section name plus this
    string.  */
 #define STUB_SUFFIX ".stub"
@@ -3266,6 +3272,7 @@ ppc64_elf_copy_indirect_symbol (bed, dir, ind)
      struct elf_link_hash_entry *dir, *ind;
 {
   struct ppc_link_hash_entry *edir, *eind;
+  flagword mask;
 
   edir = (struct ppc_link_hash_entry *) dir;
   eind = (struct ppc_link_hash_entry *) ind;
@@ -3310,20 +3317,24 @@ ppc64_elf_copy_indirect_symbol (bed, dir, ind)
   edir->is_entry |= eind->is_entry;
   edir->tls_mask |= eind->tls_mask;
 
-  /* Copy down any references that we may have already seen to the
-     symbol which just became indirect.  */
-  edir->elf.elf_link_hash_flags |=
-    (eind->elf.elf_link_hash_flags
-     & (ELF_LINK_HASH_REF_DYNAMIC
-       | ELF_LINK_HASH_REF_REGULAR
-       | ELF_LINK_HASH_REF_REGULAR_NONWEAK
-       | ELF_LINK_NON_GOT_REF));
+  mask = (ELF_LINK_HASH_REF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR
+         | ELF_LINK_HASH_REF_REGULAR_NONWEAK | ELF_LINK_NON_GOT_REF);
+  /* If called to transfer flags for a weakdef during processing
+     of elf_adjust_dynamic_symbol, don't copy ELF_LINK_NON_GOT_REF.
+     We clear it ourselves for ELIMINATE_COPY_RELOCS.  */
+  if (ELIMINATE_COPY_RELOCS
+      && eind->elf.root.type != bfd_link_hash_indirect
+      && (edir->elf.elf_link_hash_flags & ELF_LINK_HASH_DYNAMIC_ADJUSTED) != 0)
+    mask &= ~ELF_LINK_NON_GOT_REF;
+
+  edir->elf.elf_link_hash_flags |= eind->elf.elf_link_hash_flags & mask;
 
   /* If we were called to copy over info for a weak sym, that's all.  */
   if (eind->elf.root.type != bfd_link_hash_indirect)
     return;
 
-  /* Copy over got entries.  */
+  /* Copy over got entries that we may have already seen to the
+     symbol which just became indirect.  */
   if (eind->elf.got.glist != NULL)
     {
       if (edir->elf.got.glist != NULL)
@@ -3871,10 +3882,18 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs)
        case R_PPC64_UADDR32:
        case R_PPC64_UADDR64:
        case R_PPC64_TOC:
+         if (h != NULL && !info->shared)
+           /* We may need a copy reloc.  */
+           h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
+
          /* Don't propagate .opd relocs.  */
          if (NO_OPD_RELOCS && opd_sym_map != NULL)
            break;
 
+         /* Don't propagate relocs that the dynamic linker won't relocate.  */
+         if ((sec->flags & SEC_ALLOC) == 0)
+           break;
+
          /* If we are creating a shared library, and this is a reloc
             against a global symbol, or a non PC relative reloc
             against a local symbol, then we need to copy the reloc
@@ -3887,7 +3906,7 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs)
             later (it is never cleared).  In case of a weak definition,
             DEF_REGULAR may be cleared later by a strong definition in
             a shared library.  We account for that possibility below by
-            storing information in the relocs_copied field of the hash
+            storing information in the dyn_relocs field of the hash
             table entry.  A similar situation occurs when creating
             shared libraries and symbol visibility changes render the
             symbol local.
@@ -3898,15 +3917,14 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs)
             symbol.  */
        dodyn:
          if ((info->shared
-              && (sec->flags & SEC_ALLOC) != 0
               && (MUST_BE_DYN_RELOC (r_type)
                   || (h != NULL
                       && (! info->symbolic
                           || h->root.type == bfd_link_hash_defweak
                           || (h->elf_link_hash_flags
                               & ELF_LINK_HASH_DEF_REGULAR) == 0))))
-             || (!info->shared
-                 && (sec->flags & SEC_ALLOC) != 0
+             || (ELIMINATE_COPY_RELOCS
+                 && !info->shared
                  && h != NULL
                  && (h->root.type == bfd_link_hash_defweak
                      || (h->elf_link_hash_flags
@@ -4470,8 +4488,6 @@ ppc64_elf_adjust_dynamic_symbol (info, h)
      struct elf_link_hash_entry *h;
 {
   struct ppc_link_hash_table *htab;
-  struct ppc_link_hash_entry * eh;
-  struct ppc_dyn_relocs *p;
   asection *s;
   unsigned int power_of_two;
 
@@ -4489,15 +4505,13 @@ ppc64_elf_adjust_dynamic_symbol (info, h)
          break;
       if (!((struct ppc_link_hash_entry *) h)->is_func_descriptor
          || ent == NULL
-         || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
-         || (! info->shared
-             && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
-             && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0))
+         || SYMBOL_CALLS_LOCAL (info, h)
+         || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+             && h->root.type == bfd_link_hash_undefweak))
        {
          h->plt.plist = NULL;
          h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
        }
-      return TRUE;
     }
   else
     h->plt.plist = NULL;
@@ -4511,6 +4525,10 @@ ppc64_elf_adjust_dynamic_symbol (info, h)
                  || h->weakdef->root.type == bfd_link_hash_defweak);
       h->root.u.def.section = h->weakdef->root.u.def.section;
       h->root.u.def.value = h->weakdef->root.u.def.value;
+      if (ELIMINATE_COPY_RELOCS)
+       h->elf_link_hash_flags
+         = ((h->elf_link_hash_flags & ~ELF_LINK_NON_GOT_REF)
+            | (h->weakdef->elf_link_hash_flags & ELF_LINK_NON_GOT_REF));
       return TRUE;
     }
 
@@ -4529,20 +4547,26 @@ ppc64_elf_adjust_dynamic_symbol (info, h)
   if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0)
     return TRUE;
 
-  eh = (struct ppc_link_hash_entry *) h;
-  for (p = eh->dyn_relocs; p != NULL; p = p->next)
+  if (ELIMINATE_COPY_RELOCS)
     {
-      s = p->sec->output_section;
-      if (s != NULL && (s->flags & SEC_READONLY) != 0)
-       break;
-    }
+      struct ppc_link_hash_entry * eh;
+      struct ppc_dyn_relocs *p;
 
-  /* If we didn't find any dynamic relocs in read-only sections, then
-     we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
-  if (p == NULL)
-    {
-      h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF;
-      return TRUE;
+      eh = (struct ppc_link_hash_entry *) h;
+      for (p = eh->dyn_relocs; p != NULL; p = p->next)
+       {
+         s = p->sec->output_section;
+         if (s != NULL && (s->flags & SEC_READONLY) != 0)
+           break;
+       }
+
+      /* If we didn't find any dynamic relocs in read-only sections, then
+        we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
+      if (p == NULL)
+       {
+         h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF;
+         return TRUE;
+       }
     }
 
   /* We must allocate the symbol in our .dynbss section, which will
@@ -4847,9 +4871,9 @@ ppc64_elf_edit_opd (obfd, info)
       sym_hashes = elf_sym_hashes (ibfd);
 
       /* Read the relocations.  */
-      relstart = _bfd_elf64_link_read_relocs (ibfd, sec, (PTR) NULL,
-                                             (Elf_Internal_Rela *) NULL,
-                                             info->keep_memory);
+      relstart = _bfd_elf_link_read_relocs (ibfd, sec, (PTR) NULL,
+                                           (Elf_Internal_Rela *) NULL,
+                                           info->keep_memory);
       if (relstart == NULL)
        return FALSE;
 
@@ -5170,9 +5194,9 @@ ppc64_elf_tls_optimize (obfd, info)
            int expecting_tls_get_addr;
 
            /* Read the relocations.  */
-           relstart = _bfd_elf64_link_read_relocs (ibfd, sec, (PTR) NULL,
-                                                   (Elf_Internal_Rela *) NULL,
-                                                   info->keep_memory);
+           relstart = _bfd_elf_link_read_relocs (ibfd, sec, (PTR) NULL,
+                                                 (Elf_Internal_Rela *) NULL,
+                                                 info->keep_memory);
            if (relstart == NULL)
              return FALSE;
 
@@ -5238,10 +5262,10 @@ ppc64_elf_tls_optimize (obfd, info)
                    /* These relocs should never be against a symbol
                       defined in a shared lib.  Leave them alone if
                       that turns out to be the case.  */
+                   htab->tlsld_got.refcount -= 1;
                    if (!is_local)
                      continue;
 
-                   htab->tlsld_got.refcount -= 1;
                    /* LD -> LE */
                    tls_set = 0;
                    tls_clear = TLS_LD;
@@ -5438,9 +5462,9 @@ ppc64_elf_tls_optimize (obfd, info)
    will be called from elflink.h.  If elflink.h doesn't call our
    finish_dynamic_symbol routine, we'll need to do something about
    initializing any .plt and .got entries in ppc64_elf_relocate_section.  */
-#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
+#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \
   ((DYN)                                                               \
-   && ((INFO)->shared                                                  \
+   && ((SHARED)                                                                \
        || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)     \
    && ((H)->dynindx != -1                                              \
        || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
@@ -5471,7 +5495,7 @@ allocate_dynrelocs (h, inf)
 
   if (htab->elf.dynamic_sections_created
       && h->dynindx != -1
-      && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
+      && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
     {
       struct plt_entry *pent;
       bfd_boolean doneone = FALSE;
@@ -5559,7 +5583,8 @@ allocate_dynrelocs (h, inf)
              return FALSE;
          }
 
-       if ((gent->tls_type & TLS_LD) != 0)
+       if ((gent->tls_type & TLS_LD) != 0
+           && !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC))
          {
            gent->got.offset = htab->tlsld_got.offset;
            continue;
@@ -5567,9 +5592,13 @@ allocate_dynrelocs (h, inf)
 
        s = htab->sgot;
        gent->got.offset = s->_raw_size;
-       s->_raw_size += (gent->tls_type & eh->tls_mask & TLS_GD) ? 16 : 8;
+       s->_raw_size
+         += (gent->tls_type & eh->tls_mask & (TLS_GD | TLS_LD)) ? 16 : 8;
        dyn = htab->elf.dynamic_sections_created;
-       if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
+       if ((info->shared
+            || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
+           && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+               || h->root.type != bfd_link_hash_undefweak))
          htab->srelgot->_raw_size
            += (gent->tls_type & eh->tls_mask & TLS_GD
                ? 2 * sizeof (Elf64_External_Rela)
@@ -5589,9 +5618,13 @@ allocate_dynrelocs (h, inf)
 
   if (info->shared)
     {
-      if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
-         && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
-             || info->symbolic))
+      /* Relocs that use pc_count are those that appear on a call insn,
+        or certain REL relocs (see MUST_BE_DYN_RELOC) that can be
+        generated via assembly.  We want calls to protected symbols to
+        resolve directly to the function rather than going via the plt.
+        If people want function pointer comparisons to work as expected
+        then they should avoid writing weird assembly.  */
+      if (SYMBOL_CALLS_LOCAL (info, h))
        {
          struct ppc_dyn_relocs **pp;
 
@@ -5605,8 +5638,14 @@ allocate_dynrelocs (h, inf)
                pp = &p->next;
            }
        }
+
+      /* Also discard relocs on undefined weak syms with non-default
+        visibility.  */
+      if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+         && h->root.type == bfd_link_hash_undefweak)
+       eh->dyn_relocs = NULL;
     }
-  else
+  else if (ELIMINATE_COPY_RELOCS)
     {
       /* For the non-shared case, discard space for relocs against
         symbols which turn out to need copy relocs or are not
@@ -5698,7 +5737,7 @@ ppc64_elf_size_dynamic_sections (output_bfd, info)
   if (htab->elf.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (! info->shared)
+      if (info->executable)
        {
          s = bfd_get_section_by_name (dynobj, ".interp");
          if (s == NULL)
@@ -5897,7 +5936,7 @@ ppc64_elf_size_dynamic_sections (output_bfd, info)
 #define add_dynamic_entry(TAG, VAL) \
   bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
 
-      if (!info->shared)
+      if (info->executable)
        {
          if (!add_dynamic_entry (DT_DEBUG, 0))
            return FALSE;
@@ -6555,9 +6594,9 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size,
 
              /* Get the relocs.  */
              internal_relocs
-               = _bfd_elf64_link_read_relocs (input_bfd, section, NULL,
-                                              (Elf_Internal_Rela *) NULL,
-                                              info->keep_memory);
+               = _bfd_elf_link_read_relocs (input_bfd, section, NULL,
+                                            (Elf_Internal_Rela *) NULL,
+                                            info->keep_memory);
              if (internal_relocs == NULL)
                goto error_ret_free_local;
 
@@ -6961,26 +7000,6 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
     ppc_howto_init ();
 
   htab = ppc_hash_table (info);
-  if ((htab->tlsld_got.offset & 1) == 0)
-    {
-      if (info->shared)
-       {
-         outrel.r_offset = (htab->sgot->output_section->vma
-                            + htab->sgot->output_offset
-                            + htab->tlsld_got.offset);
-         outrel.r_info = ELF64_R_INFO (0, R_PPC64_DTPMOD64);
-         outrel.r_addend = 0;
-
-         loc = htab->srelgot->contents;
-         loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
-         bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
-       }
-      else
-       bfd_put_64 (output_bfd, (bfd_vma) 1,
-                   htab->sgot->contents + htab->tlsld_got.offset);
-
-      htab->tlsld_got.offset |= 1;
-    }
   local_got_ents = elf_local_got_ents (input_bfd);
   TOCstart = elf_gp (output_bfd);
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
@@ -7011,7 +7030,6 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
       r_type = (enum elf_ppc64_reloc_type) ELF64_R_TYPE (rel->r_info);
       r_symndx = ELF64_R_SYM (rel->r_info);
-      r = bfd_reloc_other;
       sym = (Elf_Internal_Sym *) 0;
       sec = (asection *) 0;
       h = (struct elf_link_hash_entry *) 0;
@@ -7088,7 +7106,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
         for the final instruction stream.  */
       tls_mask = 0;
       tls_gd = 0;
-      if (IS_TLS_RELOC (r_type))
+      if (IS_PPC64_TLS_RELOC (r_type))
        {
          if (h != NULL)
            tls_mask = ((struct ppc_link_hash_entry *) h)->tls_mask;
@@ -7566,57 +7584,59 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          {
            /* Relocation is to the entry for this symbol in the global
               offset table.  */
-           struct got_entry *ent;
+           bfd_vma *offp;
            bfd_vma off;
-           unsigned long indx;
+           unsigned long indx = 0;
 
            if (htab->sgot == NULL)
              abort ();
 
-           if (h != NULL)
-             ent = h->got.glist;
+           if (tls_type == (TLS_TLS | TLS_LD)
+               && (h == NULL
+                   || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)))
+             offp = &htab->tlsld_got.offset;
            else
              {
-               if (local_got_ents == NULL)
-                 abort ();
-               ent = local_got_ents[r_symndx];
-             }
-
-           for (; ent != NULL; ent = ent->next)
-             if (ent->addend == rel->r_addend
-                 && ent->tls_type == tls_type)
-               break;
-           if (ent == NULL)
-             abort ();
+               struct got_entry *ent;
 
-           off = ent->got.offset;
-           indx = 0;
-           if (h != NULL)
-             {
-               bfd_boolean dyn = htab->elf.dynamic_sections_created;
-               if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
-                   || (info->shared
-                       && (info->symbolic
-                           || h->dynindx == -1
-                           || (h->elf_link_hash_flags
-                               & ELF_LINK_FORCED_LOCAL))
-                       && (h->elf_link_hash_flags
-                           & ELF_LINK_HASH_DEF_REGULAR)))
-                 /* This is actually a static link, or it is a
-                    -Bsymbolic link and the symbol is defined
-                    locally, or the symbol was forced to be local
-                    because of a version file.  */
-                 ;
+               if (h != NULL)
+                 {
+                   bfd_boolean dyn = htab->elf.dynamic_sections_created;
+                   if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
+                       || (info->shared
+                           && SYMBOL_REFERENCES_LOCAL (info, h)))
+                     /* This is actually a static link, or it is a
+                        -Bsymbolic link and the symbol is defined
+                        locally, or the symbol was forced to be local
+                        because of a version file.  */
+                     ;
+                   else
+                     {
+                       indx = h->dynindx;
+                       unresolved_reloc = FALSE;
+                     }
+                   ent = h->got.glist;
+                 }
                else
                  {
-                   indx = h->dynindx;
-                   unresolved_reloc = FALSE;
+                   if (local_got_ents == NULL)
+                     abort ();
+                   ent = local_got_ents[r_symndx];
                  }
+
+               for (; ent != NULL; ent = ent->next)
+                 if (ent->addend == rel->r_addend
+                     && ent->tls_type == tls_type)
+                   break;
+               if (ent == NULL)
+                 abort ();
+               offp = &ent->got.offset;
              }
 
            /* The offset must always be a multiple of 8.  We use the
               least significant bit to record whether we have already
               processed this entry.  */
+           off = *offp;
            if ((off & 1) != 0)
              off &= ~1;
            else
@@ -7624,22 +7644,30 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                /* Generate relocs for the dynamic linker, except in
                   the case of TLSLD where we'll use one entry per
                   module.  */
+               *offp = off | 1;
                if ((info->shared || indx != 0)
-                   && tls_type != (TLS_TLS | TLS_LD))
+                   && (h == NULL
+                       || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                       || h->root.type != bfd_link_hash_undefweak))
                  {
                    outrel.r_offset = (htab->sgot->output_section->vma
                                       + htab->sgot->output_offset
                                       + off);
-                   if (tls_type == (TLS_TLS | TLS_GD))
+                   if (tls_type & (TLS_LD | TLS_GD))
                      {
-                       outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPMOD64);
                        outrel.r_addend = 0;
-                       loc = htab->srelgot->contents;
-                       loc += (htab->srelgot->reloc_count++
-                               * sizeof (Elf64_External_Rela));
-                       bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
-                       outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPREL64);
-                       outrel.r_offset += 8;
+                       outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPMOD64);
+                       if (tls_type == (TLS_TLS | TLS_GD))
+                         {
+                           loc = htab->srelgot->contents;
+                           loc += (htab->srelgot->reloc_count++
+                                   * sizeof (Elf64_External_Rela));
+                           bfd_elf64_swap_reloca_out (output_bfd,
+                                                      &outrel, loc);
+                           outrel.r_offset += 8;
+                           outrel.r_info
+                             = ELF64_R_INFO (indx, R_PPC64_DTPREL64);
+                         }
                      }
                    else if (tls_type == (TLS_TLS | TLS_DTPREL))
                      outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPREL64);
@@ -7651,7 +7679,11 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                      outrel.r_info = ELF64_R_INFO (indx, R_PPC64_GLOB_DAT);
                    outrel.r_addend = rel->r_addend;
                    if (indx == 0)
-                     outrel.r_addend += relocation;
+                     {
+                       outrel.r_addend += relocation;
+                       if (tls_type & (TLS_GD | TLS_DTPREL | TLS_TPREL))
+                         outrel.r_addend -= htab->tls_sec->vma;
+                     }
                    loc = htab->srelgot->contents;
                    loc += (htab->srelgot->reloc_count++
                            * sizeof (Elf64_External_Rela));
@@ -7660,27 +7692,28 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
                /* Init the .got section contents if we're not
                   emitting a reloc.  */
-               if (!(info->shared || indx != 0)
-                   && tls_type != (TLS_TLS | TLS_LD))
+               else
                  {
-                   relocation += ent->addend;
-                   if (tls_type != 0)
+                   relocation += rel->r_addend;
+                   if (tls_type == (TLS_TLS | TLS_LD))
+                     relocation = 1;
+                   else if (tls_type != 0)
                      {
                        relocation -= htab->tls_sec->vma + DTP_OFFSET;
-                       if ((tls_type & TLS_TPREL) != 0)
+                       if (tls_type == (TLS_TLS | TLS_TPREL))
                          relocation += DTP_OFFSET - TP_OFFSET;
-                     }
 
-                   if ((tls_type & TLS_GD) != 0)
-                     {
-                       bfd_put_64 (output_bfd, relocation,
-                                   htab->sgot->contents + off + 8);
-                       relocation = 1;
+                       if (tls_type == (TLS_TLS | TLS_GD))
+                         {
+                           bfd_put_64 (output_bfd, relocation,
+                                       htab->sgot->contents + off + 8);
+                           relocation = 1;
+                         }
                      }
+
                    bfd_put_64 (output_bfd, relocation,
                                htab->sgot->contents + off);
                  }
-               ent->got.offset |= 1;
              }
 
            if (off >= (bfd_vma) -2)
@@ -7786,6 +7819,11 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          addend -= htab->tls_sec->vma + DTP_OFFSET;
          break;
 
+       case R_PPC64_DTPMOD64:
+         relocation = 1;
+         addend = 0;
+         goto dodyn;
+
        case R_PPC64_TPREL64:
          addend -= htab->tls_sec->vma + TP_OFFSET;
          goto dodyn;
@@ -7796,7 +7834,6 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
          /* Relocations that may need to be propagated if this is a
             dynamic object.  */
-       case R_PPC64_DTPMOD64:
        case R_PPC64_REL30:
        case R_PPC64_REL32:
        case R_PPC64_REL64:
@@ -7835,13 +7872,14 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            break;
 
          if ((info->shared
+              && (h == NULL
+                  || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                  || h->root.type != bfd_link_hash_undefweak)
               && (MUST_BE_DYN_RELOC (r_type)
                   || (h != NULL
-                      && h->dynindx != -1
-                      && (! info->symbolic
-                          || (h->elf_link_hash_flags
-                              & ELF_LINK_HASH_DEF_REGULAR) == 0))))
-             || (!info->shared
+                      && !SYMBOL_CALLS_LOCAL (info, h))))
+             || (ELIMINATE_COPY_RELOCS
+                 && !info->shared
                  && h != NULL
                  && h->dynindx != -1
                  && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
@@ -7874,13 +7912,8 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              if (skip)
                memset (&outrel, 0, sizeof outrel);
              else if (h != NULL
-                      && h->dynindx != -1
-                      && !is_opd
-                      && (!MUST_BE_DYN_RELOC (r_type)
-                          || !info->shared
-                          || !info->symbolic
-                          || (h->elf_link_hash_flags
-                              & ELF_LINK_HASH_DEF_REGULAR) == 0))
+                      && !SYMBOL_REFERENCES_LOCAL (info, h)
+                      && !is_opd)
                outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
              else
                {
@@ -7973,7 +8006,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          /* These ones haven't been implemented yet.  */
 
          (*_bfd_error_handler)
-           (_("%s: Relocation %s is not supported for symbol %s."),
+           (_("%s: relocation %s is not supported for symbol %s."),
             bfd_archive_filename (input_bfd),
             ppc64_elf_howto_table[(int) r_type]->name, sym_name);
 
@@ -8015,8 +8048,9 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
             'sec' would be NULL, and we should leave the symbol
             alone (it will be set to zero elsewhere in the link).  */
          if (sec != NULL)
-           /* Add 0x10000 if sign bit in 0:15 is set.  */
-           addend += ((relocation + addend) & 0x8000) << 1;
+           /* Add 0x10000 if sign bit in 0:15 is set.
+              Bits 0:15 are not used.  */
+           addend += 0x8000;
          break;
 
        case R_PPC64_ADDR16_DS:
@@ -8087,10 +8121,11 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
               && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
        {
          (*_bfd_error_handler)
-           (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
+           (_("%s(%s+0x%lx): unresolvable %s relocation against symbol `%s'"),
             bfd_archive_filename (input_bfd),
             bfd_get_section_name (input_bfd, input_section),
             (long) rel->r_offset,
+            ppc64_elf_howto_table[(int) r_type]->name,
             h->root.root.string);
          ret = FALSE;
        }
@@ -8105,11 +8140,14 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
       if (r != bfd_reloc_ok)
        {
-         const char *name;
-
-         if (h != NULL)
+         if (sym_name == NULL)
+           sym_name = "(null)";
+         if (r == bfd_reloc_overflow)
            {
-             if (h->root.type == bfd_link_hash_undefweak
+             if (warned)
+               continue;
+             if (h != NULL
+                 && h->root.type == bfd_link_hash_undefweak
                  && ppc64_elf_howto_table[(int) r_type]->pc_relative)
                {
                  /* Assume this is a call protected by other code that
@@ -8121,31 +8159,21 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  continue;
                }
 
-             name = h->root.root.string;
-           }
-         else
-           {
-             name = bfd_elf_local_sym_name (input_bfd, sym);
-             if (name == NULL)
-               continue;
-           }
-
-         if (r == bfd_reloc_overflow)
-           {
-             if (warned)
-               continue;
              if (!((*info->callbacks->reloc_overflow)
-                   (info, name, ppc64_elf_howto_table[(int) r_type]->name,
+                   (info, sym_name, ppc64_elf_howto_table[(int) r_type]->name,
                     rel->r_addend, input_bfd, input_section, rel->r_offset)))
                return FALSE;
            }
          else
            {
              (*_bfd_error_handler)
-               (_("%s(%s+0x%lx): reloc against `%s': error %d"),
+               (_("%s(%s+0x%lx): %s reloc against `%s': error %d"),
                 bfd_archive_filename (input_bfd),
                 bfd_get_section_name (input_bfd, input_section),
-                (long) rel->r_offset, name, (int) r);
+                (long) rel->r_offset,
+                ppc64_elf_howto_table[(int) r_type]->name,
+                sym_name,
+                (int) r);
              ret = FALSE;
            }
        }
This page took 0.036929 seconds and 4 git commands to generate.