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.
This commit is contained in:
Alan Modra
2023-04-13 11:44:41 +09:30
parent 89558daae7
commit 5d1fefd3b3

View File

@@ -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;