* readelf.c (adjust_relative_path): New function.
(struct archive_info): New type. (setup_archive): New function. (release_archive): New function. (setup_nested_archive): New function. (get_archive_member_name): New function. (get_archive_member_name_at): New function. (make_qualified_name): New function. (process_archive): Factor out code for reading archive index and long filename table to setup_archive. Add support for thin archives.
This commit is contained in:
parent
83cf10fd4a
commit
2cf0635d9d
2 changed files with 854 additions and 557 deletions
|
@ -1,3 +1,16 @@
|
||||||
|
2009-03-02 Cary Coutant <ccoutant@google.com>
|
||||||
|
|
||||||
|
* readelf.c (adjust_relative_path): New function.
|
||||||
|
(struct archive_info): New type.
|
||||||
|
(setup_archive): New function.
|
||||||
|
(release_archive): New function.
|
||||||
|
(setup_nested_archive): New function.
|
||||||
|
(get_archive_member_name): New function.
|
||||||
|
(get_archive_member_name_at): New function.
|
||||||
|
(make_qualified_name): New function.
|
||||||
|
(process_archive): Factor out code for reading archive index and
|
||||||
|
long filename table to setup_archive. Add support for thin archives.
|
||||||
|
|
||||||
2009-03-02 Nick Clifton <nickc@redhat.com>
|
2009-03-02 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
* po/sk.po: Updated Slovak translation.
|
* po/sk.po: Updated Slovak translation.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* readelf.c -- display contents of an ELF format file
|
/* readelf.c -- display contents of an ELF format file
|
||||||
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||||
2008 Free Software Foundation, Inc.
|
2008, 2009 Free Software Foundation, Inc.
|
||||||
|
|
||||||
Originally developed by Eric Youngdale <eric@andante.jic.com>
|
Originally developed by Eric Youngdale <eric@andante.jic.com>
|
||||||
Modifications by Nick Clifton <nickc@redhat.com>
|
Modifications by Nick Clifton <nickc@redhat.com>
|
||||||
|
@ -145,6 +145,7 @@
|
||||||
#include "getopt.h"
|
#include "getopt.h"
|
||||||
#include "libiberty.h"
|
#include "libiberty.h"
|
||||||
#include "safe-ctype.h"
|
#include "safe-ctype.h"
|
||||||
|
#include "filenames.h"
|
||||||
|
|
||||||
char * program_name = "readelf";
|
char * program_name = "readelf";
|
||||||
int do_wide;
|
int do_wide;
|
||||||
|
@ -870,7 +871,6 @@ dump_relocations (FILE *file,
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
Elf_Internal_Rela * rels;
|
Elf_Internal_Rela * rels;
|
||||||
|
|
||||||
|
|
||||||
if (is_rela == UNKNOWN)
|
if (is_rela == UNKNOWN)
|
||||||
is_rela = guess_is_rela (elf_header.e_machine);
|
is_rela = guess_is_rela (elf_header.e_machine);
|
||||||
|
|
||||||
|
@ -4411,7 +4411,8 @@ process_section_groups (FILE *file)
|
||||||
Elf_Internal_Shdr * section;
|
Elf_Internal_Shdr * section;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct group * group;
|
struct group * group;
|
||||||
Elf_Internal_Shdr *symtab_sec, *strtab_sec;
|
Elf_Internal_Shdr * symtab_sec;
|
||||||
|
Elf_Internal_Shdr * strtab_sec;
|
||||||
Elf_Internal_Sym * symtab;
|
Elf_Internal_Sym * symtab;
|
||||||
char * strtab;
|
char * strtab;
|
||||||
size_t strtab_size;
|
size_t strtab_size;
|
||||||
|
@ -4480,7 +4481,8 @@ process_section_groups (FILE *file)
|
||||||
{
|
{
|
||||||
char * name = SECTION_NAME (section);
|
char * name = SECTION_NAME (section);
|
||||||
char * group_name;
|
char * group_name;
|
||||||
unsigned char *start, *indices;
|
unsigned char * start;
|
||||||
|
unsigned char * indices;
|
||||||
unsigned int entry, j, size;
|
unsigned int entry, j, size;
|
||||||
Elf_Internal_Shdr * sec;
|
Elf_Internal_Shdr * sec;
|
||||||
Elf_Internal_Sym * sym;
|
Elf_Internal_Sym * sym;
|
||||||
|
@ -4839,7 +4841,8 @@ find_symbol_for_address (Elf_Internal_Sym *symtab,
|
||||||
bfd_vma * offset)
|
bfd_vma * offset)
|
||||||
{
|
{
|
||||||
bfd_vma dist = 0x100000;
|
bfd_vma dist = 0x100000;
|
||||||
Elf_Internal_Sym *sym, *best = NULL;
|
Elf_Internal_Sym * sym;
|
||||||
|
Elf_Internal_Sym * best = NULL;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
|
||||||
for (i = 0, sym = symtab; i < nsyms; ++i, ++sym)
|
for (i = 0, sym = symtab; i < nsyms; ++i, ++sym)
|
||||||
|
@ -4932,8 +4935,10 @@ slurp_ia64_unwind_table (FILE *file,
|
||||||
Elf_Internal_Phdr * seg;
|
Elf_Internal_Phdr * seg;
|
||||||
struct ia64_unw_table_entry * tep;
|
struct ia64_unw_table_entry * tep;
|
||||||
Elf_Internal_Shdr * relsec;
|
Elf_Internal_Shdr * relsec;
|
||||||
Elf_Internal_Rela *rela, *rp;
|
Elf_Internal_Rela * rela;
|
||||||
unsigned char *table, *tp;
|
Elf_Internal_Rela * rp;
|
||||||
|
unsigned char * table;
|
||||||
|
unsigned char * tp;
|
||||||
Elf_Internal_Sym * sym;
|
Elf_Internal_Sym * sym;
|
||||||
const char * relname;
|
const char * relname;
|
||||||
|
|
||||||
|
@ -5048,7 +5053,9 @@ slurp_ia64_unwind_table (FILE *file,
|
||||||
static int
|
static int
|
||||||
ia64_process_unwind (FILE * file)
|
ia64_process_unwind (FILE * file)
|
||||||
{
|
{
|
||||||
Elf_Internal_Shdr *sec, *unwsec = NULL, *strsec;
|
Elf_Internal_Shdr * sec;
|
||||||
|
Elf_Internal_Shdr * unwsec = NULL;
|
||||||
|
Elf_Internal_Shdr * strsec;
|
||||||
unsigned long i, unwcount = 0, unwstart = 0;
|
unsigned long i, unwcount = 0, unwstart = 0;
|
||||||
struct ia64_unw_aux_info aux;
|
struct ia64_unw_aux_info aux;
|
||||||
|
|
||||||
|
@ -5304,8 +5311,10 @@ slurp_hppa_unwind_table (FILE *file,
|
||||||
Elf_Internal_Phdr * seg;
|
Elf_Internal_Phdr * seg;
|
||||||
struct hppa_unw_table_entry * tep;
|
struct hppa_unw_table_entry * tep;
|
||||||
Elf_Internal_Shdr * relsec;
|
Elf_Internal_Shdr * relsec;
|
||||||
Elf_Internal_Rela *rela, *rp;
|
Elf_Internal_Rela * rela;
|
||||||
unsigned char *table, *tp;
|
Elf_Internal_Rela * rp;
|
||||||
|
unsigned char * table;
|
||||||
|
unsigned char * tp;
|
||||||
Elf_Internal_Sym * sym;
|
Elf_Internal_Sym * sym;
|
||||||
const char * relname;
|
const char * relname;
|
||||||
|
|
||||||
|
@ -5512,10 +5521,12 @@ hppa_process_unwind (FILE *file)
|
||||||
static int
|
static int
|
||||||
process_unwind (FILE * file)
|
process_unwind (FILE * file)
|
||||||
{
|
{
|
||||||
struct unwind_handler {
|
struct unwind_handler
|
||||||
|
{
|
||||||
int machtype;
|
int machtype;
|
||||||
int (*handler)(FILE *file);
|
int (* handler)(FILE *);
|
||||||
} handlers[] = {
|
} handlers[] =
|
||||||
|
{
|
||||||
{ EM_IA_64, ia64_process_unwind },
|
{ EM_IA_64, ia64_process_unwind },
|
||||||
{ EM_PARISC, hppa_process_unwind },
|
{ EM_PARISC, hppa_process_unwind },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
|
@ -5690,7 +5701,8 @@ dynamic_section_ia64_val (Elf_Internal_Dyn *entry)
|
||||||
static int
|
static int
|
||||||
get_32bit_dynamic_section (FILE * file)
|
get_32bit_dynamic_section (FILE * file)
|
||||||
{
|
{
|
||||||
Elf32_External_Dyn *edyn, *ext;
|
Elf32_External_Dyn * edyn;
|
||||||
|
Elf32_External_Dyn * ext;
|
||||||
Elf_Internal_Dyn * entry;
|
Elf_Internal_Dyn * entry;
|
||||||
|
|
||||||
edyn = get_data (NULL, file, dynamic_addr, 1, dynamic_size,
|
edyn = get_data (NULL, file, dynamic_addr, 1, dynamic_size,
|
||||||
|
@ -5734,7 +5746,8 @@ get_32bit_dynamic_section (FILE *file)
|
||||||
static int
|
static int
|
||||||
get_64bit_dynamic_section (FILE * file)
|
get_64bit_dynamic_section (FILE * file)
|
||||||
{
|
{
|
||||||
Elf64_External_Dyn *edyn, *ext;
|
Elf64_External_Dyn * edyn;
|
||||||
|
Elf64_External_Dyn * ext;
|
||||||
Elf_Internal_Dyn * entry;
|
Elf_Internal_Dyn * entry;
|
||||||
|
|
||||||
edyn = get_data (NULL, file, dynamic_addr, 1, dynamic_size,
|
edyn = get_data (NULL, file, dynamic_addr, 1, dynamic_size,
|
||||||
|
@ -5943,7 +5956,8 @@ process_dynamic_section (FILE *file)
|
||||||
|
|
||||||
if (dynamic_syminfo_offset != 0 && syminsz != 0)
|
if (dynamic_syminfo_offset != 0 && syminsz != 0)
|
||||||
{
|
{
|
||||||
Elf_External_Syminfo *extsyminfo, *extsym;
|
Elf_External_Syminfo * extsyminfo;
|
||||||
|
Elf_External_Syminfo * extsym;
|
||||||
Elf_Internal_Syminfo * syminfo;
|
Elf_Internal_Syminfo * syminfo;
|
||||||
|
|
||||||
/* There is a syminfo section. Read the data. */
|
/* There is a syminfo section. Read the data. */
|
||||||
|
@ -7302,7 +7316,6 @@ process_symbol_table (FILE *file)
|
||||||
Elf_Internal_Sym * symtab;
|
Elf_Internal_Sym * symtab;
|
||||||
Elf_Internal_Sym * psym;
|
Elf_Internal_Sym * psym;
|
||||||
|
|
||||||
|
|
||||||
if ( section->sh_type != SHT_SYMTAB
|
if ( section->sh_type != SHT_SYMTAB
|
||||||
&& section->sh_type != SHT_DYNSYM)
|
&& section->sh_type != SHT_DYNSYM)
|
||||||
continue;
|
continue;
|
||||||
|
@ -8300,7 +8313,8 @@ debug_apply_relocations (void *file,
|
||||||
{
|
{
|
||||||
bfd_boolean is_rela;
|
bfd_boolean is_rela;
|
||||||
unsigned long num_relocs;
|
unsigned long num_relocs;
|
||||||
Elf_Internal_Rela *relocs, *rp;
|
Elf_Internal_Rela * relocs;
|
||||||
|
Elf_Internal_Rela * rp;
|
||||||
Elf_Internal_Shdr * symsec;
|
Elf_Internal_Shdr * symsec;
|
||||||
Elf_Internal_Sym * symtab;
|
Elf_Internal_Sym * symtab;
|
||||||
Elf_Internal_Sym * sym;
|
Elf_Internal_Sym * sym;
|
||||||
|
@ -8731,6 +8745,7 @@ static arm_attr_public_tag arm_attr_public_tags[] =
|
||||||
|
|
||||||
/* Read an unsigned LEB128 encoded value from p. Set *PLEN to the number of
|
/* Read an unsigned LEB128 encoded value from p. Set *PLEN to the number of
|
||||||
bytes read. */
|
bytes read. */
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
read_uleb128 (unsigned char * p, unsigned int * plen)
|
read_uleb128 (unsigned char * p, unsigned int * plen)
|
||||||
{
|
{
|
||||||
|
@ -9864,7 +9879,8 @@ process_mips_specific (FILE *file)
|
||||||
static int
|
static int
|
||||||
process_gnu_liblist (FILE * file)
|
process_gnu_liblist (FILE * file)
|
||||||
{
|
{
|
||||||
Elf_Internal_Shdr *section, *string_sec;
|
Elf_Internal_Shdr * section;
|
||||||
|
Elf_Internal_Shdr * string_sec;
|
||||||
Elf32_External_Lib * elib;
|
Elf32_External_Lib * elib;
|
||||||
char * strtab;
|
char * strtab;
|
||||||
size_t strtab_size;
|
size_t strtab_size;
|
||||||
|
@ -10514,7 +10530,8 @@ process_object (char *file_name, FILE *file)
|
||||||
|
|
||||||
if (section_groups)
|
if (section_groups)
|
||||||
{
|
{
|
||||||
struct group_list *g, *next;
|
struct group_list * g;
|
||||||
|
struct group_list * next;
|
||||||
|
|
||||||
for (i = 0; i < group_count; i++)
|
for (i = 0; i < group_count; i++)
|
||||||
{
|
{
|
||||||
|
@ -10534,28 +10551,98 @@ process_object (char *file_name, FILE *file)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process an ELF archive.
|
/* Return the path name for a proxy entry in a thin archive, adjusted relative
|
||||||
On entry the file is positioned just after the ARMAG string. */
|
to the path name of the thin archive itself if necessary. Always returns
|
||||||
|
a pointer to malloc'ed memory. */
|
||||||
|
|
||||||
|
static char *
|
||||||
|
adjust_relative_path (char * file_name, char * name, int name_len)
|
||||||
|
{
|
||||||
|
char * member_file_name;
|
||||||
|
const char * base_name = lbasename (file_name);
|
||||||
|
|
||||||
|
/* This is a proxy entry for a thin archive member.
|
||||||
|
If the extended name table contains an absolute path
|
||||||
|
name, or if the archive is in the current directory,
|
||||||
|
use the path name as given. Otherwise, we need to
|
||||||
|
find the member relative to the directory where the
|
||||||
|
archive is located. */
|
||||||
|
if (IS_ABSOLUTE_PATH (name) || base_name == file_name)
|
||||||
|
{
|
||||||
|
member_file_name = malloc (name_len + 1);
|
||||||
|
if (member_file_name == NULL)
|
||||||
|
{
|
||||||
|
error (_("Out of memory\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy (member_file_name, name, name_len);
|
||||||
|
member_file_name[name_len] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Concatenate the path components of the archive file name
|
||||||
|
to the relative path name from the extended name table. */
|
||||||
|
size_t prefix_len = base_name - file_name;
|
||||||
|
member_file_name = malloc (prefix_len + name_len + 1);
|
||||||
|
if (member_file_name == NULL)
|
||||||
|
{
|
||||||
|
error (_("Out of memory\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy (member_file_name, file_name, prefix_len);
|
||||||
|
memcpy (member_file_name + prefix_len, name, name_len);
|
||||||
|
member_file_name[prefix_len + name_len] = '\0';
|
||||||
|
}
|
||||||
|
return member_file_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Structure to hold information about an archive file. */
|
||||||
|
|
||||||
|
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. */
|
||||||
|
char * sym_table; /* The symbol table. */
|
||||||
|
unsigned long sym_size; /* Size of the symbol table. */
|
||||||
|
char * longnames; /* The long file names table. */
|
||||||
|
unsigned long longnames_size; /* Size of the long file names table. */
|
||||||
|
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. */
|
||||||
|
struct ar_hdr arhdr; /* Current archive header. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Read the symbol table and long-name table from an archive. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_archive (char *file_name, FILE *file)
|
setup_archive (struct archive_info * arch, char * file_name, FILE * file,
|
||||||
|
bfd_boolean is_thin_archive, bfd_boolean read_symbols)
|
||||||
{
|
{
|
||||||
struct ar_hdr arhdr;
|
|
||||||
size_t got;
|
size_t got;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
unsigned long index_num = 0;
|
|
||||||
unsigned long *index_array = NULL;
|
|
||||||
char *sym_table = NULL;
|
|
||||||
unsigned long sym_size = 0;
|
|
||||||
char *longnames = NULL;
|
|
||||||
unsigned long longnames_size = 0;
|
|
||||||
size_t file_name_size;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
show_name = 1;
|
arch->file_name = strdup (file_name);
|
||||||
|
arch->file = file;
|
||||||
|
arch->index_num = 0;
|
||||||
|
arch->index_array = NULL;
|
||||||
|
arch->sym_table = NULL;
|
||||||
|
arch->sym_size = 0;
|
||||||
|
arch->longnames = NULL;
|
||||||
|
arch->longnames_size = 0;
|
||||||
|
arch->nested_member_origin = 0;
|
||||||
|
arch->is_thin_archive = is_thin_archive;
|
||||||
|
arch->next_arhdr_offset = SARMAG;
|
||||||
|
|
||||||
got = fread (&arhdr, 1, sizeof arhdr, file);
|
/* Read the first archive member header. */
|
||||||
if (got != sizeof arhdr)
|
if (fseek (file, SARMAG, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
error (_("%s: failed to seek to first archive header\n"), file_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
got = fread (&arch->arhdr, 1, sizeof arch->arhdr, file);
|
||||||
|
if (got != sizeof arch->arhdr)
|
||||||
{
|
{
|
||||||
if (got == 0)
|
if (got == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -10565,13 +10652,15 @@ process_archive (char *file_name, FILE *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See if this is the archive symbol table. */
|
/* See if this is the archive symbol table. */
|
||||||
if (const_strneq (arhdr.ar_name, "/ ")
|
if (const_strneq (arch->arhdr.ar_name, "/ ")
|
||||||
|| const_strneq (arhdr.ar_name, "/SYM64/ "))
|
|| const_strneq (arch->arhdr.ar_name, "/SYM64/ "))
|
||||||
{
|
{
|
||||||
size = strtoul (arhdr.ar_size, NULL, 10);
|
size = strtoul (arch->arhdr.ar_size, NULL, 10);
|
||||||
size = size + (size & 1);
|
size = size + (size & 1);
|
||||||
|
|
||||||
if (do_archive_index)
|
arch->next_arhdr_offset += sizeof arch->arhdr + size;
|
||||||
|
|
||||||
|
if (read_symbols)
|
||||||
{
|
{
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
/* A buffer used to hold numbers read in from an archive index.
|
/* A buffer used to hold numbers read in from an archive index.
|
||||||
|
@ -10594,43 +10683,42 @@ process_archive (char *file_name, FILE *file)
|
||||||
error (_("%s: failed to read archive index\n"), file_name);
|
error (_("%s: failed to read archive index\n"), file_name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
index_num = byte_get_big_endian (integer_buffer, sizeof integer_buffer);
|
arch->index_num = byte_get_big_endian (integer_buffer, sizeof integer_buffer);
|
||||||
size -= SIZEOF_AR_INDEX_NUMBERS;
|
size -= SIZEOF_AR_INDEX_NUMBERS;
|
||||||
|
|
||||||
/* Read in the archive index. */
|
/* Read in the archive index. */
|
||||||
if (size < index_num * SIZEOF_AR_INDEX_NUMBERS)
|
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"),
|
error (_("%s: the archive index is supposed to have %ld entries, but the size in the header is too small\n"),
|
||||||
file_name, index_num);
|
file_name, arch->index_num);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
index_buffer = malloc (index_num * SIZEOF_AR_INDEX_NUMBERS);
|
index_buffer = malloc (arch->index_num * SIZEOF_AR_INDEX_NUMBERS);
|
||||||
if (index_buffer == NULL)
|
if (index_buffer == NULL)
|
||||||
{
|
{
|
||||||
error (_("Out of memory whilst trying to read archive symbol index\n"));
|
error (_("Out of memory whilst trying to read archive symbol index\n"));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
got = fread (index_buffer, SIZEOF_AR_INDEX_NUMBERS, index_num, file);
|
got = fread (index_buffer, SIZEOF_AR_INDEX_NUMBERS, arch->index_num, file);
|
||||||
if (got != index_num)
|
if (got != arch->index_num)
|
||||||
{
|
{
|
||||||
free (index_buffer);
|
free (index_buffer);
|
||||||
error (_("%s: failed to read archive index\n"), file_name);
|
error (_("%s: failed to read archive index\n"), file_name);
|
||||||
ret = 1;
|
return 1;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
size -= index_num * SIZEOF_AR_INDEX_NUMBERS;
|
size -= arch->index_num * SIZEOF_AR_INDEX_NUMBERS;
|
||||||
|
|
||||||
/* Convert the index numbers into the host's numeric format. */
|
/* Convert the index numbers into the host's numeric format. */
|
||||||
index_array = malloc (index_num * sizeof (* index_array));
|
arch->index_array = malloc (arch->index_num * sizeof (* arch->index_array));
|
||||||
if (index_array == NULL)
|
if (arch->index_array == NULL)
|
||||||
{
|
{
|
||||||
free (index_buffer);
|
free (index_buffer);
|
||||||
error (_("Out of memory whilst trying to convert the archive symbol index\n"));
|
error (_("Out of memory whilst trying to convert the archive symbol index\n"));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < index_num; i++)
|
for (i = 0; i < arch->index_num; i++)
|
||||||
index_array[i] = byte_get_big_endian ((unsigned char *)(index_buffer + (i * SIZEOF_AR_INDEX_NUMBERS)),
|
arch->index_array[i] = byte_get_big_endian ((unsigned char *) (index_buffer + (i * SIZEOF_AR_INDEX_NUMBERS)),
|
||||||
SIZEOF_AR_INDEX_NUMBERS);
|
SIZEOF_AR_INDEX_NUMBERS);
|
||||||
free (index_buffer);
|
free (index_buffer);
|
||||||
|
|
||||||
|
@ -10638,23 +10726,20 @@ process_archive (char *file_name, FILE *file)
|
||||||
if (size < 1)
|
if (size < 1)
|
||||||
{
|
{
|
||||||
error (_("%s: the archive has an index but no symbols\n"), file_name);
|
error (_("%s: the archive has an index but no symbols\n"), file_name);
|
||||||
ret = 1;
|
return 1;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
sym_table = malloc (size);
|
arch->sym_table = malloc (size);
|
||||||
sym_size = size;
|
arch->sym_size = size;
|
||||||
if (sym_table == NULL)
|
if (arch->sym_table == NULL)
|
||||||
{
|
{
|
||||||
error (_("Out of memory whilst trying to read archive index symbol table\n"));
|
error (_("Out of memory whilst trying to read archive index symbol table\n"));
|
||||||
ret = 1;
|
return 1;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
got = fread (sym_table, 1, size, file);
|
got = fread (arch->sym_table, 1, size, file);
|
||||||
if (got != size)
|
if (got != size)
|
||||||
{
|
{
|
||||||
error (_("%s: failed to read archive index symbol table\n"), file_name);
|
error (_("%s: failed to read archive index symbol table\n"), file_name);
|
||||||
ret = 1;
|
return 1;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -10666,135 +10751,304 @@ process_archive (char *file_name, FILE *file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
got = fread (& arhdr, 1, sizeof arhdr, file);
|
/* Read the next archive header. */
|
||||||
if (got != sizeof arhdr)
|
got = fread (&arch->arhdr, 1, sizeof arch->arhdr, file);
|
||||||
|
if (got != sizeof arch->arhdr)
|
||||||
{
|
{
|
||||||
if (got == 0)
|
if (got == 0)
|
||||||
{
|
return 0;
|
||||||
ret = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
error (_("%s: failed to read archive header following archive index\n"), file_name);
|
error (_("%s: failed to read archive header following archive index\n"), file_name);
|
||||||
ret = 1;
|
return 1;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (do_archive_index)
|
else if (read_symbols)
|
||||||
printf (_("%s has no archive index\n"), file_name);
|
printf (_("%s has no archive index\n"), file_name);
|
||||||
|
|
||||||
if (const_strneq (arhdr.ar_name, "// "))
|
if (const_strneq (arch->arhdr.ar_name, "// "))
|
||||||
{
|
{
|
||||||
/* This is the archive string table holding long member
|
/* This is the archive string table holding long member names. */
|
||||||
names. */
|
arch->longnames_size = strtoul (arch->arhdr.ar_size, NULL, 10);
|
||||||
|
arch->next_arhdr_offset += sizeof arch->arhdr + arch->longnames_size;
|
||||||
|
|
||||||
longnames_size = strtoul (arhdr.ar_size, NULL, 10);
|
arch->longnames = malloc (arch->longnames_size);
|
||||||
longnames = malloc (longnames_size);
|
if (arch->longnames == NULL)
|
||||||
if (longnames == NULL)
|
|
||||||
{
|
{
|
||||||
error (_("Out of memory reading long symbol names in archive\n"));
|
error (_("Out of memory reading long symbol names in archive\n"));
|
||||||
ret = 1;
|
return 1;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fread (longnames, longnames_size, 1, file) != 1)
|
if (fread (arch->longnames, arch->longnames_size, 1, file) != 1)
|
||||||
{
|
{
|
||||||
free (longnames);
|
free (arch->longnames);
|
||||||
|
arch->longnames = NULL;
|
||||||
error (_("%s: failed to read long symbol name string table\n"), file_name);
|
error (_("%s: failed to read long symbol name string table\n"), file_name);
|
||||||
ret = 1;
|
return 1;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((longnames_size & 1) != 0)
|
if ((arch->longnames_size & 1) != 0)
|
||||||
getc (file);
|
getc (file);
|
||||||
|
}
|
||||||
|
|
||||||
got = fread (& arhdr, 1, sizeof arhdr, file);
|
return 0;
|
||||||
if (got != sizeof arhdr)
|
}
|
||||||
|
|
||||||
|
/* Release the memory used for the archive information. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
release_archive (struct archive_info * arch)
|
||||||
{
|
{
|
||||||
if (got == 0)
|
if (arch->file_name != NULL)
|
||||||
ret = 0;
|
free (arch->file_name);
|
||||||
|
if (arch->index_array != NULL)
|
||||||
|
free (arch->index_array);
|
||||||
|
if (arch->sym_table != NULL)
|
||||||
|
free (arch->sym_table);
|
||||||
|
if (arch->longnames != NULL)
|
||||||
|
free (arch->longnames);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open and setup a nested archive, if not already open. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
setup_nested_archive (struct archive_info * nested_arch, char * member_file_name)
|
||||||
|
{
|
||||||
|
FILE * member_file;
|
||||||
|
|
||||||
|
/* Have we already setup this archive? */
|
||||||
|
if (nested_arch->file_name != NULL
|
||||||
|
&& streq (nested_arch->file_name, member_file_name))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Close previous file and discard cached information. */
|
||||||
|
if (nested_arch->file != NULL)
|
||||||
|
fclose (nested_arch->file);
|
||||||
|
release_archive (nested_arch);
|
||||||
|
|
||||||
|
member_file = fopen (member_file_name, "rb");
|
||||||
|
if (member_file == NULL)
|
||||||
|
return 1;
|
||||||
|
return setup_archive (nested_arch, member_file_name, member_file, FALSE, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_archive_member_name_at (struct archive_info * arch,
|
||||||
|
unsigned long offset,
|
||||||
|
struct archive_info * nested_arch);
|
||||||
|
|
||||||
|
/* Get the name of an archive member from the current archive header.
|
||||||
|
For simple names, this will modify the ar_name field of the current
|
||||||
|
archive header. For long names, it will return a pointer to the
|
||||||
|
longnames table. For nested archives, it will open the nested archive
|
||||||
|
and get the name recursively. NESTED_ARCH is a single-entry cache so
|
||||||
|
we don't keep rereading the same information from a nested archive. */
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_archive_member_name (struct archive_info * arch,
|
||||||
|
struct archive_info * nested_arch)
|
||||||
|
{
|
||||||
|
unsigned long j, k;
|
||||||
|
|
||||||
|
if (arch->arhdr.ar_name[0] == '/')
|
||||||
|
{
|
||||||
|
/* We have a long name. */
|
||||||
|
char * endp;
|
||||||
|
char * member_file_name;
|
||||||
|
char * member_name;
|
||||||
|
|
||||||
|
arch->nested_member_origin = 0;
|
||||||
|
k = j = strtoul (arch->arhdr.ar_name + 1, &endp, 10);
|
||||||
|
if (arch->is_thin_archive && endp != NULL && * endp == ':')
|
||||||
|
arch->nested_member_origin = strtoul (endp + 1, NULL, 10);
|
||||||
|
|
||||||
|
while ((j < arch->longnames_size)
|
||||||
|
&& (arch->longnames[j] != '\n')
|
||||||
|
&& (arch->longnames[j] != '\0'))
|
||||||
|
j++;
|
||||||
|
if (arch->longnames[j-1] == '/')
|
||||||
|
j--;
|
||||||
|
arch->longnames[j] = '\0';
|
||||||
|
|
||||||
|
if (!arch->is_thin_archive || arch->nested_member_origin == 0)
|
||||||
|
return arch->longnames + k;
|
||||||
|
|
||||||
|
/* This is a proxy for a member of a nested archive.
|
||||||
|
Find the name of the member in that archive. */
|
||||||
|
member_file_name = adjust_relative_path (arch->file_name, arch->longnames + k, j - k);
|
||||||
|
if (member_file_name != NULL
|
||||||
|
&& setup_nested_archive (nested_arch, member_file_name) == 0
|
||||||
|
&& (member_name = get_archive_member_name_at (nested_arch, arch->nested_member_origin, NULL)) != NULL)
|
||||||
|
{
|
||||||
|
free (member_file_name);
|
||||||
|
return member_name;
|
||||||
|
}
|
||||||
|
free (member_file_name);
|
||||||
|
|
||||||
|
/* Last resort: just return the name of the nested archive. */
|
||||||
|
return arch->longnames + k;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We have a normal (short) name. */
|
||||||
|
j = 0;
|
||||||
|
while ((arch->arhdr.ar_name[j] != '/') && (j < 16))
|
||||||
|
j++;
|
||||||
|
arch->arhdr.ar_name[j] = '\0';
|
||||||
|
return arch->arhdr.ar_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the name of an archive member at a given OFFSET within an archive ARCH. */
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_archive_member_name_at (struct archive_info * arch,
|
||||||
|
unsigned long offset,
|
||||||
|
struct archive_info * nested_arch)
|
||||||
|
{
|
||||||
|
size_t got;
|
||||||
|
|
||||||
|
if (fseek (arch->file, offset, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
error (_("%s: failed to seek to next file name\n"), arch->file_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
got = fread (&arch->arhdr, 1, sizeof arch->arhdr, arch->file);
|
||||||
|
if (got != sizeof arch->arhdr)
|
||||||
|
{
|
||||||
|
error (_("%s: failed to read archive header\n"), arch->file_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (memcmp (arch->arhdr.ar_fmag, ARFMAG, 2) != 0)
|
||||||
|
{
|
||||||
|
error (_("%s: did not find a valid archive header\n"), arch->file_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_archive_member_name (arch, nested_arch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Construct a string showing the name of the archive member, qualified
|
||||||
|
with the name of the containing archive file. For thin archives, we
|
||||||
|
use square brackets to denote the indirection. For nested archives,
|
||||||
|
we show the qualified name of the external member inside the square
|
||||||
|
brackets (e.g., "thin.a[normal.a(foo.o)]"). */
|
||||||
|
|
||||||
|
static char *
|
||||||
|
make_qualified_name (struct archive_info * arch,
|
||||||
|
struct archive_info * nested_arch,
|
||||||
|
char * member_name)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
char * name;
|
||||||
|
|
||||||
|
len = strlen (arch->file_name) + strlen (member_name) + 3;
|
||||||
|
if (arch->is_thin_archive && arch->nested_member_origin != 0)
|
||||||
|
len += strlen (nested_arch->file_name) + 2;
|
||||||
|
|
||||||
|
name = malloc (len);
|
||||||
|
if (name == NULL)
|
||||||
|
{
|
||||||
|
error (_("Out of memory\n"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arch->is_thin_archive && arch->nested_member_origin != 0)
|
||||||
|
snprintf (name, len, "%s[%s(%s)]", arch->file_name, nested_arch->file_name, member_name);
|
||||||
|
else if (arch->is_thin_archive)
|
||||||
|
snprintf (name, len, "%s[%s]", arch->file_name, member_name);
|
||||||
else
|
else
|
||||||
|
snprintf (name, len, "%s(%s)", arch->file_name, member_name);
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process an ELF archive.
|
||||||
|
On entry the file is positioned just after the ARMAG string. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
process_archive (char * file_name, FILE * file, bfd_boolean is_thin_archive)
|
||||||
|
{
|
||||||
|
struct archive_info arch;
|
||||||
|
struct archive_info nested_arch;
|
||||||
|
size_t got;
|
||||||
|
size_t file_name_size;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
show_name = 1;
|
||||||
|
|
||||||
|
/* The ARCH structure is used to hold information about this archive. */
|
||||||
|
arch.file_name = NULL;
|
||||||
|
arch.file = NULL;
|
||||||
|
arch.index_array = NULL;
|
||||||
|
arch.sym_table = NULL;
|
||||||
|
arch.longnames = NULL;
|
||||||
|
|
||||||
|
/* The NESTED_ARCH structure is used as a single-item cache of information
|
||||||
|
about a nested archive (when members of a thin archive reside within
|
||||||
|
another regular archive file). */
|
||||||
|
nested_arch.file_name = NULL;
|
||||||
|
nested_arch.file = NULL;
|
||||||
|
nested_arch.index_array = NULL;
|
||||||
|
nested_arch.sym_table = NULL;
|
||||||
|
nested_arch.longnames = NULL;
|
||||||
|
|
||||||
|
if (setup_archive (&arch, file_name, file, is_thin_archive, do_archive_index) != 0)
|
||||||
{
|
{
|
||||||
error (_("%s: failed to read archive header following long symbol names\n"), file_name);
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (do_archive_index)
|
if (do_archive_index)
|
||||||
{
|
{
|
||||||
if (sym_table == NULL)
|
if (arch.sym_table == NULL)
|
||||||
error (_("%s: unable to dump the index as none was found\n"), file_name);
|
error (_("%s: unable to dump the index as none was found\n"), file_name);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int i, j, k, l;
|
unsigned int i, l;
|
||||||
char elf_name[16];
|
|
||||||
unsigned long current_pos;
|
unsigned long current_pos;
|
||||||
|
|
||||||
printf (_("Index of archive %s: (%ld entries, 0x%lx bytes in the symbol table)\n"),
|
printf (_("Index of archive %s: (%ld entries, 0x%lx bytes in the symbol table)\n"),
|
||||||
file_name, index_num, sym_size);
|
file_name, arch.index_num, arch.sym_size);
|
||||||
current_pos = ftell (file);
|
current_pos = ftell (file);
|
||||||
|
|
||||||
for (i = l = 0; i < index_num; i++)
|
for (i = l = 0; i < arch.index_num; i++)
|
||||||
{
|
{
|
||||||
if ((i == 0) || ((i > 0) && (index_array[i] != index_array[i - 1])))
|
if ((i == 0) || ((i > 0) && (arch.index_array[i] != arch.index_array[i - 1])))
|
||||||
{
|
{
|
||||||
if (fseek (file, index_array[i], SEEK_SET) != 0)
|
char * member_name;
|
||||||
|
|
||||||
|
member_name = get_archive_member_name_at (&arch, arch.index_array[i], &nested_arch);
|
||||||
|
|
||||||
|
if (member_name != NULL)
|
||||||
{
|
{
|
||||||
error (_("%s: failed to seek to next file name\n"), file_name);
|
char * qualified_name = make_qualified_name (&arch, &nested_arch, member_name);
|
||||||
ret = 1;
|
|
||||||
goto out;
|
if (qualified_name != NULL)
|
||||||
|
{
|
||||||
|
printf (_("Binary %s contains:\n"), qualified_name);
|
||||||
|
free (qualified_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
got = fread (elf_name, 1, 16, file);
|
|
||||||
if (got != 16)
|
|
||||||
{
|
|
||||||
error (_("%s: failed to read file name\n"), file_name);
|
|
||||||
ret = 1;
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elf_name[0] == '/')
|
if (l >= arch.sym_size)
|
||||||
{
|
|
||||||
/* We have a long name. */
|
|
||||||
k = j = strtoul (elf_name + 1, NULL, 10);
|
|
||||||
while ((j < longnames_size) && (longnames[j] != '/'))
|
|
||||||
j++;
|
|
||||||
longnames[j] = '\0';
|
|
||||||
printf (_("Binary %s contains:\n"), longnames + k);
|
|
||||||
longnames[j] = '/';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
j = 0;
|
|
||||||
while ((elf_name[j] != '/') && (j < 16))
|
|
||||||
j++;
|
|
||||||
elf_name[j] = '\0';
|
|
||||||
printf(_("Binary %s contains:\n"), elf_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (l >= sym_size)
|
|
||||||
{
|
{
|
||||||
error (_("%s: end of the symbol table reached before the end of the index\n"),
|
error (_("%s: end of the symbol table reached before the end of the index\n"),
|
||||||
file_name);
|
file_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf ("\t%s\n", sym_table + l);
|
printf ("\t%s\n", arch.sym_table + l);
|
||||||
l += strlen (sym_table + l) + 1;
|
l += strlen (arch.sym_table + l) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l < sym_size)
|
if (l & 01)
|
||||||
|
++l;
|
||||||
|
if (l < arch.sym_size)
|
||||||
error (_("%s: symbols remain in the index symbol table, but without corresponding entries in the index table\n"),
|
error (_("%s: symbols remain in the index symbol table, but without corresponding entries in the index table\n"),
|
||||||
file_name);
|
file_name);
|
||||||
|
|
||||||
free (index_array);
|
|
||||||
index_array = NULL;
|
|
||||||
free (sym_table);
|
|
||||||
sym_table = NULL;
|
|
||||||
if (fseek (file, current_pos, SEEK_SET) != 0)
|
if (fseek (file, current_pos, SEEK_SET) != 0)
|
||||||
{
|
{
|
||||||
error (_("%s: failed to seek back to start of object files in the archive\n"), file_name);
|
error (_("%s: failed to seek back to start of object files in the archive\n"), file_name);
|
||||||
return 1;
|
ret = 1;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10802,7 +11056,10 @@ process_archive (char *file_name, FILE *file)
|
||||||
&& !do_segments && !do_header && !do_dump && !do_version
|
&& !do_segments && !do_header && !do_dump && !do_version
|
||||||
&& !do_histogram && !do_debugging && !do_arch && !do_notes
|
&& !do_histogram && !do_debugging && !do_arch && !do_notes
|
||||||
&& !do_section_groups)
|
&& !do_section_groups)
|
||||||
return 0; /* Archive index only. */
|
{
|
||||||
|
ret = 0; /* Archive index only. */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file_name_size = strlen (file_name);
|
file_name_size = strlen (file_name);
|
||||||
|
@ -10811,88 +11068,113 @@ process_archive (char *file_name, FILE *file)
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
char * name;
|
char * name;
|
||||||
char *nameend;
|
size_t namelen;
|
||||||
char *namealc;
|
char * qualified_name;
|
||||||
|
|
||||||
if (arhdr.ar_name[0] == '/')
|
/* Read the next archive header. */
|
||||||
|
if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0)
|
||||||
{
|
{
|
||||||
unsigned long off;
|
error (_("%s: failed to seek to next archive header\n"), file_name);
|
||||||
|
return 1;
|
||||||
off = strtoul (arhdr.ar_name + 1, NULL, 10);
|
}
|
||||||
if (off >= longnames_size)
|
got = fread (&arch.arhdr, 1, sizeof arch.arhdr, file);
|
||||||
|
if (got != sizeof arch.arhdr)
|
||||||
{
|
{
|
||||||
error (_("%s: invalid archive string table offset %lu\n"), file_name, off);
|
if (got == 0)
|
||||||
|
break;
|
||||||
|
error (_("%s: failed to read archive header\n"), file_name);
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0)
|
||||||
|
{
|
||||||
|
error (_("%s: did not find a valid archive header\n"), arch.file_name);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = longnames + off;
|
arch.next_arhdr_offset += sizeof arch.arhdr;
|
||||||
nameend = memchr (name, '/', longnames_size - off);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
name = arhdr.ar_name;
|
|
||||||
nameend = memchr (name, '/', 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nameend == NULL)
|
archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10);
|
||||||
|
if (archive_file_size & 01)
|
||||||
|
++archive_file_size;
|
||||||
|
|
||||||
|
name = get_archive_member_name (&arch, &nested_arch);
|
||||||
|
if (name == NULL)
|
||||||
|
{
|
||||||
|
error (_("%s: bad archive file name\n"), file_name);
|
||||||
|
ret = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
namelen = strlen (name);
|
||||||
|
|
||||||
|
qualified_name = make_qualified_name (&arch, &nested_arch, name);
|
||||||
|
if (qualified_name == NULL)
|
||||||
{
|
{
|
||||||
error (_("%s: bad archive file name\n"), file_name);
|
error (_("%s: bad archive file name\n"), file_name);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
namealc = malloc (file_name_size + (nameend - name) + 3);
|
if (is_thin_archive && arch.nested_member_origin == 0)
|
||||||
if (namealc == NULL)
|
{
|
||||||
|
/* This is a proxy for an external member of a thin archive. */
|
||||||
|
FILE * member_file;
|
||||||
|
char * member_file_name = adjust_relative_path (file_name, name, namelen);
|
||||||
|
if (member_file_name == NULL)
|
||||||
{
|
{
|
||||||
error (_("Out of memory\n"));
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (namealc, file_name, file_name_size);
|
member_file = fopen (member_file_name, "rb");
|
||||||
namealc[file_name_size] = '(';
|
if (member_file == NULL)
|
||||||
memcpy (namealc + file_name_size + 1, name, nameend - name);
|
|
||||||
namealc[file_name_size + 1 + (nameend - name)] = ')';
|
|
||||||
namealc[file_name_size + 2 + (nameend - name)] = '\0';
|
|
||||||
|
|
||||||
archive_file_offset = ftell (file);
|
|
||||||
archive_file_size = strtoul (arhdr.ar_size, NULL, 10);
|
|
||||||
|
|
||||||
ret |= process_object (namealc, file);
|
|
||||||
|
|
||||||
free (namealc);
|
|
||||||
|
|
||||||
if (fseek (file,
|
|
||||||
(archive_file_offset
|
|
||||||
+ archive_file_size
|
|
||||||
+ (archive_file_size & 1)),
|
|
||||||
SEEK_SET) != 0)
|
|
||||||
{
|
{
|
||||||
error (_("%s: failed to seek to next archive header\n"), file_name);
|
error (_("Input file '%s' is not readable.\n"), member_file_name);
|
||||||
|
free (member_file_name);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
got = fread (&arhdr, 1, sizeof arhdr, file);
|
archive_file_offset = arch.nested_member_origin;
|
||||||
if (got != sizeof arhdr)
|
|
||||||
{
|
|
||||||
if (got == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
error (_("%s: failed to read archive header\n"), file_name);
|
ret |= process_object (qualified_name, member_file);
|
||||||
|
|
||||||
|
fclose (member_file);
|
||||||
|
free (member_file_name);
|
||||||
|
}
|
||||||
|
else if (is_thin_archive)
|
||||||
|
{
|
||||||
|
/* This is a proxy for a member of a nested archive. */
|
||||||
|
archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;
|
||||||
|
|
||||||
|
/* The nested archive file will have been opened and setup by
|
||||||
|
get_archive_member_name. */
|
||||||
|
if (fseek (nested_arch.file, archive_file_offset, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
error (_("%s: failed to seek to archive member.\n"), nested_arch.file_name);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret |= process_object (qualified_name, nested_arch.file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
archive_file_offset = arch.next_arhdr_offset;
|
||||||
|
arch.next_arhdr_offset += archive_file_size;
|
||||||
|
|
||||||
|
ret |= process_object (qualified_name, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
free (qualified_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (index_array != NULL)
|
if (nested_arch.file != NULL)
|
||||||
free (index_array);
|
fclose (nested_arch.file);
|
||||||
if (sym_table != NULL)
|
release_archive (&nested_arch);
|
||||||
free (sym_table);
|
release_archive (&arch);
|
||||||
if (longnames != NULL)
|
|
||||||
free (longnames);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -10936,7 +11218,9 @@ process_file (char *file_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp (armag, ARMAG, SARMAG) == 0)
|
if (memcmp (armag, ARMAG, SARMAG) == 0)
|
||||||
ret = process_archive (file_name, file);
|
ret = process_archive (file_name, file, FALSE);
|
||||||
|
else if (memcmp (armag, ARMAGT, SARMAG) == 0)
|
||||||
|
ret = process_archive (file_name, file, TRUE);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (do_archive_index)
|
if (do_archive_index)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue