* elf32-arm.h (elf32_arm_final_link_relocate): Don't copy STN_UNDEF
[deliverable/binutils-gdb.git] / bfd / elflink.h
index a8ffb0b85d98f1392f97a778944018700a465650..a4fb88d5be5a2e692a8d9d436a15a14e07a555fe 100644 (file)
@@ -44,6 +44,8 @@ static boolean elf_merge_symbol
           boolean *, boolean *, boolean *, boolean));
 static boolean elf_export_symbol
   PARAMS ((struct elf_link_hash_entry *, PTR));
+static boolean elf_finalize_dynstr
+  PARAMS ((bfd *, struct bfd_link_info *));
 static boolean elf_fix_symbol_flags
   PARAMS ((struct elf_link_hash_entry *, struct elf_info_failed *));
 static boolean elf_adjust_dynamic_symbol
@@ -1294,13 +1296,12 @@ elf_link_add_object_symbols (abfd, info)
       if (add_needed)
        {
          /* Add a DT_NEEDED entry for this dynamic object.  */
-         oldsize = _bfd_stringtab_size (hash_table->dynstr);
-         strindex = _bfd_stringtab_add (hash_table->dynstr, name,
-                                        true, false);
+         oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
+         strindex = _bfd_elf_strtab_add (hash_table->dynstr, name, false);
          if (strindex == (bfd_size_type) -1)
            goto error_return;
 
-         if (oldsize == _bfd_stringtab_size (hash_table->dynstr))
+         if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr))
            {
              asection *sdyn;
              Elf_External_Dyn *dyncon, *dynconend;
@@ -1328,6 +1329,7 @@ elf_link_add_object_symbols (abfd, info)
                        free (buf);
                      if (extversym != NULL)
                        free (extversym);
+                     _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
                      return true;
                    }
                }
@@ -1965,6 +1967,8 @@ elf_link_add_object_symbols (abfd, info)
              case STV_HIDDEN:
                h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
                (*bed->elf_backend_hide_symbol) (info, h);
+               _bfd_elf_strtab_delref (hash_table->dynstr,
+                                       h->dynstr_index);
                break;
              }
 
@@ -1983,15 +1987,13 @@ elf_link_add_object_symbols (abfd, info)
                 have to make sure there is a DT_NEEDED entry for it.  */
 
              dt_needed = false;
-             oldsize = _bfd_stringtab_size (hash_table->dynstr);
-             strindex = _bfd_stringtab_add (hash_table->dynstr,
-                                            elf_dt_soname (abfd),
-                                            true, false);
+             oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
+             strindex = _bfd_elf_strtab_add (hash_table->dynstr,
+                                             elf_dt_soname (abfd), false);
              if (strindex == (bfd_size_type) -1)
                goto error_return;
 
-             if (oldsize
-                 == _bfd_stringtab_size (hash_table->dynstr))
+             if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr))
                {
                  asection *sdyn;
                  Elf_External_Dyn *dyncon, *dynconend;
@@ -2290,7 +2292,7 @@ elf_link_create_dynamic_sections (abfd, info)
   /* Create a strtab to hold the dynamic symbol names.  */
   if (elf_hash_table (info)->dynstr == NULL)
     {
-      elf_hash_table (info)->dynstr = elf_stringtab_init ();
+      elf_hash_table (info)->dynstr = _bfd_elf_strtab_init ();
       if (elf_hash_table (info)->dynstr == NULL)
        return false;
     }
@@ -2390,7 +2392,7 @@ elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
 {
   struct elf_link_local_dynamic_entry *entry;
   struct elf_link_hash_table *eht;
-  struct bfd_strtab_hash *dynstr;
+  struct elf_strtab_hash *dynstr;
   Elf_External_Sym esym;
   unsigned long dynstr_index;
   char *name;
@@ -2426,12 +2428,12 @@ elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx)
   if (dynstr == NULL)
     {
       /* Create a strtab to hold the dynamic symbol names.  */
-      elf_hash_table (info)->dynstr = dynstr = _bfd_elf_stringtab_init ();
+      elf_hash_table (info)->dynstr = dynstr = _bfd_elf_strtab_init ();
       if (dynstr == NULL)
        return false;
     }
 
-  dynstr_index = _bfd_stringtab_add (dynstr, name, true, false);
+  dynstr_index = _bfd_elf_strtab_add (dynstr, name, false);
   if (dynstr_index == (unsigned long) -1)
     return false;
   entry->isym.st_name = dynstr_index;
@@ -2949,8 +2951,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
 
       if (soname != NULL)
        {
-         soname_indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
-                                           soname, true, true);
+         soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                            soname, true);
          if (soname_indx == (bfd_size_type) -1
              || ! elf_add_dynamic_entry (info, (bfd_vma) DT_SONAME,
                                          soname_indx))
@@ -2969,8 +2971,10 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
        {
          bfd_size_type indx;
 
-         indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, rpath,
-                                    true, true);
+         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
+                                     true);
+         if (info->new_dtags)
+           _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr, indx);
          if (indx == (bfd_size_type) -1
              || ! elf_add_dynamic_entry (info, (bfd_vma) DT_RPATH, indx)
              || (info->new_dtags
@@ -2983,8 +2987,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
        {
          bfd_size_type indx;
 
-         indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
-                                    filter_shlib, true, true);
+         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                     filter_shlib, true);
          if (indx == (bfd_size_type) -1
              || ! elf_add_dynamic_entry (info, (bfd_vma) DT_FILTER, indx))
            return false;
@@ -2998,8 +3002,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
            {
              bfd_size_type indx;
 
-             indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
-                                        *p, true, true);
+             indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                         *p, true);
              if (indx == (bfd_size_type) -1
                  || ! elf_add_dynamic_entry (info, (bfd_vma) DT_AUXILIARY,
                                              indx))
@@ -3081,7 +3085,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
        {
          bfd_size_type strsize;
 
-         strsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
+         strsize = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
          if (! elf_add_dynamic_entry (info, (bfd_vma) DT_HASH, (bfd_vma) 0)
              || ! elf_add_dynamic_entry (info, (bfd_vma) DT_STRTAB, (bfd_vma) 0)
              || ! elf_add_dynamic_entry (info, (bfd_vma) DT_SYMTAB, (bfd_vma) 0)
@@ -3164,6 +3168,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
 
          if (soname_indx != (bfd_size_type) -1)
            {
+             _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
+                                     soname_indx);
              def.vd_hash = bfd_elf_hash (soname);
              defaux.vda_name = soname_indx;
            }
@@ -3174,8 +3180,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
 
              name = basename (output_bfd->filename);
              def.vd_hash = bfd_elf_hash (name);
-             indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
-                                           name, true, false);
+             indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                         name, false);
              if (indx == (bfd_size_type) -1)
                return false;
              defaux.vda_name = indx;
@@ -3234,6 +3240,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
              p += sizeof (Elf_External_Verdef);
 
              defaux.vda_name = h->dynstr_index;
+             _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
+                                     h->dynstr_index);
              if (t->deps == NULL)
                defaux.vda_next = 0;
              else
@@ -3253,7 +3261,11 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
                      defaux.vda_name = 0;
                    }
                  else
-                   defaux.vda_name = n->version_needed->name_indx;
+                   {
+                     defaux.vda_name = n->version_needed->name_indx;
+                     _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr,
+                                             defaux.vda_name);
+                   }
                  if (n->next == NULL)
                    defaux.vda_next = 0;
                  else
@@ -3352,14 +3364,11 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
 
                t->vn_version = VER_NEED_CURRENT;
                t->vn_cnt = caux;
-               if (elf_dt_name (t->vn_bfd) != NULL)
-                 indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
-                                            elf_dt_name (t->vn_bfd),
-                                            true, false);
-               else
-                 indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
-                                            basename (t->vn_bfd->filename),
-                                            true, false);
+               indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                           elf_dt_name (t->vn_bfd) != NULL
+                                           ? elf_dt_name (t->vn_bfd)
+                                           : basename (t->vn_bfd->filename),
+                                           false);
                if (indx == (bfd_size_type) -1)
                  return false;
                t->vn_file = indx;
@@ -3377,8 +3386,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
                for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
                  {
                    a->vna_hash = bfd_elf_hash (a->vna_nodename);
-                   indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr,
-                                              a->vna_nodename, true, false);
+                   indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                               a->vna_nodename, false);
                    if (indx == (bfd_size_type) -1)
                      return false;
                    a->vna_name = indx;
@@ -3482,7 +3491,10 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
 
       s = bfd_get_section_by_name (dynobj, ".dynstr");
       BFD_ASSERT (s != NULL);
-      s->_raw_size = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
+
+      elf_finalize_dynstr (output_bfd, info);
+
+      s->_raw_size = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
 
       for (dtagcount = 0; dtagcount <= info->spare_dynamic_tags; ++dtagcount)
        if (! elf_add_dynamic_entry (info, (bfd_vma) DT_NULL, (bfd_vma) 0))
@@ -3492,6 +3504,150 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
   return true;
 }
 \f
+/* This function is used to adjust offsets into .dynstr for
+   dynamic symbols.  This is called via elf_link_hash_traverse.  */
+      
+static boolean elf_adjust_dynstr_offsets
+PARAMS ((struct elf_link_hash_entry *, PTR));
+        
+static boolean
+elf_adjust_dynstr_offsets (h, data)
+     struct elf_link_hash_entry *h;
+     PTR data;
+{
+  struct elf_strtab_hash *dynstr = (struct elf_strtab_hash *) data;
+
+  if (h->dynindx != -1)
+    h->dynstr_index = _bfd_elf_strtab_offset (dynstr, h->dynstr_index);
+  return true;
+}
+
+/* Assign string offsets in .dynstr, update all structures referencing
+   them.  */
+
+static boolean
+elf_finalize_dynstr (output_bfd, info)
+     bfd *output_bfd;
+     struct bfd_link_info *info;
+{
+  struct elf_link_local_dynamic_entry *entry;
+  struct elf_strtab_hash *dynstr = elf_hash_table (info)->dynstr;
+  bfd *dynobj = elf_hash_table (info)->dynobj;
+  asection *sdyn;
+  bfd_size_type size;
+  Elf_External_Dyn *dyncon, *dynconend;
+
+  _bfd_elf_strtab_finalize (dynstr);
+  size = _bfd_elf_strtab_size (dynstr);
+
+  /* Update all .dynamic entries referencing .dynstr strings.  */
+  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  BFD_ASSERT (sdyn != NULL);
+
+  dyncon = (Elf_External_Dyn *) sdyn->contents;
+  dynconend = (Elf_External_Dyn *) (sdyn->contents +
+                                   sdyn->_raw_size);
+  for (; dyncon < dynconend; dyncon++)
+    {
+      Elf_Internal_Dyn dyn;
+
+      elf_swap_dyn_in (dynobj, dyncon, & dyn);
+      switch (dyn.d_tag)
+       {
+       case DT_STRSZ:
+         dyn.d_un.d_val = size;
+         elf_swap_dyn_out (dynobj, & dyn, dyncon);
+         break;
+       case DT_NEEDED:
+       case DT_SONAME:
+       case DT_RPATH:
+       case DT_RUNPATH:
+       case DT_FILTER:
+       case DT_AUXILIARY:
+         dyn.d_un.d_val = _bfd_elf_strtab_offset (dynstr, dyn.d_un.d_val);
+         elf_swap_dyn_out (dynobj, & dyn, dyncon);
+         break;
+       default:
+         break;
+       }
+    }
+
+  /* Now update local dynamic symbols.  */
+  for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next)
+    entry->isym.st_name = _bfd_elf_strtab_offset (dynstr,
+                                                 entry->isym.st_name);
+
+  /* And the rest of dynamic symbols.  */
+  elf_link_hash_traverse (elf_hash_table (info),
+                         elf_adjust_dynstr_offsets, dynstr);
+
+  /* Adjust version definitions.  */
+  if (elf_tdata (output_bfd)->cverdefs)
+    {
+      asection *s;
+      bfd_byte *p;
+      bfd_size_type i;
+      Elf_Internal_Verdef def;
+      Elf_Internal_Verdaux defaux;
+                    
+      s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
+      p = (bfd_byte *) s->contents;
+      do
+       {
+         _bfd_elf_swap_verdef_in (output_bfd, (Elf_External_Verdef *) p,
+                                  &def);
+         p += sizeof (Elf_External_Verdef);
+         for (i = 0; i < def.vd_cnt; ++i)
+           {
+             _bfd_elf_swap_verdaux_in (output_bfd,
+                                       (Elf_External_Verdaux *) p, &defaux);
+             defaux.vda_name = _bfd_elf_strtab_offset (dynstr,
+                                                       defaux.vda_name);
+             _bfd_elf_swap_verdaux_out (output_bfd,
+                                        &defaux, (Elf_External_Verdaux *) p);
+             p += sizeof (Elf_External_Verdaux);
+           }
+       }
+      while (def.vd_next);
+    }
+
+  /* Adjust version references.  */
+  if (elf_tdata (output_bfd)->verref)
+    {
+      asection *s;
+      bfd_byte *p;
+      bfd_size_type i;
+      Elf_Internal_Verneed need;
+      Elf_Internal_Vernaux needaux;
+                    
+      s = bfd_get_section_by_name (dynobj, ".gnu.version_r");
+      p = (bfd_byte *) s->contents;
+      do
+       {
+         _bfd_elf_swap_verneed_in (output_bfd, (Elf_External_Verneed *) p,
+                                   &need);
+         need.vn_file = _bfd_elf_strtab_offset (dynstr, need.vn_file);
+         _bfd_elf_swap_verneed_out (output_bfd, &need,
+                                    (Elf_External_Verneed *) p);
+         p += sizeof (Elf_External_Verneed);
+         for (i = 0; i < need.vn_cnt; ++i)
+           {
+             _bfd_elf_swap_vernaux_in (output_bfd,
+                                       (Elf_External_Vernaux *) p, &needaux);
+             needaux.vna_name = _bfd_elf_strtab_offset (dynstr,
+                                                        needaux.vna_name);
+             _bfd_elf_swap_vernaux_out (output_bfd,
+                                        &needaux,
+                                        (Elf_External_Vernaux *) p);
+             p += sizeof (Elf_External_Vernaux);
+           }
+       }
+      while (need.vn_next);
+    }
+
+  return true;
+}
+
 /* Fix up the flags for a symbol.  This handles various cases which
    can only be fixed after all the input files are seen.  This is
    currently called by both adjust_dynamic_symbol and
@@ -3591,7 +3747,11 @@ elf_fix_symbol_flags (h, eif)
       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;
+       {
+         h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+         _bfd_elf_strtab_delref (elf_hash_table (eif->info)->dynstr,
+                                 h->dynstr_index);
+       }
       (*bed->elf_backend_hide_symbol) (eif->info, h);
     }
 
@@ -3976,9 +4136,8 @@ elf_link_assign_sym_version (h, data)
                            {
                              h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
                              (*bed->elf_backend_hide_symbol) (info, h);
-                             /* FIXME: The name of the symbol has
-                                already been recorded in the dynamic
-                                string table section.  */
+                             _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
+                                                     h->dynstr_index);
                            }
 
                          break;
@@ -4089,9 +4248,8 @@ elf_link_assign_sym_version (h, data)
                        {
                          h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
                          (*bed->elf_backend_hide_symbol) (info, h);
-                         /* FIXME: The name of the symbol has already
-                            been recorded in the dynamic string table
-                            section.  */
+                         _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
+                                                 h->dynstr_index);
                        }
                      break;
                    }
@@ -4111,8 +4269,8 @@ elf_link_assign_sym_version (h, data)
            {
              h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
              (*bed->elf_backend_hide_symbol) (info, h);
-             /* FIXME: The name of the symbol has already been
-                recorded in the dynamic string table section.  */
+             _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
+                                     h->dynstr_index);
            }
        }
     }
@@ -4378,8 +4536,8 @@ elf_link_sort_cmp2 (A, B)
     return -1;
   if (a->offset > b->offset)
     return 1;
-  copya = a->type == reloc_class_copy;
-  copyb = b->type == reloc_class_copy;
+  copya = (a->type == reloc_class_copy) * 2 + (a->type == reloc_class_plt);
+  copyb = (b->type == reloc_class_copy) * 2 + (b->type == reloc_class_plt);
   if (copya < copyb)
     return -1;
   if (copya > copyb)
@@ -4480,7 +4638,7 @@ elf_link_sort_relocs (abfd, info, psec)
          }
       }
 
-  qsort (rela, count, sizeof (*rela), elf_link_sort_cmp1);
+  qsort (rela, (size_t) count, sizeof (*rela), elf_link_sort_cmp1);
   for (ret = 0; ret < count && rela[ret].type == reloc_class_relative; ret++)
     ;
   for (i = ret, j = ret; i < count; i++)
@@ -4489,7 +4647,7 @@ elf_link_sort_relocs (abfd, info, psec)
        j = i;
       rela[i].offset = rela[j].u.rel.r_offset;
     }
-  qsort (rela + ret, count - ret, sizeof (*rela), elf_link_sort_cmp2);
+  qsort (rela + ret, (size_t) count - ret, sizeof (*rela), elf_link_sort_cmp2);
 
   for (o = dynobj->sections; o != NULL; o = o->next)
     if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
@@ -4502,7 +4660,7 @@ elf_link_sort_relocs (abfd, info, psec)
            struct elf_link_sort_rela *s;
 
            erel = (Elf_External_Rel *) o->contents;
-           erelend = (Elf_External_Rel *) ((PTR) o->contents + o->_raw_size);
+           erelend = (Elf_External_Rel *) (o->contents + o->_raw_size);
            s = rela + o->output_offset / sizeof (Elf_External_Rel);
            for (; erel < erelend; erel++, s++)
              {
@@ -4519,7 +4677,7 @@ elf_link_sort_relocs (abfd, info, psec)
            struct elf_link_sort_rela *s;
 
            erela = (Elf_External_Rela *) o->contents;
-           erelaend = (Elf_External_Rela *) ((PTR) o->contents + o->_raw_size);
+           erelaend = (Elf_External_Rela *) (o->contents + o->_raw_size);
            s = rela + o->output_offset / sizeof (Elf_External_Rela);
            for (; erela < erelaend; erela++, s++)
              {
@@ -5308,8 +5466,8 @@ elf_bfd_final_link (abfd, info)
                  stringtab.  */
              off = elf_section_data (o->output_section)->this_hdr.sh_offset;
              if (bfd_seek (abfd, off, SEEK_SET) != 0
-                 || ! _bfd_stringtab_emit (abfd,
-                                           elf_hash_table (info)->dynstr))
+                 || ! _bfd_elf_strtab_emit (abfd,
+                                            elf_hash_table (info)->dynstr))
                goto error_return;
            }
        }
@@ -5696,7 +5854,8 @@ elf_link_output_extsym (h, data)
 
   /* If a symbol is not defined locally, we clear the visibility
      field.  */
-  if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+  if (! finfo->info->relocateable
+      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
     sym.st_other ^= ELF_ST_VISIBILITY (sym.st_other);
 
   /* If this symbol should be put in the .dynsym section, then put it
@@ -5897,6 +6056,7 @@ elf_link_input_bfd (finfo, input_bfd)
   asection *o;
   struct elf_backend_data *bed;
   boolean emit_relocs;
+  struct elf_link_hash_entry **sym_hashes;
 
   output_bfd = finfo->output_bfd;
   bed = get_elf_backend_data (output_bfd);
@@ -6069,6 +6229,7 @@ elf_link_input_bfd (finfo, input_bfd)
     }
 
   /* Relocate the contents of each section.  */
+  sym_hashes = elf_sym_hashes (input_bfd);
   for (o = input_bfd->sections; o != NULL; o = o->next)
     {
       bfd_byte *contents;
@@ -6116,53 +6277,121 @@ elf_link_input_bfd (finfo, input_bfd)
              && o->reloc_count > 0)
            return false;
 
-#if BFD_VERSION_DATE < 20031005
-         {
-           Elf_Internal_Rela *rel, *relend;
-           /* Run through the relocs looking for any against section
-              symbols from removed link-once sections.  Set any such
-              relocs to be against 0.  We should really complain if
-              anything in the final link tries to use it, but
-              DWARF-based exception handling might have an entry in
-              .eh_frame to describe a routine in the linkonce section,
-              and it turns out to be hard to remove the .eh_frame entry
-              too.  FIXME.  */
-           rel = internal_relocs;
-           relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
-           for ( ; rel < relend; rel++)
-             {
-               unsigned long r_symndx = ELF_R_SYM (rel->r_info);
+         /* Run through the relocs looking for any against symbols
+            from discarded sections and section symbols from
+            removed link-once sections.  Complain about relocs
+            against discarded sections.  Zero relocs against removed
+            link-once sections.  We should really complain if
+            anything in the final link tries to use it, but
+            DWARF-based exception handling might have an entry in
+            .eh_frame to describe a routine in the linkonce section,
+            and it turns out to be hard to remove the .eh_frame
+            entry too.  FIXME.  */
+         if (!finfo->info->relocateable)
+           {
+             Elf_Internal_Rela *rel, *relend;
 
-               if (r_symndx < locsymcount
-                   && (!elf_bad_symtab (input_bfd)
-                       || finfo->sections[r_symndx] != NULL))
-                 {
-                   isym = finfo->internal_syms + r_symndx;
-                   if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
-                     {
-                       asection *sec = finfo->sections[r_symndx];
+             rel = internal_relocs;
+             relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
+             for ( ; rel < relend; rel++)
+               {
+                 unsigned long r_symndx = ELF_R_SYM (rel->r_info);
 
-                       if (sec != NULL
-                           && (sec->flags & SEC_LINK_ONCE) != 0
-                           && bfd_is_abs_section (sec->output_section))
-                         {
-                           long r_type = ELF_R_TYPE (rel->r_info);
-                           rel->r_info = ELF_R_INFO (0, r_type);
+                 if (r_symndx >= locsymcount
+                     || (elf_bad_symtab (input_bfd)
+                         && finfo->sections[r_symndx] == NULL))
+                   {
+                     struct elf_link_hash_entry *h;
+
+                     h = sym_hashes[r_symndx - extsymoff];
+                     while (h->root.type == bfd_link_hash_indirect
+                            || h->root.type == bfd_link_hash_warning)
+                       h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+                     /* Complain if the definition comes from a
+                        discarded section.  */
+                     if ((h->root.type == bfd_link_hash_defined
+                          || h->root.type == bfd_link_hash_defweak)
+                         && ! bfd_is_abs_section (h->root.u.def.section)
+                         && bfd_is_abs_section (h->root.u.def.section
+                                                ->output_section))
+                       {
+#if BFD_VERSION_DATE < 20031005
+                         if ((o->flags & SEC_DEBUGGING) != 0)
+                           {
+#if BFD_VERSION_DATE > 20021005
+                             (*finfo->info->callbacks->warning)
+                               (finfo->info,
+                                _("warning: relocation against removed section; zeroing"),
+                                NULL, input_bfd, o, rel->r_offset);
+#endif
+                             memset (rel, 0, sizeof (*rel));
+                           }
+                         else
+#endif
+                           {
+                             if (! ((*finfo->info->callbacks->undefined_symbol)
+                                    (finfo->info, h->root.root.string,
+                                     input_bfd, o, rel->r_offset,
+                                     true)))
+                               return false;
+                           }
+                       }
+                   }
+                 else
+                   {
+                     isym = finfo->internal_syms + r_symndx;
+                     if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
+                       {
+                         asection *sec = finfo->sections[r_symndx];
 
+                         if (sec != NULL
+                             && ! bfd_is_abs_section (sec)
+                             && bfd_is_abs_section (sec->output_section))
+                           {
+#if BFD_VERSION_DATE < 20031005
+                             if ((o->flags & SEC_DEBUGGING) != 0
+                                 || (sec->flags & SEC_LINK_ONCE) != 0)
+                               {
 #if BFD_VERSION_DATE > 20021005
-                           (*finfo->info->callbacks->warning)
-                             (finfo->info,
-                              _("warning: relocation against removed section; zeroing"),
-                              NULL, input_bfd, o, rel->r_offset);
+                                 (*finfo->info->callbacks->warning)
+                                   (finfo->info,
+                                    _("warning: relocation against removed section"),
+                                    NULL, input_bfd, o, rel->r_offset);
 #endif
-                         }
-                     }
-                 }
-             }
-         }
-#else
-#error "This kludge ought to be fixed properly in gcc by now"
+                                 rel->r_info
+                                   = ELF_R_INFO (0, ELF_R_TYPE (rel->r_info));
+                                 rel->r_addend = 0;
+                               }
+                             else
 #endif
+                               {
+                                 boolean ok;
+                                 const char *msg
+                                   = _("local symbols in discarded section %s");
+                                 bfd_size_type amt
+                                   = strlen (sec->name) + strlen (msg) - 1;
+                                 char *buf = (char *) bfd_malloc (amt);
+
+                                 if (buf != NULL)
+                                   sprintf (buf, msg, sec->name);
+                                 else
+                                   buf = (char *) sec->name;
+                                 ok = (*finfo->info->callbacks
+                                       ->undefined_symbol) (finfo->info, buf,
+                                                            input_bfd, o,
+                                                            rel->r_offset,
+                                                            true);
+                                 if (buf != sec->name)
+                                   free (buf);
+                                 if (!ok)
+                                   return false;
+                               }
+                           }
+                       }
+                   }
+               }
+           }
 
          /* Relocate the section by invoking a back end routine.
 
@@ -6878,7 +7107,8 @@ static boolean elf_gc_smash_unused_vtentry_relocs
   PARAMS ((struct elf_link_hash_entry *h, PTR dummy));
 
 /* The mark phase of garbage collection.  For a given section, mark
-   it, and all the sections which define symbols to which it refers.  */
+   it and any sections in this section's group, and all the sections
+   which define symbols to which it refers.  */
 
 static boolean
 elf_gc_mark (info, sec, gc_mark_hook)
@@ -6888,12 +7118,19 @@ elf_gc_mark (info, sec, gc_mark_hook)
        PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
                struct elf_link_hash_entry *, Elf_Internal_Sym *));
 {
-  boolean ret = true;
+  boolean ret;
+  asection *group_sec;
 
   sec->gc_mark = 1;
 
-  /* Look through the section relocs.  */
+  /* Mark all the sections in the group.  */
+  group_sec = elf_section_data (sec)->next_in_group;
+  if (group_sec && !group_sec->gc_mark)
+    if (!elf_gc_mark (info, group_sec, gc_mark_hook))
+      return false;
 
+  /* Look through the section relocs.  */
+  ret = true;
   if ((sec->flags & SEC_RELOC) != 0 && sec->reloc_count > 0)
     {
       Elf_Internal_Rela *relstart, *rel, *relend;
This page took 0.035142 seconds and 4 git commands to generate.