gdb/
[binutils-gdb.git] / bfd / elf64-ppc.c
index 33b26cb46e183bceb8843776fa4ebd54da1ea792..ffd37dd63fd3e9cd5298c84c9f24efaf2c3206d2 100644 (file)
@@ -2546,10 +2546,10 @@ struct got_entry
 
   /* Zero for non-tls entries, or TLS_TLS and one of TLS_GD, TLS_LD,
      TLS_TPREL or TLS_DTPREL for tls entries.  */
-  char tls_type;
+  unsigned char tls_type;
 
   /* Non-zero if got.ent points to real entry.  */
-  char is_indirect;
+  unsigned char is_indirect;
 
   /* Reference count until size_dynamic_sections, GOT offset thereafter.  */
   union
@@ -2592,6 +2592,10 @@ struct ppc64_elf_obj_tdata
 
   /* A copy of relocs before they are modified for --emit-relocs.  */
   Elf_Internal_Rela *opd_relocs;
+
+  /* Nonzero if this bfd has small toc/got relocs, ie. that expect
+     the reloc to be in the range -32768 to 32767.  */
+  unsigned int has_small_toc_reloc;
 };
 
 #define ppc64_elf_tdata(bfd) \
@@ -3698,7 +3702,7 @@ struct ppc_link_hash_entry
 #define TLS_EXPLICIT   32      /* Marks TOC section TLS relocs. */
 #define TLS_TPRELGD    64      /* TPREL reloc resulting from GD->IE. */
 #define PLT_IFUNC      128     /* STT_GNU_IFUNC.  */
-  char tls_mask;
+  unsigned char tls_mask;
 };
 
 /* ppc64 ELF linker hash table.  */
@@ -3781,6 +3785,7 @@ struct ppc_link_hash_table
   unsigned int no_tls_get_addr_opt:1;
 
   /* Support for multiple toc sections.  */
+  unsigned int do_multi_toc:1;
   unsigned int multi_toc_needed:1;
   unsigned int second_toc_pass:1;
 
@@ -3799,9 +3804,22 @@ struct ppc_link_hash_table
 
 /* Rename some of the generic section flags to better document how they
    are used here.  */
-#define has_toc_reloc has_gp_reloc
-#define makes_toc_func_call need_finalize_relax
-#define call_check_in_progress reloc_done
+
+/* Nonzero if this section has TLS related relocations.  */
+#define has_tls_reloc sec_flg0
+
+/* Nonzero if this section has a call to __tls_get_addr.  */
+#define has_tls_get_addr_call sec_flg1
+
+/* Nonzero if this section has any toc or got relocs.  */
+#define has_toc_reloc sec_flg2
+
+/* Nonzero if this section has a call to another section that uses
+   the toc or got.  */
+#define makes_toc_func_call sec_flg3
+
+/* Recursion protection when determining above flag.  */
+#define call_check_in_progress sec_flg4
 
 /* Get the ppc64 ELF linker hash table from a link_info structure.  */
 
@@ -4539,7 +4557,7 @@ make_fdh (struct bfd_link_info *info,
    function type.  */
 
 static bfd_boolean
-ppc64_elf_add_symbol_hook (bfd *ibfd ATTRIBUTE_UNUSED,
+ppc64_elf_add_symbol_hook (bfd *ibfd,
                           struct bfd_link_info *info,
                           Elf_Internal_Sym *isym,
                           const char **name ATTRIBUTE_UNUSED,
@@ -4548,7 +4566,10 @@ ppc64_elf_add_symbol_hook (bfd *ibfd ATTRIBUTE_UNUSED,
                           bfd_vma *value ATTRIBUTE_UNUSED)
 {
   if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
-    elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
+    {
+      if ((ibfd->flags & DYNAMIC) == 0)
+       elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
+    }
   else if (ELF_ST_TYPE (isym->st_info) == STT_FUNC)
     ;
   else if (*sec != NULL
@@ -4727,7 +4748,7 @@ update_local_sym_info (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
 {
   struct got_entry **local_got_ents = elf_local_got_ents (abfd);
   struct plt_entry **local_plt;
-  char *local_got_tls_masks;
+  unsigned char *local_got_tls_masks;
 
   if (local_got_ents == NULL)
     {
@@ -4769,7 +4790,7 @@ update_local_sym_info (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
     }
 
   local_plt = (struct plt_entry **) (local_got_ents + symtab_hdr->sh_info);
-  local_got_tls_masks = (char *) (local_plt + symtab_hdr->sh_info);
+  local_got_tls_masks = (unsigned char *) (local_plt + symtab_hdr->sh_info);
   local_got_tls_masks[r_symndx] |= tls_type;
 
   return local_plt + r_symndx;
@@ -4997,6 +5018,17 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_GOT16_LO_DS:
          /* This symbol requires a global offset table entry.  */
          sec->has_toc_reloc = 1;
+         if (r_type == R_PPC64_GOT_TLSLD16
+             || r_type == R_PPC64_GOT_TLSGD16
+             || r_type == R_PPC64_GOT_TPREL16_DS
+             || r_type == R_PPC64_GOT_DTPREL16_DS
+             || r_type == R_PPC64_GOT16
+             || r_type == R_PPC64_GOT16_DS)
+           {
+             htab->do_multi_toc = 1;
+             ppc64_elf_tdata (abfd)->has_small_toc_reloc = 1;
+           }
+
          if (ppc64_elf_tdata (abfd)->got == NULL
              && !create_got_section (abfd, info))
            return FALSE;
@@ -5093,10 +5125,12 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          break;
 
        case R_PPC64_TOC16:
+       case R_PPC64_TOC16_DS:
+         htab->do_multi_toc = 1;
+         ppc64_elf_tdata (abfd)->has_small_toc_reloc = 1;
        case R_PPC64_TOC16_LO:
        case R_PPC64_TOC16_HI:
        case R_PPC64_TOC16_HA:
-       case R_PPC64_TOC16_DS:
        case R_PPC64_TOC16_LO_DS:
          sec->has_toc_reloc = 1;
          break;
@@ -5774,7 +5808,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
       unsigned long r_symndx;
       enum elf_ppc64_reloc_type r_type;
       struct elf_link_hash_entry *h = NULL;
-      char tls_type = 0;
+      unsigned char tls_type = 0;
 
       r_symndx = ELF64_R_SYM (rel->r_info);
       r_type = ELF64_R_TYPE (rel->r_info);
@@ -5809,7 +5843,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
            {
              struct plt_entry **local_plt = (struct plt_entry **)
                (local_got_ents + symtab_hdr->sh_info);
-             char *local_got_tls_masks = (char *)
+             unsigned char *local_got_tls_masks = (unsigned char *)
                (local_plt + symtab_hdr->sh_info);
              if ((local_got_tls_masks[r_symndx] & PLT_IFUNC) != 0)
                ifunc = local_plt + r_symndx;
@@ -6536,7 +6570,7 @@ static bfd_boolean
 get_sym_h (struct elf_link_hash_entry **hp,
           Elf_Internal_Sym **symp,
           asection **symsecp,
-          char **tls_maskp,
+          unsigned char **tls_maskp,
           Elf_Internal_Sym **locsymsp,
           unsigned long r_symndx,
           bfd *ibfd)
@@ -6604,7 +6638,7 @@ get_sym_h (struct elf_link_hash_entry **hp,
       if (tls_maskp != NULL)
        {
          struct got_entry **lgot_ents;
-         char *tls_mask;
+         unsigned char *tls_mask;
 
          tls_mask = NULL;
          lgot_ents = elf_local_got_ents (ibfd);
@@ -6612,7 +6646,7 @@ get_sym_h (struct elf_link_hash_entry **hp,
            {
              struct plt_entry **local_plt = (struct plt_entry **)
                (lgot_ents + symtab_hdr->sh_info);
-             char *lgot_masks = (char *)
+             unsigned char *lgot_masks = (unsigned char *)
                (local_plt + symtab_hdr->sh_info);
              tls_mask = &lgot_masks[r_symndx];
            }
@@ -6627,7 +6661,7 @@ get_sym_h (struct elf_link_hash_entry **hp,
    type suitable for optimization, and 1 otherwise.  */
 
 static int
-get_tls_mask (char **tls_maskp,
+get_tls_mask (unsigned char **tls_maskp,
              unsigned long *toc_symndx,
              bfd_vma *toc_addend,
              Elf_Internal_Sym **locsymsp,
@@ -6870,8 +6904,7 @@ dec_dynrel_count (bfd_vma r_info,
    applications.  */
 
 bfd_boolean
-ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
-                   bfd_boolean non_overlapping)
+ppc64_elf_edit_opd (struct bfd_link_info *info, bfd_boolean non_overlapping)
 {
   bfd *ibfd;
   bfd_boolean some_edited = FALSE;
@@ -7041,7 +7074,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
          new_contents = NULL;
          amt = sec->size * sizeof (long) / 8;
          opd = &ppc64_elf_section_data (sec)->u.opd;
-         opd->adjust = bfd_zalloc (obfd, amt);
+         opd->adjust = bfd_zalloc (sec->owner, amt);
          if (opd->adjust == NULL)
            return FALSE;
          ppc64_elf_section_data (sec)->sec_type = sec_opd;
@@ -7272,9 +7305,9 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
 /* Set htab->tls_get_addr and call the generic ELF tls_setup function.  */
 
 asection *
-ppc64_elf_tls_setup (bfd *obfd,
-                    struct bfd_link_info *info,
-                    int no_tls_get_addr_opt)
+ppc64_elf_tls_setup (struct bfd_link_info *info,
+                    int no_tls_get_addr_opt,
+                    int *no_multi_toc)
 {
   struct ppc_link_hash_table *htab;
 
@@ -7282,6 +7315,11 @@ ppc64_elf_tls_setup (bfd *obfd,
   if (htab == NULL)
     return NULL;
 
+  if (*no_multi_toc)
+    htab->do_multi_toc = 0;
+  else if (!htab->do_multi_toc)
+    *no_multi_toc = 1;
+
   htab->tls_get_addr = ((struct ppc_link_hash_entry *)
                        elf_link_hash_lookup (&htab->elf, ".__tls_get_addr",
                                              FALSE, FALSE, TRUE));
@@ -7362,7 +7400,7 @@ ppc64_elf_tls_setup (bfd *obfd,
        no_tls_get_addr_opt = TRUE;
     }
   htab->no_tls_get_addr_opt = no_tls_get_addr_opt;
-  return _bfd_elf_tls_setup (obfd, info);
+  return _bfd_elf_tls_setup (info->output_bfd, info);
 }
 
 /* Return TRUE iff REL is a branch reloc with a global symbol matching
@@ -7399,7 +7437,7 @@ branch_reloc_hash_match (const bfd *ibfd,
    dynamic relocations.  */
 
 bfd_boolean
-ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
+ppc64_elf_tls_optimize (struct bfd_link_info *info)
 {
   bfd *ibfd;
   asection *sec;
@@ -7445,8 +7483,8 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
                  struct elf_link_hash_entry *h;
                  Elf_Internal_Sym *sym;
                  asection *sym_sec;
-                 char *tls_mask;
-                 char tls_set, tls_clear, tls_type = 0;
+                 unsigned char *tls_mask;
+                 unsigned char tls_set, tls_clear, tls_type = 0;
                  bfd_vma value;
                  bfd_boolean ok_tprel, is_local;
                  long toc_ref_index = 0;
@@ -7659,7 +7697,7 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
                          if (expecting_tls_get_addr == 2)
                            {
                              /* Check for toc tls entries.  */
-                             char *toc_tls;
+                             unsigned char *toc_tls;
                              int retval;
 
                              retval = get_tls_mask (&toc_tls, NULL, NULL,
@@ -7839,7 +7877,7 @@ adjust_toc_syms (struct elf_link_hash_entry *h, void *inf)
    unused .toc entries.  */
 
 bfd_boolean
-ppc64_elf_edit_toc (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
+ppc64_elf_edit_toc (struct bfd_link_info *info)
 {
   bfd *ibfd;
   struct adjust_toc_info toc_inf;
@@ -8271,6 +8309,26 @@ allocate_got (struct elf_link_hash_entry *h,
     }
 }
 
+/* This function merges got entries in the same toc group.  */
+
+static void
+merge_got_entries (struct got_entry **pent)
+{
+  struct got_entry *ent, *ent2;
+
+  for (ent = *pent; ent != NULL; ent = ent->next)
+    if (!ent->is_indirect)
+      for (ent2 = ent->next; ent2 != NULL; ent2 = ent2->next)
+       if (!ent2->is_indirect
+           && ent2->addend == ent->addend
+           && ent2->tls_type == ent->tls_type
+           && elf_gp (ent2->owner) == elf_gp (ent->owner))
+         {
+           ent2->is_indirect = TRUE;
+           ent2->got.ent = ent;
+         }
+}
+
 /* Allocate space in .plt, .got and associated reloc sections for
    dynamic relocs.  */
 
@@ -8282,7 +8340,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   asection *s;
   struct ppc_link_hash_entry *eh;
   struct ppc_dyn_relocs *p;
-  struct got_entry *gent;
+  struct got_entry **pgent, *gent;
 
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
@@ -8381,8 +8439,30 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
            gent->tls_type = TLS_TLS | TLS_TPREL;
        }
 
-  for (gent = h->got.glist; gent != NULL; gent = gent->next)
+  /* Remove any list entry that won't generate a word in the GOT before
+     we call merge_got_entries.  Otherwise we risk merging to empty
+     entries.  */
+  pgent = &h->got.glist;
+  while ((gent = *pgent) != NULL)
     if (gent->got.refcount > 0)
+      {
+       if ((gent->tls_type & TLS_LD) != 0
+           && !h->def_dynamic)
+         {
+           ppc64_tlsld_got (gent->owner)->got.refcount += 1;
+           *pgent = gent->next;
+         }
+       else
+         pgent = &gent->next;
+      }
+    else
+      *pgent = gent->next;
+
+  if (!htab->do_multi_toc)
+    merge_got_entries (&h->got.glist);
+
+  for (gent = h->got.glist; gent != NULL; gent = gent->next)
+    if (!gent->is_indirect)
       {
        /* Make sure this symbol is output as a dynamic symbol.
           Undefined weak syms won't yet be marked as dynamic,
@@ -8396,21 +8476,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
              return FALSE;
          }
 
-       if ((gent->tls_type & TLS_LD) != 0
-           && !h->def_dynamic)
-         {
-           ppc64_tlsld_got (gent->owner)->got.refcount += 1;
-           gent->got.offset = (bfd_vma) -1;
-           continue;
-         }
-
        if (!is_ppc64_elf (gent->owner))
          abort ();
 
        allocate_got (h, info, gent);
       }
-    else
-      gent->got.offset = (bfd_vma) -1;
 
   if (eh->dyn_relocs == NULL
       || (!htab->elf.dynamic_sections_created
@@ -8550,6 +8620,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   asection *s;
   bfd_boolean relocs;
   bfd *ibfd;
+  struct got_entry *first_tlsld;
 
   htab = ppc_hash_table (info);
   if (htab == NULL)
@@ -8580,7 +8651,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       struct got_entry **end_lgot_ents;
       struct plt_entry **local_plt;
       struct plt_entry **end_local_plt;
-      char *lgot_masks;
+      unsigned char *lgot_masks;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
@@ -8623,20 +8694,21 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       end_lgot_ents = lgot_ents + locsymcount;
       local_plt = (struct plt_entry **) end_lgot_ents;
       end_local_plt = local_plt + locsymcount;
-      lgot_masks = (char *) end_local_plt;
+      lgot_masks = (unsigned char *) end_local_plt;
       s = ppc64_elf_tdata (ibfd)->got;
       srel = ppc64_elf_tdata (ibfd)->relgot;
       for (; lgot_ents < end_lgot_ents; ++lgot_ents, ++lgot_masks)
        {
-         struct got_entry *ent;
+         struct got_entry **pent, *ent;
 
-         for (ent = *lgot_ents; ent != NULL; ent = ent->next)
+         pent = lgot_ents;
+         while ((ent = *pent) != NULL)
            if (ent->got.refcount > 0)
              {
                if ((ent->tls_type & *lgot_masks & TLS_LD) != 0)
                  {
                    ppc64_tlsld_got (ibfd)->got.refcount += 1;
-                   ent->got.offset = (bfd_vma) -1;
+                   *pent = ent->next;
                  }
                else
                  {
@@ -8654,10 +8726,11 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                        htab->got_reli_size
                          += num * sizeof (Elf64_External_Rela);
                      }
+                   pent = &ent->next;
                  }
              }
            else
-             ent->got.offset = (bfd_vma) -1;
+             *pent = ent->next;
        }
 
       /* Allocate space for calls to local STT_GNU_IFUNC syms in .iplt.  */
@@ -8683,25 +8756,39 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
 
+  first_tlsld = NULL;
   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
     {
+      struct got_entry *ent;
+
       if (!is_ppc64_elf (ibfd))
        continue;
 
-      if (ppc64_tlsld_got (ibfd)->got.refcount > 0)
+      ent = ppc64_tlsld_got (ibfd);
+      if (ent->got.refcount > 0)
        {
-         s = ppc64_elf_tdata (ibfd)->got;
-         ppc64_tlsld_got (ibfd)->got.offset = s->size;
-         ppc64_tlsld_got (ibfd)->owner = ibfd;
-         s->size += 16;
-         if (info->shared)
+         if (!htab->do_multi_toc && first_tlsld != NULL)
            {
-             asection *srel = ppc64_elf_tdata (ibfd)->relgot;
-             srel->size += sizeof (Elf64_External_Rela);
+             ent->is_indirect = TRUE;
+             ent->got.ent = first_tlsld;
+           }
+         else
+           {
+             if (first_tlsld == NULL)
+               first_tlsld = ent;
+             s = ppc64_elf_tdata (ibfd)->got;
+             ent->got.offset = s->size;
+             ent->owner = ibfd;
+             s->size += 16;
+             if (info->shared)
+               {
+                 asection *srel = ppc64_elf_tdata (ibfd)->relgot;
+                 srel->size += sizeof (Elf64_External_Rela);
+               }
            }
        }
       else
-       ppc64_tlsld_got (ibfd)->got.offset = (bfd_vma) -1;
+       ent->got.offset = (bfd_vma) -1;
     }
 
   /* We now have determined the sizes of the various dynamic sections.
@@ -9751,7 +9838,7 @@ bfd_boolean
 ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
 {
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
-  bfd_vma addr, off;
+  bfd_vma addr, off, limit;
 
   if (htab == NULL)
     return FALSE;
@@ -9767,7 +9854,10 @@ ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
 
       addr = isec->output_offset + isec->output_section->vma;
       off = addr - htab->toc_curr;
-      if (off + isec->size > 0x10000)
+      limit = 0x80008000;
+      if (ppc64_elf_tdata (isec->owner)->has_small_toc_reloc)
+       limit = 0x10000;
+      if (off + isec->size > limit)
        {
          addr = (htab->toc_first_sec->output_offset
                  + htab->toc_first_sec->output_section->vma);
@@ -9813,38 +9903,6 @@ ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
   return TRUE;
 }
 
-/* This function removes unneeded got entries (those with got.offset == -1)
-   and merges entries in the same toc group.  */
-
-static void
-merge_got_entries (struct got_entry **pent)
-{
-  struct got_entry *ent, *ent2;
-
-  while ((ent = *pent) != NULL)
-    {
-      if (!ent->is_indirect)
-       {
-         if (ent->got.offset == (bfd_vma) -1)
-           {
-             *pent = ent->next;
-             continue;
-           }
-         for (ent2 = ent->next; ent2 != NULL; ent2 = ent2->next)
-           if (!ent2->is_indirect
-               && ent2->got.offset != (bfd_vma) -1
-               && ent2->addend == ent->addend
-               && ent2->tls_type == ent->tls_type
-               && elf_gp (ent2->owner) == elf_gp (ent->owner))
-             {
-               ent2->is_indirect = TRUE;
-               ent2->got.ent = ent;
-             }
-       }
-      pent = &ent->next;
-    }
-}
-
 /* Called via elf_link_hash_traverse to merge GOT entries for global
    symbol H.  */
 
@@ -9895,30 +9953,10 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info)
 
   htab->multi_toc_needed = htab->toc_curr != elf_gp (info->output_bfd);
 
-  /* Merge local got entries within a toc group.  */
-  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
-    {
-      struct got_entry **lgot_ents;
-      struct got_entry **end_lgot_ents;
-      Elf_Internal_Shdr *symtab_hdr;
-      bfd_size_type locsymcount;
-
-      if (!is_ppc64_elf (ibfd))
-       continue;
-
-      lgot_ents = elf_local_got_ents (ibfd);
-      if (!lgot_ents)
-       continue;
-
-      symtab_hdr = &elf_symtab_hdr (ibfd);
-      locsymcount = symtab_hdr->sh_info;
-      end_lgot_ents = lgot_ents + locsymcount;
-
-      for (; lgot_ents < end_lgot_ents; ++lgot_ents)
-       merge_got_entries (lgot_ents);
-    }
+  if (!htab->do_multi_toc)
+    return FALSE;
 
-  /* And the same for global sym got entries.  */
+  /* Merge global sym got entries within a toc group.  */
   elf_link_hash_traverse (&htab->elf, merge_global_got, info);
 
   /* And tlsld_got.  */
@@ -9981,7 +10019,7 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info)
       struct got_entry **end_lgot_ents;
       struct plt_entry **local_plt;
       struct plt_entry **end_local_plt;
-      char *lgot_masks;
+      unsigned char *lgot_masks;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *s, *srel;
@@ -9998,7 +10036,7 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info)
       end_lgot_ents = lgot_ents + locsymcount;
       local_plt = (struct plt_entry **) end_lgot_ents;
       end_local_plt = local_plt + locsymcount;
-      lgot_masks = (char *) end_local_plt;
+      lgot_masks = (unsigned char *) end_local_plt;
       s = ppc64_elf_tdata (ibfd)->got;
       srel = ppc64_elf_tdata (ibfd)->relgot;
       for (; lgot_ents < end_lgot_ents; ++lgot_ents, ++lgot_masks)
@@ -10006,23 +10044,22 @@ ppc64_elf_layout_multitoc (struct bfd_link_info *info)
          struct got_entry *ent;
 
          for (ent = *lgot_ents; ent != NULL; ent = ent->next)
-           if (!ent->is_indirect)
-             {
-               unsigned int num = 1;
-               ent->got.offset = s->size;
-               if ((ent->tls_type & *lgot_masks & TLS_GD) != 0)
-                 num = 2;
-               s->size += num * 8;
-               if (info->shared)
-                 srel->size += num * sizeof (Elf64_External_Rela);
-               else if ((*lgot_masks & PLT_IFUNC) != 0)
-                 {
-                   htab->reliplt->size
-                     += num * sizeof (Elf64_External_Rela);
-                   htab->got_reli_size
-                     += num * sizeof (Elf64_External_Rela);
-                 }
-             }
+           {
+             unsigned int num = 1;
+             ent->got.offset = s->size;
+             if ((ent->tls_type & *lgot_masks & TLS_GD) != 0)
+               num = 2;
+             s->size += num * 8;
+             if (info->shared)
+               srel->size += num * sizeof (Elf64_External_Rela);
+             else if ((*lgot_masks & PLT_IFUNC) != 0)
+               {
+                 htab->reliplt->size
+                   += num * sizeof (Elf64_External_Rela);
+                 htab->got_reli_size
+                   += num * sizeof (Elf64_External_Rela);
+               }
+           }
        }
     }
 
@@ -10700,7 +10737,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size)
                      && irela != internal_relocs)
                    {
                      /* Get tls info.  */
-                     char *tls_mask;
+                     unsigned char *tls_mask;
 
                      if (!get_tls_mask (&tls_mask, NULL, NULL, &local_syms,
                                         irela - 1, input_bfd))
@@ -11213,8 +11250,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
       const char *sym_name;
       unsigned long r_symndx, toc_symndx;
       bfd_vma toc_addend;
-      char tls_mask, tls_gd, tls_type;
-      char sym_type;
+      unsigned char tls_mask, tls_gd, tls_type;
+      unsigned char sym_type;
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_boolean warned;
@@ -11312,7 +11349,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        {
          struct plt_entry **local_plt = (struct plt_entry **)
            (local_got_ents + symtab_hdr->sh_info);
-         char *lgot_masks = (char *)
+         unsigned char *lgot_masks = (unsigned char *)
            (local_plt + symtab_hdr->sh_info);
          tls_mask = lgot_masks[r_symndx];
        }
@@ -11322,7 +11359,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
              || r_type == R_PPC64_TLSLD))
        {
          /* Check for toc tls entries.  */
-         char *toc_tls;
+         unsigned char *toc_tls;
 
          if (!get_tls_mask (&toc_tls, &toc_symndx, &toc_addend,
                             &local_syms, rel, input_bfd))
@@ -11386,7 +11423,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_TOC16_LO_DS:
          {
            /* Check for toc tls entries.  */
-           char *toc_tls;
+           unsigned char *toc_tls;
            int retval;
 
            retval = get_tls_mask (&toc_tls, &toc_symndx, &toc_addend,