diff options
author | Nick Clifton <nickc@redhat.com> | 2023-06-14 13:39:03 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2023-06-14 13:39:03 +0100 |
commit | fb221fba1a5eb05355f248d6aa1e3ab4316899fd (patch) | |
tree | 99d95404eca8e96812884ec49ecada00d2f093c5 /ld/ldfile.c | |
parent | 6f860418d556d4e5492b3da9e1a52e4b85a85f3e (diff) | |
download | gdb-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.c | 210 |
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. */ |