* elf32-mips.c: Extensive changes for a start at dynamic linking
[binutils-gdb.git] / bfd / elflink.h
index f324ebb1cdbaa9a1a260aa8bd1c2657e59b5cdb8..fde40063b4711ba57b40aab5ac0d4565cccea056 100644 (file)
@@ -110,13 +110,10 @@ elf_link_add_archive_symbols (abfd, info)
   c = bfd_ardata (abfd)->symdef_count;
   if (c == 0)
     return true;
-  defined = (boolean *) malloc (c * sizeof (boolean));
-  included = (boolean *) malloc (c * sizeof (boolean));
+  defined = (boolean *) bfd_malloc (c * sizeof (boolean));
+  included = (boolean *) bfd_malloc (c * sizeof (boolean));
   if (defined == (boolean *) NULL || included == (boolean *) NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
   memset (defined, 0, c * sizeof (boolean));
   memset (included, 0, c * sizeof (boolean));
 
@@ -279,10 +276,7 @@ elf_link_add_object_symbols (abfd, info)
              sz = bfd_section_size (abfd, s);
              msg = (char *) bfd_alloc (abfd, sz);
              if (msg == NULL)
-               {
-                 bfd_set_error (bfd_error_no_memory);
-                 goto error_return;
-               }
+               goto error_return;
 
              if (! bfd_get_section_contents (abfd, s, msg, (file_ptr) 0, sz))
                goto error_return;
@@ -331,12 +325,10 @@ elf_link_add_object_symbols (abfd, info)
       extsymoff = hdr->sh_info;
     }
 
-  buf = (Elf_External_Sym *) malloc (extsymcount * sizeof (Elf_External_Sym));
+  buf = ((Elf_External_Sym *)
+        bfd_malloc (extsymcount * sizeof (Elf_External_Sym)));
   if (buf == NULL && extsymcount != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   /* We store a pointer to the hash table entry for each external
      symbol.  */
@@ -344,10 +336,7 @@ elf_link_add_object_symbols (abfd, info)
              bfd_alloc (abfd,
                         extsymcount * sizeof (struct elf_link_hash_entry *)));
   if (sym_hash == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
   elf_sym_hashes (abfd) = sym_hash;
 
   if (elf_elfheader (abfd)->e_type != ET_DYN)
@@ -410,12 +399,9 @@ elf_link_add_object_symbols (abfd, info)
          int elfsec;
          unsigned long link;
 
-         dynbuf = (Elf_External_Dyn *) malloc ((size_t) s->_raw_size);
+         dynbuf = (Elf_External_Dyn *) bfd_malloc ((size_t) s->_raw_size);
          if (dynbuf == NULL)
-           {
-             bfd_set_error (bfd_error_no_memory);
-             goto error_return;
-           }
+           goto error_return;
 
          if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf,
                                          (file_ptr) 0, s->_raw_size))
@@ -478,6 +464,7 @@ elf_link_add_object_symbols (abfd, info)
         still implies that the section takes up space in the output
         file.  */
       abfd->sections = NULL;
+      abfd->section_count = 0;
 
       /* If this is the first dynamic object found in the link, create
         the special sections required for dynamic linking.  */
@@ -642,7 +629,7 @@ elf_link_add_object_symbols (abfd, info)
        definition = true;
 
       size_change_ok = false;
-      type_change_ok = false;
+      type_change_ok = get_elf_backend_data (abfd)->type_change_ok;
       if (info->hash->creator->flavour == bfd_target_elf_flavour)
        {
          /* We need to look up the symbol now in order to get some of
@@ -661,15 +648,16 @@ elf_link_add_object_symbols (abfd, info)
 
          /* It's OK to change the type if it used to be a weak
              definition.  */
-         type_change_ok = (h->root.type == bfd_link_hash_defweak
-                           || h->root.type == bfd_link_hash_undefweak);
+         if (h->root.type == bfd_link_hash_defweak
+             || h->root.type == bfd_link_hash_undefweak)
+           type_change_ok = true;
 
          /* It's OK to change the size if it used to be a weak
             definition, or if it used to be undefined, or if we will
-            be overriding an old definition.
-            */
-         size_change_ok = (type_change_ok
-                           || h->root.type == bfd_link_hash_undefined);
+            be overriding an old definition.  */
+         if (type_change_ok
+             || h->root.type == bfd_link_hash_undefined)
+           size_change_ok = true;
 
          /* If we are looking at a dynamic object, and this is a
             definition, we need to see if it has already been defined
@@ -1096,15 +1084,9 @@ elf_add_dynamic_entry (info, tag, val)
   BFD_ASSERT (s != NULL);
 
   newsize = s->_raw_size + sizeof (Elf_External_Dyn);
-  if (s->contents == NULL)
-    newcontents = (bfd_byte *) malloc (newsize);
-  else
-    newcontents = (bfd_byte *) realloc (s->contents, newsize);
+  newcontents = (bfd_byte *) bfd_realloc (s->contents, newsize);
   if (newcontents == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
+    return false;
 
   dyn.d_tag = tag;
   dyn.d_un.d_val = val;
@@ -1152,22 +1134,16 @@ elf_link_read_relocs (abfd, o, external_relocs, internal_relocs, keep_memory)
       if (keep_memory)
        internal_relocs = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
       else
-       internal_relocs = alloc2 = (Elf_Internal_Rela *) malloc (size);
+       internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_malloc (size);
       if (internal_relocs == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         goto error_return;
-       }
+       goto error_return;
     }
 
   if (external_relocs == NULL)
     {
-      alloc1 = (PTR) malloc ((size_t) rel_hdr->sh_size);
+      alloc1 = (PTR) bfd_malloc ((size_t) rel_hdr->sh_size);
       if (alloc1 == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         goto error_return;
-       }
+       goto error_return;
       external_relocs = alloc1;
     }
 
@@ -1345,6 +1321,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       struct elf_info_failed eif;
+      struct elf_link_hash_entry *h;
       bfd_size_type strsize;
 
       *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
@@ -1391,14 +1368,20 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       /* Add some entries to the .dynamic section.  We fill in some of the
         values later, in elf_bfd_final_link, but we must add the entries
         now so that we know the final size of the .dynamic section.  */
-      if (elf_link_hash_lookup (elf_hash_table (info), "_init", false,
-                               false, false) != NULL)
+      h =  elf_link_hash_lookup (elf_hash_table (info), "_init", false,
+                               false, false);
+      if (h != NULL
+         && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
+                                       | ELF_LINK_HASH_DEF_REGULAR)) != 0)
        {
          if (! elf_add_dynamic_entry (info, DT_INIT, 0))
            return false;
        }
-      if (elf_link_hash_lookup (elf_hash_table (info), "_fini", false,
-                               false, false) != NULL)
+      h =  elf_link_hash_lookup (elf_hash_table (info), "_fini", false,
+                                false, false);
+      if (h != NULL
+         && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
+                                       | ELF_LINK_HASH_DEF_REGULAR)) != 0)
        {
          if (! elf_add_dynamic_entry (info, DT_FINI, 0))
            return false;
@@ -1439,10 +1422,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       s->_raw_size = dynsymcount * sizeof (Elf_External_Sym);
       s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
       if (s->contents == NULL && s->_raw_size != 0)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
 
       /* The first entry in .dynsym is a dummy symbol.  */
       isym.st_value = 0;
@@ -1466,10 +1446,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       s->_raw_size = (2 + bucketcount + dynsymcount) * (ARCH_SIZE / 8);
       s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
       if (s->contents == NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
+       return false;
       memset (s->contents, 0, (size_t) s->_raw_size);
 
       put_word (output_bfd, bucketcount, s->contents);
@@ -1849,19 +1826,13 @@ elf_bfd_final_link (abfd, info)
             so we allocate it with bfd_alloc rather than malloc.  */
          rel_hdr->contents = (PTR) bfd_alloc (abfd, rel_hdr->sh_size);
          if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0)
-           {
-             bfd_set_error (bfd_error_no_memory);
-             goto error_return;
-           }
+           goto error_return;
 
          p = ((struct elf_link_hash_entry **)
-              malloc (o->reloc_count
-                      * sizeof (struct elf_link_hash_entry *)));
+              bfd_malloc (o->reloc_count
+                          * sizeof (struct elf_link_hash_entry *)));
          if (p == NULL && o->reloc_count != 0)
-           {
-             bfd_set_error (bfd_error_no_memory);
-             goto error_return;
-           }
+           goto error_return;
          elf_section_data (o)->rel_hashes = p;
          pend = p + o->reloc_count;
          for (; p < pend; p++)
@@ -1878,8 +1849,7 @@ elf_bfd_final_link (abfd, info)
   /* We have now assigned file positions for all the sections except
      .symtab and .strtab.  We start the .symtab section at the current
      file position, and write directly to it.  We build the .strtab
-     section in memory.  When we add .dynsym support, we will build
-     that in memory as well (.dynsym is smaller than .symtab).  */
+     section in memory.  */
   abfd->symcount = 0;
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   /* sh_name is set in prep_headers.  */
@@ -1907,12 +1877,9 @@ elf_bfd_final_link (abfd, info)
   else
     finfo.symbuf_size = max_sym_count;
   finfo.symbuf = ((Elf_External_Sym *)
-                 malloc (finfo.symbuf_size * sizeof (Elf_External_Sym)));
+                 bfd_malloc (finfo.symbuf_size * sizeof (Elf_External_Sym)));
   if (finfo.symbuf == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   /* Start writing out the symbol table.  The first symbol is always a
      dummy symbol.  */
@@ -1963,17 +1930,20 @@ elf_bfd_final_link (abfd, info)
 
   /* Allocate some memory to hold information read in from the input
      files.  */
-  finfo.contents = (bfd_byte *) malloc (max_contents_size);
-  finfo.external_relocs = (PTR) malloc (max_external_reloc_size);
+  finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
+  finfo.external_relocs = (PTR) bfd_malloc (max_external_reloc_size);
   finfo.internal_relocs = ((Elf_Internal_Rela *)
-                          malloc (max_internal_reloc_count
-                                  * sizeof (Elf_Internal_Rela)));
+                          bfd_malloc (max_internal_reloc_count
+                                      * sizeof (Elf_Internal_Rela)));
   finfo.external_syms = ((Elf_External_Sym *)
-                        malloc (max_sym_count * sizeof (Elf_External_Sym)));
+                        bfd_malloc (max_sym_count
+                                    * sizeof (Elf_External_Sym)));
   finfo.internal_syms = ((Elf_Internal_Sym *)
-                        malloc (max_sym_count * sizeof (Elf_Internal_Sym)));
-  finfo.indices = (long *) malloc (max_sym_count * sizeof (long));
-  finfo.sections = (asection **) malloc (max_sym_count * sizeof (asection *));
+                        bfd_malloc (max_sym_count
+                                    * sizeof (Elf_Internal_Sym)));
+  finfo.indices = (long *) bfd_malloc (max_sym_count * sizeof (long));
+  finfo.sections = ((asection **)
+                   bfd_malloc (max_sym_count * sizeof (asection *)));
   if ((finfo.contents == NULL && max_contents_size != 0)
       || (finfo.external_relocs == NULL && max_external_reloc_size != 0)
       || (finfo.internal_relocs == NULL && max_internal_reloc_count != 0)
@@ -1981,10 +1951,7 @@ elf_bfd_final_link (abfd, info)
       || (finfo.internal_syms == NULL && max_sym_count != 0)
       || (finfo.indices == NULL && max_sym_count != 0)
       || (finfo.sections == NULL && max_sym_count != 0))
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   /* Since ELF permits relocations to be against local symbols, we
      must have the local symbols available when we do the relocations.
@@ -2435,12 +2402,15 @@ elf_link_output_extsym (h, data)
      linker will complain that the symbol is undefined when the
      program is run.  We don't have to worry about symbols that are
      referenced by regular files, because we will already have issued
-     warnings for them.  */
+     warnings for them.  FIXME: _rld_new_interface is apparently
+     supposed to be undefined on Irix 5.3.  This should be handled in
+     a better way.  */
   if (! finfo->info->relocateable
       && ! finfo->info->shared
       && h->root.type == bfd_link_hash_undefined
       && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0
-      && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
+      && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0
+      && strcmp (h->root.root.string, "_rld_new_interface") != 0)
     {
       if (! ((*finfo->info->callbacks->undefined_symbol)
             (finfo->info, h->root.root.string, h->root.u.undef.abfd,
@@ -2543,6 +2513,12 @@ elf_link_output_extsym (h, data)
 
     case bfd_link_hash_indirect:
     case bfd_link_hash_warning:
+      /* We can't represent these symbols in ELF.  A warning symbol
+         may have come from a .gnu.warning.SYMBOL section anyhow.  We
+         just put the target symbol in the hash table.  If the target
+         symbol does not really exist, don't do anything.  */
+      if (h->root.u.i.link->type == bfd_link_hash_new)
+       return true;
       return (elf_link_output_extsym
              ((struct elf_link_hash_entry *) h->root.u.i.link, data));
     }
@@ -3015,6 +2991,7 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
   reloc_howto_type *howto;
   long indx;
   bfd_vma offset;
+  bfd_vma addend;
   struct elf_link_hash_entry **rel_hash_ptr;
   Elf_Internal_Shdr *rel_hdr;
 
@@ -3025,10 +3002,61 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
       return false;
     }
 
+  addend = link_order->u.reloc.p->addend;
+
+  /* Figure out the symbol index.  */
+  rel_hash_ptr = (elf_section_data (output_section)->rel_hashes
+                 + output_section->reloc_count);
+  if (link_order->type == bfd_section_reloc_link_order)
+    {
+      indx = link_order->u.reloc.p->u.section->target_index;
+      BFD_ASSERT (indx != 0);
+      *rel_hash_ptr = NULL;
+    }
+  else
+    {
+      struct elf_link_hash_entry *h;
+
+      /* Treat a reloc against a defined symbol as though it were
+         actually against the section.  */
+      h = elf_link_hash_lookup (elf_hash_table (info),
+                               link_order->u.reloc.p->u.name,
+                               false, false, true);
+      if (h != NULL
+         && (h->root.type == bfd_link_hash_defined
+             || h->root.type == bfd_link_hash_defweak))
+       {
+         asection *section;
+
+         section = h->root.u.def.section;
+         indx = section->output_section->target_index;
+         *rel_hash_ptr = NULL;
+         /* It seems that we ought to add the symbol value to the
+             addend here, but in practice it has already been added
+             because it was passed to constructor_callback.  */
+         addend += section->output_section->vma + section->output_offset;
+       }
+      else if (h != NULL)
+       {
+         /* Setting the index to -2 tells elf_link_output_extsym that
+            this symbol is used by a reloc.  */
+         h->indx = -2;
+         *rel_hash_ptr = h;
+         indx = 0;
+       }
+      else
+       {
+         if (! ((*info->callbacks->unattached_reloc)
+                (info, link_order->u.reloc.p->u.name, (bfd *) NULL,
+                 (asection *) NULL, (bfd_vma) 0)))
+           return false;
+         indx = 0;
+       }
+    }
+
   /* If this is an inplace reloc, we must write the addend into the
      object file.  */
-  if (howto->partial_inplace
-      && link_order->u.reloc.p->addend != 0)
+  if (howto->partial_inplace && addend != 0)
     {
       bfd_size_type size;
       bfd_reloc_status_type rstat;
@@ -3038,12 +3066,8 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
       size = bfd_get_reloc_size (howto);
       buf = (bfd_byte *) bfd_zmalloc (size);
       if (buf == (bfd_byte *) NULL)
-       {
-         bfd_set_error (bfd_error_no_memory);
-         return false;
-       }
-      rstat = _bfd_relocate_contents (howto, output_bfd,
-                                     link_order->u.reloc.p->addend, buf);
+       return false;
+      rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf);
       switch (rstat)
        {
        case bfd_reloc_ok:
@@ -3058,8 +3082,8 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
                   ? bfd_section_name (output_bfd,
                                       link_order->u.reloc.p->u.section)
                   : link_order->u.reloc.p->u.name),
-                 howto->name, link_order->u.reloc.p->addend,
-                 (bfd *) NULL, (asection *) NULL, (bfd_vma) 0)))
+                 howto->name, addend, (bfd *) NULL, (asection *) NULL,
+                 (bfd_vma) 0)))
            {
              free (buf);
              return false;
@@ -3073,40 +3097,6 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
        return false;
     }
 
-  /* Figure out the symbol index.  */
-  rel_hash_ptr = (elf_section_data (output_section)->rel_hashes
-                 + output_section->reloc_count);
-  if (link_order->type == bfd_section_reloc_link_order)
-    {
-      indx = link_order->u.reloc.p->u.section->target_index;
-      BFD_ASSERT (indx != 0);
-      *rel_hash_ptr = NULL;
-    }
-  else
-    {
-      struct elf_link_hash_entry *h;
-
-      h = elf_link_hash_lookup (elf_hash_table (info),
-                               link_order->u.reloc.p->u.name,
-                               false, false, true);
-      if (h != NULL)
-       {
-         /* Setting the index to -2 tells elf_link_output_extsym that
-            this symbol is used by a reloc.  */
-         h->indx = -2;
-         *rel_hash_ptr = h;
-         indx = 0;
-       }
-      else
-       {
-         if (! ((*info->callbacks->unattached_reloc)
-                (info, link_order->u.reloc.p->u.name, (bfd *) NULL,
-                 (asection *) NULL, (bfd_vma) 0)))
-           return false;
-         indx = 0;
-       }
-    }
-
   /* The address of a reloc is relative to the section in a
      relocateable file, and is a virtual address in an executable
      file.  */
@@ -3134,7 +3124,7 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order)
 
       irela.r_offset = offset;
       irela.r_info = ELF_R_INFO (indx, howto->type);
-      irela.r_addend = link_order->u.reloc.p->addend;
+      irela.r_addend = addend;
       erela = ((Elf_External_Rela *) rel_hdr->contents
               + output_section->reloc_count);
       elf_swap_reloca_out (output_bfd, &irela, erela);