ppc64 constify
[deliverable/binutils-gdb.git] / bfd / elf32-ppc.c
index 0cb7f67504d4d4f56a4272f37d65f4f604a0f12c..66265ef6009ef69d2450449ea1b9ac861baa58b7 100644 (file)
@@ -2195,9 +2195,6 @@ struct ppc_elf_link_hash_table
   /* The type of PLT we have chosen to use.  */
   enum ppc_elf_plt_type plt_type;
 
-  /* True if the target system is VxWorks.  */
-  unsigned int is_vxworks:1;
-
   /* Whether there exist local gnu indirect function resolvers,
      referenced by dynamic relocations.  */
   unsigned int local_ifunc_resolver:1;
@@ -2215,9 +2212,6 @@ struct ppc_elf_link_hash_table
   int plt_slot_size;
   /* The size of the first PLT entry.  */
   int plt_initial_entry_size;
-
-  /* Small local sym cache.  */
-  struct sym_cache sym_cache;
 };
 
 /* Rename some of the generic section flags to better document how they
@@ -2236,8 +2230,9 @@ struct ppc_elf_link_hash_table
 /* Get the PPC ELF linker hash table from a link_info structure.  */
 
 #define ppc_elf_hash_table(p) \
-  (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
-  == PPC32_ELF_DATA ? ((struct ppc_elf_link_hash_table *) ((p)->hash)) : NULL)
+  ((is_elf_hash_table ((p)->hash)                                      \
+    && elf_hash_table_id (elf_hash_table (p)) == PPC32_ELF_DATA)       \
+   ? (struct ppc_elf_link_hash_table *) (p)->hash : NULL)
 
 /* Create an entry in a PPC ELF linker hash table.  */
 
@@ -2335,7 +2330,7 @@ ppc_elf_create_got (bfd *abfd, struct bfd_link_info *info)
     return FALSE;
 
   htab = ppc_elf_hash_table (info);
-  if (!htab->is_vxworks)
+  if (htab->elf.target_os != is_vxworks)
     {
       /* The powerpc .got has a blrl instruction in it.  Mark it
         executable.  */
@@ -2495,7 +2490,7 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
        return FALSE;
     }
 
-  if (htab->is_vxworks
+  if (htab->elf.target_os == is_vxworks
       && !elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2))
     return FALSE;
 
@@ -2635,7 +2630,7 @@ ppc_elf_add_symbol_hook (bfd *abfd,
       htab = ppc_elf_hash_table (info);
       if (htab->sbss == NULL)
        {
-         flagword flags = SEC_IS_COMMON | SEC_LINKER_CREATED;
+         flagword flags = SEC_IS_COMMON | SEC_SMALL_DATA | SEC_LINKER_CREATED;
 
          if (!htab->elf.dynobj)
            htab->elf.dynobj = abfd;
@@ -2888,15 +2883,6 @@ ppc_elf_check_relocs (bfd *abfd,
   if (bfd_link_relocatable (info))
     return TRUE;
 
-  /* Don't do anything special with non-loaded, non-alloced sections.
-     In particular, any relocs in such sections should not affect GOT
-     and PLT reference counting (ie. we don't allow them to create GOT
-     or PLT entries), there's no possibility or desire to optimize TLS
-     relocs, and there's not much point in propagating relocs to shared
-     libs that the dynamic linker won't relocate.  */
-  if ((sec->flags & SEC_ALLOC) == 0)
-    return TRUE;
-
 #ifdef DEBUG
   _bfd_error_handler ("ppc_elf_check_relocs called for section %pA in %pB",
                      sec, abfd);
@@ -2962,9 +2948,9 @@ ppc_elf_check_relocs (bfd *abfd,
       tls_type = 0;
       r_type = ELF32_R_TYPE (rel->r_info);
       ifunc = NULL;
-      if (h == NULL && !htab->is_vxworks)
+      if (h == NULL && htab->elf.target_os != is_vxworks)
        {
-         Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+         Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
                                                          abfd, r_symndx);
          if (isym == NULL)
            return FALSE;
@@ -3001,7 +2987,7 @@ ppc_elf_check_relocs (bfd *abfd,
            }
        }
 
-      if (!htab->is_vxworks
+      if (htab->elf.target_os != is_vxworks
          && is_branch_reloc (r_type)
          && h != NULL
          && h == tga)
@@ -3316,12 +3302,14 @@ ppc_elf_check_relocs (bfd *abfd,
            return FALSE;
          break;
 
+       case R_PPC_TPREL16_HI:
+       case R_PPC_TPREL16_HA:
+         sec->has_tls_reloc = 1;
+         /* Fall through.  */
          /* We shouldn't really be seeing TPREL32.  */
        case R_PPC_TPREL32:
        case R_PPC_TPREL16:
        case R_PPC_TPREL16_LO:
-       case R_PPC_TPREL16_HI:
-       case R_PPC_TPREL16_HA:
          if (bfd_link_dll (info))
            info->flags |= DF_STATIC_TLS;
          goto dodyn;
@@ -3347,7 +3335,7 @@ ppc_elf_check_relocs (bfd *abfd,
              asection *s;
              Elf_Internal_Sym *isym;
 
-             isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+             isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
                                            abfd, r_symndx);
              if (isym == NULL)
                return FALSE;
@@ -3507,7 +3495,7 @@ ppc_elf_check_relocs (bfd *abfd,
                  void *vpp;
                  Elf_Internal_Sym *isym;
 
-                 isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+                 isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
                                                abfd, r_symndx);
                  if (isym == NULL)
                    return FALSE;
@@ -4431,6 +4419,8 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED,
   if (htab == NULL)
     return FALSE;
 
+  htab->do_tls_opt = 1;
+
   /* Make two passes through the relocs.  First time check that tls
      relocs involved in setting up a tls_get_addr call are indeed
      followed by such a call.  If they are not, don't do any tls
@@ -4596,6 +4586,37 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED,
                      tls_clear = 0;
                      break;
 
+                   case R_PPC_TPREL16_HA:
+                     if (pass == 0)
+                       {
+                         unsigned char buf[4];
+                         unsigned int insn;
+                         bfd_vma off = rel->r_offset & ~3;
+                         if (!bfd_get_section_contents (ibfd, sec, buf,
+                                                        off, 4))
+                           {
+                             if (elf_section_data (sec)->relocs != relstart)
+                               free (relstart);
+                             return FALSE;
+                           }
+                         insn = bfd_get_32 (ibfd, buf);
+                         /* addis rt,2,imm */
+                         if ((insn & ((0x3fu << 26) | 0x1f << 16))
+                             != ((15u << 26) | (2 << 16)))
+                           {
+                             /* xgettext:c-format */
+                             info->callbacks->minfo
+                               (_("%H: warning: %s unexpected insn %#x.\n"),
+                                ibfd, sec, off, "R_PPC_TPREL16_HA", insn);
+                             htab->do_tls_opt = 0;
+                           }
+                       }
+                     continue;
+
+                   case R_PPC_TPREL16_HI:
+                     htab->do_tls_opt = 0;
+                     continue;
+
                    default:
                      continue;
                    }
@@ -4690,7 +4711,6 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED,
                free (relstart);
            }
       }
-  htab->do_tls_opt = 1;
   return TRUE;
 }
 \f
@@ -4807,7 +4827,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
               || (h->non_got_ref
                   && !h->ref_regular_nonweak
                   && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)))
-             && !htab->is_vxworks
+             && htab->elf.target_os != is_vxworks
              && !ppc_elf_hash_entry (h)->has_sda_refs
              && !_bfd_elf_readonly_dynrelocs (h))
            {
@@ -4893,7 +4913,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       executable.  */
   if (ELIMINATE_COPY_RELOCS
       && !ppc_elf_hash_entry (h)->has_sda_refs
-      && !htab->is_vxworks
+      && htab->elf.target_os != is_vxworks
       && !h->def_regular
       && !alias_readonly_dynrelocs (h))
     return TRUE;
@@ -5190,7 +5210,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
            }
        }
 
-      if (htab->is_vxworks)
+      if (htab->elf.target_os == is_vxworks)
        {
          struct elf_dyn_relocs **pp;
 
@@ -5504,7 +5524,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
                     linker script /DISCARD/, so we'll be discarding
                     the relocs too.  */
                }
-             else if (htab->is_vxworks
+             else if (htab->elf.target_os == is_vxworks
                       && strcmp (p->sec->output_section->name,
                                  ".tls_vars") == 0)
                {
@@ -5569,7 +5589,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
        else
          *local_got = (bfd_vma) -1;
 
-      if (htab->is_vxworks)
+      if (htab->elf.target_os == is_vxworks)
        continue;
 
       /* Allocate space for calls to local STT_GNU_IFUNC syms in .iplt.  */
@@ -5834,20 +5854,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
 #define add_dynamic_entry(TAG, VAL) \
   _bfd_elf_add_dynamic_entry (info, TAG, VAL)
 
-      if (bfd_link_executable (info))
-       {
-         if (!add_dynamic_entry (DT_DEBUG, 0))
-           return FALSE;
-       }
-
-      if (htab->elf.splt != NULL && htab->elf.splt->size != 0)
-       {
-         if (!add_dynamic_entry (DT_PLTGOT, 0)
-             || !add_dynamic_entry (DT_PLTRELSZ, 0)
-             || !add_dynamic_entry (DT_PLTREL, DT_RELA)
-             || !add_dynamic_entry (DT_JMPREL, 0))
-           return FALSE;
-       }
+      if (!_bfd_elf_maybe_vxworks_add_dynamic_tags (output_bfd, info,
+                                                   relocs))
+       return FALSE;
 
       if (htab->plt_type == PLT_NEW
          && htab->glink != NULL
@@ -5861,30 +5870,6 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
              && !add_dynamic_entry (DT_PPC_OPT, PPC_OPT_TLS))
            return FALSE;
        }
-
-      if (relocs)
-       {
-         if (!add_dynamic_entry (DT_RELA, 0)
-             || !add_dynamic_entry (DT_RELASZ, 0)
-             || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
-           return FALSE;
-       }
-
-      /* If any dynamic relocs apply to a read-only section, then we
-        need a DT_TEXTREL entry.  */
-      if ((info->flags & DF_TEXTREL) == 0)
-       elf_link_hash_traverse (elf_hash_table (info),
-                               _bfd_elf_maybe_set_textrel,
-                               info);
-
-      if ((info->flags & DF_TEXTREL) != 0)
-       {
-         if (!add_dynamic_entry (DT_TEXTREL, 0))
-           return FALSE;
-       }
-      if (htab->is_vxworks
-         && !elf_vxworks_add_dynamic_entries (output_bfd, info))
-       return FALSE;
    }
 #undef add_dynamic_entry
 
@@ -6989,7 +6974,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
   sym_hashes = elf_sym_hashes (input_bfd);
   /* We have to handle relocations in vxworks .tls_vars sections
      specially, because the dynamic loader is 'weird'.  */
-  is_vxworks_tls = (htab->is_vxworks && bfd_link_pic (info)
+  is_vxworks_tls = (htab->elf.target_os == is_vxworks && bfd_link_pic (info)
                    && !strcmp (input_section->output_section->name,
                                ".tls_vars"));
   if (input_section->sec_info_type == SEC_INFO_TYPE_TARGET)
@@ -7521,7 +7506,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
        }
 
       ifunc = NULL;
-      if (!htab->is_vxworks)
+      if (htab->elf.target_os != is_vxworks)
        {
          struct plt_entry *ent;
 
@@ -7602,39 +7587,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
       if (r_type < R_PPC_max)
        howto = ppc_elf_howto_table[r_type];
 
-      switch (r_type)
-       {
-       default:
-         break;
-
-       case R_PPC_TPREL16_HA:
-         if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
-           {
-             bfd_byte *p = contents + (rel->r_offset & ~3);
-             unsigned int insn = bfd_get_32 (input_bfd, p);
-             if ((insn & ((0x3fu << 26) | 0x1f << 16))
-                 != ((15u << 26) | (2 << 16)) /* addis rt,2,imm */)
-               /* xgettext:c-format */
-               info->callbacks->minfo
-                 (_("%H: warning: %s unexpected insn %#x.\n"),
-                  input_bfd, input_section, rel->r_offset, howto->name, insn);
-             else
-               bfd_put_32 (input_bfd, NOP, p);
-           }
-         break;
-
-       case R_PPC_TPREL16_LO:
-         if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
-           {
-             bfd_byte *p = contents + (rel->r_offset & ~3);
-             unsigned int insn = bfd_get_32 (input_bfd, p);
-             insn &= ~(0x1f << 16);
-             insn |= 2 << 16;
-             bfd_put_32 (input_bfd, insn, p);
-           }
-         break;
-       }
-
       tls_type = 0;
       switch (r_type)
        {
@@ -8799,6 +8751,31 @@ ppc_elf_relocate_section (bfd *output_bfd,
          goto copy_reloc;
        }
 
+      switch (r_type)
+       {
+       default:
+         break;
+
+       case R_PPC_TPREL16_HA:
+         if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+           {
+             bfd_byte *p = contents + (rel->r_offset & ~3);
+             bfd_put_32 (input_bfd, NOP, p);
+           }
+         break;
+
+       case R_PPC_TPREL16_LO:
+         if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+           {
+             bfd_byte *p = contents + (rel->r_offset & ~3);
+             unsigned int insn = bfd_get_32 (input_bfd, p);
+             insn &= ~(0x1f << 16);
+             insn |= 2 << 16;
+             bfd_put_32 (input_bfd, insn, p);
+           }
+         break;
+       }
+
       switch (r_type)
        {
        default:
@@ -9893,7 +9870,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
          switch (dyn.d_tag)
            {
            case DT_PLTGOT:
-             if (htab->is_vxworks)
+             if (htab->elf.target_os == is_vxworks)
                s = htab->elf.sgotplt;
              else
                s = htab->elf.splt;
@@ -9925,7 +9902,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
              continue;
 
            default:
-             if (htab->is_vxworks
+             if (htab->elf.target_os == is_vxworks
                  && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
                break;
              continue;
@@ -9977,7 +9954,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
     }
 
   /* Fill in the first entry in the VxWorks procedure linkage table.  */
-  if (htab->is_vxworks
+  if (htab->elf.target_os == is_vxworks
       && htab->elf.splt != NULL
       && htab->elf.splt->size != 0
       && htab->elf.splt->output_section != bfd_abs_section_ptr)
@@ -10386,6 +10363,9 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 
 #undef  ELF_OSABI
 
+#undef ELF_TARGET_OS
+#define ELF_TARGET_OS          is_vxworks
+
 /* VxWorks uses the elf default section flags for .plt.  */
 static const struct bfd_elf_special_section *
 ppc_elf_vxworks_get_sec_type_attr (bfd *abfd, asection *sec)
@@ -10411,7 +10391,6 @@ ppc_elf_vxworks_link_hash_table_create (bfd *abfd)
     {
       struct ppc_elf_link_hash_table *htab
        = (struct ppc_elf_link_hash_table *)ret;
-      htab->is_vxworks = 1;
       htab->plt_type = PLT_VXWORKS;
       htab->plt_entry_size = VXWORKS_PLT_ENTRY_SIZE;
       htab->plt_slot_size = VXWORKS_PLT_ENTRY_SIZE;
This page took 0.030336 seconds and 4 git commands to generate.