* [PATCH] readelf: Compute dynamic symbol table size from hash table
@ 2020-03-12 13:23 H.J. Lu
2020-03-19 12:51 ` [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms table H.J. Lu
0 siblings, 1 reply; 11+ messages in thread
From: H.J. Lu @ 2020-03-12 13:23 UTC (permalink / raw)
To: binutils
When reconstructing dynamic symbol table from the PT_DYNAMIC segment,
compute dynamic symbol table size from hash table. For DT_HASH, the
number of dynamic symbol table entries equals the number of chains.
For DT_GNU_HASH/DT_MIPS_XHASH, only defined symbols with non-STB_LOCAL
indings are in hash table. Since DT_GNU_HASH/DT_MIPS_XHASH place all
symbols with STB_LOCAL binding before symbols with other bindings and
all undefined symbols defined ones in dynamic symbol table, the highest
symbol index in DT_GNU_HASH/DT_MIPS_XHASH is the highest dynamic symbol
table index.
Also iterate dynamic symbol table to print each entry so that output
of "readelf -D -s" without section header is similar to "readelf -s"
with section header.
`
binutils/
* readelf.c (nbuckets): New.
(nchains): Likewise.
(buckets): Likewise.
(chains): Likewise.
(ngnubuckets): Likewise.
(gnubuckets): Likewise.
(gnuchains): Likewise.
(mipsxlat): Likewise.
(ngnuchains): Likewise.
(gnusymidx): Likewise.
(get_dynamic_data): Moved before process_dynamic_section.
(get_num_dynamic_syms): New function.
(process_dynamic_section): Use DT_SYMTAB, DT_SYMENT, DT_HASH,
DT_GNU_HASH and DT_MIPS_XHASH to reconstruct dynamic symbol
table. Use DT_STRTAB and DT_STRSZ to reconstruct dynamic string
table.
(get_symbol_index_type): Don't print "bad section index" when
there is no section header.
(print_dynamic_symbol): Don't print bucket number.
(process_symbol_table): Simplify dumping dynamic symbol table
from DT_HASH and DT_GNU_HASH.
ld/
* testsuite/ld-elf/hash.d: Updated.
* testsuite/ld-elf/pr13195.d: Likewise.
* testsuite/ld-elfvsb/hidden2.d: Likewise.
* testsuite/ld-mips-elf/hash2.d: Likewise.
---
binutils/readelf.c | 831 ++++++++++++++++---------------
ld/testsuite/ld-elf/hash.d | 8 +-
ld/testsuite/ld-elf/pr13195.d | 2 +-
ld/testsuite/ld-elfvsb/hidden2.d | 2 +-
ld/testsuite/ld-mips-elf/hash2.d | 8 +-
5 files changed, 440 insertions(+), 411 deletions(-)
diff --git a/binutils/readelf.c b/binutils/readelf.c
index d009b91920..a009b7f5ee 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -226,6 +226,16 @@ static size_t dynamic_nent;
static char * dynamic_strings;
static unsigned long dynamic_strings_length;
static unsigned long num_dynamic_syms;
+static bfd_size_type nbuckets;
+static bfd_size_type nchains;
+static bfd_vma *buckets;
+static bfd_vma *chains;
+static bfd_vma ngnubuckets;
+static bfd_vma *gnubuckets;
+static bfd_vma *gnuchains;
+static bfd_vma *mipsxlat;
+static bfd_size_type ngnuchains;
+static bfd_vma gnusymidx;
static Elf_Internal_Sym * dynamic_symbols;
static Elf_Internal_Syminfo * dynamic_syminfo;
static unsigned long dynamic_syminfo_offset;
@@ -9846,6 +9856,320 @@ print_dynamic_flags (bfd_vma flags)
puts ("");
}
+static bfd_vma *
+get_dynamic_data (Filedata * filedata, bfd_size_type number, unsigned int ent_size)
+{
+ unsigned char * e_data;
+ bfd_vma * i_data;
+
+ /* If the size_t type is smaller than the bfd_size_type, eg because
+ you are building a 32-bit tool on a 64-bit host, then make sure
+ that when (number) is cast to (size_t) no information is lost. */
+ if (sizeof (size_t) < sizeof (bfd_size_type)
+ && (bfd_size_type) ((size_t) number) != number)
+ {
+ error (_("Size truncation prevents reading %s elements of size %u\n"),
+ bfd_vmatoa ("u", number), ent_size);
+ return NULL;
+ }
+
+ /* Be kind to memory checkers (eg valgrind, address sanitizer) by not
+ attempting to allocate memory when the read is bound to fail. */
+ if (ent_size * number > filedata->file_size)
+ {
+ error (_("Invalid number of dynamic entries: %s\n"),
+ bfd_vmatoa ("u", number));
+ return NULL;
+ }
+
+ e_data = (unsigned char *) cmalloc ((size_t) number, ent_size);
+ if (e_data == NULL)
+ {
+ error (_("Out of memory reading %s dynamic entries\n"),
+ bfd_vmatoa ("u", number));
+ return NULL;
+ }
+
+ if (fread (e_data, ent_size, (size_t) number, filedata->handle) != number)
+ {
+ error (_("Unable to read in %s bytes of dynamic data\n"),
+ bfd_vmatoa ("u", number * ent_size));
+ free (e_data);
+ return NULL;
+ }
+
+ i_data = (bfd_vma *) cmalloc ((size_t) number, sizeof (*i_data));
+ if (i_data == NULL)
+ {
+ error (_("Out of memory allocating space for %s dynamic entries\n"),
+ bfd_vmatoa ("u", number));
+ free (e_data);
+ return NULL;
+ }
+
+ while (number--)
+ i_data[number] = byte_get (e_data + number * ent_size, ent_size);
+
+ free (e_data);
+
+ return i_data;
+}
+
+static unsigned long
+get_num_dynamic_syms (Filedata * filedata)
+{
+ unsigned long num_of_syms = 0;
+
+ if (!do_histogram && (!do_using_dynamic || do_dyn_syms))
+ return num_of_syms;
+
+ if (dynamic_info[DT_HASH])
+ {
+ unsigned char nb[8];
+ unsigned char nc[8];
+ unsigned int hash_ent_size = 4;
+
+ if ((filedata->file_header.e_machine == EM_ALPHA
+ || filedata->file_header.e_machine == EM_S390
+ || filedata->file_header.e_machine == EM_S390_OLD)
+ && filedata->file_header.e_ident[EI_CLASS] == ELFCLASS64)
+ hash_ent_size = 8;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, dynamic_info[DT_HASH],
+ sizeof nb + sizeof nc)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ goto no_hash;
+ }
+
+ if (fread (nb, hash_ent_size, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to read in number of buckets\n"));
+ goto no_hash;
+ }
+
+ if (fread (nc, hash_ent_size, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to read in number of chains\n"));
+ goto no_hash;
+ }
+
+ nbuckets = byte_get (nb, hash_ent_size);
+ nchains = byte_get (nc, hash_ent_size);
+ num_of_syms = nchains;
+
+ buckets = get_dynamic_data (filedata, nbuckets, hash_ent_size);
+ chains = get_dynamic_data (filedata, nchains, hash_ent_size);
+
+ no_hash:
+ if (num_of_syms == 0)
+ {
+ if (buckets)
+ {
+ free (buckets);
+ buckets = NULL;
+ }
+ if (chains)
+ {
+ free (chains);
+ buckets = NULL;
+ }
+ nbuckets = 0;
+ }
+ }
+
+ if (dynamic_info_DT_GNU_HASH)
+ {
+ unsigned char nb[16];
+ bfd_vma i, maxchain = 0xffffffff, bitmaskwords;
+ bfd_vma buckets_vma;
+ unsigned long hn;
+ bfd_boolean gnu_hash_error = FALSE;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, dynamic_info_DT_GNU_HASH,
+ sizeof nb)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ if (fread (nb, 16, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to read in number of buckets\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ ngnubuckets = byte_get (nb, 4);
+ gnusymidx = byte_get (nb + 4, 4);
+ bitmaskwords = byte_get (nb + 8, 4);
+ buckets_vma = dynamic_info_DT_GNU_HASH + 16;
+ if (is_32bit_elf)
+ buckets_vma += bitmaskwords * 4;
+ else
+ buckets_vma += bitmaskwords * 8;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, buckets_vma, 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ gnubuckets = get_dynamic_data (filedata, ngnubuckets, 4);
+
+ if (gnubuckets == NULL)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ for (i = 0; i < ngnubuckets; i++)
+ if (gnubuckets[i] != 0)
+ {
+ if (gnubuckets[i] < gnusymidx)
+ {
+ gnu_hash_error = TRUE;
+ return FALSE;
+ }
+
+ if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
+ maxchain = gnubuckets[i];
+ }
+
+ if (maxchain == 0xffffffff)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ maxchain -= gnusymidx;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, buckets_vma
+ + 4 * (ngnubuckets + maxchain), 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ do
+ {
+ if (fread (nb, 4, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to determine last chain length\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ if (maxchain + 1 == 0)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ ++maxchain;
+ }
+ while ((byte_get (nb, 4) & 1) == 0);
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, buckets_vma + 4 * ngnubuckets, 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ gnuchains = get_dynamic_data (filedata, maxchain, 4);
+ ngnuchains = maxchain;
+
+ if (gnuchains == NULL)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ if (dynamic_info_DT_MIPS_XHASH)
+ {
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, (buckets_vma
+ + 4 * (ngnubuckets
+ + maxchain)), 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ mipsxlat = get_dynamic_data (filedata, maxchain, 4);
+ }
+
+ for (hn = 0; hn < ngnubuckets; ++hn)
+ if (gnubuckets[hn] != 0)
+ {
+ bfd_vma si = gnubuckets[hn];
+ bfd_vma off = si - gnusymidx;
+
+ do
+ {
+ if (dynamic_info_DT_MIPS_XHASH)
+ {
+ if (mipsxlat[off] >= num_of_syms)
+ num_of_syms = mipsxlat[off] + 1;
+ }
+ else
+ {
+ if (si >= num_of_syms)
+ num_of_syms = si + 1;
+ }
+ si++;
+ }
+ while (off < ngnuchains && (gnuchains[off++] & 1) == 0);
+ }
+
+ no_gnu_hash:
+ if (gnu_hash_error)
+ {
+ if (mipsxlat)
+ {
+ free (mipsxlat);
+ mipsxlat = NULL;
+ }
+ if (gnuchains)
+ {
+ free (gnuchains);
+ gnuchains = NULL;
+ }
+ if (gnubuckets)
+ {
+ free (gnubuckets);
+ gnubuckets = NULL;
+ }
+ ngnubuckets = 0;
+ ngnuchains = 0;
+ }
+ }
+
+ return num_of_syms;
+}
+
/* Parse and display the contents of the dynamic section. */
static bfd_boolean
@@ -9873,103 +10197,117 @@ process_dynamic_section (Filedata * filedata)
}
/* Find the appropriate symbol table. */
- if (dynamic_symbols == NULL)
+ if (dynamic_symbols == NULL || do_histogram)
{
for (entry = dynamic_section;
entry < dynamic_section + dynamic_nent;
++entry)
- {
- Elf_Internal_Shdr section;
-
- if (entry->d_tag != DT_SYMTAB)
- continue;
-
+ if (entry->d_tag == DT_SYMTAB)
dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
+ else if (entry->d_tag == DT_SYMENT)
+ dynamic_info[DT_SYMENT] = entry->d_un.d_val;
+ else if (entry->d_tag == DT_HASH)
+ dynamic_info[DT_HASH] = entry->d_un.d_val;
+ else if (entry->d_tag == DT_GNU_HASH)
+ dynamic_info_DT_GNU_HASH = entry->d_un.d_val;
+ else if ((filedata->file_header.e_machine == EM_MIPS
+ || filedata->file_header.e_machine == EM_MIPS_RS3_LE)
+ && entry->d_tag == DT_MIPS_XHASH)
+ {
+ dynamic_info_DT_MIPS_XHASH = entry->d_un.d_val;
+ dynamic_info_DT_GNU_HASH = entry->d_un.d_val;
+ }
- /* Since we do not know how big the symbol table is,
- we default to reading in the entire file (!) and
- processing that. This is overkill, I know, but it
- should work. */
- section.sh_offset = offset_from_vma (filedata, entry->d_un.d_val, 0);
- if ((bfd_size_type) section.sh_offset > filedata->file_size)
- {
- /* See PR 21379 for a reproducer. */
- error (_("Invalid DT_SYMTAB entry: %lx\n"),
- (long) section.sh_offset);
- return FALSE;
- }
+ if (dynamic_info[DT_SYMTAB] && dynamic_info[DT_SYMENT])
+ {
+ Elf_Internal_Phdr *seg;
+ bfd_vma vma = dynamic_info[DT_SYMTAB];
- if (archive_file_offset != 0)
- section.sh_size = archive_file_size - section.sh_offset;
- else
- section.sh_size = filedata->file_size - section.sh_offset;
+ if (! get_program_headers (filedata))
+ {
+ error (_("Cannot interpret virtual addresses without program headers.\n"));
+ return FALSE;
+ }
- if (is_32bit_elf)
- section.sh_entsize = sizeof (Elf32_External_Sym);
- else
- section.sh_entsize = sizeof (Elf64_External_Sym);
- section.sh_name = filedata->string_table_length;
+ for (seg = filedata->program_headers;
+ seg < filedata->program_headers + filedata->file_header.e_phnum;
+ ++seg)
+ {
+ if (seg->p_type != PT_LOAD)
+ continue;
- if (dynamic_symbols != NULL)
- {
- error (_("Multiple dynamic symbol table sections found\n"));
- free (dynamic_symbols);
- }
- dynamic_symbols = GET_ELF_SYMBOLS (filedata, §ion, & num_dynamic_syms);
- if (num_dynamic_syms < 1)
- {
- error (_("Unable to determine the number of symbols to load\n"));
- continue;
- }
- }
- }
+ if ((seg->p_offset + seg->p_filesz)
+ > filedata->file_size)
+ {
+ /* See PR 21379 for a reproducer. */
+ error (_("Invalid PT_LOAD entry\n"));
+ return FALSE;
+ }
+
+ if (vma >= (seg->p_vaddr & -seg->p_align)
+ && vma <= seg->p_vaddr + seg->p_filesz)
+ {
+ /* Since we do not know how big the symbol table is,
+ we default to reading in up to the end of PT_LOAD
+ segment and processing that. This is overkill, I
+ know, but it should work. */
+ Elf_Internal_Shdr section;
+ unsigned long num_of_syms
+ = get_num_dynamic_syms (filedata);
+ section.sh_offset = (vma - seg->p_vaddr
+ + seg->p_offset);
+ section.sh_size = (num_of_syms
+ * dynamic_info[DT_SYMENT]);
+ section.sh_entsize = dynamic_info[DT_SYMENT];
+ section.sh_name = filedata->string_table_length;
+ dynamic_symbols = GET_ELF_SYMBOLS (filedata,
+ §ion,
+ & num_dynamic_syms);
+ if (dynamic_symbols == NULL
+ || num_of_syms == 0
+ || num_dynamic_syms != num_of_syms)
+ {
+ error (_("Corrupt DT_SYMTAB dynamic entry\n"));
+ return FALSE;
+ }
+ }
+ }
+ }
+ }
/* Similarly find a string table. */
if (dynamic_strings == NULL)
- {
- for (entry = dynamic_section;
- entry < dynamic_section + dynamic_nent;
- ++entry)
- {
- unsigned long offset;
- long str_tab_len;
-
- if (entry->d_tag != DT_STRTAB)
- continue;
-
+ for (entry = dynamic_section;
+ entry < dynamic_section + dynamic_nent;
+ ++entry)
+ {
+ if (entry->d_tag == DT_STRTAB)
dynamic_info[DT_STRTAB] = entry->d_un.d_val;
- /* Since we do not know how big the string table is,
- we default to reading in the entire file (!) and
- processing that. This is overkill, I know, but it
- should work. */
-
- offset = offset_from_vma (filedata, entry->d_un.d_val, 0);
-
- if (archive_file_offset != 0)
- str_tab_len = archive_file_size - offset;
- else
- str_tab_len = filedata->file_size - offset;
-
- if (str_tab_len < 1)
- {
- error
- (_("Unable to determine the length of the dynamic string table\n"));
- continue;
- }
+ if (entry->d_tag == DT_STRSZ)
+ dynamic_info[DT_STRSZ] = entry->d_un.d_val;
- if (dynamic_strings != NULL)
- {
- error (_("Multiple dynamic string tables found\n"));
- free (dynamic_strings);
- }
+ if (dynamic_info[DT_STRTAB] && dynamic_info[DT_STRSZ])
+ {
+ unsigned long offset;
+ bfd_size_type str_tab_len = dynamic_info[DT_STRSZ];
+
+ offset = offset_from_vma (filedata,
+ dynamic_info[DT_STRTAB],
+ str_tab_len);
+ dynamic_strings = (char *) get_data (NULL, filedata, offset, 1,
+ str_tab_len,
+ _("dynamic string table"));
+ if (dynamic_strings == NULL)
+ {
+ error (_("Corrupt DT_STRTAB dynamic entry\n"));
+ break;
+ }
- dynamic_strings = (char *) get_data (NULL, filedata, offset, 1,
- str_tab_len,
- _("dynamic string table"));
- dynamic_strings_length = dynamic_strings == NULL ? 0 : str_tab_len;
- }
- }
+ dynamic_strings_length = str_tab_len;
+ break;
+ }
+ }
/* And find the syminfo section if available. */
if (dynamic_syminfo == NULL)
@@ -11412,7 +11750,8 @@ get_symbol_index_type (Filedata * filedata, unsigned int type)
sprintf (buff, "OS [0x%04x]", type & 0xffff);
else if (type >= SHN_LORESERVE)
sprintf (buff, "RSV[0x%04x]", type & 0xffff);
- else if (type >= filedata->file_header.e_shnum)
+ else if (filedata->file_header.e_shnum != 0
+ && type >= filedata->file_header.e_shnum)
sprintf (buff, _("bad section index[%3d]"), type);
else
sprintf (buff, "%3d", type);
@@ -11422,67 +11761,8 @@ get_symbol_index_type (Filedata * filedata, unsigned int type)
return buff;
}
-static bfd_vma *
-get_dynamic_data (Filedata * filedata, bfd_size_type number, unsigned int ent_size)
-{
- unsigned char * e_data;
- bfd_vma * i_data;
-
- /* If the size_t type is smaller than the bfd_size_type, eg because
- you are building a 32-bit tool on a 64-bit host, then make sure
- that when (number) is cast to (size_t) no information is lost. */
- if (sizeof (size_t) < sizeof (bfd_size_type)
- && (bfd_size_type) ((size_t) number) != number)
- {
- error (_("Size truncation prevents reading %s elements of size %u\n"),
- bfd_vmatoa ("u", number), ent_size);
- return NULL;
- }
-
- /* Be kind to memory checkers (eg valgrind, address sanitizer) by not
- attempting to allocate memory when the read is bound to fail. */
- if (ent_size * number > filedata->file_size)
- {
- error (_("Invalid number of dynamic entries: %s\n"),
- bfd_vmatoa ("u", number));
- return NULL;
- }
-
- e_data = (unsigned char *) cmalloc ((size_t) number, ent_size);
- if (e_data == NULL)
- {
- error (_("Out of memory reading %s dynamic entries\n"),
- bfd_vmatoa ("u", number));
- return NULL;
- }
-
- if (fread (e_data, ent_size, (size_t) number, filedata->handle) != number)
- {
- error (_("Unable to read in %s bytes of dynamic data\n"),
- bfd_vmatoa ("u", number * ent_size));
- free (e_data);
- return NULL;
- }
-
- i_data = (bfd_vma *) cmalloc ((size_t) number, sizeof (*i_data));
- if (i_data == NULL)
- {
- error (_("Out of memory allocating space for %s dynamic entries\n"),
- bfd_vmatoa ("u", number));
- free (e_data);
- return NULL;
- }
-
- while (number--)
- i_data[number] = byte_get (e_data + number * ent_size, ent_size);
-
- free (e_data);
-
- return i_data;
-}
-
static void
-print_dynamic_symbol (Filedata * filedata, bfd_vma si, unsigned long hn)
+print_dynamic_symbol (Filedata * filedata, bfd_vma si)
{
Elf_Internal_Sym * psym;
int n;
@@ -11490,7 +11770,7 @@ print_dynamic_symbol (Filedata * filedata, bfd_vma si, unsigned long hn)
n = print_vma (si, DEC_5);
if (n < 5)
fputs (&" "[n], stdout);
- printf (" %3lu: ", hn);
+ fputs (": ", stdout);
if (dynamic_symbols == NULL || si >= num_dynamic_syms)
{
@@ -11708,214 +11988,10 @@ static bfd_boolean
process_symbol_table (Filedata * filedata)
{
Elf_Internal_Shdr * section;
- bfd_size_type nbuckets = 0;
- bfd_size_type nchains = 0;
- bfd_vma * buckets = NULL;
- bfd_vma * chains = NULL;
- bfd_vma ngnubuckets = 0;
- bfd_vma * gnubuckets = NULL;
- bfd_vma * gnuchains = NULL;
- bfd_vma * mipsxlat = NULL;
- bfd_vma gnusymidx = 0;
- bfd_size_type ngnuchains = 0;
if (!do_syms && !do_dyn_syms && !do_histogram)
return TRUE;
- if (dynamic_info[DT_HASH]
- && (do_histogram
- || (do_using_dynamic
- && !do_dyn_syms
- && dynamic_strings != NULL)))
- {
- unsigned char nb[8];
- unsigned char nc[8];
- unsigned int hash_ent_size = 4;
-
- if ((filedata->file_header.e_machine == EM_ALPHA
- || filedata->file_header.e_machine == EM_S390
- || filedata->file_header.e_machine == EM_S390_OLD)
- && filedata->file_header.e_ident[EI_CLASS] == ELFCLASS64)
- hash_ent_size = 8;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, dynamic_info[DT_HASH],
- sizeof nb + sizeof nc)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_hash;
- }
-
- if (fread (nb, hash_ent_size, 1, filedata->handle) != 1)
- {
- error (_("Failed to read in number of buckets\n"));
- goto no_hash;
- }
-
- if (fread (nc, hash_ent_size, 1, filedata->handle) != 1)
- {
- error (_("Failed to read in number of chains\n"));
- goto no_hash;
- }
-
- nbuckets = byte_get (nb, hash_ent_size);
- nchains = byte_get (nc, hash_ent_size);
-
- buckets = get_dynamic_data (filedata, nbuckets, hash_ent_size);
- chains = get_dynamic_data (filedata, nchains, hash_ent_size);
-
- no_hash:
- if (buckets == NULL || chains == NULL)
- {
- if (do_using_dynamic)
- return FALSE;
- free (buckets);
- free (chains);
- buckets = NULL;
- chains = NULL;
- nbuckets = 0;
- nchains = 0;
- }
- }
-
- if (dynamic_info_DT_GNU_HASH
- && (do_histogram
- || (do_using_dynamic
- && !do_dyn_syms
- && dynamic_strings != NULL)))
- {
- unsigned char nb[16];
- bfd_vma i, maxchain = 0xffffffff, bitmaskwords;
- bfd_vma buckets_vma;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, dynamic_info_DT_GNU_HASH,
- sizeof nb)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- if (fread (nb, 16, 1, filedata->handle) != 1)
- {
- error (_("Failed to read in number of buckets\n"));
- goto no_gnu_hash;
- }
-
- ngnubuckets = byte_get (nb, 4);
- gnusymidx = byte_get (nb + 4, 4);
- bitmaskwords = byte_get (nb + 8, 4);
- buckets_vma = dynamic_info_DT_GNU_HASH + 16;
- if (is_32bit_elf)
- buckets_vma += bitmaskwords * 4;
- else
- buckets_vma += bitmaskwords * 8;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, buckets_vma, 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- gnubuckets = get_dynamic_data (filedata, ngnubuckets, 4);
-
- if (gnubuckets == NULL)
- goto no_gnu_hash;
-
- for (i = 0; i < ngnubuckets; i++)
- if (gnubuckets[i] != 0)
- {
- if (gnubuckets[i] < gnusymidx)
- return FALSE;
-
- if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
- maxchain = gnubuckets[i];
- }
-
- if (maxchain == 0xffffffff)
- goto no_gnu_hash;
-
- maxchain -= gnusymidx;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, buckets_vma
- + 4 * (ngnubuckets + maxchain), 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- do
- {
- if (fread (nb, 4, 1, filedata->handle) != 1)
- {
- error (_("Failed to determine last chain length\n"));
- goto no_gnu_hash;
- }
-
- if (maxchain + 1 == 0)
- goto no_gnu_hash;
-
- ++maxchain;
- }
- while ((byte_get (nb, 4) & 1) == 0);
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, buckets_vma + 4 * ngnubuckets, 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- gnuchains = get_dynamic_data (filedata, maxchain, 4);
- ngnuchains = maxchain;
-
- if (gnuchains == NULL)
- goto no_gnu_hash;
-
- if (dynamic_info_DT_MIPS_XHASH)
- {
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, (buckets_vma
- + 4 * (ngnubuckets
- + maxchain)), 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- mipsxlat = get_dynamic_data (filedata, maxchain, 4);
- }
-
- no_gnu_hash:
- if (dynamic_info_DT_MIPS_XHASH && mipsxlat == NULL)
- {
- free (gnuchains);
- gnuchains = NULL;
- }
- if (gnuchains == NULL)
- {
- free (gnubuckets);
- gnubuckets = NULL;
- ngnubuckets = 0;
- if (do_using_dynamic)
- return FALSE;
- }
- }
-
if ((dynamic_info[DT_HASH] || dynamic_info_DT_GNU_HASH)
&& do_syms
&& do_using_dynamic
@@ -11924,61 +12000,14 @@ process_symbol_table (Filedata * filedata)
{
unsigned long hn;
- if (dynamic_info[DT_HASH])
- {
- bfd_vma si;
- char *visited;
-
- printf (_("\nSymbol table for image:\n"));
- if (is_32bit_elf)
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
- else
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
-
- visited = xcmalloc (nchains, 1);
- memset (visited, 0, nchains);
- for (hn = 0; hn < nbuckets; hn++)
- {
- for (si = buckets[hn]; si > 0; si = chains[si])
- {
- print_dynamic_symbol (filedata, si, hn);
- if (si >= nchains || visited[si])
- {
- error (_("histogram chain is corrupt\n"));
- break;
- }
- visited[si] = 1;
- }
- }
- free (visited);
- }
-
- if (dynamic_info_DT_GNU_HASH)
- {
- printf (_("\nSymbol table of `%s' for image:\n"),
- GNU_HASH_SECTION_NAME);
- if (is_32bit_elf)
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
- else
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
-
- for (hn = 0; hn < ngnubuckets; ++hn)
- if (gnubuckets[hn] != 0)
- {
- bfd_vma si = gnubuckets[hn];
- bfd_vma off = si - gnusymidx;
+ printf (_("\nSymbol table for image:\n"));
+ if (is_32bit_elf)
+ printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
+ else
+ printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
- do
- {
- if (dynamic_info_DT_MIPS_XHASH)
- print_dynamic_symbol (filedata, mipsxlat[off], hn);
- else
- print_dynamic_symbol (filedata, si, hn);
- si++;
- }
- while (off < ngnuchains && (gnuchains[off++] & 1) == 0);
- }
- }
+ for (hn = 0; hn < num_dynamic_syms; hn++)
+ print_dynamic_symbol (filedata, hn);
}
else if ((do_dyn_syms || (do_syms && !do_using_dynamic))
&& filedata->section_headers != NULL)
diff --git a/ld/testsuite/ld-elf/hash.d b/ld/testsuite/ld-elf/hash.d
index efe675e0c7..a0bebb0b00 100644
--- a/ld/testsuite/ld-elf/hash.d
+++ b/ld/testsuite/ld-elf/hash.d
@@ -9,11 +9,11 @@
#...
+0x[0-9a-z]+ +\(GNU_HASH\) +0x[0-9a-z]+
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] _start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] _start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] main
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] main
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] __start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] __start
#...
diff --git a/ld/testsuite/ld-elf/pr13195.d b/ld/testsuite/ld-elf/pr13195.d
index 8a0f9bd805..fb02e22afa 100644
--- a/ld/testsuite/ld-elf/pr13195.d
+++ b/ld/testsuite/ld-elf/pr13195.d
@@ -5,5 +5,5 @@
# generic linker targets don't support --gc-sections, nor do a bunch of others
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[1-9]+ foo
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[1-9]+ foo
#pass
diff --git a/ld/testsuite/ld-elfvsb/hidden2.d b/ld/testsuite/ld-elfvsb/hidden2.d
index 72a42d57bc..8fe2da65b9 100644
--- a/ld/testsuite/ld-elfvsb/hidden2.d
+++ b/ld/testsuite/ld-elfvsb/hidden2.d
@@ -5,5 +5,5 @@
Symbol table for image:
#...
-[ ]*[0-9]+ +[0-9]+: [0-9a-fA-F]* +0 +OBJECT +LOCAL +DEFAULT .* foo
+[ ]*[0-9]+: [0-9a-fA-F]* +0 +OBJECT +LOCAL +DEFAULT .* foo
#pass
diff --git a/ld/testsuite/ld-mips-elf/hash2.d b/ld/testsuite/ld-mips-elf/hash2.d
index 122edb80e1..a0fe4266f2 100644
--- a/ld/testsuite/ld-mips-elf/hash2.d
+++ b/ld/testsuite/ld-mips-elf/hash2.d
@@ -6,11 +6,11 @@
#...
+0x[0-9a-z]+ +\(MIPS_XHASH\) +0x[0-9a-z]+
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) _start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) __start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) main
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) _start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) main
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) __start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) start
#...
--
2.24.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms table
2020-03-12 13:23 [PATCH] readelf: Compute dynamic symbol table size from hash table H.J. Lu
@ 2020-03-19 12:51 ` H.J. Lu
2020-03-22 12:34 ` H.J. Lu
0 siblings, 1 reply; 11+ messages in thread
From: H.J. Lu @ 2020-03-19 12:51 UTC (permalink / raw)
To: binutils
On Thu, Mar 12, 2020 at 06:23:34AM -0700, H.J. Lu wrote:
> When reconstructing dynamic symbol table from the PT_DYNAMIC segment,
> compute dynamic symbol table size from hash table. For DT_HASH, the
> number of dynamic symbol table entries equals the number of chains.
> For DT_GNU_HASH/DT_MIPS_XHASH, only defined symbols with non-STB_LOCAL
> indings are in hash table. Since DT_GNU_HASH/DT_MIPS_XHASH place all
> symbols with STB_LOCAL binding before symbols with other bindings and
> all undefined symbols defined ones in dynamic symbol table, the highest
> symbol index in DT_GNU_HASH/DT_MIPS_XHASH is the highest dynamic symbol
> table index.
>
> Also iterate dynamic symbol table to print each entry so that output
> of "readelf -D -s" without section header is similar to "readelf -s"
> with section header.
> `
Here is the updated patch to make --syms --use-dynamic output almost
identical with --dyn-syms. On Linux/x86-64, I got
[hjl@gnu-cfl-2 pr25617]$ ./readelf -D -s /lib64/libc.so.6 > 1
[hjl@gnu-cfl-2 pr25617]$ ./readelf --dyn-syms /lib64/libc.so.6 > 2
[hjl@gnu-cfl-2 pr25617]$ diff -up 1 2
--- 1 2020-03-19 05:50:11.367432099 -0700
+++ 2 2020-03-19 05:50:20.265739131 -0700
@@ -1,5 +1,5 @@
-Symbol table for image contains 2369 entries:
+Symbol table '.dynsym' contains 2369 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 OBJECT WEAK DEFAULT UND _dl_starting_up@GLIBC_PRIVATE (33)
[hjl@gnu-cfl-2 pr25617]$
Any comments, objections?
Thanks.
H.J.
---
When reconstructing dynamic symbol table from the PT_DYNAMIC segment,
compute dynamic symbol table size from hash table. For DT_HASH, the
number of dynamic symbol table entries equals the number of chains.
For DT_GNU_HASH/DT_MIPS_XHASH, only defined symbols with non-STB_LOCAL
indings are in hash table. Since DT_GNU_HASH/DT_MIPS_XHASH place all
symbols with STB_LOCAL binding before symbols with other bindings and
all undefined symbols defined ones in dynamic symbol table, the highest
symbol index in DT_GNU_HASH/DT_MIPS_XHASH is the highest dynamic symbol
table index.
Rewrite print_dynamic_symbol to dump dynamic symbol table for --dyn-syms
and --syms --use-dynamic.
binutils/
* readelf.c (nbuckets): New.
(nchains): Likewise.
(buckets): Likewise.
(chains): Likewise.
(ngnubuckets): Likewise.
(gnubuckets): Likewise.
(gnuchains): Likewise.
(mipsxlat): Likewise.
(ngnuchains): Likewise.
(gnusymidx): Likewise.
(VALID_SYMBOL_NAME): Likewise.
(VALID_DYNAMIC_NAME): Use it.
(get_dynamic_data): Moved before process_dynamic_section.
(get_num_dynamic_syms): New function.
(process_dynamic_section): Use DT_SYMTAB, DT_SYMENT, DT_HASH,
DT_GNU_HASH and DT_MIPS_XHASH to reconstruct dynamic symbol
table. Use DT_STRTAB and DT_STRSZ to reconstruct dynamic string
table.
(get_symbol_index_type): Don't print "bad section index" when
there is no section header.
(print_dynamic_symbol): Rewrite.
(process_symbol_table): Call print_dynamic_symbol to dump dynamic
symbol table.
ld/
* testsuite/ld-elf/hash.d: Updated.
* testsuite/ld-elf/pr13195.d: Likewise.
* testsuite/ld-elfvsb/hidden2.d: Likewise.
* testsuite/ld-mips-elf/hash2.d: Likewise.
---
binutils/readelf.c | 1053 +++++++++++++++---------------
ld/testsuite/ld-elf/hash.d | 8 +-
ld/testsuite/ld-elf/pr13195.d | 2 +-
ld/testsuite/ld-elfvsb/hidden2.d | 4 +-
ld/testsuite/ld-mips-elf/hash2.d | 8 +-
5 files changed, 538 insertions(+), 537 deletions(-)
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 66d91a37b7..4816513cf7 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -226,6 +226,16 @@ static size_t dynamic_nent;
static char * dynamic_strings;
static unsigned long dynamic_strings_length;
static unsigned long num_dynamic_syms;
+static bfd_size_type nbuckets;
+static bfd_size_type nchains;
+static bfd_vma *buckets;
+static bfd_vma *chains;
+static bfd_vma ngnubuckets;
+static bfd_vma *gnubuckets;
+static bfd_vma *gnuchains;
+static bfd_vma *mipsxlat;
+static bfd_size_type ngnuchains;
+static bfd_vma gnusymidx;
static Elf_Internal_Sym * dynamic_symbols;
static Elf_Internal_Syminfo * dynamic_syminfo;
static unsigned long dynamic_syminfo_offset;
@@ -325,7 +335,10 @@ static const char * get_symbol_version_string
(is_32bit_elf ? get_32bit_elf_symbols (file, section, sym_count) \
: get_64bit_elf_symbols (file, section, sym_count))
-#define VALID_DYNAMIC_NAME(offset) ((dynamic_strings != NULL) && (offset < dynamic_strings_length))
+#define VALID_SYMBOL_NAME(strtab, strtab_size, offset) \
+ (strtab != NULL && offset < strtab_size)
+#define VALID_DYNAMIC_NAME(offset) \
+ VALID_SYMBOL_NAME (dynamic_strings, dynamic_strings_length, offset)
/* GET_DYNAMIC_NAME asssumes that VALID_DYNAMIC_NAME has
already been called and verified that the string exists. */
#define GET_DYNAMIC_NAME(offset) (dynamic_strings + offset)
@@ -9862,6 +9875,320 @@ print_dynamic_flags (bfd_vma flags)
puts ("");
}
+static bfd_vma *
+get_dynamic_data (Filedata * filedata, bfd_size_type number, unsigned int ent_size)
+{
+ unsigned char * e_data;
+ bfd_vma * i_data;
+
+ /* If the size_t type is smaller than the bfd_size_type, eg because
+ you are building a 32-bit tool on a 64-bit host, then make sure
+ that when (number) is cast to (size_t) no information is lost. */
+ if (sizeof (size_t) < sizeof (bfd_size_type)
+ && (bfd_size_type) ((size_t) number) != number)
+ {
+ error (_("Size truncation prevents reading %s elements of size %u\n"),
+ bfd_vmatoa ("u", number), ent_size);
+ return NULL;
+ }
+
+ /* Be kind to memory checkers (eg valgrind, address sanitizer) by not
+ attempting to allocate memory when the read is bound to fail. */
+ if (ent_size * number > filedata->file_size)
+ {
+ error (_("Invalid number of dynamic entries: %s\n"),
+ bfd_vmatoa ("u", number));
+ return NULL;
+ }
+
+ e_data = (unsigned char *) cmalloc ((size_t) number, ent_size);
+ if (e_data == NULL)
+ {
+ error (_("Out of memory reading %s dynamic entries\n"),
+ bfd_vmatoa ("u", number));
+ return NULL;
+ }
+
+ if (fread (e_data, ent_size, (size_t) number, filedata->handle) != number)
+ {
+ error (_("Unable to read in %s bytes of dynamic data\n"),
+ bfd_vmatoa ("u", number * ent_size));
+ free (e_data);
+ return NULL;
+ }
+
+ i_data = (bfd_vma *) cmalloc ((size_t) number, sizeof (*i_data));
+ if (i_data == NULL)
+ {
+ error (_("Out of memory allocating space for %s dynamic entries\n"),
+ bfd_vmatoa ("u", number));
+ free (e_data);
+ return NULL;
+ }
+
+ while (number--)
+ i_data[number] = byte_get (e_data + number * ent_size, ent_size);
+
+ free (e_data);
+
+ return i_data;
+}
+
+static unsigned long
+get_num_dynamic_syms (Filedata * filedata)
+{
+ unsigned long num_of_syms = 0;
+
+ if (!do_histogram && (!do_using_dynamic || do_dyn_syms))
+ return num_of_syms;
+
+ if (dynamic_info[DT_HASH])
+ {
+ unsigned char nb[8];
+ unsigned char nc[8];
+ unsigned int hash_ent_size = 4;
+
+ if ((filedata->file_header.e_machine == EM_ALPHA
+ || filedata->file_header.e_machine == EM_S390
+ || filedata->file_header.e_machine == EM_S390_OLD)
+ && filedata->file_header.e_ident[EI_CLASS] == ELFCLASS64)
+ hash_ent_size = 8;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, dynamic_info[DT_HASH],
+ sizeof nb + sizeof nc)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ goto no_hash;
+ }
+
+ if (fread (nb, hash_ent_size, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to read in number of buckets\n"));
+ goto no_hash;
+ }
+
+ if (fread (nc, hash_ent_size, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to read in number of chains\n"));
+ goto no_hash;
+ }
+
+ nbuckets = byte_get (nb, hash_ent_size);
+ nchains = byte_get (nc, hash_ent_size);
+ num_of_syms = nchains;
+
+ buckets = get_dynamic_data (filedata, nbuckets, hash_ent_size);
+ chains = get_dynamic_data (filedata, nchains, hash_ent_size);
+
+ no_hash:
+ if (num_of_syms == 0)
+ {
+ if (buckets)
+ {
+ free (buckets);
+ buckets = NULL;
+ }
+ if (chains)
+ {
+ free (chains);
+ buckets = NULL;
+ }
+ nbuckets = 0;
+ }
+ }
+
+ if (dynamic_info_DT_GNU_HASH)
+ {
+ unsigned char nb[16];
+ bfd_vma i, maxchain = 0xffffffff, bitmaskwords;
+ bfd_vma buckets_vma;
+ unsigned long hn;
+ bfd_boolean gnu_hash_error = FALSE;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, dynamic_info_DT_GNU_HASH,
+ sizeof nb)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ if (fread (nb, 16, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to read in number of buckets\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ ngnubuckets = byte_get (nb, 4);
+ gnusymidx = byte_get (nb + 4, 4);
+ bitmaskwords = byte_get (nb + 8, 4);
+ buckets_vma = dynamic_info_DT_GNU_HASH + 16;
+ if (is_32bit_elf)
+ buckets_vma += bitmaskwords * 4;
+ else
+ buckets_vma += bitmaskwords * 8;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, buckets_vma, 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ gnubuckets = get_dynamic_data (filedata, ngnubuckets, 4);
+
+ if (gnubuckets == NULL)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ for (i = 0; i < ngnubuckets; i++)
+ if (gnubuckets[i] != 0)
+ {
+ if (gnubuckets[i] < gnusymidx)
+ {
+ gnu_hash_error = TRUE;
+ return FALSE;
+ }
+
+ if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
+ maxchain = gnubuckets[i];
+ }
+
+ if (maxchain == 0xffffffff)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ maxchain -= gnusymidx;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, buckets_vma
+ + 4 * (ngnubuckets + maxchain), 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ do
+ {
+ if (fread (nb, 4, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to determine last chain length\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ if (maxchain + 1 == 0)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ ++maxchain;
+ }
+ while ((byte_get (nb, 4) & 1) == 0);
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, buckets_vma + 4 * ngnubuckets, 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ gnuchains = get_dynamic_data (filedata, maxchain, 4);
+ ngnuchains = maxchain;
+
+ if (gnuchains == NULL)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ if (dynamic_info_DT_MIPS_XHASH)
+ {
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, (buckets_vma
+ + 4 * (ngnubuckets
+ + maxchain)), 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ mipsxlat = get_dynamic_data (filedata, maxchain, 4);
+ }
+
+ for (hn = 0; hn < ngnubuckets; ++hn)
+ if (gnubuckets[hn] != 0)
+ {
+ bfd_vma si = gnubuckets[hn];
+ bfd_vma off = si - gnusymidx;
+
+ do
+ {
+ if (dynamic_info_DT_MIPS_XHASH)
+ {
+ if (mipsxlat[off] >= num_of_syms)
+ num_of_syms = mipsxlat[off] + 1;
+ }
+ else
+ {
+ if (si >= num_of_syms)
+ num_of_syms = si + 1;
+ }
+ si++;
+ }
+ while (off < ngnuchains && (gnuchains[off++] & 1) == 0);
+ }
+
+ no_gnu_hash:
+ if (gnu_hash_error)
+ {
+ if (mipsxlat)
+ {
+ free (mipsxlat);
+ mipsxlat = NULL;
+ }
+ if (gnuchains)
+ {
+ free (gnuchains);
+ gnuchains = NULL;
+ }
+ if (gnubuckets)
+ {
+ free (gnubuckets);
+ gnubuckets = NULL;
+ }
+ ngnubuckets = 0;
+ ngnuchains = 0;
+ }
+ }
+
+ return num_of_syms;
+}
+
/* Parse and display the contents of the dynamic section. */
static bfd_boolean
@@ -9889,103 +10216,117 @@ process_dynamic_section (Filedata * filedata)
}
/* Find the appropriate symbol table. */
- if (dynamic_symbols == NULL)
+ if (dynamic_symbols == NULL || do_histogram)
{
for (entry = dynamic_section;
entry < dynamic_section + dynamic_nent;
++entry)
- {
- Elf_Internal_Shdr section;
-
- if (entry->d_tag != DT_SYMTAB)
- continue;
-
+ if (entry->d_tag == DT_SYMTAB)
dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
+ else if (entry->d_tag == DT_SYMENT)
+ dynamic_info[DT_SYMENT] = entry->d_un.d_val;
+ else if (entry->d_tag == DT_HASH)
+ dynamic_info[DT_HASH] = entry->d_un.d_val;
+ else if (entry->d_tag == DT_GNU_HASH)
+ dynamic_info_DT_GNU_HASH = entry->d_un.d_val;
+ else if ((filedata->file_header.e_machine == EM_MIPS
+ || filedata->file_header.e_machine == EM_MIPS_RS3_LE)
+ && entry->d_tag == DT_MIPS_XHASH)
+ {
+ dynamic_info_DT_MIPS_XHASH = entry->d_un.d_val;
+ dynamic_info_DT_GNU_HASH = entry->d_un.d_val;
+ }
- /* Since we do not know how big the symbol table is,
- we default to reading in the entire file (!) and
- processing that. This is overkill, I know, but it
- should work. */
- section.sh_offset = offset_from_vma (filedata, entry->d_un.d_val, 0);
- if ((bfd_size_type) section.sh_offset > filedata->file_size)
- {
- /* See PR 21379 for a reproducer. */
- error (_("Invalid DT_SYMTAB entry: %lx\n"),
- (long) section.sh_offset);
- return FALSE;
- }
+ if (dynamic_info[DT_SYMTAB] && dynamic_info[DT_SYMENT])
+ {
+ Elf_Internal_Phdr *seg;
+ bfd_vma vma = dynamic_info[DT_SYMTAB];
- if (archive_file_offset != 0)
- section.sh_size = archive_file_size - section.sh_offset;
- else
- section.sh_size = filedata->file_size - section.sh_offset;
+ if (! get_program_headers (filedata))
+ {
+ error (_("Cannot interpret virtual addresses without program headers.\n"));
+ return FALSE;
+ }
- if (is_32bit_elf)
- section.sh_entsize = sizeof (Elf32_External_Sym);
- else
- section.sh_entsize = sizeof (Elf64_External_Sym);
- section.sh_name = filedata->string_table_length;
+ for (seg = filedata->program_headers;
+ seg < filedata->program_headers + filedata->file_header.e_phnum;
+ ++seg)
+ {
+ if (seg->p_type != PT_LOAD)
+ continue;
- if (dynamic_symbols != NULL)
- {
- error (_("Multiple dynamic symbol table sections found\n"));
- free (dynamic_symbols);
- }
- dynamic_symbols = GET_ELF_SYMBOLS (filedata, §ion, & num_dynamic_syms);
- if (num_dynamic_syms < 1)
- {
- error (_("Unable to determine the number of symbols to load\n"));
- continue;
- }
- }
- }
+ if ((seg->p_offset + seg->p_filesz)
+ > filedata->file_size)
+ {
+ /* See PR 21379 for a reproducer. */
+ error (_("Invalid PT_LOAD entry\n"));
+ return FALSE;
+ }
+
+ if (vma >= (seg->p_vaddr & -seg->p_align)
+ && vma <= seg->p_vaddr + seg->p_filesz)
+ {
+ /* Since we do not know how big the symbol table is,
+ we default to reading in up to the end of PT_LOAD
+ segment and processing that. This is overkill, I
+ know, but it should work. */
+ Elf_Internal_Shdr section;
+ unsigned long num_of_syms
+ = get_num_dynamic_syms (filedata);
+ section.sh_offset = (vma - seg->p_vaddr
+ + seg->p_offset);
+ section.sh_size = (num_of_syms
+ * dynamic_info[DT_SYMENT]);
+ section.sh_entsize = dynamic_info[DT_SYMENT];
+ section.sh_name = filedata->string_table_length;
+ dynamic_symbols = GET_ELF_SYMBOLS (filedata,
+ §ion,
+ & num_dynamic_syms);
+ if (dynamic_symbols == NULL
+ || num_of_syms == 0
+ || num_dynamic_syms != num_of_syms)
+ {
+ error (_("Corrupt DT_SYMTAB dynamic entry\n"));
+ return FALSE;
+ }
+ }
+ }
+ }
+ }
/* Similarly find a string table. */
if (dynamic_strings == NULL)
- {
- for (entry = dynamic_section;
- entry < dynamic_section + dynamic_nent;
- ++entry)
- {
- unsigned long offset;
- long str_tab_len;
-
- if (entry->d_tag != DT_STRTAB)
- continue;
-
+ for (entry = dynamic_section;
+ entry < dynamic_section + dynamic_nent;
+ ++entry)
+ {
+ if (entry->d_tag == DT_STRTAB)
dynamic_info[DT_STRTAB] = entry->d_un.d_val;
- /* Since we do not know how big the string table is,
- we default to reading in the entire file (!) and
- processing that. This is overkill, I know, but it
- should work. */
-
- offset = offset_from_vma (filedata, entry->d_un.d_val, 0);
-
- if (archive_file_offset != 0)
- str_tab_len = archive_file_size - offset;
- else
- str_tab_len = filedata->file_size - offset;
+ if (entry->d_tag == DT_STRSZ)
+ dynamic_info[DT_STRSZ] = entry->d_un.d_val;
- if (str_tab_len < 1)
- {
- error
- (_("Unable to determine the length of the dynamic string table\n"));
- continue;
- }
-
- if (dynamic_strings != NULL)
- {
- error (_("Multiple dynamic string tables found\n"));
- free (dynamic_strings);
- }
+ if (dynamic_info[DT_STRTAB] && dynamic_info[DT_STRSZ])
+ {
+ unsigned long offset;
+ bfd_size_type str_tab_len = dynamic_info[DT_STRSZ];
+
+ offset = offset_from_vma (filedata,
+ dynamic_info[DT_STRTAB],
+ str_tab_len);
+ dynamic_strings = (char *) get_data (NULL, filedata, offset, 1,
+ str_tab_len,
+ _("dynamic string table"));
+ if (dynamic_strings == NULL)
+ {
+ error (_("Corrupt DT_STRTAB dynamic entry\n"));
+ break;
+ }
- dynamic_strings = (char *) get_data (NULL, filedata, offset, 1,
- str_tab_len,
- _("dynamic string table"));
- dynamic_strings_length = dynamic_strings == NULL ? 0 : str_tab_len;
- }
- }
+ dynamic_strings_length = str_tab_len;
+ break;
+ }
+ }
/* And find the syminfo section if available. */
if (dynamic_syminfo == NULL)
@@ -11407,143 +11748,36 @@ get_symbol_index_type (Filedata * filedata, unsigned int type)
default:
if (type == SHN_IA_64_ANSI_COMMON
&& filedata->file_header.e_machine == EM_IA_64
- && filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
- return "ANSI_COM";
- else if ((filedata->file_header.e_machine == EM_X86_64
- || filedata->file_header.e_machine == EM_L1OM
- || filedata->file_header.e_machine == EM_K1OM)
- && type == SHN_X86_64_LCOMMON)
- return "LARGE_COM";
- else if ((type == SHN_MIPS_SCOMMON
- && filedata->file_header.e_machine == EM_MIPS)
- || (type == SHN_TIC6X_SCOMMON
- && filedata->file_header.e_machine == EM_TI_C6000))
- return "SCOM";
- else if (type == SHN_MIPS_SUNDEFINED
- && filedata->file_header.e_machine == EM_MIPS)
- return "SUND";
- else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
- sprintf (buff, "PRC[0x%04x]", type & 0xffff);
- else if (type >= SHN_LOOS && type <= SHN_HIOS)
- sprintf (buff, "OS [0x%04x]", type & 0xffff);
- else if (type >= SHN_LORESERVE)
- sprintf (buff, "RSV[0x%04x]", type & 0xffff);
- else if (type >= filedata->file_header.e_shnum)
- sprintf (buff, _("bad section index[%3d]"), type);
- else
- sprintf (buff, "%3d", type);
- break;
- }
-
- return buff;
-}
-
-static bfd_vma *
-get_dynamic_data (Filedata * filedata, bfd_size_type number, unsigned int ent_size)
-{
- unsigned char * e_data;
- bfd_vma * i_data;
-
- /* If the size_t type is smaller than the bfd_size_type, eg because
- you are building a 32-bit tool on a 64-bit host, then make sure
- that when (number) is cast to (size_t) no information is lost. */
- if (sizeof (size_t) < sizeof (bfd_size_type)
- && (bfd_size_type) ((size_t) number) != number)
- {
- error (_("Size truncation prevents reading %s elements of size %u\n"),
- bfd_vmatoa ("u", number), ent_size);
- return NULL;
- }
-
- /* Be kind to memory checkers (eg valgrind, address sanitizer) by not
- attempting to allocate memory when the read is bound to fail. */
- if (ent_size * number > filedata->file_size)
- {
- error (_("Invalid number of dynamic entries: %s\n"),
- bfd_vmatoa ("u", number));
- return NULL;
- }
-
- e_data = (unsigned char *) cmalloc ((size_t) number, ent_size);
- if (e_data == NULL)
- {
- error (_("Out of memory reading %s dynamic entries\n"),
- bfd_vmatoa ("u", number));
- return NULL;
- }
-
- if (fread (e_data, ent_size, (size_t) number, filedata->handle) != number)
- {
- error (_("Unable to read in %s bytes of dynamic data\n"),
- bfd_vmatoa ("u", number * ent_size));
- free (e_data);
- return NULL;
- }
-
- i_data = (bfd_vma *) cmalloc ((size_t) number, sizeof (*i_data));
- if (i_data == NULL)
- {
- error (_("Out of memory allocating space for %s dynamic entries\n"),
- bfd_vmatoa ("u", number));
- free (e_data);
- return NULL;
- }
-
- while (number--)
- i_data[number] = byte_get (e_data + number * ent_size, ent_size);
-
- free (e_data);
-
- return i_data;
-}
-
-static void
-print_dynamic_symbol (Filedata * filedata, bfd_vma si, unsigned long hn)
-{
- Elf_Internal_Sym * psym;
- int n;
-
- n = print_vma (si, DEC_5);
- if (n < 5)
- fputs (&" "[n], stdout);
- printf (" %3lu: ", hn);
-
- if (dynamic_symbols == NULL || si >= num_dynamic_syms)
- {
- printf (_("<No info available for dynamic symbol number %lu>\n"),
- (unsigned long) si);
- return;
- }
-
- psym = dynamic_symbols + si;
- print_vma (psym->st_value, LONG_HEX);
- putchar (' ');
- print_vma (psym->st_size, DEC_5);
-
- printf (" %-7s", get_symbol_type (filedata, ELF_ST_TYPE (psym->st_info)));
- printf (" %-6s", get_symbol_binding (filedata, ELF_ST_BIND (psym->st_info)));
-
- if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
- printf (" %-7s", get_solaris_symbol_visibility (psym->st_other));
- else
- {
- unsigned int vis = ELF_ST_VISIBILITY (psym->st_other);
-
- printf (" %-7s", get_symbol_visibility (vis));
- /* Check to see if any other bits in the st_other field are set.
- Note - displaying this information disrupts the layout of the
- table being generated, but for the moment this case is very
- rare. */
- if (psym->st_other ^ vis)
- printf (" [%s] ", get_symbol_other (filedata, psym->st_other ^ vis));
+ && filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
+ return "ANSI_COM";
+ else if ((filedata->file_header.e_machine == EM_X86_64
+ || filedata->file_header.e_machine == EM_L1OM
+ || filedata->file_header.e_machine == EM_K1OM)
+ && type == SHN_X86_64_LCOMMON)
+ return "LARGE_COM";
+ else if ((type == SHN_MIPS_SCOMMON
+ && filedata->file_header.e_machine == EM_MIPS)
+ || (type == SHN_TIC6X_SCOMMON
+ && filedata->file_header.e_machine == EM_TI_C6000))
+ return "SCOM";
+ else if (type == SHN_MIPS_SUNDEFINED
+ && filedata->file_header.e_machine == EM_MIPS)
+ return "SUND";
+ else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
+ sprintf (buff, "PRC[0x%04x]", type & 0xffff);
+ else if (type >= SHN_LOOS && type <= SHN_HIOS)
+ sprintf (buff, "OS [0x%04x]", type & 0xffff);
+ else if (type >= SHN_LORESERVE)
+ sprintf (buff, "RSV[0x%04x]", type & 0xffff);
+ else if (filedata->file_header.e_shnum != 0
+ && type >= filedata->file_header.e_shnum)
+ sprintf (buff, _("bad section index[%3d]"), type);
+ else
+ sprintf (buff, "%3d", type);
+ break;
}
- printf (" %3.3s ", get_symbol_index_type (filedata, psym->st_shndx));
- if (VALID_DYNAMIC_NAME (psym->st_name))
- print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
- else
- printf (_(" <corrupt: %14ld>"), psym->st_name);
- putchar ('\n');
+ return buff;
}
static const char *
@@ -11719,214 +11953,78 @@ get_symbol_version_string (Filedata * filedata,
return NULL;
}
-/* Dump the symbol table. */
-static bfd_boolean
-process_symbol_table (Filedata * filedata)
+static void
+print_dynamic_symbol (Filedata *filedata, unsigned long si,
+ Elf_Internal_Sym *symtab,
+ Elf_Internal_Shdr *section,
+ char *strtab, size_t strtab_size)
{
- Elf_Internal_Shdr * section;
- bfd_size_type nbuckets = 0;
- bfd_size_type nchains = 0;
- bfd_vma * buckets = NULL;
- bfd_vma * chains = NULL;
- bfd_vma ngnubuckets = 0;
- bfd_vma * gnubuckets = NULL;
- bfd_vma * gnuchains = NULL;
- bfd_vma * mipsxlat = NULL;
- bfd_vma gnusymidx = 0;
- bfd_size_type ngnuchains = 0;
-
- if (!do_syms && !do_dyn_syms && !do_histogram)
- return TRUE;
+ const char *version_string;
+ enum versioned_symbol_info sym_info;
+ unsigned short vna_other;
+ Elf_Internal_Sym *psym = symtab + si;
- if (dynamic_info[DT_HASH]
- && (do_histogram
- || (do_using_dynamic
- && !do_dyn_syms
- && dynamic_strings != NULL)))
+ printf ("%6ld: ", si);
+ print_vma (psym->st_value, LONG_HEX);
+ putchar (' ');
+ print_vma (psym->st_size, DEC_5);
+ printf (" %-7s", get_symbol_type (filedata, ELF_ST_TYPE (psym->st_info)));
+ printf (" %-6s", get_symbol_binding (filedata, ELF_ST_BIND (psym->st_info)));
+ if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
+ printf (" %-7s", get_solaris_symbol_visibility (psym->st_other));
+ else
{
- unsigned char nb[8];
- unsigned char nc[8];
- unsigned int hash_ent_size = 4;
-
- if ((filedata->file_header.e_machine == EM_ALPHA
- || filedata->file_header.e_machine == EM_S390
- || filedata->file_header.e_machine == EM_S390_OLD)
- && filedata->file_header.e_ident[EI_CLASS] == ELFCLASS64)
- hash_ent_size = 8;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, dynamic_info[DT_HASH],
- sizeof nb + sizeof nc)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_hash;
- }
-
- if (fread (nb, hash_ent_size, 1, filedata->handle) != 1)
- {
- error (_("Failed to read in number of buckets\n"));
- goto no_hash;
- }
-
- if (fread (nc, hash_ent_size, 1, filedata->handle) != 1)
- {
- error (_("Failed to read in number of chains\n"));
- goto no_hash;
- }
-
- nbuckets = byte_get (nb, hash_ent_size);
- nchains = byte_get (nc, hash_ent_size);
-
- buckets = get_dynamic_data (filedata, nbuckets, hash_ent_size);
- chains = get_dynamic_data (filedata, nchains, hash_ent_size);
+ unsigned int vis = ELF_ST_VISIBILITY (psym->st_other);
- if (buckets == NULL || chains == NULL)
- {
- no_hash:
- free (buckets);
- free (chains);
- buckets = NULL;
- chains = NULL;
- nbuckets = 0;
- nchains = 0;
- if (do_using_dynamic)
- goto err_out;
- }
+ printf (" %-7s", get_symbol_visibility (vis));
+ /* Check to see if any other bits in the st_other field are set.
+ Note - displaying this information disrupts the layout of the
+ table being generated, but for the moment this case is very rare. */
+ if (psym->st_other ^ vis)
+ printf (" [%s] ", get_symbol_other (filedata, psym->st_other ^ vis));
}
-
- if (dynamic_info_DT_GNU_HASH
- && (do_histogram
- || (do_using_dynamic
- && !do_dyn_syms
- && dynamic_strings != NULL)))
- {
- unsigned char nb[16];
- bfd_vma i, maxchain = 0xffffffff, bitmaskwords;
- bfd_vma buckets_vma;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, dynamic_info_DT_GNU_HASH,
- sizeof nb)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- if (fread (nb, 16, 1, filedata->handle) != 1)
- {
- error (_("Failed to read in number of buckets\n"));
- goto no_gnu_hash;
- }
-
- ngnubuckets = byte_get (nb, 4);
- gnusymidx = byte_get (nb + 4, 4);
- bitmaskwords = byte_get (nb + 8, 4);
- buckets_vma = dynamic_info_DT_GNU_HASH + 16;
- if (is_32bit_elf)
- buckets_vma += bitmaskwords * 4;
+ printf (" %4s ", get_symbol_index_type (filedata, psym->st_shndx));
+ print_symbol (25, VALID_SYMBOL_NAME (strtab, strtab_size,
+ psym->st_name)
+ ? strtab + psym->st_name : _("<corrupt>"));
+
+ version_string
+ = get_symbol_version_string (filedata,
+ (section == NULL
+ || section->sh_type == SHT_DYNSYM),
+ strtab, strtab_size, si,
+ psym, &sym_info, &vna_other);
+ if (version_string)
+ {
+ if (sym_info == symbol_undefined)
+ printf ("@%s (%d)", version_string, vna_other);
else
- buckets_vma += bitmaskwords * 8;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, buckets_vma, 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- gnubuckets = get_dynamic_data (filedata, ngnubuckets, 4);
-
- if (gnubuckets == NULL)
- goto no_gnu_hash;
-
- for (i = 0; i < ngnubuckets; i++)
- if (gnubuckets[i] != 0)
- {
- if (gnubuckets[i] < gnusymidx)
- goto err_out;
-
- if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
- maxchain = gnubuckets[i];
- }
-
- if (maxchain == 0xffffffff)
- goto no_gnu_hash;
-
- maxchain -= gnusymidx;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, buckets_vma
- + 4 * (ngnubuckets + maxchain), 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- do
- {
- if (fread (nb, 4, 1, filedata->handle) != 1)
- {
- error (_("Failed to determine last chain length\n"));
- goto no_gnu_hash;
- }
-
- if (maxchain + 1 == 0)
- goto no_gnu_hash;
-
- ++maxchain;
- }
- while ((byte_get (nb, 4) & 1) == 0);
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, buckets_vma + 4 * ngnubuckets, 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
+ printf (sym_info == symbol_hidden ? "@%s" : "@@%s",
+ version_string);
+ }
- gnuchains = get_dynamic_data (filedata, maxchain, 4);
- ngnuchains = maxchain;
+ putchar ('\n');
- if (gnuchains == NULL)
- goto no_gnu_hash;
+ if (ELF_ST_BIND (psym->st_info) == STB_LOCAL
+ && section != NULL
+ && si >= section->sh_info
+ /* Irix 5 and 6 MIPS binaries are known to ignore this requirement. */
+ && filedata->file_header.e_machine != EM_MIPS
+ /* Solaris binaries have been found to violate this requirement as
+ well. Not sure if this is a bug or an ABI requirement. */
+ && filedata->file_header.e_ident[EI_OSABI] != ELFOSABI_SOLARIS)
+ warn (_("local symbol %lu found at index >= %s's sh_info value of %u\n"),
+ si, printable_section_name (filedata, section), section->sh_info);
+}
- if (dynamic_info_DT_MIPS_XHASH)
- {
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, (buckets_vma
- + 4 * (ngnubuckets
- + maxchain)), 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
+/* Dump the symbol table. */
+static bfd_boolean
+process_symbol_table (Filedata * filedata)
+{
+ Elf_Internal_Shdr * section;
- mipsxlat = get_dynamic_data (filedata, maxchain, 4);
- if (mipsxlat == NULL)
- {
- no_gnu_hash:
- free (gnuchains);
- gnuchains = NULL;
- free (gnubuckets);
- gnubuckets = NULL;
- ngnubuckets = 0;
- if (do_using_dynamic)
- goto err_out;
- }
- }
- }
+ if (!do_syms && !do_dyn_syms && !do_histogram)
+ return TRUE;
if ((dynamic_info[DT_HASH] || dynamic_info_DT_GNU_HASH)
&& do_syms
@@ -11934,63 +12032,19 @@ process_symbol_table (Filedata * filedata)
&& dynamic_strings != NULL
&& dynamic_symbols != NULL)
{
- unsigned long hn;
-
- if (dynamic_info[DT_HASH])
- {
- bfd_vma si;
- char *visited;
-
- printf (_("\nSymbol table for image:\n"));
- if (is_32bit_elf)
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
- else
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
-
- visited = xcmalloc (nchains, 1);
- memset (visited, 0, nchains);
- for (hn = 0; hn < nbuckets; hn++)
- {
- for (si = buckets[hn]; si > 0; si = chains[si])
- {
- print_dynamic_symbol (filedata, si, hn);
- if (si >= nchains || visited[si])
- {
- error (_("histogram chain is corrupt\n"));
- break;
- }
- visited[si] = 1;
- }
- }
- free (visited);
- }
+ unsigned long si;
- if (dynamic_info_DT_GNU_HASH)
- {
- printf (_("\nSymbol table of `%s' for image:\n"),
- GNU_HASH_SECTION_NAME);
- if (is_32bit_elf)
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
- else
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
-
- for (hn = 0; hn < ngnubuckets; ++hn)
- if (gnubuckets[hn] != 0)
- {
- bfd_vma si = gnubuckets[hn];
- bfd_vma off = si - gnusymidx;
+ printf (ngettext ("\nSymbol table for image contains %lu entry:\n",
+ "\nSymbol table for image contains %lu entries:\n",
+ num_dynamic_syms), num_dynamic_syms);
+ if (is_32bit_elf)
+ printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
+ else
+ printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
- do
- {
- if (dynamic_info_DT_MIPS_XHASH)
- print_dynamic_symbol (filedata, mipsxlat[off], hn);
- else
- print_dynamic_symbol (filedata, si, hn);
- si++;
- }
- while (off < ngnuchains && (gnuchains[off++] & 1) == 0);
- }
- }
+ for (si = 0; si < num_dynamic_syms; si++)
+ print_dynamic_symbol (filedata, si, dynamic_symbols, NULL,
+ dynamic_strings, dynamic_strings_length);
}
else if ((do_dyn_syms || (do_syms && !do_using_dynamic))
&& filedata->section_headers != NULL)
@@ -12004,7 +12058,6 @@ process_symbol_table (Filedata * filedata)
char * strtab = NULL;
unsigned long int strtab_size = 0;
Elf_Internal_Sym * symtab;
- Elf_Internal_Sym * psym;
unsigned long si, num_syms;
if ((section->sh_type != SHT_SYMTAB
@@ -12053,61 +12106,9 @@ process_symbol_table (Filedata * filedata)
strtab_size = strtab != NULL ? string_sec->sh_size : 0;
}
- 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 ("%6ld: ", si);
- print_vma (psym->st_value, LONG_HEX);
- putchar (' ');
- print_vma (psym->st_size, DEC_5);
- printf (" %-7s", get_symbol_type (filedata, ELF_ST_TYPE (psym->st_info)));
- printf (" %-6s", get_symbol_binding (filedata, ELF_ST_BIND (psym->st_info)));
- if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
- printf (" %-7s", get_solaris_symbol_visibility (psym->st_other));
- else
- {
- unsigned int vis = ELF_ST_VISIBILITY (psym->st_other);
-
- printf (" %-7s", get_symbol_visibility (vis));
- /* Check to see if any other bits in the st_other field are set.
- Note - displaying this information disrupts the layout of the
- table being generated, but for the moment this case is very rare. */
- if (psym->st_other ^ vis)
- printf (" [%s] ", get_symbol_other (filedata, psym->st_other ^ vis));
- }
- printf (" %4s ", get_symbol_index_type (filedata, psym->st_shndx));
- print_symbol (25, psym->st_name < strtab_size
- ? strtab + psym->st_name : _("<corrupt>"));
-
- version_string
- = get_symbol_version_string (filedata,
- section->sh_type == SHT_DYNSYM,
- strtab, strtab_size, si,
- psym, &sym_info, &vna_other);
- if (version_string)
- {
- if (sym_info == symbol_undefined)
- printf ("@%s (%d)", version_string, vna_other);
- else
- printf (sym_info == symbol_hidden ? "@%s" : "@@%s",
- version_string);
- }
-
- putchar ('\n');
-
- if (ELF_ST_BIND (psym->st_info) == STB_LOCAL
- && si >= section->sh_info
- /* Irix 5 and 6 MIPS binaries are known to ignore this requirement. */
- && filedata->file_header.e_machine != EM_MIPS
- /* Solaris binaries have been found to violate this requirement as
- well. Not sure if this is a bug or an ABI requirement. */
- && filedata->file_header.e_ident[EI_OSABI] != ELFOSABI_SOLARIS)
- warn (_("local symbol %lu found at index >= %s's sh_info value of %u\n"),
- si, printable_section_name (filedata, section), section->sh_info);
- }
+ for (si = 0; si < num_syms; si++)
+ print_dynamic_symbol (filedata, si, symtab, section,
+ strtab, strtab_size);
free (symtab);
if (strtab != filedata->string_table)
diff --git a/ld/testsuite/ld-elf/hash.d b/ld/testsuite/ld-elf/hash.d
index efe675e0c7..a0bebb0b00 100644
--- a/ld/testsuite/ld-elf/hash.d
+++ b/ld/testsuite/ld-elf/hash.d
@@ -9,11 +9,11 @@
#...
+0x[0-9a-z]+ +\(GNU_HASH\) +0x[0-9a-z]+
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] _start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] _start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] main
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] main
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] __start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] __start
#...
diff --git a/ld/testsuite/ld-elf/pr13195.d b/ld/testsuite/ld-elf/pr13195.d
index 8a0f9bd805..7e45f08b33 100644
--- a/ld/testsuite/ld-elf/pr13195.d
+++ b/ld/testsuite/ld-elf/pr13195.d
@@ -5,5 +5,5 @@
# generic linker targets don't support --gc-sections, nor do a bunch of others
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[1-9]+ foo
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[1-9]+ foo@@VERS_2.0
#pass
diff --git a/ld/testsuite/ld-elfvsb/hidden2.d b/ld/testsuite/ld-elfvsb/hidden2.d
index 72a42d57bc..5d299746f5 100644
--- a/ld/testsuite/ld-elfvsb/hidden2.d
+++ b/ld/testsuite/ld-elfvsb/hidden2.d
@@ -3,7 +3,7 @@
#readelf: -Ds
# It is also ok to remove this symbol, but we currently make it local.
-Symbol table for image:
+Symbol table for image contains [0-9]+ entries:
#...
-[ ]*[0-9]+ +[0-9]+: [0-9a-fA-F]* +0 +OBJECT +LOCAL +DEFAULT .* foo
+[ ]*[0-9]+: [0-9a-fA-F]* +0 +OBJECT +LOCAL +DEFAULT .* foo
#pass
diff --git a/ld/testsuite/ld-mips-elf/hash2.d b/ld/testsuite/ld-mips-elf/hash2.d
index 122edb80e1..a0fe4266f2 100644
--- a/ld/testsuite/ld-mips-elf/hash2.d
+++ b/ld/testsuite/ld-mips-elf/hash2.d
@@ -6,11 +6,11 @@
#...
+0x[0-9a-z]+ +\(MIPS_XHASH\) +0x[0-9a-z]+
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) _start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) __start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) main
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) _start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) main
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) __start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) start
#...
--
2.25.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms table
2020-03-19 12:51 ` [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms table H.J. Lu
@ 2020-03-22 12:34 ` H.J. Lu
2020-04-09 13:01 ` PING " H.J. Lu
0 siblings, 1 reply; 11+ messages in thread
From: H.J. Lu @ 2020-03-22 12:34 UTC (permalink / raw)
To: Binutils
[-- Attachment #1: Type: text/plain, Size: 3761 bytes --]
On Thu, Mar 19, 2020 at 5:51 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Thu, Mar 12, 2020 at 06:23:34AM -0700, H.J. Lu wrote:
> > When reconstructing dynamic symbol table from the PT_DYNAMIC segment,
> > compute dynamic symbol table size from hash table. For DT_HASH, the
> > number of dynamic symbol table entries equals the number of chains.
> > For DT_GNU_HASH/DT_MIPS_XHASH, only defined symbols with non-STB_LOCAL
> > indings are in hash table. Since DT_GNU_HASH/DT_MIPS_XHASH place all
> > symbols with STB_LOCAL binding before symbols with other bindings and
> > all undefined symbols defined ones in dynamic symbol table, the highest
> > symbol index in DT_GNU_HASH/DT_MIPS_XHASH is the highest dynamic symbol
> > table index.
> >
> > Also iterate dynamic symbol table to print each entry so that output
> > of "readelf -D -s" without section header is similar to "readelf -s"
> > with section header.
> > `
>
> Here is the updated patch to make --syms --use-dynamic output almost
> identical with --dyn-syms. On Linux/x86-64, I got
>
> [hjl@gnu-cfl-2 pr25617]$ ./readelf -D -s /lib64/libc.so.6 > 1
> [hjl@gnu-cfl-2 pr25617]$ ./readelf --dyn-syms /lib64/libc.so.6 > 2
> [hjl@gnu-cfl-2 pr25617]$ diff -up 1 2
> --- 1 2020-03-19 05:50:11.367432099 -0700
> +++ 2 2020-03-19 05:50:20.265739131 -0700
> @@ -1,5 +1,5 @@
>
> -Symbol table for image contains 2369 entries:
> +Symbol table '.dynsym' contains 2369 entries:
> Num: Value Size Type Bind Vis Ndx Name
> 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
> 1: 0000000000000000 0 OBJECT WEAK DEFAULT UND _dl_starting_up@GLIBC_PRIVATE (33)
> [hjl@gnu-cfl-2 pr25617]$
>
> Any comments, objections?
>
> Thanks.
>
> H.J.
> ---
> When reconstructing dynamic symbol table from the PT_DYNAMIC segment,
> compute dynamic symbol table size from hash table. For DT_HASH, the
> number of dynamic symbol table entries equals the number of chains.
> For DT_GNU_HASH/DT_MIPS_XHASH, only defined symbols with non-STB_LOCAL
> indings are in hash table. Since DT_GNU_HASH/DT_MIPS_XHASH place all
> symbols with STB_LOCAL binding before symbols with other bindings and
> all undefined symbols defined ones in dynamic symbol table, the highest
> symbol index in DT_GNU_HASH/DT_MIPS_XHASH is the highest dynamic symbol
> table index.
>
> Rewrite print_dynamic_symbol to dump dynamic symbol table for --dyn-syms
> and --syms --use-dynamic.
>
> binutils/
>
> * readelf.c (nbuckets): New.
> (nchains): Likewise.
> (buckets): Likewise.
> (chains): Likewise.
> (ngnubuckets): Likewise.
> (gnubuckets): Likewise.
> (gnuchains): Likewise.
> (mipsxlat): Likewise.
> (ngnuchains): Likewise.
> (gnusymidx): Likewise.
> (VALID_SYMBOL_NAME): Likewise.
> (VALID_DYNAMIC_NAME): Use it.
> (get_dynamic_data): Moved before process_dynamic_section.
> (get_num_dynamic_syms): New function.
> (process_dynamic_section): Use DT_SYMTAB, DT_SYMENT, DT_HASH,
> DT_GNU_HASH and DT_MIPS_XHASH to reconstruct dynamic symbol
> table. Use DT_STRTAB and DT_STRSZ to reconstruct dynamic string
> table.
> (get_symbol_index_type): Don't print "bad section index" when
> there is no section header.
> (print_dynamic_symbol): Rewrite.
> (process_symbol_table): Call print_dynamic_symbol to dump dynamic
> symbol table.
>
> ld/
>
> * testsuite/ld-elf/hash.d: Updated.
> * testsuite/ld-elf/pr13195.d: Likewise.
> * testsuite/ld-elfvsb/hidden2.d: Likewise.
> * testsuite/ld-mips-elf/hash2.d: Likewise.
I opened:
https://sourceware.org/bugzilla/show_bug.cgi?id=25707
--
H.J.
[-- Attachment #2: 0001-readelf-Consolidate-syms-use-dynamic-with-dyn-syms.patch --]
[-- Type: text/x-patch, Size: 39559 bytes --]
From 35937bb8f1c16b16b51beaf16dbdab29f4a49bed Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 4 Mar 2020 15:58:13 -0800
Subject: [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms
When reconstructing dynamic symbol table from the PT_DYNAMIC segment,
compute dynamic symbol table size from hash table. For DT_HASH, the
number of dynamic symbol table entries equals the number of chains.
For DT_GNU_HASH/DT_MIPS_XHASH, only defined symbols with non-STB_LOCAL
indings are in hash table. Since DT_GNU_HASH/DT_MIPS_XHASH place all
symbols with STB_LOCAL binding before symbols with other bindings and
all undefined symbols defined ones in dynamic symbol table, the highest
symbol index in DT_GNU_HASH/DT_MIPS_XHASH is the highest dynamic symbol
table index.
Rewrite print_dynamic_symbol to dump dynamic symbol table for --dyn-syms
and --syms --use-dynamic.
binutils/
PR binutils/25707
* readelf.c (nbuckets): New.
(nchains): Likewise.
(buckets): Likewise.
(chains): Likewise.
(ngnubuckets): Likewise.
(gnubuckets): Likewise.
(gnuchains): Likewise.
(mipsxlat): Likewise.
(ngnuchains): Likewise.
(gnusymidx): Likewise.
(VALID_SYMBOL_NAME): Likewise.
(VALID_DYNAMIC_NAME): Use it.
(get_dynamic_data): Moved before process_dynamic_section.
(get_num_dynamic_syms): New function.
(process_dynamic_section): Use DT_SYMTAB, DT_SYMENT, DT_HASH,
DT_GNU_HASH and DT_MIPS_XHASH to reconstruct dynamic symbol
table. Use DT_STRTAB and DT_STRSZ to reconstruct dynamic string
table.
(get_symbol_index_type): Don't print "bad section index" when
there is no section header.
(print_dynamic_symbol): Rewrite.
(process_symbol_table): Call print_dynamic_symbol to dump dynamic
symbol table.
ld/
PR binutils/25707
* testsuite/ld-elf/hash.d: Updated.
* testsuite/ld-elf/pr13195.d: Likewise.
* testsuite/ld-elfvsb/hidden2.d: Likewise.
* testsuite/ld-mips-elf/hash2.d: Likewise.
---
binutils/readelf.c | 1051 +++++++++++++++---------------
ld/testsuite/ld-elf/hash.d | 8 +-
ld/testsuite/ld-elf/pr13195.d | 2 +-
ld/testsuite/ld-elfvsb/hidden2.d | 4 +-
ld/testsuite/ld-mips-elf/hash2.d | 8 +-
5 files changed, 537 insertions(+), 536 deletions(-)
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 61f0617683..63457a546b 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -226,6 +226,16 @@ static size_t dynamic_nent;
static char * dynamic_strings;
static unsigned long dynamic_strings_length;
static unsigned long num_dynamic_syms;
+static bfd_size_type nbuckets;
+static bfd_size_type nchains;
+static bfd_vma *buckets;
+static bfd_vma *chains;
+static bfd_vma ngnubuckets;
+static bfd_vma *gnubuckets;
+static bfd_vma *gnuchains;
+static bfd_vma *mipsxlat;
+static bfd_size_type ngnuchains;
+static bfd_vma gnusymidx;
static Elf_Internal_Sym * dynamic_symbols;
static Elf_Internal_Syminfo * dynamic_syminfo;
static unsigned long dynamic_syminfo_offset;
@@ -325,7 +335,10 @@ static const char * get_symbol_version_string
(is_32bit_elf ? get_32bit_elf_symbols (file, section, sym_count) \
: get_64bit_elf_symbols (file, section, sym_count))
-#define VALID_DYNAMIC_NAME(offset) ((dynamic_strings != NULL) && (offset < dynamic_strings_length))
+#define VALID_SYMBOL_NAME(strtab, strtab_size, offset) \
+ (strtab != NULL && offset < strtab_size)
+#define VALID_DYNAMIC_NAME(offset) \
+ VALID_SYMBOL_NAME (dynamic_strings, dynamic_strings_length, offset)
/* GET_DYNAMIC_NAME asssumes that VALID_DYNAMIC_NAME has
already been called and verified that the string exists. */
#define GET_DYNAMIC_NAME(offset) (dynamic_strings + offset)
@@ -9865,6 +9878,320 @@ print_dynamic_flags (bfd_vma flags)
puts ("");
}
+static bfd_vma *
+get_dynamic_data (Filedata * filedata, bfd_size_type number, unsigned int ent_size)
+{
+ unsigned char * e_data;
+ bfd_vma * i_data;
+
+ /* If the size_t type is smaller than the bfd_size_type, eg because
+ you are building a 32-bit tool on a 64-bit host, then make sure
+ that when (number) is cast to (size_t) no information is lost. */
+ if (sizeof (size_t) < sizeof (bfd_size_type)
+ && (bfd_size_type) ((size_t) number) != number)
+ {
+ error (_("Size truncation prevents reading %s elements of size %u\n"),
+ bfd_vmatoa ("u", number), ent_size);
+ return NULL;
+ }
+
+ /* Be kind to memory checkers (eg valgrind, address sanitizer) by not
+ attempting to allocate memory when the read is bound to fail. */
+ if (ent_size * number > filedata->file_size)
+ {
+ error (_("Invalid number of dynamic entries: %s\n"),
+ bfd_vmatoa ("u", number));
+ return NULL;
+ }
+
+ e_data = (unsigned char *) cmalloc ((size_t) number, ent_size);
+ if (e_data == NULL)
+ {
+ error (_("Out of memory reading %s dynamic entries\n"),
+ bfd_vmatoa ("u", number));
+ return NULL;
+ }
+
+ if (fread (e_data, ent_size, (size_t) number, filedata->handle) != number)
+ {
+ error (_("Unable to read in %s bytes of dynamic data\n"),
+ bfd_vmatoa ("u", number * ent_size));
+ free (e_data);
+ return NULL;
+ }
+
+ i_data = (bfd_vma *) cmalloc ((size_t) number, sizeof (*i_data));
+ if (i_data == NULL)
+ {
+ error (_("Out of memory allocating space for %s dynamic entries\n"),
+ bfd_vmatoa ("u", number));
+ free (e_data);
+ return NULL;
+ }
+
+ while (number--)
+ i_data[number] = byte_get (e_data + number * ent_size, ent_size);
+
+ free (e_data);
+
+ return i_data;
+}
+
+static unsigned long
+get_num_dynamic_syms (Filedata * filedata)
+{
+ unsigned long num_of_syms = 0;
+
+ if (!do_histogram && (!do_using_dynamic || do_dyn_syms))
+ return num_of_syms;
+
+ if (dynamic_info[DT_HASH])
+ {
+ unsigned char nb[8];
+ unsigned char nc[8];
+ unsigned int hash_ent_size = 4;
+
+ if ((filedata->file_header.e_machine == EM_ALPHA
+ || filedata->file_header.e_machine == EM_S390
+ || filedata->file_header.e_machine == EM_S390_OLD)
+ && filedata->file_header.e_ident[EI_CLASS] == ELFCLASS64)
+ hash_ent_size = 8;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, dynamic_info[DT_HASH],
+ sizeof nb + sizeof nc)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ goto no_hash;
+ }
+
+ if (fread (nb, hash_ent_size, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to read in number of buckets\n"));
+ goto no_hash;
+ }
+
+ if (fread (nc, hash_ent_size, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to read in number of chains\n"));
+ goto no_hash;
+ }
+
+ nbuckets = byte_get (nb, hash_ent_size);
+ nchains = byte_get (nc, hash_ent_size);
+ num_of_syms = nchains;
+
+ buckets = get_dynamic_data (filedata, nbuckets, hash_ent_size);
+ chains = get_dynamic_data (filedata, nchains, hash_ent_size);
+
+ no_hash:
+ if (num_of_syms == 0)
+ {
+ if (buckets)
+ {
+ free (buckets);
+ buckets = NULL;
+ }
+ if (chains)
+ {
+ free (chains);
+ buckets = NULL;
+ }
+ nbuckets = 0;
+ }
+ }
+
+ if (dynamic_info_DT_GNU_HASH)
+ {
+ unsigned char nb[16];
+ bfd_vma i, maxchain = 0xffffffff, bitmaskwords;
+ bfd_vma buckets_vma;
+ unsigned long hn;
+ bfd_boolean gnu_hash_error = FALSE;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, dynamic_info_DT_GNU_HASH,
+ sizeof nb)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ if (fread (nb, 16, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to read in number of buckets\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ ngnubuckets = byte_get (nb, 4);
+ gnusymidx = byte_get (nb + 4, 4);
+ bitmaskwords = byte_get (nb + 8, 4);
+ buckets_vma = dynamic_info_DT_GNU_HASH + 16;
+ if (is_32bit_elf)
+ buckets_vma += bitmaskwords * 4;
+ else
+ buckets_vma += bitmaskwords * 8;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, buckets_vma, 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ gnubuckets = get_dynamic_data (filedata, ngnubuckets, 4);
+
+ if (gnubuckets == NULL)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ for (i = 0; i < ngnubuckets; i++)
+ if (gnubuckets[i] != 0)
+ {
+ if (gnubuckets[i] < gnusymidx)
+ {
+ gnu_hash_error = TRUE;
+ return FALSE;
+ }
+
+ if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
+ maxchain = gnubuckets[i];
+ }
+
+ if (maxchain == 0xffffffff)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ maxchain -= gnusymidx;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, buckets_vma
+ + 4 * (ngnubuckets + maxchain), 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ do
+ {
+ if (fread (nb, 4, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to determine last chain length\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ if (maxchain + 1 == 0)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ ++maxchain;
+ }
+ while ((byte_get (nb, 4) & 1) == 0);
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, buckets_vma + 4 * ngnubuckets, 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ gnuchains = get_dynamic_data (filedata, maxchain, 4);
+ ngnuchains = maxchain;
+
+ if (gnuchains == NULL)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ if (dynamic_info_DT_MIPS_XHASH)
+ {
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, (buckets_vma
+ + 4 * (ngnubuckets
+ + maxchain)), 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ mipsxlat = get_dynamic_data (filedata, maxchain, 4);
+ }
+
+ for (hn = 0; hn < ngnubuckets; ++hn)
+ if (gnubuckets[hn] != 0)
+ {
+ bfd_vma si = gnubuckets[hn];
+ bfd_vma off = si - gnusymidx;
+
+ do
+ {
+ if (dynamic_info_DT_MIPS_XHASH)
+ {
+ if (mipsxlat[off] >= num_of_syms)
+ num_of_syms = mipsxlat[off] + 1;
+ }
+ else
+ {
+ if (si >= num_of_syms)
+ num_of_syms = si + 1;
+ }
+ si++;
+ }
+ while (off < ngnuchains && (gnuchains[off++] & 1) == 0);
+ }
+
+ no_gnu_hash:
+ if (gnu_hash_error)
+ {
+ if (mipsxlat)
+ {
+ free (mipsxlat);
+ mipsxlat = NULL;
+ }
+ if (gnuchains)
+ {
+ free (gnuchains);
+ gnuchains = NULL;
+ }
+ if (gnubuckets)
+ {
+ free (gnubuckets);
+ gnubuckets = NULL;
+ }
+ ngnubuckets = 0;
+ ngnuchains = 0;
+ }
+ }
+
+ return num_of_syms;
+}
+
/* Parse and display the contents of the dynamic section. */
static bfd_boolean
@@ -9892,103 +10219,117 @@ process_dynamic_section (Filedata * filedata)
}
/* Find the appropriate symbol table. */
- if (dynamic_symbols == NULL)
+ if (dynamic_symbols == NULL || do_histogram)
{
for (entry = dynamic_section;
entry < dynamic_section + dynamic_nent;
++entry)
- {
- Elf_Internal_Shdr section;
+ if (entry->d_tag == DT_SYMTAB)
+ dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
+ else if (entry->d_tag == DT_SYMENT)
+ dynamic_info[DT_SYMENT] = entry->d_un.d_val;
+ else if (entry->d_tag == DT_HASH)
+ dynamic_info[DT_HASH] = entry->d_un.d_val;
+ else if (entry->d_tag == DT_GNU_HASH)
+ dynamic_info_DT_GNU_HASH = entry->d_un.d_val;
+ else if ((filedata->file_header.e_machine == EM_MIPS
+ || filedata->file_header.e_machine == EM_MIPS_RS3_LE)
+ && entry->d_tag == DT_MIPS_XHASH)
+ {
+ dynamic_info_DT_MIPS_XHASH = entry->d_un.d_val;
+ dynamic_info_DT_GNU_HASH = entry->d_un.d_val;
+ }
- if (entry->d_tag != DT_SYMTAB)
- continue;
+ if (dynamic_info[DT_SYMTAB] && dynamic_info[DT_SYMENT])
+ {
+ Elf_Internal_Phdr *seg;
+ bfd_vma vma = dynamic_info[DT_SYMTAB];
- dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
+ if (! get_program_headers (filedata))
+ {
+ error (_("Cannot interpret virtual addresses without program headers.\n"));
+ return FALSE;
+ }
- /* Since we do not know how big the symbol table is,
- we default to reading in the entire file (!) and
- processing that. This is overkill, I know, but it
- should work. */
- section.sh_offset = offset_from_vma (filedata, entry->d_un.d_val, 0);
- if ((bfd_size_type) section.sh_offset > filedata->file_size)
- {
- /* See PR 21379 for a reproducer. */
- error (_("Invalid DT_SYMTAB entry: %lx\n"),
- (long) section.sh_offset);
- return FALSE;
- }
+ for (seg = filedata->program_headers;
+ seg < filedata->program_headers + filedata->file_header.e_phnum;
+ ++seg)
+ {
+ unsigned long num_of_syms;
- if (archive_file_offset != 0)
- section.sh_size = archive_file_size - section.sh_offset;
- else
- section.sh_size = filedata->file_size - section.sh_offset;
+ if (seg->p_type != PT_LOAD)
+ continue;
- if (is_32bit_elf)
- section.sh_entsize = sizeof (Elf32_External_Sym);
- else
- section.sh_entsize = sizeof (Elf64_External_Sym);
- section.sh_name = filedata->string_table_length;
+ if ((seg->p_offset + seg->p_filesz)
+ > filedata->file_size)
+ {
+ /* See PR 21379 for a reproducer. */
+ error (_("Invalid PT_LOAD entry\n"));
+ return FALSE;
+ }
- if (dynamic_symbols != NULL)
- {
- error (_("Multiple dynamic symbol table sections found\n"));
- free (dynamic_symbols);
- }
- dynamic_symbols = GET_ELF_SYMBOLS (filedata, §ion, & num_dynamic_syms);
- if (num_dynamic_syms < 1)
- {
- error (_("Unable to determine the number of symbols to load\n"));
- continue;
- }
- }
- }
+ if (vma >= (seg->p_vaddr & -seg->p_align)
+ && vma <= seg->p_vaddr + seg->p_filesz
+ && (num_of_syms = get_num_dynamic_syms (filedata)))
+ {
+ /* Since we do not know how big the symbol table is,
+ we default to reading in up to the end of PT_LOAD
+ segment and processing that. This is overkill, I
+ know, but it should work. */
+ Elf_Internal_Shdr section;
+ section.sh_offset = (vma - seg->p_vaddr
+ + seg->p_offset);
+ section.sh_size = (num_of_syms
+ * dynamic_info[DT_SYMENT]);
+ section.sh_entsize = dynamic_info[DT_SYMENT];
+ section.sh_name = filedata->string_table_length;
+ dynamic_symbols = GET_ELF_SYMBOLS (filedata,
+ §ion,
+ & num_dynamic_syms);
+ if (dynamic_symbols == NULL
+ || num_dynamic_syms != num_of_syms)
+ {
+ error (_("Corrupt DT_SYMTAB dynamic entry\n"));
+ return FALSE;
+ }
+ }
+ }
+ }
+ }
/* Similarly find a string table. */
if (dynamic_strings == NULL)
- {
- for (entry = dynamic_section;
- entry < dynamic_section + dynamic_nent;
- ++entry)
- {
- unsigned long offset;
- long str_tab_len;
-
- if (entry->d_tag != DT_STRTAB)
- continue;
-
+ for (entry = dynamic_section;
+ entry < dynamic_section + dynamic_nent;
+ ++entry)
+ {
+ if (entry->d_tag == DT_STRTAB)
dynamic_info[DT_STRTAB] = entry->d_un.d_val;
- /* Since we do not know how big the string table is,
- we default to reading in the entire file (!) and
- processing that. This is overkill, I know, but it
- should work. */
-
- offset = offset_from_vma (filedata, entry->d_un.d_val, 0);
-
- if (archive_file_offset != 0)
- str_tab_len = archive_file_size - offset;
- else
- str_tab_len = filedata->file_size - offset;
-
- if (str_tab_len < 1)
- {
- error
- (_("Unable to determine the length of the dynamic string table\n"));
- continue;
- }
+ if (entry->d_tag == DT_STRSZ)
+ dynamic_info[DT_STRSZ] = entry->d_un.d_val;
- if (dynamic_strings != NULL)
- {
- error (_("Multiple dynamic string tables found\n"));
- free (dynamic_strings);
- }
+ if (dynamic_info[DT_STRTAB] && dynamic_info[DT_STRSZ])
+ {
+ unsigned long offset;
+ bfd_size_type str_tab_len = dynamic_info[DT_STRSZ];
+
+ offset = offset_from_vma (filedata,
+ dynamic_info[DT_STRTAB],
+ str_tab_len);
+ dynamic_strings = (char *) get_data (NULL, filedata, offset, 1,
+ str_tab_len,
+ _("dynamic string table"));
+ if (dynamic_strings == NULL)
+ {
+ error (_("Corrupt DT_STRTAB dynamic entry\n"));
+ break;
+ }
- dynamic_strings = (char *) get_data (NULL, filedata, offset, 1,
- str_tab_len,
- _("dynamic string table"));
- dynamic_strings_length = dynamic_strings == NULL ? 0 : str_tab_len;
- }
- }
+ dynamic_strings_length = str_tab_len;
+ break;
+ }
+ }
/* And find the syminfo section if available. */
if (dynamic_syminfo == NULL)
@@ -11410,143 +11751,36 @@ get_symbol_index_type (Filedata * filedata, unsigned int type)
default:
if (type == SHN_IA_64_ANSI_COMMON
&& filedata->file_header.e_machine == EM_IA_64
- && filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
- return "ANSI_COM";
- else if ((filedata->file_header.e_machine == EM_X86_64
- || filedata->file_header.e_machine == EM_L1OM
- || filedata->file_header.e_machine == EM_K1OM)
- && type == SHN_X86_64_LCOMMON)
- return "LARGE_COM";
- else if ((type == SHN_MIPS_SCOMMON
- && filedata->file_header.e_machine == EM_MIPS)
- || (type == SHN_TIC6X_SCOMMON
- && filedata->file_header.e_machine == EM_TI_C6000))
- return "SCOM";
- else if (type == SHN_MIPS_SUNDEFINED
- && filedata->file_header.e_machine == EM_MIPS)
- return "SUND";
- else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
- sprintf (buff, "PRC[0x%04x]", type & 0xffff);
- else if (type >= SHN_LOOS && type <= SHN_HIOS)
- sprintf (buff, "OS [0x%04x]", type & 0xffff);
- else if (type >= SHN_LORESERVE)
- sprintf (buff, "RSV[0x%04x]", type & 0xffff);
- else if (type >= filedata->file_header.e_shnum)
- sprintf (buff, _("bad section index[%3d]"), type);
- else
- sprintf (buff, "%3d", type);
- break;
- }
-
- return buff;
-}
-
-static bfd_vma *
-get_dynamic_data (Filedata * filedata, bfd_size_type number, unsigned int ent_size)
-{
- unsigned char * e_data;
- bfd_vma * i_data;
-
- /* If the size_t type is smaller than the bfd_size_type, eg because
- you are building a 32-bit tool on a 64-bit host, then make sure
- that when (number) is cast to (size_t) no information is lost. */
- if (sizeof (size_t) < sizeof (bfd_size_type)
- && (bfd_size_type) ((size_t) number) != number)
- {
- error (_("Size truncation prevents reading %s elements of size %u\n"),
- bfd_vmatoa ("u", number), ent_size);
- return NULL;
- }
-
- /* Be kind to memory checkers (eg valgrind, address sanitizer) by not
- attempting to allocate memory when the read is bound to fail. */
- if (ent_size * number > filedata->file_size)
- {
- error (_("Invalid number of dynamic entries: %s\n"),
- bfd_vmatoa ("u", number));
- return NULL;
- }
-
- e_data = (unsigned char *) cmalloc ((size_t) number, ent_size);
- if (e_data == NULL)
- {
- error (_("Out of memory reading %s dynamic entries\n"),
- bfd_vmatoa ("u", number));
- return NULL;
- }
-
- if (fread (e_data, ent_size, (size_t) number, filedata->handle) != number)
- {
- error (_("Unable to read in %s bytes of dynamic data\n"),
- bfd_vmatoa ("u", number * ent_size));
- free (e_data);
- return NULL;
- }
-
- i_data = (bfd_vma *) cmalloc ((size_t) number, sizeof (*i_data));
- if (i_data == NULL)
- {
- error (_("Out of memory allocating space for %s dynamic entries\n"),
- bfd_vmatoa ("u", number));
- free (e_data);
- return NULL;
- }
-
- while (number--)
- i_data[number] = byte_get (e_data + number * ent_size, ent_size);
-
- free (e_data);
-
- return i_data;
-}
-
-static void
-print_dynamic_symbol (Filedata * filedata, bfd_vma si, unsigned long hn)
-{
- Elf_Internal_Sym * psym;
- int n;
-
- n = print_vma (si, DEC_5);
- if (n < 5)
- fputs (&" "[n], stdout);
- printf (" %3lu: ", hn);
-
- if (dynamic_symbols == NULL || si >= num_dynamic_syms)
- {
- printf (_("<No info available for dynamic symbol number %lu>\n"),
- (unsigned long) si);
- return;
- }
-
- psym = dynamic_symbols + si;
- print_vma (psym->st_value, LONG_HEX);
- putchar (' ');
- print_vma (psym->st_size, DEC_5);
-
- printf (" %-7s", get_symbol_type (filedata, ELF_ST_TYPE (psym->st_info)));
- printf (" %-6s", get_symbol_binding (filedata, ELF_ST_BIND (psym->st_info)));
-
- if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
- printf (" %-7s", get_solaris_symbol_visibility (psym->st_other));
- else
- {
- unsigned int vis = ELF_ST_VISIBILITY (psym->st_other);
-
- printf (" %-7s", get_symbol_visibility (vis));
- /* Check to see if any other bits in the st_other field are set.
- Note - displaying this information disrupts the layout of the
- table being generated, but for the moment this case is very
- rare. */
- if (psym->st_other ^ vis)
- printf (" [%s] ", get_symbol_other (filedata, psym->st_other ^ vis));
+ && filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
+ return "ANSI_COM";
+ else if ((filedata->file_header.e_machine == EM_X86_64
+ || filedata->file_header.e_machine == EM_L1OM
+ || filedata->file_header.e_machine == EM_K1OM)
+ && type == SHN_X86_64_LCOMMON)
+ return "LARGE_COM";
+ else if ((type == SHN_MIPS_SCOMMON
+ && filedata->file_header.e_machine == EM_MIPS)
+ || (type == SHN_TIC6X_SCOMMON
+ && filedata->file_header.e_machine == EM_TI_C6000))
+ return "SCOM";
+ else if (type == SHN_MIPS_SUNDEFINED
+ && filedata->file_header.e_machine == EM_MIPS)
+ return "SUND";
+ else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
+ sprintf (buff, "PRC[0x%04x]", type & 0xffff);
+ else if (type >= SHN_LOOS && type <= SHN_HIOS)
+ sprintf (buff, "OS [0x%04x]", type & 0xffff);
+ else if (type >= SHN_LORESERVE)
+ sprintf (buff, "RSV[0x%04x]", type & 0xffff);
+ else if (filedata->file_header.e_shnum != 0
+ && type >= filedata->file_header.e_shnum)
+ sprintf (buff, _("bad section index[%3d]"), type);
+ else
+ sprintf (buff, "%3d", type);
+ break;
}
- printf (" %3.3s ", get_symbol_index_type (filedata, psym->st_shndx));
- if (VALID_DYNAMIC_NAME (psym->st_name))
- print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
- else
- printf (_(" <corrupt: %14ld>"), psym->st_name);
- putchar ('\n');
+ return buff;
}
static const char *
@@ -11722,214 +11956,78 @@ get_symbol_version_string (Filedata * filedata,
return NULL;
}
-/* Dump the symbol table. */
-static bfd_boolean
-process_symbol_table (Filedata * filedata)
+static void
+print_dynamic_symbol (Filedata *filedata, unsigned long si,
+ Elf_Internal_Sym *symtab,
+ Elf_Internal_Shdr *section,
+ char *strtab, size_t strtab_size)
{
- Elf_Internal_Shdr * section;
- bfd_size_type nbuckets = 0;
- bfd_size_type nchains = 0;
- bfd_vma * buckets = NULL;
- bfd_vma * chains = NULL;
- bfd_vma ngnubuckets = 0;
- bfd_vma * gnubuckets = NULL;
- bfd_vma * gnuchains = NULL;
- bfd_vma * mipsxlat = NULL;
- bfd_vma gnusymidx = 0;
- bfd_size_type ngnuchains = 0;
-
- if (!do_syms && !do_dyn_syms && !do_histogram)
- return TRUE;
+ const char *version_string;
+ enum versioned_symbol_info sym_info;
+ unsigned short vna_other;
+ Elf_Internal_Sym *psym = symtab + si;
- if (dynamic_info[DT_HASH]
- && (do_histogram
- || (do_using_dynamic
- && !do_dyn_syms
- && dynamic_strings != NULL)))
+ printf ("%6ld: ", si);
+ print_vma (psym->st_value, LONG_HEX);
+ putchar (' ');
+ print_vma (psym->st_size, DEC_5);
+ printf (" %-7s", get_symbol_type (filedata, ELF_ST_TYPE (psym->st_info)));
+ printf (" %-6s", get_symbol_binding (filedata, ELF_ST_BIND (psym->st_info)));
+ if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
+ printf (" %-7s", get_solaris_symbol_visibility (psym->st_other));
+ else
{
- unsigned char nb[8];
- unsigned char nc[8];
- unsigned int hash_ent_size = 4;
-
- if ((filedata->file_header.e_machine == EM_ALPHA
- || filedata->file_header.e_machine == EM_S390
- || filedata->file_header.e_machine == EM_S390_OLD)
- && filedata->file_header.e_ident[EI_CLASS] == ELFCLASS64)
- hash_ent_size = 8;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, dynamic_info[DT_HASH],
- sizeof nb + sizeof nc)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_hash;
- }
-
- if (fread (nb, hash_ent_size, 1, filedata->handle) != 1)
- {
- error (_("Failed to read in number of buckets\n"));
- goto no_hash;
- }
-
- if (fread (nc, hash_ent_size, 1, filedata->handle) != 1)
- {
- error (_("Failed to read in number of chains\n"));
- goto no_hash;
- }
-
- nbuckets = byte_get (nb, hash_ent_size);
- nchains = byte_get (nc, hash_ent_size);
-
- buckets = get_dynamic_data (filedata, nbuckets, hash_ent_size);
- chains = get_dynamic_data (filedata, nchains, hash_ent_size);
+ unsigned int vis = ELF_ST_VISIBILITY (psym->st_other);
- if (buckets == NULL || chains == NULL)
- {
- no_hash:
- free (buckets);
- free (chains);
- buckets = NULL;
- chains = NULL;
- nbuckets = 0;
- nchains = 0;
- if (do_using_dynamic)
- goto err_out;
- }
+ printf (" %-7s", get_symbol_visibility (vis));
+ /* Check to see if any other bits in the st_other field are set.
+ Note - displaying this information disrupts the layout of the
+ table being generated, but for the moment this case is very rare. */
+ if (psym->st_other ^ vis)
+ printf (" [%s] ", get_symbol_other (filedata, psym->st_other ^ vis));
}
-
- if (dynamic_info_DT_GNU_HASH
- && (do_histogram
- || (do_using_dynamic
- && !do_dyn_syms
- && dynamic_strings != NULL)))
- {
- unsigned char nb[16];
- bfd_vma i, maxchain = 0xffffffff, bitmaskwords;
- bfd_vma buckets_vma;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, dynamic_info_DT_GNU_HASH,
- sizeof nb)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- if (fread (nb, 16, 1, filedata->handle) != 1)
- {
- error (_("Failed to read in number of buckets\n"));
- goto no_gnu_hash;
- }
-
- ngnubuckets = byte_get (nb, 4);
- gnusymidx = byte_get (nb + 4, 4);
- bitmaskwords = byte_get (nb + 8, 4);
- buckets_vma = dynamic_info_DT_GNU_HASH + 16;
- if (is_32bit_elf)
- buckets_vma += bitmaskwords * 4;
+ printf (" %4s ", get_symbol_index_type (filedata, psym->st_shndx));
+ print_symbol (25, VALID_SYMBOL_NAME (strtab, strtab_size,
+ psym->st_name)
+ ? strtab + psym->st_name : _("<corrupt>"));
+
+ version_string
+ = get_symbol_version_string (filedata,
+ (section == NULL
+ || section->sh_type == SHT_DYNSYM),
+ strtab, strtab_size, si,
+ psym, &sym_info, &vna_other);
+ if (version_string)
+ {
+ if (sym_info == symbol_undefined)
+ printf ("@%s (%d)", version_string, vna_other);
else
- buckets_vma += bitmaskwords * 8;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, buckets_vma, 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- gnubuckets = get_dynamic_data (filedata, ngnubuckets, 4);
-
- if (gnubuckets == NULL)
- goto no_gnu_hash;
-
- for (i = 0; i < ngnubuckets; i++)
- if (gnubuckets[i] != 0)
- {
- if (gnubuckets[i] < gnusymidx)
- goto err_out;
-
- if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
- maxchain = gnubuckets[i];
- }
-
- if (maxchain == 0xffffffff)
- goto no_gnu_hash;
-
- maxchain -= gnusymidx;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, buckets_vma
- + 4 * (ngnubuckets + maxchain), 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- do
- {
- if (fread (nb, 4, 1, filedata->handle) != 1)
- {
- error (_("Failed to determine last chain length\n"));
- goto no_gnu_hash;
- }
-
- if (maxchain + 1 == 0)
- goto no_gnu_hash;
-
- ++maxchain;
- }
- while ((byte_get (nb, 4) & 1) == 0);
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, buckets_vma + 4 * ngnubuckets, 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
+ printf (sym_info == symbol_hidden ? "@%s" : "@@%s",
+ version_string);
+ }
- gnuchains = get_dynamic_data (filedata, maxchain, 4);
- ngnuchains = maxchain;
+ putchar ('\n');
- if (gnuchains == NULL)
- goto no_gnu_hash;
+ if (ELF_ST_BIND (psym->st_info) == STB_LOCAL
+ && section != NULL
+ && si >= section->sh_info
+ /* Irix 5 and 6 MIPS binaries are known to ignore this requirement. */
+ && filedata->file_header.e_machine != EM_MIPS
+ /* Solaris binaries have been found to violate this requirement as
+ well. Not sure if this is a bug or an ABI requirement. */
+ && filedata->file_header.e_ident[EI_OSABI] != ELFOSABI_SOLARIS)
+ warn (_("local symbol %lu found at index >= %s's sh_info value of %u\n"),
+ si, printable_section_name (filedata, section), section->sh_info);
+}
- if (dynamic_info_DT_MIPS_XHASH)
- {
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, (buckets_vma
- + 4 * (ngnubuckets
- + maxchain)), 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
+/* Dump the symbol table. */
+static bfd_boolean
+process_symbol_table (Filedata * filedata)
+{
+ Elf_Internal_Shdr * section;
- mipsxlat = get_dynamic_data (filedata, maxchain, 4);
- if (mipsxlat == NULL)
- {
- no_gnu_hash:
- free (gnuchains);
- gnuchains = NULL;
- free (gnubuckets);
- gnubuckets = NULL;
- ngnubuckets = 0;
- if (do_using_dynamic)
- goto err_out;
- }
- }
- }
+ if (!do_syms && !do_dyn_syms && !do_histogram)
+ return TRUE;
if ((dynamic_info[DT_HASH] || dynamic_info_DT_GNU_HASH)
&& do_syms
@@ -11937,63 +12035,19 @@ process_symbol_table (Filedata * filedata)
&& dynamic_strings != NULL
&& dynamic_symbols != NULL)
{
- unsigned long hn;
-
- if (dynamic_info[DT_HASH])
- {
- bfd_vma si;
- char *visited;
-
- printf (_("\nSymbol table for image:\n"));
- if (is_32bit_elf)
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
- else
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
-
- visited = xcmalloc (nchains, 1);
- memset (visited, 0, nchains);
- for (hn = 0; hn < nbuckets; hn++)
- {
- for (si = buckets[hn]; si > 0; si = chains[si])
- {
- print_dynamic_symbol (filedata, si, hn);
- if (si >= nchains || visited[si])
- {
- error (_("histogram chain is corrupt\n"));
- break;
- }
- visited[si] = 1;
- }
- }
- free (visited);
- }
+ unsigned long si;
- if (dynamic_info_DT_GNU_HASH)
- {
- printf (_("\nSymbol table of `%s' for image:\n"),
- GNU_HASH_SECTION_NAME);
- if (is_32bit_elf)
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
- else
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
-
- for (hn = 0; hn < ngnubuckets; ++hn)
- if (gnubuckets[hn] != 0)
- {
- bfd_vma si = gnubuckets[hn];
- bfd_vma off = si - gnusymidx;
+ printf (ngettext ("\nSymbol table for image contains %lu entry:\n",
+ "\nSymbol table for image contains %lu entries:\n",
+ num_dynamic_syms), num_dynamic_syms);
+ if (is_32bit_elf)
+ printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
+ else
+ printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
- do
- {
- if (dynamic_info_DT_MIPS_XHASH)
- print_dynamic_symbol (filedata, mipsxlat[off], hn);
- else
- print_dynamic_symbol (filedata, si, hn);
- si++;
- }
- while (off < ngnuchains && (gnuchains[off++] & 1) == 0);
- }
- }
+ for (si = 0; si < num_dynamic_syms; si++)
+ print_dynamic_symbol (filedata, si, dynamic_symbols, NULL,
+ dynamic_strings, dynamic_strings_length);
}
else if ((do_dyn_syms || (do_syms && !do_using_dynamic))
&& filedata->section_headers != NULL)
@@ -12007,7 +12061,6 @@ process_symbol_table (Filedata * filedata)
char * strtab = NULL;
unsigned long int strtab_size = 0;
Elf_Internal_Sym * symtab;
- Elf_Internal_Sym * psym;
unsigned long si, num_syms;
if ((section->sh_type != SHT_SYMTAB
@@ -12056,61 +12109,9 @@ process_symbol_table (Filedata * filedata)
strtab_size = strtab != NULL ? string_sec->sh_size : 0;
}
- 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 ("%6ld: ", si);
- print_vma (psym->st_value, LONG_HEX);
- putchar (' ');
- print_vma (psym->st_size, DEC_5);
- printf (" %-7s", get_symbol_type (filedata, ELF_ST_TYPE (psym->st_info)));
- printf (" %-6s", get_symbol_binding (filedata, ELF_ST_BIND (psym->st_info)));
- if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
- printf (" %-7s", get_solaris_symbol_visibility (psym->st_other));
- else
- {
- unsigned int vis = ELF_ST_VISIBILITY (psym->st_other);
-
- printf (" %-7s", get_symbol_visibility (vis));
- /* Check to see if any other bits in the st_other field are set.
- Note - displaying this information disrupts the layout of the
- table being generated, but for the moment this case is very rare. */
- if (psym->st_other ^ vis)
- printf (" [%s] ", get_symbol_other (filedata, psym->st_other ^ vis));
- }
- printf (" %4s ", get_symbol_index_type (filedata, psym->st_shndx));
- print_symbol (25, psym->st_name < strtab_size
- ? strtab + psym->st_name : _("<corrupt>"));
-
- version_string
- = get_symbol_version_string (filedata,
- section->sh_type == SHT_DYNSYM,
- strtab, strtab_size, si,
- psym, &sym_info, &vna_other);
- if (version_string)
- {
- if (sym_info == symbol_undefined)
- printf ("@%s (%d)", version_string, vna_other);
- else
- printf (sym_info == symbol_hidden ? "@%s" : "@@%s",
- version_string);
- }
-
- putchar ('\n');
-
- if (ELF_ST_BIND (psym->st_info) == STB_LOCAL
- && si >= section->sh_info
- /* Irix 5 and 6 MIPS binaries are known to ignore this requirement. */
- && filedata->file_header.e_machine != EM_MIPS
- /* Solaris binaries have been found to violate this requirement as
- well. Not sure if this is a bug or an ABI requirement. */
- && filedata->file_header.e_ident[EI_OSABI] != ELFOSABI_SOLARIS)
- warn (_("local symbol %lu found at index >= %s's sh_info value of %u\n"),
- si, printable_section_name (filedata, section), section->sh_info);
- }
+ for (si = 0; si < num_syms; si++)
+ print_dynamic_symbol (filedata, si, symtab, section,
+ strtab, strtab_size);
free (symtab);
if (strtab != filedata->string_table)
diff --git a/ld/testsuite/ld-elf/hash.d b/ld/testsuite/ld-elf/hash.d
index efe675e0c7..a0bebb0b00 100644
--- a/ld/testsuite/ld-elf/hash.d
+++ b/ld/testsuite/ld-elf/hash.d
@@ -9,11 +9,11 @@
#...
+0x[0-9a-z]+ +\(GNU_HASH\) +0x[0-9a-z]+
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] _start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] _start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] main
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] main
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] __start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] __start
#...
diff --git a/ld/testsuite/ld-elf/pr13195.d b/ld/testsuite/ld-elf/pr13195.d
index 8a0f9bd805..7e45f08b33 100644
--- a/ld/testsuite/ld-elf/pr13195.d
+++ b/ld/testsuite/ld-elf/pr13195.d
@@ -5,5 +5,5 @@
# generic linker targets don't support --gc-sections, nor do a bunch of others
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[1-9]+ foo
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[1-9]+ foo@@VERS_2.0
#pass
diff --git a/ld/testsuite/ld-elfvsb/hidden2.d b/ld/testsuite/ld-elfvsb/hidden2.d
index 72a42d57bc..5d299746f5 100644
--- a/ld/testsuite/ld-elfvsb/hidden2.d
+++ b/ld/testsuite/ld-elfvsb/hidden2.d
@@ -3,7 +3,7 @@
#readelf: -Ds
# It is also ok to remove this symbol, but we currently make it local.
-Symbol table for image:
+Symbol table for image contains [0-9]+ entries:
#...
-[ ]*[0-9]+ +[0-9]+: [0-9a-fA-F]* +0 +OBJECT +LOCAL +DEFAULT .* foo
+[ ]*[0-9]+: [0-9a-fA-F]* +0 +OBJECT +LOCAL +DEFAULT .* foo
#pass
diff --git a/ld/testsuite/ld-mips-elf/hash2.d b/ld/testsuite/ld-mips-elf/hash2.d
index 122edb80e1..a0fe4266f2 100644
--- a/ld/testsuite/ld-mips-elf/hash2.d
+++ b/ld/testsuite/ld-mips-elf/hash2.d
@@ -6,11 +6,11 @@
#...
+0x[0-9a-z]+ +\(MIPS_XHASH\) +0x[0-9a-z]+
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) _start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) __start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) main
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) _start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) main
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) __start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) start
#...
--
2.25.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* PING [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms table
2020-03-22 12:34 ` H.J. Lu
@ 2020-04-09 13:01 ` H.J. Lu
2020-04-09 14:43 ` Nick Clifton
0 siblings, 1 reply; 11+ messages in thread
From: H.J. Lu @ 2020-04-09 13:01 UTC (permalink / raw)
To: Binutils, Nick Clifton, Alan Modra
On Sun, Mar 22, 2020 at 5:34 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Thu, Mar 19, 2020 at 5:51 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Thu, Mar 12, 2020 at 06:23:34AM -0700, H.J. Lu wrote:
> > > When reconstructing dynamic symbol table from the PT_DYNAMIC segment,
> > > compute dynamic symbol table size from hash table. For DT_HASH, the
> > > number of dynamic symbol table entries equals the number of chains.
> > > For DT_GNU_HASH/DT_MIPS_XHASH, only defined symbols with non-STB_LOCAL
> > > indings are in hash table. Since DT_GNU_HASH/DT_MIPS_XHASH place all
> > > symbols with STB_LOCAL binding before symbols with other bindings and
> > > all undefined symbols defined ones in dynamic symbol table, the highest
> > > symbol index in DT_GNU_HASH/DT_MIPS_XHASH is the highest dynamic symbol
> > > table index.
> > >
> > > Also iterate dynamic symbol table to print each entry so that output
> > > of "readelf -D -s" without section header is similar to "readelf -s"
> > > with section header.
> > > `
> >
> > Here is the updated patch to make --syms --use-dynamic output almost
> > identical with --dyn-syms. On Linux/x86-64, I got
> >
> > [hjl@gnu-cfl-2 pr25617]$ ./readelf -D -s /lib64/libc.so.6 > 1
> > [hjl@gnu-cfl-2 pr25617]$ ./readelf --dyn-syms /lib64/libc.so.6 > 2
> > [hjl@gnu-cfl-2 pr25617]$ diff -up 1 2
> > --- 1 2020-03-19 05:50:11.367432099 -0700
> > +++ 2 2020-03-19 05:50:20.265739131 -0700
> > @@ -1,5 +1,5 @@
> >
> > -Symbol table for image contains 2369 entries:
> > +Symbol table '.dynsym' contains 2369 entries:
> > Num: Value Size Type Bind Vis Ndx Name
> > 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
> > 1: 0000000000000000 0 OBJECT WEAK DEFAULT UND _dl_starting_up@GLIBC_PRIVATE (33)
> > [hjl@gnu-cfl-2 pr25617]$
> >
> > Any comments, objections?
> >
> > Thanks.
> >
> > H.J.
> > ---
> > When reconstructing dynamic symbol table from the PT_DYNAMIC segment,
> > compute dynamic symbol table size from hash table. For DT_HASH, the
> > number of dynamic symbol table entries equals the number of chains.
> > For DT_GNU_HASH/DT_MIPS_XHASH, only defined symbols with non-STB_LOCAL
> > indings are in hash table. Since DT_GNU_HASH/DT_MIPS_XHASH place all
> > symbols with STB_LOCAL binding before symbols with other bindings and
> > all undefined symbols defined ones in dynamic symbol table, the highest
> > symbol index in DT_GNU_HASH/DT_MIPS_XHASH is the highest dynamic symbol
> > table index.
> >
> > Rewrite print_dynamic_symbol to dump dynamic symbol table for --dyn-syms
> > and --syms --use-dynamic.
> >
> > binutils/
> >
> > * readelf.c (nbuckets): New.
> > (nchains): Likewise.
> > (buckets): Likewise.
> > (chains): Likewise.
> > (ngnubuckets): Likewise.
> > (gnubuckets): Likewise.
> > (gnuchains): Likewise.
> > (mipsxlat): Likewise.
> > (ngnuchains): Likewise.
> > (gnusymidx): Likewise.
> > (VALID_SYMBOL_NAME): Likewise.
> > (VALID_DYNAMIC_NAME): Use it.
> > (get_dynamic_data): Moved before process_dynamic_section.
> > (get_num_dynamic_syms): New function.
> > (process_dynamic_section): Use DT_SYMTAB, DT_SYMENT, DT_HASH,
> > DT_GNU_HASH and DT_MIPS_XHASH to reconstruct dynamic symbol
> > table. Use DT_STRTAB and DT_STRSZ to reconstruct dynamic string
> > table.
> > (get_symbol_index_type): Don't print "bad section index" when
> > there is no section header.
> > (print_dynamic_symbol): Rewrite.
> > (process_symbol_table): Call print_dynamic_symbol to dump dynamic
> > symbol table.
> >
> > ld/
> >
> > * testsuite/ld-elf/hash.d: Updated.
> > * testsuite/ld-elf/pr13195.d: Likewise.
> > * testsuite/ld-elfvsb/hidden2.d: Likewise.
> > * testsuite/ld-mips-elf/hash2.d: Likewise.
>
> I opened:
>
> https://sourceware.org/bugzilla/show_bug.cgi?id=25707
>
Hi Nick, Alan,
Can you take a look at
https://sourceware.org/pipermail/binutils/2020-March/000234.html
Thanks.
--
H.J.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: PING [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms table
2020-04-09 13:01 ` PING " H.J. Lu
@ 2020-04-09 14:43 ` Nick Clifton
2020-04-09 17:35 ` Fangrui Song
2020-04-09 17:51 ` V2 " H.J. Lu
0 siblings, 2 replies; 11+ messages in thread
From: Nick Clifton @ 2020-04-09 14:43 UTC (permalink / raw)
To: H.J. Lu, Binutils, Alan Modra
Hi H.J.
> Can you take a look at
> https://sourceware.org/pipermail/binutils/2020-March/000234.html
Generally the patch looks fine to me, but ... there appear to be some
linker testsuite regressions for various targets:
mips-elf: LD REGRESSION: ld-mips-elf/hash2 [and other mips based targets]
arm-nto: LD REGRESSION: Thumb shared library with ARM [and other arm based targets]
LD REGRESSION: Mixed ARM/Thumb shared library
LD REGRESSION: Mixed ARM/Thumb dynamic application
LD REGRESSION: Mixed ARM/Thumb arch5 dynamic application
A quick look suggests that these are all due to readelf's output
changing slightly and the tests not expecting the new format.
Could you take a look and tweak the tests as necessary please ?
Cheers
Nick
PS. Hmm, just noticed that you had already patched the ld-mips-elf/hash2
test, so I am wondering why it is failing. The entry in ld.log looks like
this:
Executing on host: sh -c {readelf -d -s -D tmpdir/dump > tmpdir/dump.out 2>dump.tmp} /dev/null (timeout = 300)
spawn [open ...]
extra regexps in ld/testsuite/ld-mips-elf/hash2.d starting with "^ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) __start$"
EOF from tmpdir/dump.out
FAIL: ld-mips-elf/hash2
Is it possible that your revision of the original patch now makes this test fail ?
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: PING [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms table
2020-04-09 14:43 ` Nick Clifton
@ 2020-04-09 17:35 ` Fangrui Song
2020-04-09 17:52 ` H.J. Lu
2020-04-09 17:51 ` V2 " H.J. Lu
1 sibling, 1 reply; 11+ messages in thread
From: Fangrui Song @ 2020-04-09 17:35 UTC (permalink / raw)
To: H.J. Lu; +Cc: Alan Modra, Binutils
On 2020-04-09, Nick Clifton via Binutils wrote:
>Hi H.J.
>
>> Can you take a look at
>> https://sourceware.org/pipermail/binutils/2020-March/000234.html
>
>Generally the patch looks fine to me, but ... there appear to be some
>linker testsuite regressions for various targets:
>
> mips-elf: LD REGRESSION: ld-mips-elf/hash2 [and other mips based targets]
>
> arm-nto: LD REGRESSION: Thumb shared library with ARM [and other arm based targets]
> LD REGRESSION: Mixed ARM/Thumb shared library
> LD REGRESSION: Mixed ARM/Thumb dynamic application
> LD REGRESSION: Mixed ARM/Thumb arch5 dynamic application
>
>A quick look suggests that these are all due to readelf's output
>changing slightly and the tests not expecting the new format.
>
>Could you take a look and tweak the tests as necessary please ?
>
>Cheers
> Nick
>
>PS. Hmm, just noticed that you had already patched the ld-mips-elf/hash2
>test, so I am wondering why it is failing. The entry in ld.log looks like
>this:
>
> Executing on host: sh -c {readelf -d -s -D tmpdir/dump > tmpdir/dump.out 2>dump.tmp} /dev/null (timeout = 300)
> spawn [open ...]
>
> extra regexps in ld/testsuite/ld-mips-elf/hash2.d starting with "^ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) __start$"
> EOF from tmpdir/dump.out
> FAIL: ld-mips-elf/hash2
>
>Is it possible that your revision of the original patch now makes this test fail ?
>
My understanding is that readelf -D --dyn-syms still uses the section
header table (inferred from the output: `Symbol table '.dynsym'`, not `from image`)
Should -D --dyn-syms decode the dynamic symbol table via DT_SYMTAB as well?
As a possible future enhancement, when DT_SYMTAB and SHT_DYNSYM disagree
with the location, a warning can be issued.
(llvm-readelf >= 10 can print
warning: '[[FILE]]': SHT_DYNSYM section header and DT_SYMTAB disagree about the location of the dynamic symbol table
llvm-readelf >= 11 will have more diagnostics:
warning: '[[FILE]]': hash table nchain (93) differs from symbol count derived from SHT_DYNSYM section header (1)
)
^ permalink raw reply [flat|nested] 11+ messages in thread
* V2 [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms table
2020-04-09 14:43 ` Nick Clifton
2020-04-09 17:35 ` Fangrui Song
@ 2020-04-09 17:51 ` H.J. Lu
2020-04-14 10:47 ` Nick Clifton
2020-04-15 3:18 ` Alan Modra
1 sibling, 2 replies; 11+ messages in thread
From: H.J. Lu @ 2020-04-09 17:51 UTC (permalink / raw)
To: Nick Clifton; +Cc: Binutils, Alan Modra
[-- Attachment #1: Type: text/plain, Size: 1626 bytes --]
On Thu, Apr 9, 2020 at 7:44 AM Nick Clifton <nickc@redhat.com> wrote:
>
> Hi H.J.
>
> > Can you take a look at
> > https://sourceware.org/pipermail/binutils/2020-March/000234.html
>
> Generally the patch looks fine to me, but ... there appear to be some
> linker testsuite regressions for various targets:
>
> mips-elf: LD REGRESSION: ld-mips-elf/hash2 [and other mips based targets]
>
> arm-nto: LD REGRESSION: Thumb shared library with ARM [and other arm based targets]
> LD REGRESSION: Mixed ARM/Thumb shared library
> LD REGRESSION: Mixed ARM/Thumb dynamic application
> LD REGRESSION: Mixed ARM/Thumb arch5 dynamic application
Fixed.
> A quick look suggests that these are all due to readelf's output
> changing slightly and the tests not expecting the new format.
>
> Could you take a look and tweak the tests as necessary please ?
>
> Cheers
> Nick
>
> PS. Hmm, just noticed that you had already patched the ld-mips-elf/hash2
> test, so I am wondering why it is failing. The entry in ld.log looks like
> this:
>
> Executing on host: sh -c {readelf -d -s -D tmpdir/dump > tmpdir/dump.out 2>dump.tmp} /dev/null (timeout = 300)
> spawn [open ...]
>
> extra regexps in ld/testsuite/ld-mips-elf/hash2.d starting with "^ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) __start$"
> EOF from tmpdir/dump.out
> FAIL: ld-mips-elf/hash2
>
> Is it possible that your revision of the original patch now makes this test fail ?
>
readelf never outputs PRC. It outputs PRC[0xff02]. It is
fixed in this updated version. OK for master?
--
H.J.
[-- Attachment #2: 0001-readelf-Consolidate-syms-use-dynamic-with-dyn-syms.patch --]
[-- Type: text/x-patch, Size: 59605 bytes --]
From ffe2ec9ee5bb365176615eab778dfc89b75c6c71 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 4 Mar 2020 15:58:13 -0800
Subject: [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms
When reconstructing dynamic symbol table from the PT_DYNAMIC segment,
compute dynamic symbol table size from hash table. For DT_HASH, the
number of dynamic symbol table entries equals the number of chains.
For DT_GNU_HASH/DT_MIPS_XHASH, only defined symbols with non-STB_LOCAL
indings are in hash table. Since DT_GNU_HASH/DT_MIPS_XHASH place all
symbols with STB_LOCAL binding before symbols with other bindings and
all undefined symbols defined ones in dynamic symbol table, the highest
symbol index in DT_GNU_HASH/DT_MIPS_XHASH is the highest dynamic symbol
table index.
Rewrite print_dynamic_symbol to dump dynamic symbol table for --dyn-syms
and --syms --use-dynamic.
binutils/
PR binutils/25707
* readelf.c (nbuckets): New.
(nchains): Likewise.
(buckets): Likewise.
(chains): Likewise.
(ngnubuckets): Likewise.
(gnubuckets): Likewise.
(gnuchains): Likewise.
(mipsxlat): Likewise.
(ngnuchains): Likewise.
(gnusymidx): Likewise.
(VALID_SYMBOL_NAME): Likewise.
(VALID_DYNAMIC_NAME): Use it.
(get_dynamic_data): Moved before process_dynamic_section.
(get_num_dynamic_syms): New function.
(process_dynamic_section): Use DT_SYMTAB, DT_SYMENT, DT_HASH,
DT_GNU_HASH and DT_MIPS_XHASH to reconstruct dynamic symbol
table. Use DT_STRTAB and DT_STRSZ to reconstruct dynamic string
table.
(get_symbol_index_type): Don't print "bad section index" when
there is no section header.
(print_dynamic_symbol): Rewrite.
(process_symbol_table): Call print_dynamic_symbol to dump dynamic
symbol table.
ld/
PR binutils/25707
* testsuite/ld-arm/armthumb-lib.sym: Updated.
* testsuite/ld-arm/farcall-mixed-app.sym: Likewise.
* testsuite/ld-arm/farcall-mixed-app2.sym: Likewise.
* testsuite/ld-arm/fdpic-main-m.sym: Likewise.
* testsuite/ld-arm/fdpic-main.sym: Likewise.
* testsuite/ld-arm/fdpic-shared-m.sym: Likewise.
* testsuite/ld-arm/fdpic-shared.sym: Likewise.
* testsuite/ld-arm/mixed-app.sym: Likewise.
* testsuite/ld-arm/mixed-lib.sym: Likewise.
* testsuite/ld-arm/preempt-app.sym: Likewise.
* testsuite/ld-elf/hash.d: Likewise.
* testsuite/ld-elf/pr13195.d: Likewise.
* testsuite/ld-elfvsb/hidden2.d: Likewise.
* testsuite/ld-mips-elf/hash2.d: Likewise.
---
binutils/readelf.c | 1051 ++++++++++----------
ld/testsuite/ld-arm/armthumb-lib.sym | 29 +-
ld/testsuite/ld-arm/farcall-mixed-app.sym | 29 +-
ld/testsuite/ld-arm/farcall-mixed-app2.sym | 29 +-
ld/testsuite/ld-arm/fdpic-main-m.sym | 27 +-
ld/testsuite/ld-arm/fdpic-main.sym | 27 +-
ld/testsuite/ld-arm/fdpic-shared-m.sym | 29 +-
ld/testsuite/ld-arm/fdpic-shared.sym | 29 +-
ld/testsuite/ld-arm/mixed-app.sym | 29 +-
ld/testsuite/ld-arm/mixed-lib.sym | 29 +-
ld/testsuite/ld-arm/preempt-app.sym | 27 +-
ld/testsuite/ld-elf/hash.d | 8 +-
ld/testsuite/ld-elf/pr13195.d | 2 +-
ld/testsuite/ld-elfvsb/hidden2.d | 4 +-
ld/testsuite/ld-mips-elf/hash2.d | 8 +-
15 files changed, 684 insertions(+), 673 deletions(-)
diff --git a/binutils/readelf.c b/binutils/readelf.c
index eb41e10dae..cd456b0290 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -226,6 +226,16 @@ static size_t dynamic_nent;
static char * dynamic_strings;
static unsigned long dynamic_strings_length;
static unsigned long num_dynamic_syms;
+static bfd_size_type nbuckets;
+static bfd_size_type nchains;
+static bfd_vma *buckets;
+static bfd_vma *chains;
+static bfd_vma ngnubuckets;
+static bfd_vma *gnubuckets;
+static bfd_vma *gnuchains;
+static bfd_vma *mipsxlat;
+static bfd_size_type ngnuchains;
+static bfd_vma gnusymidx;
static Elf_Internal_Sym * dynamic_symbols;
static Elf_Internal_Syminfo * dynamic_syminfo;
static unsigned long dynamic_syminfo_offset;
@@ -325,7 +335,10 @@ static const char * get_symbol_version_string
(is_32bit_elf ? get_32bit_elf_symbols (file, section, sym_count) \
: get_64bit_elf_symbols (file, section, sym_count))
-#define VALID_DYNAMIC_NAME(offset) ((dynamic_strings != NULL) && (offset < dynamic_strings_length))
+#define VALID_SYMBOL_NAME(strtab, strtab_size, offset) \
+ (strtab != NULL && offset < strtab_size)
+#define VALID_DYNAMIC_NAME(offset) \
+ VALID_SYMBOL_NAME (dynamic_strings, dynamic_strings_length, offset)
/* GET_DYNAMIC_NAME asssumes that VALID_DYNAMIC_NAME has
already been called and verified that the string exists. */
#define GET_DYNAMIC_NAME(offset) (dynamic_strings + offset)
@@ -9865,6 +9878,320 @@ print_dynamic_flags (bfd_vma flags)
puts ("");
}
+static bfd_vma *
+get_dynamic_data (Filedata * filedata, bfd_size_type number, unsigned int ent_size)
+{
+ unsigned char * e_data;
+ bfd_vma * i_data;
+
+ /* If the size_t type is smaller than the bfd_size_type, eg because
+ you are building a 32-bit tool on a 64-bit host, then make sure
+ that when (number) is cast to (size_t) no information is lost. */
+ if (sizeof (size_t) < sizeof (bfd_size_type)
+ && (bfd_size_type) ((size_t) number) != number)
+ {
+ error (_("Size truncation prevents reading %s elements of size %u\n"),
+ bfd_vmatoa ("u", number), ent_size);
+ return NULL;
+ }
+
+ /* Be kind to memory checkers (eg valgrind, address sanitizer) by not
+ attempting to allocate memory when the read is bound to fail. */
+ if (ent_size * number > filedata->file_size)
+ {
+ error (_("Invalid number of dynamic entries: %s\n"),
+ bfd_vmatoa ("u", number));
+ return NULL;
+ }
+
+ e_data = (unsigned char *) cmalloc ((size_t) number, ent_size);
+ if (e_data == NULL)
+ {
+ error (_("Out of memory reading %s dynamic entries\n"),
+ bfd_vmatoa ("u", number));
+ return NULL;
+ }
+
+ if (fread (e_data, ent_size, (size_t) number, filedata->handle) != number)
+ {
+ error (_("Unable to read in %s bytes of dynamic data\n"),
+ bfd_vmatoa ("u", number * ent_size));
+ free (e_data);
+ return NULL;
+ }
+
+ i_data = (bfd_vma *) cmalloc ((size_t) number, sizeof (*i_data));
+ if (i_data == NULL)
+ {
+ error (_("Out of memory allocating space for %s dynamic entries\n"),
+ bfd_vmatoa ("u", number));
+ free (e_data);
+ return NULL;
+ }
+
+ while (number--)
+ i_data[number] = byte_get (e_data + number * ent_size, ent_size);
+
+ free (e_data);
+
+ return i_data;
+}
+
+static unsigned long
+get_num_dynamic_syms (Filedata * filedata)
+{
+ unsigned long num_of_syms = 0;
+
+ if (!do_histogram && (!do_using_dynamic || do_dyn_syms))
+ return num_of_syms;
+
+ if (dynamic_info[DT_HASH])
+ {
+ unsigned char nb[8];
+ unsigned char nc[8];
+ unsigned int hash_ent_size = 4;
+
+ if ((filedata->file_header.e_machine == EM_ALPHA
+ || filedata->file_header.e_machine == EM_S390
+ || filedata->file_header.e_machine == EM_S390_OLD)
+ && filedata->file_header.e_ident[EI_CLASS] == ELFCLASS64)
+ hash_ent_size = 8;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, dynamic_info[DT_HASH],
+ sizeof nb + sizeof nc)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ goto no_hash;
+ }
+
+ if (fread (nb, hash_ent_size, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to read in number of buckets\n"));
+ goto no_hash;
+ }
+
+ if (fread (nc, hash_ent_size, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to read in number of chains\n"));
+ goto no_hash;
+ }
+
+ nbuckets = byte_get (nb, hash_ent_size);
+ nchains = byte_get (nc, hash_ent_size);
+ num_of_syms = nchains;
+
+ buckets = get_dynamic_data (filedata, nbuckets, hash_ent_size);
+ chains = get_dynamic_data (filedata, nchains, hash_ent_size);
+
+ no_hash:
+ if (num_of_syms == 0)
+ {
+ if (buckets)
+ {
+ free (buckets);
+ buckets = NULL;
+ }
+ if (chains)
+ {
+ free (chains);
+ buckets = NULL;
+ }
+ nbuckets = 0;
+ }
+ }
+
+ if (dynamic_info_DT_GNU_HASH)
+ {
+ unsigned char nb[16];
+ bfd_vma i, maxchain = 0xffffffff, bitmaskwords;
+ bfd_vma buckets_vma;
+ unsigned long hn;
+ bfd_boolean gnu_hash_error = FALSE;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, dynamic_info_DT_GNU_HASH,
+ sizeof nb)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ if (fread (nb, 16, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to read in number of buckets\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ ngnubuckets = byte_get (nb, 4);
+ gnusymidx = byte_get (nb + 4, 4);
+ bitmaskwords = byte_get (nb + 8, 4);
+ buckets_vma = dynamic_info_DT_GNU_HASH + 16;
+ if (is_32bit_elf)
+ buckets_vma += bitmaskwords * 4;
+ else
+ buckets_vma += bitmaskwords * 8;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, buckets_vma, 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ gnubuckets = get_dynamic_data (filedata, ngnubuckets, 4);
+
+ if (gnubuckets == NULL)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ for (i = 0; i < ngnubuckets; i++)
+ if (gnubuckets[i] != 0)
+ {
+ if (gnubuckets[i] < gnusymidx)
+ {
+ gnu_hash_error = TRUE;
+ return FALSE;
+ }
+
+ if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
+ maxchain = gnubuckets[i];
+ }
+
+ if (maxchain == 0xffffffff)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ maxchain -= gnusymidx;
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, buckets_vma
+ + 4 * (ngnubuckets + maxchain), 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ do
+ {
+ if (fread (nb, 4, 1, filedata->handle) != 1)
+ {
+ error (_("Failed to determine last chain length\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ if (maxchain + 1 == 0)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ ++maxchain;
+ }
+ while ((byte_get (nb, 4) & 1) == 0);
+
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, buckets_vma + 4 * ngnubuckets, 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ gnuchains = get_dynamic_data (filedata, maxchain, 4);
+ ngnuchains = maxchain;
+
+ if (gnuchains == NULL)
+ {
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ if (dynamic_info_DT_MIPS_XHASH)
+ {
+ if (fseek (filedata->handle,
+ (archive_file_offset
+ + offset_from_vma (filedata, (buckets_vma
+ + 4 * (ngnubuckets
+ + maxchain)), 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ gnu_hash_error = TRUE;
+ goto no_gnu_hash;
+ }
+
+ mipsxlat = get_dynamic_data (filedata, maxchain, 4);
+ }
+
+ for (hn = 0; hn < ngnubuckets; ++hn)
+ if (gnubuckets[hn] != 0)
+ {
+ bfd_vma si = gnubuckets[hn];
+ bfd_vma off = si - gnusymidx;
+
+ do
+ {
+ if (dynamic_info_DT_MIPS_XHASH)
+ {
+ if (mipsxlat[off] >= num_of_syms)
+ num_of_syms = mipsxlat[off] + 1;
+ }
+ else
+ {
+ if (si >= num_of_syms)
+ num_of_syms = si + 1;
+ }
+ si++;
+ }
+ while (off < ngnuchains && (gnuchains[off++] & 1) == 0);
+ }
+
+ no_gnu_hash:
+ if (gnu_hash_error)
+ {
+ if (mipsxlat)
+ {
+ free (mipsxlat);
+ mipsxlat = NULL;
+ }
+ if (gnuchains)
+ {
+ free (gnuchains);
+ gnuchains = NULL;
+ }
+ if (gnubuckets)
+ {
+ free (gnubuckets);
+ gnubuckets = NULL;
+ }
+ ngnubuckets = 0;
+ ngnuchains = 0;
+ }
+ }
+
+ return num_of_syms;
+}
+
/* Parse and display the contents of the dynamic section. */
static bfd_boolean
@@ -9892,103 +10219,117 @@ process_dynamic_section (Filedata * filedata)
}
/* Find the appropriate symbol table. */
- if (dynamic_symbols == NULL)
+ if (dynamic_symbols == NULL || do_histogram)
{
for (entry = dynamic_section;
entry < dynamic_section + dynamic_nent;
++entry)
- {
- Elf_Internal_Shdr section;
+ if (entry->d_tag == DT_SYMTAB)
+ dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
+ else if (entry->d_tag == DT_SYMENT)
+ dynamic_info[DT_SYMENT] = entry->d_un.d_val;
+ else if (entry->d_tag == DT_HASH)
+ dynamic_info[DT_HASH] = entry->d_un.d_val;
+ else if (entry->d_tag == DT_GNU_HASH)
+ dynamic_info_DT_GNU_HASH = entry->d_un.d_val;
+ else if ((filedata->file_header.e_machine == EM_MIPS
+ || filedata->file_header.e_machine == EM_MIPS_RS3_LE)
+ && entry->d_tag == DT_MIPS_XHASH)
+ {
+ dynamic_info_DT_MIPS_XHASH = entry->d_un.d_val;
+ dynamic_info_DT_GNU_HASH = entry->d_un.d_val;
+ }
- if (entry->d_tag != DT_SYMTAB)
- continue;
+ if (dynamic_info[DT_SYMTAB] && dynamic_info[DT_SYMENT])
+ {
+ Elf_Internal_Phdr *seg;
+ bfd_vma vma = dynamic_info[DT_SYMTAB];
- dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
+ if (! get_program_headers (filedata))
+ {
+ error (_("Cannot interpret virtual addresses without program headers.\n"));
+ return FALSE;
+ }
- /* Since we do not know how big the symbol table is,
- we default to reading in the entire file (!) and
- processing that. This is overkill, I know, but it
- should work. */
- section.sh_offset = offset_from_vma (filedata, entry->d_un.d_val, 0);
- if ((bfd_size_type) section.sh_offset > filedata->file_size)
- {
- /* See PR 21379 for a reproducer. */
- error (_("Invalid DT_SYMTAB entry: %lx\n"),
- (long) section.sh_offset);
- return FALSE;
- }
+ for (seg = filedata->program_headers;
+ seg < filedata->program_headers + filedata->file_header.e_phnum;
+ ++seg)
+ {
+ unsigned long num_of_syms;
- if (archive_file_offset != 0)
- section.sh_size = archive_file_size - section.sh_offset;
- else
- section.sh_size = filedata->file_size - section.sh_offset;
+ if (seg->p_type != PT_LOAD)
+ continue;
- if (is_32bit_elf)
- section.sh_entsize = sizeof (Elf32_External_Sym);
- else
- section.sh_entsize = sizeof (Elf64_External_Sym);
- section.sh_name = filedata->string_table_length;
+ if ((seg->p_offset + seg->p_filesz)
+ > filedata->file_size)
+ {
+ /* See PR 21379 for a reproducer. */
+ error (_("Invalid PT_LOAD entry\n"));
+ return FALSE;
+ }
- if (dynamic_symbols != NULL)
- {
- error (_("Multiple dynamic symbol table sections found\n"));
- free (dynamic_symbols);
- }
- dynamic_symbols = GET_ELF_SYMBOLS (filedata, §ion, & num_dynamic_syms);
- if (num_dynamic_syms < 1)
- {
- error (_("Unable to determine the number of symbols to load\n"));
- continue;
- }
- }
- }
+ if (vma >= (seg->p_vaddr & -seg->p_align)
+ && vma <= seg->p_vaddr + seg->p_filesz
+ && (num_of_syms = get_num_dynamic_syms (filedata)))
+ {
+ /* Since we do not know how big the symbol table is,
+ we default to reading in up to the end of PT_LOAD
+ segment and processing that. This is overkill, I
+ know, but it should work. */
+ Elf_Internal_Shdr section;
+ section.sh_offset = (vma - seg->p_vaddr
+ + seg->p_offset);
+ section.sh_size = (num_of_syms
+ * dynamic_info[DT_SYMENT]);
+ section.sh_entsize = dynamic_info[DT_SYMENT];
+ section.sh_name = filedata->string_table_length;
+ dynamic_symbols = GET_ELF_SYMBOLS (filedata,
+ §ion,
+ & num_dynamic_syms);
+ if (dynamic_symbols == NULL
+ || num_dynamic_syms != num_of_syms)
+ {
+ error (_("Corrupt DT_SYMTAB dynamic entry\n"));
+ return FALSE;
+ }
+ }
+ }
+ }
+ }
/* Similarly find a string table. */
if (dynamic_strings == NULL)
- {
- for (entry = dynamic_section;
- entry < dynamic_section + dynamic_nent;
- ++entry)
- {
- unsigned long offset;
- long str_tab_len;
-
- if (entry->d_tag != DT_STRTAB)
- continue;
-
+ for (entry = dynamic_section;
+ entry < dynamic_section + dynamic_nent;
+ ++entry)
+ {
+ if (entry->d_tag == DT_STRTAB)
dynamic_info[DT_STRTAB] = entry->d_un.d_val;
- /* Since we do not know how big the string table is,
- we default to reading in the entire file (!) and
- processing that. This is overkill, I know, but it
- should work. */
-
- offset = offset_from_vma (filedata, entry->d_un.d_val, 0);
-
- if (archive_file_offset != 0)
- str_tab_len = archive_file_size - offset;
- else
- str_tab_len = filedata->file_size - offset;
-
- if (str_tab_len < 1)
- {
- error
- (_("Unable to determine the length of the dynamic string table\n"));
- continue;
- }
+ if (entry->d_tag == DT_STRSZ)
+ dynamic_info[DT_STRSZ] = entry->d_un.d_val;
- if (dynamic_strings != NULL)
- {
- error (_("Multiple dynamic string tables found\n"));
- free (dynamic_strings);
- }
+ if (dynamic_info[DT_STRTAB] && dynamic_info[DT_STRSZ])
+ {
+ unsigned long offset;
+ bfd_size_type str_tab_len = dynamic_info[DT_STRSZ];
+
+ offset = offset_from_vma (filedata,
+ dynamic_info[DT_STRTAB],
+ str_tab_len);
+ dynamic_strings = (char *) get_data (NULL, filedata, offset, 1,
+ str_tab_len,
+ _("dynamic string table"));
+ if (dynamic_strings == NULL)
+ {
+ error (_("Corrupt DT_STRTAB dynamic entry\n"));
+ break;
+ }
- dynamic_strings = (char *) get_data (NULL, filedata, offset, 1,
- str_tab_len,
- _("dynamic string table"));
- dynamic_strings_length = dynamic_strings == NULL ? 0 : str_tab_len;
- }
- }
+ dynamic_strings_length = str_tab_len;
+ break;
+ }
+ }
/* And find the syminfo section if available. */
if (dynamic_syminfo == NULL)
@@ -11410,143 +11751,36 @@ get_symbol_index_type (Filedata * filedata, unsigned int type)
default:
if (type == SHN_IA_64_ANSI_COMMON
&& filedata->file_header.e_machine == EM_IA_64
- && filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
- return "ANSI_COM";
- else if ((filedata->file_header.e_machine == EM_X86_64
- || filedata->file_header.e_machine == EM_L1OM
- || filedata->file_header.e_machine == EM_K1OM)
- && type == SHN_X86_64_LCOMMON)
- return "LARGE_COM";
- else if ((type == SHN_MIPS_SCOMMON
- && filedata->file_header.e_machine == EM_MIPS)
- || (type == SHN_TIC6X_SCOMMON
- && filedata->file_header.e_machine == EM_TI_C6000))
- return "SCOM";
- else if (type == SHN_MIPS_SUNDEFINED
- && filedata->file_header.e_machine == EM_MIPS)
- return "SUND";
- else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
- sprintf (buff, "PRC[0x%04x]", type & 0xffff);
- else if (type >= SHN_LOOS && type <= SHN_HIOS)
- sprintf (buff, "OS [0x%04x]", type & 0xffff);
- else if (type >= SHN_LORESERVE)
- sprintf (buff, "RSV[0x%04x]", type & 0xffff);
- else if (type >= filedata->file_header.e_shnum)
- sprintf (buff, _("bad section index[%3d]"), type);
- else
- sprintf (buff, "%3d", type);
- break;
- }
-
- return buff;
-}
-
-static bfd_vma *
-get_dynamic_data (Filedata * filedata, bfd_size_type number, unsigned int ent_size)
-{
- unsigned char * e_data;
- bfd_vma * i_data;
-
- /* If the size_t type is smaller than the bfd_size_type, eg because
- you are building a 32-bit tool on a 64-bit host, then make sure
- that when (number) is cast to (size_t) no information is lost. */
- if (sizeof (size_t) < sizeof (bfd_size_type)
- && (bfd_size_type) ((size_t) number) != number)
- {
- error (_("Size truncation prevents reading %s elements of size %u\n"),
- bfd_vmatoa ("u", number), ent_size);
- return NULL;
- }
-
- /* Be kind to memory checkers (eg valgrind, address sanitizer) by not
- attempting to allocate memory when the read is bound to fail. */
- if (ent_size * number > filedata->file_size)
- {
- error (_("Invalid number of dynamic entries: %s\n"),
- bfd_vmatoa ("u", number));
- return NULL;
- }
-
- e_data = (unsigned char *) cmalloc ((size_t) number, ent_size);
- if (e_data == NULL)
- {
- error (_("Out of memory reading %s dynamic entries\n"),
- bfd_vmatoa ("u", number));
- return NULL;
- }
-
- if (fread (e_data, ent_size, (size_t) number, filedata->handle) != number)
- {
- error (_("Unable to read in %s bytes of dynamic data\n"),
- bfd_vmatoa ("u", number * ent_size));
- free (e_data);
- return NULL;
- }
-
- i_data = (bfd_vma *) cmalloc ((size_t) number, sizeof (*i_data));
- if (i_data == NULL)
- {
- error (_("Out of memory allocating space for %s dynamic entries\n"),
- bfd_vmatoa ("u", number));
- free (e_data);
- return NULL;
- }
-
- while (number--)
- i_data[number] = byte_get (e_data + number * ent_size, ent_size);
-
- free (e_data);
-
- return i_data;
-}
-
-static void
-print_dynamic_symbol (Filedata * filedata, bfd_vma si, unsigned long hn)
-{
- Elf_Internal_Sym * psym;
- int n;
-
- n = print_vma (si, DEC_5);
- if (n < 5)
- fputs (&" "[n], stdout);
- printf (" %3lu: ", hn);
-
- if (dynamic_symbols == NULL || si >= num_dynamic_syms)
- {
- printf (_("<No info available for dynamic symbol number %lu>\n"),
- (unsigned long) si);
- return;
- }
-
- psym = dynamic_symbols + si;
- print_vma (psym->st_value, LONG_HEX);
- putchar (' ');
- print_vma (psym->st_size, DEC_5);
-
- printf (" %-7s", get_symbol_type (filedata, ELF_ST_TYPE (psym->st_info)));
- printf (" %-6s", get_symbol_binding (filedata, ELF_ST_BIND (psym->st_info)));
-
- if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
- printf (" %-7s", get_solaris_symbol_visibility (psym->st_other));
- else
- {
- unsigned int vis = ELF_ST_VISIBILITY (psym->st_other);
-
- printf (" %-7s", get_symbol_visibility (vis));
- /* Check to see if any other bits in the st_other field are set.
- Note - displaying this information disrupts the layout of the
- table being generated, but for the moment this case is very
- rare. */
- if (psym->st_other ^ vis)
- printf (" [%s] ", get_symbol_other (filedata, psym->st_other ^ vis));
+ && filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
+ return "ANSI_COM";
+ else if ((filedata->file_header.e_machine == EM_X86_64
+ || filedata->file_header.e_machine == EM_L1OM
+ || filedata->file_header.e_machine == EM_K1OM)
+ && type == SHN_X86_64_LCOMMON)
+ return "LARGE_COM";
+ else if ((type == SHN_MIPS_SCOMMON
+ && filedata->file_header.e_machine == EM_MIPS)
+ || (type == SHN_TIC6X_SCOMMON
+ && filedata->file_header.e_machine == EM_TI_C6000))
+ return "SCOM";
+ else if (type == SHN_MIPS_SUNDEFINED
+ && filedata->file_header.e_machine == EM_MIPS)
+ return "SUND";
+ else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
+ sprintf (buff, "PRC[0x%04x]", type & 0xffff);
+ else if (type >= SHN_LOOS && type <= SHN_HIOS)
+ sprintf (buff, "OS [0x%04x]", type & 0xffff);
+ else if (type >= SHN_LORESERVE)
+ sprintf (buff, "RSV[0x%04x]", type & 0xffff);
+ else if (filedata->file_header.e_shnum != 0
+ && type >= filedata->file_header.e_shnum)
+ sprintf (buff, _("bad section index[%3d]"), type);
+ else
+ sprintf (buff, "%3d", type);
+ break;
}
- printf (" %3.3s ", get_symbol_index_type (filedata, psym->st_shndx));
- if (VALID_DYNAMIC_NAME (psym->st_name))
- print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
- else
- printf (_(" <corrupt: %14ld>"), psym->st_name);
- putchar ('\n');
+ return buff;
}
static const char *
@@ -11722,214 +11956,78 @@ get_symbol_version_string (Filedata * filedata,
return NULL;
}
-/* Dump the symbol table. */
-static bfd_boolean
-process_symbol_table (Filedata * filedata)
+static void
+print_dynamic_symbol (Filedata *filedata, unsigned long si,
+ Elf_Internal_Sym *symtab,
+ Elf_Internal_Shdr *section,
+ char *strtab, size_t strtab_size)
{
- Elf_Internal_Shdr * section;
- bfd_size_type nbuckets = 0;
- bfd_size_type nchains = 0;
- bfd_vma * buckets = NULL;
- bfd_vma * chains = NULL;
- bfd_vma ngnubuckets = 0;
- bfd_vma * gnubuckets = NULL;
- bfd_vma * gnuchains = NULL;
- bfd_vma * mipsxlat = NULL;
- bfd_vma gnusymidx = 0;
- bfd_size_type ngnuchains = 0;
-
- if (!do_syms && !do_dyn_syms && !do_histogram)
- return TRUE;
+ const char *version_string;
+ enum versioned_symbol_info sym_info;
+ unsigned short vna_other;
+ Elf_Internal_Sym *psym = symtab + si;
- if (dynamic_info[DT_HASH]
- && (do_histogram
- || (do_using_dynamic
- && !do_dyn_syms
- && dynamic_strings != NULL)))
+ printf ("%6ld: ", si);
+ print_vma (psym->st_value, LONG_HEX);
+ putchar (' ');
+ print_vma (psym->st_size, DEC_5);
+ printf (" %-7s", get_symbol_type (filedata, ELF_ST_TYPE (psym->st_info)));
+ printf (" %-6s", get_symbol_binding (filedata, ELF_ST_BIND (psym->st_info)));
+ if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
+ printf (" %-7s", get_solaris_symbol_visibility (psym->st_other));
+ else
{
- unsigned char nb[8];
- unsigned char nc[8];
- unsigned int hash_ent_size = 4;
-
- if ((filedata->file_header.e_machine == EM_ALPHA
- || filedata->file_header.e_machine == EM_S390
- || filedata->file_header.e_machine == EM_S390_OLD)
- && filedata->file_header.e_ident[EI_CLASS] == ELFCLASS64)
- hash_ent_size = 8;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, dynamic_info[DT_HASH],
- sizeof nb + sizeof nc)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_hash;
- }
-
- if (fread (nb, hash_ent_size, 1, filedata->handle) != 1)
- {
- error (_("Failed to read in number of buckets\n"));
- goto no_hash;
- }
-
- if (fread (nc, hash_ent_size, 1, filedata->handle) != 1)
- {
- error (_("Failed to read in number of chains\n"));
- goto no_hash;
- }
-
- nbuckets = byte_get (nb, hash_ent_size);
- nchains = byte_get (nc, hash_ent_size);
-
- buckets = get_dynamic_data (filedata, nbuckets, hash_ent_size);
- chains = get_dynamic_data (filedata, nchains, hash_ent_size);
+ unsigned int vis = ELF_ST_VISIBILITY (psym->st_other);
- if (buckets == NULL || chains == NULL)
- {
- no_hash:
- free (buckets);
- free (chains);
- buckets = NULL;
- chains = NULL;
- nbuckets = 0;
- nchains = 0;
- if (do_using_dynamic)
- goto err_out;
- }
+ printf (" %-7s", get_symbol_visibility (vis));
+ /* Check to see if any other bits in the st_other field are set.
+ Note - displaying this information disrupts the layout of the
+ table being generated, but for the moment this case is very rare. */
+ if (psym->st_other ^ vis)
+ printf (" [%s] ", get_symbol_other (filedata, psym->st_other ^ vis));
}
-
- if (dynamic_info_DT_GNU_HASH
- && (do_histogram
- || (do_using_dynamic
- && !do_dyn_syms
- && dynamic_strings != NULL)))
- {
- unsigned char nb[16];
- bfd_vma i, maxchain = 0xffffffff, bitmaskwords;
- bfd_vma buckets_vma;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, dynamic_info_DT_GNU_HASH,
- sizeof nb)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- if (fread (nb, 16, 1, filedata->handle) != 1)
- {
- error (_("Failed to read in number of buckets\n"));
- goto no_gnu_hash;
- }
-
- ngnubuckets = byte_get (nb, 4);
- gnusymidx = byte_get (nb + 4, 4);
- bitmaskwords = byte_get (nb + 8, 4);
- buckets_vma = dynamic_info_DT_GNU_HASH + 16;
- if (is_32bit_elf)
- buckets_vma += bitmaskwords * 4;
+ printf (" %4s ", get_symbol_index_type (filedata, psym->st_shndx));
+ print_symbol (25, VALID_SYMBOL_NAME (strtab, strtab_size,
+ psym->st_name)
+ ? strtab + psym->st_name : _("<corrupt>"));
+
+ version_string
+ = get_symbol_version_string (filedata,
+ (section == NULL
+ || section->sh_type == SHT_DYNSYM),
+ strtab, strtab_size, si,
+ psym, &sym_info, &vna_other);
+ if (version_string)
+ {
+ if (sym_info == symbol_undefined)
+ printf ("@%s (%d)", version_string, vna_other);
else
- buckets_vma += bitmaskwords * 8;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, buckets_vma, 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- gnubuckets = get_dynamic_data (filedata, ngnubuckets, 4);
-
- if (gnubuckets == NULL)
- goto no_gnu_hash;
-
- for (i = 0; i < ngnubuckets; i++)
- if (gnubuckets[i] != 0)
- {
- if (gnubuckets[i] < gnusymidx)
- goto err_out;
-
- if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
- maxchain = gnubuckets[i];
- }
-
- if (maxchain == 0xffffffff)
- goto no_gnu_hash;
-
- maxchain -= gnusymidx;
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, buckets_vma
- + 4 * (ngnubuckets + maxchain), 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
-
- do
- {
- if (fread (nb, 4, 1, filedata->handle) != 1)
- {
- error (_("Failed to determine last chain length\n"));
- goto no_gnu_hash;
- }
-
- if (maxchain + 1 == 0)
- goto no_gnu_hash;
-
- ++maxchain;
- }
- while ((byte_get (nb, 4) & 1) == 0);
-
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, buckets_vma + 4 * ngnubuckets, 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
+ printf (sym_info == symbol_hidden ? "@%s" : "@@%s",
+ version_string);
+ }
- gnuchains = get_dynamic_data (filedata, maxchain, 4);
- ngnuchains = maxchain;
+ putchar ('\n');
- if (gnuchains == NULL)
- goto no_gnu_hash;
+ if (ELF_ST_BIND (psym->st_info) == STB_LOCAL
+ && section != NULL
+ && si >= section->sh_info
+ /* Irix 5 and 6 MIPS binaries are known to ignore this requirement. */
+ && filedata->file_header.e_machine != EM_MIPS
+ /* Solaris binaries have been found to violate this requirement as
+ well. Not sure if this is a bug or an ABI requirement. */
+ && filedata->file_header.e_ident[EI_OSABI] != ELFOSABI_SOLARIS)
+ warn (_("local symbol %lu found at index >= %s's sh_info value of %u\n"),
+ si, printable_section_name (filedata, section), section->sh_info);
+}
- if (dynamic_info_DT_MIPS_XHASH)
- {
- if (fseek (filedata->handle,
- (archive_file_offset
- + offset_from_vma (filedata, (buckets_vma
- + 4 * (ngnubuckets
- + maxchain)), 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- goto no_gnu_hash;
- }
+/* Dump the symbol table. */
+static bfd_boolean
+process_symbol_table (Filedata * filedata)
+{
+ Elf_Internal_Shdr * section;
- mipsxlat = get_dynamic_data (filedata, maxchain, 4);
- if (mipsxlat == NULL)
- {
- no_gnu_hash:
- free (gnuchains);
- gnuchains = NULL;
- free (gnubuckets);
- gnubuckets = NULL;
- ngnubuckets = 0;
- if (do_using_dynamic)
- goto err_out;
- }
- }
- }
+ if (!do_syms && !do_dyn_syms && !do_histogram)
+ return TRUE;
if ((dynamic_info[DT_HASH] || dynamic_info_DT_GNU_HASH)
&& do_syms
@@ -11937,63 +12035,19 @@ process_symbol_table (Filedata * filedata)
&& dynamic_strings != NULL
&& dynamic_symbols != NULL)
{
- unsigned long hn;
-
- if (dynamic_info[DT_HASH])
- {
- bfd_vma si;
- char *visited;
-
- printf (_("\nSymbol table for image:\n"));
- if (is_32bit_elf)
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
- else
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
-
- visited = xcmalloc (nchains, 1);
- memset (visited, 0, nchains);
- for (hn = 0; hn < nbuckets; hn++)
- {
- for (si = buckets[hn]; si > 0; si = chains[si])
- {
- print_dynamic_symbol (filedata, si, hn);
- if (si >= nchains || visited[si])
- {
- error (_("histogram chain is corrupt\n"));
- break;
- }
- visited[si] = 1;
- }
- }
- free (visited);
- }
+ unsigned long si;
- if (dynamic_info_DT_GNU_HASH)
- {
- printf (_("\nSymbol table of `%s' for image:\n"),
- GNU_HASH_SECTION_NAME);
- if (is_32bit_elf)
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
- else
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
-
- for (hn = 0; hn < ngnubuckets; ++hn)
- if (gnubuckets[hn] != 0)
- {
- bfd_vma si = gnubuckets[hn];
- bfd_vma off = si - gnusymidx;
+ printf (ngettext ("\nSymbol table for image contains %lu entry:\n",
+ "\nSymbol table for image contains %lu entries:\n",
+ num_dynamic_syms), num_dynamic_syms);
+ if (is_32bit_elf)
+ printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
+ else
+ printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
- do
- {
- if (dynamic_info_DT_MIPS_XHASH)
- print_dynamic_symbol (filedata, mipsxlat[off], hn);
- else
- print_dynamic_symbol (filedata, si, hn);
- si++;
- }
- while (off < ngnuchains && (gnuchains[off++] & 1) == 0);
- }
- }
+ for (si = 0; si < num_dynamic_syms; si++)
+ print_dynamic_symbol (filedata, si, dynamic_symbols, NULL,
+ dynamic_strings, dynamic_strings_length);
}
else if ((do_dyn_syms || (do_syms && !do_using_dynamic))
&& filedata->section_headers != NULL)
@@ -12007,7 +12061,6 @@ process_symbol_table (Filedata * filedata)
char * strtab = NULL;
unsigned long int strtab_size = 0;
Elf_Internal_Sym * symtab;
- Elf_Internal_Sym * psym;
unsigned long si, num_syms;
if ((section->sh_type != SHT_SYMTAB
@@ -12056,61 +12109,9 @@ process_symbol_table (Filedata * filedata)
strtab_size = strtab != NULL ? string_sec->sh_size : 0;
}
- 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 ("%6ld: ", si);
- print_vma (psym->st_value, LONG_HEX);
- putchar (' ');
- print_vma (psym->st_size, DEC_5);
- printf (" %-7s", get_symbol_type (filedata, ELF_ST_TYPE (psym->st_info)));
- printf (" %-6s", get_symbol_binding (filedata, ELF_ST_BIND (psym->st_info)));
- if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS)
- printf (" %-7s", get_solaris_symbol_visibility (psym->st_other));
- else
- {
- unsigned int vis = ELF_ST_VISIBILITY (psym->st_other);
-
- printf (" %-7s", get_symbol_visibility (vis));
- /* Check to see if any other bits in the st_other field are set.
- Note - displaying this information disrupts the layout of the
- table being generated, but for the moment this case is very rare. */
- if (psym->st_other ^ vis)
- printf (" [%s] ", get_symbol_other (filedata, psym->st_other ^ vis));
- }
- printf (" %4s ", get_symbol_index_type (filedata, psym->st_shndx));
- print_symbol (25, psym->st_name < strtab_size
- ? strtab + psym->st_name : _("<corrupt>"));
-
- version_string
- = get_symbol_version_string (filedata,
- section->sh_type == SHT_DYNSYM,
- strtab, strtab_size, si,
- psym, &sym_info, &vna_other);
- if (version_string)
- {
- if (sym_info == symbol_undefined)
- printf ("@%s (%d)", version_string, vna_other);
- else
- printf (sym_info == symbol_hidden ? "@%s" : "@@%s",
- version_string);
- }
-
- putchar ('\n');
-
- if (ELF_ST_BIND (psym->st_info) == STB_LOCAL
- && si >= section->sh_info
- /* Irix 5 and 6 MIPS binaries are known to ignore this requirement. */
- && filedata->file_header.e_machine != EM_MIPS
- /* Solaris binaries have been found to violate this requirement as
- well. Not sure if this is a bug or an ABI requirement. */
- && filedata->file_header.e_ident[EI_OSABI] != ELFOSABI_SOLARIS)
- warn (_("local symbol %lu found at index >= %s's sh_info value of %u\n"),
- si, printable_section_name (filedata, section), section->sh_info);
- }
+ for (si = 0; si < num_syms; si++)
+ print_dynamic_symbol (filedata, si, symtab, section,
+ strtab, strtab_size);
free (symtab);
if (strtab != filedata->string_table)
diff --git a/ld/testsuite/ld-arm/armthumb-lib.sym b/ld/testsuite/ld-arm/armthumb-lib.sym
index 3714e80847..7119e351fc 100644
--- a/ld/testsuite/ld-arm/armthumb-lib.sym
+++ b/ld/testsuite/ld-arm/armthumb-lib.sym
@@ -1,15 +1,16 @@
-Symbol table for image:
- +Num +Buc: +Value +Size +Type +Bind +Vis +Ndx +Name
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _edata
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _end
- +.. +..: ........ +4 +OBJECT +GLOBAL +DEFAULT +9 data_obj
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_end__
- +.. +..: .......0 +20 +FUNC +GLOBAL +DEFAULT +6 lib_func1
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __data_start
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start
- +.. +..: 00000000 +0 +NOTYPE +GLOBAL +DEFAULT +UND app_func2
- +.. +..: .......[048c] +2 +FUNC +GLOBAL +DEFAULT +6 lib_func2
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _bss_end__
+Symbol table for image contains 13 entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+ +..: +00000000 +0 +NOTYPE +LOCAL +DEFAULT +UND
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start__
+ +..: +.......[048c] +2 +FUNC +GLOBAL +DEFAULT +6 lib_func2
+ +..: +.......0 +20 +FUNC +GLOBAL +DEFAULT +6 lib_func1
+ +..: +00000000 +0 +NOTYPE +GLOBAL +DEFAULT +UND app_func2
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __end__
+ +..: +........ +4 +OBJECT +GLOBAL +DEFAULT +9 data_obj
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _edata
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _end
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __data_start
diff --git a/ld/testsuite/ld-arm/farcall-mixed-app.sym b/ld/testsuite/ld-arm/farcall-mixed-app.sym
index 093397cfa6..febf1fedaf 100644
--- a/ld/testsuite/ld-arm/farcall-mixed-app.sym
+++ b/ld/testsuite/ld-arm/farcall-mixed-app.sym
@@ -1,15 +1,16 @@
-Symbol table for image:
- +Num +Buc: +Value +Size +Type +Bind +Vis +Ndx +Name
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +11 _edata
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _end
- +.. +..: ........ +4 +OBJECT +GLOBAL +DEFAULT +12 data_obj
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_end__
- +.. +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func1
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +11 __data_start
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start
- +.. +..: .......0 +0 +FUNC +GLOBAL +DEFAULT +14 app_func2
- +.. +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func2
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _bss_end__
+Symbol table for image contains 13 entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+ +..: +00000000 +0 +NOTYPE +LOCAL +DEFAULT +UND
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start__
+ +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func2
+ +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func1
+ +..: +.......0 +0 +FUNC +GLOBAL +DEFAULT +14 app_func2
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __end__
+ +..: +........ +4 +OBJECT +GLOBAL +DEFAULT +12 data_obj
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +11 _edata
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _end
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +11 __data_start
diff --git a/ld/testsuite/ld-arm/farcall-mixed-app2.sym b/ld/testsuite/ld-arm/farcall-mixed-app2.sym
index 1d3bd1d537..97cccf0e35 100644
--- a/ld/testsuite/ld-arm/farcall-mixed-app2.sym
+++ b/ld/testsuite/ld-arm/farcall-mixed-app2.sym
@@ -1,15 +1,16 @@
-Symbol table for image:
- +Num +Buc: +Value +Size +Type +Bind +Vis +Ndx +Name
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +11 _edata
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _end
- +.. +..: ........ +4 +OBJECT +GLOBAL +DEFAULT +12 data_obj
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_end__
- +.. +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func1
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +11 __data_start
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start
- +.. +..: .......0 +0 +FUNC +GLOBAL +DEFAULT +15 app_func2
- +.. +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func2
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _bss_end__
+Symbol table for image contains 13 entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+ +..: +00000000 +0 +NOTYPE +LOCAL +DEFAULT +UND
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start__
+ +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func2
+ +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func1
+ +..: +.......0 +0 +FUNC +GLOBAL +DEFAULT +15 app_func2
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __end__
+ +..: +........ +4 +OBJECT +GLOBAL +DEFAULT +12 data_obj
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +11 _edata
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _end
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +11 __data_start
diff --git a/ld/testsuite/ld-arm/fdpic-main-m.sym b/ld/testsuite/ld-arm/fdpic-main-m.sym
index 9eaf617760..6e655d67c1 100644
--- a/ld/testsuite/ld-arm/fdpic-main-m.sym
+++ b/ld/testsuite/ld-arm/fdpic-main-m.sym
@@ -1,14 +1,15 @@
-Symbol table for image:
- +Num +Buc: +Value +Size +Type +Bind +Vis +Ndx +Name
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _edata
- +.. +..: ........ +0 +FUNC +GLOBAL +DEFAULT +UND my_shared_func2
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +13 _end
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +13 __bss_end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +13 __end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT + 9 __ROFIXUP_LIST__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT + 9 __ROFIXUP_END__
- +.. +..: ........ +0 +FUNC +GLOBAL +DEFAULT +UND my_shared_func1
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +13 _bss_end__
+Symbol table for image contains 12 entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+ +..: +00000000 +0 +NOTYPE +LOCAL +DEFAULT +UND
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +13 _bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start__
+ +..: +........ +0 +FUNC +GLOBAL +DEFAULT +UND my_shared_func1
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +13 __bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __ROFIXUP_END__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __ROFIXUP_LIST__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +13 __end__
+ +..: +........ +0 +FUNC +GLOBAL +DEFAULT +UND my_shared_func2
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _edata
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +13 _end
diff --git a/ld/testsuite/ld-arm/fdpic-main.sym b/ld/testsuite/ld-arm/fdpic-main.sym
index 9eaf617760..6e655d67c1 100644
--- a/ld/testsuite/ld-arm/fdpic-main.sym
+++ b/ld/testsuite/ld-arm/fdpic-main.sym
@@ -1,14 +1,15 @@
-Symbol table for image:
- +Num +Buc: +Value +Size +Type +Bind +Vis +Ndx +Name
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _edata
- +.. +..: ........ +0 +FUNC +GLOBAL +DEFAULT +UND my_shared_func2
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +13 _end
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +13 __bss_end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +13 __end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT + 9 __ROFIXUP_LIST__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT + 9 __ROFIXUP_END__
- +.. +..: ........ +0 +FUNC +GLOBAL +DEFAULT +UND my_shared_func1
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +13 _bss_end__
+Symbol table for image contains 12 entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+ +..: +00000000 +0 +NOTYPE +LOCAL +DEFAULT +UND
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +13 _bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start__
+ +..: +........ +0 +FUNC +GLOBAL +DEFAULT +UND my_shared_func1
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +13 __bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __ROFIXUP_END__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __ROFIXUP_LIST__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +13 __end__
+ +..: +........ +0 +FUNC +GLOBAL +DEFAULT +UND my_shared_func2
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _edata
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +13 _end
diff --git a/ld/testsuite/ld-arm/fdpic-shared-m.sym b/ld/testsuite/ld-arm/fdpic-shared-m.sym
index 14753702dc..801eaa779a 100644
--- a/ld/testsuite/ld-arm/fdpic-shared-m.sym
+++ b/ld/testsuite/ld-arm/fdpic-shared-m.sym
@@ -1,15 +1,16 @@
-Symbol table for image:
- +Num +Buc: +Value +Size +Type +Bind +Vis +Ndx +Name
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _edata
- +.. +..: ........ +12 +FUNC +GLOBAL +DEFAULT +6 my_shared_func2
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _end
- +.. +..: ........ +6 +FUNC +GLOBAL +DEFAULT +6 my_shared_func3
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +7 __ROFIXUP_LIST__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +7 __ROFIXUP_END__
- +.. +..: ........ +2 +FUNC +GLOBAL +DEFAULT +6 my_shared_func1
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _bss_end__
+Symbol table for image contains 13 entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+ +..: +00000000 +0 +NOTYPE +LOCAL +DEFAULT +UND
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start__
+ +..: +........ +2 +FUNC +GLOBAL +DEFAULT +6 my_shared_func1
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_end__
+ +..: +........ +6 +FUNC +GLOBAL +DEFAULT +6 my_shared_func3
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +7 __ROFIXUP_END__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +7 __ROFIXUP_LIST__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __end__
+ +..: +........ +12 +FUNC +GLOBAL +DEFAULT +6 my_shared_func2
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _edata
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _end
diff --git a/ld/testsuite/ld-arm/fdpic-shared.sym b/ld/testsuite/ld-arm/fdpic-shared.sym
index 2938b36b5f..e11fbdd6b0 100644
--- a/ld/testsuite/ld-arm/fdpic-shared.sym
+++ b/ld/testsuite/ld-arm/fdpic-shared.sym
@@ -1,15 +1,16 @@
-Symbol table for image:
- +Num +Buc: +Value +Size +Type +Bind +Vis +Ndx +Name
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _edata
- +.. +..: ........ +20 +FUNC +GLOBAL +DEFAULT +6 my_shared_func2
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _end
- +.. +..: ........ +8 +FUNC +GLOBAL +DEFAULT +6 my_shared_func3
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +7 __ROFIXUP_LIST__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +7 __ROFIXUP_END__
- +.. +..: ........ +4 +FUNC +GLOBAL +DEFAULT +6 my_shared_func1
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _bss_end__
+Symbol table for image contains 13 entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+ +..: +00000000 +0 +NOTYPE +LOCAL +DEFAULT +UND
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start__
+ +..: +........ +4 +FUNC +GLOBAL +DEFAULT +6 my_shared_func1
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_end__
+ +..: +........ +8 +FUNC +GLOBAL +DEFAULT +6 my_shared_func3
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +7 __ROFIXUP_END__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +7 __ROFIXUP_LIST__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __end__
+ +..: +........ +20 +FUNC +GLOBAL +DEFAULT +6 my_shared_func2
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _edata
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _end
diff --git a/ld/testsuite/ld-arm/mixed-app.sym b/ld/testsuite/ld-arm/mixed-app.sym
index cfa35f5c30..c249f4d776 100644
--- a/ld/testsuite/ld-arm/mixed-app.sym
+++ b/ld/testsuite/ld-arm/mixed-app.sym
@@ -1,15 +1,16 @@
-Symbol table for image:
- +Num +Buc: +Value +Size +Type +Bind +Vis +Ndx +Name
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +11 _edata
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _end
- +.. +..: ........ +4 +OBJECT +GLOBAL +DEFAULT +12 data_obj
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_end__
- +.. +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func1
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +11 __data_start
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start
- +.. +..: .......0 +0 +FUNC +GLOBAL +DEFAULT +8 app_func2
- +.. +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func2
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _bss_end__
+Symbol table for image contains 13 entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+ +..: +00000000 +0 +NOTYPE +LOCAL +DEFAULT +UND
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start__
+ +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func2
+ +..: 0*[^0]*.* +0 +FUNC +GLOBAL +DEFAULT +UND lib_func1
+ +..: +.......0 +0 +FUNC +GLOBAL +DEFAULT +8 app_func2
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __bss_start
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 __end__
+ +..: +........ +4 +OBJECT +GLOBAL +DEFAULT +12 data_obj
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +11 _edata
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +12 _end
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +11 __data_start
diff --git a/ld/testsuite/ld-arm/mixed-lib.sym b/ld/testsuite/ld-arm/mixed-lib.sym
index f5b16dcb30..f14aeed501 100644
--- a/ld/testsuite/ld-arm/mixed-lib.sym
+++ b/ld/testsuite/ld-arm/mixed-lib.sym
@@ -1,15 +1,16 @@
-Symbol table for image:
- +Num +Buc: +Value +Size +Type +Bind +Vis +Ndx +Name
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _edata
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _end
- +.. +..: ........ +4 +OBJECT +GLOBAL +DEFAULT +9 data_obj
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_end__
- +.. +..: .......0 +20 +FUNC +GLOBAL +DEFAULT +6 lib_func1
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __data_start
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start
- +.. +..: 00000000 +0 +NOTYPE +GLOBAL +DEFAULT +UND app_func2
- +.. +..: .......1 +2 +FUNC +GLOBAL +DEFAULT +6 lib_func2
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _bss_end__
+Symbol table for image contains 13 entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+ +..: +00000000 +0 +NOTYPE +LOCAL +DEFAULT +UND
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start__
+ +..: +.......1 +2 +FUNC +GLOBAL +DEFAULT +6 lib_func2
+ +..: +.......0 +20 +FUNC +GLOBAL +DEFAULT +6 lib_func1
+ +..: +00000000 +0 +NOTYPE +GLOBAL +DEFAULT +UND app_func2
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __bss_start
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __end__
+ +..: +........ +4 +OBJECT +GLOBAL +DEFAULT +9 data_obj
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _edata
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _end
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __data_start
diff --git a/ld/testsuite/ld-arm/preempt-app.sym b/ld/testsuite/ld-arm/preempt-app.sym
index ec1d6beabb..31c01cc897 100644
--- a/ld/testsuite/ld-arm/preempt-app.sym
+++ b/ld/testsuite/ld-arm/preempt-app.sym
@@ -1,14 +1,15 @@
-Symbol table for image:
- +Num +Buc: +Value +Size +Type +Bind +Vis +Ndx +Name
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _edata
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +10 __bss_start__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +10 _end
- +.. +..: ........ +4 +OBJECT +GLOBAL +DEFAULT +10 data_obj
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +10 __bss_end__
- +.. +..: .......1 +20 +FUNC +GLOBAL +DEFAULT +6 lib_func1
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __data_start
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +10 __end__
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +10 __bss_start
- +.. +..: .......0 +0 +FUNC +GLOBAL +DEFAULT +6 app_func2
- +.. +..: ........ +0 +NOTYPE +GLOBAL +DEFAULT +10 _bss_end__
+Symbol table for image contains 12 entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+ +..: +00000000 +0 +NOTYPE +LOCAL +DEFAULT +UND
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +10 _bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +10 __bss_start__
+ +..: +.......1 +20 +FUNC +GLOBAL +DEFAULT +6 lib_func1
+ +..: +.......0 +0 +FUNC +GLOBAL +DEFAULT +6 app_func2
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +10 __bss_end__
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +10 __bss_start
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +10 __end__
+ +..: +........ +4 +OBJECT +GLOBAL +DEFAULT +10 data_obj
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 _edata
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +10 _end
+ +..: +........ +0 +NOTYPE +GLOBAL +DEFAULT +9 __data_start
diff --git a/ld/testsuite/ld-elf/hash.d b/ld/testsuite/ld-elf/hash.d
index d21c1c9239..61d84e44a6 100644
--- a/ld/testsuite/ld-elf/hash.d
+++ b/ld/testsuite/ld-elf/hash.d
@@ -10,11 +10,11 @@
#...
+0x[0-9a-z]+ +\(GNU_HASH\) +0x[0-9a-z]+
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] _start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] _start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] main
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] main
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] __start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] __start
#...
diff --git a/ld/testsuite/ld-elf/pr13195.d b/ld/testsuite/ld-elf/pr13195.d
index 4e58929e5a..c22de0e6ce 100644
--- a/ld/testsuite/ld-elf/pr13195.d
+++ b/ld/testsuite/ld-elf/pr13195.d
@@ -5,5 +5,5 @@
# generic linker targets don't support --gc-sections, nor do a bunch of others
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[1-9]+ foo
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +[1-9]+ foo@@VERS_2.0
#pass
diff --git a/ld/testsuite/ld-elfvsb/hidden2.d b/ld/testsuite/ld-elfvsb/hidden2.d
index 72a42d57bc..5d299746f5 100644
--- a/ld/testsuite/ld-elfvsb/hidden2.d
+++ b/ld/testsuite/ld-elfvsb/hidden2.d
@@ -3,7 +3,7 @@
#readelf: -Ds
# It is also ok to remove this symbol, but we currently make it local.
-Symbol table for image:
+Symbol table for image contains [0-9]+ entries:
#...
-[ ]*[0-9]+ +[0-9]+: [0-9a-fA-F]* +0 +OBJECT +LOCAL +DEFAULT .* foo
+[ ]*[0-9]+: [0-9a-fA-F]* +0 +OBJECT +LOCAL +DEFAULT .* foo
#pass
diff --git a/ld/testsuite/ld-mips-elf/hash2.d b/ld/testsuite/ld-mips-elf/hash2.d
index 122edb80e1..aec48e106c 100644
--- a/ld/testsuite/ld-mips-elf/hash2.d
+++ b/ld/testsuite/ld-mips-elf/hash2.d
@@ -6,11 +6,11 @@
#...
+0x[0-9a-z]+ +\(MIPS_XHASH\) +0x[0-9a-z]+
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) _start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC\[[0x[0-9a-f]+\]) __start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) main
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC\[[0x[0-9a-f]+\]) _start
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC\[[0x[0-9a-f]+\]) main
#...
- +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) __start
+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC\[[0x[0-9a-f]+\]) start
#...
--
2.25.2
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: PING [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms table
2020-04-09 17:35 ` Fangrui Song
@ 2020-04-09 17:52 ` H.J. Lu
0 siblings, 0 replies; 11+ messages in thread
From: H.J. Lu @ 2020-04-09 17:52 UTC (permalink / raw)
To: Fangrui Song; +Cc: Alan Modra, Binutils
On Thu, Apr 9, 2020 at 10:35 AM Fangrui Song <i@maskray.me> wrote:
>
> On 2020-04-09, Nick Clifton via Binutils wrote:
> >Hi H.J.
> >
> >> Can you take a look at
> >> https://sourceware.org/pipermail/binutils/2020-March/000234.html
> >
> >Generally the patch looks fine to me, but ... there appear to be some
> >linker testsuite regressions for various targets:
> >
> > mips-elf: LD REGRESSION: ld-mips-elf/hash2 [and other mips based targets]
> >
> > arm-nto: LD REGRESSION: Thumb shared library with ARM [and other arm based targets]
> > LD REGRESSION: Mixed ARM/Thumb shared library
> > LD REGRESSION: Mixed ARM/Thumb dynamic application
> > LD REGRESSION: Mixed ARM/Thumb arch5 dynamic application
> >
> >A quick look suggests that these are all due to readelf's output
> >changing slightly and the tests not expecting the new format.
> >
> >Could you take a look and tweak the tests as necessary please ?
> >
> >Cheers
> > Nick
> >
> >PS. Hmm, just noticed that you had already patched the ld-mips-elf/hash2
> >test, so I am wondering why it is failing. The entry in ld.log looks like
> >this:
> >
> > Executing on host: sh -c {readelf -d -s -D tmpdir/dump > tmpdir/dump.out 2>dump.tmp} /dev/null (timeout = 300)
> > spawn [open ...]
> >
> > extra regexps in ld/testsuite/ld-mips-elf/hash2.d starting with "^ +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +GLOBAL +DEFAULT +([1-9]|PRC) __start$"
> > EOF from tmpdir/dump.out
> > FAIL: ld-mips-elf/hash2
> >
> >Is it possible that your revision of the original patch now makes this test fail ?
> >
>
> My understanding is that readelf -D --dyn-syms still uses the section
> header table (inferred from the output: `Symbol table '.dynsym'`, not `from image`)
That is correct.
> Should -D --dyn-syms decode the dynamic symbol table via DT_SYMTAB as well?
It is possible after my patch has landed.
> As a possible future enhancement, when DT_SYMTAB and SHT_DYNSYM disagree
> with the location, a warning can be issued.
Can you open a bug?
> (llvm-readelf >= 10 can print
> warning: '[[FILE]]': SHT_DYNSYM section header and DT_SYMTAB disagree about the location of the dynamic symbol table
> llvm-readelf >= 11 will have more diagnostics:
> warning: '[[FILE]]': hash table nchain (93) differs from symbol count derived from SHT_DYNSYM section header (1)
> )
Thanks.
--
H.J.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: V2 [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms table
2020-04-09 17:51 ` V2 " H.J. Lu
@ 2020-04-14 10:47 ` Nick Clifton
2020-04-15 3:18 ` Alan Modra
1 sibling, 0 replies; 11+ messages in thread
From: Nick Clifton @ 2020-04-14 10:47 UTC (permalink / raw)
To: H.J. Lu; +Cc: Binutils, Alan Modra
Hi H.J.
> fixed in this updated version. OK for master?
Yes - please apply.
Cheers
Nick
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: V2 [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms table
2020-04-09 17:51 ` V2 " H.J. Lu
2020-04-14 10:47 ` Nick Clifton
@ 2020-04-15 3:18 ` Alan Modra
2020-04-15 12:04 ` H.J. Lu
1 sibling, 1 reply; 11+ messages in thread
From: Alan Modra @ 2020-04-15 3:18 UTC (permalink / raw)
To: H.J. Lu; +Cc: Binutils
The fuzzers certainly found this one quickly.
PR 25821
* readelf.c (get_num_dynamic_syms): Typo fix.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 9149bb8ce4..efcd6f30e7 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -9997,7 +9997,7 @@ get_num_dynamic_syms (Filedata * filedata)
if (chains)
{
free (chains);
- buckets = NULL;
+ chains = NULL;
}
nbuckets = 0;
}
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: V2 [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms table
2020-04-15 3:18 ` Alan Modra
@ 2020-04-15 12:04 ` H.J. Lu
0 siblings, 0 replies; 11+ messages in thread
From: H.J. Lu @ 2020-04-15 12:04 UTC (permalink / raw)
To: Alan Modra; +Cc: Binutils
On Tue, Apr 14, 2020 at 8:19 PM Alan Modra <amodra@gmail.com> wrote:
>
> The fuzzers certainly found this one quickly.
>
> PR 25821
> * readelf.c (get_num_dynamic_syms): Typo fix.
>
> diff --git a/binutils/readelf.c b/binutils/readelf.c
> index 9149bb8ce4..efcd6f30e7 100644
> --- a/binutils/readelf.c
> +++ b/binutils/readelf.c
> @@ -9997,7 +9997,7 @@ get_num_dynamic_syms (Filedata * filedata)
> if (chains)
> {
> free (chains);
> - buckets = NULL;
> + chains = NULL;
> }
> nbuckets = 0;
> }
>
Thanks.
--
H.J.
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2020-04-15 12:04 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-12 13:23 [PATCH] readelf: Compute dynamic symbol table size from hash table H.J. Lu
2020-03-19 12:51 ` [PATCH] readelf: Consolidate --syms --use-dynamic with --dyn-syms table H.J. Lu
2020-03-22 12:34 ` H.J. Lu
2020-04-09 13:01 ` PING " H.J. Lu
2020-04-09 14:43 ` Nick Clifton
2020-04-09 17:35 ` Fangrui Song
2020-04-09 17:52 ` H.J. Lu
2020-04-09 17:51 ` V2 " H.J. Lu
2020-04-14 10:47 ` Nick Clifton
2020-04-15 3:18 ` Alan Modra
2020-04-15 12:04 ` H.J. Lu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).