This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] PR binutils/16496: Display symbol version when dumping dynrelocs
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- Cc: Binutils <binutils at sourceware dot org>
- Date: Wed, 29 Jan 2014 21:33:53 -0800
- Subject: Re: [PATCH] PR binutils/16496: Display symbol version when dumping dynrelocs
- Authentication-results: sourceware.org; auth=none
- References: <20140124191614 dot GA20867 at intel dot com>
On Fri, Jan 24, 2014 at 11:16 AM, H.J. Lu <hongjiu.lu@intel.com> wrote:
>
> 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. OK for trunk?
>
> Thanks.
>
>
> H.J.
> --
> 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.
> ---
> bfd/ChangeLog | 8 +
> bfd/elf-bfd.h | 2 +
> bfd/elf.c | 92 +++++----
> binutils/ChangeLog | 17 ++
> binutils/objdump.c | 23 ++-
> binutils/readelf.c | 393 ++++++++++++++++++++++----------------
> ld/testsuite/ChangeLog | 16 ++
> ld/testsuite/ld-cris/weakref3.d | 4 +-
> ld/testsuite/ld-cris/weakref4.d | 2 +-
> ld/testsuite/ld-elf/pr16496a.c | 4 +
> ld/testsuite/ld-elf/pr16496a.map | 4 +
> ld/testsuite/ld-elf/pr16496b.c | 5 +
> ld/testsuite/ld-elf/pr16496b.od | 3 +
> ld/testsuite/ld-elf/shared.exp | 9 +
> ld/testsuite/ld-elfvers/vers24.rd | 2 +-
> 15 files changed, 378 insertions(+), 206 deletions(-)
> create mode 100644 ld/testsuite/ld-elf/pr16496a.c
> create mode 100644 ld/testsuite/ld-elf/pr16496a.map
> create mode 100644 ld/testsuite/ld-elf/pr16496b.c
> create mode 100644 ld/testsuite/ld-elf/pr16496b.od
>
> diff --git a/bfd/ChangeLog b/bfd/ChangeLog
> index a5fcadf..75a81fe 100644
> --- a/bfd/ChangeLog
> +++ b/bfd/ChangeLog
> @@ -1,3 +1,11 @@
> +2014-01-24 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-01-24 Alan Modra <amodra@gmail.com>
>
> * elf64-ppc.c (ppc_build_one_stub): Correct reloc count passed
> diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
> index 0aab5fa..b9c55e7 100644
> --- a/bfd/elf-bfd.h
> +++ b/bfd/elf-bfd.h
> @@ -1767,6 +1767,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);
>
> diff --git a/bfd/elf.c b/bfd/elf.c
> index c0303fc..5783d88 100644
> --- a/bfd/elf.c
> +++ b/bfd/elf.c
> @@ -1396,6 +1396,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
> @@ -1422,6 +1469,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*)";
>
> @@ -1447,45 +1496,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
> {
> diff --git a/binutils/ChangeLog b/binutils/ChangeLog
> index 6f107e1..6545d62 100644
> --- a/binutils/ChangeLog
> +++ b/binutils/ChangeLog
> @@ -1,3 +1,20 @@
> +2014-01-24 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-01-08 H.J. Lu <hongjiu.lu@intel.com>
>
> * version.c (print_version): Update copyright year to 2014.
> diff --git a/binutils/objdump.c b/binutils/objdump.c
> index 0098ae7..af7bfce 100644
> --- a/binutils/objdump.c
> +++ b/binutils/objdump.c
> @@ -792,7 +792,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);
> @@ -804,10 +805,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);
> diff --git a/binutils/readelf.c b/binutils/readelf.c
> index 7d228d6..669cda7 100644
> --- a/binutils/readelf.c
> +++ b/binutils/readelf.c
> @@ -271,6 +271,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) \
> @@ -926,7 +940,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;
> @@ -1360,9 +1375,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)
> @@ -1389,6 +1415,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
> @@ -1446,7 +1475,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)
> {
> @@ -5920,7 +5954,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);
> }
> }
>
> @@ -5995,14 +6030,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;
> }
> @@ -9581,6 +9618,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)
> @@ -9877,6 +10089,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 (' ');
> @@ -9893,163 +10109,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');
> diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
> index 39cc0fb..e104817 100644
> --- a/ld/testsuite/ChangeLog
> +++ b/ld/testsuite/ChangeLog
> @@ -1,5 +1,21 @@
> 2014-01-24 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-01-24 H.J. Lu <hongjiu.lu@intel.com>
> +
> * ld-elf/pr16498a.s: Replace .align with .p2align.
>
> 2014-01-24 H.J. Lu <hongjiu.lu@intel.com>
> diff --git a/ld/testsuite/ld-cris/weakref3.d b/ld/testsuite/ld-cris/weakref3.d
> index aea3ad6..4807106 100644
> --- a/ld/testsuite/ld-cris/weakref3.d
> +++ b/ld/testsuite/ld-cris/weakref3.d
> @@ -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.
>
> diff --git a/ld/testsuite/ld-cris/weakref4.d b/ld/testsuite/ld-cris/weakref4.d
> index 79de291..aed0f39 100644
> --- a/ld/testsuite/ld-cris/weakref4.d
> +++ b/ld/testsuite/ld-cris/weakref4.d
> @@ -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.
>
> diff --git a/ld/testsuite/ld-elf/pr16496a.c b/ld/testsuite/ld-elf/pr16496a.c
> new file mode 100644
> index 0000000..35e8555
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pr16496a.c
> @@ -0,0 +1,4 @@
> +void
> +sd_get_seats (void)
> +{
> +}
> diff --git a/ld/testsuite/ld-elf/pr16496a.map b/ld/testsuite/ld-elf/pr16496a.map
> new file mode 100644
> index 0000000..d677f37
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pr16496a.map
> @@ -0,0 +1,4 @@
> +LIBSYSTEMD_209 {
> +global:
> + sd_get_seats;
> +};
> diff --git a/ld/testsuite/ld-elf/pr16496b.c b/ld/testsuite/ld-elf/pr16496b.c
> new file mode 100644
> index 0000000..94a0f30
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pr16496b.c
> @@ -0,0 +1,5 @@
> +void sd_get_seats (void);
> +void call_sd_get_seats (void)
> +{
> + sd_get_seats ();
> +}
> diff --git a/ld/testsuite/ld-elf/pr16496b.od b/ld/testsuite/ld-elf/pr16496b.od
> new file mode 100644
> index 0000000..6fb54c1
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pr16496b.od
> @@ -0,0 +1,3 @@
> +#...
> +.* sd_get_seats@LIBSYSTEMD_209
> +#pass
> diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
> index bbfd464..da5f8e4 100644
> --- a/ld/testsuite/ld-elf/shared.exp
> +++ b/ld/testsuite/ld-elf/shared.exp
> @@ -224,6 +224,15 @@ set build_tests {
> {"Build libpr2404b.a"
> "" ""
> {pr2404b.c} {} "libpr2404b.a"}
> + {"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
> diff --git a/ld/testsuite/ld-elfvers/vers24.rd b/ld/testsuite/ld-elfvers/vers24.rd
> index fb464f9..2360447 100644
> --- a/ld/testsuite/ld-elfvers/vers24.rd
> +++ b/ld/testsuite/ld-elfvers/vers24.rd
> @@ -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
> --
> 1.8.4.2
>
Does anyone have comments on this?
--
H.J.