aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2012-07-17 16:29:36 +0000
committerNick Clifton <nickc@redhat.com>2012-07-17 16:29:36 +0000
commitc2a7d3f57d9b69909262d5c36fd500b94c84542f (patch)
tree7f2fef1bb415096821123c111905209b703fe9ca /binutils
parent2e84b6bfc2f02b1f7f9274d897d62d93faffd483 (diff)
downloadgdb-c2a7d3f57d9b69909262d5c36fd500b94c84542f.zip
gdb-c2a7d3f57d9b69909262d5c36fd500b94c84542f.tar.gz
gdb-c2a7d3f57d9b69909262d5c36fd500b94c84542f.tar.bz2
* elfcomm.c (setup_archive): Extract index table and symbol table
scanning code into... (process_archive_index_and_symbols): ... this function and add support for 64-bit index tables. * elfcomm.h (struct archive_info): Change type of index_num and index_array to elf_vma. Add 'uses_64bit_indicies' field. * readelf.c (process_archive): Fix support for 64-bit indicies.
Diffstat (limited to 'binutils')
-rw-r--r--binutils/ChangeLog11
-rw-r--r--binutils/elfcomm.c269
-rw-r--r--binutils/elfcomm.h5
-rw-r--r--binutils/readelf.c18
4 files changed, 176 insertions, 127 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 7c3018f..3068937 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,14 @@
+2012-07-17 Nick Clifton <nickc@redhat.com>
+
+ * elfcomm.c (setup_archive): Extract index table and symbol table
+ scanning code into...
+ (process_archive_index_and_symbols): ... this function and add
+ support for 64-bit index tables.
+ * elfcomm.h (struct archive_info): Change type of index_num and
+ index_array to elf_vma.
+ Add 'uses_64bit_indicies' field.
+ * readelf.c (process_archive): Fix support for 64-bit indicies.
+
2012-07-03 Nick Clifton <nickc@redhat.com>
* readelf.c (process_archive): Display member indicies when
diff --git a/binutils/elfcomm.c b/binutils/elfcomm.c
index 4224f82..a50b1ec 100644
--- a/binutils/elfcomm.c
+++ b/binutils/elfcomm.c
@@ -29,6 +29,7 @@
#include "aout/ar.h"
#include "bucomm.h"
#include "elfcomm.h"
+#include <assert.h>
void
error (const char *message, ...)
@@ -303,6 +304,146 @@ adjust_relative_path (const char *file_name, const char *name,
return member_file_name;
}
+/* Processes the archive index table and symbol table in ARCH.
+ Entries in the index table are SIZEOF_AR_INDEX bytes long.
+ Fills in ARCH->next_arhdr_offset and ARCH->arhdr.
+ If READ_SYMBOLS is true then fills in ARCH->index_num, ARCH->index_array,
+ ARCH->sym_size and ARCH->sym_table.
+ It is the caller's responsibility to free ARCH->index_array and
+ ARCH->sym_table.
+ Returns TRUE upon success, FALSE otherwise.
+ If failure occurs an error message is printed. */
+
+static bfd_boolean
+process_archive_index_and_symbols (struct archive_info * arch,
+ unsigned int sizeof_ar_index,
+ bfd_boolean read_symbols)
+{
+ size_t got;
+ unsigned long size;
+
+ size = strtoul (arch->arhdr.ar_size, NULL, 10);
+ size = size + (size & 1);
+
+ arch->next_arhdr_offset += sizeof arch->arhdr + size;
+
+ if (! read_symbols)
+ {
+ if (fseek (arch->file, size, SEEK_CUR) != 0)
+ {
+ error (_("%s: failed to skip archive symbol table\n"),
+ arch->file_name);
+ return FALSE;
+ }
+ }
+ else
+ {
+ unsigned long i;
+ /* A buffer used to hold numbers read in from an archive index.
+ These are always SIZEOF_AR_INDEX bytes long and stored in
+ big-endian format. */
+ unsigned char integer_buffer[sizeof arch->index_num];
+ unsigned char * index_buffer;
+
+ assert (sizeof_ar_index <= sizeof integer_buffer);
+
+ /* Check the size of the archive index. */
+ if (size < sizeof_ar_index)
+ {
+ error (_("%s: the archive index is empty\n"), arch->file_name);
+ return FALSE;
+ }
+
+ /* Read the number of entries in the archive index. */
+ got = fread (integer_buffer, 1, sizeof_ar_index, arch->file);
+ if (got != sizeof_ar_index)
+ {
+ error (_("%s: failed to read archive index\n"), arch->file_name);
+ return FALSE;
+ }
+
+ arch->index_num = byte_get_big_endian (integer_buffer, sizeof_ar_index);
+ size -= sizeof_ar_index;
+
+ if (size < arch->index_num * sizeof_ar_index)
+ {
+ error (_("%s: the archive index is supposed to have %ld entries of %d bytes, but the size is only %ld\n"),
+ arch->file_name, (long) arch->index_num, sizeof_ar_index, size);
+ return FALSE;
+ }
+
+ /* Read in the archive index. */
+ index_buffer = (unsigned char *)
+ malloc (arch->index_num * sizeof_ar_index);
+ if (index_buffer == NULL)
+ {
+ error (_("Out of memory whilst trying to read archive symbol index\n"));
+ return FALSE;
+ }
+
+ got = fread (index_buffer, sizeof_ar_index, arch->index_num, arch->file);
+ if (got != arch->index_num)
+ {
+ free (index_buffer);
+ error (_("%s: failed to read archive index\n"), arch->file_name);
+ return FALSE;
+ }
+
+ size -= arch->index_num * sizeof_ar_index;
+
+ /* Convert the index numbers into the host's numeric format. */
+ arch->index_array = (elf_vma *)
+ malloc (arch->index_num * sizeof (* arch->index_array));
+ if (arch->index_array == NULL)
+ {
+ free (index_buffer);
+ error (_("Out of memory whilst trying to convert the archive symbol index\n"));
+ return FALSE;
+ }
+
+ for (i = 0; i < arch->index_num; i++)
+ arch->index_array[i] =
+ byte_get_big_endian ((unsigned char *) (index_buffer + (i * sizeof_ar_index)),
+ sizeof_ar_index);
+ free (index_buffer);
+
+ /* The remaining space in the header is taken up by the symbol table. */
+ if (size < 1)
+ {
+ error (_("%s: the archive has an index but no symbols\n"),
+ arch->file_name);
+ return FALSE;
+ }
+
+ arch->sym_table = (char *) malloc (size);
+ if (arch->sym_table == NULL)
+ {
+ error (_("Out of memory whilst trying to read archive index symbol table\n"));
+ return FALSE;
+ }
+
+ arch->sym_size = size;
+ got = fread (arch->sym_table, 1, size, arch->file);
+ if (got != size)
+ {
+ error (_("%s: failed to read archive index symbol table\n"),
+ arch->file_name);
+ return FALSE;
+ }
+ }
+
+ /* Read the next archive header. */
+ got = fread (&arch->arhdr, 1, sizeof arch->arhdr, arch->file);
+ if (got != sizeof arch->arhdr && got != 0)
+ {
+ error (_("%s: failed to read archive header following archive index\n"),
+ arch->file_name);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/* Read the symbol table and long-name table from an archive. */
int
@@ -311,7 +452,6 @@ setup_archive (struct archive_info *arch, const char *file_name,
bfd_boolean read_symbols)
{
size_t got;
- unsigned long size;
arch->file_name = strdup (file_name);
arch->file = file;
@@ -323,6 +463,7 @@ setup_archive (struct archive_info *arch, const char *file_name,
arch->longnames_size = 0;
arch->nested_member_origin = 0;
arch->is_thin_archive = is_thin_archive;
+ arch->uses_64bit_indicies = FALSE;
arch->next_arhdr_offset = SARMAG;
/* Read the first archive member header. */
@@ -342,124 +483,16 @@ setup_archive (struct archive_info *arch, const char *file_name,
}
/* See if this is the archive symbol table. */
- if (const_strneq (arch->arhdr.ar_name, "/ ")
- || const_strneq (arch->arhdr.ar_name, "/SYM64/ "))
+ if (const_strneq (arch->arhdr.ar_name, "/ "))
{
- size = strtoul (arch->arhdr.ar_size, NULL, 10);
- size = size + (size & 1);
-
- arch->next_arhdr_offset += sizeof arch->arhdr + size;
-
- if (read_symbols)
- {
- unsigned long i;
- /* A buffer used to hold numbers read in from an archive index.
- These are always 4 bytes long and stored in big-endian
- format. */
-#define SIZEOF_AR_INDEX_NUMBERS 4
- unsigned char integer_buffer[SIZEOF_AR_INDEX_NUMBERS];
- unsigned char * index_buffer;
-
- /* Check the size of the archive index. */
- if (size < SIZEOF_AR_INDEX_NUMBERS)
- {
- error (_("%s: the archive index is empty\n"), file_name);
- return 1;
- }
-
- /* Read the numer of entries in the archive index. */
- got = fread (integer_buffer, 1, sizeof integer_buffer, file);
- if (got != sizeof (integer_buffer))
- {
- error (_("%s: failed to read archive index\n"), file_name);
- return 1;
- }
- arch->index_num = byte_get_big_endian (integer_buffer,
- sizeof integer_buffer);
- size -= SIZEOF_AR_INDEX_NUMBERS;
-
- /* Read in the archive index. */
- if (size < arch->index_num * SIZEOF_AR_INDEX_NUMBERS)
- {
- error (_("%s: the archive index is supposed to have %ld entries, but the size in the header is too small\n"),
- file_name, arch->index_num);
- return 1;
- }
- index_buffer = (unsigned char *)
- malloc (arch->index_num * SIZEOF_AR_INDEX_NUMBERS);
- if (index_buffer == NULL)
- {
- error (_("Out of memory whilst trying to read archive symbol index\n"));
- return 1;
- }
- got = fread (index_buffer, SIZEOF_AR_INDEX_NUMBERS,
- arch->index_num, file);
- if (got != arch->index_num)
- {
- free (index_buffer);
- error (_("%s: failed to read archive index\n"), file_name);
- return 1;
- }
- size -= arch->index_num * SIZEOF_AR_INDEX_NUMBERS;
-
- /* Convert the index numbers into the host's numeric format. */
- arch->index_array = (long unsigned int *)
- malloc (arch->index_num * sizeof (* arch->index_array));
- if (arch->index_array == NULL)
- {
- free (index_buffer);
- error (_("Out of memory whilst trying to convert the archive symbol index\n"));
- return 1;
- }
-
- for (i = 0; i < arch->index_num; i++)
- arch->index_array[i] = byte_get_big_endian ((unsigned char *) (index_buffer + (i * SIZEOF_AR_INDEX_NUMBERS)),
- SIZEOF_AR_INDEX_NUMBERS);
- free (index_buffer);
-
- /* The remaining space in the header is taken up by the symbol
- table. */
- if (size < 1)
- {
- error (_("%s: the archive has an index but no symbols\n"),
- file_name);
- return 1;
- }
- arch->sym_table = (char *) malloc (size);
- arch->sym_size = size;
- if (arch->sym_table == NULL)
- {
- error (_("Out of memory whilst trying to read archive index symbol table\n"));
- return 1;
- }
- got = fread (arch->sym_table, 1, size, file);
- if (got != size)
- {
- error (_("%s: failed to read archive index symbol table\n"),
- file_name);
- return 1;
- }
- }
- else
- {
- if (fseek (file, size, SEEK_CUR) != 0)
- {
- error (_("%s: failed to skip archive symbol table\n"),
- file_name);
- return 1;
- }
- }
-
- /* Read the next archive header. */
- got = fread (&arch->arhdr, 1, sizeof arch->arhdr, file);
- if (got != sizeof arch->arhdr)
- {
- if (got == 0)
- return 0;
- error (_("%s: failed to read archive header following archive index\n"),
- file_name);
- return 1;
- }
+ if (! process_archive_index_and_symbols (arch, 4, read_symbols))
+ return 1;
+ }
+ else if (const_strneq (arch->arhdr.ar_name, "/SYM64/ "))
+ {
+ arch->uses_64bit_indicies = TRUE;
+ if (! process_archive_index_and_symbols (arch, 8, read_symbols))
+ return 1;
}
else if (read_symbols)
printf (_("%s has no archive index\n"), file_name);
diff --git a/binutils/elfcomm.h b/binutils/elfcomm.h
index 2a3c913..a8c3aa3 100644
--- a/binutils/elfcomm.h
+++ b/binutils/elfcomm.h
@@ -64,8 +64,8 @@ struct archive_info
{
char * file_name; /* Archive file name. */
FILE * file; /* Open file descriptor. */
- unsigned long index_num; /* Number of symbols in table. */
- unsigned long * index_array; /* The array of member offsets. */
+ elf_vma index_num; /* Number of symbols in table. */
+ elf_vma * index_array; /* The array of member offsets. */
char * sym_table; /* The symbol table. */
unsigned long sym_size; /* Size of the symbol table. */
char * longnames; /* The long file names table. */
@@ -73,6 +73,7 @@ struct archive_info
unsigned long nested_member_origin; /* Origin in the nested archive of the current member. */
unsigned long next_arhdr_offset; /* Offset of the next archive header. */
bfd_boolean is_thin_archive; /* TRUE if this is a thin archive. */
+ bfd_boolean uses_64bit_indicies; /* TRUE if the index table uses 64bit entries. */
struct ar_hdr arhdr; /* Current archive header. */
};
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 2fcd582..e6f2be6 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -13442,7 +13442,7 @@ process_archive (char * file_name, FILE * file, bfd_boolean is_thin_archive)
unsigned long current_pos;
printf (_("Index of archive %s: (%ld entries, 0x%lx bytes in the symbol table)\n"),
- file_name, arch.index_num, arch.sym_size);
+ file_name, (long) arch.index_num, arch.sym_size);
current_pos = ftell (file);
for (i = l = 0; i < arch.index_num; i++)
@@ -13459,8 +13459,9 @@ process_archive (char * file_name, FILE * file, bfd_boolean is_thin_archive)
if (qualified_name != NULL)
{
- printf (_("Binary %s at offset 0x%lx contains:\n"),
- qualified_name, arch.index_array[i]);
+ printf (_("Contents of binary %s at offset "), qualified_name);
+ (void) print_vma (arch.index_array[i], PREFIX_HEX);
+ putchar ('\n');
free (qualified_name);
}
}
@@ -13476,11 +13477,14 @@ process_archive (char * file_name, FILE * file, bfd_boolean is_thin_archive)
l += strlen (arch.sym_table + l) + 1;
}
- if (l & 01)
- ++l;
+ if (arch.uses_64bit_indicies)
+ l = (l + 7) & ~ 7;
+ else
+ l += l & 1;
+
if (l < arch.sym_size)
- error (_("%s: symbols remain in the index symbol table, but without corresponding entries in the index table\n"),
- file_name);
+ error (_("%s: %ld bytes remain in the symbol table, but without corresponding entries in the index table\n"),
+ file_name, arch.sym_size - l);
if (fseek (file, current_pos, SEEK_SET) != 0)
{