bfd/
[binutils-gdb.git] / bfd / elflink.c
index 09d06167fa55772941d59a21c3ff2c5daa8b54df..7b33ae67e3454aa6d92cce99e8a02b979904b794 100644 (file)
@@ -1078,6 +1078,13 @@ _bfd_elf_merge_symbol (bfd *abfd,
       || h->root.type == bfd_link_hash_undefined)
     *size_change_ok = TRUE;
 
+  /* Skip weak definitions of symbols that are already defined.  */
+  if (newdef && olddef && newweak && !oldweak)
+    {
+      *skip = TRUE;
+      return TRUE;
+    }
+
   /* NEWDYNCOMMON and OLDDYNCOMMON indicate whether the new or old
      symbol, respectively, appears to be a common symbol in a dynamic
      object.  If a symbol appears in an uninitialized section, and is
@@ -2935,8 +2942,11 @@ elf_smash_syms (struct elf_link_hash_entry *h, void *data)
   if (h->ref_regular)
     abort ();
 
-  /* Set sym back to newly created state, but keep undefs list pointer.  */
+  /* Set sym back to newly created state, but keep undef.next if it is
+     being used as a list pointer.  */
   bh = h->root.u.undef.next;
+  if (bh == &h->root)
+    bh = NULL;
   if (bh != NULL || inf->htab->root.undefs_tail == &h->root)
     inf->twiddled = TRUE;
   (*inf->htab->root.table.newfunc) (&h->root.root,
@@ -7016,6 +7026,23 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                          && finfo->sections[r_symndx] == NULL))
                    {
                      h = sym_hashes[r_symndx - extsymoff];
+
+                     /* Badly formatted input files can contain relocs that
+                        reference non-existant symbols.  Check here so that
+                        we do not seg fault.  */
+                     if (h == NULL)
+                       {
+                         char buffer [32];
+
+                         sprintf_vma (buffer, rel->r_info);
+                         (*_bfd_error_handler)
+                           (_("error: %B contains a reloc (0x%s) for section %A "
+                              "that references a non-existent global symbol"),
+                            input_bfd, o, buffer);
+                         bfd_set_error (bfd_error_bad_value);
+                         return FALSE;
+                       }
+                     
                      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;
@@ -7031,7 +7058,9 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                    {
                      Elf_Internal_Sym *sym = isymbuf + r_symndx;
                      ps = &finfo->sections[r_symndx];
-                     sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym);
+                     sym_name = bfd_elf_sym_name (input_bfd,
+                                                  symtab_hdr,
+                                                  sym, *ps);
                    }
 
                  /* Complain if the definition comes from a
@@ -7045,6 +7074,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                            (_("`%s' referenced in section `%A' of %B: "
                               "defined in discarded section `%A' of %B"),
                             o, input_bfd, sec, sec->owner, sym_name);
+                         bfd_set_error (bfd_error_bad_value);
+                         return FALSE;
                        }
 
                      /* Try to do the best we can to support buggy old
@@ -9784,9 +9815,11 @@ _bfd_elf_provide_symbol (struct bfd_link_info *info, const char *name,
                         bfd_vma val)
 {
   struct elf_link_hash_entry *h;
+
   h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE,
                            FALSE);
-  if (h != NULL && h->root.type == bfd_link_hash_undefined)
+  if (h != NULL && (h->root.type == bfd_link_hash_undefined
+                   || h->root.type == bfd_link_hash_undefweak))
     {
       h->root.type = bfd_link_hash_defined;
       h->root.u.def.section = bfd_abs_section_ptr;