From 5d1fefd3b35589d792e5bff800d2bb7e9c4431e2 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 13 Apr 2023 11:44:41 +0930 Subject: [PATCH] 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. --- bfd/format.c | 44 +++++++++++++++++++++++++++++--------------- 1 file 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; -- 2.30.2