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.
This commit is contained in:
Alan Modra 2002-06-23 02:04:28 +00:00
parent e7d838cb85
commit f5d44ba06b
4 changed files with 177 additions and 7 deletions

View 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>
@ -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.

View 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. */

View File

@ -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;

View 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;
}