diff options
author | Alan Modra <amodra@gmail.com> | 2023-04-13 11:44:41 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2023-04-13 12:26:00 +0930 |
commit | 5d1fefd3b35589d792e5bff800d2bb7e9c4431e2 (patch) | |
tree | 6b45cc40038a212c3031a4f7341106ed5304e8fb /bfd | |
parent | 89558daae726d14f33a0dd65178527c072b158cd (diff) | |
download | gdb-5d1fefd3b35589d792e5bff800d2bb7e9c4431e2.zip gdb-5d1fefd3b35589d792e5bff800d2bb7e9c4431e2.tar.gz gdb-5d1fefd3b35589d792e5bff800d2bb7e9c4431e2.tar.bz2 |
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.c | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/bfd/format.c b/bfd/format.c index dd50b5e..66b45ae 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; |