[RFC] Make bfd_check_format better respect given target
Alan Modra
amodra@gmail.com
Mon Aug 4 13:15:50 GMT 2025
More information about the Binutils mailing list
Mon Aug 4 13:15:50 GMT 2025
- Previous message (by thread): windres PR 33244 testcase
- Next message (by thread): Make bfd_check_format better respect given target
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
bfd_check_format currently does not take much notice of the target
set in its abfd arg, merely checking that target first if
target_defaulted is false. It then merrily goes on to check other
targets. As the comment says this was due to complications with
archive handling which I think was fixed in commit f832531609d0. It
should now be possible to just check the given target, except for
linker input and the horrible plugin hack.
This will no doubt expose some misuse of target options, as found in
the binutils "efi app" tests.
One of the motivations for this patch was to reduce time spent
checking the first object in an archive.
bfd/
* archive.c (bfd_generic_archive_p): Correct object in archive
target test.
* format.c (bfd_check_format_matches_lto): Try to match given
target first even when target_defaulted is set. Don't try
other targets if !target_defaulted except for linker input and
plugin target.
* opncls.c (_bfd_new_bfd_contained_in): Always set
target_defaulted.
binutils/
* testsuite/binutils-all/aarch64/pei-aarch64-little.d: Don't
wrongly specify both input and output target, just specify
output.
* testsuite/binutils-all/loongarch64/pei-loongarch64.d: Likewise.
* testsuite/binutils-all/riscv/pei-riscv64.d: Likewise.
diff --git a/bfd/archive.c b/bfd/archive.c
index c61d4b12658..f0ed9096bd2 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -947,8 +947,9 @@ bfd_generic_archive_p (bfd *abfd)
if (first != NULL)
{
first->target_defaulted = false;
- if (bfd_check_format (first, bfd_object)
- && first->xvec != abfd->xvec)
+ bfd_set_error (bfd_error_no_error);
+ if (!bfd_check_format (first, bfd_object)
+ || first->xvec != abfd->xvec)
bfd_set_error (bfd_error_wrong_object_format);
bfd_close (first);
}
diff --git a/bfd/format.c b/bfd/format.c
index f3a0774af08..bb0a0b8490d 100644
--- a/bfd/format.c
+++ b/bfd/format.c
@@ -449,7 +449,7 @@ DESCRIPTION
When done with the list that @var{matching} points to, the caller
should free it.
- If LTO_SECTION_REMOVED is true, ignore plugin target.
+ If LTO_SECTIONS_REMOVED is true, ignore plugin target.
*/
bool
@@ -461,6 +461,7 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format format,
const bfd_target * const *target;
const bfd_target **matching_vector = NULL;
const bfd_target *save_targ, *right_targ, *ar_right_targ, *match_targ;
+ const bfd_target *fail_targ;
int match_count, best_count, best_match;
int ar_match_index;
unsigned int initial_section_id = _bfd_section_id;
@@ -524,13 +525,19 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format format,
if (!bfd_preserve_save (abfd, &preserve, NULL))
goto err_ret;
- /* If the target type was explicitly specified, just check that target.
- If LTO_SECTION_REMOVED is true, don't match the plugin target. */
- if (!abfd->target_defaulted
+ /* First try matching the current target. The current target may
+ have been set due to a user option, or due to the linker trying
+ optimistically to load input files for the same target as the
+ output, or due to the plugin support setting "plugin" as the
+ target. All of those cases result in abfd->target_defaulted
+ being false. Failing that bfd_find_target will have chosen a
+ default target, in which case target_defaulted will be true.
+ FIXME: Rearrange the plugin support so that ar, objcopy, nm
+ don't need to supply "plugin" as a target. */
+ fail_targ = NULL;
#if BFD_SUPPORTS_PLUGINS
- && (!lto_sections_removed || !bfd_plugin_target_p (abfd->xvec))
+ if (!lto_sections_removed || !bfd_plugin_target_p (save_targ))
#endif
- )
{
if (bfd_seek (abfd, 0, SEEK_SET) != 0) /* rewind! */
goto err_ret;
@@ -538,26 +545,29 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format format,
cleanup = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
if (cleanup)
- goto ok_ret;
-
- /* For a long time the code has dropped through to check all
- targets if the specified target was wrong. I don't know why,
- and I'm reluctant to change it. However, in the case of an
- archive, it can cause problems. If the specified target does
- not permit archives (e.g., the binary target), then we should
- not allow some other target to recognize it as an archive, but
- should instead allow the specified target to recognize it as an
- object. When I first made this change, it broke the PE target,
- because the specified pei-i386 target did not recognize the
- actual pe-i386 archive. Since there may be other problems of
- this sort, I changed this test to check only for the binary
- target. */
- if (format == bfd_archive && save_targ == &binary_vec)
- goto err_unrecog;
+ {
+ /* An archive with object files not matching the archive
+ target should be further tested.
+ ??? What about for ar --target? */
+ if (abfd->format != bfd_archive
+ || (bfd_has_map (abfd)
+ && bfd_get_error () != bfd_error_wrong_object_format))
+ goto ok_ret;
+ }
+ else
+ {
+ if (!abfd->target_defaulted
+ && !abfd->is_linker_input
+#if BFD_SUPPORTS_PLUGINS
+ && !bfd_plugin_target_p (save_targ)
+#endif
+ )
+ goto err_unrecog;
+ fail_targ = save_targ;
+ }
}
- /* Since the target type was defaulted, check them all in the hope
- that one will be uniquely recognized. */
+ /* Check all targets in the hope that one will be recognized. */
right_targ = NULL;
ar_right_targ = NULL;
match_targ = NULL;
@@ -574,14 +584,15 @@ bfd_check_format_matches_lto (bfd *abfd, bfd_format format,
searching. Don't match the plugin target if we have another
alternative since we want to properly set the input format
before allowing a plugin to claim the file. Also, don't
- check the default target twice. If LTO_SECTION_REMOVED is
+ check the current target twice. If LTO_SECTIONS_REMOVED is
true, don't match the plugin target. */
if (*target == &binary_vec
+ || *target == fail_targ
#if BFD_SUPPORTS_PLUGINS
|| ((lto_sections_removed || match_count != 0)
&& bfd_plugin_target_p (*target))
#endif
- || (!abfd->target_defaulted && *target == save_targ))
+ )
continue;
#if BFD_SUPPORTS_PLUGINS
diff --git a/bfd/opncls.c b/bfd/opncls.c
index 47a74512efc..6ccf2e65b7d 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -135,7 +135,7 @@ _bfd_new_bfd_contained_in (bfd *obfd)
nbfd->iostream = obfd->iostream;
nbfd->my_archive = obfd;
nbfd->direction = read_direction;
- nbfd->target_defaulted = obfd->target_defaulted;
+ nbfd->target_defaulted = true;
nbfd->lto_output = obfd->lto_output;
nbfd->no_export = obfd->no_export;
return nbfd;
diff --git a/binutils/testsuite/binutils-all/aarch64/pei-aarch64-little.d b/binutils/testsuite/binutils-all/aarch64/pei-aarch64-little.d
index 27cb6e17db3..22f664929c5 100644
--- a/binutils/testsuite/binutils-all/aarch64/pei-aarch64-little.d
+++ b/binutils/testsuite/binutils-all/aarch64/pei-aarch64-little.d
@@ -1,7 +1,7 @@
#skip: aarch64_be-*-*
#ld: -e0
#PROG: objcopy
-#objcopy: -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* -j .reloc --target=efi-app-aarch64
+#objcopy: -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* -j .reloc --output-target=efi-app-aarch64
#objdump: -h -f
#name: Check if efi app format is recognized
diff --git a/binutils/testsuite/binutils-all/loongarch64/pei-loongarch64.d b/binutils/testsuite/binutils-all/loongarch64/pei-loongarch64.d
index 574b3e5448d..61b026d59ca 100644
--- a/binutils/testsuite/binutils-all/loongarch64/pei-loongarch64.d
+++ b/binutils/testsuite/binutils-all/loongarch64/pei-loongarch64.d
@@ -1,6 +1,6 @@
#ld: -e0
#PROG: objcopy
-#objcopy: -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* -j .reloc --target=pei-loongarch64
+#objcopy: -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* -j .reloc --output-target=pei-loongarch64
#objdump: -h -f
#name: Check if efi app format is recognized
diff --git a/binutils/testsuite/binutils-all/riscv/pei-riscv64.d b/binutils/testsuite/binutils-all/riscv/pei-riscv64.d
index 189b0162ba5..43164147c3d 100644
--- a/binutils/testsuite/binutils-all/riscv/pei-riscv64.d
+++ b/binutils/testsuite/binutils-all/riscv/pei-riscv64.d
@@ -1,7 +1,7 @@
#as: -march=rv64gc -mabi=lp64d
#ld: -m elf64lriscv -e0
#PROG: objcopy
-#objcopy: -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* -j .reloc --target=pei-riscv64-little
+#objcopy: -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* -j .reloc --output-target=pei-riscv64-little
#objdump: -h -f
#name: Check if efi app format is recognized
--
Alan Modra
- Previous message (by thread): windres PR 33244 testcase
- Next message (by thread): Make bfd_check_format better respect given target
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list