123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911 |
- /* elfcomm.c -- common code for ELF format file.
- Copyright (C) 2010-2015 Free Software Foundation, Inc.
- Originally developed by Eric Youngdale <eric@andante.jic.com>
- Modifications by Nick Clifton <nickc@redhat.com>
- This file is part of GNU Binutils.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
- 02110-1301, USA. */
- #include "sysdep.h"
- #include "libiberty.h"
- #include "filenames.h"
- #include "bfd.h"
- #include "aout/ar.h"
- #include "bucomm.h"
- #include "elfcomm.h"
- #include <assert.h>
- void
- error (const char *message, ...)
- {
- va_list args;
- /* Try to keep error messages in sync with the program's normal output. */
- fflush (stdout);
- va_start (args, message);
- fprintf (stderr, _("%s: Error: "), program_name);
- vfprintf (stderr, message, args);
- va_end (args);
- }
- void
- warn (const char *message, ...)
- {
- va_list args;
- /* Try to keep warning messages in sync with the program's normal output. */
- fflush (stdout);
- va_start (args, message);
- fprintf (stderr, _("%s: Warning: "), program_name);
- vfprintf (stderr, message, args);
- va_end (args);
- }
- void (*byte_put) (unsigned char *, elf_vma, int);
- void
- byte_put_little_endian (unsigned char * field, elf_vma value, int size)
- {
- switch (size)
- {
- case 8:
- field[7] = (((value >> 24) >> 24) >> 8) & 0xff;
- field[6] = ((value >> 24) >> 24) & 0xff;
- field[5] = ((value >> 24) >> 16) & 0xff;
- field[4] = ((value >> 24) >> 8) & 0xff;
- /* Fall through. */
- case 4:
- field[3] = (value >> 24) & 0xff;
- /* Fall through. */
- case 3:
- field[2] = (value >> 16) & 0xff;
- /* Fall through. */
- case 2:
- field[1] = (value >> 8) & 0xff;
- /* Fall through. */
- case 1:
- field[0] = value & 0xff;
- break;
- default:
- error (_("Unhandled data length: %d\n"), size);
- abort ();
- }
- }
- void
- byte_put_big_endian (unsigned char * field, elf_vma value, int size)
- {
- switch (size)
- {
- case 8:
- field[7] = value & 0xff;
- field[6] = (value >> 8) & 0xff;
- field[5] = (value >> 16) & 0xff;
- field[4] = (value >> 24) & 0xff;
- value >>= 16;
- value >>= 16;
- /* Fall through. */
- case 4:
- field[3] = value & 0xff;
- value >>= 8;
- /* Fall through. */
- case 3:
- field[2] = value & 0xff;
- value >>= 8;
- /* Fall through. */
- case 2:
- field[1] = value & 0xff;
- value >>= 8;
- /* Fall through. */
- case 1:
- field[0] = value & 0xff;
- break;
- default:
- error (_("Unhandled data length: %d\n"), size);
- abort ();
- }
- }
- elf_vma (*byte_get) (unsigned char *, int);
- elf_vma
- byte_get_little_endian (unsigned char *field, int size)
- {
- switch (size)
- {
- case 1:
- return *field;
- case 2:
- return ((unsigned int) (field[0]))
- | (((unsigned int) (field[1])) << 8);
- case 3:
- return ((unsigned long) (field[0]))
- | (((unsigned long) (field[1])) << 8)
- | (((unsigned long) (field[2])) << 16);
- case 4:
- return ((unsigned long) (field[0]))
- | (((unsigned long) (field[1])) << 8)
- | (((unsigned long) (field[2])) << 16)
- | (((unsigned long) (field[3])) << 24);
- case 5:
- if (sizeof (elf_vma) == 8)
- return ((elf_vma) (field[0]))
- | (((elf_vma) (field[1])) << 8)
- | (((elf_vma) (field[2])) << 16)
- | (((elf_vma) (field[3])) << 24)
- | (((elf_vma) (field[4])) << 32);
- else if (sizeof (elf_vma) == 4)
- /* We want to extract data from an 8 byte wide field and
- place it into a 4 byte wide field. Since this is a little
- endian source we can just use the 4 byte extraction code. */
- return ((unsigned long) (field[0]))
- | (((unsigned long) (field[1])) << 8)
- | (((unsigned long) (field[2])) << 16)
- | (((unsigned long) (field[3])) << 24);
- case 6:
- if (sizeof (elf_vma) == 8)
- return ((elf_vma) (field[0]))
- | (((elf_vma) (field[1])) << 8)
- | (((elf_vma) (field[2])) << 16)
- | (((elf_vma) (field[3])) << 24)
- | (((elf_vma) (field[4])) << 32)
- | (((elf_vma) (field[5])) << 40);
- else if (sizeof (elf_vma) == 4)
- /* We want to extract data from an 8 byte wide field and
- place it into a 4 byte wide field. Since this is a little
- endian source we can just use the 4 byte extraction code. */
- return ((unsigned long) (field[0]))
- | (((unsigned long) (field[1])) << 8)
- | (((unsigned long) (field[2])) << 16)
- | (((unsigned long) (field[3])) << 24);
- case 7:
- if (sizeof (elf_vma) == 8)
- return ((elf_vma) (field[0]))
- | (((elf_vma) (field[1])) << 8)
- | (((elf_vma) (field[2])) << 16)
- | (((elf_vma) (field[3])) << 24)
- | (((elf_vma) (field[4])) << 32)
- | (((elf_vma) (field[5])) << 40)
- | (((elf_vma) (field[6])) << 48);
- else if (sizeof (elf_vma) == 4)
- /* We want to extract data from an 8 byte wide field and
- place it into a 4 byte wide field. Since this is a little
- endian source we can just use the 4 byte extraction code. */
- return ((unsigned long) (field[0]))
- | (((unsigned long) (field[1])) << 8)
- | (((unsigned long) (field[2])) << 16)
- | (((unsigned long) (field[3])) << 24);
- case 8:
- if (sizeof (elf_vma) == 8)
- return ((elf_vma) (field[0]))
- | (((elf_vma) (field[1])) << 8)
- | (((elf_vma) (field[2])) << 16)
- | (((elf_vma) (field[3])) << 24)
- | (((elf_vma) (field[4])) << 32)
- | (((elf_vma) (field[5])) << 40)
- | (((elf_vma) (field[6])) << 48)
- | (((elf_vma) (field[7])) << 56);
- else if (sizeof (elf_vma) == 4)
- /* We want to extract data from an 8 byte wide field and
- place it into a 4 byte wide field. Since this is a little
- endian source we can just use the 4 byte extraction code. */
- return ((unsigned long) (field[0]))
- | (((unsigned long) (field[1])) << 8)
- | (((unsigned long) (field[2])) << 16)
- | (((unsigned long) (field[3])) << 24);
- default:
- error (_("Unhandled data length: %d\n"), size);
- abort ();
- }
- }
- elf_vma
- byte_get_big_endian (unsigned char *field, int size)
- {
- switch (size)
- {
- case 1:
- return *field;
- case 2:
- return ((unsigned int) (field[1])) | (((int) (field[0])) << 8);
- case 3:
- return ((unsigned long) (field[2]))
- | (((unsigned long) (field[1])) << 8)
- | (((unsigned long) (field[0])) << 16);
- case 4:
- return ((unsigned long) (field[3]))
- | (((unsigned long) (field[2])) << 8)
- | (((unsigned long) (field[1])) << 16)
- | (((unsigned long) (field[0])) << 24);
- case 5:
- if (sizeof (elf_vma) == 8)
- return ((elf_vma) (field[4]))
- | (((elf_vma) (field[3])) << 8)
- | (((elf_vma) (field[2])) << 16)
- | (((elf_vma) (field[1])) << 24)
- | (((elf_vma) (field[0])) << 32);
- else if (sizeof (elf_vma) == 4)
- {
- /* Although we are extracting data from an 8 byte wide field,
- we are returning only 4 bytes of data. */
- field += 1;
- return ((unsigned long) (field[3]))
- | (((unsigned long) (field[2])) << 8)
- | (((unsigned long) (field[1])) << 16)
- | (((unsigned long) (field[0])) << 24);
- }
- case 6:
- if (sizeof (elf_vma) == 8)
- return ((elf_vma) (field[5]))
- | (((elf_vma) (field[4])) << 8)
- | (((elf_vma) (field[3])) << 16)
- | (((elf_vma) (field[2])) << 24)
- | (((elf_vma) (field[1])) << 32)
- | (((elf_vma) (field[0])) << 40);
- else if (sizeof (elf_vma) == 4)
- {
- /* Although we are extracting data from an 8 byte wide field,
- we are returning only 4 bytes of data. */
- field += 2;
- return ((unsigned long) (field[3]))
- | (((unsigned long) (field[2])) << 8)
- | (((unsigned long) (field[1])) << 16)
- | (((unsigned long) (field[0])) << 24);
- }
- case 7:
- if (sizeof (elf_vma) == 8)
- return ((elf_vma) (field[6]))
- | (((elf_vma) (field[5])) << 8)
- | (((elf_vma) (field[4])) << 16)
- | (((elf_vma) (field[3])) << 24)
- | (((elf_vma) (field[2])) << 32)
- | (((elf_vma) (field[1])) << 40)
- | (((elf_vma) (field[0])) << 48);
- else if (sizeof (elf_vma) == 4)
- {
- /* Although we are extracting data from an 8 byte wide field,
- we are returning only 4 bytes of data. */
- field += 3;
- return ((unsigned long) (field[3]))
- | (((unsigned long) (field[2])) << 8)
- | (((unsigned long) (field[1])) << 16)
- | (((unsigned long) (field[0])) << 24);
- }
- case 8:
- if (sizeof (elf_vma) == 8)
- return ((elf_vma) (field[7]))
- | (((elf_vma) (field[6])) << 8)
- | (((elf_vma) (field[5])) << 16)
- | (((elf_vma) (field[4])) << 24)
- | (((elf_vma) (field[3])) << 32)
- | (((elf_vma) (field[2])) << 40)
- | (((elf_vma) (field[1])) << 48)
- | (((elf_vma) (field[0])) << 56);
- else if (sizeof (elf_vma) == 4)
- {
- /* Although we are extracting data from an 8 byte wide field,
- we are returning only 4 bytes of data. */
- field += 4;
- return ((unsigned long) (field[3]))
- | (((unsigned long) (field[2])) << 8)
- | (((unsigned long) (field[1])) << 16)
- | (((unsigned long) (field[0])) << 24);
- }
- default:
- error (_("Unhandled data length: %d\n"), size);
- abort ();
- }
- }
- elf_vma
- byte_get_signed (unsigned char *field, int size)
- {
- elf_vma x = byte_get (field, size);
- switch (size)
- {
- case 1:
- return (x ^ 0x80) - 0x80;
- case 2:
- return (x ^ 0x8000) - 0x8000;
- case 3:
- return (x ^ 0x800000) - 0x800000;
- case 4:
- return (x ^ 0x80000000) - 0x80000000;
- case 5:
- case 6:
- case 7:
- case 8:
- /* Reads of 5-, 6-, and 7-byte numbers are the result of
- trying to read past the end of a buffer, and will therefore
- not have meaningful values, so we don't try to deal with
- the sign in these cases. */
- return x;
- default:
- abort ();
- }
- }
- /* Return the high-order 32-bits and the low-order 32-bits
- of an 8-byte value separately. */
- void
- byte_get_64 (unsigned char *field, elf_vma *high, elf_vma *low)
- {
- if (byte_get == byte_get_big_endian)
- {
- *high = byte_get_big_endian (field, 4);
- *low = byte_get_big_endian (field + 4, 4);
- }
- else
- {
- *high = byte_get_little_endian (field + 4, 4);
- *low = byte_get_little_endian (field, 4);
- }
- return;
- }
- /* Return the path name for a proxy entry in a thin archive, adjusted
- relative to the path name of the thin archive itself if necessary.
- Always returns a pointer to malloc'ed memory. */
- char *
- adjust_relative_path (const char *file_name, const char *name,
- unsigned long name_len)
- {
- char * member_file_name;
- const char * base_name = lbasename (file_name);
- size_t amt;
- /* 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)
- {
- amt = name_len + 1;
- if (amt == 0)
- return NULL;
- member_file_name = (char *) malloc (amt);
- 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;
- amt = prefix_len + name_len + 1;
- /* PR 17531: file: 2896dc8b
- Catch wraparound. */
- if (amt < prefix_len || amt < name_len)
- {
- error (_("Abnormal length of thin archive member name: %lx\n"),
- name_len);
- return NULL;
- }
- member_file_name = (char *) malloc (amt);
- 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;
- }
- /* 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);
- /* PR 17531: file: 912bd7de. */
- if ((signed long) size < 0)
- {
- error (_("%s: invalid archive header size: %ld\n"),
- arch->file_name, size);
- return FALSE;
- }
- 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
- /* PR 17531: file: 585515d1. */
- || size < arch->index_num)
- {
- error (_("%s: the archive index is supposed to have 0x%lx entries of %d bytes, but the size is only 0x%lx\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
- setup_archive (struct archive_info *arch, const char *file_name,
- FILE *file, bfd_boolean is_thin_archive,
- bfd_boolean read_symbols)
- {
- size_t got;
- 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->uses_64bit_indicies = FALSE;
- arch->next_arhdr_offset = SARMAG;
- /* Read the first archive member header. */
- 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)
- return 0;
- error (_("%s: failed to read archive header\n"), file_name);
- return 1;
- }
- /* See if this is the archive symbol table. */
- if (const_strneq (arch->arhdr.ar_name, "/ "))
- {
- 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);
- if (const_strneq (arch->arhdr.ar_name, "// "))
- {
- /* This is the archive string table holding long member names. */
- arch->longnames_size = strtoul (arch->arhdr.ar_size, NULL, 10);
- /* PR 17531: file: 01068045. */
- if (arch->longnames_size < 8)
- {
- error (_("%s: long name table is too small, (size = %ld)\n"),
- file_name, arch->longnames_size);
- return 1;
- }
- /* PR 17531: file: 639d6a26. */
- if ((signed long) arch->longnames_size < 0)
- {
- error (_("%s: long name table is too big, (size = 0x%lx)\n"),
- file_name, arch->longnames_size);
- return 1;
- }
- arch->next_arhdr_offset += sizeof arch->arhdr + arch->longnames_size;
- /* Plus one to allow for a string terminator. */
- arch->longnames = (char *) malloc (arch->longnames_size + 1);
- if (arch->longnames == NULL)
- {
- error (_("Out of memory reading long symbol names in archive\n"));
- return 1;
- }
- if (fread (arch->longnames, arch->longnames_size, 1, file) != 1)
- {
- free (arch->longnames);
- arch->longnames = NULL;
- error (_("%s: failed to read long symbol name string table\n"),
- file_name);
- return 1;
- }
- if ((arch->longnames_size & 1) != 0)
- getc (file);
- arch->longnames[arch->longnames_size] = 0;
- }
- return 0;
- }
- /* Open and setup a nested archive, if not already open. */
- int
- setup_nested_archive (struct archive_info *nested_arch,
- const 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);
- }
- /* Release the memory used for the archive information. */
- void
- release_archive (struct archive_info * arch)
- {
- if (arch->file_name != NULL)
- 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);
- }
- /* 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. */
- 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;
- if (arch->longnames == NULL || arch->longnames_size == 0)
- {
- error (_("Archive member uses long names, but no longname table found\n"));
- return NULL;
- }
- 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);
- if (j > arch->longnames_size)
- {
- error (_("Found long name index (%ld) beyond end of long name table\n"),j);
- return NULL;
- }
- while ((j < arch->longnames_size)
- && (arch->longnames[j] != '\n')
- && (arch->longnames[j] != '\0'))
- j++;
- if (j > 0 && arch->longnames[j-1] == '/')
- j--;
- if (j > arch->longnames_size)
- j = arch->longnames_size;
- arch->longnames[j] = '\0';
- if (!arch->is_thin_archive || arch->nested_member_origin == 0)
- return arch->longnames + k;
- /* PR 17531: file: 2896dc8b. */
- if (k >= j)
- {
- error (_("Invalid Thin archive member name\n"));
- return NULL;
- }
- /* 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);
- if (member_name != 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. */
- for (j = 0; j < sizeof (arch->arhdr.ar_name); j++)
- if (arch->arhdr.ar_name[j] == '/')
- {
- arch->arhdr.ar_name[j] = '\0';
- return arch->arhdr.ar_name;
- }
- /* The full ar_name field is used. Don't rely on ar_date starting
- with a zero byte. */
- {
- char *name = xmalloc (sizeof (arch->arhdr.ar_name) + 1);
- memcpy (name, arch->arhdr.ar_name, sizeof (arch->arhdr.ar_name));
- name[sizeof (arch->arhdr.ar_name)] = '\0';
- return name;
- }
- }
- /* Get the name of an archive member at a given OFFSET within an archive
- ARCH. */
- 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)]"). */
- char *
- make_qualified_name (struct archive_info * arch,
- struct archive_info * nested_arch,
- const char *member_name)
- {
- const char * error_name = _("<corrupt>");
- size_t len;
- char * name;
- len = strlen (arch->file_name) + strlen (member_name) + 3;
- if (arch->is_thin_archive
- && arch->nested_member_origin != 0)
- {
- /* PR 15140: Allow for corrupt thin archives. */
- if (nested_arch->file_name)
- len += strlen (nested_arch->file_name) + 2;
- else
- len += strlen (error_name) + 2;
- }
- name = (char *) malloc (len);
- if (name == NULL)
- {
- error (_("Out of memory\n"));
- return NULL;
- }
- if (arch->is_thin_archive
- && arch->nested_member_origin != 0)
- {
- if (nested_arch->file_name)
- snprintf (name, len, "%s[%s(%s)]", arch->file_name,
- nested_arch->file_name, member_name);
- else
- snprintf (name, len, "%s[%s(%s)]", arch->file_name,
- error_name, member_name);
- }
- else if (arch->is_thin_archive)
- snprintf (name, len, "%s[%s]", arch->file_name, member_name);
- else
- snprintf (name, len, "%s(%s)", arch->file_name, member_name);
- return name;
- }
|