diff options
author | Nick Clifton <nickc@redhat.com> | 2012-07-17 16:29:36 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2012-07-17 16:29:36 +0000 |
commit | c2a7d3f57d9b69909262d5c36fd500b94c84542f (patch) | |
tree | 7f2fef1bb415096821123c111905209b703fe9ca /binutils/elfcomm.c | |
parent | 2e84b6bfc2f02b1f7f9274d897d62d93faffd483 (diff) | |
download | gdb-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/elfcomm.c')
-rw-r--r-- | binutils/elfcomm.c | 269 |
1 files changed, 151 insertions, 118 deletions
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); |