Make `aout_get_external_symbols' return unsuccessfully right away if
called for a non-aout BFD, preventing a crash from an attempt to access
inexistent ->tdata.aout_data->a (`struct aoutdata') struct member. Add
assertions at call sites to track potential invalid usage.
This converts a segmentation fault to an assertion failure followed by
graceful termination:
.../ld/ld-new: BFD (GNU Binutils) 2.45.50.
20251209 assertion fail .../bfd/aoutx.h:3449
.../ld/ld-new: tmpdir/ab.a: error adding symbols: file in wrong format
with an upcoming test case:
FAIL: CRIS regular archive link (implicit emulation)
where a `cris-aout' target linker invocation:
$ .../ld/ld-new -o tmpdir/abci -e ff tmpdir/abc.o tmpdir/ab.a
lands in `_bfd_generic_link_add_archive_symbols' with an inconsistent
state between an archive's BFD and its member's BFD:
Breakpoint 1, _bfd_generic_link_add_archive_symbols (abfd=0x100264700,
info=0x100253110 <link_info>,
checkfn=0x10009ac80 <aout_link_check_archive_element>)
at .../bfd/linker.c:1020
1020 if (! (*checkfn) (element, info, h, arsym->name, &needed))
(gdb) print *abfd
$1 = {filename = 0x1002b6200 "tmpdir/ab.a",
xvec = 0x10028d650 <cris_aout_vec>, iostream = 0x1002a47d0,
[...]
(gdb) print *element
$2 = {filename = 0x1002ccfb0 "a.o", xvec = 0x10028ea30 <cris_elf32_us_vec>,
iostream = 0x0, iovec = 0x10028ace8 <cache_iovec>, lru_prev = 0x0,
[...]
(gdb)
static bool
aout_get_external_symbols (bfd *abfd)
{
+ if (bfd_get_flavour (abfd) != bfd_target_aout_flavour)
+ return false;
+
if (obj_aout_external_syms (abfd) == NULL)
{
bfd_size_type count;
aout_symbol_type *cached;
bfd_size_type cached_size;
+ BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
/* If there's no work to be done, don't do any. */
if (obj_aout_symbols (abfd) != NULL)
return true;
void * *minisymsp,
unsigned int *sizep)
{
+ BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
if (dynamic)
/* We could handle the dynamic symbols here as well, but it's
easier to hand them off. */
static bool
aout_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
{
+ BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
if (! aout_get_external_symbols (abfd))
return false;
if (! aout_link_add_symbols (abfd, info))
bfd *oldbfd;
bool needed;
+ BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
if (!aout_get_external_symbols (abfd))
return false;
aout_link_input_bfd (struct aout_final_link_info *flaginfo, bfd *input_bfd)
{
BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object);
+ BFD_ASSERT (bfd_get_flavour (input_bfd) == bfd_target_aout_flavour);
/* If this is a dynamic object, it may need special handling. */
if ((input_bfd->flags & DYNAMIC) != 0
static bool
aout_get_external_symbols (bfd *abfd)
{
+ if (bfd_get_flavour (abfd) != bfd_target_aout_flavour)
+ return false;
+
if (obj_aout_external_syms (abfd) == NULL)
{
bfd_size_type count;
aout_symbol_type *cached;
bfd_size_type cached_size;
+ BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
/* If there's no work to be done, don't do any. */
if (obj_aout_symbols (abfd) != NULL)
return true;
void * *minisymsp,
unsigned int *sizep)
{
+ BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
if (dynamic)
/* We could handle the dynamic symbols here as well, but it's
easier to hand them off. */
static bool
aout_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
{
+ BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
if (! aout_get_external_symbols (abfd))
return false;
if (! aout_link_add_symbols (abfd, info))
bfd *oldbfd;
bool needed;
+ BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
if (!aout_get_external_symbols (abfd))
return false;
aout_link_input_bfd (struct aout_final_link_info *flaginfo, bfd *input_bfd)
{
BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object);
+ BFD_ASSERT (bfd_get_flavour (input_bfd) == bfd_target_aout_flavour);
/* If this is a dynamic object, it may need special handling. */
if ((input_bfd->flags & DYNAMIC) != 0