+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
/* 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 \
. {* 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 \
abfd->iostream = NULL;
--open_files;
+ abfd->flags |= BFD_CLOSED_BY_CACHE;
return ret;
}
&& !(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;
}
{
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;
}
+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
{
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];
|| 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);
= 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;
}
}
}
{
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];
|| 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);
= 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;
}
}
}
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)
{
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
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)
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)
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;