* elf-bfd.h (_bfd_elf_slurp_version_tables): Update prototype.
	* elf.c (_bfd_elf_print_private_bfd_data): Pass extra argument.
	(_bfd_elf_slurp_version_tables): Add extra argument.  Create extra
	default version definition for unversioned symbols.
	* elfcode.h (elf_slurp_symbol_table): Pass extra argument.
	* elflink.c (elf_link_add_object_symbols): Pass extra argument to
	_bfd_elf_slurp_version_tables.  Set default version for unversioned
	imported symbols.
include/
	* bfdlink.h (bfd_link_info): Add default_imported_symver.
ld/
	* ld.texinfo: Document --default-imported-symver.
	* ldmain.c (main): Set link_info.default_imported_symver.
	* lexsup.c (option_values): Add OPTION_DEFAULT_IMPORTED_SYMVER.
	(ld_options): Add --default-imported-symver.
	(parse_args): Handle OPTION_DEFAULT_IMPORTED_SYMVER.
This commit is contained in:
Paul Brook 2004-11-15 23:21:27 +00:00
parent 2e8d14f482
commit fc0e6df64d
11 changed files with 297 additions and 195 deletions

View File

@ -1,3 +1,14 @@
2004-11-04 Paul Brook <paul@codesourcery.com>
* elf-bfd.h (_bfd_elf_slurp_version_tables): Update prototype.
* elf.c (_bfd_elf_print_private_bfd_data): Pass extra argument.
(_bfd_elf_slurp_version_tables): Add extra argument. Create extra
default version definition for unversioned symbols.
* elfcode.h (elf_slurp_symbol_table): Pass extra argument.
* elflink.c (elf_link_add_object_symbols): Pass extra argument to
_bfd_elf_slurp_version_tables. Set default version for unversioned
imported symbols.
2004-11-15 Paul Brook <paul@codesourcery.com>
* elflink.c (elf_link_add_object_symbols): Don't assume version

View File

@ -1419,7 +1419,7 @@ extern bfd_boolean _bfd_elf_link_hash_table_init
struct bfd_hash_entry *(*)
(struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
extern bfd_boolean _bfd_elf_slurp_version_tables
(bfd *);
(bfd *, bfd_boolean);
extern bfd_boolean _bfd_elf_merge_sections
(bfd *, struct bfd_link_info *);
extern bfd_boolean bfd_elf_is_group_section

254
bfd/elf.c
View File

@ -1192,7 +1192,7 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
if ((elf_dynverdef (abfd) != 0 && elf_tdata (abfd)->verdef == NULL)
|| (elf_dynverref (abfd) != 0 && elf_tdata (abfd)->verref == NULL))
{
if (! _bfd_elf_slurp_version_tables (abfd))
if (! _bfd_elf_slurp_version_tables (abfd, FALSE))
return FALSE;
}
@ -6027,109 +6027,11 @@ _bfd_elf_canonicalize_dynamic_reloc (bfd *abfd,
/* Read in the version information. */
bfd_boolean
_bfd_elf_slurp_version_tables (bfd *abfd)
_bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
{
bfd_byte *contents = NULL;
bfd_size_type amt;
if (elf_dynverdef (abfd) != 0)
{
Elf_Internal_Shdr *hdr;
Elf_External_Verdef *everdef;
Elf_Internal_Verdef *iverdef;
Elf_Internal_Verdef *iverdefarr;
Elf_Internal_Verdef iverdefmem;
unsigned int i;
unsigned int maxidx;
hdr = &elf_tdata (abfd)->dynverdef_hdr;
contents = bfd_malloc (hdr->sh_size);
if (contents == NULL)
goto error_return;
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
|| bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
goto error_return;
/* We know the number of entries in the section but not the maximum
index. Therefore we have to run through all entries and find
the maximum. */
everdef = (Elf_External_Verdef *) contents;
maxidx = 0;
for (i = 0; i < hdr->sh_info; ++i)
{
_bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem);
if ((iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION)) > maxidx)
maxidx = iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION);
everdef = ((Elf_External_Verdef *)
((bfd_byte *) everdef + iverdefmem.vd_next));
}
amt = (bfd_size_type) maxidx * sizeof (Elf_Internal_Verdef);
elf_tdata (abfd)->verdef = bfd_zalloc (abfd, amt);
if (elf_tdata (abfd)->verdef == NULL)
goto error_return;
elf_tdata (abfd)->cverdefs = maxidx;
everdef = (Elf_External_Verdef *) contents;
iverdefarr = elf_tdata (abfd)->verdef;
for (i = 0; i < hdr->sh_info; i++)
{
Elf_External_Verdaux *everdaux;
Elf_Internal_Verdaux *iverdaux;
unsigned int j;
_bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem);
iverdef = &iverdefarr[(iverdefmem.vd_ndx & VERSYM_VERSION) - 1];
memcpy (iverdef, &iverdefmem, sizeof (Elf_Internal_Verdef));
iverdef->vd_bfd = abfd;
amt = (bfd_size_type) iverdef->vd_cnt * sizeof (Elf_Internal_Verdaux);
iverdef->vd_auxptr = bfd_alloc (abfd, amt);
if (iverdef->vd_auxptr == NULL)
goto error_return;
everdaux = ((Elf_External_Verdaux *)
((bfd_byte *) everdef + iverdef->vd_aux));
iverdaux = iverdef->vd_auxptr;
for (j = 0; j < iverdef->vd_cnt; j++, iverdaux++)
{
_bfd_elf_swap_verdaux_in (abfd, everdaux, iverdaux);
iverdaux->vda_nodename =
bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
iverdaux->vda_name);
if (iverdaux->vda_nodename == NULL)
goto error_return;
if (j + 1 < iverdef->vd_cnt)
iverdaux->vda_nextptr = iverdaux + 1;
else
iverdaux->vda_nextptr = NULL;
everdaux = ((Elf_External_Verdaux *)
((bfd_byte *) everdaux + iverdaux->vda_next));
}
iverdef->vd_nodename = iverdef->vd_auxptr->vda_nodename;
if (i + 1 < hdr->sh_info)
iverdef->vd_nextdef = iverdef + 1;
else
iverdef->vd_nextdef = NULL;
everdef = ((Elf_External_Verdef *)
((bfd_byte *) everdef + iverdef->vd_next));
}
free (contents);
contents = NULL;
}
unsigned int freeidx = 0;
if (elf_dynverref (abfd) != 0)
{
@ -6196,6 +6098,9 @@ _bfd_elf_slurp_version_tables (bfd *abfd)
evernaux = ((Elf_External_Vernaux *)
((bfd_byte *) evernaux + ivernaux->vna_next));
if (ivernaux->vna_other > freeidx)
freeidx = ivernaux->vna_other;
}
if (i + 1 < hdr->sh_info)
@ -6211,6 +6116,153 @@ _bfd_elf_slurp_version_tables (bfd *abfd)
contents = NULL;
}
if (elf_dynverdef (abfd) != 0)
{
Elf_Internal_Shdr *hdr;
Elf_External_Verdef *everdef;
Elf_Internal_Verdef *iverdef;
Elf_Internal_Verdef *iverdefarr;
Elf_Internal_Verdef iverdefmem;
unsigned int i;
unsigned int maxidx;
hdr = &elf_tdata (abfd)->dynverdef_hdr;
contents = bfd_malloc (hdr->sh_size);
if (contents == NULL)
goto error_return;
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
|| bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
goto error_return;
/* We know the number of entries in the section but not the maximum
index. Therefore we have to run through all entries and find
the maximum. */
everdef = (Elf_External_Verdef *) contents;
maxidx = 0;
for (i = 0; i < hdr->sh_info; ++i)
{
_bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem);
if ((iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION)) > maxidx)
maxidx = iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION);
everdef = ((Elf_External_Verdef *)
((bfd_byte *) everdef + iverdefmem.vd_next));
}
if (default_imported_symver)
{
if (freeidx > maxidx)
maxidx = ++freeidx;
else
freeidx = ++maxidx;
}
amt = (bfd_size_type) maxidx * sizeof (Elf_Internal_Verdef);
elf_tdata (abfd)->verdef = bfd_zalloc (abfd, amt);
if (elf_tdata (abfd)->verdef == NULL)
goto error_return;
elf_tdata (abfd)->cverdefs = maxidx;
everdef = (Elf_External_Verdef *) contents;
iverdefarr = elf_tdata (abfd)->verdef;
for (i = 0; i < hdr->sh_info; i++)
{
Elf_External_Verdaux *everdaux;
Elf_Internal_Verdaux *iverdaux;
unsigned int j;
_bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem);
iverdef = &iverdefarr[(iverdefmem.vd_ndx & VERSYM_VERSION) - 1];
memcpy (iverdef, &iverdefmem, sizeof (Elf_Internal_Verdef));
iverdef->vd_bfd = abfd;
amt = (bfd_size_type) iverdef->vd_cnt * sizeof (Elf_Internal_Verdaux);
iverdef->vd_auxptr = bfd_alloc (abfd, amt);
if (iverdef->vd_auxptr == NULL)
goto error_return;
everdaux = ((Elf_External_Verdaux *)
((bfd_byte *) everdef + iverdef->vd_aux));
iverdaux = iverdef->vd_auxptr;
for (j = 0; j < iverdef->vd_cnt; j++, iverdaux++)
{
_bfd_elf_swap_verdaux_in (abfd, everdaux, iverdaux);
iverdaux->vda_nodename =
bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
iverdaux->vda_name);
if (iverdaux->vda_nodename == NULL)
goto error_return;
if (j + 1 < iverdef->vd_cnt)
iverdaux->vda_nextptr = iverdaux + 1;
else
iverdaux->vda_nextptr = NULL;
everdaux = ((Elf_External_Verdaux *)
((bfd_byte *) everdaux + iverdaux->vda_next));
}
iverdef->vd_nodename = iverdef->vd_auxptr->vda_nodename;
if (i + 1 < hdr->sh_info)
iverdef->vd_nextdef = iverdef + 1;
else
iverdef->vd_nextdef = NULL;
everdef = ((Elf_External_Verdef *)
((bfd_byte *) everdef + iverdef->vd_next));
}
free (contents);
contents = NULL;
}
else if (default_imported_symver)
{
if (freeidx < 3)
freeidx = 3;
else
freeidx++;
amt = (bfd_size_type) freeidx * sizeof (Elf_Internal_Verdef);
elf_tdata (abfd)->verdef = bfd_zalloc (abfd, amt);
if (elf_tdata (abfd)->verdef == NULL)
goto error_return;
elf_tdata (abfd)->cverdefs = freeidx;
}
/* Create a default version based on the soname. */
if (default_imported_symver)
{
Elf_Internal_Verdef *iverdef;
Elf_Internal_Verdaux *iverdaux;
iverdef = &elf_tdata (abfd)->verdef[freeidx - 1];;
iverdef->vd_version = VER_DEF_CURRENT;
iverdef->vd_flags = 0;
iverdef->vd_ndx = freeidx;
iverdef->vd_cnt = 1;
iverdef->vd_bfd = abfd;
iverdef->vd_nodename = bfd_elf_get_dt_soname (abfd);
if (iverdef->vd_nodename == NULL)
goto error_return;
iverdef->vd_nextdef = NULL;
amt = (bfd_size_type) sizeof (Elf_Internal_Verdaux);
iverdef->vd_auxptr = bfd_alloc (abfd, amt);
iverdaux = iverdef->vd_auxptr;
iverdaux->vda_nodename = iverdef->vd_nodename;
iverdaux->vda_nextptr = NULL;
}
return TRUE;
error_return:

View File

@ -1026,7 +1026,7 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
|| (elf_tdata (abfd)->dynverref_section != 0
&& elf_tdata (abfd)->verref == NULL))
{
if (! _bfd_elf_slurp_version_tables (abfd))
if (!_bfd_elf_slurp_version_tables (abfd, FALSE))
return -1;
}
}

View File

@ -3347,7 +3347,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (dynamic)
{
/* Read in any version definitions. */
if (! _bfd_elf_slurp_version_tables (abfd))
if (!_bfd_elf_slurp_version_tables (abfd,
info->default_imported_symver))
goto error_free_sym;
/* Read in the symbol versions, but don't bother to convert them
@ -3499,102 +3500,109 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
unsigned int vernum = 0;
bfd_boolean skip;
if (ever != NULL)
if (ever == NULL)
{
_bfd_elf_swap_versym_in (abfd, ever, &iver);
vernum = iver.vs_vers & VERSYM_VERSION;
if (info->default_imported_symver)
/* Use the default symbol version created earlier. */
iver.vs_vers = elf_tdata (abfd)->cverdefs;
else
iver.vs_vers = 0;
}
else
_bfd_elf_swap_versym_in (abfd, ever, &iver);
/* If this is a hidden symbol, or if it is not version
1, we append the version name to the symbol name.
However, we do not modify a non-hidden absolute
symbol, because it might be the version symbol
itself. FIXME: What if it isn't? */
if ((iver.vs_vers & VERSYM_HIDDEN) != 0
|| (vernum > 1 && ! bfd_is_abs_section (sec)))
vernum = iver.vs_vers & VERSYM_VERSION;
/* If this is a hidden symbol, or if it is not version
1, we append the version name to the symbol name.
However, we do not modify a non-hidden absolute
symbol, because it might be the version symbol
itself. FIXME: What if it isn't? */
if ((iver.vs_vers & VERSYM_HIDDEN) != 0
|| (vernum > 1 && ! bfd_is_abs_section (sec)))
{
const char *verstr;
size_t namelen, verlen, newlen;
char *newname, *p;
if (isym->st_shndx != SHN_UNDEF)
{
const char *verstr;
size_t namelen, verlen, newlen;
char *newname, *p;
if (isym->st_shndx != SHN_UNDEF)
{
if (vernum > elf_tdata (abfd)->cverdefs)
verstr = NULL;
else if (vernum > 1)
verstr =
elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
else
verstr = "";
if (verstr == NULL)
{
(*_bfd_error_handler)
(_("%B: %s: invalid version %u (max %d)"),
abfd, name, vernum,
elf_tdata (abfd)->cverdefs);
bfd_set_error (bfd_error_bad_value);
goto error_free_vers;
}
}
if (vernum > elf_tdata (abfd)->cverdefs)
verstr = NULL;
else if (vernum > 1)
verstr =
elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
else
verstr = "";
if (verstr == NULL)
{
/* We cannot simply test for the number of
entries in the VERNEED section since the
numbers for the needed versions do not start
at 0. */
Elf_Internal_Verneed *t;
verstr = NULL;
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)
{
verstr = a->vna_nodename;
break;
}
}
if (a != NULL)
break;
}
if (verstr == NULL)
{
(*_bfd_error_handler)
(_("%B: %s: invalid needed version %d"),
abfd, name, vernum);
bfd_set_error (bfd_error_bad_value);
goto error_free_vers;
}
(*_bfd_error_handler)
(_("%B: %s: invalid version %u (max %d)"),
abfd, name, vernum,
elf_tdata (abfd)->cverdefs);
bfd_set_error (bfd_error_bad_value);
goto error_free_vers;
}
namelen = strlen (name);
verlen = strlen (verstr);
newlen = namelen + verlen + 2;
if ((iver.vs_vers & VERSYM_HIDDEN) == 0
&& isym->st_shndx != SHN_UNDEF)
++newlen;
newname = bfd_alloc (abfd, newlen);
if (newname == NULL)
goto error_free_vers;
memcpy (newname, name, namelen);
p = newname + namelen;
*p++ = ELF_VER_CHR;
/* If this is a defined non-hidden version symbol,
we add another @ to the name. This indicates the
default version of the symbol. */
if ((iver.vs_vers & VERSYM_HIDDEN) == 0
&& isym->st_shndx != SHN_UNDEF)
*p++ = ELF_VER_CHR;
memcpy (p, verstr, verlen + 1);
name = newname;
}
else
{
/* We cannot simply test for the number of
entries in the VERNEED section since the
numbers for the needed versions do not start
at 0. */
Elf_Internal_Verneed *t;
verstr = NULL;
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)
{
verstr = a->vna_nodename;
break;
}
}
if (a != NULL)
break;
}
if (verstr == NULL)
{
(*_bfd_error_handler)
(_("%B: %s: invalid needed version %d"),
abfd, name, vernum);
bfd_set_error (bfd_error_bad_value);
goto error_free_vers;
}
}
namelen = strlen (name);
verlen = strlen (verstr);
newlen = namelen + verlen + 2;
if ((iver.vs_vers & VERSYM_HIDDEN) == 0
&& isym->st_shndx != SHN_UNDEF)
++newlen;
newname = bfd_alloc (abfd, newlen);
if (newname == NULL)
goto error_free_vers;
memcpy (newname, name, namelen);
p = newname + namelen;
*p++ = ELF_VER_CHR;
/* If this is a defined non-hidden version symbol,
we add another @ to the name. This indicates the
default version of the symbol. */
if ((iver.vs_vers & VERSYM_HIDDEN) == 0
&& isym->st_shndx != SHN_UNDEF)
*p++ = ELF_VER_CHR;
memcpy (p, verstr, verlen + 1);
name = newname;
}
if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, &value,

View File

@ -1,3 +1,7 @@
2004-11-04 Paul Brook <paul@codesourcery.com>
* bfdlink.h (bfd_link_info): Add default_imported_symver.
2004-11-12 Bob Wilson <bob.wilson@acm.org>
* xtensa-isa-internal.h (xtensa_interface_internal): Add class_id.

View File

@ -262,9 +262,14 @@ struct bfd_link_info
/* TRUE if ok to have version with no definition. */
unsigned int allow_undefined_version: 1;
/* TRUE id a fedault symbol version should be created and used. */
/* TRUE if a default symbol version should be created and used for
exported symbols. */
unsigned int create_default_symver: 1;
/* TRUE if a default symbol version should be created and used for
imported symbols. */
unsigned int default_imported_symver: 1;
/* TRUE if symbols should be retained in memory, FALSE if they
should be freed and reread. */
unsigned int keep_memory: 1;

View File

@ -1,3 +1,11 @@
2004-11-04 Paul Brook <paul@codesourcery.com>
* ld.texinfo: Document --default-imported-symver.
* ldmain.c (main): Set link_info.default_imported_symver.
* lexsup.c (option_values): Add OPTION_DEFAULT_IMPORTED_SYMVER.
(ld_options): Add --default-imported-symver.
(parse_args): Handle OPTION_DEFAULT_IMPORTED_SYMVER.
2004-11-08 Inderpreet Singh <inderpreetb@nioda.hcltech.com>
Vineet Sharma <vineets@noida.hcltech.com>

View File

@ -1237,7 +1237,12 @@ will be issued instead.
@kindex --default-symver
@item --default-symver
Create and use a default symbol version (the soname) for unversioned
symbols.
exported symbols.
@kindex --default-imported-symver
@item --default-imported-symver
Create and use a default symbol version (the soname) for unversioned
imported symbols.
@kindex --no-warn-mismatch
@item --no-warn-mismatch

View File

@ -307,6 +307,7 @@ main (int argc, char **argv)
link_info.allow_multiple_definition = FALSE;
link_info.allow_undefined_version = TRUE;
link_info.create_default_symver = FALSE;
link_info.default_imported_symver = FALSE;
link_info.keep_memory = TRUE;
link_info.notice_all = FALSE;
link_info.nocopyreloc = FALSE;

View File

@ -136,6 +136,7 @@ enum option_values
OPTION_ALLOW_MULTIPLE_DEFINITION,
OPTION_NO_UNDEFINED_VERSION,
OPTION_DEFAULT_SYMVER,
OPTION_DEFAULT_IMPORTED_SYMVER,
OPTION_DISCARD_NONE,
OPTION_SPARE_DYNAMIC_TAGS,
OPTION_NO_DEFINE_COMMON,
@ -397,6 +398,10 @@ static const struct ld_option ld_options[] =
'\0', NULL, N_("Disallow undefined version"), TWO_DASHES },
{ {"default-symver", no_argument, NULL, OPTION_DEFAULT_SYMVER},
'\0', NULL, N_("Create default symbol version"), TWO_DASHES },
{ {"default-imported-symver", no_argument, NULL,
OPTION_DEFAULT_IMPORTED_SYMVER},
'\0', NULL, N_("Create default symbol version for imported symbols"),
TWO_DASHES },
{ {"no-warn-mismatch", no_argument, NULL, OPTION_NO_WARN_MISMATCH},
'\0', NULL, N_("Don't warn about mismatched input files"), TWO_DASHES},
{ {"no-whole-archive", no_argument, NULL, OPTION_NO_WHOLE_ARCHIVE},
@ -909,6 +914,9 @@ parse_args (unsigned argc, char **argv)
case OPTION_DEFAULT_SYMVER:
link_info.create_default_symver = TRUE;
break;
case OPTION_DEFAULT_IMPORTED_SYMVER:
link_info.default_imported_symver = TRUE;
break;
case OPTION_NO_WARN_MISMATCH:
command_line.warn_mismatch = FALSE;
break;