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 b4af06c79ff3293453e960f91845587f45e02181..1fbc6ab8886f44a8bd3a7bc8a07d0c66b335abc8 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
 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.
 
        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,
 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>
        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.
 
        * 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.
        alignment to 4 bytes.
        (_bfd_xcoff_copy_private_bfd_data): Use text and data alignment
        power accessor macro.
index 28dbe83c6a7bf419ed91b4577e96f36800b56474..86242409dbe9589ff4b4730433be73c50a65c19b 100644 (file)
@@ -223,6 +223,12 @@ struct elf_link_local_dynamic_entry
   Elf_Internal_Sym isym;
 };
 
   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,
 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;
 
   /* 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.  */
 };
 
 /* Look up an entry in an ELF linker hash table.  */
index 61b9f50b064b2e12f03060d58e736ed281dbd7f8..e592086983c8623783335f58b3989742ffa65485 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->bucketcount = 0;
   table->needed = NULL;
   table->runpath = NULL;
+  table->loaded = NULL;
   table->hgot = NULL;
   table->stab_info = NULL;
   table->merge_info = NULL;
   table->hgot = NULL;
   table->stab_info = NULL;
   table->merge_info = NULL;
index b442361b611ba5c57efd7390092b78beada0dd1d..3cd9e0c49aa6a1b7e82687af472acda1fe5b450f 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:
   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));
   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
 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;
 }
 
   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
 /* 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
       && ! 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,
     {
       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
     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)
     {
   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
                        }
 
                      /* 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;
                    }
                      if (rela_normal)
                        irela->r_addend += sec->output_offset;
                    }
This page took 0.039793 seconds and 4 git commands to generate.