[nasm:nasm-2.15.xx] Add option to create reproducible output

nasm-bot for H. Peter Anvin (Intel) hpa at zytor.com
Thu Aug 27 13:09:03 PDT 2020


Commit-ID:  bf79786e894ad16519e5374291205ebe71da07b8
Gitweb:     http://repo.or.cz/w/nasm.git?a=commitdiff;h=bf79786e894ad16519e5374291205ebe71da07b8
Author:     H. Peter Anvin (Intel) <hpa at zytor.com>
AuthorDate: Thu, 27 Aug 2020 13:01:57 -0700
Committer:  H. Peter Anvin (Intel) <hpa at zytor.com>
CommitDate: Thu, 27 Aug 2020 13:06:08 -0700

Add option to create reproducible output

We need the ability to produce consistent output for our own tests,
anyway, so make this a user-accessible feature. This was requested in
BR 3392635.

This obsoletes the NASM_TEST_RUN environment variable; simply use the
normal NASMENV environment variable instead.

The .obj tests in travis needed to be updated in order to remove the
rather pointless suffix " CONST" from the NASM signatures.

Reported-by: Joshua Watt <JPEWhacker at gmail.com>
Signed-off-by: H. Peter Anvin (Intel) <hpa at zytor.com>


---
 asm/nasm.c                     |   9 ++++++++-
 doc/changes.src                |   3 +++
 doc/nasmdoc.src                |   6 ++++++
 include/nasm.h                 |   9 ++++++++-
 include/ver.h                  |   6 +++---
 nasmlib/ver.c                  |  44 +++++++++++++++++------------------------
 output/outcoff.c               |  11 +----------
 travis/nasm-t.py               |   2 +-
 travis/test/alonesym-obj.obj.t | Bin 1161 -> 1155 bytes
 travis/test/br3392643.obj.t    | Bin 349 -> 343 bytes
 travis/test/elif.o.t           | Bin 230 -> 224 bytes
 travis/test/obj.o.t            | Bin 480 -> 474 bytes
 12 files changed, 48 insertions(+), 42 deletions(-)

diff --git a/asm/nasm.c b/asm/nasm.c
index c5d03c8a..e5ae89af 100644
--- a/asm/nasm.c
+++ b/asm/nasm.c
@@ -938,7 +938,8 @@ enum text_options {
     OPT_LIMIT,
     OPT_KEEP_ALL,
     OPT_NO_LINE,
-    OPT_DEBUG
+    OPT_DEBUG,
+    OPT_REPRODUCIBLE
 };
 enum need_arg {
     ARG_NO,
@@ -970,6 +971,7 @@ static const struct textargs textopts[] = {
     {"keep-all", OPT_KEEP_ALL, ARG_NO, 0},
     {"no-line",  OPT_NO_LINE, ARG_NO, 0},
     {"debug",    OPT_DEBUG, ARG_MAYBE, 0},
+    {"reproducible", OPT_REPRODUCIBLE, ARG_NO, 0},
     {NULL, OPT_BOGUS, ARG_NO, 0}
 };
 
@@ -1332,6 +1334,9 @@ static bool process_arg(char *p, char *q, int pass)
                 case OPT_DEBUG:
                     debug_nasm = param ? strtoul(param, NULL, 10) : debug_nasm+1;
                     break;
+                case OPT_REPRODUCIBLE:
+                    reproducible = true;
+                    break;
                 case OPT_HELP:
                     help(stdout);
                     exit(0);
@@ -2293,6 +2298,8 @@ static void help(FILE *out)
         "   --lprefix str  prepend the given string to local symbols\n"
         "   --lpostfix str append the given string to local symbols\n"
         "\n"
+        "   --reproducible attempt to produce run-to-run identical output\n"
+        "\n"
         "    -w+x          enable warning x (also -Wx)\n"
         "    -w-x          disable warning x (also -Wno-x)\n"
         "    -w[+-]error   promote all warnings to errors (also -Werror)\n"
diff --git a/doc/changes.src b/doc/changes.src
index 9b0e02d0..7b9665a2 100644
--- a/doc/changes.src
+++ b/doc/changes.src
@@ -12,6 +12,9 @@ since 2007.
 \b Correct \c{%ifid $} and \c{%ifid $$} being treated as true. See
 \k{iftyp}.
 
+\b Add \c{--reproducible} option to suppress NASM version numbers and
+timestamps in output files. See \k{opt-reproducible}.
+
 \S{cl-2.15.04} Version 2.15.04
 
 \b More sensible handling of the case where one single-line macro
diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src
index 027c7445..efbf3b23 100644
--- a/doc/nasmdoc.src
+++ b/doc/nasmdoc.src
@@ -982,6 +982,12 @@ If this option is given, all \i\c{%line} directives in the source code
 are ignored. This can be useful for debugging already preprocessed
 code. See \k{line}.
 
+\S{opt-reproducible} The \i\c{--reproducible} Option
+
+If this option is given, NASM will not emit information that is
+inherently dependent on the NASM version or different from run to run
+(such as timestamps) into the output file.
+
 
 \S{nasmenv} The \i\c{NASMENV} \i{Environment} Variable
 
diff --git a/include/nasm.h b/include/nasm.h
index cf8b808e..f6e77db6 100644
--- a/include/nasm.h
+++ b/include/nasm.h
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 1996-2018 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2020 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -67,6 +67,13 @@ struct compile_time {
 };
 extern struct compile_time official_compile_time;
 
+/* POSIX timestamp if and only if we are not a reproducible build */
+extern bool reproducible;
+static inline int64_t posix_timestamp(void)
+{
+    return reproducible ? 0 : official_compile_time.posix;
+}
+
 #define NO_SEG  INT32_C(-1)     /* null segment value */
 #define SEG_ABS 0x40000000L     /* mask for far-absolute segments */
 
diff --git a/include/ver.h b/include/ver.h
index ab6e9784..a5bbf384 100644
--- a/include/ver.h
+++ b/include/ver.h
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 1996-2016 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2020 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -44,12 +44,12 @@ extern const char nasm_version[];
 extern const char nasm_date[];
 extern const char nasm_compile_options[];
 
+extern bool reproducible;
+
 extern const char *nasm_comment(void);
 extern size_t nasm_comment_len(void);
 
 extern const char *nasm_signature(void);
 extern size_t nasm_signature_len(void);
 
-extern int nasm_test_run(void);
-
 #endif /* NASM_VER_H */
diff --git a/nasmlib/ver.c b/nasmlib/ver.c
index 9f80f79c..96260b6c 100644
--- a/nasmlib/ver.c
+++ b/nasmlib/ver.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *   
- *   Copyright 1996-2016 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2020 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -43,46 +43,38 @@ const char nasm_compile_options[] = ""
 #endif
     ;
 
-/* These are used by some backends. */
-static const char __nasm_comment[] =
-    "The Netwide Assembler " NASM_VER;
+bool reproducible;              /* Reproducible output */
 
-static const char __nasm_signature[] =
-    "NASM " NASM_VER;
-
-/* These are constant so we could pass regression tests  */
-static const char __nasm_comment_const[] ="The Netwide Assembler CONST";
-static const char __nasm_signature_const[] = "NASM CONST";
-
-int nasm_test_run(void)
+/* These are used by some backends. For a reproducible build,
+ * these cannot contain version numbers.
+ */
+static const char * const _nasm_comment[2] =
 {
-	return getenv("NASM_TEST_RUN") ? 1 : 0;
-}
+    "The Netwide Assembler " NASM_VER,
+    "The Netwide Assembler"
+};
+
+static const char * const _nasm_signature[2] = {
+    "NASM " NASM_VER,
+    "NASM"
+};
 
 const char *nasm_comment(void)
 {
-	if (!nasm_test_run())
-		return __nasm_comment;
-	return __nasm_comment_const;
+    return _nasm_comment[reproducible];
 }
 
 size_t nasm_comment_len(void)
 {
-	if (!nasm_test_run())
-		return strlen(__nasm_comment);
-	return strlen(__nasm_comment_const);
+    return strlen(nasm_comment());
 }
 
 const char *nasm_signature(void)
 {
-	if (!nasm_test_run())
-		return __nasm_signature;
-	return __nasm_signature_const;
+    return _nasm_signature[reproducible];
 }
 
 size_t nasm_signature_len(void)
 {
-	if (!nasm_test_run())
-		return strlen(__nasm_signature);
-	return strlen(__nasm_signature_const);
+    return strlen(nasm_signature());
 }
diff --git a/output/outcoff.c b/output/outcoff.c
index 6568ac23..58fa0249 100644
--- a/output/outcoff.c
+++ b/output/outcoff.c
@@ -936,16 +936,7 @@ static void coff_write(void)
         i = IMAGE_FILE_MACHINE_I386;
     fwriteint16_t(i,                    ofile); /* machine type */
     fwriteint16_t(coff_nsects,               ofile); /* number of sections */
-
-    /*
-     * When running tests we'are comparing binary output
-     * so time should be zapped.
-     */
-    if (nasm_test_run())
-        fwriteint32_t(0, ofile); /* time stamp */
-    else
-        fwriteint32_t(time(NULL), ofile); /* time stamp */
-
+    fwriteint32_t(posix_timestamp(), ofile); /* timestamp */
     fwriteint32_t(sympos,               ofile);
     fwriteint32_t(coff_nsyms + initsym,      ofile);
     fwriteint16_t(0,                    ofile); /* no optional header */
diff --git a/travis/nasm-t.py b/travis/nasm-t.py
index 02b145db..2470ad45 100755
--- a/travis/nasm-t.py
+++ b/travis/nasm-t.py
@@ -340,7 +340,7 @@ def exec_nasm(desc):
     opts = [args.nasm] + prepare_run_opts(desc)
 
     nasm_env = os.environ.copy()
-    nasm_env['NASM_TEST_RUN'] = 'y'
+    nasm_env['NASMENV'] = '--reproducible'
 
     desc_env = desc.get('environ')
     if desc_env:
diff --git a/travis/test/alonesym-obj.obj.t b/travis/test/alonesym-obj.obj.t
index 99ec34c4..aa25a5c9 100644
Binary files a/travis/test/alonesym-obj.obj.t and b/travis/test/alonesym-obj.obj.t differ
diff --git a/travis/test/br3392643.obj.t b/travis/test/br3392643.obj.t
index de1dafbb..28fbb387 100644
Binary files a/travis/test/br3392643.obj.t and b/travis/test/br3392643.obj.t differ
diff --git a/travis/test/elif.o.t b/travis/test/elif.o.t
index 60336dcd..89787192 100644
Binary files a/travis/test/elif.o.t and b/travis/test/elif.o.t differ
diff --git a/travis/test/obj.o.t b/travis/test/obj.o.t
index a91f3ad1..b3607882 100644
Binary files a/travis/test/obj.o.t and b/travis/test/obj.o.t differ


More information about the Nasm-commits mailing list