From Eric Youngdale <eric@andante.jic.com>:
* elf-bfd.h (elf_symbol_type): Add version field. * elfcode.h (elf_slurp_symbol_table): Set version field. * elflink.h (elf_link_add_object_symbols): When creating an indirect symbol for a default version symbol, set DEF_DYNAMIC if appropriate. Set up an indirection from the nondefault version of the symbol as well. (NAME(bfd_elf,size_dynamic_sections)): Call elf_link_assign_sym_version before checking whether there are any versions. Always record the version name as a dynamic symbol. Initialize counters. (elf_link_assign_sym_version): After finding a version, see if a symbol should be forced to local scope. Create a new version definition if appropriate. (elf_link_output_extsym): Correct indirect symbol handling. * elf.c (bfd_elf_print_symbol): Print version information. (bfd_section_from_shdr): Turn version sections into BFD sections. (elf_fake_sections): Only copy cverdefs and cverrefs into sh_info if sh_info is not already set. (_bfd_elf_copy_private_section_data): Copy sh_info for version sections. * elflink.c (_bfd_elf_link_record_dynamic_symbol): Tell _bfd_stringtab_add to copy the name into permanent memory if appropriate.
This commit is contained in:
parent
998f2b67a9
commit
d6bfcdb505
4 changed files with 344 additions and 56 deletions
|
@ -1,3 +1,30 @@
|
|||
Sun Mar 9 23:08:49 1997 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
From Eric Youngdale <eric@andante.jic.com>:
|
||||
* elf-bfd.h (elf_symbol_type): Add version field.
|
||||
* elfcode.h (elf_slurp_symbol_table): Set version field.
|
||||
* elflink.h (elf_link_add_object_symbols): When creating an
|
||||
indirect symbol for a default version symbol, set DEF_DYNAMIC if
|
||||
appropriate. Set up an indirection from the nondefault version of
|
||||
the symbol as well.
|
||||
(NAME(bfd_elf,size_dynamic_sections)): Call
|
||||
elf_link_assign_sym_version before checking whether there are any
|
||||
versions. Always record the version name as a dynamic symbol.
|
||||
Initialize counters.
|
||||
(elf_link_assign_sym_version): After finding a version, see if a
|
||||
symbol should be forced to local scope. Create a new version
|
||||
definition if appropriate.
|
||||
(elf_link_output_extsym): Correct indirect symbol handling.
|
||||
* elf.c (bfd_elf_print_symbol): Print version information.
|
||||
(bfd_section_from_shdr): Turn version sections into BFD sections.
|
||||
(elf_fake_sections): Only copy cverdefs and cverrefs into sh_info
|
||||
if sh_info is not already set.
|
||||
(_bfd_elf_copy_private_section_data): Copy sh_info for version
|
||||
sections.
|
||||
* elflink.c (_bfd_elf_link_record_dynamic_symbol): Tell
|
||||
_bfd_stringtab_add to copy the name into permanent memory if
|
||||
appropriate.
|
||||
|
||||
Fri Mar 7 11:55:31 1997 H.J. Lu <hjl@gnu.ai.mit.edu>
|
||||
|
||||
* elf64-alpha.c (alpha_elf_dynamic_symbol_p): Fully parenthesize.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* BFD back-end data structures for ELF files.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
|
||||
Written by Cygnus Support.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
|
@ -62,6 +62,12 @@ typedef struct
|
|||
PTR any;
|
||||
}
|
||||
tc_data;
|
||||
|
||||
/* Version information. This is from an Elf_Internal_Versym
|
||||
structure in a SHT_GNU_versym section. It is zero if there is no
|
||||
version information. */
|
||||
unsigned short version;
|
||||
|
||||
} elf_symbol_type;
|
||||
|
||||
/* ELF linker hash table entries. */
|
||||
|
@ -107,6 +113,19 @@ struct elf_link_hash_entry
|
|||
from the beginning of the section. */
|
||||
struct elf_linker_section_pointers *linker_section_pointer;
|
||||
|
||||
/* Version information. */
|
||||
union
|
||||
{
|
||||
/* This field is used for a symbol which is not defined in a
|
||||
regular object. It points to the version information read in
|
||||
from the dynamic object. */
|
||||
Elf_Internal_Verdef *verdef;
|
||||
/* This field is used for a symbol which is defined in a regular
|
||||
object. It is set up in size_dynamic_sections. It points to
|
||||
the version information we should write out for this symbol. */
|
||||
struct bfd_elf_version_tree *vertree;
|
||||
} verinfo;
|
||||
|
||||
/* Symbol type (STT_NOTYPE, STT_OBJECT, etc.). */
|
||||
char type;
|
||||
|
||||
|
@ -114,7 +133,7 @@ struct elf_link_hash_entry
|
|||
unsigned char other;
|
||||
|
||||
/* Some flags; legal values follow. */
|
||||
unsigned char elf_link_hash_flags;
|
||||
unsigned short elf_link_hash_flags;
|
||||
/* Symbol is referenced by a non-shared object. */
|
||||
#define ELF_LINK_HASH_REF_REGULAR 01
|
||||
/* Symbol is defined by a non-shared object. */
|
||||
|
@ -131,8 +150,8 @@ struct elf_link_hash_entry
|
|||
#define ELF_LINK_HASH_NEEDS_PLT 0100
|
||||
/* Symbol appears in a non-ELF input file. */
|
||||
#define ELF_LINK_NON_ELF 0200
|
||||
/* Note: If you add more flags, you must change the type of
|
||||
elf_link_hash_flags. */
|
||||
/* Symbol should be marked as hidden in the version information. */
|
||||
#define ELF_LINK_HIDDEN 0400
|
||||
};
|
||||
|
||||
/* ELF linker hash table. */
|
||||
|
@ -572,8 +591,12 @@ struct elf_obj_tdata
|
|||
Elf_Internal_Shdr strtab_hdr;
|
||||
Elf_Internal_Shdr dynsymtab_hdr;
|
||||
Elf_Internal_Shdr dynstrtab_hdr;
|
||||
Elf_Internal_Shdr dynversym_hdr;
|
||||
Elf_Internal_Shdr dynverref_hdr;
|
||||
Elf_Internal_Shdr dynverdef_hdr;
|
||||
unsigned int symtab_section, shstrtab_section;
|
||||
unsigned int strtab_section, dynsymtab_section;
|
||||
unsigned int dynversym_section, dynverdef_section, dynverref_section;
|
||||
file_ptr next_file_pos;
|
||||
void *prstatus; /* The raw /proc prstatus structure */
|
||||
void *prpsinfo; /* The raw /proc prpsinfo structure */
|
||||
|
@ -626,9 +649,26 @@ struct elf_obj_tdata
|
|||
find_nearest_line. */
|
||||
struct mips_elf_find_line *find_line_info;
|
||||
|
||||
/* An array of stub sections indexed by symbol number, used by the
|
||||
MIPS ELF linker. FIXME: We should figure out some way to only
|
||||
include this field for a MIPS ELF target. */
|
||||
asection **local_stubs;
|
||||
|
||||
/* Used to determine if the e_flags field has been initialized */
|
||||
boolean flags_init;
|
||||
|
||||
/* Number of symbol version definitions we are about to emit. */
|
||||
int cverdefs;
|
||||
|
||||
/* Number of symbol version references we are about to emit. */
|
||||
int cverrefs;
|
||||
|
||||
/* Symbol version definitions in external objects. */
|
||||
Elf_Internal_Verdef *verdef;
|
||||
|
||||
/* Symbol version references to external objects. */
|
||||
Elf_Internal_Verneed *verref;
|
||||
|
||||
/* Linker sections that we are interested in. */
|
||||
struct elf_linker_section *linker_section[ (int)LINKER_SECTION_MAX ];
|
||||
};
|
||||
|
@ -639,6 +679,9 @@ struct elf_obj_tdata
|
|||
#define elf_shstrtab(bfd) (elf_tdata(bfd) -> strtab_ptr)
|
||||
#define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section)
|
||||
#define elf_dynsymtab(bfd) (elf_tdata(bfd) -> dynsymtab_section)
|
||||
#define elf_dynversym(bfd) (elf_tdata(bfd) -> dynversym_section)
|
||||
#define elf_dynverdef(bfd) (elf_tdata(bfd) -> dynverdef_section)
|
||||
#define elf_dynverref(bfd) (elf_tdata(bfd) -> dynverref_section)
|
||||
#define elf_num_locals(bfd) (elf_tdata(bfd) -> num_locals)
|
||||
#define elf_num_globals(bfd) (elf_tdata(bfd) -> num_globals)
|
||||
#define elf_section_syms(bfd) (elf_tdata(bfd) -> section_syms)
|
||||
|
@ -654,6 +697,27 @@ struct elf_obj_tdata
|
|||
#define elf_flags_init(bfd) (elf_tdata(bfd) -> flags_init)
|
||||
#define elf_linker_section(bfd,n) (elf_tdata(bfd) -> linker_section[(int)n])
|
||||
|
||||
extern void _bfd_elf_swap_verdef_in
|
||||
PARAMS ((bfd *, const Elf_External_Verdef *, Elf_Internal_Verdef *));
|
||||
extern void _bfd_elf_swap_verdef_out
|
||||
PARAMS ((bfd *, const Elf_Internal_Verdef *, Elf_External_Verdef *));
|
||||
extern void _bfd_elf_swap_verdaux_in
|
||||
PARAMS ((bfd *, const Elf_External_Verdaux *, Elf_Internal_Verdaux *));
|
||||
extern void _bfd_elf_swap_verdaux_out
|
||||
PARAMS ((bfd *, const Elf_Internal_Verdaux *, Elf_External_Verdaux *));
|
||||
extern void _bfd_elf_swap_verneed_in
|
||||
PARAMS ((bfd *, const Elf_External_Verneed *, Elf_Internal_Verneed *));
|
||||
extern void _bfd_elf_swap_verneed_out
|
||||
PARAMS ((bfd *, const Elf_Internal_Verneed *, Elf_External_Verneed *));
|
||||
extern void _bfd_elf_swap_vernaux_in
|
||||
PARAMS ((bfd *, const Elf_External_Vernaux *, Elf_Internal_Vernaux *));
|
||||
extern void _bfd_elf_swap_vernaux_out
|
||||
PARAMS ((bfd *, const Elf_Internal_Vernaux *, Elf_External_Vernaux *));
|
||||
extern void _bfd_elf_swap_versym_in
|
||||
PARAMS ((bfd *, const Elf_External_Versym *, Elf_Internal_Versym *));
|
||||
extern void _bfd_elf_swap_versym_out
|
||||
PARAMS ((bfd *, const Elf_Internal_Versym *, Elf_External_Versym *));
|
||||
|
||||
extern int _bfd_elf_section_from_bfd_section PARAMS ((bfd *, asection *));
|
||||
extern char *bfd_elf_string_from_elf_section
|
||||
PARAMS ((bfd *, unsigned, unsigned));
|
||||
|
@ -690,6 +754,7 @@ extern boolean _bfd_elf_link_hash_table_init
|
|||
struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
|
||||
struct bfd_hash_table *,
|
||||
const char *)));
|
||||
extern boolean _bfd_elf_slurp_version_tables PARAMS ((bfd *));
|
||||
|
||||
extern boolean _bfd_elf_copy_private_symbol_data
|
||||
PARAMS ((bfd *, asymbol *, bfd *, asymbol *));
|
||||
|
@ -712,6 +777,7 @@ extern long _bfd_elf_canonicalize_dynamic_reloc PARAMS ((bfd *, arelent **,
|
|||
extern asymbol *_bfd_elf_make_empty_symbol PARAMS ((bfd *));
|
||||
extern void _bfd_elf_get_symbol_info PARAMS ((bfd *, asymbol *,
|
||||
symbol_info *));
|
||||
extern boolean _bfd_elf_is_local_label_name PARAMS ((bfd *, const char *));
|
||||
extern alent *_bfd_elf_get_lineno PARAMS ((bfd *, asymbol *));
|
||||
extern boolean _bfd_elf_set_arch_mach PARAMS ((bfd *, enum bfd_architecture,
|
||||
unsigned long));
|
||||
|
|
110
bfd/elf.c
110
bfd/elf.c
|
@ -701,9 +701,10 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
|
|||
}
|
||||
|
||||
/* Display ELF-specific fields of a symbol. */
|
||||
|
||||
void
|
||||
bfd_elf_print_symbol (ignore_abfd, filep, symbol, how)
|
||||
bfd *ignore_abfd;
|
||||
bfd_elf_print_symbol (abfd, filep, symbol, how)
|
||||
bfd *abfd;
|
||||
PTR filep;
|
||||
asymbol *symbol;
|
||||
bfd_print_symbol_type how;
|
||||
|
@ -733,11 +734,64 @@ bfd_elf_print_symbol (ignore_abfd, filep, symbol, how)
|
|||
(bfd_is_com_section (symbol->section)
|
||||
? ((elf_symbol_type *) symbol)->internal_elf_sym.st_value
|
||||
: ((elf_symbol_type *) symbol)->internal_elf_sym.st_size));
|
||||
|
||||
/* If we have version information, print it. */
|
||||
if (elf_tdata (abfd)->dynversym_section != 0
|
||||
&& (elf_tdata (abfd)->dynverdef_section != 0
|
||||
|| elf_tdata (abfd)->dynverref_section != 0))
|
||||
{
|
||||
unsigned int vernum;
|
||||
const char *version_string;
|
||||
|
||||
vernum = ((elf_symbol_type *) symbol)->version & VERSYM_VERSION;
|
||||
|
||||
if (vernum == 0)
|
||||
version_string = "";
|
||||
else if (vernum == 1)
|
||||
version_string = "Base";
|
||||
else if (vernum < elf_tdata (abfd)->cverdefs)
|
||||
version_string =
|
||||
elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
|
||||
else
|
||||
{
|
||||
Elf_Internal_Verneed *t;
|
||||
|
||||
version_string = "";
|
||||
for (t = elf_tdata (abfd)->verref;
|
||||
t != NULL;
|
||||
t = t->vn_nextref)
|
||||
{
|
||||
Elf_Internal_Vernaux *a;
|
||||
|
||||
for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
|
||||
{
|
||||
if (a->vna_other == vernum)
|
||||
{
|
||||
version_string = a->vna_nodename;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((((elf_symbol_type *) symbol)->version & VERSYM_HIDDEN) == 0)
|
||||
fprintf (file, " %-12s", version_string);
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf (file, " (%s)", version_string);
|
||||
for (i = strlen (version_string) - 10; i > 0; --i)
|
||||
putc (' ', file);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the st_other field is not zero, print it. */
|
||||
if (((elf_symbol_type *) symbol)->internal_elf_sym.st_other != 0)
|
||||
fprintf (file, " 0x%02x",
|
||||
((unsigned int)
|
||||
((elf_symbol_type *) symbol)->internal_elf_sym.st_other));
|
||||
|
||||
fprintf (file, " %s", symbol->name);
|
||||
}
|
||||
break;
|
||||
|
@ -1098,16 +1152,19 @@ bfd_section_from_shdr (abfd, shindex)
|
|||
case SHT_GNU_verdef:
|
||||
elf_dynverdef (abfd) = shindex;
|
||||
elf_tdata (abfd)->dynverdef_hdr = *hdr;
|
||||
return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
|
||||
break;
|
||||
|
||||
case SHT_GNU_versym:
|
||||
elf_dynversym (abfd) = shindex;
|
||||
elf_tdata (abfd)->dynversym_hdr = *hdr;
|
||||
return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
|
||||
break;
|
||||
|
||||
case SHT_GNU_verneed:
|
||||
elf_dynverref (abfd) = shindex;
|
||||
elf_tdata (abfd)->dynverref_hdr = *hdr;
|
||||
return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
|
||||
break;
|
||||
|
||||
case SHT_SHLIB:
|
||||
|
@ -1338,13 +1395,27 @@ elf_fake_sections (abfd, asect, failedptrarg)
|
|||
{
|
||||
this_hdr->sh_type = SHT_GNU_verdef;
|
||||
this_hdr->sh_entsize = 0;
|
||||
this_hdr->sh_info = elf_tdata (abfd)->cverdefs;
|
||||
/* objcopy or strip will copy over sh_info, but may not set
|
||||
cverdefs. The linker will set cverdefs, but sh_info will be
|
||||
zero. */
|
||||
if (this_hdr->sh_info == 0)
|
||||
this_hdr->sh_info = elf_tdata (abfd)->cverdefs;
|
||||
else
|
||||
BFD_ASSERT (elf_tdata (abfd)->cverdefs == 0
|
||||
|| this_hdr->sh_info == elf_tdata (abfd)->cverdefs);
|
||||
}
|
||||
else if (strcmp (asect->name, ".gnu.version_r") == 0)
|
||||
{
|
||||
this_hdr->sh_type = SHT_GNU_verneed;
|
||||
this_hdr->sh_entsize = 0;
|
||||
this_hdr->sh_info = elf_tdata (abfd)->cverrefs;
|
||||
/* objcopy or strip will copy over sh_info, but may not set
|
||||
cverrefs. The linker will set cverrefs, but sh_info will be
|
||||
zero. */
|
||||
if (this_hdr->sh_info == 0)
|
||||
this_hdr->sh_info = elf_tdata (abfd)->cverrefs;
|
||||
else
|
||||
BFD_ASSERT (elf_tdata (abfd)->cverrefs == 0
|
||||
|| this_hdr->sh_info == elf_tdata (abfd)->cverrefs);
|
||||
}
|
||||
else if ((asect->flags & SEC_ALLOC) != 0
|
||||
&& (asect->flags & SEC_LOAD) != 0)
|
||||
|
@ -3187,7 +3258,9 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
|
|||
ohdr->sh_entsize = ihdr->sh_entsize;
|
||||
|
||||
if (ihdr->sh_type == SHT_SYMTAB
|
||||
|| ihdr->sh_type == SHT_DYNSYM)
|
||||
|| ihdr->sh_type == SHT_DYNSYM
|
||||
|| ihdr->sh_type == SHT_GNU_verneed
|
||||
|| ihdr->sh_type == SHT_GNU_verdef)
|
||||
ohdr->sh_info = ihdr->sh_info;
|
||||
|
||||
return true;
|
||||
|
@ -3831,17 +3904,34 @@ _bfd_elf_get_symbol_info (ignore_abfd, symbol, ret)
|
|||
bfd_symbol_info (symbol, ret);
|
||||
}
|
||||
|
||||
/* Return whether a symbol name implies a local symbol. In ELF, local
|
||||
symbols generally start with ``.L''. Most targets use this
|
||||
function for the is_local_label_name entry point, but some override
|
||||
it. */
|
||||
/* Return whether a symbol name implies a local symbol. Most targets
|
||||
use this function for the is_local_label_name entry point, but some
|
||||
override it. */
|
||||
|
||||
boolean
|
||||
_bfd_elf_is_local_label_name (abfd, name)
|
||||
bfd *abfd;
|
||||
const char *name;
|
||||
{
|
||||
return name[0] == '.' && name[1] == 'L';
|
||||
/* Normal local symbols start with ``.L''. */
|
||||
if (name[0] == '.' && name[1] == 'L')
|
||||
return true;
|
||||
|
||||
/* At least some SVR4 compilers (e.g., UnixWare 2.1 cc) generate
|
||||
DWARF debugging symbols starting with ``..''. */
|
||||
if (name[0] == '.' && name[1] == '.')
|
||||
return true;
|
||||
|
||||
/* gcc will sometimes generate symbols beginning with ``_.L_'' when
|
||||
emitting DWARF debugging output. I suspect this is actually a
|
||||
small bug in gcc (it calls ASM_OUTPUT_LABEL when it should call
|
||||
ASM_GENERATE_INTERNAL_LABEL, and this causes the leading
|
||||
underscore to be emitted on some ELF targets). For ease of use,
|
||||
we treat such symbols as local. */
|
||||
if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
alent *
|
||||
|
|
189
bfd/elflink.h
189
bfd/elflink.h
|
@ -1075,7 +1075,41 @@ elf_link_add_object_symbols (abfd, info)
|
|||
goto error_return;
|
||||
|
||||
if (hi->root.type == bfd_link_hash_indirect)
|
||||
hi->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
|
||||
{
|
||||
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? */
|
||||
}
|
||||
|
||||
/* We also need to define an indirection from the
|
||||
nondefault version of the symbol. */
|
||||
|
||||
shortname = bfd_hash_allocate (&info->hash->table,
|
||||
strlen (name));
|
||||
if (shortname == NULL)
|
||||
goto error_return;
|
||||
strncpy (shortname, name, p - name);
|
||||
strcpy (shortname + (p - name), p + 1);
|
||||
|
||||
hi = NULL;
|
||||
if (! (_bfd_generic_link_add_one_symbol
|
||||
(info, abfd, shortname, BSF_INDIRECT,
|
||||
bfd_ind_section_ptr, (bfd_vma) 0, name, false,
|
||||
collect, (struct bfd_link_hash_entry **) &hi)))
|
||||
goto error_return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1823,30 +1857,35 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
|
|||
size_t i;
|
||||
size_t bucketcount = 0;
|
||||
Elf_Internal_Sym isym;
|
||||
struct elf_assign_sym_version_info sinfo;
|
||||
|
||||
/* Set up the version definition section. */
|
||||
s = bfd_get_section_by_name (dynobj, ".gnu.version_d");
|
||||
BFD_ASSERT (s != NULL);
|
||||
|
||||
/* Attach all the symbols to their version information. This
|
||||
may cause some symbols to be unexported. */
|
||||
sinfo.output_bfd = output_bfd;
|
||||
sinfo.info = info;
|
||||
sinfo.verdefs = verdefs;
|
||||
sinfo.export_dynamic = export_dynamic;
|
||||
sinfo.removed_dynamic = false;
|
||||
sinfo.failed = false;
|
||||
|
||||
elf_link_hash_traverse (elf_hash_table (info),
|
||||
elf_link_assign_sym_version,
|
||||
(PTR) &sinfo);
|
||||
if (sinfo.failed)
|
||||
return false;
|
||||
|
||||
/* We may have created additional version definitions if we are
|
||||
just linking a regular application. */
|
||||
verdefs = sinfo.verdefs;
|
||||
|
||||
if (verdefs == NULL)
|
||||
{
|
||||
struct elf_assign_sym_version_info sinfo;
|
||||
asection **spp;
|
||||
|
||||
/* No version script was used. In this case, we just check
|
||||
that there were no version overrides for any symbols. */
|
||||
sinfo.output_bfd = output_bfd;
|
||||
sinfo.info = info;
|
||||
sinfo.verdefs = verdefs;
|
||||
sinfo.removed_dynamic = false;
|
||||
sinfo.export_dynamic = export_dynamic;
|
||||
sinfo.failed = false;
|
||||
|
||||
elf_link_hash_traverse (elf_hash_table (info),
|
||||
elf_link_assign_sym_version,
|
||||
(PTR) &sinfo);
|
||||
if (sinfo.failed)
|
||||
return false;
|
||||
|
||||
/* Don't include this section in the output file. */
|
||||
for (spp = &output_bfd->sections;
|
||||
*spp != s->output_section;
|
||||
|
@ -1857,7 +1896,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
|
|||
}
|
||||
else
|
||||
{
|
||||
struct elf_assign_sym_version_info sinfo;
|
||||
unsigned int cdefs;
|
||||
bfd_size_type size;
|
||||
struct bfd_elf_version_tree *t;
|
||||
|
@ -1865,20 +1903,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
|
|||
Elf_Internal_Verdef def;
|
||||
Elf_Internal_Verdaux defaux;
|
||||
|
||||
/* Attach all of the symbols to their version information.
|
||||
This may cause some symbols to be unexported. */
|
||||
sinfo.output_bfd = output_bfd;
|
||||
sinfo.info = info;
|
||||
sinfo.verdefs = verdefs;
|
||||
sinfo.export_dynamic = export_dynamic;
|
||||
sinfo.removed_dynamic = false;
|
||||
sinfo.failed = false;
|
||||
elf_link_hash_traverse (elf_hash_table (info),
|
||||
elf_link_assign_sym_version,
|
||||
(PTR) &sinfo);
|
||||
if (sinfo.failed)
|
||||
return false;
|
||||
|
||||
if (sinfo.removed_dynamic)
|
||||
{
|
||||
/* Some dynamic symbols were changed to be local
|
||||
|
@ -1979,11 +2003,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
|
|||
h->type = STT_OBJECT;
|
||||
h->verinfo.vertree = t;
|
||||
|
||||
if (info->shared)
|
||||
{
|
||||
if (! _bfd_elf_link_record_dynamic_symbol (info, h))
|
||||
return false;
|
||||
}
|
||||
if (! _bfd_elf_link_record_dynamic_symbol (info, h))
|
||||
return false;
|
||||
|
||||
def.vd_version = VER_DEF_CURRENT;
|
||||
def.vd_flags = 0;
|
||||
|
@ -2075,6 +2096,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
|
|||
bfd_byte *p;
|
||||
|
||||
/* Build the version definition section. */
|
||||
size = 0;
|
||||
crefs = 0;
|
||||
for (t = elf_tdata (output_bfd)->verref;
|
||||
t != NULL;
|
||||
t = t->vn_nextref)
|
||||
|
@ -2549,14 +2572,94 @@ elf_link_assign_sym_version (h, data)
|
|||
{
|
||||
h->verinfo.vertree = t;
|
||||
t->used = true;
|
||||
|
||||
/* See if there is anything to force this symbol to
|
||||
local scope. */
|
||||
if (t->locals != NULL)
|
||||
{
|
||||
int len;
|
||||
char *alc;
|
||||
struct bfd_elf_version_expr *d;
|
||||
|
||||
len = p - h->root.root.string;
|
||||
alc = bfd_alloc (sinfo->output_bfd, len);
|
||||
if (alc == NULL)
|
||||
return false;
|
||||
strncpy (alc, h->root.root.string, len - 1);
|
||||
alc[len - 1] = '\0';
|
||||
if (alc[len - 2] == ELF_VER_CHR)
|
||||
alc[len - 2] = '\0';
|
||||
|
||||
for (d = t->locals; d != NULL; d = d->next)
|
||||
{
|
||||
if ((d->match[0] == '*' && d->match[1] == '\0')
|
||||
|| fnmatch (d->match, alc, 0) == 0)
|
||||
{
|
||||
if (h->dynindx != -1
|
||||
&& info->shared
|
||||
&& ! sinfo->export_dynamic
|
||||
&& (h->elf_link_hash_flags
|
||||
& ELF_LINK_HASH_NEEDS_PLT) == 0)
|
||||
{
|
||||
sinfo->removed_dynamic = true;
|
||||
h->dynindx = -1;
|
||||
/* FIXME: The name of the symbol has
|
||||
already been recorded in the dynamic
|
||||
string table section. */
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bfd_release (sinfo->output_bfd, alc);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (t == NULL)
|
||||
/* If we are building an application, we need to create a
|
||||
version node for this version. */
|
||||
if (t == NULL && ! info->shared)
|
||||
{
|
||||
/* We could not find the version. Return an error.
|
||||
FIXME: Why? */
|
||||
struct bfd_elf_version_tree **pp;
|
||||
int version_index;
|
||||
|
||||
/* If we aren't going to export this symbol, we don't need
|
||||
to worry about it. */
|
||||
if (h->dynindx == -1)
|
||||
return true;
|
||||
|
||||
t = ((struct bfd_elf_version_tree *)
|
||||
bfd_alloc (sinfo->output_bfd, sizeof *t));
|
||||
if (t == NULL)
|
||||
{
|
||||
sinfo->failed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
t->next = NULL;
|
||||
t->name = p;
|
||||
t->globals = NULL;
|
||||
t->locals = NULL;
|
||||
t->deps = NULL;
|
||||
t->name_indx = (unsigned int) -1;
|
||||
t->used = true;
|
||||
|
||||
version_index = 1;
|
||||
for (pp = &sinfo->verdefs; *pp != NULL; pp = &(*pp)->next)
|
||||
++version_index;
|
||||
t->vernum = version_index;
|
||||
|
||||
*pp = t;
|
||||
|
||||
h->verinfo.vertree = t;
|
||||
}
|
||||
else if (t == NULL)
|
||||
{
|
||||
/* We could not find the version for a symbol when
|
||||
generating a shared archive. Return an error. */
|
||||
(*_bfd_error_handler)
|
||||
("%s: invalid version %s", bfd_get_filename (sinfo->output_bfd),
|
||||
h->root.root.string);
|
||||
|
@ -3617,8 +3720,10 @@ elf_link_output_extsym (h, data)
|
|||
to the decorated version of the name. For example, if the
|
||||
symbol foo@@GNU_1.2 is the default, which should be used when
|
||||
foo is used with no version, then we add an indirect symbol
|
||||
foo which points to foo@@GNU_1.2. */
|
||||
if ((h->elf_link_hash_flags & ELF_LINK_NON_ELF) != 0)
|
||||
foo which points to foo@@GNU_1.2. We ignore these symbols,
|
||||
since the indirected symbol is already in the hash table. If
|
||||
the indirect symbol is non-ELF, fall through and output it. */
|
||||
if ((h->elf_link_hash_flags & ELF_LINK_NON_ELF) == 0)
|
||||
return true;
|
||||
|
||||
/* Fall through. */
|
||||
|
|
Loading…
Add table
Reference in a new issue