/* BFD back-end for archive files (libraries).
- Copyright (C) 1990-2018 Free Software Foundation, Inc.
+ Copyright (C) 1990-2020 Free Software Foundation, Inc.
Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault.
This file is part of BFD, the Binary File Descriptor library.
return NULL;
}
n_bfd->proxy_origin = bfd_tell (archive);
+
+ /* Copy BFD_COMPRESS, BFD_DECOMPRESS and BFD_COMPRESS_GABI
+ flags. */
+ n_bfd->flags |= archive->flags & (BFD_COMPRESS
+ | BFD_DECOMPRESS
+ | BFD_COMPRESS_GABI);
+
return n_bfd;
}
else
{
n_bfd->origin = n_bfd->proxy_origin;
- n_bfd->filename = xstrdup (filename);
+ n_bfd->filename = bfd_strdup (filename);
+ if (n_bfd->filename == NULL)
+ goto out;
}
n_bfd->arelt_data = new_areldata;
/* Copy is_linker_input. */
n_bfd->is_linker_input = archive->is_linker_input;
- if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_bfd))
+ if (archive->no_element_cache
+ || _bfd_add_bfd_to_archive_cache (archive, filepos, n_bfd))
return n_bfd;
+ out:
free (new_areldata);
n_bfd->arelt_data = NULL;
+ bfd_close (n_bfd);
return NULL;
}
return NULL;
}
- bfd_is_thin_archive (abfd) = (strncmp (armag, ARMAGT, SARMAG) == 0);
+ bfd_set_thin_archive (abfd, strncmp (armag, ARMAGT, SARMAG) == 0);
if (strncmp (armag, ARMAG, SARMAG) != 0
&& ! bfd_is_thin_archive (abfd))
{
bfd_set_error (bfd_error_wrong_format);
- if (abfd->format == bfd_archive)
- abfd->format = bfd_unknown;
return NULL;
}
if (abfd->target_defaulted && bfd_has_map (abfd))
{
bfd *first;
+ unsigned int save;
/* This archive has a map, so we may presume that the contents
are object files. Make sure that if the first file in the
normal archive, regardless of the format of the object files.
We do accept an empty archive. */
+ save = abfd->no_element_cache;
+ abfd->no_element_cache = 1;
first = bfd_openr_next_archived_file (abfd, NULL);
+ abfd->no_element_cache = save;
if (first != NULL)
{
first->target_defaulted = FALSE;
if (bfd_check_format (first, bfd_object)
&& first->xvec != abfd->xvec)
bfd_set_error (bfd_error_wrong_object_format);
- /* And we ought to close `first' here too. */
+ bfd_close (first);
}
}
if (parsed_size < 4)
return FALSE;
- raw_armap = (bfd_byte *) bfd_zalloc (abfd, parsed_size);
+ raw_armap = (bfd_byte *) bfd_alloc (abfd, parsed_size);
if (raw_armap == NULL)
return FALSE;
goto byebye;
}
- ardata->cache = 0;
rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE;
stringbase = ((char *) rbase
+ ardata->symdef_count * BSD_SYMDEF_SIZE
/* FIXME, we should provide some way to free raw_ardata when
we are done using the strings from it. For now, it seems
to be allocated on an objalloc anyway... */
- bfd_has_map (abfd) = TRUE;
+ abfd->has_armap = TRUE;
return TRUE;
}
int *raw_armap, *rawptr;
struct artdata *ardata = bfd_ardata (abfd);
char *stringbase;
+ char *stringend;
bfd_size_type stringsize;
bfd_size_type parsed_size;
carsym *carsyms;
bsd-style one in core all at once, for simplicity. */
if (nsymz > ~ (bfd_size_type) 0 / sizeof (carsym))
- return FALSE;
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return FALSE;
+ }
carsym_size = (nsymz * sizeof (carsym));
ptrsize = (4 * nsymz);
if (carsym_size + stringsize + 1 <= carsym_size)
- return FALSE;
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return FALSE;
+ }
- ardata->symdefs = (struct carsym *) bfd_zalloc (abfd,
- carsym_size + stringsize + 1);
+ ardata->symdefs = (struct carsym *) bfd_alloc (abfd,
+ carsym_size + stringsize + 1);
if (ardata->symdefs == NULL)
return FALSE;
carsyms = ardata->symdefs;
{
if (bfd_get_error () != bfd_error_system_call)
bfd_set_error (bfd_error_malformed_archive);
- goto release_raw_armap;
+ goto release_symdefs;
}
/* OK, build the carsyms. */
- for (i = 0; i < nsymz && stringsize > 0; i++)
+ stringend = stringbase + stringsize;
+ *stringend = 0;
+ for (i = 0; i < nsymz; i++)
{
- bfd_size_type len;
-
rawptr = raw_armap + i;
carsyms->file_offset = swap ((bfd_byte *) rawptr);
carsyms->name = stringbase;
- /* PR 17512: file: 4a1d50c1. */
- len = strnlen (stringbase, stringsize);
- if (len < stringsize)
- len ++;
- stringbase += len;
- stringsize -= len;
+ stringbase += strlen (stringbase);
+ if (stringbase != stringend)
+ ++stringbase;
carsyms++;
}
- *stringbase = 0;
ardata->symdef_count = nsymz;
ardata->first_file_filepos = bfd_tell (abfd);
/* Pad to an even boundary if you have to. */
ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
- bfd_has_map (abfd) = TRUE;
+ abfd->has_armap = TRUE;
bfd_release (abfd, raw_armap);
/* Check for a second archive header (as used by PE). */
return TRUE;
-release_raw_armap:
- bfd_release (abfd, raw_armap);
release_symdefs:
bfd_release (abfd, (ardata)->symdefs);
return FALSE;
return do_slurp_bsd_armap (abfd);
}
- bfd_has_map (abfd) = FALSE;
- return TRUE;
-}
-\f
-/* Returns FALSE on error, TRUE otherwise. */
-/* Flavor 2 of a bsd armap, similar to bfd_slurp_bsd_armap except the
- header is in a slightly different order and the map name is '/'.
- This flavour is used by hp300hpux. */
-
-#define HPUX_SYMDEF_COUNT_SIZE 2
-
-bfd_boolean
-bfd_slurp_bsd_armap_f2 (bfd *abfd)
-{
- struct areltdata *mapdata;
- char nextname[17];
- unsigned int counter;
- bfd_byte *raw_armap, *rbase;
- struct artdata *ardata = bfd_ardata (abfd);
- char *stringbase;
- unsigned int stringsize;
- unsigned int left;
- bfd_size_type amt;
- carsym *set;
- int i = bfd_bread (nextname, 16, abfd);
-
- if (i == 0)
- return TRUE;
- if (i != 16)
- return FALSE;
-
- /* The archive has at least 16 bytes in it. */
- if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
- return FALSE;
-
- if (CONST_STRNEQ (nextname, "__.SYMDEF ")
- || CONST_STRNEQ (nextname, "__.SYMDEF/ ")) /* Old Linux archives. */
- return do_slurp_bsd_armap (abfd);
-
- if (! CONST_STRNEQ (nextname, "/ "))
- {
- bfd_has_map (abfd) = FALSE;
- return TRUE;
- }
-
- mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
- if (mapdata == NULL)
- return FALSE;
-
- if (mapdata->parsed_size < HPUX_SYMDEF_COUNT_SIZE + BSD_STRING_COUNT_SIZE)
- {
- free (mapdata);
- wrong_format:
- bfd_set_error (bfd_error_wrong_format);
- byebye:
- return FALSE;
- }
- left = mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE - BSD_STRING_COUNT_SIZE;
-
- amt = mapdata->parsed_size;
- free (mapdata);
-
- raw_armap = (bfd_byte *) bfd_zalloc (abfd, amt);
- if (raw_armap == NULL)
- goto byebye;
-
- if (bfd_bread (raw_armap, amt, abfd) != amt)
- {
- if (bfd_get_error () != bfd_error_system_call)
- bfd_set_error (bfd_error_malformed_archive);
- goto byebye;
- }
-
- ardata->symdef_count = H_GET_16 (abfd, raw_armap);
-
- ardata->cache = 0;
-
- stringsize = H_GET_32 (abfd, raw_armap + HPUX_SYMDEF_COUNT_SIZE);
- if (stringsize > left)
- goto wrong_format;
- left -= stringsize;
-
- /* Skip sym count and string sz. */
- stringbase = ((char *) raw_armap
- + HPUX_SYMDEF_COUNT_SIZE
- + BSD_STRING_COUNT_SIZE);
- rbase = (bfd_byte *) stringbase + stringsize;
- amt = ardata->symdef_count * BSD_SYMDEF_SIZE;
- if (amt > left)
- goto wrong_format;
-
- ardata->symdefs = (struct carsym *) bfd_alloc (abfd, amt);
- if (!ardata->symdefs)
- return FALSE;
-
- for (counter = 0, set = ardata->symdefs;
- counter < ardata->symdef_count;
- counter++, set++, rbase += BSD_SYMDEF_SIZE)
- {
- set->name = H_GET_32 (abfd, rbase) + stringbase;
- set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
- }
-
- ardata->first_file_filepos = bfd_tell (abfd);
- /* Pad to an even boundary if you have to. */
- ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
- /* FIXME, we should provide some way to free raw_ardata when
- we are done using the strings from it. For now, it seems
- to be allocated on an objalloc anyway... */
- bfd_has_map (abfd) = TRUE;
+ abfd->has_armap = FALSE;
return TRUE;
}
\f
goto byebye;
bfd_ardata (abfd)->extended_names_size = amt;
- bfd_ardata (abfd)->extended_names = (char *) bfd_zalloc (abfd, amt + 1);
+ bfd_ardata (abfd)->extended_names = (char *) bfd_alloc (abfd, amt + 1);
if (bfd_ardata (abfd)->extended_names == NULL)
{
byebye:
bfd_ardata (abfd)->extended_names = NULL;
goto byebye;
}
+ bfd_ardata (abfd)->extended_names[amt] = 0;
/* Since the archive is supposed to be printable if it contains
text, the entries in the list are newline-padded, not null
const char *last;
char *copy;
+ if (abfd->flags & BFD_ARCHIVE_FULL_PATH)
+ return file;
+
first = file + strlen (file) - 1;
last = first + 1;
#else
static const char *
-normalize (bfd *abfd ATTRIBUTE_UNUSED, const char *file)
+normalize (bfd *abfd, const char *file)
{
+ if (abfd->flags & BFD_ARCHIVE_FULL_PATH)
+ return file;
return lbasename (file);
}
#endif
continue;
}
- normal = normalize (current, current->filename);
+ normal = normalize (abfd, current->filename);
if (normal == NULL)
return FALSE;
if (total_namelen == 0)
return TRUE;
- *tabloc = (char *) bfd_zalloc (abfd, total_namelen);
+ *tabloc = (char *) bfd_alloc (abfd, total_namelen);
if (*tabloc == NULL)
return FALSE;
}
else
{
- normal = normalize (current, filename);
+ normal = normalize (abfd, filename);
if (normal == NULL)
return FALSE;
}
stroff = last_stroff;
else
{
- strcpy (strptr, normal);
- if (! trailing_slash)
- strptr[thislen] = ARFMAG[1];
- else
- {
- strptr[thislen] = '/';
- strptr[thislen + 1] = ARFMAG[1];
- }
+ last_filename = filename;
stroff = strptr - *tabloc;
last_stroff = stroff;
+ memcpy (strptr, normal, thislen);
+ strptr += thislen;
+ if (trailing_slash)
+ *strptr++ = '/';
+ *strptr++ = ARFMAG[1];
}
hdr->ar_name[0] = ar_padchar (current);
if (bfd_is_thin_archive (abfd) && current->origin > 0)
}
else
_bfd_ar_spacepad (hdr->ar_name + 1, maxname - 1, "%-ld", stroff);
- if (normal != last_filename)
- {
- strptr += thislen + 1;
- if (trailing_slash)
- ++strptr;
- last_filename = filename;
- }
}
}
current != NULL;
current = current->archive_next)
{
- const char *normal = normalize (current, current->filename);
+ const char *normal = normalize (abfd, current->filename);
int has_space = 0;
unsigned int len;
long syms_max = 0;
bfd_boolean ret;
bfd_size_type amt;
+ static bfd_boolean report_plugin_err = TRUE;
/* Dunno if this is the best place for this info... */
if (elength != 0)
long symcount;
long src_count;
+ if (current->lto_slim_object && report_plugin_err)
+ {
+ report_plugin_err = FALSE;
+ _bfd_error_handler
+ (_("%pB: plugin needed to handle lto object"),
+ current);
+ }
+
storage = bfd_get_symtab_upper_bound (current);
if (storage < 0)
goto error_return;
&& syms[src_count]->name[1] == '_'
&& strcmp (syms[src_count]->name
+ (syms[src_count]->name[2] == '_'),
- "__gnu_lto_slim") == 0)
- _bfd_error_handler
- (_("%pB: plugin needed to handle lto object"),
- current);
+ "__gnu_lto_slim") == 0
+ && report_plugin_err)
+ {
+ report_plugin_err = FALSE;
+ _bfd_error_handler
+ (_("%pB: plugin needed to handle lto object"),
+ current);
+ }
namelen = strlen (syms[src_count]->name);
amt = sizeof (char *);
map[orl_count].name = (char **) bfd_alloc (arch, amt);
return 1;
}
+void
+_bfd_unlink_from_archive_parent (bfd *abfd)
+{
+ if (arch_eltdata (abfd) != NULL)
+ {
+ struct areltdata *ared = arch_eltdata (abfd);
+ htab_t htab = (htab_t) ared->parent_cache;
+
+ if (htab)
+ {
+ struct ar_cache ent;
+ void **slot;
+
+ ent.ptr = ared->key;
+ slot = htab_find_slot (htab, &ent, NO_INSERT);
+ if (slot != NULL)
+ {
+ BFD_ASSERT (((struct ar_cache *) *slot)->arbfd == abfd);
+ htab_clear_slot (htab, slot);
+ }
+ }
+ }
+}
+
bfd_boolean
_bfd_archive_close_and_cleanup (bfd *abfd)
{
bfd_ardata (abfd)->cache = NULL;
}
}
- if (arch_eltdata (abfd) != NULL)
- {
- struct areltdata *ared = arch_eltdata (abfd);
- htab_t htab = (htab_t) ared->parent_cache;
- if (htab)
- {
- struct ar_cache ent;
- void **slot;
+ _bfd_unlink_from_archive_parent (abfd);
- ent.ptr = ared->key;
- slot = htab_find_slot (htab, &ent, NO_INSERT);
- if (slot != NULL)
- {
- BFD_ASSERT (((struct ar_cache *) *slot)->arbfd == abfd);
- htab_clear_slot (htab, slot);
- }
- }
- }
if (abfd->is_linker_output)
(*abfd->link.hash->hash_table_free) (abfd);