pe_ILF_object_p and bfd_check_format_matches
If pe_ILF_object_p succeeds, pe_ILF_build_a_bfd will have changed the bfd from being file backed to in-memory. This can have unfortunate results for targets checked by bfd_check_format_matches after that point as they will be matching against the created in-memory image rather than the file. bfd_preserve_restore also has a problem if it flips the BFD_IN_MEMORY flag, because the flag affects iostream meaning and should be set if using _bfd_memory_iovec. To fix these problems, save and restore iostream and iovec along with flags, and modify bfd_reinit to make the bfd file backed again. Restoring the iovec and iostream allows the hack in bfd_reinit keeping BFD_IN_MEMORY (part of BFD_FLAGS_SAVED) to be removed. One more detail: If restoring from file backed to in-memory then the bfd needs to be forcibly removed from the cache lru list, since after the bfd becomes in-memory a bfd_close will delete the bfd's memory leaving the lru list pointing into freed memory. * cache.c (bfd_cache_init): Clear BFD_CLOSED_BY_CACHE here.. (bfd_cache_lookup_worker): ..rather than here. (bfd_cache_close): Comment. * format.c (struct bfd_preserve): Add iovec and iostream fields. (bfd_preserve_save): Save them.. (bfd_preserve_restore): ..and restore them, calling bfd_cache_close if the iovec differs. (bfd_reinit): Add preserve param. If the bfd has been flipped to in-memory, reopen the file. Restore flags. * peicode.h (pe_ILF_cleanup): New function. (pe_ILF_object_p): Return it. * bfd.c (BFD_FLAGS_SAVED): Delete. * bfd-in2.h: Regenerate.
This commit is contained in:
parent
dff05c9c82
commit
f656f9c77c
@ -6622,12 +6622,6 @@ struct bfd
|
||||
/* Compress sections in this BFD with SHF_COMPRESSED zstd. */
|
||||
#define BFD_COMPRESS_ZSTD 0x400000
|
||||
|
||||
/* Flags bits to be saved in bfd_preserve_save. */
|
||||
#define BFD_FLAGS_SAVED \
|
||||
(BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
|
||||
| BFD_PLUGIN | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON \
|
||||
| BFD_USE_ELF_STT_COMMON | BFD_COMPRESS_ZSTD)
|
||||
|
||||
/* Flags bits which are for BFD use only. */
|
||||
#define BFD_FLAGS_FOR_BFD_USE_MASK \
|
||||
(BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
|
||||
|
@ -181,12 +181,6 @@ CODE_FRAGMENT
|
||||
. {* Compress sections in this BFD with SHF_COMPRESSED zstd. *}
|
||||
.#define BFD_COMPRESS_ZSTD 0x400000
|
||||
.
|
||||
. {* Flags bits to be saved in bfd_preserve_save. *}
|
||||
.#define BFD_FLAGS_SAVED \
|
||||
. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
|
||||
. | BFD_PLUGIN | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON \
|
||||
. | BFD_USE_ELF_STT_COMMON | BFD_COMPRESS_ZSTD)
|
||||
.
|
||||
. {* Flags bits which are for BFD use only. *}
|
||||
.#define BFD_FLAGS_FOR_BFD_USE_MASK \
|
||||
. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
|
||||
|
@ -266,10 +266,7 @@ bfd_cache_lookup_worker (bfd *abfd, enum cache_flag flag)
|
||||
&& !(flag & CACHE_NO_SEEK_ERROR))
|
||||
bfd_set_error (bfd_error_system_call);
|
||||
else
|
||||
{
|
||||
abfd->flags &= ~BFD_CLOSED_BY_CACHE;
|
||||
return (FILE *) abfd->iostream;
|
||||
}
|
||||
return (FILE *) abfd->iostream;
|
||||
|
||||
/* xgettext:c-format */
|
||||
_bfd_error_handler (_("reopening %pB: %s"),
|
||||
@ -506,6 +503,7 @@ bfd_cache_init (bfd *abfd)
|
||||
}
|
||||
abfd->iovec = &cache_iovec;
|
||||
insert (abfd);
|
||||
abfd->flags &= ~BFD_CLOSED_BY_CACHE;
|
||||
++open_files;
|
||||
return true;
|
||||
}
|
||||
@ -528,6 +526,7 @@ DESCRIPTION
|
||||
bool
|
||||
bfd_cache_close (bfd *abfd)
|
||||
{
|
||||
/* Don't remove this test. bfd_reinit depends on it. */
|
||||
if (abfd->iovec != &cache_iovec)
|
||||
return true;
|
||||
|
||||
|
26
bfd/format.c
26
bfd/format.c
@ -99,6 +99,8 @@ struct bfd_preserve
|
||||
void *marker;
|
||||
void *tdata;
|
||||
flagword flags;
|
||||
const struct bfd_iovec *iovec;
|
||||
void *iostream;
|
||||
const struct bfd_arch_info *arch_info;
|
||||
struct bfd_section *sections;
|
||||
struct bfd_section *section_last;
|
||||
@ -125,6 +127,8 @@ bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve,
|
||||
preserve->tdata = abfd->tdata.any;
|
||||
preserve->arch_info = abfd->arch_info;
|
||||
preserve->flags = abfd->flags;
|
||||
preserve->iovec = abfd->iovec;
|
||||
preserve->iostream = abfd->iostream;
|
||||
preserve->sections = abfd->sections;
|
||||
preserve->section_last = abfd->section_last;
|
||||
preserve->section_count = abfd->section_count;
|
||||
@ -143,14 +147,24 @@ bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve,
|
||||
/* Clear out a subset of BFD state. */
|
||||
|
||||
static void
|
||||
bfd_reinit (bfd *abfd, unsigned int section_id, bfd_cleanup cleanup)
|
||||
bfd_reinit (bfd *abfd, unsigned int section_id,
|
||||
struct bfd_preserve *preserve, bfd_cleanup cleanup)
|
||||
{
|
||||
_bfd_section_id = section_id;
|
||||
if (cleanup)
|
||||
cleanup (abfd);
|
||||
abfd->tdata.any = NULL;
|
||||
abfd->arch_info = &bfd_default_arch_struct;
|
||||
abfd->flags &= BFD_FLAGS_SAVED;
|
||||
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;
|
||||
abfd->build_id = NULL;
|
||||
bfd_section_list_clear (abfd);
|
||||
}
|
||||
@ -164,7 +178,11 @@ 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;
|
||||
abfd->section_htab = preserve->section_htab;
|
||||
abfd->sections = preserve->sections;
|
||||
abfd->section_last = preserve->section_last;
|
||||
@ -368,7 +386,7 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
|
||||
/* If we already tried a match, the bfd is modified and may
|
||||
have sections attached, which will confuse the next
|
||||
_bfd_check_format call. */
|
||||
bfd_reinit (abfd, initial_section_id, cleanup);
|
||||
bfd_reinit (abfd, initial_section_id, &preserve, cleanup);
|
||||
/* Free bfd_alloc memory too. If we have matched and preserved
|
||||
a target then the high water mark is that much higher. */
|
||||
if (preserve_match.marker)
|
||||
@ -527,7 +545,7 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching)
|
||||
RIGHT_TARG again. */
|
||||
if (match_targ != right_targ)
|
||||
{
|
||||
bfd_reinit (abfd, initial_section_id, cleanup);
|
||||
bfd_reinit (abfd, initial_section_id, &preserve, cleanup);
|
||||
bfd_release (abfd, preserve.marker);
|
||||
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
|
||||
goto err_ret;
|
||||
|
@ -1158,6 +1158,17 @@ pe_ILF_build_a_bfd (bfd * abfd,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Cleanup function, returned from check_format hook. */
|
||||
|
||||
static void
|
||||
pe_ILF_cleanup (bfd *abfd)
|
||||
{
|
||||
struct bfd_in_memory *bim = abfd->iostream;
|
||||
free (bim->buffer);
|
||||
free (bim);
|
||||
abfd->iostream = NULL;
|
||||
}
|
||||
|
||||
/* We have detected an Import Library Format archive element.
|
||||
Decode the element and return the appropriate target. */
|
||||
|
||||
@ -1331,7 +1342,7 @@ pe_ILF_object_p (bfd * abfd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _bfd_no_cleanup;
|
||||
return pe_ILF_cleanup;
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
x
Reference in New Issue
Block a user