summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2022-08-03 13:31:57 +0100
committerNick Clifton <nickc@redhat.com>2022-08-03 13:31:57 +0100
commita6ad7914429a22d3d835bd998b032212b776a08a (patch)
treed81caa6275932745dedefa9f17d391454a84a19f
parent8b8da1a9f31941fa167c9f2bd2a80cdd1dccb452 (diff)
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.
-rw-r--r--bfd/ChangeLog13
-rw-r--r--bfd/bfd-in2.h2
-rw-r--r--bfd/bfd.c2
-rw-r--r--bfd/cache.c8
-rw-r--r--bfd/opncls.c24
-rw-r--r--ld/ChangeLog11
-rw-r--r--ld/emultempl/pe.em25
-rw-r--r--ld/emultempl/pep.em25
-rw-r--r--ld/ldlang.c43
-rw-r--r--ld/ldlang.h2
10 files changed, 107 insertions, 48 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index afabbc0f56..cb1f48ba48 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,16 @@
+2022-08-03 Nick Clifton <nickc@redhat.com>
+
+ 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 <nickc@redhat.com>
PR 29424
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 91ada0e3a9..a95e4a24ca 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 3e85e171e3..5e5272b908 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 8a6d359a78..73b68c7aff 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 f0ca9048f6..a5bc2de364 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 30fc1937d0..06dd21bfd4 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,14 @@
+2022-08-03 Alan Modra <amodra@gmail.com>
+
+ 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 <ro@CeBiTec.Uni-Bielefeld.DE>
PR ld/29411
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 2fd4ff4aca..ad969ccec1 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 e68d1e69f1..ee36a9a7e5 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 e7bc9f2d26..b7bb4a3aed 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 95f6e468b3..b853cdbd45 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;