* elf32-i386.c (elf_i386_check_relocs): Don't make syms dynamic
[deliverable/binutils-gdb.git] / bfd / elf32-i386.c
index b79eb0d30c63b396eeac7b9dcb563db2523a8894..e76e75b01312f2680efbf396b288a1ef57c6f2d2 100644 (file)
@@ -43,12 +43,10 @@ static boolean elf_i386_check_relocs
           const Elf_Internal_Rela *));
 static boolean elf_i386_adjust_dynamic_symbol
   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
-static boolean allocate_plt_and_got
+static boolean allocate_plt_and_got_and_discard_relocs
   PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_i386_size_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
-static boolean discard_copies
-  PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_i386_relocate_section
   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
           Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
@@ -359,18 +357,15 @@ static const bfd_byte elf_i386_pic_plt_entry[PLT_ENTRY_SIZE] =
 };
 
 /* The i386 linker needs to keep track of the number of relocs that it
-   decides to copy in check_relocs for each symbol.  This is so that
-   it can discard PC relative relocs if it doesn't need them when
-   linking with -Bsymbolic.  We store the information in a field
-   extending the regular ELF linker hash table.  */
-
-/* This structure keeps track of the number of PC relative relocs we
-   have copied for a given symbol.  */
+   decides to copy as dynamic relocs in check_relocs for each symbol.
+   This is so that it can later discard them if they are found to be
+   unnecessary.  We store the information in a field extending the
+   regular ELF linker hash table.  */
 
-struct elf_i386_pcrel_relocs_copied
+struct elf_i386_dyn_relocs
 {
   /* Next section.  */
-  struct elf_i386_pcrel_relocs_copied *next;
+  struct elf_i386_dyn_relocs *next;
   /* A section in dynobj.  */
   asection *section;
   /* Number of relocs copied in this section.  */
@@ -384,7 +379,7 @@ struct elf_i386_link_hash_entry
   struct elf_link_hash_entry root;
 
   /* Number of PC relative relocs copied for this symbol.  */
-  struct elf_i386_pcrel_relocs_copied *pcrel_relocs_copied;
+  struct elf_i386_dyn_relocs *dyn_relocs;
 };
 
 /* i386 ELF linker hash table.  */
@@ -434,7 +429,7 @@ elf_i386_link_hash_newfunc (entry, table, string)
                                     table, string));
   if (ret != (struct elf_i386_link_hash_entry *) NULL)
     {
-      ret->pcrel_relocs_copied = NULL;
+      ret->dyn_relocs = NULL;
     }
 
   return (struct bfd_hash_entry *) ret;
@@ -591,14 +586,15 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 
       /* Some relocs require a global offset table.  */
-      if (dynobj == NULL)
+      if (htab->sgot == NULL)
        {
          switch (ELF32_R_TYPE (rel->r_info))
            {
            case R_386_GOT32:
            case R_386_GOTOFF:
            case R_386_GOTPC:
-             elf_hash_table (info)->dynobj = dynobj = abfd;
+             if (dynobj == NULL)
+               htab->root.dynobj = dynobj = abfd;
              if (!create_got_section (dynobj, info))
                return false;
              break;
@@ -615,21 +611,13 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
          if (h != NULL)
            {
              if (h->got.refcount == -1)
-               {
-                 /* Make sure this symbol is output as a dynamic symbol.  */
-                 if (h->dynindx == -1)
-                   {
-                     if (! bfd_elf32_link_record_dynamic_symbol (info, h))
-                       return false;
-                   }
-                 h->got.refcount = 1;
-               }
+               h->got.refcount = 1;
              else
                h->got.refcount += 1;
            }
          else
            {
-             /* This is a global offset table entry for a local symbol.  */
+             /* This is a global offset table entry for a local symbol.  */
              if (local_got_refcounts == NULL)
                {
                  size_t size;
@@ -651,14 +639,14 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
 
        case R_386_PLT32:
          /* This symbol requires a procedure linkage table entry.  We
-             actually build the entry in adjust_dynamic_symbol,
-             because this might be a case of linking PIC code which is
-             never referenced by a dynamic object, in which case we
-             don't need to generate a procedure linkage table entry
-             after all.  */
+            actually build the entry in adjust_dynamic_symbol,
+            because this might be a case of linking PIC code which is
+            never referenced by a dynamic object, in which case we
+            don't need to generate a procedure linkage table entry
+            after all.  */
 
          /* If this is a local symbol, we resolve it directly without
-             creating a procedure linkage table entry.  */
+            creating a procedure linkage table entry.  */
          if (h == NULL)
            continue;
 
@@ -673,19 +661,19 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
 
        case R_386_32:
        case R_386_PC32:
-         if (h != NULL)
+         if (h != NULL && !info->shared)
            {
-             h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
-
-             if (!info->shared)
-               {
-                 /* We may need a .plt entry if the function this
-                    reloc refers to is in a shared lib.  */
-                 if (h->plt.refcount == -1)
-                   h->plt.refcount = 1;
-                 else
-                   h->plt.refcount += 1;
-               }
+             /* If this reloc is in a read-only section, we might
+                need a copy reloc.  */
+             if ((sec->flags & SEC_READONLY) != 0)
+               h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
+
+             /* We may need a .plt entry if the function this reloc
+                refers to is in a shared lib.  */
+             if (h->plt.refcount == -1)
+               h->plt.refcount = 1;
+             else
+               h->plt.refcount += 1;
            }
 
          /* If we are creating a shared library, and this is a reloc
@@ -703,19 +691,33 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
             storing information in the relocs_copied field of the hash
             table entry.  A similar situation occurs when creating
             shared libraries and symbol visibility changes render the
-            symbol local.  */
-         if (info->shared
-             && (sec->flags & SEC_ALLOC) != 0
-             && (ELF32_R_TYPE (rel->r_info) != R_386_PC32
-                 || (h != NULL
-                     && (! info->symbolic
-                         || h->root.type == bfd_link_hash_defweak
-                         || (h->elf_link_hash_flags
-                             & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+            symbol local.
+            If on the other hand, we are creating an executable, we
+            may need to keep relocations for symbols satisfied by a
+            dynamic library if we manage to avoid copy relocs for the
+            symbol.  */
+         if ((info->shared
+              && (sec->flags & SEC_ALLOC) != 0
+              && (ELF32_R_TYPE (rel->r_info) != R_386_PC32
+                  || (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
+                 && h != NULL
+                 && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
+                 && (h->root.type == bfd_link_hash_defweak
+                     || (h->elf_link_hash_flags
+                         & ELF_LINK_HASH_DEF_REGULAR) == 0)))
            {
-             /* When creating a shared object, we must copy these
-                reloc types into the output file.  We create a reloc
-                section in dynobj and make room for this reloc.  */
+             /* We must copy these reloc types into the output file.
+                Create a reloc section in dynobj and make room for
+                this reloc.  */
+             if (dynobj == NULL)
+               htab->root.dynobj = dynobj = abfd;
+
              if (sreloc == NULL)
                {
                  const char *name;
@@ -767,26 +769,27 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
                 that this function is only called if we are using an
                 elf_i386 linker hash table, which means that h is
                 really a pointer to an elf_i386_link_hash_entry.  */
-             if (h != NULL
-                 && ELF32_R_TYPE (rel->r_info) == R_386_PC32)
+             if (!info->shared
+                 || (h != NULL
+                     && ELF32_R_TYPE (rel->r_info) == R_386_PC32))
                {
                  struct elf_i386_link_hash_entry *eh;
-                 struct elf_i386_pcrel_relocs_copied *p;
+                 struct elf_i386_dyn_relocs *p;
 
                  eh = (struct elf_i386_link_hash_entry *) h;
 
-                 for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next)
+                 for (p = eh->dyn_relocs; p != NULL; p = p->next)
                    if (p->section == sreloc)
                      break;
 
                  if (p == NULL)
                    {
-                     p = ((struct elf_i386_pcrel_relocs_copied *)
+                     p = ((struct elf_i386_dyn_relocs *)
                           bfd_alloc (dynobj, sizeof *p));
                      if (p == NULL)
                        return false;
-                     p->next = eh->pcrel_relocs_copied;
-                     eh->pcrel_relocs_copied = p;
+                     p->next = eh->dyn_relocs;
+                     eh->dyn_relocs = p;
                      p->section = sreloc;
                      p->count = 0;
                    }
@@ -955,17 +958,6 @@ elf_i386_adjust_dynamic_symbol (info, h)
   htab = elf_i386_hash_table (info);
   dynobj = htab->root.dynobj;
 
-  /* Make sure we know what is going on here.  */
-  BFD_ASSERT (dynobj != NULL
-             && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
-                 || h->weakdef != NULL
-                 || ((h->elf_link_hash_flags
-                      & ELF_LINK_HASH_DEF_DYNAMIC) != 0
-                     && (h->elf_link_hash_flags
-                         & ELF_LINK_HASH_REF_REGULAR) != 0
-                     && (h->elf_link_hash_flags
-                         & ELF_LINK_HASH_DEF_REGULAR) == 0)));
-
   /* If this is a function, put it in the procedure linkage table.  We
      will fill in the contents of the procedure linkage table later,
      when we know the address of the .got section.  */
@@ -984,14 +976,6 @@ elf_i386_adjust_dynamic_symbol (info, h)
             linkage table, and we can just do a PC32 reloc instead.  */
          h->plt.refcount = (bfd_vma) -1;
          h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
-         return true;
-       }
-
-      /* Make sure this symbol is output as a dynamic symbol.  */
-      if (h->dynindx == -1)
-       {
-         if (! bfd_elf32_link_record_dynamic_symbol (info, h))
-           return false;
        }
 
       return true;
@@ -1042,7 +1026,8 @@ elf_i386_adjust_dynamic_symbol (info, h)
      same memory location for the variable.  */
 
   s = htab->sdynbss;
-  BFD_ASSERT (s != NULL);
+  if (s == NULL)
+    abort ();
 
   /* We must generate a R_386_COPY reloc to tell the dynamic linker to
      copy the initial value out of the dynamic object and into the
@@ -1053,7 +1038,8 @@ elf_i386_adjust_dynamic_symbol (info, h)
       asection *srel;
 
       srel = htab->srelbss;
-      BFD_ASSERT (srel != NULL);
+      if (srel == NULL)
+       abort ();
       srel->_raw_size += sizeof (Elf32_External_Rel);
       h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
     }
@@ -1095,16 +1081,19 @@ elf_i386_adjust_dynamic_symbol (info, h)
        || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
 
 /* Allocate space in .plt, .got and associated reloc sections for
-   global syms.  */
+   global syms. Also discards space allocated for relocs in the
+   check_relocs function that we subsequently have found to be
+   unneeded.  */
 
 static boolean
-allocate_plt_and_got (h, inf)
+allocate_plt_and_got_and_discard_relocs (h, inf)
      struct elf_link_hash_entry *h;
      PTR inf;
 {
   struct bfd_link_info *info;
   struct elf_i386_link_hash_table *htab;
   asection *s;
+  struct elf_i386_link_hash_entry *eh;
 
   if (h->root.type == bfd_link_hash_indirect
       || h->root.type == bfd_link_hash_warning)
@@ -1116,8 +1105,18 @@ allocate_plt_and_got (h, inf)
   if (htab->root.dynamic_sections_created
       && h->plt.refcount > 0)
     {
+      /* Make sure this symbol is output as a dynamic symbol.
+        Undefined weak syms won't yet be marked as dynamic.  */
+      if (h->dynindx == -1
+         && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+       {
+         if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+           return false;
+       }
+
       s = htab->splt;
-      BFD_ASSERT (s != NULL);
+      if (s == NULL)
+       abort ();
 
       /* If this is the first .plt entry, make room for the special
         first entry.  */
@@ -1144,14 +1143,16 @@ allocate_plt_and_got (h, inf)
       /* We also need to make an entry in the .got.plt section, which
         will be placed in the .got section by the linker script.  */
       s = htab->sgotplt;
-      BFD_ASSERT (s != NULL);
+      if (s == NULL)
+       abort ();
       s->_raw_size += 4;
 
       if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
        {
          /* We also need to make an entry in the .rel.plt section.  */
          s = htab->srelplt;
-         BFD_ASSERT (s != NULL);
+         if (s == NULL)
+           abort ();
          s->_raw_size += sizeof (Elf32_External_Rel);
        }
     }
@@ -1165,6 +1166,15 @@ allocate_plt_and_got (h, inf)
     {
       boolean dyn;
 
+      /* Make sure this symbol is output as a dynamic symbol.
+        Undefined weak syms won't yet be marked as dynamic.  */
+      if (h->dynindx == -1
+         && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+       {
+         if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+           return false;
+       }
+
       s = htab->sgot;
       h->got.offset = s->_raw_size;
       s->_raw_size += 4;
@@ -1175,6 +1185,48 @@ allocate_plt_and_got (h, inf)
   else
     h->got.offset = (bfd_vma) -1;
 
+  /* In the shared -Bsymbolic case, discard space allocated for
+     dynamic relocs against symbols which turn out to be defined
+     in regular objects.  For the normal shared case, discard space
+     for relocs that have become local due to symbol visibility
+     changes.  For the non-shared case, discard space for symbols
+     which turn out to need copy relocs or are not dynamic.  */
+
+  eh = (struct elf_i386_link_hash_entry *) h;
+  if (eh->dyn_relocs == NULL)
+    return true;
+
+  if (!info->shared
+      && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
+      && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+         || h->root.type == bfd_link_hash_undefweak
+         || h->root.type == bfd_link_hash_undefined))
+    {
+      /* Make sure this symbol is output as a dynamic symbol.
+        Undefined weak syms won't yet be marked as dynamic.  */
+      if (h->dynindx == -1
+         && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+       {
+         if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+           return false;
+       }
+
+      /* If that succeeded, we know we'll be keeping all the relocs.  */
+      if (h->dynindx != -1)
+       return true;
+    }
+
+  if (!info->shared
+      || ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
+         && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
+             || info->symbolic)))
+    {
+      struct elf_i386_dyn_relocs *c;
+
+      for (c = eh->dyn_relocs; c != NULL; c = c->next)
+       c->section->_raw_size -= c->count * sizeof (Elf32_External_Rel);
+    }
+
   return true;
 }
 
@@ -1190,77 +1242,69 @@ elf_i386_size_dynamic_sections (output_bfd, info)
   asection *s;
   boolean relocs;
   boolean reltext;
+  bfd *i;
 
   htab = elf_i386_hash_table (info);
   dynobj = htab->root.dynobj;
-  BFD_ASSERT (dynobj != NULL);
+  if (dynobj == NULL)
+    abort ();
 
   if (htab->root.dynamic_sections_created)
     {
-      bfd *i;
-
       /* Set the contents of the .interp section to the interpreter.  */
       if (! info->shared)
        {
          s = bfd_get_section_by_name (dynobj, ".interp");
-         BFD_ASSERT (s != NULL);
+         if (s == NULL)
+           abort ();
          s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
          s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
        }
+    }
 
-      /* Set up .got offsets for local syms.  */
-      for (i = info->input_bfds; i; i = i->link_next)
-       {
-         bfd_signed_vma *local_got;
-         bfd_signed_vma *end_local_got;
-         bfd_size_type locsymcount;
-         Elf_Internal_Shdr *symtab_hdr;
-         asection *srel;
+  /* Set up .got offsets for local syms.  */
+  for (i = info->input_bfds; i; i = i->link_next)
+    {
+      bfd_signed_vma *local_got;
+      bfd_signed_vma *end_local_got;
+      bfd_size_type locsymcount;
+      Elf_Internal_Shdr *symtab_hdr;
+      asection *srel;
 
-         if (bfd_get_flavour (i) != bfd_target_elf_flavour)
-           continue;
+      if (bfd_get_flavour (i) != bfd_target_elf_flavour)
+       continue;
 
-         local_got = elf_local_got_refcounts (i);
-         if (!local_got)
-           continue;
+      local_got = elf_local_got_refcounts (i);
+      if (!local_got)
+       continue;
 
-         symtab_hdr = &elf_tdata (i)->symtab_hdr;
-         locsymcount = symtab_hdr->sh_info;
-         end_local_got = local_got + locsymcount;
-         s = htab->sgot;
-         srel = htab->srelgot;
-         for (; local_got < end_local_got; ++local_got)
+      symtab_hdr = &elf_tdata (i)->symtab_hdr;
+      locsymcount = symtab_hdr->sh_info;
+      end_local_got = local_got + locsymcount;
+      s = htab->sgot;
+      srel = htab->srelgot;
+      for (; local_got < end_local_got; ++local_got)
+       {
+         if (*local_got > 0)
            {
-             if (*local_got > 0)
-               {
-                 *local_got = s->_raw_size;
-                 s->_raw_size += 4;
-                 if (info->shared)
-                   srel->_raw_size += sizeof (Elf32_External_Rel);
-               }
-             else
-               *local_got = (bfd_vma) -1;
+             *local_got = s->_raw_size;
+             s->_raw_size += 4;
+             if (info->shared)
+               srel->_raw_size += sizeof (Elf32_External_Rel);
            }
+         else
+           *local_got = (bfd_vma) -1;
        }
     }
 
-  /* Allocate global sym .plt and .got entries.  */
+  /* Allocate global sym .plt and .got entries.  Also discard all
+     unneeded relocs.  */
   elf_link_hash_traverse (&htab->root,
-                         allocate_plt_and_got,
+                         allocate_plt_and_got_and_discard_relocs,
                          (PTR) info);
 
-  /* If this is a -Bsymbolic shared link, then we need to discard all
-     PC relative relocs against symbols defined in a regular object.
-     We allocated space for them in the check_relocs routine, but we
-     will not fill them in in the relocate_section routine.  */
-  if (info->shared)
-    elf_link_hash_traverse (&htab->root,
-                           discard_copies,
-                           (PTR) info);
-
-  /* The check_relocs and adjust_dynamic_symbol entry points have
-     determined the sizes of the various dynamic sections.  Allocate
-     memory for them.  */
+  /* We now have determined the sizes of the various dynamic sections.
+     Allocate memory for them.  */
   relocs = false;
   reltext = false;
   for (s = dynobj->sections; s != NULL; s = s->next)
@@ -1294,7 +1338,7 @@ elf_i386_size_dynamic_sections (output_bfd, info)
              asection *target;
 
              /* Remember whether there are any reloc sections other
-                 than .rel.plt.  */
+                than .rel.plt.  */
              if (s != htab->srelplt)
                {
                  const char *outname;
@@ -1384,41 +1428,6 @@ elf_i386_size_dynamic_sections (output_bfd, info)
   return true;
 }
 
-/* This function is called via elf_link_hash_traverse if we are
-   creating a shared object.  In the -Bsymbolic case, it discards the
-   space allocated to copy PC relative relocs against symbols which
-   are defined in regular objects.  For the normal non-symbolic case,
-   we also discard space for relocs that have become local due to
-   symbol visibility changes.  We allocated space for them in the
-   check_relocs routine, but we won't fill them in in the
-   relocate_section routine.  */
-
-static boolean
-discard_copies (h, inf)
-     struct elf_link_hash_entry *h;
-     PTR inf;
-{
-  struct elf_i386_pcrel_relocs_copied *s;
-  struct bfd_link_info *info;
-  struct elf_i386_link_hash_entry *eh;
-
-  info = (struct bfd_link_info *) inf;
-  eh = (struct elf_i386_link_hash_entry *) h;
-
-  /* If a symbol has been forced local or we have found a regular
-     definition for the symbolic link case, then we won't be needing
-     any relocs.  */
-  if ((eh->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
-      && ((eh->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
-         || info->symbolic))
-    {
-      for (s = eh->pcrel_relocs_copied; s != NULL; s = s->next)
-       s->section->_raw_size -= s->count * sizeof (Elf32_External_Rel);
-    }
-
-  return true;
-}
-
 /* Relocate an i386 ELF section.  */
 
 static boolean
@@ -1459,7 +1468,9 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       asection *sec;
+      bfd_vma off;
       bfd_vma relocation;
+      boolean unresolved_reloc;
       bfd_reloc_status_type r;
       unsigned int indx;
 
@@ -1506,6 +1517,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
       h = NULL;
       sym = NULL;
       sec = NULL;
+      unresolved_reloc = false;
       if (r_symndx < symtab_hdr->sh_info)
        {
          sym = local_syms + r_symndx;
@@ -1520,50 +1532,18 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
          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;
+
          relocation = 0;
          if (h->root.type == bfd_link_hash_defined
              || h->root.type == bfd_link_hash_defweak)
            {
              sec = h->root.u.def.section;
-             if (r_type == R_386_GOTPC
-                 || (r_type == R_386_PLT32
-                     && htab->splt != NULL
-                     && h->plt.offset != (bfd_vma) -1)
-                 || (r_type == R_386_GOT32
-                     && (WILL_CALL_FINISH_DYNAMIC_SYMBOL
-                         (htab->root.dynamic_sections_created, 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)))
-                 || (info->shared
-                     && ((! info->symbolic && h->dynindx != -1)
-                         || (h->elf_link_hash_flags
-                             & ELF_LINK_HASH_DEF_REGULAR) == 0)
-                     && (r_type == R_386_32
-                         || r_type == R_386_PC32)
-                     && ((input_section->flags & SEC_ALLOC) != 0
-                         /* DWARF will emit R_386_32 relocations in its
-                            sections against symbols defined externally
-                            in shared libraries.  We can't do anything
-                            with them here.  */
-                         || ((input_section->flags & SEC_DEBUGGING) != 0
-                             && (h->elf_link_hash_flags
-                                 & ELF_LINK_HASH_DEF_DYNAMIC) != 0))))
-               /* In these cases, we don't need the relocation
-                  value.  We check specially because in some
-                  obscure cases sec->output_section will be NULL.  */
-               ;
-             else if (sec->output_section == NULL)
-               (*_bfd_error_handler)
-                 (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
-                  bfd_get_filename (input_bfd),
-                  bfd_get_section_name (input_bfd, input_section),
-                  (long) rel->r_offset,
-                  h->root.root.string);
+             if (sec->output_section == NULL)
+               /* Set a flag that will be cleared later if we find a
+                  relocation value for this symbol.  output_section
+                  is typically NULL for symbols satisfied by a shared
+                  library.  */
+               unresolved_reloc = true;
              else
                relocation = (h->root.u.def.value
                              + sec->output_section->vma
@@ -1591,16 +1571,14 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_386_GOT32:
          /* Relocation is to the entry for this symbol in the global
             offset table.  */
-         BFD_ASSERT (htab->sgot != NULL);
+         if (htab->sgot == NULL)
+           abort ();
 
          if (h != NULL)
            {
-             bfd_vma off;
              boolean dyn;
 
              off = h->got.offset;
-             BFD_ASSERT (off != (bfd_vma) -1);
-
              dyn = htab->root.dynamic_sections_created;
              if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
                  || (info->shared
@@ -1630,21 +1608,19 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
                      h->got.offset |= 1;
                    }
                }
-
-             relocation = htab->sgot->output_offset + off;
+             else
+               unresolved_reloc = false;
            }
          else
            {
-             bfd_vma off;
-
-             BFD_ASSERT (local_got_offsets != NULL
-                         && local_got_offsets[r_symndx] != (bfd_vma) -1);
+             if (local_got_offsets == NULL)
+               abort ();
 
              off = local_got_offsets[r_symndx];
 
              /* The offset must always be a multiple of 4.  We use
-                 the least significant bit to record whether we have
-                 already generated the necessary reloc.  */
+                the least significant bit to record whether we have
+                already generated the necessary reloc.  */
              if ((off & 1) != 0)
                off &= ~1;
              else
@@ -1658,7 +1634,8 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
                      Elf_Internal_Rel outrel;
 
                      srelgot = htab->srelgot;
-                     BFD_ASSERT (srelgot != NULL);
+                     if (srelgot == NULL)
+                       abort ();
 
                      outrel.r_offset = (htab->sgot->output_section->vma
                                         + htab->sgot->output_offset
@@ -1673,10 +1650,12 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
 
                  local_got_offsets[r_symndx] |= 1;
                }
-
-             relocation = htab->sgot->output_offset + off;
            }
 
+         if (off >= (bfd_vma) -2)
+           abort ();
+
+         relocation = htab->sgot->output_offset + off;
          break;
 
        case R_386_GOTOFF:
@@ -1689,12 +1668,12 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
             permitted by the ABI, we might have to change this
             calculation.  */
          relocation -= htab->sgot->output_section->vma;
-
          break;
 
        case R_386_GOTPC:
          /* Use global offset table as symbol value.  */
          relocation = htab->sgot->output_section->vma;
+         unresolved_reloc = false;
          break;
 
        case R_386_PLT32:
@@ -1702,7 +1681,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
             procedure linkage table.  */
 
          /* Resolve a PLT32 reloc against a local symbol directly,
-             without using the procedure linkage table.  */
+            without using the procedure linkage table.  */
          if (h == NULL)
            break;
 
@@ -1710,27 +1689,36 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
              || htab->splt == NULL)
            {
              /* We didn't make a PLT entry for this symbol.  This
-                 happens when statically linking PIC code, or when
-                 using -Bsymbolic.  */
+                happens when statically linking PIC code, or when
+                using -Bsymbolic.  */
              break;
            }
 
          relocation = (htab->splt->output_section->vma
                        + htab->splt->output_offset
                        + h->plt.offset);
-
+         unresolved_reloc = false;
          break;
 
        case R_386_32:
        case R_386_PC32:
-         if (info->shared
-             && (input_section->flags & SEC_ALLOC) != 0
-             && (r_type != R_386_PC32
-                 || (h != NULL
-                     && h->dynindx != -1
-                     && (! info->symbolic
-                         || (h->elf_link_hash_flags
-                             & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+         if ((info->shared
+              && (input_section->flags & SEC_ALLOC) != 0
+              && (r_type != R_386_PC32
+                  || (h != NULL
+                      && h->dynindx != -1
+                      && (! info->symbolic
+                          || (h->elf_link_hash_flags
+                              & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+             || (!info->shared
+                 && (input_section->flags & SEC_ALLOC) != 0
+                 && h != NULL
+                 && h->dynindx != -1
+                 && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
+                 && ((h->elf_link_hash_flags
+                      & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+                     || h->root.type == bfd_link_hash_undefweak
+                     || h->root.type == bfd_link_hash_undefined)))
            {
              Elf_Internal_Rel outrel;
              boolean skip, relocate;
@@ -1756,19 +1744,22 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
                                 name + 4) != 0)
                    {
                      if (input_bfd->my_archive)
-                       (*_bfd_error_handler) (_("%s(%s): bad relocation section name `%s\'"),
-                                              bfd_get_filename (input_bfd->my_archive),
-                                              bfd_get_filename (input_bfd),
-                                              name);
+                       (*_bfd_error_handler)\
+                         (_("%s(%s): bad relocation section name `%s\'"),
+                          bfd_get_filename (input_bfd->my_archive),
+                          bfd_get_filename (input_bfd),
+                          name);
                      else
-                       (*_bfd_error_handler) (_("%s: bad relocation section name `%s\'"),
-                                              bfd_get_filename (input_bfd),
-                                              name);
+                       (*_bfd_error_handler)
+                         (_("%s: bad relocation section name `%s\'"),
+                          bfd_get_filename (input_bfd),
+                          name);
                      return false;
                    }
 
                  sreloc = bfd_get_section_by_name (dynobj, name);
-                 BFD_ASSERT (sreloc != NULL);
+                 if (sreloc == NULL)
+                   abort ();
                }
 
              skip = false;
@@ -1780,8 +1771,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
                  bfd_vma off;
 
                  off = (_bfd_stab_section_offset
-                        (output_bfd, &elf_hash_table (info)->stab_info,
-                         input_section,
+                        (output_bfd, htab->root.stab_info, input_section,
                          &elf_section_data (input_section)->stab_info,
                          rel->r_offset));
                  if (off == (bfd_vma) -1)
@@ -1797,30 +1787,23 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
                  memset (&outrel, 0, sizeof outrel);
                  relocate = false;
                }
-             else if (r_type == R_386_PC32)
+             else if (h != NULL
+                      && h->dynindx != -1
+                      && (r_type == R_386_PC32
+                          || !info->shared
+                          || !info->symbolic
+                          || (h->elf_link_hash_flags
+                              & ELF_LINK_HASH_DEF_REGULAR) == 0))
+
                {
-                 BFD_ASSERT (h != NULL && h->dynindx != -1);
                  relocate = false;
-                 outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_PC32);
+                 outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
                }
              else
                {
-                 /* h->dynindx may be -1 if this symbol was marked to
-                     become local.  */
-                 if (h == NULL
-                     || ((info->symbolic || h->dynindx == -1)
-                         && (h->elf_link_hash_flags
-                             & ELF_LINK_HASH_DEF_REGULAR) != 0))
-                   {
-                     relocate = true;
-                     outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
-                   }
-                 else
-                   {
-                     BFD_ASSERT (h->dynindx != -1);
-                     relocate = false;
-                     outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_32);
-                   }
+                 /* This symbol is local, or marked to become local.  */
+                 relocate = true;
+                 outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
                }
 
              bfd_elf32_swap_reloc_out (output_bfd, &outrel,
@@ -1843,40 +1826,58 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
          break;
        }
 
+      /* FIXME: Why do we allow debugging sections to escape this error?
+        More importantly, why do we not emit dynamic relocs for
+        R_386_32 above in debugging sections (which are ! SEC_ALLOC)?
+        If we had emitted the dynamic reloc, we could remove the
+        fudge here.  */
+      if (unresolved_reloc
+         && !(info->shared
+              && (input_section->flags & SEC_DEBUGGING) != 0
+              && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
+       (*_bfd_error_handler)
+         (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
+          bfd_get_filename (input_bfd),
+          bfd_get_section_name (input_bfd, input_section),
+          (long) rel->r_offset,
+          h->root.root.string);
+
       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
                                    contents, rel->r_offset,
                                    relocation, (bfd_vma) 0);
 
-      if (r != bfd_reloc_ok)
+      switch (r)
        {
-         switch (r)
-           {
-           default:
-           case bfd_reloc_outofrange:
-             abort ();
-           case bfd_reloc_overflow:
+       case bfd_reloc_ok:
+         break;
+
+       case bfd_reloc_overflow:
+         {
+           const char *name;
+
+           if (h != NULL)
+             name = h->root.root.string;
+           else
              {
-               const char *name;
-
-               if (h != NULL)
-                 name = h->root.root.string;
-               else
-                 {
-                   name = bfd_elf_string_from_elf_section (input_bfd,
-                                                           symtab_hdr->sh_link,
-                                                           sym->st_name);
-                   if (name == NULL)
-                     return false;
-                   if (*name == '\0')
-                     name = bfd_section_name (input_bfd, sec);
-                 }
-               if (! ((*info->callbacks->reloc_overflow)
-                      (info, name, howto->name, (bfd_vma) 0,
-                       input_bfd, input_section, rel->r_offset)))
+               name = bfd_elf_string_from_elf_section (input_bfd,
+                                                       symtab_hdr->sh_link,
+                                                       sym->st_name);
+               if (name == NULL)
                  return false;
+               if (*name == '\0')
+                 name = bfd_section_name (input_bfd, sec);
              }
-             break;
-           }
+           if (! ((*info->callbacks->reloc_overflow)
+                  (info, name, howto->name, (bfd_vma) 0,
+                   input_bfd, input_section, rel->r_offset)))
+             return false;
+         }
+         break;
+
+       default:
+       case bfd_reloc_outofrange:
+         abort ();
+         break;
        }
     }
 
@@ -1908,10 +1909,11 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
       /* This symbol has an entry in the procedure linkage table.  Set
         it up.  */
 
-      BFD_ASSERT (h->dynindx != -1
-                 && htab->splt != NULL
-                 && htab->sgotplt != NULL
-                 && htab->srelplt != NULL);
+      if (h->dynindx == -1
+         || htab->splt == NULL
+         || htab->sgotplt == NULL
+         || htab->srelplt == NULL)
+       abort ();
 
       /* Get the index in the procedure linkage table which
         corresponds to this symbol.  This is the index of this symbol
@@ -1980,7 +1982,8 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
       /* This symbol has an entry in the global offset table.  Set it
         up.  */
 
-      BFD_ASSERT (htab->sgot != NULL && htab->srelgot != NULL);
+      if (htab->sgot == NULL || htab->srelgot == NULL)
+       abort ();
 
       rel.r_offset = (htab->sgot->output_section->vma
                      + htab->sgot->output_offset
@@ -2020,10 +2023,11 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
 
       /* This symbol needs a copy reloc.  Set it up.  */
 
-      BFD_ASSERT (h->dynindx != -1
-                 && (h->root.type == bfd_link_hash_defined
-                     || h->root.type == bfd_link_hash_defweak)
-                 && htab->srelbss != NULL);
+      if (h->dynindx == -1
+         || (h->root.type != bfd_link_hash_defined
+             && h->root.type != bfd_link_hash_defweak)
+         || htab->srelbss == NULL)
+       abort ();
 
       rel.r_offset = (h->root.u.def.value
                      + h->root.u.def.section->output_section->vma
@@ -2056,15 +2060,14 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
 
   htab = elf_i386_hash_table (info);
   dynobj = htab->root.dynobj;
-
-  BFD_ASSERT (htab->sgot != NULL);
   sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
 
   if (htab->root.dynamic_sections_created)
     {
       Elf32_External_Dyn *dyncon, *dynconend;
 
-      BFD_ASSERT (sdyn != NULL);
+      if (sdyn == NULL || htab->sgot == NULL)
+       abort ();
 
       dyncon = (Elf32_External_Dyn *) sdyn->contents;
       dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
@@ -2148,19 +2151,21 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
        }
     }
 
-  /* Fill in the first three entries in the global offset table.  */
-  if (htab->sgotplt->_raw_size > 0)
+  if (htab->sgotplt)
     {
-      bfd_put_32 (output_bfd,
-                 (sdyn == NULL ? (bfd_vma) 0
-                  : sdyn->output_section->vma + sdyn->output_offset),
-                 htab->sgotplt->contents);
-      bfd_put_32 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 4);
-      bfd_put_32 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 8);
-    }
-
-  elf_section_data (htab->sgotplt->output_section)->this_hdr.sh_entsize = 4;
+      /* Fill in the first three entries in the global offset table.  */
+      if (htab->sgotplt->_raw_size > 0)
+       {
+         bfd_put_32 (output_bfd,
+                     (sdyn == NULL ? (bfd_vma) 0
+                      : sdyn->output_section->vma + sdyn->output_offset),
+                     htab->sgotplt->contents);
+         bfd_put_32 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 4);
+         bfd_put_32 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + 8);
+       }
 
+      elf_section_data (htab->sgotplt->output_section)->this_hdr.sh_entsize = 4;
+    }
   return true;
 }
 
@@ -2231,6 +2236,6 @@ elf_i386_fake_sections (abfd, hdr, sec)
 #define elf_backend_gc_sweep_hook            elf_i386_gc_sweep_hook
 #define elf_backend_relocate_section         elf_i386_relocate_section
 #define elf_backend_size_dynamic_sections     elf_i386_size_dynamic_sections
-#define elf_backend_fake_sections            elf_i386_fake_sections
+#define elf_backend_fake_sections            elf_i386_fake_sections
 
 #include "elf32-target.h"
This page took 0.037593 seconds and 4 git commands to generate.