* elflink.h (elf_link_add_object_symbols): Use extsymoff when

setting ever.  Sanity check the version number.  Sort out copying
	flags and other information when adding an indirect symbol.
	(NAME(bfd_elf,size_dynamic_sections)): Preserve any dynamic
	symbols added by the backend.  Clear the entire contents of the
	versym section.
	(elf_export_symbol): Ignore indirect symbols.
	(elf_link_output_extsym): Accept a section without an owner in an
	assert.
	* elfcode.h (elf_slurp_symbol_table): Add a sanity check on the
	version count.  Correct the allocation of x_versymp.
This commit is contained in:
Ian Lance Taylor 1997-03-13 02:41:44 +00:00
parent 7d996a75d2
commit e549b1d2a3
3 changed files with 274 additions and 38 deletions

View file

@ -1,3 +1,45 @@
Wed Mar 12 21:36:05 1997 Ian Lance Taylor <ian@cygnus.com>
* elflink.h (elf_link_add_object_symbols): Use extsymoff when
setting ever. Sanity check the version number. Sort out copying
flags and other information when adding an indirect symbol.
(NAME(bfd_elf,size_dynamic_sections)): Preserve any dynamic
symbols added by the backend. Clear the entire contents of the
versym section.
(elf_export_symbol): Ignore indirect symbols.
(elf_link_output_extsym): Accept a section without an owner in an
assert.
* elfcode.h (elf_slurp_symbol_table): Add a sanity check on the
version count. Correct the allocation of x_versymp.
* elf32-mips.c (mips_elf_add_symbol_hook): Don't set the owner of
the magic sections used for SHN_MIPS_TEXT and SHN_MIPS_DATA.
Don't return bfd_und_section_ptr when info->shared.
(mips_elf_final_link): Set the alignment of .rtproc to 4, not 12.
(mips_elf_create_dynamic_sections): Correct type: ^= for &=.
(mips_elf_check_relocs): Resolve an indirect symbol in
sym_hashes.
(mips_elf_finish_dynamic_symbol): Don't change SHN_ABS into
SHN_MIPS_TEXT or SHN_MIPS_DATA.
* elf.c (bfd_elf_print_symbol): Tweak version output slightly.
Tue Mar 11 01:38:36 1997 Ian Lance Taylor <ian@cygnus.com>
From Eric Youngdale <eric@andante.jic.com>:
* elf-bfd.h (ELF_LINK_FORCED_LOCAL): Define.
* elf.c (bfd_elf_print_symbol): Correct errors in last change.
* elflink.h (elf_link_add_object_symbols): Handle cases in which a
versioned symbol appears in both a regular and a shared object.
(elf_link_assign_sym_version): Set ELF_LINK_FORCED_LOCAL when
appropriate. Improve error message.
(struct elf_outext_info): Rename from elf_finfo_failed. Change
all uses. Add localsyms field.
(elf_bfd_final_link): When generating a shared library, call
elf_link_output_extsym to output all local symbols.
(elf_link_output_extsym): Handle symbols which were forced to
become local.
Sun Mar 9 23:08:49 1997 Ian Lance Taylor <ian@cygnus.com>
From Eric Youngdale <eric@andante.jic.com>:

View file

@ -1,5 +1,5 @@
/* ELF executable support for BFD.
Copyright 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
Copyright 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Written by Fred Fish @ Cygnus Support, from information published
in "UNIX System V Release 4, Programmers Guide: ANSI C and
@ -68,6 +68,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "fnmatch.h"
/* Renaming structures, typedefs, macros and functions to be size-specific. */
#define Elf_External_Ehdr NAME(Elf,External_Ehdr)
@ -455,6 +456,7 @@ elf_object_p (abfd)
struct elf_backend_data *ebd;
struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd);
struct elf_obj_tdata *new_tdata = NULL;
asection *s;
/* Read in the ELF header in external format. */
@ -658,6 +660,25 @@ elf_object_p (abfd)
goto got_wrong_format_error;
}
/* If we have created any reloc sections that are associated with
debugging sections, mark the reloc sections as debugging as well. */
for (s = abfd->sections; s != NULL; s = s->next)
{
if ((elf_section_data (s)->this_hdr.sh_type == SHT_REL
|| elf_section_data (s)->this_hdr.sh_type == SHT_RELA)
&& elf_section_data (s)->this_hdr.sh_info > 0)
{
unsigned long targ_index;
asection *targ_sec;
targ_index = elf_section_data (s)->this_hdr.sh_info;
targ_sec = bfd_section_from_elf_index (abfd, targ_index);
if (targ_sec != NULL
&& (targ_sec->flags & SEC_DEBUGGING) != 0)
s->flags |= SEC_DEBUGGING;
}
}
return (abfd->xvec);
got_wrong_format_error:
@ -902,11 +923,13 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
boolean dynamic;
{
Elf_Internal_Shdr *hdr;
Elf_Internal_Shdr *verhdr;
long symcount; /* Number of external ELF symbols */
elf_symbol_type *sym; /* Pointer to current bfd symbol */
elf_symbol_type *symbase; /* Buffer for generated bfd symbols */
Elf_Internal_Sym i_sym;
Elf_External_Sym *x_symp = NULL;
Elf_External_Versym *x_versymp = NULL;
/* Read each raw ELF symbol, converting from external ELF form to
internal ELF form, and then using the information to create a
@ -918,10 +941,25 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
space left over at the end. When we have all the symbols, we
build the caller's pointer vector. */
if (dynamic)
hdr = &elf_tdata (abfd)->dynsymtab_hdr;
if (! dynamic)
{
hdr = &elf_tdata (abfd)->symtab_hdr;
verhdr = NULL;
}
else
hdr = &elf_tdata (abfd)->symtab_hdr;
{
hdr = &elf_tdata (abfd)->dynsymtab_hdr;
verhdr = &elf_tdata (abfd)->dynversym_hdr;
if ((elf_tdata (abfd)->dynverdef_section != 0
&& elf_tdata (abfd)->verdef == NULL)
|| (elf_tdata (abfd)->dynverref_section != 0
&& elf_tdata (abfd)->verref == NULL))
{
if (! _bfd_elf_slurp_version_tables (abfd))
return -1;
}
}
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1)
return -1;
@ -951,6 +989,38 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
if (bfd_read ((PTR) x_symp, sizeof (Elf_External_Sym), symcount, abfd)
!= symcount * sizeof (Elf_External_Sym))
goto error_return;
/* Read the raw ELF version symbol information. */
if (elf_dynversym (abfd) != 0
&& verhdr != NULL
&& verhdr->sh_size / sizeof (Elf_External_Versym) != symcount)
{
(*_bfd_error_handler)
("%s: version count (%ld) does not match symbol count (%ld)",
abfd->filename,
(long) (verhdr->sh_size / sizeof (Elf_External_Versym)),
symcount);
/* Slurp in the symbols without the version information,
since that is more helpful than just quitting. */
verhdr = NULL;
}
if (verhdr != NULL)
{
if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0)
goto error_return;
x_versymp = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size);
if (x_versymp == NULL && symcount != 0)
goto error_return;
if (bfd_read ((PTR) x_versymp, 1, verhdr->sh_size, abfd)
!= verhdr->sh_size)
goto error_return;
}
/* Skip first symbol, which is a null dummy. */
for (i = 1; i < symcount; i++)
{
@ -1035,6 +1105,14 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
if (dynamic)
sym->symbol.flags |= BSF_DYNAMIC;
if (x_versymp != NULL)
{
Elf_Internal_Versym iversym;
_bfd_elf_swap_versym_in (abfd, x_versymp + i, &iversym);
sym->version = iversym.vs_vers;
}
/* Do some backend-specific processing on this symbol. */
{
struct elf_backend_data *ebd = get_elf_backend_data (abfd);
@ -1071,10 +1149,14 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
*symptrs = 0; /* Final null pointer */
}
if (x_versymp != NULL)
free (x_versymp);
if (x_symp != NULL)
free (x_symp);
return symcount;
error_return:
if (x_versymp != NULL)
free (x_versymp);
if (x_symp != NULL)
free (x_symp);
return -1;

View file

@ -679,7 +679,7 @@ elf_link_add_object_symbols (abfd, info)
weaks = NULL;
ever = extversym != NULL ? extversym + hdr->sh_info : NULL;
ever = extversym != NULL ? extversym + extsymoff : NULL;
esymend = buf + extsymcount;
for (esym = buf;
esym < esymend;
@ -805,7 +805,16 @@ elf_link_add_object_symbols (abfd, info)
int namelen, newlen;
char *newname, *p;
if (vernum > 1)
if (vernum > elf_tdata (abfd)->dynverdef_hdr.sh_info)
{
(*_bfd_error_handler)
("%s: %s: invalid version %d (max %d)",
abfd->filename, name, vernum,
elf_tdata (abfd)->dynverdef_hdr.sh_info);
bfd_set_error (bfd_error_bad_value);
goto error_return;
}
else if (vernum > 1)
verstr = elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
else
verstr = "";
@ -1128,15 +1137,64 @@ elf_link_add_object_symbols (abfd, info)
if (hi->root.type == bfd_link_hash_indirect)
{
hi->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
if (dynamic)
hi->elf_link_hash_flags |=
ELF_LINK_HASH_DEF_DYNAMIC;
/* We don't set DEF_REGULAR because we don't
the symbol to get exported even if we are
exporting all defined symbols. FIXME:
What a hack. */
/* FIXME: Do we need to copy any flags from
H to HI? */
/* If the symbol became indirect, then we
assume that we have not seen a definition
before. */
BFD_ASSERT ((hi->elf_link_hash_flags
& (ELF_LINK_HASH_DEF_DYNAMIC
| ELF_LINK_HASH_DEF_REGULAR))
== 0);
/* Copy down any references that we may have
already seen to the symbol which just
became indirect. */
h->elf_link_hash_flags |=
(hi->elf_link_hash_flags
& (ELF_LINK_HASH_REF_DYNAMIC
| ELF_LINK_HASH_REF_REGULAR));
/* Copy over the global table offset entry.
This may have been already set up by a
check_relocs routine. */
if (h->got_offset == (bfd_vma) -1)
{
h->got_offset = hi->got_offset;
hi->got_offset = (bfd_vma) -1;
}
BFD_ASSERT (hi->got_offset == (bfd_vma) -1);
if (h->dynindx == -1)
{
h->dynindx = hi->dynindx;
h->dynstr_index = hi->dynstr_index;
hi->dynindx = -1;
hi->dynstr_index = 0;
}
BFD_ASSERT (hi->dynindx == -1);
/* FIXME: There may be other information to
copy over for particular targets. */
/* See if the new flags lead us to realize
that the symbol must be dynamic. */
if (! dynsym)
{
if (! dynamic)
{
if (info->shared
|| ((hi->elf_link_hash_flags
& ELF_LINK_HASH_REF_DYNAMIC)
!= 0))
dynsym = true;
}
else
{
if ((hi->elf_link_hash_flags
& ELF_LINK_HASH_REF_REGULAR) != 0)
dynsym = true;
}
}
}
}
@ -1211,15 +1269,64 @@ elf_link_add_object_symbols (abfd, info)
if (hi->root.type == bfd_link_hash_indirect)
{
hi->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
if (dynamic)
hi->elf_link_hash_flags |=
ELF_LINK_HASH_DEF_DYNAMIC;
/* We don't set DEF_REGULAR because we don't
the symbol to get exported even if we are
exporting all defined symbols. FIXME:
What a hack. */
/* FIXME: Do we need to copy any flags from
H to HI? */
/* If the symbol became indirect, then we
assume that we have not seen a definition
before. */
BFD_ASSERT ((hi->elf_link_hash_flags
& (ELF_LINK_HASH_DEF_DYNAMIC
| ELF_LINK_HASH_DEF_REGULAR))
== 0);
/* Copy down any references that we may have
already seen to the symbol which just
became indirect. */
h->elf_link_hash_flags |=
(hi->elf_link_hash_flags
& (ELF_LINK_HASH_REF_DYNAMIC
| ELF_LINK_HASH_REF_REGULAR));
/* Copy over the global table offset entry.
This may have been already set up by a
check_relocs routine. */
if (h->got_offset == (bfd_vma) -1)
{
h->got_offset = hi->got_offset;
hi->got_offset = (bfd_vma) -1;
}
BFD_ASSERT (hi->got_offset == (bfd_vma) -1);
if (h->dynindx == -1)
{
h->dynindx = hi->dynindx;
h->dynstr_index = hi->dynstr_index;
hi->dynindx = -1;
hi->dynstr_index = 0;
}
BFD_ASSERT (hi->dynindx == -1);
/* FIXME: There may be other information to
copy over for particular targets. */
/* See if the new flags lead us to realize
that the symbol must be dynamic. */
if (! dynsym)
{
if (! dynamic)
{
if (info->shared
|| ((hi->elf_link_hash_flags
& ELF_LINK_HASH_REF_DYNAMIC)
!= 0))
dynsym = true;
}
else
{
if ((hi->elf_link_hash_flags
& ELF_LINK_HASH_REF_REGULAR) != 0)
dynsym = true;
}
}
}
}
}
@ -1818,6 +1925,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
bfd_size_type soname_indx;
bfd *dynobj;
struct elf_backend_data *bed;
bfd_size_type old_dynsymcount;
*sinterpptr = NULL;
@ -1959,6 +2067,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
/* The backend must work out the sizes of all the other dynamic
sections. */
old_dynsymcount = elf_hash_table (info)->dynsymcount;
if (! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
return false;
@ -2018,11 +2127,15 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
if (sinfo.removed_dynamic)
{
/* Some dynamic symbols were changed to be local
symbols. In this case, we renumber all of the
dynamic symbols, so that we don't have a hole.
FIXME: The names of the removed symbols will still be
in the dynamic string table, wasting space. */
elf_hash_table (info)->dynsymcount = 1;
symbols. In this case, we renumber all of the
dynamic symbols, so that we don't have a hole. If
the backend changed dynsymcount, then assume that the
new symbols are at the start. This is the case on
the MIPS. FIXME: The names of the removed symbols
will still be in the dynamic string table, wasting
space. */
elf_hash_table (info)->dynsymcount =
1 + (elf_hash_table (info)->dynsymcount - old_dynsymcount);
elf_link_hash_traverse (elf_hash_table (info),
elf_link_renumber_dynsyms,
(PTR) info);
@ -2307,17 +2420,11 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
}
else
{
Elf_Internal_Versym intversym;
s->_raw_size = dynsymcount * sizeof (Elf_External_Versym);
s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
s->contents = (bfd_byte *) bfd_zalloc (output_bfd, s->_raw_size);
if (s->contents == NULL)
return false;
intversym.vs_vers = 0;
_bfd_elf_swap_versym_out (output_bfd, &intversym,
(Elf_External_Versym *) s->contents);
if (! elf_add_dynamic_entry (info, DT_VERSYM, 0))
return false;
}
@ -2389,7 +2496,7 @@ elf_adjust_dynamic_symbol (h, data)
bfd *dynobj;
struct elf_backend_data *bed;
/* Ignore indirect symbols. There are added by the versioning code. */
/* Ignore indirect symbols. These are added by the versioning code. */
if (h->root.type == bfd_link_hash_indirect)
return true;
@ -2546,6 +2653,10 @@ elf_export_symbol (h, data)
{
struct elf_info_failed *eif = (struct elf_info_failed *) data;
/* Ignore indirect symbols. These are added by the versioning code. */
if (h->root.type == bfd_link_hash_indirect)
return true;
if (h->dynindx == -1
&& (h->elf_link_hash_flags
& (ELF_LINK_HASH_DEF_REGULAR | ELF_LINK_HASH_REF_REGULAR)) != 0)
@ -3853,7 +3964,8 @@ elf_link_output_extsym (h, data)
}
else
{
BFD_ASSERT ((input_sec->owner->flags & DYNAMIC) != 0);
BFD_ASSERT (input_sec->owner == NULL
|| (input_sec->owner->flags & DYNAMIC) != 0);
sym.st_shndx = SHN_UNDEF;
input_sec = bfd_und_section_ptr;
}