aboutsummaryrefslogtreecommitdiff
path: root/bfd/format.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2022-09-23 22:27:13 +0930
committerAlan Modra <amodra@gmail.com>2022-09-24 11:28:55 +0930
commit5aa0f10c424e7904d9ab1d0746d8211451552411 (patch)
tree218e7d76df4307a4015580797354b441556ed5ed /bfd/format.c
parent31f4ff5731d0e6a0715e1af81e8c5fc5b71d2df6 (diff)
downloadbinutils-5aa0f10c424e7904d9ab1d0746d8211451552411.zip
binutils-5aa0f10c424e7904d9ab1d0746d8211451552411.tar.gz
binutils-5aa0f10c424e7904d9ab1d0746d8211451552411.tar.bz2
The problem with warning in elf_object_p
elfcode.h can emit three warnings in elf_object_p for various things, "section extending past end of file", "corrupt string table index", and "program header with invalid alignment". The problem with doing this is that the warning can be emitted for multiple possible targets as each one is tried. I was looking at a fuzzer testcase that had an object file with 6144 program headers, 5316 of which had invalid alignment. It would be bad enough to get 5316 messages all the same, but this object was contained in an archive and resulted in 4975776 repeats. Some trimming can be done by not warning if the bfd is already marked read_only, as is done for the "section extending past end of file" warning, but that still results in an unacceptable number of warnings for object files in archives. Besides that, it is just wrong to warn about a problem detected by a target elf_object_p other than the one that actually matches. At some point we might have more target specific warnings. So what to do? One obvious solution is to remove the warnings. Another is to poke any warning strings into the target xvec, emitting them if that xvec is the final one chosen. This also has the benefit of solving the archive problem. A warning when recursing into _bfd_check_format for the first element of the archive (to find the correct target for the archive) will still be on the xvec at the point that target is chosen for the archive. However, target xvecs are read-only. Thus the need for per_xvec_warn to logically extend bfd_target with a writable field. I've made per_xvec_warn one larger than bfd_target_vector to provide one place for user code that makes private copies of target xvecs. * elfcode.h (elf_swap_shdr_in, elf_object_p): Stash potential warnings in _bfd_per_xvec_warn location. * format.c (clear_warnmsg): New function. (bfd_check_format_matches): Call clear_warnmsg before trying a new xvec. Print warnings for the successful non-archive match. * targets.c: Include libiberty.h. (_bfd_target_vector_entries): Use ARRAY_SIZE. (per_xvec_warn): New. (_bfd_per_xvec_warn): New function. * Makefile.am (LIBBFD_H_FILES): Add targets.c. * Makefile.in: Regenerate. * libbfd.h: Regenerate.
Diffstat (limited to 'bfd/format.c')
-rw-r--r--bfd/format.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/bfd/format.c b/bfd/format.c
index 489ffcf..7e2813c 100644
--- a/bfd/format.c
+++ b/bfd/format.c
@@ -202,6 +202,13 @@ bfd_preserve_finish (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_preserve *preserve)
preserve->marker = NULL;
}
+static void
+clear_warnmsg (const bfd_target *targ)
+{
+ const char **warn = _bfd_per_xvec_warn (targ);
+ *warn = NULL;
+}
+
/*
FUNCTION
bfd_check_format_matches
@@ -275,6 +282,7 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) /* rewind! */
goto err_ret;
+ clear_warnmsg (abfd->xvec);
cleanup = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
if (cleanup)
@@ -341,6 +349,7 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
goto err_ret;
+ clear_warnmsg (abfd->xvec);
cleanup = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
if (cleanup)
{
@@ -506,6 +515,13 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
bfd_preserve_finish (abfd, &preserve_match);
bfd_preserve_finish (abfd, &preserve);
+ if (!abfd->my_archive)
+ {
+ const char **warn = _bfd_per_xvec_warn (abfd->xvec);
+ if (*warn)
+ _bfd_error_handler (*warn, abfd);
+ }
+
/* File position has moved, BTW. */
return true;
}