summaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2023-04-13 11:44:41 +0930
committerAlan Modra <amodra@gmail.com>2023-04-13 12:26:00 +0930
commit5d1fefd3b35589d792e5bff800d2bb7e9c4431e2 (patch)
tree6b45cc40038a212c3031a4f7341106ed5304e8fb /bfd
parent89558daae726d14f33a0dd65178527c072b158cd (diff)
downloadbinutils-gdb-5d1fefd3b35589d792e5bff800d2bb7e9c4431e2.tar.gz
Re: pe_ILF_object_p and bfd_check_format_matches
The last patch wasn't quite correct. bfd_preserve_restore also needs to handle an in-memory to file backed transition, seen in a testcase ILF object matching both pei-arm-little and pei-arm-wince-little. There the first match is saved in preserve_match, and restored at the end of the bfd_check_format_matches loop making the bfd in-memory. On finding more than one match the function wants to restore the bfd back to its original state with another bfd_preserve_restore call before exiting with a bfd_error_file_ambiguously_recognized error. It is also not correct to restore abfd->iostream unless the iovec changes. abfd->iostream is a FILE* when using cache_iovec, and if the file has been closed and reopened the iostream may have changed. * format.c (io_reinit): New function. (bfd_reinit, bfd_preserve_restore): Use it.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/format.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/bfd/format.c b/bfd/format.c
index dd50b5e653a..66b45ae1979 100644
--- a/bfd/format.c
+++ b/bfd/format.c
@@ -144,6 +144,33 @@ bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve,
sizeof (struct section_hash_entry));
}
+/* A back-end object_p function may flip a bfd from file backed to
+ in-memory, eg. pe_ILF_object_p. In that case to restore the
+ original IO state we need to reopen the file. Conversely, if we
+ are restoring a previously matched pe ILF format and have been
+ checking further target matches using file IO then we need to close
+ the file and detach the bfd from the cache lru list. */
+
+static void
+io_reinit (bfd *abfd, struct bfd_preserve *preserve)
+{
+ if (abfd->iovec != preserve->iovec)
+ {
+ /* Handle file backed to in-memory transition. bfd_cache_close
+ won't do anything unless abfd->iovec is the cache_iovec. */
+ bfd_cache_close (abfd);
+ abfd->iovec = preserve->iovec;
+ abfd->iostream = preserve->iostream;
+ /* Handle in-memory to file backed transition. */
+ if ((abfd->flags & BFD_CLOSED_BY_CACHE) != 0
+ && (abfd->flags & BFD_IN_MEMORY) != 0
+ && (preserve->flags & BFD_CLOSED_BY_CACHE) == 0
+ && (preserve->flags & BFD_IN_MEMORY) == 0)
+ bfd_open_file (abfd);
+ }
+ abfd->flags = preserve->flags;
+}
+
/* Clear out a subset of BFD state. */
static void
@@ -155,16 +182,7 @@ bfd_reinit (bfd *abfd, unsigned int section_id,
cleanup (abfd);
abfd->tdata.any = NULL;
abfd->arch_info = &bfd_default_arch_struct;
- if ((abfd->flags & BFD_CLOSED_BY_CACHE) != 0
- && (abfd->flags & BFD_IN_MEMORY) != 0
- && (preserve->flags & BFD_CLOSED_BY_CACHE) == 0
- && (preserve->flags & BFD_IN_MEMORY) == 0)
- {
- /* This is to reverse pe_ILF_build_a_bfd, which closes the file
- and sets up a bfd in memory. */
- bfd_open_file (abfd);
- }
- abfd->flags = preserve->flags;
+ io_reinit (abfd, preserve);
abfd->build_id = NULL;
bfd_section_list_clear (abfd);
}
@@ -178,11 +196,7 @@ bfd_preserve_restore (bfd *abfd, struct bfd_preserve *preserve)
abfd->tdata.any = preserve->tdata;
abfd->arch_info = preserve->arch_info;
- if (abfd->iovec != preserve->iovec)
- bfd_cache_close (abfd);
- abfd->flags = preserve->flags;
- abfd->iovec = preserve->iovec;
- abfd->iostream = preserve->iostream;
+ io_reinit (abfd, preserve);
abfd->section_htab = preserve->section_htab;
abfd->sections = preserve->sections;
abfd->section_last = preserve->section_last;