From a6ad7914429a22d3d835bd998b032212b776a08a Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 3 Aug 2022 13:31:57 +0100 Subject: Fix a conflict between the linker's need to rename some PE format input libraries and the BFD library's file caching mechanism. PR 29389 bfd * bfd.c (BFD_CLOSED_BY_CACHE): New bfd flag. * cache.c (bfd_cache_delete): Set BFD_CLOSED_BY_DELETE on the closed bfd. (bfd_cache_lookup_worker): Clear BFD_CLOSED_BY_DELETE on the newly reopened bfd. * opncls.c (bfd_set_filename): Refuse to change the name of a bfd that has been closed by bfd_cache_delete. Mark changed bfds as uncacheable. * bfd-in2.h: Regenerate. ld * ldlang.h (lang_input_statement_struct): Add sort_key field. * emultempl/pe.em (after_open): If multiple import libraries refer to the same bfd, store their names in the sort_key field. * emultempl/pep.em (after_open): Likewise. * ldlang.c (sort_filename): New function. Returns the filename to be used when sorting input files. (wild_sort): Use the sort_filename function. --- bfd/ChangeLog | 13 +++++++++++++ bfd/bfd-in2.h | 2 ++ bfd/bfd.c | 2 ++ bfd/cache.c | 8 ++++++-- bfd/opncls.c | 24 +++++++++++++++++++++--- ld/ChangeLog | 11 +++++++++++ ld/emultempl/pe.em | 25 ++++++++++++++----------- ld/emultempl/pep.em | 25 ++++++++++++++----------- ld/ldlang.c | 43 ++++++++++++++++++++++--------------------- ld/ldlang.h | 2 ++ 10 files changed, 107 insertions(+), 48 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index afabbc0..cb1f48b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2022-08-03 Nick Clifton + + PR 29389 + * bfd.c (BFD_CLOSED_BY_CACHE): New bfd flag. + * cache.c (bfd_cache_delete): Set BFD_CLOSED_BY_DELETE on the + closed bfd. + (bfd_cache_lookup_worker): Clear BFD_CLOSED_BY_DELETE on the newly + reopened bfd. + * opncls.c (bfd_set_filename): Refuse to change the name of a bfd + that has been closed by bfd_cache_delete. Mark changed bfds as + uncacheable. + * bfd-in2.h: Regenerate. + 2022-07-29 Nick Clifton PR 29424 diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 91ada0e..a95e4a2 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -6638,6 +6638,8 @@ struct bfd /* Put pathnames into archives (non-POSIX). */ #define BFD_ARCHIVE_FULL_PATH 0x100000 +#define BFD_CLOSED_BY_CACHE 0x200000 + /* Flags bits to be saved in bfd_preserve_save. */ #define BFD_FLAGS_SAVED \ (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \ diff --git a/bfd/bfd.c b/bfd/bfd.c index 3e85e17..5e5272b 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -176,6 +176,8 @@ CODE_FRAGMENT . {* Put pathnames into archives (non-POSIX). *} .#define BFD_ARCHIVE_FULL_PATH 0x100000 . +.#define BFD_CLOSED_BY_CACHE 0x200000 +. . {* Flags bits to be saved in bfd_preserve_save. *} .#define BFD_FLAGS_SAVED \ . (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \ diff --git a/bfd/cache.c b/bfd/cache.c index 8a6d359..73b68c7 100644 --- a/bfd/cache.c +++ b/bfd/cache.c @@ -177,6 +177,7 @@ bfd_cache_delete (bfd *abfd) abfd->iostream = NULL; --open_files; + abfd->flags |= BFD_CLOSED_BY_CACHE; return ret; } @@ -265,10 +266,13 @@ bfd_cache_lookup_worker (bfd *abfd, enum cache_flag flag) && !(flag & CACHE_NO_SEEK_ERROR)) bfd_set_error (bfd_error_system_call); else - return (FILE *) abfd->iostream; + { + abfd->flags &= ~BFD_CLOSED_BY_CACHE; + return (FILE *) abfd->iostream; + } /* xgettext:c-format */ - _bfd_error_handler (_("reopening %pB: %s\n"), + _bfd_error_handler (_("reopening %pB: %s"), abfd, bfd_errmsg (bfd_get_error ())); return NULL; } diff --git a/bfd/opncls.c b/bfd/opncls.c index f0ca904..a5bc2de 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -2107,10 +2107,28 @@ bfd_set_filename (bfd *abfd, const char *filename) { size_t len = strlen (filename) + 1; char *n = bfd_alloc (abfd, len); - if (n) + + if (n == NULL) + return NULL; + + if (abfd->filename != NULL) { - memcpy (n, filename, len); - abfd->filename = n; + /* PR 29389. If we attempt to rename a file that has been closed due + to caching, then we will not be able to reopen it later on. */ + if (abfd->iostream == NULL && (abfd->flags & BFD_CLOSED_BY_CACHE)) + { + bfd_set_error (bfd_error_invalid_operation); + return NULL; + } + + /* Similarly if we attempt to close a renamed file because the + cache is now full, we will not be able to reopen it later on. */ + if (abfd->iostream != NULL) + abfd->cacheable = 0; } + + memcpy (n, filename, len); + abfd->filename = n; + return n; } diff --git a/ld/ChangeLog b/ld/ChangeLog index 30fc193..06dd21b 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,14 @@ +2022-08-03 Alan Modra + + PR 29389 + * ldlang.h (lang_input_statement_struct): Add sort_key field. + * emultempl/pe.em (after_open): If multiple import libraries refer + to the same bfd, store their names in the sort_key field. + * emultempl/pep.em (after_open): Likewise. + * ldlang.c (sort_filename): New function. Returns the filename to + be used when sorting input files. + (wild_sort): Use the sort_filename function. + 2022-07-29 Rainer Orth PR ld/29411 diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 2fd4ff4..ad969cc 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -1583,6 +1583,7 @@ gld${EMULATION_NAME}_after_open (void) { struct bfd_symbol *s; struct bfd_link_hash_entry * blhe; + bfd *other_bfd; const char *other_bfd_filename; s = (relocs[i]->sym_ptr_ptr)[0]; @@ -1599,20 +1600,25 @@ gld${EMULATION_NAME}_after_open (void) || blhe->type != bfd_link_hash_defined) continue; + other_bfd = blhe->u.def.section->owner; + if (other_bfd->my_archive == is->the_bfd->my_archive) + continue; + other_bfd_filename - = blhe->u.def.section->owner->my_archive - ? bfd_get_filename (blhe->u.def.section->owner->my_archive) - : bfd_get_filename (blhe->u.def.section->owner); + = (other_bfd->my_archive + ? bfd_get_filename (other_bfd->my_archive) + : bfd_get_filename (other_bfd)); if (filename_cmp (bfd_get_filename (is->the_bfd->my_archive), other_bfd_filename) == 0) continue; - /* Rename this implib to match the other one. */ - if (!bfd_set_filename (is->the_bfd->my_archive, - other_bfd_filename)) - einfo ("%F%P: %pB: %E\n", is->the_bfd); + /* Sort this implib to match the other one. */ + lang_input_statement_type *arch_is + = bfd_usrdata (is->the_bfd->my_archive); + arch_is->sort_key = other_bfd_filename; + break; } free (relocs); @@ -1719,10 +1725,7 @@ gld${EMULATION_NAME}_after_open (void) = xmalloc (strlen (bfd_get_filename (is->the_bfd)) + 3); sprintf (new_name, "%s.%c", bfd_get_filename (is->the_bfd), seq); - is->filename = bfd_set_filename (is->the_bfd, new_name); - free (new_name); - if (!is->filename) - einfo ("%F%P: %pB: %E\n", is->the_bfd); + is->sort_key = new_name; } } } diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index e68d1e6..ee36a9a 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -1547,6 +1547,7 @@ gld${EMULATION_NAME}_after_open (void) { struct bfd_symbol *s; struct bfd_link_hash_entry * blhe; + bfd *other_bfd; const char *other_bfd_filename; s = (relocs[i]->sym_ptr_ptr)[0]; @@ -1563,20 +1564,25 @@ gld${EMULATION_NAME}_after_open (void) || blhe->type != bfd_link_hash_defined) continue; + other_bfd = blhe->u.def.section->owner; + if (other_bfd->my_archive == is->the_bfd->my_archive) + continue; + other_bfd_filename - = blhe->u.def.section->owner->my_archive - ? bfd_get_filename (blhe->u.def.section->owner->my_archive) - : bfd_get_filename (blhe->u.def.section->owner); + = (other_bfd->my_archive + ? bfd_get_filename (other_bfd->my_archive) + : bfd_get_filename (other_bfd)); if (filename_cmp (bfd_get_filename (is->the_bfd->my_archive), other_bfd_filename) == 0) continue; - /* Rename this implib to match the other one. */ - if (!bfd_set_filename (is->the_bfd->my_archive, - other_bfd_filename)) - einfo ("%F%P: %pB: %E\n", is->the_bfd); + /* Sort this implib to match the other one. */ + lang_input_statement_type *arch_is + = bfd_usrdata (is->the_bfd->my_archive); + arch_is->sort_key = other_bfd_filename; + break; } free (relocs); @@ -1683,10 +1689,7 @@ gld${EMULATION_NAME}_after_open (void) = xmalloc (strlen (bfd_get_filename (is->the_bfd)) + 3); sprintf (new_name, "%s.%c", bfd_get_filename (is->the_bfd), seq); - is->filename = bfd_set_filename (is->the_bfd, new_name); - free (new_name); - if (!is->filename) - einfo ("%F%P: %pB: %E\n", is->the_bfd); + is->sort_key = new_name; } } } diff --git a/ld/ldlang.c b/ld/ldlang.c index e7bc9f2..b7bb4a3 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1125,6 +1125,7 @@ new_afile (const char *name, p->flags.add_DT_NEEDED_for_regular = input_flags.add_DT_NEEDED_for_regular; p->flags.whole_archive = input_flags.whole_archive; p->flags.sysrooted = input_flags.sysrooted; + p->sort_key = NULL; switch (file_type) { @@ -2723,6 +2724,17 @@ lang_add_section (lang_statement_list_type *ptr, new_section->pattern = pattern; } +/* PE puts the sort key in the input statement. */ + +static const char * +sort_filename (bfd *abfd) +{ + lang_input_statement_type *is = bfd_usrdata (abfd); + if (is->sort_key) + return is->sort_key; + return bfd_get_filename (abfd); +} + /* Handle wildcard sorting. This returns the lang_input_section which should follow the one we are going to create for SECTION and FILE, based on the sorting requirements of WILD. It returns NULL if the @@ -2762,28 +2774,17 @@ wild_sort (lang_wild_statement_type *wild, the archive and then the name of the file within the archive. */ - if (file->the_bfd != NULL - && file->the_bfd->my_archive != NULL) - { - fn = bfd_get_filename (file->the_bfd->my_archive); - fa = true; - } + fa = file->the_bfd->my_archive != NULL; + if (fa) + fn = sort_filename (file->the_bfd->my_archive); else - { - fn = file->filename; - fa = false; - } + fn = sort_filename (file->the_bfd); - if (ls->section->owner->my_archive != NULL) - { - ln = bfd_get_filename (ls->section->owner->my_archive); - la = true; - } + la = ls->section->owner->my_archive != NULL; + if (la) + ln = sort_filename (ls->section->owner->my_archive); else - { - ln = bfd_get_filename (ls->section->owner); - la = false; - } + ln = sort_filename (ls->section->owner); i = filename_cmp (fn, ln); if (i > 0) @@ -2794,9 +2795,9 @@ wild_sort (lang_wild_statement_type *wild, if (fa || la) { if (fa) - fn = file->filename; + fn = sort_filename (file->the_bfd); if (la) - ln = bfd_get_filename (ls->section->owner); + ln = sort_filename (ls->section->owner); i = filename_cmp (fn, ln); if (i > 0) diff --git a/ld/ldlang.h b/ld/ldlang.h index 95f6e46..b853cdb 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -305,6 +305,8 @@ typedef struct lang_input_statement_struct Usually the same as filename, but for a file spec'd with -l this is the -l switch itself rather than the filename. */ const char *local_sym_name; + /* Name to use when sorting. */ + const char *sort_key; /* Extra search path. Used to find a file relative to the directory of the current linker script. */ const char *extra_search_path; -- cgit v1.1