Start of sparc generic testsuite.
[deliverable/binutils-gdb.git] / bfd / elflink.h
index c47495976a26b7ff602d8281e262f0f4fd878c75..b625ae09b331aa6f9fe59385c778b14d8e61a315 100644 (file)
@@ -1,3 +1,22 @@
+/* ELF linker support.
+   Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
 /* ELF linker code.  */
 
 static boolean elf_link_add_object_symbols
@@ -28,29 +47,11 @@ elf_bfd_link_add_symbols (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
 {
-  bfd *first;
-
   switch (bfd_get_format (abfd))
     {
     case bfd_object:
       return elf_link_add_object_symbols (abfd, info);
     case bfd_archive:
-      first = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
-      if (first == NULL)
-       {
-         /* It's OK to have an empty archive.  */
-         return true;
-       }
-      if (! bfd_check_format (first, bfd_object))
-       return false;
-      if (bfd_get_flavour (first) != bfd_target_elf_flavour)
-       {
-         /* On Linux, we may have an a.out archive which got
-             recognized as an ELF archive.  Therefore, we treat all
-             archives as though they were actually of the flavour of
-             their first element.  */
-         return (*first->xvec->_bfd_link_add_symbols) (abfd, info);
-       }
       return elf_link_add_archive_symbols (abfd, info);
     default:
       bfd_set_error (bfd_error_wrong_format);
@@ -154,7 +155,8 @@ elf_link_add_archive_symbols (abfd, info)
            continue;
          if (h->root.type != bfd_link_hash_undefined)
            {
-             defined[i] = true;
+             if (h->root.type != bfd_link_hash_undefweak)
+               defined[i] = true;
              continue;
            }
 
@@ -362,7 +364,7 @@ elf_link_add_object_symbols (abfd, info)
          int elfsec;
          unsigned long link;
 
-         dynbuf = (Elf_External_Dyn *) malloc (s->_raw_size);
+         dynbuf = (Elf_External_Dyn *) malloc ((size_t) s->_raw_size);
          if (dynbuf == NULL)
            {
              bfd_set_error (bfd_error_no_memory);
@@ -397,8 +399,9 @@ elf_link_add_object_symbols (abfd, info)
                  struct bfd_elf_link_needed_list *n, **pn;
                  char *fnm, *anm;
 
-                 n = bfd_alloc (abfd,
-                                sizeof (struct bfd_elf_link_needed_list));
+                 n = (struct bfd_elf_link_needed_list *)
+                   bfd_alloc (abfd,
+                              sizeof (struct bfd_elf_link_needed_list));
                  fnm = bfd_elf_string_from_elf_section (abfd, link,
                                                         dyn.d_un.d_val);
                  if (n == NULL || fnm == NULL)
@@ -506,6 +509,7 @@ elf_link_add_object_symbols (abfd, info)
       const char *name;
       struct elf_link_hash_entry *h = NULL;
       boolean definition;
+      boolean new_weakdef;
 
       elf_swap_symbol_in (abfd, esym, &sym);
 
@@ -645,6 +649,7 @@ elf_link_add_object_symbols (abfd, info)
              false, collect, (struct bfd_link_hash_entry **) sym_hash)))
        goto error_return;
 
+      new_weakdef = false;
       if (dynamic
          && definition
          && (flags & BSF_WEAK) != 0
@@ -666,6 +671,7 @@ elf_link_add_object_symbols (abfd, info)
 
          (*sym_hash)->weakdef = weaks;
          weaks = *sym_hash;
+         new_weakdef = true;
        }
 
       /* Get the alignment of a common symbol.  */
@@ -720,7 +726,10 @@ elf_link_add_object_symbols (abfd, info)
                new_flag = ELF_LINK_HASH_DEF_DYNAMIC;
              if ((old_flags & new_flag) != 0
                  || (old_flags & (ELF_LINK_HASH_DEF_REGULAR
-                                  | ELF_LINK_HASH_REF_REGULAR)) != 0)
+                                  | ELF_LINK_HASH_REF_REGULAR)) != 0
+                 || (h->weakdef != NULL
+                     && (old_flags & (ELF_LINK_HASH_DEF_DYNAMIC
+                                      | ELF_LINK_HASH_REF_DYNAMIC)) != 0))
                dynsym = true;
            }
 
@@ -729,6 +738,14 @@ elf_link_add_object_symbols (abfd, info)
            {
              if (! _bfd_elf_link_record_dynamic_symbol (info, h))
                goto error_return;
+             if (h->weakdef != NULL
+                 && ! new_weakdef
+                 && h->weakdef->dynindx == -1)
+               {
+                 if (! _bfd_elf_link_record_dynamic_symbol (info,
+                                                            h->weakdef))
+                   goto error_return;
+               }
            }
        }
     }
@@ -1056,7 +1073,7 @@ elf_link_read_relocs (abfd, o, external_relocs, internal_relocs, keep_memory)
 
   if (external_relocs == NULL)
     {
-      alloc1 = (PTR) malloc (rel_hdr->sh_size);
+      alloc1 = (PTR) malloc ((size_t) rel_hdr->sh_size);
       if (alloc1 == NULL)
        {
          bfd_set_error (bfd_error_no_memory);
@@ -1255,6 +1272,12 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
            return false;
        }      
 
+      if (info->symbolic)
+       {
+         if (! elf_add_dynamic_entry (info, DT_SYMBOLIC, 0))
+           return false;
+       }
+
       if (rpath != NULL)
        {
          bfd_size_type indx;
@@ -1340,7 +1363,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       isym.st_other = 0;
       isym.st_shndx = 0;
       elf_swap_symbol_out (output_bfd, &isym,
-                          (char *) (Elf_External_Sym *) s->contents);
+                          (PTR) (Elf_External_Sym *) s->contents);
 
       for (i = 0; elf_buckets[i] != 0; i++)
        {
@@ -1358,7 +1381,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
          bfd_set_error (bfd_error_no_memory);
          return false;
        }
-      memset (s->contents, 0, s->_raw_size);
+      memset (s->contents, 0, (size_t) s->_raw_size);
 
       put_word (output_bfd, bucketcount, s->contents);
       put_word (output_bfd, dynsymcount, s->contents + (ARCH_SIZE / 8));
@@ -1413,15 +1436,28 @@ elf_adjust_dynamic_symbol (h, data)
   bfd *dynobj;
   struct elf_backend_data *bed;
 
+  /* If -Bsymbolic was used (which means to bind references to global
+     symbols to the definition within the shared object), and this
+     symbol was defined in a regular object, then it actually doesn't
+     need a PLT entry.  */
+  if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0
+      && eif->info->shared
+      && eif->info->symbolic
+      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
+    h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
+
   /* If this symbol does not require a PLT entry, and it is not
      defined by a dynamic object, or is not referenced by a regular
-     object, ignore it.  FIXME: Do we need to worry about symbols
-     which are defined by one dynamic object and referenced by another
-     one?  */
+     object, ignore it.  We do have to handle a weak defined symbol,
+     even if no regular object refers to it, if we decided to add it
+     to the dynamic symbol table.  FIXME: Do we normally need to worry
+     about symbols which are defined by one dynamic object and
+     referenced by another one?  */
   if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0
       && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
          || (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_REF_REGULAR) == 0
+             && (h->weakdef == NULL || h->weakdef->dynindx == -1))))
     return true;
 
   /* If we've already adjusted this symbol, don't do it again.  This
@@ -2255,7 +2291,7 @@ elf_link_output_sym (finfo, name, elfsym, input_sec)
     }
 
   elf_swap_symbol_out (finfo->output_bfd, elfsym,
-                      (char *) (finfo->symbuf + finfo->symbuf_count));
+                      (PTR) (finfo->symbuf + finfo->symbuf_count));
   ++finfo->symbuf_count;
 
   ++finfo->output_bfd->symcount;
@@ -2445,8 +2481,9 @@ elf_link_output_extsym (h, data)
        }
 
       elf_swap_symbol_out (finfo->output_bfd, &sym,
-                          (char *) ((Elf_External_Sym *) finfo->dynsym_sec->contents
-                                    + h->dynindx));
+                          (PTR) (((Elf_External_Sym *)
+                                  finfo->dynsym_sec->contents)
+                                 + h->dynindx));
 
       bucketcount = elf_hash_table (finfo->info)->bucketcount;
       bucket = (bfd_elf_hash ((const unsigned char *) h->root.root.string)
This page took 0.025924 seconds and 4 git commands to generate.