aboutsummaryrefslogtreecommitdiff
path: root/ld/ldfile.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2023-06-14 13:39:03 +0100
committerNick Clifton <nickc@redhat.com>2023-06-14 13:39:03 +0100
commitfb221fba1a5eb05355f248d6aa1e3ab4316899fd (patch)
tree99d95404eca8e96812884ec49ecada00d2f093c5 /ld/ldfile.c
parent6f860418d556d4e5492b3da9e1a52e4b85a85f3e (diff)
downloadgdb-fb221fba1a5eb05355f248d6aa1e3ab4316899fd.zip
gdb-fb221fba1a5eb05355f248d6aa1e3ab4316899fd.tar.gz
gdb-fb221fba1a5eb05355f248d6aa1e3ab4316899fd.tar.bz2
Add --remap-inputs option to the BFD linker.
PR 30374 * ldfile.c (struct input_remap): New structure. (ldfile_add_remap): New function. (ldfile_remap_input_free): New function. (ldfile_add_remap_file): New function. (ldfile_possibly_remap_input): New function. (ldfile_print_input_remaps): New function. * ldfile.h: Add prototypes for new functions. * ldlang.c (new_afile): Call ldfile_possibly_remap_input. (lang_finish): Call ldfile_remap_input_free. (lang_map): Call ldfile_print_input_remaps. * ldlex.h (OPTION_REMAP_INPUTS, OPTION_REMAP_INPUTS_FILE): Define. * lexsup.c (ld_options): Add --remap-inputs-file and --remap-inputs. (parse_args): Handle new options. * NEWS: Mention the new feature. * ld.texi: Document the new options. * testsuite/ld-misc/input-remap.exp: New test driver. * testsuite/ld-misc/remaps.r: New file: Expected linker output. * testsuite/ld-misc/remaps.txt: New file. Input remaps file.
Diffstat (limited to 'ld/ldfile.c')
-rw-r--r--ld/ldfile.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/ld/ldfile.c b/ld/ldfile.c
index b8fd4e5..4976367 100644
--- a/ld/ldfile.c
+++ b/ld/ldfile.c
@@ -34,6 +34,7 @@
#include "ldemul.h"
#include "libiberty.h"
#include "filenames.h"
+#include <fnmatch.h>
#if BFD_SUPPORTS_PLUGINS
#include "plugin-api.h"
#include "plugin.h"
@@ -65,6 +66,215 @@ static search_dirs_type **search_tail_ptr = &search_head;
static search_arch_type *search_arch_head;
static search_arch_type **search_arch_tail_ptr = &search_arch_head;
+typedef struct input_remap
+{
+ const char * pattern; /* Pattern to match input files. */
+ const char * renamed; /* Filename to use if the pattern matches. */
+ struct input_remap * next; /* Link in a chain of these structures. */
+} input_remap;
+
+static struct input_remap * input_remaps = NULL;
+
+void
+ldfile_add_remap (const char * pattern, const char * renamed)
+{
+ struct input_remap * new_entry;
+
+ new_entry = xmalloc (sizeof * new_entry);
+ new_entry->pattern = xstrdup (pattern);
+ new_entry->next = NULL;
+
+ /* Look for special filenames that mean that the input file should be ignored. */
+ if (strcmp (renamed, "/dev/null") == 0
+ || strcmp (renamed, "NUL") == 0)
+ new_entry->renamed = NULL;
+ else
+ /* FIXME: Should we add sanity checking of the 'renamed' string ? */
+ new_entry->renamed = xstrdup (renamed);
+
+ /* It would be easier to add this new node at the start of the chain,
+ but users expect that remapping will occur in the order in which
+ they occur on the command line, and in the remapping files. */
+ if (input_remaps == NULL)
+ {
+ input_remaps = new_entry;
+ }
+ else
+ {
+ struct input_remap * i;
+
+ for (i = input_remaps; i->next != NULL; i = i->next)
+ ;
+ i->next = new_entry;
+ }
+}
+
+void
+ldfile_remap_input_free (void)
+{
+ while (input_remaps != NULL)
+ {
+ struct input_remap * i = input_remaps;
+
+ input_remaps = i->next;
+ free ((void *) i->pattern);
+ free ((void *) i->renamed);
+ free (i);
+ }
+}
+
+bool
+ldfile_add_remap_file (const char * file)
+{
+ FILE * f;
+
+ f = fopen (file, FOPEN_RT);
+ if (f == NULL)
+ return false;
+
+ size_t linelen = 256;
+ char * line = xmalloc (linelen);
+
+ do
+ {
+ char * p = line;
+ char * q;
+
+ /* Normally this would use getline(3), but we need to be portable. */
+ while ((q = fgets (p, linelen - (p - line), f)) != NULL
+ && strlen (q) == linelen - (p - line) - 1
+ && line[linelen - 2] != '\n')
+ {
+ line = xrealloc (line, 2 * linelen);
+ p = line + linelen - 1;
+ linelen += linelen;
+ }
+
+ if (q == NULL && p == line)
+ break;
+
+ p = strchr (line, '\n');
+ if (p)
+ *p = '\0';
+
+ /* Because the file format does not know any form of quoting we
+ can search forward for the next '#' character and if found
+ make it terminating the line. */
+ p = strchr (line, '#');
+ if (p)
+ *p = '\0';
+
+ /* Remove leading whitespace. NUL is no whitespace character. */
+ p = line;
+ while (*p == ' ' || *p == '\f' || *p == '\r' || *p == '\t' || *p == '\v')
+ ++p;
+
+ /* If the line is blank it is ignored. */
+ if (*p == '\0')
+ continue;
+
+ char * pattern = p;
+
+ /* Advance past the pattern. We accept whitespace or '=' as an
+ end-of-pattern marker. */
+ while (*p && *p != '=' && *p != ' ' && *p != '\t' && *p != '\f'
+ && *p != '\r' && *p != '\v')
+ ++p;
+
+ if (*p == '\0')
+ {
+ einfo ("%F%P: malformed remap file entry: %s\n", line);
+ continue;
+ }
+
+ * p++ = '\0';
+
+ /* Skip whitespace again. */
+ while (*p == ' ' || *p == '\f' || *p == '\r' || *p == '\t' || *p == '\v')
+ ++p;
+
+ if (*p == '\0')
+ {
+ einfo ("%F%P: malformed remap file entry: %s\n", line);
+ continue;
+ }
+
+ char * rename = p;
+
+ /* Advance past the rename entry. */
+ while (*p && *p != '=' && *p != ' ' && *p != '\t' && *p != '\f'
+ && *p != '\r' && *p != '\v')
+ ++p;
+ /* And terminate it. */
+ *p = '\0';
+
+ ldfile_add_remap (pattern, rename);
+ }
+ while (! feof (f));
+
+ free (line);
+ fclose (f);
+
+ return true;
+}
+
+const char *
+ldfile_possibly_remap_input (const char * filename)
+{
+ struct input_remap * i;
+
+ if (filename == NULL)
+ return NULL;
+
+ for (i = input_remaps; i != NULL; i = i->next)
+ {
+ if (fnmatch (i->pattern, filename, 0) == 0)
+ {
+ if (verbose)
+ {
+ if (strpbrk ((i->pattern), "?*[") != NULL)
+ {
+ if (i->renamed)
+ info_msg (_("remap input file '%s' to '%s' based upon pattern '%s'\n"),
+ filename, i->renamed, i->pattern);
+ else
+ info_msg (_("remove input file '%s' based upon pattern '%s'\n"),
+ filename, i->pattern);
+ }
+ else
+ {
+ if (i->renamed)
+ info_msg (_("remap input file '%s' to '%s'\n"),
+ filename, i->renamed);
+ else
+ info_msg (_("remove input file '%s'\n"),
+ filename);
+ }
+ }
+
+ return i->renamed;
+ }
+ }
+
+ return filename;
+}
+
+void
+ldfile_print_input_remaps (void)
+{
+ if (input_remaps == NULL)
+ return;
+
+ minfo (_("\nInput File Remapping\n\n"));
+
+ struct input_remap * i;
+
+ for (i = input_remaps; i != NULL; i = i->next)
+ minfo (_(" Pattern: %s\tMaps To: %s\n"), i->pattern,
+ i->renamed ? i->renamed : _("<discard>"));
+}
+
+
/* Test whether a pathname, after canonicalization, is the same or a
sub-directory of the sysroot directory. */