2002-06-23 Alan Modra <amodra@bigpond.net.au>
authorAlan Modra <amodra@gmail.com>
Sun, 23 Jun 2002 02:04:28 +0000 (02:04 +0000)
committerAlan Modra <amodra@gmail.com>
Sun, 23 Jun 2002 02:04:28 +0000 (02:04 +0000)
* elflink.h: Comment typo fixes.

2002-06-23  H.J. Lu  <hjl@gnu.org>

* elf-bfd.h (elf_link_loaded_list): New structure.
(elf_link_hash_table): Add "loaded".
* elf.c (_bfd_elf_link_hash_table_init): Initialize "loaded".
* elflink.h (elf_link_check_versioned_symbol): New function.
(elf_link_output_extsym): Call elf_link_check_versioned_symbol.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf.c
bfd/elflink.h

index b4af06c..1fbc6ab 100644 (file)
@@ -1,7 +1,19 @@
+2002-06-23  Alan Modra  <amodra@bigpond.net.au>
+
+       * elflink.h: Comment typo fixes.
+
+2002-06-23  H.J. Lu  <hjl@gnu.org>
+
+       * elf-bfd.h (elf_link_loaded_list): New structure.
+       (elf_link_hash_table): Add "loaded".
+       * elf.c (_bfd_elf_link_hash_table_init): Initialize "loaded".
+       * elflink.h (elf_link_check_versioned_symbol): New function.
+       (elf_link_output_extsym): Call elf_link_check_versioned_symbol.
+
 2002-06-19  Nick Clifton  <nickc@cambridge.redhat.com>
 
        * elflink.h (size_dynamic_sections): If the target does not
-       support an ELF style has table, return true, indicating that
+       support an ELF style hash table, return true, indicating that
        nothing needed to be done, rather than false, indicating that the
        section's size could not be computed.
 
@@ -33,7 +45,7 @@
 2002-06-17  Tom Rix <trix@redhat.com>
 
        * elf32-d10v.c (elf_d10v_howto_table): Change R_D10V_10_PCREL_R,
-       R_D10V_10_PCREL_L and R_D10V_18_PCREL to use 
+       R_D10V_10_PCREL_L and R_D10V_18_PCREL to use
        complain_overflow_bitfield.
 
 2002-06-17  Alan Modra  <amodra@bigpond.net.au>
        * coffcode.h (coff_compute_section_file_positions): Add data
        section to AIX loader alignment check.
 
-       * coff-rs6000.c (_bfd_xcoff_mkobject): Set default text section 
+       * coff-rs6000.c (_bfd_xcoff_mkobject): Set default text section
        alignment to 4 bytes.
        (_bfd_xcoff_copy_private_bfd_data): Use text and data alignment
        power accessor macro.
index 28dbe83..8624240 100644 (file)
@@ -223,6 +223,12 @@ struct elf_link_local_dynamic_entry
   Elf_Internal_Sym isym;
 };
 
+struct elf_link_loaded_list
+{
+  struct elf_link_loaded_list *next;
+  bfd *abfd;
+};
+
 enum elf_link_info_type
 {
   ELF_INFO_TYPE_NONE,
@@ -297,6 +303,9 @@ struct elf_link_hash_table
 
   /* Cached start, size and alignment of PT_TLS segment.  */
   struct elf_link_tls_segment *tls_segment;
+
+  /* A linked list of BFD's loaded in the link.  */
+  struct elf_link_loaded_list *loaded;
 };
 
 /* Look up an entry in an ELF linker hash table.  */
index 61b9f50..e592086 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1430,6 +1430,7 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc)
   table->bucketcount = 0;
   table->needed = NULL;
   table->runpath = NULL;
+  table->loaded = NULL;
   table->hgot = NULL;
   table->stab_info = NULL;
   table->merge_info = NULL;
index b442361..3cd9e0c 100644 (file)
@@ -2315,6 +2315,20 @@ elf_link_add_object_symbols (abfd, info)
          }
     }
 
+  if (is_elf_hash_table (info))
+    {
+      /* Add this bfd to the loaded list.  */
+      struct elf_link_loaded_list *n;
+
+      n = ((struct elf_link_loaded_list *)
+          bfd_alloc (abfd, sizeof (struct elf_link_loaded_list)));
+      if (n == NULL)
+       goto error_return;
+      n->abfd = abfd;
+      n->next = hash_table->loaded;
+      hash_table->loaded = n;
+    }
+
   return true;
 
  error_return:
@@ -4536,6 +4550,8 @@ static boolean elf_link_output_extsym
   PARAMS ((struct elf_link_hash_entry *, PTR));
 static boolean elf_link_sec_merge_syms
   PARAMS ((struct elf_link_hash_entry *, PTR));
+static boolean elf_link_check_versioned_symbol
+  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
 static boolean elf_link_input_bfd
   PARAMS ((struct elf_final_link_info *, bfd *));
 static boolean elf_reloc_link_order
@@ -6042,6 +6058,137 @@ elf_link_sec_merge_syms (h, data)
   return true;
 }
 
+/* For DSOs loaded in via a DT_NEEDED entry, emulate ld.so in
+   allowing an unsatisfied unversioned symbol in the DSO to match a
+   versioned symbol that would normally require an explicit version.  */
+
+static boolean
+elf_link_check_versioned_symbol (info, h)
+     struct bfd_link_info *info;
+     struct elf_link_hash_entry *h;
+{
+  bfd *undef_bfd = h->root.u.undef.abfd;
+  struct elf_link_loaded_list *loaded;
+  Elf_External_Sym *buf;
+  Elf_External_Versym *extversym;
+
+  if ((undef_bfd->flags & DYNAMIC) == 0
+      || info->hash->creator->flavour != bfd_target_elf_flavour
+      || elf_dt_soname (h->root.u.undef.abfd) == NULL)
+    return false;
+
+  for (loaded = elf_hash_table (info)->loaded;
+       loaded != NULL;
+       loaded = loaded->next)
+    {
+      bfd *input;
+      Elf_Internal_Shdr *hdr;
+      bfd_size_type symcount;
+      bfd_size_type extsymcount;
+      bfd_size_type extsymoff;
+      Elf_Internal_Shdr *versymhdr;
+      Elf_External_Versym *ever;
+      Elf_External_Sym *esym;
+      Elf_External_Sym *esymend;
+      bfd_size_type count;
+      file_ptr pos;
+
+      input = loaded->abfd;
+
+      /* We check each DSO for a possible hidden versioned definition.  */
+      if (input == undef_bfd
+         || (input->flags & DYNAMIC) == 0
+         || elf_dynversym (input) == 0)
+       continue;
+
+      hdr = &elf_tdata (input)->dynsymtab_hdr;
+
+      symcount = hdr->sh_size / sizeof (Elf_External_Sym);
+      if (elf_bad_symtab (input))
+       {
+         extsymcount = symcount;
+         extsymoff = 0;
+       }
+      else
+       {
+         extsymcount = symcount - hdr->sh_info;
+         extsymoff = hdr->sh_info;
+       }
+
+      if (extsymcount == 0)
+       continue;
+
+      count = extsymcount * sizeof (Elf_External_Sym);
+      buf = (Elf_External_Sym *) bfd_malloc (count);
+      if (buf == NULL)
+       return false;
+
+      /* Read in the symbol table.  */
+      pos = hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym);
+      if (bfd_seek (input, pos, SEEK_SET) != 0
+         || bfd_bread ((PTR) buf, count, input) != count)
+       goto error_ret;
+
+      /* Read in any version definitions.  */
+      versymhdr = &elf_tdata (input)->dynversym_hdr;
+      extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
+      if (extversym == NULL)
+       goto error_ret;
+
+      if (bfd_seek (input, versymhdr->sh_offset, SEEK_SET) != 0
+         || (bfd_bread ((PTR) extversym, versymhdr->sh_size, input)
+             != versymhdr->sh_size))
+       {
+         free (extversym);
+       error_ret:
+         free (buf);
+         return false;
+       }
+
+      ever = extversym + extsymoff;
+      esymend = buf + extsymcount;
+      for (esym = buf; esym < esymend; esym++, ever++)
+       {
+         const char *name;
+         Elf_Internal_Sym sym;
+         Elf_Internal_Versym iver;
+
+         elf_swap_symbol_in (input, esym, NULL, &sym);
+         if (ELF_ST_BIND (sym.st_info) == STB_LOCAL
+             || sym.st_shndx == SHN_UNDEF)
+           continue;
+
+         name = bfd_elf_string_from_elf_section (input,
+                                                 hdr->sh_link,
+                                                 sym.st_name);
+         if (strcmp (name, h->root.root.string) != 0)
+           continue;
+
+         _bfd_elf_swap_versym_in (input, ever, &iver);
+
+         if ((iver.vs_vers & VERSYM_HIDDEN) == 0)
+           {
+             /* If we have a non-hidden versioned sym, then it should
+                have provided a definition for the undefined sym.  */
+             abort ();
+           }
+
+         if ((iver.vs_vers & VERSYM_VERSION) == 2)
+           {
+             /* This is the oldest (default) sym.  We can use it.  */
+             free (extversym);
+             free (buf);
+             return true;
+           }
+       }
+
+      free (extversym);
+      free (buf);
+    }
+
+  return false;
+}
+
 /* Add an external symbol to the symbol table.  This is called from
    the hash table traversal routine.  When generating a shared object,
    we go through the symbol table twice.  The first time we output
@@ -6091,7 +6238,8 @@ elf_link_output_extsym (h, data)
       && ! 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
+      && ! elf_link_check_versioned_symbol (finfo->info, h))
     {
       if (! ((*finfo->info->callbacks->undefined_symbol)
             (finfo->info, h->root.root.string, h->root.u.undef.abfd,
@@ -6264,8 +6412,8 @@ elf_link_output_extsym (h, data)
     sym.st_other ^= ELF_ST_VISIBILITY (sym.st_other);
 
   /* If this symbol should be put in the .dynsym section, then put it
-     there now.  We have already know the symbol index.  We also fill
-     in the entry in the .hash section.  */
+     there now.  We already know the symbol index.  We also fill in
+     the entry in the .hash section.  */
   if (h->dynindx != -1
       && elf_hash_table (finfo->info)->dynamic_sections_created)
     {
@@ -6959,7 +7107,7 @@ elf_link_input_bfd (finfo, input_bfd)
                        }
 
                      /* Adjust the addend according to where the
-                        section winds up in the output section.  */ 
+                        section winds up in the output section.  */
                      if (rela_normal)
                        irela->r_addend += sec->output_offset;
                    }