Change PLT code to avoid using r2 - it used by GCC to return large startures
[deliverable/binutils-gdb.git] / bfd / elflink.h
index 5ba86e77e5ad4f9d9b535951b1e0acd691fe8fb2..0f5c71252035be930b51c2f8d0d20414ec2c080f 100644 (file)
@@ -895,7 +895,6 @@ elf_link_add_object_symbols (abfd, info)
   Elf_External_Sym *buf = NULL;
   struct elf_link_hash_entry **sym_hash;
   boolean dynamic;
-  bfd_byte *dynver = NULL;
   Elf_External_Versym *extversym = NULL;
   Elf_External_Versym *ever;
   Elf_External_Dyn *dynbuf = NULL;
@@ -1023,7 +1022,7 @@ elf_link_add_object_symbols (abfd, info)
          Elf_Internal_Shdr *versymhdr;
 
          versymhdr = &elf_tdata (abfd)->dynversym_hdr;
-         extversym = (Elf_External_Versym *) bfd_malloc (hdr->sh_size);
+         extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
          if (extversym == NULL)
            goto error_return;
          if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0
@@ -1322,7 +1321,7 @@ elf_link_add_object_symbols (abfd, info)
       /* Save the SONAME, if there is one, because sometimes the
          linker emulation code will need to know it.  */
       if (*name == '\0')
-       name = bfd_get_filename (abfd);
+       name = basename (bfd_get_filename (abfd));
       elf_dt_name (abfd) = name;
     }
 
@@ -2167,6 +2166,18 @@ elf_link_add_object_symbols (abfd, info)
        }
     }
 
+  if (! info->relocateable && ! dynamic)
+    {
+      asection *s;
+
+      for (s = abfd->sections; s != NULL; s = s->next)
+       if ((s->flags & SEC_MERGE)
+           && ! _bfd_merge_section (abfd,
+                                    &elf_hash_table (info)->merge_info,
+                                    s, &elf_section_data (s)->merge_info))
+         goto error_return;
+    }
+
   return true;
 
  error_return:
@@ -2174,8 +2185,6 @@ elf_link_add_object_symbols (abfd, info)
     free (buf);
   if (dynbuf != NULL)
     free (dynbuf);
-  if (dynver != NULL)
-    free (dynver);
   if (extversym != NULL)
     free (extversym);
   return false;
@@ -2456,7 +2465,7 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs,
       Elf_Internal_Rel *irel;
 
       erel = (Elf_External_Rel *) external_relocs;
-      erelend = erel + shdr->sh_size / shdr->sh_entsize;
+      erelend = erel + NUM_SHDR_ENTRIES (shdr);
       irela = internal_relocs;
       irel = bfd_alloc (abfd, (bed->s->int_rels_per_ext_rel
                               * sizeof (Elf_Internal_Rel)));
@@ -2486,7 +2495,7 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs,
       BFD_ASSERT (shdr->sh_entsize == sizeof (Elf_External_Rela));
 
       erela = (Elf_External_Rela *) external_relocs;
-      erelaend = erela + shdr->sh_size / shdr->sh_entsize;
+      erelaend = erela + NUM_SHDR_ENTRIES (shdr);
       irela = internal_relocs;
       for (; erela < erelaend; erela++, irela += bed->s->int_rels_per_ext_rel)
        {
@@ -2566,7 +2575,7 @@ NAME(_bfd_elf,link_read_relocs) (abfd, o, external_relocs, internal_relocs,
       (abfd,
        elf_section_data (o)->rel_hdr2,
        ((bfd_byte *) external_relocs) + rel_hdr->sh_size,
-       internal_relocs + (rel_hdr->sh_size / rel_hdr->sh_entsize
+       internal_relocs + (NUM_SHDR_ENTRIES (rel_hdr)
                          * bed->s->int_rels_per_ext_rel)))
     goto error_return;
 
@@ -2957,14 +2966,13 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
            }
        }
 
+      eif.info = info;
+      eif.failed = false;
+
       /* If we are supposed to export all symbols into the dynamic symbol
          table (this is not the normal case), then do so.  */
       if (export_dynamic)
        {
-         struct elf_info_failed eif;
-
-         eif.failed = false;
-         eif.info = info;
          elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol,
                                  (PTR) &eif);
          if (eif.failed)
@@ -2986,8 +2994,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
 
       /* Find all symbols which were defined in a dynamic object and make
         the backend pick a reasonable value for them.  */
-      eif.failed = false;
-      eif.info = info;
       elf_link_hash_traverse (elf_hash_table (info),
                              elf_adjust_dynamic_symbol,
                              (PTR) &eif);
@@ -3124,7 +3130,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
              const char *name;
              bfd_size_type indx;
 
-             name = output_bfd->filename;
+             name = basename (output_bfd->filename);
              def.vd_hash = bfd_elf_hash (name);
              indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
                                            name, true, false);
@@ -3308,7 +3314,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
                                             true, false);
                else
                  indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
-                                            t->vn_bfd->filename, true, false);
+                                            basename (t->vn_bfd->filename),
+                                            true, false);
                if (indx == (bfd_size_type) -1)
                  return false;
                t->vn_file = indx;
@@ -3518,16 +3525,24 @@ elf_fix_symbol_flags (h, eif)
   /* If -Bsymbolic was used (which means to bind references to global
      symbols to the definition within the shared object), and this
      symbol was defined in a regular object, then it actually doesn't
-     need a PLT entry.  Likewise, if the symbol has any kind of
-     visibility (internal, hidden, or protected), it doesn't need a
-     PLT.  */
+     need a PLT entry, and we can accomplish that by forcing it local.
+     Likewise, if the symbol has hidden or internal visibility.
+     FIXME: It might be that we also do not need a PLT for other
+     non-hidden visibilities, but we would have to tell that to the
+     backend specifically; we can't just clear PLT-related data here.  */
   if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0
       && eif->info->shared
-      && (eif->info->symbolic || ELF_ST_VISIBILITY (h->other))
+      && (eif->info->symbolic
+         || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+         || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)
       && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
     {
-      h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
-      h->plt.offset = (bfd_vma) -1;
+      struct elf_backend_data *bed;
+      bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj);
+      if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
+         || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)
+       h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+      (*bed->elf_backend_hide_symbol) (eif->info, h);
     }
 
   /* If this is a weak defined symbol in a dynamic object, and we know
@@ -4067,6 +4082,8 @@ static boolean elf_link_flush_output_syms
   PARAMS ((struct elf_final_link_info *));
 static boolean elf_link_output_extsym
   PARAMS ((struct elf_link_hash_entry *, PTR));
+static boolean elf_link_sec_merge_syms
+  PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_link_input_bfd
   PARAMS ((struct elf_final_link_info *, bfd *));
 static boolean elf_reloc_link_order
@@ -4216,6 +4233,7 @@ elf_bfd_final_link (abfd, info)
   Elf_Internal_Shdr *symstrtab_hdr;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
   struct elf_outext_info eoinfo;
+  boolean merged;
 
   if (info->shared)
     abfd->flags |= DYNAMIC;
@@ -4261,6 +4279,7 @@ elf_bfd_final_link (abfd, info)
   max_external_reloc_size = 0;
   max_internal_reloc_count = 0;
   max_sym_count = 0;
+  merged = false;
   for (o = abfd->sections; o != (asection *) NULL; o = o->next)
     {
       o->reloc_count = 0;
@@ -4282,6 +4301,9 @@ elf_bfd_final_link (abfd, info)
                 the linker has decided to not include.  */
              sec->linker_mark = true;
 
+             if (sec->flags & SEC_MERGE)
+               merged = true;
+
              if (info->relocateable || info->emitrelocations)
                o->reloc_count += sec->reloc_count;
 
@@ -4339,6 +4361,10 @@ elf_bfd_final_link (abfd, info)
        o->vma = 0;
     }
 
+  if (! info->relocateable && merged)
+    elf_link_hash_traverse (elf_hash_table (info),
+                           elf_link_sec_merge_syms, (PTR) abfd);
+
   /* Figure out the file positions for everything but the symbol table
      and the relocs.  We set symcount to force assign_section_numbers
      to create a symbol table.  */
@@ -4387,11 +4413,9 @@ elf_bfd_final_link (abfd, info)
                  rel_count2 = &esdo->rel_count;
                }
 
-             *rel_count += (esdi->rel_hdr.sh_size
-                            / esdi->rel_hdr.sh_entsize);
+             *rel_count += NUM_SHDR_ENTRIES (& esdi->rel_hdr);
              if (esdi->rel_hdr2)
-               *rel_count2 += (esdi->rel_hdr2->sh_size
-                               / esdi->rel_hdr2->sh_entsize);
+               *rel_count2 += NUM_SHDR_ENTRIES (esdi->rel_hdr2);
            }
        }
 
@@ -5058,6 +5082,33 @@ elf_link_flush_output_syms (finfo)
   return true;
 }
 
+/* Adjust all external symbols pointing into SEC_MERGE sections
+   to reflect the object merging within the sections.  */
+
+static boolean
+elf_link_sec_merge_syms (h, data)
+     struct elf_link_hash_entry *h;
+     PTR data;
+{
+  asection *sec;
+
+  if ((h->root.type == bfd_link_hash_defined
+       || h->root.type == bfd_link_hash_defweak)
+      && ((sec = h->root.u.def.section)->flags & SEC_MERGE)
+      && elf_section_data (sec)->merge_info)
+    {
+      bfd *output_bfd = (bfd *) data;
+
+      h->root.u.def.value =
+       _bfd_merged_section_offset (output_bfd,
+                                   &h->root.u.def.section,
+                                   elf_section_data (sec)->merge_info,
+                                   h->root.u.def.value, (bfd_vma) 0);
+    }
+
+  return true;
+}
+
 /* Add an external symbol to the symbol table.  This is called from
    the hash table traversal routine.  When generating a shared object,
    we go through the symbol table twice.  The first time we output
@@ -5389,7 +5440,7 @@ elf_link_output_relocs (output_bfd, input_section, input_rel_hdr,
 
   bed = get_elf_backend_data (output_bfd);
   irela = internal_relocs;
-  irelaend = irela + input_rel_hdr->sh_size / input_rel_hdr->sh_entsize;
+  irelaend = irela + NUM_SHDR_ENTRIES (input_rel_hdr);
   if (input_rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
     {
       Elf_External_Rel *erel;
@@ -5424,7 +5475,7 @@ elf_link_output_relocs (output_bfd, input_section, input_rel_hdr,
 
   /* Bump the counter, so that we know where to add the next set of
      relocations.  */
-  *rel_countp += input_rel_hdr->sh_size / input_rel_hdr->sh_entsize;
+  *rel_countp += NUM_SHDR_ENTRIES (input_rel_hdr);
 }
 
 /* Link an input file into the linker output file.  This function
@@ -5523,7 +5574,15 @@ elf_link_input_bfd (finfo, input_bfd)
          name = isec->name;
        }
       else if (isym->st_shndx > 0 && isym->st_shndx < SHN_LORESERVE)
-       isec = section_from_elf_index (input_bfd, isym->st_shndx);
+       {
+         isec = section_from_elf_index (input_bfd, isym->st_shndx);
+         if (isec && elf_section_data (isec)->merge_info
+             && ELF_ST_TYPE (isym->st_info) != STT_SECTION)
+           isym->st_value =
+             _bfd_merged_section_offset (output_bfd, &isec,
+                                         elf_section_data (isec)->merge_info,
+                                         isym->st_value, (bfd_vma) 0);
+       }
       else if (isym->st_shndx == SHN_ABS)
        {
          isec = bfd_abs_section_ptr;
@@ -5625,7 +5684,9 @@ elf_link_input_bfd (finfo, input_bfd)
       if ((finfo->info->strip == strip_some
           && (bfd_hash_lookup (finfo->info->keep_hash, name, false, false)
               == NULL))
-         || (finfo->info->discard == discard_l
+         || (((finfo->info->discard == discard_sec_merge
+               && (isec->flags & SEC_MERGE) && ! finfo->info->relocateable)
+              || finfo->info->discard == discard_l)
              && bfd_is_local_label_name (input_bfd, name)))
        continue;
 
@@ -5876,8 +5937,7 @@ elf_link_input_bfd (finfo, input_bfd)
              elf_link_output_relocs (output_bfd, o,
                                      input_rel_hdr,
                                      internal_relocs);
-             internal_relocs
-               += input_rel_hdr->sh_size / input_rel_hdr->sh_entsize;
+             internal_relocs += NUM_SHDR_ENTRIES (input_rel_hdr);
              input_rel_hdr = elf_section_data (o)->rel_hdr2;
              if (input_rel_hdr)
                elf_link_output_relocs (output_bfd, o,
@@ -5887,7 +5947,20 @@ elf_link_input_bfd (finfo, input_bfd)
        }
 
       /* Write out the modified section contents.  */
-      if (elf_section_data (o)->stab_info == NULL)
+      if (elf_section_data (o)->stab_info)
+       {
+         if (! (_bfd_write_section_stabs
+                (output_bfd, &elf_hash_table (finfo->info)->stab_info,
+                 o, &elf_section_data (o)->stab_info, contents)))
+           return false;
+       }
+      else if (elf_section_data (o)->merge_info)
+       {
+         if (! (_bfd_write_merged_section
+                (output_bfd, o, elf_section_data (o)->merge_info)))
+           return false;
+       }
+      else
        {
          if (! (o->flags & SEC_EXCLUDE) &&
              ! bfd_set_section_contents (output_bfd, o->output_section,
@@ -5897,13 +5970,6 @@ elf_link_input_bfd (finfo, input_bfd)
                                           : o->_raw_size)))
            return false;
        }
-      else
-       {
-         if (! (_bfd_write_section_stabs
-                (output_bfd, &elf_hash_table (finfo->info)->stab_info,
-                 o, &elf_section_data (o)->stab_info, contents)))
-           return false;
-       }
     }
 
   return true;
This page took 0.028831 seconds and 4 git commands to generate.