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@gmail.com>
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel) 2020-08-27 13:01:57 -07:00
parent 7497737aa2
commit bf79786e89
12 changed files with 48 additions and 42 deletions

View File

@ -938,7 +938,8 @@ enum text_options {
OPT_LIMIT, OPT_LIMIT,
OPT_KEEP_ALL, OPT_KEEP_ALL,
OPT_NO_LINE, OPT_NO_LINE,
OPT_DEBUG OPT_DEBUG,
OPT_REPRODUCIBLE
}; };
enum need_arg { enum need_arg {
ARG_NO, ARG_NO,
@ -970,6 +971,7 @@ static const struct textargs textopts[] = {
{"keep-all", OPT_KEEP_ALL, ARG_NO, 0}, {"keep-all", OPT_KEEP_ALL, ARG_NO, 0},
{"no-line", OPT_NO_LINE, ARG_NO, 0}, {"no-line", OPT_NO_LINE, ARG_NO, 0},
{"debug", OPT_DEBUG, ARG_MAYBE, 0}, {"debug", OPT_DEBUG, ARG_MAYBE, 0},
{"reproducible", OPT_REPRODUCIBLE, ARG_NO, 0},
{NULL, OPT_BOGUS, 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: case OPT_DEBUG:
debug_nasm = param ? strtoul(param, NULL, 10) : debug_nasm+1; debug_nasm = param ? strtoul(param, NULL, 10) : debug_nasm+1;
break; break;
case OPT_REPRODUCIBLE:
reproducible = true;
break;
case OPT_HELP: case OPT_HELP:
help(stdout); help(stdout);
exit(0); exit(0);
@ -2293,6 +2298,8 @@ static void help(FILE *out)
" --lprefix str prepend the given string to local symbols\n" " --lprefix str prepend the given string to local symbols\n"
" --lpostfix str append the given string to local symbols\n" " --lpostfix str append the given string to local symbols\n"
"\n" "\n"
" --reproducible attempt to produce run-to-run identical output\n"
"\n"
" -w+x enable warning x (also -Wx)\n" " -w+x enable warning x (also -Wx)\n"
" -w-x disable warning x (also -Wno-x)\n" " -w-x disable warning x (also -Wno-x)\n"
" -w[+-]error promote all warnings to errors (also -Werror)\n" " -w[+-]error promote all warnings to errors (also -Werror)\n"

View File

@ -12,6 +12,9 @@ since 2007.
\b Correct \c{%ifid $} and \c{%ifid $$} being treated as true. See \b Correct \c{%ifid $} and \c{%ifid $$} being treated as true. See
\k{iftyp}. \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 \S{cl-2.15.04} Version 2.15.04
\b More sensible handling of the case where one single-line macro \b More sensible handling of the case where one single-line macro

View File

@ -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 are ignored. This can be useful for debugging already preprocessed
code. See \k{line}. 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 \S{nasmenv} The \i\c{NASMENV} \i{Environment} Variable

View File

@ -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 * See the file AUTHORS included with the NASM distribution for
* the specific copyright holders. * the specific copyright holders.
* *
@ -67,6 +67,13 @@ struct compile_time {
}; };
extern struct compile_time official_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 NO_SEG INT32_C(-1) /* null segment value */
#define SEG_ABS 0x40000000L /* mask for far-absolute segments */ #define SEG_ABS 0x40000000L /* mask for far-absolute segments */

View File

@ -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 * See the file AUTHORS included with the NASM distribution for
* the specific copyright holders. * the specific copyright holders.
* *
@ -44,12 +44,12 @@ extern const char nasm_version[];
extern const char nasm_date[]; extern const char nasm_date[];
extern const char nasm_compile_options[]; extern const char nasm_compile_options[];
extern bool reproducible;
extern const char *nasm_comment(void); extern const char *nasm_comment(void);
extern size_t nasm_comment_len(void); extern size_t nasm_comment_len(void);
extern const char *nasm_signature(void); extern const char *nasm_signature(void);
extern size_t nasm_signature_len(void); extern size_t nasm_signature_len(void);
extern int nasm_test_run(void);
#endif /* NASM_VER_H */ #endif /* NASM_VER_H */

View File

@ -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 * See the file AUTHORS included with the NASM distribution for
* the specific copyright holders. * the specific copyright holders.
* *
@ -43,46 +43,38 @@ const char nasm_compile_options[] = ""
#endif #endif
; ;
/* These are used by some backends. */ bool reproducible; /* Reproducible output */
static const char __nasm_comment[] =
"The Netwide Assembler " NASM_VER;
static const char __nasm_signature[] = /* These are used by some backends. For a reproducible build,
"NASM " NASM_VER; * these cannot contain version numbers.
*/
/* These are constant so we could pass regression tests */ static const char * const _nasm_comment[2] =
static const char __nasm_comment_const[] ="The Netwide Assembler CONST";
static const char __nasm_signature_const[] = "NASM CONST";
int nasm_test_run(void)
{ {
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) const char *nasm_comment(void)
{ {
if (!nasm_test_run()) return _nasm_comment[reproducible];
return __nasm_comment;
return __nasm_comment_const;
} }
size_t nasm_comment_len(void) size_t nasm_comment_len(void)
{ {
if (!nasm_test_run()) return strlen(nasm_comment());
return strlen(__nasm_comment);
return strlen(__nasm_comment_const);
} }
const char *nasm_signature(void) const char *nasm_signature(void)
{ {
if (!nasm_test_run()) return _nasm_signature[reproducible];
return __nasm_signature;
return __nasm_signature_const;
} }
size_t nasm_signature_len(void) size_t nasm_signature_len(void)
{ {
if (!nasm_test_run()) return strlen(nasm_signature());
return strlen(__nasm_signature);
return strlen(__nasm_signature_const);
} }

View File

@ -936,16 +936,7 @@ static void coff_write(void)
i = IMAGE_FILE_MACHINE_I386; i = IMAGE_FILE_MACHINE_I386;
fwriteint16_t(i, ofile); /* machine type */ fwriteint16_t(i, ofile); /* machine type */
fwriteint16_t(coff_nsects, ofile); /* number of sections */ fwriteint16_t(coff_nsects, ofile); /* number of sections */
fwriteint32_t(posix_timestamp(), ofile); /* timestamp */
/*
* 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(sympos, ofile); fwriteint32_t(sympos, ofile);
fwriteint32_t(coff_nsyms + initsym, ofile); fwriteint32_t(coff_nsyms + initsym, ofile);
fwriteint16_t(0, ofile); /* no optional header */ fwriteint16_t(0, ofile); /* no optional header */

View File

@ -340,7 +340,7 @@ def exec_nasm(desc):
opts = [args.nasm] + prepare_run_opts(desc) opts = [args.nasm] + prepare_run_opts(desc)
nasm_env = os.environ.copy() nasm_env = os.environ.copy()
nasm_env['NASM_TEST_RUN'] = 'y' nasm_env['NASMENV'] = '--reproducible'
desc_env = desc.get('environ') desc_env = desc.get('environ')
if desc_env: if desc_env:

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.