Display symbol version when dumping dynrelocs
Both readelf/objdump know how to get symbol version string for dynamic symbols. This patch extracts this functionality into a separate function and uses it to add symbol version string to versioned symbol names when dumping dynamic relocations. bfd/ PR binutils/16496 * elf-bfd.h (bfd_elf_get_symbol_version_string): New. * elf.c (bfd_elf_get_symbol_version_string): New. Extracted from bfd_elf_print_symbol. (bfd_elf_print_symbol): Use it. binutils/ PR binutils/16496 * objdump.c (objdump_print_symname): Call bfd_elf_get_symbol_version_string to get ELF symbol version string. Append version string if needed. * readelf.c (versioned_symbol_info): New enum. (get_symbol_version_string): New. Extracted from process_symbol_table. (dump_relocations): Add a new argument to indicate if dynamic symbol table is used. Use get_symbol_version_string to get symbol version string for dynamic symbol. Append version string if needed. (process_relocs): Updated dump_relocations call. (process_symbol_table): Use get_symbol_version_string. ld/testsuite/ PR binutils/16496 * ld-cris/weakref3.d: Add symbol version string to versioned symbol names in dynamic relocation. * ld-cris/weakref4.d: Likewise. * ld-elfvers/vers24.rd: Likewise. * ld-elf/pr16496a.c: New file. * ld-elf/pr16496a.map: Likewise. * ld-elf/pr16496b.c: Likewise. * ld-elf/pr16496b.od: Likewise. * ld-elf/shared.exp (build_tests): Add libpr16496a.so and libpr16496b.so tests.
This commit is contained in:
parent
dd7e64d45b
commit
bb4d2ac2cc
15 changed files with 378 additions and 206 deletions
|
@ -1,3 +1,11 @@
|
|||
2014-11-25 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR binutils/16496
|
||||
* elf-bfd.h (bfd_elf_get_symbol_version_string): New.
|
||||
* elf.c (bfd_elf_get_symbol_version_string): New. Extracted
|
||||
from bfd_elf_print_symbol.
|
||||
(bfd_elf_print_symbol): Use it.
|
||||
|
||||
2014-11-25 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* elf32-i386.c (elf_i386_got_plt_entry): New.
|
||||
|
|
|
@ -1772,6 +1772,8 @@ extern bfd_boolean _bfd_elf_copy_private_bfd_data
|
|||
(bfd *, bfd *);
|
||||
extern bfd_boolean _bfd_elf_print_private_bfd_data
|
||||
(bfd *, void *);
|
||||
const char * bfd_elf_get_symbol_version_string
|
||||
(bfd *, asymbol *, bfd_boolean *);
|
||||
extern void bfd_elf_print_symbol
|
||||
(bfd *, void *, asymbol *, bfd_print_symbol_type);
|
||||
|
||||
|
|
92
bfd/elf.c
92
bfd/elf.c
|
@ -1422,6 +1422,53 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Get version string. */
|
||||
|
||||
const char *
|
||||
bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol,
|
||||
bfd_boolean *hidden)
|
||||
{
|
||||
const char *version_string = NULL;
|
||||
if (elf_dynversym (abfd) != 0
|
||||
&& (elf_dynverdef (abfd) != 0 || elf_dynverref (abfd) != 0))
|
||||
{
|
||||
unsigned int vernum = ((elf_symbol_type *) symbol)->version;
|
||||
|
||||
*hidden = (vernum & VERSYM_HIDDEN) != 0;
|
||||
vernum &= 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return version_string;
|
||||
}
|
||||
|
||||
/* Display ELF-specific fields of a symbol. */
|
||||
|
||||
void
|
||||
|
@ -1448,6 +1495,8 @@ bfd_elf_print_symbol (bfd *abfd,
|
|||
const struct elf_backend_data *bed;
|
||||
unsigned char st_other;
|
||||
bfd_vma val;
|
||||
const char *version_string;
|
||||
bfd_boolean hidden;
|
||||
|
||||
section_name = symbol->section ? symbol->section->name : "(*none*)";
|
||||
|
||||
|
@ -1473,45 +1522,12 @@ bfd_elf_print_symbol (bfd *abfd,
|
|||
bfd_fprintf_vma (abfd, file, val);
|
||||
|
||||
/* If we have version information, print it. */
|
||||
if (elf_dynversym (abfd) != 0
|
||||
&& (elf_dynverdef (abfd) != 0
|
||||
|| elf_dynverref (abfd) != 0))
|
||||
version_string = bfd_elf_get_symbol_version_string (abfd,
|
||||
symbol,
|
||||
&hidden);
|
||||
if (version_string)
|
||||
{
|
||||
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)
|
||||
if (!hidden)
|
||||
fprintf (file, " %-11s", version_string);
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
2014-11-25 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR binutils/16496
|
||||
* objdump.c (objdump_print_symname): Call
|
||||
bfd_elf_get_symbol_version_string to get ELF symbol version
|
||||
string. Append version string if needed.
|
||||
|
||||
* readelf.c (versioned_symbol_info): New enum.
|
||||
(get_symbol_version_string): New. Extracted from
|
||||
process_symbol_table.
|
||||
(dump_relocations): Add a new argument to indicate if dynamic
|
||||
symbol table is used. Use get_symbol_version_string to get
|
||||
symbol version string for dynamic symbol. Append version string
|
||||
if needed.
|
||||
(process_relocs): Updated dump_relocations call.
|
||||
(process_symbol_table): Use get_symbol_version_string.
|
||||
|
||||
2014-11-24 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* configure: Regenerated.
|
||||
|
|
|
@ -795,7 +795,8 @@ objdump_print_symname (bfd *abfd, struct disassemble_info *inf,
|
|||
asymbol *sym)
|
||||
{
|
||||
char *alloc;
|
||||
const char *name;
|
||||
const char *name, *version_string = NULL;
|
||||
bfd_boolean hidden = FALSE;
|
||||
|
||||
alloc = NULL;
|
||||
name = bfd_asymbol_name (sym);
|
||||
|
@ -807,10 +808,26 @@ objdump_print_symname (bfd *abfd, struct disassemble_info *inf,
|
|||
name = alloc;
|
||||
}
|
||||
|
||||
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
|
||||
version_string = bfd_elf_get_symbol_version_string (abfd, sym,
|
||||
&hidden);
|
||||
|
||||
if (bfd_is_und_section (bfd_get_section (sym)))
|
||||
hidden = TRUE;
|
||||
|
||||
if (inf != NULL)
|
||||
(*inf->fprintf_func) (inf->stream, "%s", name);
|
||||
{
|
||||
(*inf->fprintf_func) (inf->stream, "%s", name);
|
||||
if (version_string && *version_string != '\0')
|
||||
(*inf->fprintf_func) (inf->stream, hidden ? "@%s" : "@@%s",
|
||||
version_string);
|
||||
}
|
||||
else
|
||||
printf ("%s", name);
|
||||
{
|
||||
printf ("%s", name);
|
||||
if (version_string && *version_string != '\0')
|
||||
printf (hidden ? "@%s" : "@@%s", version_string);
|
||||
}
|
||||
|
||||
if (alloc != NULL)
|
||||
free (alloc);
|
||||
|
|
|
@ -272,6 +272,20 @@ typedef enum print_mode
|
|||
}
|
||||
print_mode;
|
||||
|
||||
/* Versioned symbol info. */
|
||||
enum versioned_symbol_info
|
||||
{
|
||||
symbol_undefined,
|
||||
symbol_hidden,
|
||||
symbol_public
|
||||
};
|
||||
|
||||
static const char *get_symbol_version_string
|
||||
(FILE *file, int is_dynsym, const char *strtab,
|
||||
unsigned long int strtab_size, unsigned int si,
|
||||
Elf_Internal_Sym *psym, enum versioned_symbol_info *sym_info,
|
||||
unsigned short *vna_other);
|
||||
|
||||
#define UNKNOWN -1
|
||||
|
||||
#define SECTION_NAME(X) \
|
||||
|
@ -1015,7 +1029,8 @@ dump_relocations (FILE * file,
|
|||
unsigned long nsyms,
|
||||
char * strtab,
|
||||
unsigned long strtablen,
|
||||
int is_rela)
|
||||
int is_rela,
|
||||
int is_dynsym)
|
||||
{
|
||||
unsigned int i;
|
||||
Elf_Internal_Rela * rels;
|
||||
|
@ -1448,9 +1463,20 @@ dump_relocations (FILE * file,
|
|||
else
|
||||
{
|
||||
Elf_Internal_Sym * psym;
|
||||
const char * version_string;
|
||||
enum versioned_symbol_info sym_info;
|
||||
unsigned short vna_other;
|
||||
|
||||
psym = symtab + symtab_index;
|
||||
|
||||
version_string
|
||||
= get_symbol_version_string (file, is_dynsym,
|
||||
strtab, strtablen,
|
||||
symtab_index,
|
||||
psym,
|
||||
&sym_info,
|
||||
&vna_other);
|
||||
|
||||
printf (" ");
|
||||
|
||||
if (ELF_ST_TYPE (psym->st_info) == STT_GNU_IFUNC)
|
||||
|
@ -1477,6 +1503,9 @@ dump_relocations (FILE * file,
|
|||
name = strtab + psym->st_name;
|
||||
|
||||
len = print_symbol (width, name);
|
||||
if (version_string)
|
||||
printf (sym_info == symbol_public ? "@@%s" : "@%s",
|
||||
version_string);
|
||||
printf ("()%-*s", len <= width ? (width + 1) - len : 1, " ");
|
||||
}
|
||||
else
|
||||
|
@ -1533,7 +1562,12 @@ dump_relocations (FILE * file,
|
|||
else if (psym->st_name >= strtablen)
|
||||
printf (_("<corrupt string table index: %3ld>"), psym->st_name);
|
||||
else
|
||||
print_symbol (22, strtab + psym->st_name);
|
||||
{
|
||||
print_symbol (22, strtab + psym->st_name);
|
||||
if (version_string)
|
||||
printf (sym_info == symbol_public ? "@@%s" : "@%s",
|
||||
version_string);
|
||||
}
|
||||
|
||||
if (is_rela)
|
||||
{
|
||||
|
@ -6097,7 +6131,8 @@ process_relocs (FILE * file)
|
|||
offset_from_vma (file, rel_offset, rel_size),
|
||||
rel_size,
|
||||
dynamic_symbols, num_dynamic_syms,
|
||||
dynamic_strings, dynamic_strings_length, is_rela);
|
||||
dynamic_strings, dynamic_strings_length,
|
||||
is_rela, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6172,14 +6207,16 @@ process_relocs (FILE * file)
|
|||
}
|
||||
|
||||
dump_relocations (file, rel_offset, rel_size,
|
||||
symtab, nsyms, strtab, strtablen, is_rela);
|
||||
symtab, nsyms, strtab, strtablen,
|
||||
is_rela,
|
||||
symsec->sh_type == SHT_DYNSYM);
|
||||
if (strtab)
|
||||
free (strtab);
|
||||
free (symtab);
|
||||
}
|
||||
else
|
||||
dump_relocations (file, rel_offset, rel_size,
|
||||
NULL, 0, NULL, 0, is_rela);
|
||||
NULL, 0, NULL, 0, is_rela, 0);
|
||||
|
||||
found = 1;
|
||||
}
|
||||
|
@ -9879,6 +9916,181 @@ print_dynamic_symbol (bfd_vma si, unsigned long hn)
|
|||
putchar ('\n');
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_symbol_version_string (FILE *file, int is_dynsym,
|
||||
const char *strtab,
|
||||
unsigned long int strtab_size,
|
||||
unsigned int si, Elf_Internal_Sym *psym,
|
||||
enum versioned_symbol_info *sym_info,
|
||||
unsigned short *vna_other)
|
||||
{
|
||||
const char *version_string = NULL;
|
||||
|
||||
if (is_dynsym
|
||||
&& version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
|
||||
{
|
||||
unsigned char data[2];
|
||||
unsigned short vers_data;
|
||||
unsigned long offset;
|
||||
int is_nobits;
|
||||
int check_def;
|
||||
|
||||
offset = offset_from_vma
|
||||
(file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
|
||||
sizeof data + si * sizeof (vers_data));
|
||||
|
||||
if (get_data (&data, file, offset + si * sizeof (vers_data),
|
||||
sizeof (data), 1, _("version data")) == NULL)
|
||||
return NULL;
|
||||
|
||||
vers_data = byte_get (data, 2);
|
||||
|
||||
is_nobits = (psym->st_shndx < elf_header.e_shnum
|
||||
&& section_headers[psym->st_shndx].sh_type
|
||||
== SHT_NOBITS);
|
||||
|
||||
check_def = (psym->st_shndx != SHN_UNDEF);
|
||||
|
||||
if ((vers_data & VERSYM_HIDDEN) || vers_data > 1)
|
||||
{
|
||||
if (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
|
||||
&& (is_nobits || ! check_def))
|
||||
{
|
||||
Elf_External_Verneed evn;
|
||||
Elf_Internal_Verneed ivn;
|
||||
Elf_Internal_Vernaux ivna;
|
||||
|
||||
/* We must test both. */
|
||||
offset = offset_from_vma
|
||||
(file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
|
||||
sizeof evn);
|
||||
|
||||
do
|
||||
{
|
||||
unsigned long vna_off;
|
||||
|
||||
if (get_data (&evn, file, offset, sizeof (evn), 1,
|
||||
_("version need")) == NULL)
|
||||
{
|
||||
ivna.vna_next = 0;
|
||||
ivna.vna_other = 0;
|
||||
ivna.vna_name = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ivn.vn_aux = BYTE_GET (evn.vn_aux);
|
||||
ivn.vn_next = BYTE_GET (evn.vn_next);
|
||||
|
||||
vna_off = offset + ivn.vn_aux;
|
||||
|
||||
do
|
||||
{
|
||||
Elf_External_Vernaux evna;
|
||||
|
||||
if (get_data (&evna, file, vna_off,
|
||||
sizeof (evna), 1,
|
||||
_("version need aux (3)")) == NULL)
|
||||
{
|
||||
ivna.vna_next = 0;
|
||||
ivna.vna_other = 0;
|
||||
ivna.vna_name = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ivna.vna_other = BYTE_GET (evna.vna_other);
|
||||
ivna.vna_next = BYTE_GET (evna.vna_next);
|
||||
ivna.vna_name = BYTE_GET (evna.vna_name);
|
||||
}
|
||||
|
||||
vna_off += ivna.vna_next;
|
||||
}
|
||||
while (ivna.vna_other != vers_data
|
||||
&& ivna.vna_next != 0);
|
||||
|
||||
if (ivna.vna_other == vers_data)
|
||||
break;
|
||||
|
||||
offset += ivn.vn_next;
|
||||
}
|
||||
while (ivn.vn_next != 0);
|
||||
|
||||
if (ivna.vna_other == vers_data)
|
||||
{
|
||||
*sym_info = symbol_undefined;
|
||||
*vna_other = ivna.vna_other;
|
||||
version_string = (ivna.vna_name < strtab_size
|
||||
? strtab + ivna.vna_name
|
||||
: _("<corrupt>"));
|
||||
check_def = 0;
|
||||
}
|
||||
else if (! is_nobits)
|
||||
error (_("bad dynamic symbol\n"));
|
||||
else
|
||||
check_def = 1;
|
||||
}
|
||||
|
||||
if (check_def)
|
||||
{
|
||||
if (vers_data != 0x8001
|
||||
&& version_info[DT_VERSIONTAGIDX (DT_VERDEF)])
|
||||
{
|
||||
Elf_Internal_Verdef ivd;
|
||||
Elf_Internal_Verdaux ivda;
|
||||
Elf_External_Verdaux evda;
|
||||
unsigned long off;
|
||||
|
||||
off = offset_from_vma
|
||||
(file,
|
||||
version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
|
||||
sizeof (Elf_External_Verdef));
|
||||
|
||||
do
|
||||
{
|
||||
Elf_External_Verdef evd;
|
||||
|
||||
if (get_data (&evd, file, off, sizeof (evd),
|
||||
1, _("version def")) == NULL)
|
||||
{
|
||||
ivd.vd_ndx = 0;
|
||||
ivd.vd_aux = 0;
|
||||
ivd.vd_next = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
|
||||
ivd.vd_aux = BYTE_GET (evd.vd_aux);
|
||||
ivd.vd_next = BYTE_GET (evd.vd_next);
|
||||
}
|
||||
|
||||
off += ivd.vd_next;
|
||||
}
|
||||
while (ivd.vd_ndx != (vers_data & VERSYM_VERSION)
|
||||
&& ivd.vd_next != 0);
|
||||
|
||||
off -= ivd.vd_next;
|
||||
off += ivd.vd_aux;
|
||||
|
||||
if (get_data (&evda, file, off, sizeof (evda),
|
||||
1, _("version def aux")) == NULL)
|
||||
return version_string;
|
||||
|
||||
ivda.vda_name = BYTE_GET (evda.vda_name);
|
||||
|
||||
if (psym->st_name != ivda.vda_name)
|
||||
{
|
||||
*sym_info = ((vers_data & VERSYM_HIDDEN) != 0
|
||||
? symbol_hidden : symbol_public);
|
||||
version_string = (ivda.vda_name < strtab_size
|
||||
? strtab + ivda.vda_name
|
||||
: _("<corrupt>"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return version_string;
|
||||
}
|
||||
|
||||
/* Dump the symbol table. */
|
||||
static int
|
||||
process_symbol_table (FILE * file)
|
||||
|
@ -10179,6 +10391,10 @@ process_symbol_table (FILE * file)
|
|||
|
||||
for (si = 0, psym = symtab; si < num_syms; si++, psym++)
|
||||
{
|
||||
const char *version_string;
|
||||
enum versioned_symbol_info sym_info;
|
||||
unsigned short vna_other;
|
||||
|
||||
printf ("%6d: ", si);
|
||||
print_vma (psym->st_value, LONG_HEX);
|
||||
putchar (' ');
|
||||
|
@ -10195,163 +10411,18 @@ process_symbol_table (FILE * file)
|
|||
print_symbol (25, psym->st_name < strtab_size
|
||||
? strtab + psym->st_name : _("<corrupt>"));
|
||||
|
||||
if (section->sh_type == SHT_DYNSYM
|
||||
&& version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
|
||||
version_string
|
||||
= get_symbol_version_string (file,
|
||||
section->sh_type == SHT_DYNSYM,
|
||||
strtab, strtab_size, si,
|
||||
psym, &sym_info, &vna_other);
|
||||
if (version_string)
|
||||
{
|
||||
unsigned char data[2];
|
||||
unsigned short vers_data;
|
||||
unsigned long offset;
|
||||
int is_nobits;
|
||||
int check_def;
|
||||
|
||||
offset = offset_from_vma
|
||||
(file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
|
||||
sizeof data + si * sizeof (vers_data));
|
||||
|
||||
if (get_data (&data, file, offset + si * sizeof (vers_data),
|
||||
sizeof (data), 1, _("version data")) == NULL)
|
||||
break;
|
||||
|
||||
vers_data = byte_get (data, 2);
|
||||
|
||||
is_nobits = (psym->st_shndx < elf_header.e_shnum
|
||||
&& section_headers[psym->st_shndx].sh_type
|
||||
== SHT_NOBITS);
|
||||
|
||||
check_def = (psym->st_shndx != SHN_UNDEF);
|
||||
|
||||
if ((vers_data & VERSYM_HIDDEN) || vers_data > 1)
|
||||
{
|
||||
if (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
|
||||
&& (is_nobits || ! check_def))
|
||||
{
|
||||
Elf_External_Verneed evn;
|
||||
Elf_Internal_Verneed ivn;
|
||||
Elf_Internal_Vernaux ivna;
|
||||
|
||||
/* We must test both. */
|
||||
offset = offset_from_vma
|
||||
(file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
|
||||
sizeof evn);
|
||||
|
||||
do
|
||||
{
|
||||
unsigned long vna_off;
|
||||
|
||||
if (get_data (&evn, file, offset, sizeof (evn), 1,
|
||||
_("version need")) == NULL)
|
||||
{
|
||||
ivna.vna_next = 0;
|
||||
ivna.vna_other = 0;
|
||||
ivna.vna_name = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ivn.vn_aux = BYTE_GET (evn.vn_aux);
|
||||
ivn.vn_next = BYTE_GET (evn.vn_next);
|
||||
|
||||
vna_off = offset + ivn.vn_aux;
|
||||
|
||||
do
|
||||
{
|
||||
Elf_External_Vernaux evna;
|
||||
|
||||
if (get_data (&evna, file, vna_off,
|
||||
sizeof (evna), 1,
|
||||
_("version need aux (3)")) == NULL)
|
||||
{
|
||||
ivna.vna_next = 0;
|
||||
ivna.vna_other = 0;
|
||||
ivna.vna_name = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ivna.vna_other = BYTE_GET (evna.vna_other);
|
||||
ivna.vna_next = BYTE_GET (evna.vna_next);
|
||||
ivna.vna_name = BYTE_GET (evna.vna_name);
|
||||
}
|
||||
|
||||
vna_off += ivna.vna_next;
|
||||
}
|
||||
while (ivna.vna_other != vers_data
|
||||
&& ivna.vna_next != 0);
|
||||
|
||||
if (ivna.vna_other == vers_data)
|
||||
break;
|
||||
|
||||
offset += ivn.vn_next;
|
||||
}
|
||||
while (ivn.vn_next != 0);
|
||||
|
||||
if (ivna.vna_other == vers_data)
|
||||
{
|
||||
printf ("@%s (%d)",
|
||||
ivna.vna_name < strtab_size
|
||||
? strtab + ivna.vna_name : _("<corrupt>"),
|
||||
ivna.vna_other);
|
||||
check_def = 0;
|
||||
}
|
||||
else if (! is_nobits)
|
||||
error (_("bad dynamic symbol\n"));
|
||||
else
|
||||
check_def = 1;
|
||||
}
|
||||
|
||||
if (check_def)
|
||||
{
|
||||
if (vers_data != 0x8001
|
||||
&& version_info[DT_VERSIONTAGIDX (DT_VERDEF)])
|
||||
{
|
||||
Elf_Internal_Verdef ivd;
|
||||
Elf_Internal_Verdaux ivda;
|
||||
Elf_External_Verdaux evda;
|
||||
unsigned long off;
|
||||
|
||||
off = offset_from_vma
|
||||
(file,
|
||||
version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
|
||||
sizeof (Elf_External_Verdef));
|
||||
|
||||
do
|
||||
{
|
||||
Elf_External_Verdef evd;
|
||||
|
||||
if (get_data (&evd, file, off, sizeof (evd),
|
||||
1, _("version def")) == NULL)
|
||||
{
|
||||
ivd.vd_ndx = 0;
|
||||
ivd.vd_aux = 0;
|
||||
ivd.vd_next = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
|
||||
ivd.vd_aux = BYTE_GET (evd.vd_aux);
|
||||
ivd.vd_next = BYTE_GET (evd.vd_next);
|
||||
}
|
||||
|
||||
off += ivd.vd_next;
|
||||
}
|
||||
while (ivd.vd_ndx != (vers_data & VERSYM_VERSION)
|
||||
&& ivd.vd_next != 0);
|
||||
|
||||
off -= ivd.vd_next;
|
||||
off += ivd.vd_aux;
|
||||
|
||||
if (get_data (&evda, file, off, sizeof (evda),
|
||||
1, _("version def aux")) == NULL)
|
||||
break;
|
||||
|
||||
ivda.vda_name = BYTE_GET (evda.vda_name);
|
||||
|
||||
if (psym->st_name != ivda.vda_name)
|
||||
printf ((vers_data & VERSYM_HIDDEN)
|
||||
? "@%s" : "@@%s",
|
||||
ivda.vda_name < strtab_size
|
||||
? strtab + ivda.vda_name : _("<corrupt>"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sym_info == symbol_undefined)
|
||||
printf ("@%s (%d)", version_string, vna_other);
|
||||
else
|
||||
printf (sym_info == symbol_hidden ? "@%s" : "@@%s",
|
||||
version_string);
|
||||
}
|
||||
|
||||
putchar ('\n');
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
2014-11-25 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR binutils/16496
|
||||
* ld-cris/weakref3.d: Add symbol version string to versioned
|
||||
symbol names in dynamic relocation.
|
||||
* ld-cris/weakref4.d: Likewise.
|
||||
* ld-elfvers/vers24.rd: Likewise.
|
||||
|
||||
* ld-elf/pr16496a.c: New file.
|
||||
* ld-elf/pr16496a.map: Likewise.
|
||||
* ld-elf/pr16496b.c: Likewise.
|
||||
* ld-elf/pr16496b.od: Likewise.
|
||||
|
||||
* ld-elf/shared.exp (build_tests): Add libpr16496a.so and
|
||||
libpr16496b.so tests.
|
||||
|
||||
2014-11-25 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* ld-i386/i386.exp: Add run-time relocation tests for plt-main.
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
#...
|
||||
Relocation section '.rela.dyn' at offset 0x... contains 1 entries:
|
||||
Offset +Info +Type +Sym.Value +Sym. Name \+ Addend
|
||||
.* R_CRIS_COPY .* __expobj2 \+ 0
|
||||
.* R_CRIS_COPY .* __expobj2@TST3 \+ 0
|
||||
|
||||
Relocation section '.rela.plt' at offset 0x... contains 1 entries:
|
||||
Offset +Info +Type +Sym.Value +Sym. Name \+ Addend
|
||||
.* R_CRIS_JUMP_SLOT .* expfn2 \+ 0
|
||||
.* R_CRIS_JUMP_SLOT .* expfn2@TST3 \+ 0
|
||||
|
||||
The decoding of unwind sections for machine type Axis Communications 32-bit embedded processor is not currently supported.
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#...
|
||||
Relocation section '.rela.dyn' at offset 0x... contains 1 entries:
|
||||
#...
|
||||
.* R_CRIS_COPY .* __expobj2 \+ 0
|
||||
.* R_CRIS_COPY .* __expobj2@TST3 \+ 0
|
||||
|
||||
The decoding of unwind sections for machine type Axis Communications 32-bit embedded processor is not currently supported.
|
||||
|
||||
|
|
4
ld/testsuite/ld-elf/pr16496a.c
Normal file
4
ld/testsuite/ld-elf/pr16496a.c
Normal file
|
@ -0,0 +1,4 @@
|
|||
void
|
||||
sd_get_seats (void)
|
||||
{
|
||||
}
|
4
ld/testsuite/ld-elf/pr16496a.map
Normal file
4
ld/testsuite/ld-elf/pr16496a.map
Normal file
|
@ -0,0 +1,4 @@
|
|||
LIBSYSTEMD_209 {
|
||||
global:
|
||||
sd_get_seats;
|
||||
};
|
5
ld/testsuite/ld-elf/pr16496b.c
Normal file
5
ld/testsuite/ld-elf/pr16496b.c
Normal file
|
@ -0,0 +1,5 @@
|
|||
void sd_get_seats (void);
|
||||
void call_sd_get_seats (void)
|
||||
{
|
||||
sd_get_seats ();
|
||||
}
|
3
ld/testsuite/ld-elf/pr16496b.od
Normal file
3
ld/testsuite/ld-elf/pr16496b.od
Normal file
|
@ -0,0 +1,3 @@
|
|||
#...
|
||||
.* sd_get_seats@LIBSYSTEMD_209
|
||||
#pass
|
|
@ -246,6 +246,15 @@ set build_tests {
|
|||
{"Build dynamic-1"
|
||||
"-Wl,--dynamic-list,dynamic-1.syms -Wl,--gc-sections" "-ffunction-sections"
|
||||
{dynamic-1.c} {{readelf {-s} dynamic-1.rd}} "dynamic-1"}
|
||||
{"Build libpr16496a.so"
|
||||
"-shared -Wl,--version-script=pr16496a.map" "-fPIC"
|
||||
{pr16496a.c} {} "libpr16496a.so"}
|
||||
{"Build libpr16496b.a"
|
||||
"" "-fPIC"
|
||||
{pr16496b.c} {} "libpr16496b.a"}
|
||||
{"Build libpr16496b.so"
|
||||
"-shared tmpdir/pr16496b.o tmpdir/libpr16496a.so" ""
|
||||
{dummy.c} {{objdump {-R} pr16496b.od}} "libpr16496b.so"}
|
||||
}
|
||||
|
||||
run_cc_link_tests $build_tests
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Relocation section .*
|
||||
# Ensure there is a dynamic relocation against x
|
||||
#...
|
||||
[0-9a-f]+ +[0-9a-f]+ R_.* +_?x(| \+ 0)
|
||||
[0-9a-f]+ +[0-9a-f]+ R_.* +_?x@VERS.0(| \+ 0)
|
||||
#...
|
||||
Symbol table '.dynsym' contains [0-9]+ entries:
|
||||
# And ensure the dynamic symbol table contains at least x@VERS.0
|
||||
|
|
Loading…
Reference in a new issue