aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2002-06-23 02:04:28 +0000
committerAlan Modra <amodra@gmail.com>2002-06-23 02:04:28 +0000
commitf5d44ba06b007de0a5b890878296d33af3d992dd (patch)
tree9401a0fd0dd5a36490f02b8e79de01a9a254511a
parente7d838cb85f9d429ed170eb6f1e1052dd687e880 (diff)
downloadgdb-f5d44ba06b007de0a5b890878296d33af3d992dd.zip
gdb-f5d44ba06b007de0a5b890878296d33af3d992dd.tar.gz
gdb-f5d44ba06b007de0a5b890878296d33af3d992dd.tar.bz2
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.
-rw-r--r--bfd/ChangeLog18
-rw-r--r--bfd/elf-bfd.h9
-rw-r--r--bfd/elf.c1
-rw-r--r--bfd/elflink.h156
4 files changed, 177 insertions, 7 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index b4af06c..1fbc6ab 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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>
@@ -98,7 +110,7 @@
* 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.
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 28dbe83..8624240 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -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. */
diff --git a/bfd/elf.c b/bfd/elf.c
index 61b9f50..e592086 100644
--- 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;
diff --git a/bfd/elflink.h b/bfd/elflink.h
index b442361..3cd9e0c 100644
--- a/bfd/elflink.h
+++ b/bfd/elflink.h
@@ -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;
}