| From 10baf9f75e4e4e2fb37a579c68672141858aea5e Mon Sep 17 00:00:00 2001 |
| From: Joshua Watt <JPEWhacker@gmail.com> |
| Date: Tue, 19 Nov 2019 13:12:17 -0600 |
| Subject: [PATCH] Add --debug-prefix-map option |
| |
| Adds an option to remap file prefixes in output object files. This is |
| analogous to the "-fdebug-prefix-map" option in GCC, and allows files to |
| be built in a reproducible manner regardless of the build directory. |
| |
| Upstream-Status: Submitted [https://bugzilla.nasm.us/show_bug.cgi?id=3392635] |
| Signed-off-by: Joshua Watt <JPEWhacker@gmail.com> |
| --- |
| asm/nasm.c | 28 ++++++++++++++++++++++++++-- |
| include/nasmlib.h | 9 +++++++++ |
| nasm.txt | 3 +++ |
| nasmlib/filename.c | 20 ++++++++++++++++++++ |
| output/outas86.c | 4 +++- |
| output/outcoff.c | 4 ++-- |
| output/outelf.c | 13 ++++++++----- |
| output/outieee.c | 2 +- |
| output/outobj.c | 2 +- |
| stdlib/strlcat.c | 2 +- |
| test/elfdebugprefix.asm | 5 +++++ |
| test/performtest.pl | 12 ++++++++++-- |
| 12 files changed, 89 insertions(+), 15 deletions(-) |
| create mode 100644 test/elfdebugprefix.asm |
| |
| diff --git a/asm/nasm.c b/asm/nasm.c |
| index 49fa00e..ff117cf 100644 |
| --- a/asm/nasm.c |
| +++ b/asm/nasm.c |
| @@ -913,7 +913,8 @@ enum text_options { |
| OPT_DEBUG, |
| OPT_INFO, |
| OPT_REPRODUCIBLE, |
| - OPT_BITS |
| + OPT_BITS, |
| + OPT_DEBUG_PREFIX_MAP |
| }; |
| enum need_arg { |
| ARG_NO, |
| @@ -952,6 +953,7 @@ static const struct textargs textopts[] = { |
| {"debug", OPT_DEBUG, ARG_MAYBE, 0}, |
| {"reproducible", OPT_REPRODUCIBLE, ARG_NO, 0}, |
| {"bits", OPT_BITS, ARG_YES, 0}, |
| + {"debug-prefix-map", OPT_DEBUG_PREFIX_MAP, true, 0}, |
| {NULL, OPT_BOGUS, ARG_NO, 0} |
| }; |
| |
| @@ -1337,6 +1339,26 @@ static bool process_arg(char *p, char *q, int pass) |
| case OPT_REPRODUCIBLE: |
| reproducible = true; |
| break; |
| + case OPT_DEBUG_PREFIX_MAP: { |
| + struct debug_prefix_list *d; |
| + char *c; |
| + c = strchr(param, '='); |
| + |
| + if (!c) { |
| + nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE, |
| + "option `--%s' must be of the form `BASE=DEST'", p); |
| + break; |
| + } |
| + |
| + *c = '\0'; |
| + d = nasm_malloc(sizeof(*d)); |
| + d->next = debug_prefixes; |
| + d->base = nasm_strdup(param); |
| + d->dest = nasm_strdup(c + 1); |
| + debug_prefixes = d; |
| + *c = '='; |
| + } |
| + break; |
| case OPT_HELP: |
| /* Allow --help topic without *requiring* topic */ |
| if (!param) |
| @@ -2428,7 +2450,9 @@ static void help(FILE *out, const char *what) |
| " -w+x enable warning x %s(also -Wx)\n" |
| " -w-x disable warning x (also -Wno-x)\n" |
| " -w[+-]error promote all warnings to errors (also -Werror)\n" |
| - " -w[+-]error=x promote warning x to errors (also -Werror=x)\n", |
| + " -w[+-]error=x promote warning x to errors (also -Werror=x)\n" |
| + " --debug-prefix-map base=dest\n" |
| + " remap paths starting with 'base' to 'dest' in output files\n", |
| SEE("-w")); |
| } |
| if (help_is(with, 'w')) { |
| diff --git a/include/nasmlib.h b/include/nasmlib.h |
| index ed4222b..aafbf00 100644 |
| --- a/include/nasmlib.h |
| +++ b/include/nasmlib.h |
| @@ -334,10 +334,19 @@ static inline const char *nasm_digit_chars(bool ucase) |
| */ |
| int32_t seg_alloc(void); |
| |
| +struct debug_prefix_list { |
| + struct debug_prefix_list *next; |
| + char *base; |
| + char *dest; |
| +}; |
| + |
| +extern struct debug_prefix_list *debug_prefixes; |
| + |
| /* |
| * Add/replace or remove an extension to the end of a filename |
| */ |
| const char *filename_set_extension(const char *inname, const char *extension); |
| +char *filename_debug_remap(char *dest, char const *inname, size_t len); |
| |
| /* |
| * Utility macros... |
| diff --git a/nasm.txt b/nasm.txt |
| index 950c361..8447409 100644 |
| --- a/nasm.txt |
| +++ b/nasm.txt |
| @@ -146,6 +146,9 @@ OPTIONS |
| --postfix:: |
| Prepend or append (respectively) the given argument to all global or |
| extern variables. |
| +--debug-prefix-map 'BASE=DEST':: |
| + Map file names beginning with 'BASE' to 'DEST' when encoding them in |
| + output object files. |
| |
| SYNTAX |
| ------ |
| diff --git a/nasmlib/filename.c b/nasmlib/filename.c |
| index 2c29d38..0e27f69 100644 |
| --- a/nasmlib/filename.c |
| +++ b/nasmlib/filename.c |
| @@ -9,6 +9,8 @@ |
| #include "nasmlib.h" |
| #include "error.h" |
| |
| +struct debug_prefix_list *debug_prefixes = NULL; |
| + |
| /* |
| * Add/modify a filename extension, assumed to be a period-delimited |
| * field at the very end of the filename. Returns a newly allocated |
| @@ -31,3 +33,21 @@ const char *filename_set_extension(const char *inname, const char *extension) |
| |
| return p; |
| } |
| + |
| +char *filename_debug_remap(char *dest, char const *in, size_t len) |
| +{ |
| + struct debug_prefix_list *d; |
| + size_t n; |
| + |
| + for (d = debug_prefixes; d != NULL; d = d->next) { |
| + n = strlen(d->base); |
| + if (strncmp(in, d->base, n) == 0) { |
| + strlcpy(dest, d->dest, len); |
| + strlcat(dest, &in[n], len); |
| + return dest; |
| + } |
| + } |
| + |
| + strlcpy(dest, in, len); |
| + return dest; |
| +} |
| \ No newline at end of file |
| diff --git a/output/outas86.c b/output/outas86.c |
| index 0640af7..c654bbe 100644 |
| --- a/output/outas86.c |
| +++ b/output/outas86.c |
| @@ -80,6 +80,8 @@ static void as86_sect_write(struct Section *, const uint8_t *, |
| |
| static void as86_init(void) |
| { |
| + char filename[FILENAME_MAX]; |
| + |
| stext.data = saa_init(1L); |
| stext.datalen = 0L; |
| stext.head = stext.last = NULL; |
| @@ -101,7 +103,7 @@ static void as86_init(void) |
| strslen = 0; |
| |
| /* as86 module name = input file minus extension */ |
| - as86_add_string(filename_set_extension(inname, "")); |
| + as86_add_string(filename_debug_remap(filename, filename_set_extension(inname, ""), sizeof(filename))); |
| } |
| |
| static void as86_cleanup(void) |
| diff --git a/output/outcoff.c b/output/outcoff.c |
| index d38085d..b490bb6 100644 |
| --- a/output/outcoff.c |
| +++ b/output/outcoff.c |
| @@ -1231,7 +1231,7 @@ static void coff_symbol(char *name, int32_t strpos, int32_t value, |
| |
| static void coff_write_symbols(void) |
| { |
| - char filename[18]; |
| + char filename[19]; |
| uint32_t i; |
| |
| /* |
| @@ -1241,7 +1241,7 @@ static void coff_write_symbols(void) |
| if (reproducible) |
| memset(filename, 0, 18); |
| else |
| - strncpy(filename, inname, 18); |
| + filename_debug_remap(filename, inname, 19); |
| nasm_write(filename, 18, ofile); |
| |
| /* |
| diff --git a/output/outelf.c b/output/outelf.c |
| index 7288dda..9847c6e 100644 |
| --- a/output/outelf.c |
| +++ b/output/outelf.c |
| @@ -516,8 +516,8 @@ static void elf_init(void) |
| const char * const *p; |
| const char * cur_path = nasm_realpath(inname); |
| |
| - strlcpy(elf_module, inname, sizeof(elf_module)); |
| - strlcpy(elf_dir, nasm_dirname(cur_path), sizeof(elf_dir)); |
| + filename_debug_remap(elf_module, inname, sizeof(elf_module)); |
| + filename_debug_remap(elf_dir, nasm_dirname(cur_path), sizeof(elf_dir)); |
| sects = NULL; |
| nsects = sectlen = 0; |
| syms = saa_init((int32_t)sizeof(struct elf_symbol)); |
| @@ -3551,13 +3551,17 @@ static void dwarf_findfile(const char * fname) |
| if (dwarf_clist && !(strcmp(fname, dwarf_clist->filename))) |
| return; |
| |
| + char * fname_remapped = nasm_malloc(FILENAME_MAX); |
| + filename_debug_remap(fname_remapped,fname,FILENAME_MAX); |
| + |
| /* search for match */ |
| match = 0; |
| if (dwarf_flist) { |
| match = dwarf_flist; |
| for (finx = 0; finx < dwarf_numfiles; finx++) { |
| - if (!(strcmp(fname, match->filename))) { |
| + if (!(strcmp(fname_remapped, match->filename))) { |
| dwarf_clist = match; |
| + nasm_free(fname_remapped); |
| return; |
| } |
| match = match->next; |
| @@ -3568,8 +3572,7 @@ static void dwarf_findfile(const char * fname) |
| dwarf_clist = nasm_malloc(sizeof(struct linelist)); |
| dwarf_numfiles++; |
| dwarf_clist->line = dwarf_numfiles; |
| - dwarf_clist->filename = nasm_malloc(strlen(fname) + 1); |
| - strcpy(dwarf_clist->filename,fname); |
| + dwarf_clist->filename = fname_remapped; |
| dwarf_clist->next = 0; |
| if (!dwarf_flist) { /* if first entry */ |
| dwarf_flist = dwarf_elist = dwarf_clist; |
| diff --git a/output/outieee.c b/output/outieee.c |
| index 9e26cec..3643eeb 100644 |
| --- a/output/outieee.c |
| +++ b/output/outieee.c |
| @@ -178,7 +178,7 @@ static void ieee_unqualified_name(char *, char *); |
| */ |
| static void ieee_init(void) |
| { |
| - strlcpy(ieee_infile, inname, sizeof(ieee_infile)); |
| + filename_debug_remap(ieee_infile, inname, sizeof(ieee_infile)); |
| any_segs = false; |
| fpubhead = NULL; |
| fpubtail = &fpubhead; |
| diff --git a/output/outobj.c b/output/outobj.c |
| index 685c593..e3eb34a 100644 |
| --- a/output/outobj.c |
| +++ b/output/outobj.c |
| @@ -656,7 +656,7 @@ static const char *get_default_class(const char *segment) |
| |
| static void obj_init(void) |
| { |
| - strlcpy(obj_infile, inname, sizeof(obj_infile)); |
| + filename_debug_remap(obj_infile, inname, sizeof(obj_infile)); |
| first_seg = seg_alloc(); |
| any_segs = false; |
| fpubhead = NULL; |
| diff --git a/stdlib/strlcat.c b/stdlib/strlcat.c |
| index c7cbd59..92a873d 100644 |
| --- a/stdlib/strlcat.c |
| +++ b/stdlib/strlcat.c |
| @@ -29,7 +29,7 @@ size_t strlcat(char *dest, const char *src, size_t size) |
| size_t n; |
| |
| /* find the NULL terminator in dest */ |
| - for (n = 0; i < size && dest[n] != '\0'; n++) |
| + for (n = 0; n < size && dest[n] != '\0'; n++) |
| ; |
| |
| /* destination was not NULL terminated. Return the initial size */ |
| diff --git a/test/elfdebugprefix.asm b/test/elfdebugprefix.asm |
| new file mode 100644 |
| index 0000000..bf845ce |
| --- /dev/null |
| +++ b/test/elfdebugprefix.asm |
| @@ -0,0 +1,5 @@ |
| +;Testname=unoptimized; Arguments=-O0 --debug-prefix-map elf=ELF -felf -oelfdebugprefix.o; Files=stdout stderr elfdebugprefix.o; Validate=readelf --wide --symbols elfdebugprefix.o | grep 'FILE.*ELFdebugprefix.asm' |
| + |
| + SECTION .text |
| +test: ; [1] |
| + ret |
| diff --git a/test/performtest.pl b/test/performtest.pl |
| index 46b1bdf..2426848 100755 |
| --- a/test/performtest.pl |
| +++ b/test/performtest.pl |
| @@ -42,14 +42,22 @@ sub perform { |
| TEST: |
| while(<TESTFILE>) { |
| #See if there is a test case |
| - last unless /Testname=(.*);\s*Arguments=(.*);\s*Files=(.*)/; |
| - my ($subname, $arguments, $files) = ($1, $2, $3); |
| + last unless /Testname=(.*);\s*Arguments=(.*);\s*Files=([^;]*)(?:;\s*Validate=(.*))?/; |
| + my ($subname, $arguments, $files, $validate) = ($1, $2, $3, $4); |
| + chomp $files; |
| debugprint("$subname | $arguments | $files"); |
| |
| #Call nasm with this test case |
| system("$nasm $arguments $testpath > $stdoutfile 2> $stderrfile"); |
| debugprint("$nasm $arguments $testpath > $stdoutfile 2> $stderrfile ----> $?"); |
| |
| + if($validate) { |
| + if(system("$validate >> $stdoutfile 2>> $stderrfile") != 0) { |
| + print "Test $testname/$subname validation failed\n"; |
| + $globalresult = 1; |
| + } |
| + } |
| + |
| #Move the output to the test dir |
| mkpath("$outputdir/$testname/$subname"); |
| foreach(split / /,$files) { |