From 79561027a08c3d673152775524cf713c80a82323 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 15 Jun 2018 17:51:39 -0700 Subject: [PATCH 01/83] Make limits 64 bits, add globallines limit to configurable limits Make all limit counters 64 bits, in case someone really has a usage for an insanely large program. The globallines limit was omitted, add it to the list of configurable limits. Signed-off-by: H. Peter Anvin --- asm/eval.c | 2 +- asm/nasm.c | 32 +++++++++++++++++--------------- asm/preproc.c | 4 ++-- include/nasm.h | 9 +++++---- output/outdbg.c | 3 ++- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/asm/eval.c b/asm/eval.c index 582f9503..1a6680f2 100644 --- a/asm/eval.c +++ b/asm/eval.c @@ -72,7 +72,7 @@ static void *scpriv; static int *opflags; static struct eval_hints *hint; -static int deadman; +static int64_t deadman; /* diff --git a/asm/nasm.c b/asm/nasm.c index 94bbc6b2..6299831f 100644 --- a/asm/nasm.c +++ b/asm/nasm.c @@ -94,7 +94,8 @@ static bool abort_on_panic = ABORT_ON_PANIC; static bool keep_all; bool tasm_compatible_mode = false; -int pass0, passn; +int pass0; +int64_t passn; static int pass1, pass2; /* XXX: Get rid of these, they are redundant */ int globalrel = 0; int globalbnd = 0; @@ -106,8 +107,7 @@ const char *outname; static const char *listname; static const char *errname; -static int globallineno; /* for forward-reference tracking */ -#define GLOBALLINENO_MAX INT32_MAX +static int64_t globallineno; /* for forward-reference tracking */ /* static int pass = 0; */ const struct ofmt *ofmt = &OF_DEFAULT; @@ -159,10 +159,10 @@ static char *(*quote_for_make)(const char *) = quote_for_pmake; * Execution limits that can be set via a command-line option or %pragma */ -#define LIMIT_MAX_VAL (INT_MAX >> 1) /* Effectively unlimited */ +#define LIMIT_MAX_VAL (INT64_MAX >> 1) /* Effectively unlimited */ -int nasm_limit[LIMIT_MAX+1] = -{ LIMIT_MAX_VAL, 1000, 1000000, 1000000, 1000000 }; +int64_t nasm_limit[LIMIT_MAX+1] = +{ LIMIT_MAX_VAL, 1000, 1000000, 1000000, 1000000, 2000000000 }; struct limit_info { const char *name; @@ -173,7 +173,8 @@ static const struct limit_info limit_info[LIMIT_MAX+1] = { { "stalled-passes", "number of passes without forward progress" }, { "macro-levels", "levels of macro expansion"}, { "rep", "%rep count" }, - { "eval", "expression evaluation descent"} + { "eval", "expression evaluation descent"}, + { "lines", "total source lines processed"} }; enum directive_result @@ -1378,7 +1379,7 @@ static void assemble_file(const char *fname, StrList **depend_ptr) insn output_ins; int i; uint64_t prev_offset_changed; - int stall_count = 0; /* Make sure we make forward progress... */ + int64_t stall_count = 0; /* Make sure we make forward progress... */ switch (cmd_sb) { case 16: @@ -1432,10 +1433,10 @@ static void assemble_file(const char *fname, StrList **depend_ptr) globallineno = 0; while ((line = preproc->getline())) { - if (globallineno++ == GLOBALLINENO_MAX) - nasm_error(ERR_FATAL, - "overall line number reaches the maximum %d\n", - GLOBALLINENO_MAX); + if (++globallineno > nasm_limit[LIMIT_LINES]) + nasm_fatal(0, + "overall line count exceeds the maximum %"PRId64"\n", + nasm_limit[LIMIT_LINES]); /* * Here we parse our directives; this is not handled by the @@ -1639,7 +1640,7 @@ static void assemble_file(const char *fname, StrList **depend_ptr) */ nasm_error(ERR_NONFATAL, "Can't find valid values for all labels " - "after %d passes, giving up.", passn); + "after %"PRId64" passes, giving up.", passn); nasm_error(ERR_NONFATAL, "Possible causes: recursive EQUs, macro abuse."); break; @@ -1650,7 +1651,8 @@ static void assemble_file(const char *fname, StrList **depend_ptr) lfmt->cleanup(); if (!terminate_after_phase && opt_verbose_info) { /* -On and -Ov switches */ - fprintf(stdout, "info: assembly required 1+%d+1 passes\n", passn-3); + fprintf(stdout, "info: assembly required 1+%"PRId64"+1 passes\n", + passn-3); } } @@ -1955,7 +1957,7 @@ static void help(const char xopt) printf(" %-15s %s (default ", limit_info[i].name, limit_info[i].help); if (nasm_limit[i] < LIMIT_MAX_VAL) { - printf("%d)\n", nasm_limit[i]); + printf("%"PRId64")\n", nasm_limit[i]); } else { printf("unlimited)\n"); } diff --git a/asm/preproc.c b/asm/preproc.c index 88bc6971..8e1e6369 100644 --- a/asm/preproc.c +++ b/asm/preproc.c @@ -3044,7 +3044,7 @@ issue_error: count = reloc_value(evalresult); if (count > nasm_limit[LIMIT_REP]) { nasm_error(ERR_NONFATAL, - "`%%rep' count %"PRId64" exceeds limit (currently %d)", + "`%%rep' count %"PRId64" exceeds limit (currently %"PRId64")", count, nasm_limit[LIMIT_REP]); count = 0; } else if (count < 0) { @@ -4195,7 +4195,7 @@ static Token *expand_smacro(Token * tline) Token *org_tline = tline; Context *ctx; const char *mname; - int deadman = nasm_limit[LIMIT_MACROS]; + int64_t deadman = nasm_limit[LIMIT_MACROS]; bool expanded; /* diff --git a/include/nasm.h b/include/nasm.h index a801da46..164ae0e7 100644 --- a/include/nasm.h +++ b/include/nasm.h @@ -768,10 +768,11 @@ enum nasm_limit { LIMIT_STALLED, LIMIT_MACROS, LIMIT_REP, - LIMIT_EVAL + LIMIT_EVAL, + LIMIT_LINES }; -#define LIMIT_MAX LIMIT_EVAL -extern int nasm_limit[LIMIT_MAX+1]; +#define LIMIT_MAX LIMIT_LINES +extern int64_t nasm_limit[LIMIT_MAX+1]; extern enum directive_result nasm_set_limit(const char *, const char *); /* @@ -1250,7 +1251,7 @@ enum decorator_tokens { */ extern int pass0; -extern int passn; /* Actual pass number */ +extern int64_t passn; /* Actual pass number */ extern bool tasm_compatible_mode; extern int optimizing; diff --git a/output/outdbg.c b/output/outdbg.c index 84cccf73..a28e85f7 100644 --- a/output/outdbg.c +++ b/output/outdbg.c @@ -75,7 +75,8 @@ static void dbg_init(void) static void dbg_reset(void) { - fprintf(ofile, "*** pass reset: pass0 = %d, passn = %d\n", pass0, passn); + fprintf(ofile, "*** pass reset: pass0 = %d, passn = %"PRId64"\n", + pass0, passn); } static void dbg_cleanup(void) From 854730bf62d4bad0431f7d175b1e5e73e0cb48d2 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sat, 16 Jun 2018 00:13:58 -0700 Subject: [PATCH 02/83] insns.dat: update with instructions from ISE 319433-034 Add instructions from the Intel Instruction Set Extensions and Future Features Programming Reference, document 319433-034, May 2018. Signed-off-by: H. Peter Anvin --- x86/insns-iflags.ph | 9 ++- x86/insns.dat | 132 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 138 insertions(+), 3 deletions(-) diff --git a/x86/insns-iflags.ph b/x86/insns-iflags.ph index 43bf70e8..7258d3c2 100644 --- a/x86/insns-iflags.ph +++ b/x86/insns-iflags.ph @@ -1,7 +1,7 @@ #!/usr/bin/perl ## -------------------------------------------------------------------------- ## -## Copyright 1996-2016 The NASM Authors - All Rights Reserved +## Copyright 1996-2018 The NASM Authors - All Rights Reserved ## See the file AUTHORS included with the NASM distribution for ## the specific copyright holders. ## @@ -142,7 +142,12 @@ my %insns_flag_bit = ( "AVX512VBMI" => [$f++, "AVX-512 VBMI instructions"], "AES" => [$f++, "AES instructions"], "VAES" => [$f++, "AES AVX instructions"], - "VPCLMULQDQ" => [$f++, "Carry-Less Multiplication extention"], + "VPCLMULQDQ" => [$f++, "AVX Carryless Multiplication"], + "GFNI" => [$f++, "Galois Field instructions"], + "AVX512VBMI2" => [$f++, "AVX-512 VBMI2 instructions"], + "AVX512VNNI" => [$f++, "AVX-512 VNNI instructions"], + "AVX512BITALG" => [$f++, "AVX-512 Bit Algorithm instructions"], + "AVX512VPOPCNTDQ" => [$f++, "AVX-512 VPOPCNTD/VPOPCNTQ"], # Put these last "OBSOLETE" => [$f++, "Instruction removed from architecture"], diff --git a/x86/insns.dat b/x86/insns.dat index 47367bf7..cabd9bd6 100644 --- a/x86/insns.dat +++ b/x86/insns.dat @@ -2093,7 +2093,6 @@ VAESENCLAST zmmreg,zmmreg*,zmmrm512 [rvm:fv: evex.nds.512.66.0f38.wig dd /r] AV VAESDEC zmmreg,zmmreg*,zmmrm512 [rvm:fv: evex.nds.512.66.0f38.wig de /r] AVX512,VAES,FUTURE VAESDECLAST zmmreg,zmmreg*,zmmrm512 [rvm:fv: evex.nds.512.66.0f38.wig df /r] AVX512,VAES,FUTURE - ;# Intel AVX instructions VADDPD xmmreg,xmmreg*,xmmrm128 [rvm: vex.nds.128.66.0f 58 /r] AVX,SANDYBRIDGE VADDPD ymmreg,ymmreg*,ymmrm256 [rvm: vex.nds.256.66.0f 58 /r] AVX,SANDYBRIDGE @@ -5198,6 +5197,137 @@ PCOMMIT void [ 66 0f ae f8] ; AMD Zen v1 CLZERO void [ 0f 01 fc] FUTURE,AMD +;# Instructions from the Intel Instruction Set Extensions, +;# doc 319433-034 May 2018 +CLDEMOTE mem [m: np 0f 1c /0] FUTURE +MOVDIRI mem32,reg32 [mr: np 0f 38 f9 /r] FUTURE,SD +MOVDIRI mem64,reg64 [mr: o64 0f 38 f9 /r] FUTURE,X64,SQ +MOVDIR64B reg16,mem512 [rm: a16 66 0f 38 f8 /r] FUTURE,NOLONG +MOVDIR64B reg32,mem512 [rm: a32 66 0f 38 f8 /r] FUTURE +MOVDIR64B reg64,mem512 [rm: a64 66 0f 38 f8 /r] FUTURE,X64 +PCONFIG void [ np 0f 01 c5] FUTURE +TPAUSE reg32 [m: 66 0f ae /6] FUTURE +TPAUSE reg32,reg_edx,reg_eax [m--: 66 0f ae /6] FUTURE,ND +UMONITOR reg16 [m: a16 f3 0f ae /6] FUTURE,NOLONG +UMONITOR reg32 [m: a32 f3 0f ae /6] FUTURE +UMONITOR reg64 [m: a64 f3 0f ae /6] FUTURE,X64 +UMWAIT reg32 [m: f2 0f ae /6] FUTURE +UMWAIT reg32,reg_edx,reg_eax [m--: f2 0f ae /6] FUTURE,ND +WBNOINVD void [ f3 0f 09] FUTURE + +;# Galois field operations (GFNI) +GF2P8AFFINEINVQB xmmreg,xmmrm128,imm8 [rmi: 66 0f 3a cf /r ib] GFNI,SSE,FUTURE +VGF2P8AFFINEINVQB xmmreg,xmmreg*,xmmrm128,imm8 [rvmi: vex.nds.128.66.0f3a.w1 cf /r ib] GFNI,AVX,FUTURE +VGF2P8AFFINEINVQB ymmreg,ymmreg*,ymmrm256,imm8 [rvmi: vex.nds.256.66.0f3a.w1 cf /r ib] GFNI,AVX,FUTURE +VGF2P8AFFINEINVQB xmmreg|mask|z,xmmreg*,xmmrm128|b64,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w1 cf /r ib] GFNI,AVX512VL,FUTURE +VGF2P8AFFINEINVQB ymmreg|mask|z,ymmreg*,ymmrm256|b64,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w1 cf /r ib] GFNI,AVX512VL,FUTURE +VGF2P8AFFINEINVQB zmmreg|mask|z,zmmreg*,zmmrm512|b64,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w1 cf /r ib] GFNI,AVX512,FUTURE +GF2P8AFFINEQB xmmreg,xmmrm128,imm8 [rmi: 66 0f 3a ce /r ib] GFNI,SSE,FUTURE +VGF2P8AFFINEQB xmmreg,xmmreg*,xmmrm128,imm8 [rvmi: vex.nds.128.66.0f3a.w1 ce /r ib] GFNI,AVX,FUTURE +VGF2P8AFFINEQB ymmreg,ymmreg*,ymmrm256,imm8 [rvmi: vex.nds.256.66.0f3a.w1 ce /r ib] GFNI,AVX,FUTURE +VGF2P8AFFINEQB xmmreg|mask|z,xmmreg*,xmmrm128|b64,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w1 ce /r ib] GFNI,AVX512VL,FUTURE +VGF2P8AFFINEQB ymmreg|mask|z,ymmreg*,ymmrm256|b64,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w1 ce /r ib] GFNI,AVX512VL,FUTURE +VGF2P8AFFINEQB zmmreg|mask|z,zmmreg*,zmmrm512|b64,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w1 ce /r ib] GFNI,AVX512,FUTURE +GF2P8MULB xmmreg,xmmrm128 [rm: 66 0f 38 cf /r] GFNI,SSE,FUTURE +VGF2P8MULB xmmreg,xmmreg*,xmmrm128 [rvm: vex.nds.128.66.0f38.w0 cf /r] GFNI,AVX,FUTURE +VGF2P8MULB ymmreg,ymmreg*,ymmrm256 [rvm: vex.nds.256.66.0f38.w0 cf /r] GFNI,AVX,FUTURE +VGF2P8MULB xmmreg|mask|z,xmmreg*,xmmrm128 [rvm:fvm: evex.nds.128.66.0f38.w0 cf /r] GFNI,AVX512VL,FUTURE +VGF2P8MULB ymmreg|mask|z,ymmreg*,ymmrm256 [rvm:fvm: evex.nds.256.66.0f38.w0 cf /r] GFNI,AVX512VL,FUTURE +VGF2P8MULB zmmreg|mask|z,zmmreg*,zmmrm512 [rvm:fvm: evex.nds.512.66.0f38.w0 cf /r] GFNI,AVX512,FUTURE + +;# AVX512 Vector Bit Manipulation Instructions 2 +VPCOMPRESSB mem128|mask,xmmreg [mr:t1s: evex.128.66.0f38.w0 63 /r] AVX512VBMI2,AVX512VL,FUTURE +VPCOMPRESSB mem256|mask,ymmreg [mr:t1s: evex.256.66.0f38.w0 63 /r] AVX512VBMI2,AVX512VL,FUTURE +VPCOMPRESSB mem512|mask,zmmreg [mr:t1s: evex.512.66.0f38.w0 63 /r] AVX512VBMI2,FUTURE +VPCOMPRESSB xmmreg|mask|z,xmmreg [mr: evex.128.66.0f38.w0 63 /r] AVX512VBMI2,AVX512VL,FUTURE +VPCOMPRESSB ymmreg|mask|z,ymmreg [mr: evex.256.66.0f38.w0 63 /r] AVX512VBMI2,AVX512VL,FUTURE +VPCOMPRESSB zmmreg|mask|z,zmmreg [mr: evex.512.66.0f38.w0 63 /r] AVX512VBMI2,FUTURE +VPCOMPRESSW mem128|mask,xmmreg [mr:t1s: evex.128.66.0f38.w1 63 /r] AVX512VBMI2,AVX512VL,FUTURE +VPCOMPRESSW mem256|mask,ymmreg [mr:t1s: evex.256.66.0f38.w1 63 /r] AVX512VBMI2,AVX512VL,FUTURE +VPCOMPRESSW mem512|mask,zmmreg [mr:t1s: evex.512.66.0f38.w1 63 /r] AVX512VBMI2,FUTURE +VPCOMPRESSW xmmreg|mask|z,xmmreg [mr: evex.128.66.0f38.w1 63 /r] AVX512VBMI2,AVX512VL,FUTURE +VPCOMPRESSW ymmreg|mask|z,ymmreg [mr: evex.256.66.0f38.w1 63 /r] AVX512VBMI2,AVX512VL,FUTURE +VPCOMPRESSW zmmreg|mask|z,zmmreg [mr: evex.512.66.0f38.w1 63 /r] AVX512VBMI2,FUTURE +VPEXPANDB mem128|mask,xmmreg [mr:t1s: evex.128.66.0f38.w0 62 /r] AVX512VBMI2,AVX512VL,FUTURE +VPEXPANDB mem256|mask,ymmreg [mr:t1s: evex.256.66.0f38.w0 62 /r] AVX512VBMI2,AVX512VL,FUTURE +VPEXPANDB mem512|mask,zmmreg [mr:t1s: evex.512.66.0f38.w0 62 /r] AVX512VBMI2,FUTURE +VPEXPANDB xmmreg|mask|z,xmmreg [mr: evex.128.66.0f38.w0 62 /r] AVX512VBMI2,AVX512VL,FUTURE +VPEXPANDB ymmreg|mask|z,ymmreg [mr: evex.256.66.0f38.w0 62 /r] AVX512VBMI2,AVX512VL,FUTURE +VPEXPANDB zmmreg|mask|z,zmmreg [mr: evex.512.66.0f38.w0 62 /r] AVX512VBMI2,FUTURE +VPEXPANDW mem128|mask,xmmreg [mr:t1s: evex.128.66.0f38.w1 62 /r] AVX512VBMI2,AVX512VL,FUTURE +VPEXPANDW mem256|mask,ymmreg [mr:t1s: evex.256.66.0f38.w1 62 /r] AVX512VBMI2,AVX512VL,FUTURE +VPEXPANDW mem512|mask,zmmreg [mr:t1s: evex.512.66.0f38.w1 62 /r] AVX512VBMI2,FUTURE +VPEXPANDW xmmreg|mask|z,xmmreg [mr: evex.128.66.0f38.w1 62 /r] AVX512VBMI2,AVX512VL,FUTURE +VPEXPANDW ymmreg|mask|z,ymmreg [mr: evex.256.66.0f38.w1 62 /r] AVX512VBMI2,AVX512VL,FUTURE +VPEXPANDW zmmreg|mask|z,zmmreg [mr: evex.512.66.0f38.w1 62 /r] AVX512VBMI2,FUTURE +VPSHLDW xmmreg|mask|z,xmmreg*,xmmrm128,imm8 [rvmi:fvm: evex.nds.128.66.0f3a.w1 70 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHLDW ymmreg|mask|z,ymmreg*,ymmrm256,imm8 [rvmi:fvm: evex.nds.256.66.0f3a.w1 70 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHLDW zmmreg|mask|z,zmmreg*,zmmrm512,imm8 [rvmi:fvm: evex.nds.512.66.0f3a.w1 70 /r ib] AVX512VBMI2,FUTURE +VPSHLDD xmmreg|mask|z,xmmreg*,xmmrm128|b32,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w0 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHLDD ymmreg|mask|z,ymmreg*,ymmrm256|b32,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w0 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHLDD zmmreg|mask|z,zmmreg*,zmmrm512|b32,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w0 71 /r ib] AVX512VBMI2,FUTURE +VPSHLDQ xmmreg|mask|z,xmmreg*,xmmrm128|b64,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w1 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHLDQ ymmreg|mask|z,ymmreg*,ymmrm256|b64,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w1 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHLDQ zmmreg|mask|z,zmmreg*,zmmrm512|b64,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w1 71 /r ib] AVX512VBMI2,FUTURE +VPSHLDVW xmmreg|mask|z,xmmreg*,xmmrm128 [rvmi:fvm: evex.dds.128.66.0f38.w1 70 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHLDVW ymmreg|mask|z,ymmreg*,ymmrm256 [rvmi:fvm: evex.dds.256.66.0f38.w1 70 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHLDVW zmmreg|mask|z,zmmreg*,zmmrm512 [rvmi:fvm: evex.dds.512.66.0f38.w1 70 /r ib] AVX512VBMI2,FUTURE +VPSHLDVD xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvmi:fv: evex.dds.128.66.0f38.w0 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHLDVD ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvmi:fv: evex.dds.256.66.0f38.w0 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHLDVD zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvmi:fv: evex.dds.512.66.0f38.w0 71 /r ib] AVX512VBMI2,FUTURE +VPSHLDVQ xmmreg|mask|z,xmmreg*,xmmrm128|b64 [rvmi:fv: evex.dds.128.66.0f38.w1 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHLDVQ ymmreg|mask|z,ymmreg*,ymmrm256|b64 [rvmi:fv: evex.dds.256.66.0f38.w1 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHLDVQ zmmreg|mask|z,zmmreg*,zmmrm512|b64 [rvmi:fv: evex.dds.512.66.0f38.w1 71 /r ib] AVX512VBMI2,FUTURE +VPSHRDW xmmreg|mask|z,xmmreg*,xmmrm128,imm8 [rvmi:fvm: evex.nds.128.66.0f3a.w1 72 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHRDW ymmreg|mask|z,ymmreg*,ymmrm256,imm8 [rvmi:fvm: evex.nds.256.66.0f3a.w1 72 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHRDW zmmreg|mask|z,zmmreg*,zmmrm512,imm8 [rvmi:fvm: evex.nds.512.66.0f3a.w1 72 /r ib] AVX512VBMI2,FUTURE +VPSHRDD xmmreg|mask|z,xmmreg*,xmmrm128|b32,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w0 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHRDD ymmreg|mask|z,ymmreg*,ymmrm256|b32,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w0 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHRDD zmmreg|mask|z,zmmreg*,zmmrm512|b32,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w0 73 /r ib] AVX512VBMI2,FUTURE +VPSHRDQ xmmreg|mask|z,xmmreg*,xmmrm128|b64,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w1 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHRDQ ymmreg|mask|z,ymmreg*,ymmrm256|b64,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w1 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHRDQ zmmreg|mask|z,zmmreg*,zmmrm512|b64,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w1 73 /r ib] AVX512VBMI2,FUTURE +VPSHRDVW xmmreg|mask|z,xmmreg*,xmmrm128 [rvmi:fvm: evex.dds.128.66.0f38.w1 72 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHRDVW ymmreg|mask|z,ymmreg*,ymmrm256 [rvmi:fvm: evex.dds.256.66.0f38.w1 72 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHRDVW zmmreg|mask|z,zmmreg*,zmmrm512 [rvmi:fvm: evex.dds.512.66.0f38.w1 72 /r ib] AVX512VBMI2,FUTURE +VPSHRDVD xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvmi:fv: evex.dds.128.66.0f38.w0 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHRDVD ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvmi:fv: evex.dds.256.66.0f38.w0 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHRDVD zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvmi:fv: evex.dds.512.66.0f38.w0 73 /r ib] AVX512VBMI2,FUTURE +VPSHRDVQ xmmreg|mask|z,xmmreg*,xmmrm128|b64 [rvmi:fv: evex.dds.128.66.0f38.w1 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHRDVQ ymmreg|mask|z,ymmreg*,ymmrm256|b64 [rvmi:fv: evex.dds.256.66.0f38.w1 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE +VPSHRDVQ zmmreg|mask|z,zmmreg*,zmmrm512|b64 [rvmi:fv: evex.dds.512.66.0f38.w1 73 /r ib] AVX512VBMI2,FUTURE + +;# AVX512 VNNI +VPDPBUSD xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvm:fv: evex.dds.128.66.0f38.w0 50 /r] AVX512VNNI,AVX512VL,FUTURE +VPDPBUSD ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvm:fv: evex.dds.256.66.0f38.w0 50 /r] AVX512VNNI,AVX512VL,FUTURE +VPDPBUSD zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvm:fv: evex.dds.512.66.0f38.w0 50 /r] AVX512VNNI,FUTURE +VPDPBUSDS xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvm:fv: evex.dds.128.66.0f38.w0 51 /r] AVX512VNNI,AVX512VL,FUTURE +VPDPBUSDS ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvm:fv: evex.dds.256.66.0f38.w0 51 /r] AVX512VNNI,AVX512VL,FUTURE +VPDPBUSDS zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvm:fv: evex.dds.512.66.0f38.w0 51 /r] AVX512VNNI,FUTURE +VPDPWSSD xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvm:fv: evex.dds.128.66.0f38.w0 52 /r] AVX512VNNI,AVX512VL,FUTURE +VPDPWSSD ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvm:fv: evex.dds.256.66.0f38.w0 52 /r] AVX512VNNI,AVX512VL,FUTURE +VPDPWSSD zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvm:fv: evex.dds.512.66.0f38.w0 52 /r] AVX512VNNI,FUTURE +VPDPWSSDS xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvm:fv: evex.dds.128.66.0f38.w0 53 /r] AVX512VNNI,AVX512VL,FUTURE +VPDPWSSDS ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvm:fv: evex.dds.256.66.0f38.w0 53 /r] AVX512VNNI,AVX512VL,FUTURE +VPDPWSSDS zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvm:fv: evex.dds.512.66.0f38.w0 53 /r] AVX512VNNI,FUTURE + +;# AVX512 Bit Algorithms +VPOPCNTB xmmreg|mask|z,xmmrm128 [rm:fvm: evex.128.66.0f38.w0 54 /r] AVX512BITALG,AVX512VL,FUTURE +VPOPCNTB ymmreg|mask|z,ymmrm256 [rm:fvm: evex.256.66.0f38.w0 54 /r] AVX512BITALG,AVX512VL,FUTURE +VPOPCNTB zmmreg|mask|z,zmmrm512 [rm:fvm: evex.512.66.0f38.w0 54 /r] AVX512BITALG,FUTURE +VPOPCNTW xmmreg|mask|z,xmmrm128 [rm:fvm: evex.128.66.0f38.w1 54 /r] AVX512BITALG,AVX512VL,FUTURE +VPOPCNTW ymmreg|mask|z,ymmrm256 [rm:fvm: evex.256.66.0f38.w1 54 /r] AVX512BITALG,AVX512VL,FUTURE +VPOPCNTW zmmreg|mask|z,zmmrm512 [rm:fvm: evex.512.66.0f38.w1 54 /r] AVX512BITALG,FUTURE +VPOPCNTD xmmreg|mask|z,xmmrm128 [rm:fv: evex.128.66.0f38.w0 55 /r] AVX512VPOPCNTDQ,AVX512VL,FUTURE +VPOPCNTD ymmreg|mask|z,ymmrm256 [rm:fv: evex.256.66.0f38.w0 55 /r] AVX512VPOPCNTDQ,AVX512VL,FUTURE +VPOPCNTD zmmreg|mask|z,zmmrm512 [rm:fv: evex.512.66.0f38.w0 55 /r] AVX512VPOPCNTDQ,FUTURE +VPOPCNTQ xmmreg|mask|z,xmmrm128 [rm:fv: evex.128.66.0f38.w1 55 /r] AVX512VPOPCNTDQ,AVX512VL,FUTURE +VPOPCNTQ ymmreg|mask|z,ymmrm256 [rm:fv: evex.256.66.0f38.w1 55 /r] AVX512VPOPCNTDQ,AVX512VL,FUTURE +VPOPCNTQ zmmreg|mask|z,zmmrm512 [rm:fv: evex.512.66.0f38.w1 55 /r] AVX512VPOPCNTDQ,FUTURE +VPSHUFBITQMB kreg|mask,xmmreg,xmmrm128 [rvm:fvm: evex.nds.128.66.0f38.w0 8f /r] AVX512BITALG,AVX512VL,FUTURE +VPSHUFBITQMB kreg|mask,ymmreg,ymmrm256 [rvm:fvm: evex.nds.256.66.0f38.w0 8f /r] AVX512BITALG,AVX512VL,FUTURE +VPSHUFBITQMB kreg|mask,zmmreg,zmmrm512 [rvm:fvm: evex.nds.512.66.0f38.w0 8f /r] AVX512BITALG,FUTURE + ;# Systematic names for the hinting nop instructions ; These should be last in the file HINT_NOP0 rm16 [m: o16 0f 18 /0] P6,UNDOC From fee097f724233916bed71d6c0406e3c03f93d01b Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sat, 16 Jun 2018 00:16:12 -0700 Subject: [PATCH 03/83] NASM 2.14rc5 --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index c4a380cc..92402d5a 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.14rc4 +2.14rc5 From 8eb3096f7adcf3de3cdd8f6598cb3ad8003b34b7 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 14 Jun 2018 20:28:57 -0700 Subject: [PATCH 04/83] nasm.h: remove unused constants Remove unused constants for prefix and suffix, long since obsolete. Signed-off-by: H. Peter Anvin --- include/nasm.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/include/nasm.h b/include/nasm.h index 164ae0e7..00cea322 100644 --- a/include/nasm.h +++ b/include/nasm.h @@ -65,14 +65,6 @@ extern struct compile_time official_compile_time; #define NO_SEG INT32_C(-1) /* null segment value */ #define SEG_ABS 0x40000000L /* mask for far-absolute segments */ -#ifndef PREFIX_MAX -#define PREFIX_MAX 10 -#endif - -#ifndef POSTFIX_MAX -#define POSTFIX_MAX 10 -#endif - #define IDLEN_MAX 4096 #define DECOLEN_MAX 32 From 41103ab4310c71836761c205a7424975edb4f2ad Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Jun 2018 11:30:48 -0700 Subject: [PATCH 05/83] test/Makefile: qualify the names of list files with output format It is quite likely we may want to build the same input with multiple output formats; make it so we don't lose the list file. Signed-off-by: H. Peter Anvin --- test/Makefile | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/Makefile b/test/Makefile index ebd8c3f3..7cba37ec 100644 --- a/test/Makefile +++ b/test/Makefile @@ -12,46 +12,46 @@ $(NASM): $(MAKE) -C .. %.bin: %.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f bin -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f bin -o $@ -MD $@.dep -l $@.lst $< %.ith: %.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f ith -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f ith -o $@ -MD $@.dep -l $@.lst $< %.srec: %.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f srec -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f srec -o $@ -MD $@.dep -l $@.lst $< %.o: %.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f elf32 -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f elf32 -o $@ -MD $@.dep -l $@.lst $< %.o64: %.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f elf64 -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f elf64 -o $@ -MD $@.dep -l $@.lst $< %.obj: %.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f obj -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f obj -o $@ -MD $@.dep -l $@.lst $< %.rdf: %.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f rdf -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f rdf -o $@ -MD $@.dep -l $@.lst $< %.od: %.obj ../misc/omfdump ../misc/omfdump $< > $@ %.coff: %.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f coff -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f coff -o $@ -MD $@.dep -l $@.lst $< %.win32: %.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f win32 -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f win32 -o $@ -MD $@.dep -l $@.lst $< %.win64: %.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f win64 -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f win64 -o $@ -MD $@.dep -l $@.lst $< %.mo32: %.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f macho32 -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f macho32 -o $@ -MD $@.dep -l $@.lst $< %.mo64: %.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f macho64 -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f macho64 -o $@ -MD $@.dep -l $@.lst $< %.dbg: %.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f dbg -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f dbg -o $@ -MD $@.dep -l $@.lst $< %.asm: %.pl $(PERL) $< > $@ @@ -83,7 +83,7 @@ spotless: clean # Test for ELF32 shared libraries; assumes an x86 Linux system # elfso.o: elfso.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f elf32 -F stabs -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f elf32 -F stabs -o $@ -MD $@.dep -l $@.lst $< elfso.so: elfso.o $(LD) -m elf_i386 -shared -o $@ -MD $@.dep $< @@ -96,7 +96,7 @@ elftest: elftest.c elfso.so # Test for ELF64 shared libraries; assumes an x86-64 Linux system # elf64so.o: elf64so.asm $(NASMDEP) - $(NASM) $(NASMOPT) -f elf64 -F dwarf -o $@ -MD $@.dep -l $*.lst $< + $(NASM) $(NASMOPT) -f elf64 -F dwarf -o $@ -MD $@.dep -l $@.lst $< elf64so.so: elf64so.o $(LD) -shared -o $@ -MD $@.dep $< From f7be8b3253b90ed590c7dc862c402da5e8ea08c2 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Jun 2018 11:32:17 -0700 Subject: [PATCH 06/83] pragma: define a hander for generic output (and debug) pragmas There are cases where we may want to implement generic pragmas, while still make them selective based on output and/or debug formats. Initially, use this for the prefix/suffix options. Signed-off-by: H. Peter Anvin Cc: Chang Seok Bae --- asm/pragma.c | 30 ++++++++++++++++++++---------- include/nasm.h | 3 ++- test/subsection.asm | 6 +++--- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/asm/pragma.c b/asm/pragma.c index 71861a94..a4e76094 100644 --- a/asm/pragma.c +++ b/asm/pragma.c @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * * - * Copyright 1996-2017 The NASM Authors - All Rights Reserved + * Copyright 1996-2018 The NASM Authors - All Rights Reserved * See the file AUTHORS included with the NASM distribution for * the specific copyright holders. * @@ -49,7 +49,7 @@ #include "assemble.h" #include "error.h" -static enum directive_result asm_pragma(const struct pragma *pragma); +static enum directive_result output_pragma(const struct pragma *pragma); static enum directive_result limit_pragma(const struct pragma *pragma); /* @@ -87,14 +87,14 @@ static enum directive_result limit_pragma(const struct pragma *pragma); */ static struct pragma_facility global_pragmas[] = { - { "asm", asm_pragma }, + { "asm", NULL }, { "limit", limit_pragma }, { "list", NULL }, { "file", NULL }, { "input", NULL }, - /* None of these should actually happen... */ - { "preproc", NULL }, /* This shouldn't happen... */ + /* None of these should actually happen due to special handling */ + { "preproc", NULL }, /* Handled in the preprocessor by necessity */ { "output", NULL }, { "debug", NULL }, { "ignore", NULL }, @@ -110,6 +110,7 @@ static struct pragma_facility global_pragmas[] = */ static bool search_pragma_list(const struct pragma_facility *list, const char *default_name, + pragma_handler generic_handler, struct pragma *pragma) { const struct pragma_facility *pf; @@ -137,6 +138,10 @@ found_it: else rv = DIRR_UNKNOWN; + /* Is there an additional, applicable generic handler? */ + if (rv == DIRR_UNKNOWN && generic_handler) + rv = generic_handler(pragma); + switch (rv) { case DIRR_UNKNOWN: switch (pragma->opcode) { @@ -210,15 +215,16 @@ void process_pragma(char *str) pragma.tail = nasm_trim_spaces(p); /* Look for a global pragma namespace */ - if (search_pragma_list(global_pragmas, NULL, &pragma)) + if (search_pragma_list(global_pragmas, NULL, NULL, &pragma)) return; /* Look to see if it is an output backend pragma */ - if (search_pragma_list(ofmt->pragmas, ofmt->shortname, &pragma)) + if (search_pragma_list(ofmt->pragmas, ofmt->shortname, + output_pragma, &pragma)) return; /* Look to see if it is a debug format pragma */ - if (search_pragma_list(dfmt->pragmas, dfmt->shortname, &pragma)) + if (search_pragma_list(dfmt->pragmas, dfmt->shortname, NULL, &pragma)) return; /* @@ -234,9 +240,10 @@ void process_pragma(char *str) } /* - * Pragmas for the assembler proper + * Generic pragmas that apply to all output backends; these are handled + * specially so they can be made selective based on the output format. */ -static enum directive_result asm_pragma(const struct pragma *pragma) +static enum directive_result output_pragma(const struct pragma *pragma) { switch (pragma->opcode) { case D_PREFIX: @@ -258,6 +265,9 @@ static enum directive_result asm_pragma(const struct pragma *pragma) } } +/* + * %pragma limit to set resource limits + */ static enum directive_result limit_pragma(const struct pragma *pragma) { return nasm_set_limit(pragma->opname, pragma->tail); diff --git a/include/nasm.h b/include/nasm.h index 00cea322..9eae9b8b 100644 --- a/include/nasm.h +++ b/include/nasm.h @@ -727,10 +727,11 @@ enum directive_result { * as part of the struct pragma. */ struct pragma; +typedef enum directive_result (*pragma_handler)(const struct pragma *); struct pragma_facility { const char *name; - enum directive_result (*handler)(const struct pragma *); + pragma_handler handler; }; /* diff --git a/test/subsection.asm b/test/subsection.asm index ce8ed4aa..8ba61978 100644 --- a/test/subsection.asm +++ b/test/subsection.asm @@ -4,9 +4,9 @@ ; Test of Mach-O subsection_by_symbol ; -%pragma output subsections_via_symbols -%pragma asm gprefix _ -%pragma asm lprefix L_ +%pragma macho subsections_via_symbols +%pragma macho gprefix _ +%pragma macho lprefix L. bits 32 From 1bcc1e012aea5435150d8903328703d14bd9efb5 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Jun 2018 11:37:17 -0700 Subject: [PATCH 07/83] test: test for ELF symbol visibility Add test for declaring ELF visibility. Signed-off-by: H. Peter Anvin --- test/elf_visibility.asm | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 test/elf_visibility.asm diff --git a/test/elf_visibility.asm b/test/elf_visibility.asm new file mode 100644 index 00000000..4874b62d --- /dev/null +++ b/test/elf_visibility.asm @@ -0,0 +1,10 @@ +global foo +global foo_hidden:function hidden + +SECTION .text align=16 + +foo: +foo_hidden: +foo_label: +ret + From ef4e5e209fd1ad9e2ffff9112a66bb2b73225d8f Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Jun 2018 11:38:47 -0700 Subject: [PATCH 08/83] .gitignore: add asm/directbl.h asm/directbl.h was missing from .gitignore, making this generated file show up as a file not checked in. Signed-off-by: H. Peter Anvin --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index de8fed98..d55e31f8 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ TAGS /*.1 /Makefile /asm/directbl.c +/asm/directbl.h /asm/directiv.h /asm/pptok.c /asm/pptok.h From 5d8193367e638092f35f5e54128795329f42a746 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Jun 2018 13:50:25 -0700 Subject: [PATCH 09/83] MSVC: fix dependency generation and building RDOFF under MSVC 1. The mkdep.pl program didn't handle excluded dependencies correctly, causing it to error out due to config/config.h not existing. 2. NMAKE is sensitive to the order suffixes appear in .SUFFIXES, causing it to try to use the builtin rule .c.exe instead of .c.obj -> .obj.exe. 3. NMAKE doesn't handle the && operator between commands. 4. The !ifdef jungle around dependency generation was wrong. Signed-off-by: H. Peter Anvin --- Makefile.in | 33 ++++++++++++++++----------------- Mkfiles/msvc.mak | 39 +++++++++++++++++---------------------- tools/mkdep.pl | 16 ++++++++-------- 3 files changed, 41 insertions(+), 47 deletions(-) diff --git a/Makefile.in b/Makefile.in index 9a8e2def..0943f39e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -50,7 +50,7 @@ XMLTO = @XMLTO@ MAKENSIS = makensis -MKDIR = mkdir +MKDIR = mkdir -p RM_F = rm -f RM_RF = rm -rf LN_S = @LN_S@ @@ -277,6 +277,13 @@ asm/directbl.c: asm/directiv.dat nasmlib/perfhash.pl perllib/phash.ph perlreq: $(PERLREQ) +# This rule is only used for RDOFF +.$(O)$(X): + $(CC) $(ALL_CFLAGS) -o $@ $< $(LDFLAGS) $(RDFLIB) $(NASMLIB) $(LIBS) + +RDFLN = cd rdoff && ln -s +RDFLNPFX = + #-- Begin RDOFF Shared Rules --# RDFLIBOBJ = rdoff/rdoff.$(O) rdoff/rdfload.$(O) rdoff/symtab.$(O) \ @@ -291,31 +298,23 @@ RDF2BINLINKS = rdoff/rdf2com$(X) rdoff/rdf2ith$(X) \ RDFLIB = rdoff/librdoff.$(A) RDFLIBS = $(RDFLIB) $(NASMLIB) -# This rule is only used for rdoff, to allow common rules -MAKERDF = $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $< $(RDFLIB) $(NASMLIB) $(LIBS) - rdoff/rdfdump$(X): rdoff/rdfdump.$(O) $(RDFLIBS) - $(MAKERDF) rdoff/ldrdf$(X): rdoff/ldrdf.$(O) $(RDFLIBS) - $(MAKERDF) rdoff/rdx$(X): rdoff/rdx.$(O) $(RDFLIBS) - $(MAKERDF) rdoff/rdflib$(X): rdoff/rdflib.$(O) $(RDFLIBS) - $(MAKERDF) rdoff/rdf2bin$(X): rdoff/rdf2bin.$(O) $(RDFLIBS) - $(MAKERDF) rdoff/rdf2com$(X): rdoff/rdf2bin$(X) $(RM_F) rdoff/rdf2com$(X) - cd rdoff && $(LN_S) rdf2bin$(X) rdf2com$(X) + $(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2com$(X) rdoff/rdf2ith$(X): rdoff/rdf2bin$(X) $(RM_F) rdoff/rdf2ith$(X) - cd rdoff && $(LN_S) rdf2bin$(X) rdf2ith$(X) + $(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2ith$(X) rdoff/rdf2ihx$(X): rdoff/rdf2bin$(X) $(RM_F) rdoff/rdf2ihx$(X) - cd rdoff && $(LN_S) rdf2bin$(X) rdf2ihx$(X) + $(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2ihx$(X) rdoff/rdf2srec$(X): rdoff/rdf2bin$(X) $(RM_F) rdoff/rdf2srec$(X) - cd rdoff && $(LN_S) rdf2bin$(X) rdf2srec$(X) + $(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2srec$(X) #-- End RDOFF Shared Rules --# @@ -345,10 +344,10 @@ nsis: nsis/nasm.nsi nsis/arch.nsh nsis/version.nsh manpages: nasm.1 ndisasm.1 install: nasm$(X) ndisasm$(X) - $(MKDIR) -p $(DESTDIR)$(bindir) + $(MKDIR) $(DESTDIR)$(bindir) $(INSTALL_PROGRAM) nasm$(X) $(DESTDIR)$(bindir)/nasm$(X) $(INSTALL_PROGRAM) ndisasm$(X) $(DESTDIR)$(bindir)/ndisasm$(X) - $(MKDIR) -p $(DESTDIR)$(mandir)/man1 + $(MKDIR) $(DESTDIR)$(mandir)/man1 $(INSTALL_DATA) $(srcdir)/nasm.1 $(DESTDIR)$(mandir)/man1/nasm.1 $(INSTALL_DATA) $(srcdir)/ndisasm.1 $(DESTDIR)$(mandir)/man1/ndisasm.1 @@ -397,7 +396,7 @@ cscope: cscope -b -f cscope.out rdf_install install_rdf install_rdoff: - $(MKDIR) -p $(DESTDIR)$(bindir) + $(MKDIR) $(DESTDIR)$(bindir) for f in $(RDFPROGS); do \ $(INSTALL_PROGRAM) "$$f" '$(DESTDIR)$(bindir)'/ ; \ done @@ -406,7 +405,7 @@ rdf_install install_rdf install_rdoff: bn=`basename "$$f"` && $(RM_F) "$$bn" && \ $(LN_S) rdf2bin$(X) "$$bn" ; \ done - $(MKDIR) -p $(DESTDIR)$(mandir)/man1 + $(MKDIR) $(DESTDIR)$(mandir)/man1 $(INSTALL_DATA) $(srcdir)/rdoff/*.1 $(DESTDIR)$(mandir)/man1/ doc: diff --git a/Mkfiles/msvc.mak b/Mkfiles/msvc.mak index 430fa2d3..9aec80fc 100644 --- a/Mkfiles/msvc.mak +++ b/Mkfiles/msvc.mak @@ -46,7 +46,7 @@ RUNPERL = $(PERL) $(PERLFLAGS) MAKENSIS = makensis -RM_F = del /f +RM_F = -del /f LN_S = copy # Binary suffixes @@ -54,15 +54,11 @@ O = obj A = lib X = .exe .SUFFIXES: -.SUFFIXES: .c .i .s .$(O) .$(A) .exe .1 .man +.SUFFIXES: $(X) .$(A) .$(O) .c .i .s .1 .man .c.obj: $(CC) /c $(ALL_CFLAGS) /Fo$@ $< -# This rule is only used for rdoff -.obj.exe: - $(CC) $(ALL_CFLAGS) /Fe$@ $< $(LDFLAGS) $(RDFLIB) $(NASMLIB) $(LIBS) - #-- Begin File Lists --# # Edit in Makefile.in, not here! NASM = asm\nasm.$(O) @@ -252,6 +248,13 @@ asm\directbl.c: asm\directiv.dat nasmlib\perfhash.pl perllib\phash.ph perlreq: $(PERLREQ) +# This rule is only used for RDOFF +.obj.exe: + $(CC) /Fe$@ $< $(LDFLAGS) $(RDFLIB) $(NASMLIB) $(LIBS) + +RDFLN = copy +RDFLNPFX = rdoff^\ + #-- Begin RDOFF Shared Rules --# # Edit in Makefile.in, not here! @@ -267,31 +270,23 @@ RDF2BINLINKS = rdoff\rdf2com$(X) rdoff\rdf2ith$(X) \ RDFLIB = rdoff\librdoff.$(A) RDFLIBS = $(RDFLIB) $(NASMLIB) -# This rule is only used for rdoff, to allow common rules -MAKERDF = $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $< $(RDFLIB) $(NASMLIB) $(LIBS) - rdoff\rdfdump$(X): rdoff\rdfdump.$(O) $(RDFLIBS) - $(MAKERDF) rdoff\ldrdf$(X): rdoff\ldrdf.$(O) $(RDFLIBS) - $(MAKERDF) rdoff\rdx$(X): rdoff\rdx.$(O) $(RDFLIBS) - $(MAKERDF) rdoff\rdflib$(X): rdoff\rdflib.$(O) $(RDFLIBS) - $(MAKERDF) rdoff\rdf2bin$(X): rdoff\rdf2bin.$(O) $(RDFLIBS) - $(MAKERDF) rdoff\rdf2com$(X): rdoff\rdf2bin$(X) $(RM_F) rdoff\rdf2com$(X) - cd rdoff && $(LN_S) rdf2bin$(X) rdf2com$(X) + $(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2com$(X) rdoff\rdf2ith$(X): rdoff\rdf2bin$(X) $(RM_F) rdoff\rdf2ith$(X) - cd rdoff && $(LN_S) rdf2bin$(X) rdf2ith$(X) + $(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2ith$(X) rdoff\rdf2ihx$(X): rdoff\rdf2bin$(X) $(RM_F) rdoff\rdf2ihx$(X) - cd rdoff && $(LN_S) rdf2bin$(X) rdf2ihx$(X) + $(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2ihx$(X) rdoff\rdf2srec$(X): rdoff\rdf2bin$(X) $(RM_F) rdoff\rdf2srec$(X) - cd rdoff && $(LN_S) rdf2bin$(X) rdf2srec$(X) + $(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2srec$(X) #-- End RDOFF Shared Rules --# @@ -384,21 +379,21 @@ dep: msvc.dep # Include and/or generate msvc.dep as needed. This is too complex to # use the include-command feature, but we can open-code it here. -!IF $(EXTERNAL_DEPENDENCIES) == 1 -!IFDEF MKDEP +MKDEP=0 +!IF $(EXTERNAL_DEPENDENCIES) == 1 && $(MKDEP) == 0 !IF EXISTS(msvc.dep) !INCLUDE msvc.dep -!ENDIF !ELSEIF [$(MAKE) /c MKDEP=1 /f Mkfiles\msvc.mak msvc.dep] == 0 !INCLUDE msvc.dep !ELSE !ERROR Unable to rebuild dependencies file msvc.dep !ENDIF +!ENDIF #-- Magic hints to mkdep.pl --# # @object-ending: ".$(O)" # @path-separator: "\" -# @exclude: "config/config.h" +# @exclude: "config\config.h" # @external: "msvc.dep" # @selfrule: "1" #-- Everything below is generated by mkdep.pl - do not edit --# diff --git a/tools/mkdep.pl b/tools/mkdep.pl index e84cc358..8c89f39a 100755 --- a/tools/mkdep.pl +++ b/tools/mkdep.pl @@ -51,6 +51,9 @@ $barrier = "#-- Everything below is generated by mkdep.pl - do not edit --#\n"; # This converts from filenames to full pathnames for our dependencies %dep_path = {}; +# List of files that cannot be found; these *must* be excluded +@must_exclude = (); + # # Scan files for dependencies # @@ -70,7 +73,8 @@ sub scandeps($) { if ( $line =~ /^\s*\#\s*include\s+\"(.*)\"\s*$/ ) { my $nf = $1; if (!defined($dep_path{$nf})) { - die "$0: cannot determine path for dependency: $file -> $nf\n"; + push(@must_exclude, $nf); + next; } $nf = $dep_path{$nf}; $mdeps{$nf}++; @@ -138,7 +142,7 @@ sub _insert_deps($$) { my $selfrule = 0; my $do_external = 0; my $maxline = 78; # Seems like a reasonable default - my @exclude = (); # Don't exclude anything + my %exclude = (); # Don't exclude anything my @genhdrs = (); my $external = undef; my $raw_output = 0; @@ -165,7 +169,7 @@ sub _insert_deps($$) { } elsif ( $parm eq 'continuation' ) { $cont = $val; } elsif ( $parm eq 'exclude' ) { - @exclude = split(/\,/, $val); + $excludes{$val}++; } elsif ( $parm eq 'include-command' ) { $include_command = $val; } elsif ( $parm eq 'external' ) { @@ -201,10 +205,6 @@ sub _insert_deps($$) { } my $e; - my %do_exclude = (); - foreach $e (@exclude) { - $do_exclude{$e} = 1; - } foreach my $dfile ($external, sort(keys(%deps)) ) { my $ofile; @@ -222,7 +222,7 @@ sub _insert_deps($$) { my $len = length($ofile); print $out $ofile; foreach my $dep (@deps) { - unless ($do_exclude{$dep}) { + unless ($excludes{$dep}) { my $str = convert_file($dep, $sep); my $sl = length($str)+1; if ( $len+$sl > $maxline-2 ) { From 50bbafbffb2c4ccb3612d79d4d70176f765eae69 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Jun 2018 14:02:29 -0700 Subject: [PATCH 10/83] Makefile.in: fix building RDOFF Apparently it isn't just NMAKE which is sensitive to the ordering of .SUFFIXES, it apparently applies just as well to Unix make. Signed-off-by: H. Peter Anvin --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index 0943f39e..949d0131 100644 --- a/Makefile.in +++ b/Makefile.in @@ -67,7 +67,7 @@ ifeq ($(TRACE),1) endif .SUFFIXES: -.SUFFIXES: .c .i .s .$(O) .$(A) $(X) .1 .txt .xml +.SUFFIXES: $(X) .$(O) .$(A) .xml .1 .c .i .s .txt .PHONY: all doc rdf install clean distclean cleaner spotless install_rdf test .PHONY: install_doc everything install_everything strip perlreq dist tags TAGS From 84ca80abd776ba758d0be85da8060ed962b98e73 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Jun 2018 14:04:40 -0700 Subject: [PATCH 11/83] NASM 2.14rc6 --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 92402d5a..b47207a4 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.14rc5 +2.14rc6 From a7c8e39686c5613ff20ad2c11e1866f01b6a8863 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Jun 2018 14:17:26 -0700 Subject: [PATCH 12/83] labels: pass the mangled name to the backend for fixups ofmt->symdef() always takes the mangled label name, make sure we actually do the correct thing even for forward fixups. Signed-off-by: H. Peter Anvin --- asm/labels.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asm/labels.c b/asm/labels.c index 88edc9ed..32f13180 100644 --- a/asm/labels.c +++ b/asm/labels.c @@ -146,7 +146,7 @@ static void out_symdef(union label *lptr) case LBL_EXTERN: case LBL_COMMON: if (lptr->defn.special) - ofmt->symdef(lptr->defn.label, 0, 0, 3, lptr->defn.special); + ofmt->symdef(lptr->defn.mangled, 0, 0, 3, lptr->defn.special); break; default: break; From a5992a4c41784aafe6741b78a71288550bbbdc21 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Jun 2018 16:00:48 -0700 Subject: [PATCH 13/83] outmacho: don't use raa_read() for pointer values If we write pointers, we have to read pointers. This unbreaks non-64-bit bigendian systems. Signed-off-by: H. Peter Anvin --- output/outmacho.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/output/outmacho.c b/output/outmacho.c index 9f937c90..e540b7d8 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -363,7 +363,7 @@ static struct section *get_section_by_index(int32_t index) if (index < 0 || index >= SEG_ABS || (index & 1)) return NULL; - return (struct section *)raa_read(section_by_index, index >> 1); + return raa_read_ptr(section_by_index, index >> 1); } struct dir_list { From 2c57d0a5ca2d7a8982f3e6591e12c45e6fd35717 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Jun 2018 17:11:54 -0700 Subject: [PATCH 14/83] RAA: make pointer vs integer RAAs type safe Use pseudo-types to make it impossible to confuse RAAs made of integers and RAAs made of pointers. Signed-off-by: H. Peter Anvin --- include/raa.h | 51 ++++++++++++++++++++++++++++++---- nasmlib/raa.c | 71 +++++++++++++++++++---------------------------- output/outmacho.c | 6 ++-- 3 files changed, 76 insertions(+), 52 deletions(-) diff --git a/include/raa.h b/include/raa.h index 9b636693..445318a8 100644 --- a/include/raa.h +++ b/include/raa.h @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * * - * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * Copyright 1996-2016 The NASM Authors - All Rights Reserved * See the file AUTHORS included with the NASM distribution for * the specific copyright holders. * @@ -36,13 +36,52 @@ #include "compiler.h" +struct real_raa; struct RAA; +union intorptr { + int64_t i; + void *p; +}; -struct RAA * never_null raa_init(void); -void raa_free(struct RAA *); +struct real_raa * never_null real_raa_init(void); +static inline struct RAA *never_null raa_init(void) +{ + return (struct RAA *)real_raa_init(); +} +static inline struct RAAPTR *never_null raa_init_ptr(void) +{ + return (struct RAAPTR *)real_raa_init(); +} +void real_raa_free(struct real_raa *); +static inline void raa_free(struct RAA *raa) +{ + real_raa_free((struct real_raa *)raa); +} +static inline void raa_free_ptr(struct RAAPTR *raa) +{ + real_raa_free((struct real_raa *)raa); +} int64_t raa_read(struct RAA *, int32_t); -void *raa_read_ptr(struct RAA *, int32_t); -struct RAA * never_null raa_write(struct RAA *r, int32_t posn, int64_t value); -struct RAA * never_null raa_write_ptr(struct RAA *r, int32_t posn, void *value); +void *raa_read_ptr(struct RAAPTR *, int32_t); +struct real_raa * never_null +real_raa_write(struct real_raa *r, int32_t posn, union intorptr value); + +static inline struct RAA * never_null +raa_write(struct RAA *r, int32_t posn, int64_t value) +{ + union intorptr ip; + + ip.i = value; + return (struct RAA *)real_raa_write((struct real_raa *)r, posn, ip); +} + +static inline struct RAAPTR * never_null +raa_write_ptr(struct RAAPTR *r, int32_t posn, void *value) +{ + union intorptr ip; + + ip.p = value; + return (struct RAAPTR *)real_raa_write((struct real_raa *)r, posn, ip); +} #endif /* NASM_RAA_H */ diff --git a/nasmlib/raa.c b/nasmlib/raa.c index dd510dfb..77329d3c 100644 --- a/nasmlib/raa.c +++ b/nasmlib/raa.c @@ -45,17 +45,11 @@ #define RAA_LAYERSHIFT 15 /* 2**this many _pointers_ allocated */ #define RAA_LAYERSIZE (1 << RAA_LAYERSHIFT) -typedef struct RAA RAA; typedef union RAA_UNION RAA_UNION; typedef struct RAA_LEAF RAA_LEAF; typedef struct RAA_BRANCH RAA_BRANCH; -union intorptr { - int64_t i; - void *p; -}; - -struct RAA { +struct real_raa { /* * Number of layers below this one to get to the real data. 0 * means this structure is a leaf, holding RAA_BLKSIZE real @@ -79,19 +73,26 @@ struct RAA { union intorptr data[RAA_BLKSIZE]; } l; struct RAA_BRANCH { - struct RAA *data[RAA_LAYERSIZE]; + struct real_raa *data[RAA_LAYERSIZE]; } b; } u; }; -#define LEAFSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_LEAF)) -#define BRANCHSIZ (sizeof(RAA)-sizeof(RAA_UNION)+sizeof(RAA_BRANCH)) +struct RAA { + struct real_raa raa; +}; +struct RAAPTR { + struct real_raa raa; +}; + +#define LEAFSIZ (sizeof(struct real_raa)-sizeof(RAA_UNION)+sizeof(RAA_LEAF)) +#define BRANCHSIZ (sizeof(struct real_raa)-sizeof(RAA_UNION)+sizeof(RAA_BRANCH)) #define LAYERSHIFT(r) ( (r)->layers==0 ? RAA_BLKSHIFT : RAA_LAYERSHIFT ) -static struct RAA *real_raa_init(int layers) +static struct real_raa *raa_init_layer(int layers) { - struct RAA *r; + struct real_raa *r; if (layers == 0) { r = nasm_zalloc(LEAFSIZ); @@ -104,23 +105,23 @@ static struct RAA *real_raa_init(int layers) return r; } -struct RAA *raa_init(void) +struct real_raa *real_raa_init(void) { - return real_raa_init(0); + return raa_init_layer(0); } -void raa_free(struct RAA *r) +void real_raa_free(struct real_raa *r) { if (r->layers) { - struct RAA **p; + struct real_raa **p; for (p = r->u.b.data; p - r->u.b.data < RAA_LAYERSIZE; p++) if (*p) - raa_free(*p); + real_raa_free(*p); } nasm_free(r); } -static const union intorptr *real_raa_read(struct RAA *r, int32_t posn) +static const union intorptr *real_raa_read(struct real_raa *r, int32_t posn) { if ((uint32_t) posn >= (UINT32_C(1) << (r->shift + LAYERSHIFT(r)))) return NULL; /* Beyond the end */ @@ -138,23 +139,23 @@ int64_t raa_read(struct RAA *r, int32_t pos) { const union intorptr *ip; - ip = real_raa_read(r, pos); + ip = real_raa_read((struct real_raa *)r, pos); return ip ? ip->i : 0; } -void *raa_read_ptr(struct RAA *r, int32_t pos) +void *raa_read_ptr(struct RAAPTR *r, int32_t pos) { const union intorptr *ip; - ip = real_raa_read(r, pos); + ip = real_raa_read((struct real_raa *)r, pos); return ip ? ip->p : NULL; } -static struct RAA * -real_raa_write(struct RAA *r, int32_t posn, union intorptr value) +struct real_raa * +real_raa_write(struct real_raa *r, int32_t posn, union intorptr value) { - struct RAA *result; + struct real_raa *result; nasm_assert(posn >= 0); @@ -162,7 +163,7 @@ real_raa_write(struct RAA *r, int32_t posn, union intorptr value) /* * Must add a layer. */ - struct RAA *s; + struct real_raa *s; s = nasm_zalloc(BRANCHSIZ); s->layers = r->layers + 1; @@ -174,12 +175,12 @@ real_raa_write(struct RAA *r, int32_t posn, union intorptr value) result = r; while (r->layers > 0) { - struct RAA **s; + struct real_raa **s; int32_t l = posn >> r->shift; posn &= (UINT32_C(1) << r->shift) - 1; s = &r->u.b.data[l]; if (!*s) - *s = real_raa_init(r->layers - 1); + *s = raa_init_layer(r->layers - 1); r = *s; } @@ -187,19 +188,3 @@ real_raa_write(struct RAA *r, int32_t posn, union intorptr value) return result; } - -struct RAA *raa_write(struct RAA *r, int32_t posn, int64_t value) -{ - union intorptr ip; - - ip.i = value; - return real_raa_write(r, posn, ip); -} - -struct RAA *raa_write_ptr(struct RAA *r, int32_t posn, void *value) -{ - union intorptr ip; - - ip.p = value; - return real_raa_write(r, posn, ip); -} diff --git a/output/outmacho.c b/output/outmacho.c index e540b7d8..75650b47 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -313,7 +313,7 @@ static uint64_t rel_padcnt = 0; ALIGN(x, fmt.ptrsize) /* align x to output format width */ static struct hash_table section_by_name; -static struct RAA *section_by_index; +static struct RAAPTR *section_by_index; static struct section * never_null find_or_add_section(const char *segname, const char *sectname) @@ -436,7 +436,7 @@ static void macho_init(void) extsyms = raa_init(); strs = saa_init(1L); - section_by_index = raa_init(); + section_by_index = raa_init_ptr(); hash_init(§ion_by_name, HASH_MEDIUM); /* string table starts with a zero byte so index 0 is an empty string */ @@ -1808,7 +1808,7 @@ static void macho_cleanup(void) nasm_free(extdefsyms); nasm_free(undefsyms); nasm_free(sectstab); - raa_free(section_by_index); + raa_free_ptr(section_by_index); hash_free(§ion_by_name); } From 5ce7d1e8975d54eb885e1eba675daf6d3fc13a8e Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 18 Jun 2018 17:14:39 -0700 Subject: [PATCH 15/83] NASM 2.14rc7 --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index b47207a4..41c799f1 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.14rc6 +2.14rc7 From bc77f9c5874db1729bc1fae13d9bf38ba579d3d1 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin, Intel" Date: Mon, 25 Jun 2018 12:39:42 -0700 Subject: [PATCH 16/83] labels: don't update the local variable base for *ANY* dot labels ..@ labels (macro-local) are NASM specials, although not "magic": they are explicitly defined to not preturb the local label base name. However, they return false for both islocal() and ismagic(), so we need to add a new function containing the correct test for when the local label base should be advanced. Reported-by: Signed-off-by: H. Peter Anvin (Intel) Cc: Cyrill Gorcunov Cc: Bae, Chang Seok --- asm/labels.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/asm/labels.c b/asm/labels.c index 32f13180..8c4e6f22 100644 --- a/asm/labels.c +++ b/asm/labels.c @@ -72,6 +72,21 @@ static bool ismagic(const char *l) return l[0] == '.' && l[1] == '.' && l[2] != '@'; } +/* + * Return true if we should update the local label base + * as a result of this symbol. We must exclude local labels + * as well as any kind of special labels, including ..@ ones. + */ +static bool set_prevlabel(const char *l) +{ + if (tasm_compatible_mode) { + if (l[0] == '@' && l[1] == '@') + return false; + } + + return l[0] != '.'; +} + #define LABEL_BLOCK 128 /* no. of labels/block */ #define LBLK_SIZE (LABEL_BLOCK * sizeof(union label)) @@ -419,11 +434,6 @@ void define_label(const char *label, int32_t segment, */ lptr = find_label(label, true, &created); - if (pass0 > 1) { - if (created) - nasm_error(ERR_WARNING, "label `%s' defined on pass two", label); - } - if (!segment) segment = lptr->defn.segment ? lptr->defn.segment : seg_alloc(); @@ -436,9 +446,8 @@ void define_label(const char *label, int32_t segment, if (ismagic(label) && lptr->defn.type == LBL_LOCAL) lptr->defn.type = LBL_SPECIAL; - if (!islocal(label) && normal) { + if (set_prevlabel(label) && normal) prevlabel = lptr->defn.label; - } if (lptr->defn.type == LBL_COMMON) { size = offset; @@ -447,7 +456,8 @@ void define_label(const char *label, int32_t segment, size = 0; /* This is a hack... */ } - changed = !lptr->defn.defined || lptr->defn.segment != segment || + changed = created || !lptr->defn.defined || + lptr->defn.segment != segment || lptr->defn.offset != offset || lptr->defn.size != size; global_offset_changed += changed; @@ -456,9 +466,11 @@ void define_label(const char *label, int32_t segment, * special case, LBL_SPECIAL symbols are allowed to be changed * even during the last pass. */ - if (changed && pass0 == 2 && lptr->defn.type != LBL_SPECIAL) - nasm_error(ERR_WARNING, "label `%s' changed during code generation", + if (changed && pass0 > 1 && lptr->defn.type != LBL_SPECIAL) { + nasm_error(ERR_WARNING, "label `%s' %s during code generation", + created ? "defined" : "changed", lptr->defn.label); + } lptr->defn.segment = segment; lptr->defn.offset = offset; From 87d9e626c3218c04eb8b217f2e5cf0ed7a487ebe Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin, Intel" Date: Mon, 25 Jun 2018 12:58:49 -0700 Subject: [PATCH 17/83] nasm: need to call init_labels() before command line parsing The prefix and suffix options call perm_alloc() in labels.c, which is not available until init_labels() have run. There is no reason not to call init_labels() early. Signed-off-by: H. Peter Anvin (Intel) --- asm/nasm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/asm/nasm.c b/asm/nasm.c index 6299831f..b851ac4c 100644 --- a/asm/nasm.c +++ b/asm/nasm.c @@ -424,6 +424,13 @@ int main(int argc, char **argv) tolower_init(); src_init(); + /* + * We must call init_labels() before the command line parsing, + * because we may be setting prefixes/suffixes from the command + * line. + */ + init_labels(); + offsets = raa_init(); forwrefs = saa_init((int32_t)sizeof(struct forwrefinfo)); @@ -553,13 +560,6 @@ int main(int argc, char **argv) nasm_fatal(ERR_NOFILE, "unable to open output file `%s'", outname); - /* - * We must call init_labels() before ofmt->init() since - * some object formats will want to define labels in their - * init routines. (eg OS/2 defines the FLAT group) - */ - init_labels(); - ofmt->init(); dfmt->init(); From 2139874de255afe69533d59724896a2627f9a62f Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin, Intel" Date: Mon, 25 Jun 2018 13:03:39 -0700 Subject: [PATCH 18/83] labels: fix formatting of warning message Output was backwards... Signed-off-by: H. Peter Anvin (Intel) --- asm/labels.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/asm/labels.c b/asm/labels.c index 8c4e6f22..0f9f17d8 100644 --- a/asm/labels.c +++ b/asm/labels.c @@ -468,8 +468,8 @@ void define_label(const char *label, int32_t segment, */ if (changed && pass0 > 1 && lptr->defn.type != LBL_SPECIAL) { nasm_error(ERR_WARNING, "label `%s' %s during code generation", - created ? "defined" : "changed", - lptr->defn.label); + lptr->defn.label, + created ? "defined" : "changed"); } lptr->defn.segment = segment; From 4fb2acc0d3ff6bdb0d5dbcb6368ac1a524186ced Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin, Intel" Date: Mon, 25 Jun 2018 13:11:01 -0700 Subject: [PATCH 19/83] labels: if we have overridden EXTERN, don't call define_label() If we have overridden EXTERN, then we should not call define_label() on it again. Return a fail status from declare_label(), indicating that the type declaration failed, but of course we don't print an error message. Signed-off-by: H. Peter Anvin (Intel) --- asm/labels.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asm/labels.c b/asm/labels.c index 0f9f17d8..1b93348c 100644 --- a/asm/labels.c +++ b/asm/labels.c @@ -398,7 +398,7 @@ static bool declare_label_lptr(union label *lptr, type == LBL_EXTERN) { if (!lptr->defn.special) lptr->defn.special = perm_copy(special); - return true; + return false; /* Don't call define_label() after this! */ } nasm_error(ERR_NONFATAL, "symbol `%s' declared both as %s and %s", From c5e45f6b7081c6dd5959d48327c2a9828b65315d Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin, Intel" Date: Mon, 25 Jun 2018 13:16:53 -0700 Subject: [PATCH 20/83] labels: auto-promote EXTERN labels to GLOBAL if defined If we define a label which was previously declared EXTERN, then automatically treat is as GLOBAL. Previously, we would fail to converge and loop forever, which is obviously not what we want. This is more user-friendly anyway. Signed-off-by: H. Peter Anvin (Intel) --- asm/labels.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/asm/labels.c b/asm/labels.c index 1b93348c..93a687ea 100644 --- a/asm/labels.c +++ b/asm/labels.c @@ -434,8 +434,14 @@ void define_label(const char *label, int32_t segment, */ lptr = find_label(label, true, &created); - if (!segment) + if (segment) { + /* We are actually defining this label */ + if (lptr->defn.type == LBL_EXTERN) /* auto-promote EXTERN to GLOBAL */ + lptr->defn.type = LBL_GLOBAL; + } else { + /* It's a pseudo-segment (extern, common) */ segment = lptr->defn.segment ? lptr->defn.segment : seg_alloc(); + } if (lptr->defn.defined || lptr->defn.type == LBL_BACKEND) { /* We have seen this on at least one previous pass */ From 59242bd10aa8dd3087c31b10a39f94ef0aa3986e Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin, Intel" Date: Mon, 25 Jun 2018 13:19:32 -0700 Subject: [PATCH 21/83] test: add test for context-local labels and extern label promotion Add a simple test case for context-local (%$) labels not disturbing the local variable namespace, and extern labels getting promoted to global. Signed-off-by: H. Peter Anvin (Intel) --- test/ctxlocal.asm | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 test/ctxlocal.asm diff --git a/test/ctxlocal.asm b/test/ctxlocal.asm new file mode 100644 index 00000000..93e9fcae --- /dev/null +++ b/test/ctxlocal.asm @@ -0,0 +1,25 @@ +;; +;; Test of context-local labels +;; + + bits 64 + extern everywhere ; Test of extern -> global promotion, too + extern tjosan +here: + jz .there +%push foo + jo %$mordor + hlt +%$mordor: + nop +%pop +.there: + ret + +everywhere: + ret + + global everywhere + +tjosan: + ret From 6bc18f1978257dae185c5f64e2e85f06c806424a Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin, Intel" Date: Mon, 25 Jun 2018 13:24:51 -0700 Subject: [PATCH 22/83] test: make absolute.asm buildable even when not in binary mode absolute.asm is useful even for other backends, so explicitly test to see if ORG is possible for this format. Signed-off-by: H. Peter Anvin (Intel) --- test/absolute.asm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/absolute.asm b/test/absolute.asm index 31c8178c..969a85e9 100644 --- a/test/absolute.asm +++ b/test/absolute.asm @@ -1,5 +1,7 @@ ;Testname=bin; Arguments=-fbin -oabsolute.bin; Files=stdout stderr absolute.bin +%ifmacro org org 7c00h +%endif init_foo: jmp init_bar nop @@ -15,7 +17,7 @@ init_foo: nop nop nop - + init_bar: mov [b1],dl mov [b2],edx @@ -33,8 +35,7 @@ init_bar: nop nop ret - + absolute init_bar+7 b1: resb 1 b2: resd 6 - From 415b6b3df13c27afd71963e450d151fc9bb8ea40 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Mon, 25 Jun 2018 14:09:52 -0700 Subject: [PATCH 23/83] absolute: in absolute space, need to use absolute.segment We can be in absolute space and still end up with segment-relative references. This is in fact the meaning of absolute.segment. Make sure we define the labels appropriately. Reported-by: Cyrill Gorcunov Signed-off-by: H. Peter Anvin (Intel) --- asm/directiv.c | 1 + asm/parser.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/asm/directiv.c b/asm/directiv.c index 68a74a12..89750c8c 100644 --- a/asm/directiv.c +++ b/asm/directiv.c @@ -399,6 +399,7 @@ bool process_directives(char *directive) "in pass two"); in_absolute = true; location.segment = NO_SEG; + location.offset = absolute.offset; break; } diff --git a/asm/parser.c b/asm/parser.c index 40188410..64d7a024 100644 --- a/asm/parser.c +++ b/asm/parser.c @@ -486,7 +486,8 @@ restart_parse: * Generally fix things. I think this is right as it is, but * am still not certain. */ - define_label(result->label, location.segment, + define_label(result->label, + in_absolute ? absolute.segment : location.segment, location.offset, true); } } From ff6faf6134aa3ced7373fd7c63b329fc5900f614 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Mon, 25 Jun 2018 14:13:20 -0700 Subject: [PATCH 24/83] NASM 2.14rc8 --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 41c799f1..696c44e7 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.14rc7 +2.14rc8 From 1af6ef4e146b740fdc02a969c28d50e809286ee6 Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Wed, 20 Jun 2018 17:05:12 -0700 Subject: [PATCH 25/83] nasm: fix some typo and description for the option help Signed-off-by: Chang S. Bae Signed-off-by: H. Peter Anvin (Intel) --- asm/nasm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/asm/nasm.c b/asm/nasm.c index b851ac4c..f9bd3db0 100644 --- a/asm/nasm.c +++ b/asm/nasm.c @@ -1943,14 +1943,16 @@ static void help(const char xopt) " -w-foo disable warning foo (equiv. -Wno-foo)\n" " -w[+-]error[=foo]\n" " promote [specific] warnings to errors\n" - " -h show invocation summary and exit\n\n" + " -h show invocation summary and exit (also --help)\n\n" " --pragma str pre-executes a specific %%pragma\n" " --before str add line (usually a preprocessor statement) before the input\n" " --prefix str prepend the given string to all the given string\n" - " to all extern, common and global symbols\n" - " --suffix str append the given string to all the given string\n" - " to all extern, common and global symbols\n" + " to all extern, common and global symbols (also --gprefix)\n" + " --postfix str append the given string to all the given string\n" + " to all extern, common and global symbols (also --gpostfix)\n" " --lprefix str prepend the given string to all other symbols\n" + " --lpostfix str append the given string to all other symbols\n" + " --keep-all output files will not be removed even if an error happens\n" " --limit-X val set execution limit X\n"); for (i = 0; i <= LIMIT_MAX; i++) { From 754edd85ee3e0cf668e1fd84802ab6aabeef6b8f Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Wed, 20 Jun 2018 17:05:13 -0700 Subject: [PATCH 26/83] doc: document new feature from version 2.14 Added descriptions about new commandline options, STATIC directive, symbol mingling, and some output format specifics. Signed-off-by: Chang S. Bae Signed-off-by: H. Peter Anvin (Intel) --- doc/nasmdoc.src | 145 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 139 insertions(+), 6 deletions(-) diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src index 7b331d35..b6aab1c0 100644 --- a/doc/nasmdoc.src +++ b/doc/nasmdoc.src @@ -368,6 +368,8 @@ To get further usage instructions from NASM, try typing \c nasm -h +\c{--help} option is also the same. + As \c{-hf}, this will also list the available output file formats, and what they are. @@ -657,10 +659,13 @@ option. So running is equivalent to running \c{nasm myfile.asm} and placing the directive \c{%include "myinc.inc"} at the start of the file. +\c{--include} option is also accepted. + For consistency with the \c{-I}, \c{-D} and \c{-U} options, this option can also be specified as \c{-P}. + \S{opt-d} The \i\c{-d}\I\c{-D} Option: \I{pre-defining macros}Pre-Define a Macro \I\c{%define}Just as the \c{-p} option gives an alternative to placing @@ -917,13 +922,72 @@ is indicated by an asterisk. For example: \c dwarf elf32 (i386) dwarf debug format for Linux -\S{opt-pfix} The \i\c{--prefix} and \i\c{--postfix} Options. +\S{opt-pfix} The \i\c{--(g|l)prefix}, \i\c{--(g|l)postfix} Options. -The \c{--prefix} and \c{--postfix} options prepend or append -(respectively) the given argument to all \c{global} or -\c{extern} variables. E.g. \c{--prefix _} will prepend the -underscore to all global and external variables, as C requires it in -some, but not all, system calling conventions. +The \c{--(g)prefix} options prepend the given argument +to all \c{extern}, \c{common}, \c{static}, and \c{global} symbols, and the +\c{--lprefix} option prepends to all other symbols. Similarly, +\c{--(g)postfix} and \c{--lpostfix} options append +the argument in the exactly same way as the \c{--xxprefix} options does. + +Running this: + +\c nasm -f macho --gprefix _ + +is equivalent to place the directive with \c{%pragma macho gprefix _} +at the start of the file (\k{mangling}). It will prepend the underscore +to all global and external variables, as C requires it in some, but not all, +system calling conventions. + +\S{opt-pragma} The \i\c{--pragma} Option + +NASM accepts an argument as \c{%pragma} option, which is like placing +a \c{%pragma} preprocess statement at the beginning of the source. +Running this: + +\c nasm -f macho --pragma "macho gprefix _" + +is equivalent to the example in \k{opt-pfix}. + + +\S{opt-before} The \i\c{--before} Option + +A preprocess statement can be accepted with this option. The example +shown in \k{opt-pragma} is the same as running this: + +\c nasm -f macho --before "%pragma macho gprefix _" + + +\S{opt-limit} The \i\c{--limit-X} Option + +This option allows user to setup various maximum values for these: + +\b\c{--limit-passes}: Number of maximum allowed passes. Default is +effectively unlimited. + +\b\c{--limit-stalled-passes}: Maximum number of allowed unfinished +passes. Default is 1000. + +\b\c{--limit-macro-levels}: Define maximum depth of macro expansion +(in preprocess). Default is 1000000. + +\b\c{--limit-rep}: Maximum number of allowed preprocessor loop, defined +under \c{%rep}. Default is 1000000. + +\b\c{--limit-eval}: This number sets the boundary condition of allowed +expression length. Default is 1000000. + +\b\c{--limit-lines}: Total number of source lines as allowed to be +processed. Default is 2000000000. + +In example, running this limits the maximum line count to be 1000. + +\c nasm --limit-lines 1000 + + +\S{opt-keep-all} The \i\c{--keep-all} Option + +This option doesn't delete any output files even if an error happens. \S{nasmenv} The \i\c{NASMENV} \i{Environment} Variable @@ -4607,6 +4671,62 @@ Once again, like \c{EXTERN} and \c{GLOBAL}, the primitive form of \c{COMMON} differs from the user-level form only in that it can take only one argument at a time. +\H{static} \i\c{STATIC}: Local Symbols within Modules + +Opposite to \c{EXTERN} and \c{GLOBAL}, \c{STATIC} is local symbol, +but should be named according to the global mangling rules (named +by analogy with the C keyword "static" as applied to the functions). +And like \c{GLOBAL} directive, the directive applying to a symbol +should be \i{before} the definition of the symbol. For example: + +\c static foo +\c foo: +\c ; codes + +Unlike \c{GLOBAL}, \c{STATIC} does not allow object formats to accept +private extensions mentioned in \k{global}. + +\H{mangling} \i\c{(G|L)PREFIX}, \i\c{(G|L)POSTFIX}: Mangling Symbols + +\c{PREFIX}, \c{GPREFIX}, \c{LPREFIX}, \c{POSTFIX}, \c{GPOSTFIX}, and +\c{LPOSTFIX} directives can prepend or append the given argument to +a certain type of symbols. The directive should be as a preprocess +statement. Each usage is: + +\b\c{PREFIX}|\c{GPREFIX}: Prepend the argument to all \c{EXTERN} +\c{COMMON}, \c{STATIC}, and \c{GLOBAL} symbols + +\b\c{LPREFIX}: Prepend the argument to all other symbols +such as Local Labels, and backend defined symbols + +\b\c{POSTFIX}|\c{GPOSTFIX}: Append the argument to all \c{EXTERN} +\c{COMMON}, \c{STATIC}, and \c{GLOBAL} symbols + +\b\c{LPOSTFIX}: Append the argument to all other symbols +such as Local Labels, and backend defined symbols + +This is a macro implemented as a \c{%pragma}: + +\c %pragma macho lprefix L_ + +Commandline option is also possible. See also \k{opt-pfix}. + + +\H{gen-namespace} \i\c{OUTPUT}, \i\c{DEBUG}: Generic Namespaces + +\c{OUTPUT} and \c{DEBUG} are generic \c{%pragma} namespaces that are +supposed to redirect to the current output and debug formats. +For example, when mangling local symbols via the generic namespace: + +\c %pragma output gprefix _ + +This is useful when the directive is needed to be output format +agnostic. + +The example is also euquivalent to this, when the output format is \c{elf}: + +\c %pragma elf gprefix _ + \H{CPU} \i\c{CPU}: Defining CPU Dependencies @@ -5731,6 +5851,19 @@ non-Mach-O builds of the same source code: \c %pragma macho no_dead_strip symbol... +\S{machosect} \c{macho} specific extensions to the \c{GLOBAL} +Directive: \i\c{private_extern} + +The directive extension to \c{GLOBAL} marks the symbol with limited +global scope. For example, you can specify the global symbol with +this extension: + +\c global foo:private_extern +\c foo: +\c ; codes + +Using with static linker will clear the private extern attribute. +But linker option like \c{-keep_private_externs} can avoid it. \H{elffmt} \i\c{elf32}, \i\c{elf64}, \i\c{elfx32}: \I{ELF}\I{linux, elf}\i{Executable and Linkable Format} Object Files From ef21926ec2068d9ddd6c2e0b8de014afb2968849 Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Wed, 20 Jun 2018 17:05:14 -0700 Subject: [PATCH 27/83] doc: 2.14 change log Signed-off-by: Chang S. Bae Signed-off-by: H. Peter Anvin (Intel) --- doc/changes.src | 47 +++++++++++++++++++++++++++++++++++++++++++++++ doc/nasmdoc.src | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/doc/changes.src b/doc/changes.src index ddfe6b38..835cee7d 100644 --- a/doc/changes.src +++ b/doc/changes.src @@ -7,6 +7,53 @@ The NASM 2 series supports x86-64, and is the production version of NASM since 2007. +\S{cl-2.14} Version 2.14 + +\b Fixed \c{subsections_via_symbols} for \c{macho} object format. + +\b Support to mangle labels based on the types through \c{%pragma}. See +\k{mangling}. + +\b Added \c{--gprefix}, \c{--gpostfix}, \c{--lprefix}, and \c{--lpostfix} +that allows commandline base symbol mangling. See \k{opt-pfix}. + +\b Supported generic \c{%pragma} namespaces, \c{output} and \c{debug}. See +\k{gen-namespace}. + +\b Added \c{--pragma} argument as \c{%pragma} option. See \k{opt-pragma}. + +\b Added \c{--before} to accept preprocess statement before input. See \k{opt-before}. + +\b Added \c{AVX512} \c{VBMI2} (Additional Bit Manipulation), \c{VNNI} (Vector +Neural Network), \c{BITALG} (Bit Algorithm), and \c{GFNI} (Galois Field New +Instruction) instructions. + +\b Support \c{STATIC} directive. See \k{static}. + +\b Support \c{private_extern} as \c{macho} specific extension to the +\c{GLOBAL} Directive. See \k{macho-pext}. + +\b Updated \c{UD0} encoding to match with the specification + +\b Added \c{--limit-X} to set execution limit. See \k{opt-limit}. + +\b Fixed \c{CPU} directive case insensitive + +\b Fixed modules name for \c{ELF}, \c{IEEE}, \c{macho}, \c{obj} output format + +\b Fixed to build \c{rdoff} tool and resolve to handle dependencies correctly +with \c{Microsoft Visual Studio} + +\b Fixed \c{Codeview} version number to be aligned with \c{NASM}’s + +\b Fixed to assign (internal) segment number correctly and efficiently + +\b Added \c{--keep-all}. See \k{opt-keep-all}. + +\b Added \c{--include} that is an alias to -P (\k{opt-p}). + +\b Added \c{--help} as an alias to -h (\k{syntax}). + \S{cl-2.13.04} Version 2.13.04 \b Added \c{-W}, \c{-D}, and \c{-Q} suffix aliases for \c{RET} diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src index b6aab1c0..b0db9d59 100644 --- a/doc/nasmdoc.src +++ b/doc/nasmdoc.src @@ -5851,7 +5851,7 @@ non-Mach-O builds of the same source code: \c %pragma macho no_dead_strip symbol... -\S{machosect} \c{macho} specific extensions to the \c{GLOBAL} +\S{macho-pext} \c{macho} specific extensions to the \c{GLOBAL} Directive: \i\c{private_extern} The directive extension to \c{GLOBAL} marks the symbol with limited From b6b4b5d5460cfd4157c570546d92f02dbc3c2698 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Mon, 25 Jun 2018 14:19:39 -0700 Subject: [PATCH 28/83] changes.src: cleanup and fixes Clean up the language somewhat, and fix a couple of confusing statements. Signed-off-by: H. Peter Anvin (Intel) --- doc/changes.src | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/doc/changes.src b/doc/changes.src index 835cee7d..7c272e0a 100644 --- a/doc/changes.src +++ b/doc/changes.src @@ -14,28 +14,33 @@ since 2007. \b Support to mangle labels based on the types through \c{%pragma}. See \k{mangling}. -\b Added \c{--gprefix}, \c{--gpostfix}, \c{--lprefix}, and \c{--lpostfix} -that allows commandline base symbol mangling. See \k{opt-pfix}. +\b Added the \c{--gprefix}, \c{--gpostfix}, \c{--lprefix}, and +\c{--lpostfix} command line options, to allow command line base symbol +mangling. See \k{opt-pfix}. \b Supported generic \c{%pragma} namespaces, \c{output} and \c{debug}. See \k{gen-namespace}. -\b Added \c{--pragma} argument as \c{%pragma} option. See \k{opt-pragma}. +\b Added the \c{--pragma} command line option to inject a \c{%pragma} +directive. See \k{opt-pragma}. -\b Added \c{--before} to accept preprocess statement before input. See \k{opt-before}. +\b Added the \c{--before} command line option to accept preprocess +statement before input. See \k{opt-before}. \b Added \c{AVX512} \c{VBMI2} (Additional Bit Manipulation), \c{VNNI} (Vector Neural Network), \c{BITALG} (Bit Algorithm), and \c{GFNI} (Galois Field New Instruction) instructions. -\b Support \c{STATIC} directive. See \k{static}. +\b Added the \c{STATIC} directive for local symbols that should be +renamed using global-symbol rules. See \k{static}. \b Support \c{private_extern} as \c{macho} specific extension to the -\c{GLOBAL} Directive. See \k{macho-pext}. +\c{GLOBAL} directive. See \k{macho-pext}. \b Updated \c{UD0} encoding to match with the specification -\b Added \c{--limit-X} to set execution limit. See \k{opt-limit}. +\b Added the \c{--limit-X} command line option to set execution +limits. See \k{opt-limit}. \b Fixed \c{CPU} directive case insensitive @@ -44,17 +49,14 @@ Instruction) instructions. \b Fixed to build \c{rdoff} tool and resolve to handle dependencies correctly with \c{Microsoft Visual Studio} -\b Fixed \c{Codeview} version number to be aligned with \c{NASM}’s +\b Fixed \c{Codeview} version number to be aligned with \c{MASM}. -\b Fixed to assign (internal) segment number correctly and efficiently +\b Added the \c{--keep-all} command line option to preserve output +files. See \k{opt-keep-all}. -\b Added \c{--keep-all}. See \k{opt-keep-all}. +\b Added the \c{--include} command line option, an alias to \c{-P} (\k{opt-p}). -\b Added \c{--include} that is an alias to -P (\k{opt-p}). - -\b Added \c{--help} as an alias to -h (\k{syntax}). - -\S{cl-2.13.04} Version 2.13.04 +\b Added the \c{--help} command line option as an alias to \c{-h} (\k{syntax}). \b Added \c{-W}, \c{-D}, and \c{-Q} suffix aliases for \c{RET} instructions so the operand sizes of these instructions can be From 26b810176f939f5c7f1e6364ed5901283d1a576b Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Mon, 25 Jun 2018 14:35:05 -0700 Subject: [PATCH 29/83] insns.dat: add PTWRITE instruction Add PTWRITE instruction. It is worth noting that we should be able to do "ptwrite [eax]" in 32-bit mode, but the instruction selector doesn't currently handle that well in a way that doesn't make 64-bit mode very confusing. Signed-off-by: H. Peter Anvin (Intel) --- x86/insns.dat | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x86/insns.dat b/x86/insns.dat index cabd9bd6..96295dc1 100644 --- a/x86/insns.dat +++ b/x86/insns.dat @@ -5197,6 +5197,10 @@ PCOMMIT void [ 66 0f ae f8] ; AMD Zen v1 CLZERO void [ 0f 01 fc] FUTURE,AMD +;# Processor trace write +PTWRITE rm32 [m: np 0f ae /4] FUTURE +PTWRITE rm64 [m: o64 np 0f ae /4] X64,FUTURE + ;# Instructions from the Intel Instruction Set Extensions, ;# doc 319433-034 May 2018 CLDEMOTE mem [m: np 0f 1c /0] FUTURE From 2bf35e0b026d937bbd1c5208c0060e36caacb7cc Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Mon, 25 Jun 2018 14:51:15 -0700 Subject: [PATCH 30/83] insns.dat: add support for the V4* and VP4* 4-way instructions New instructions which do four full iterations of a data-reduction operation (FMA, dot product.) Bug report: https://bugzilla.nasm.us/show_bug.cgi?id=3392492 Reported-by: ff_ff Signed-off-by: H. Peter Anvin (Intel) --- x86/insns-iflags.ph | 2 ++ x86/insns.dat | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/x86/insns-iflags.ph b/x86/insns-iflags.ph index 7258d3c2..1042f0f5 100644 --- a/x86/insns-iflags.ph +++ b/x86/insns-iflags.ph @@ -148,6 +148,8 @@ my %insns_flag_bit = ( "AVX512VNNI" => [$f++, "AVX-512 VNNI instructions"], "AVX512BITALG" => [$f++, "AVX-512 Bit Algorithm instructions"], "AVX512VPOPCNTDQ" => [$f++, "AVX-512 VPOPCNTD/VPOPCNTQ"], + "AVX5124FMAPS" => [$f++, "AVX-512 4-iteration multiply-add"], + "AVX5124VNNIW" => [$f++, "AVX-512 4-iteration dot product"], # Put these last "OBSOLETE" => [$f++, "Instruction removed from architecture"], diff --git a/x86/insns.dat b/x86/insns.dat index 96295dc1..22af9f5f 100644 --- a/x86/insns.dat +++ b/x86/insns.dat @@ -5332,6 +5332,16 @@ VPSHUFBITQMB kreg|mask,xmmreg,xmmrm128 [rvm:fvm: evex.nds.128.66.0f38.w0 8f /r VPSHUFBITQMB kreg|mask,ymmreg,ymmrm256 [rvm:fvm: evex.nds.256.66.0f38.w0 8f /r] AVX512BITALG,AVX512VL,FUTURE VPSHUFBITQMB kreg|mask,zmmreg,zmmrm512 [rvm:fvm: evex.nds.512.66.0f38.w0 8f /r] AVX512BITALG,FUTURE +;# AVX512 4-iteration Multiply-Add +V4FMADDPS zmmreg|mask|z,zmmreg,mem128 [rvm:m128:evex.dds.512.f2.0f38.w0 9a /r] AVX5124FMAPS,FUTURE +V4FNMADDPS zmmreg|mask|z,zmmreg,mem128 [rvm:m128:evex.dds.512.f2.0f38.w0 9a /r] AVX5124FMAPS,FUTURE +V4FMADDSS zmmreg|mask|z,zmmreg,mem128 [rvm:m128:evex.dds.512.f2.0f38.w0 9b /r] AVX5124FMAPS,FUTURE +V4FNMADDSS zmmreg|mask|z,zmmreg,mem128 [rvm:m128:evex.dds.512.f2.0f38.w0 9b /r] AVX5124FMAPS,FUTURE + +;# AVX512 4-iteration Dot Product +V4DPWSSDS zmmreg|mask|z,zmmreg,mem128 [rvm:m128:evex.dds.512.f2.0f38.w0 53 /r] AVX5124VNNIW,FUTURE +V4DPWSSD zmmreg|mask|z,zmmreg,mem128 [rvm:m128:evex.dds.512.f2.0f38.w0 52 /r] AVX5124VNNIW,FUTURE + ;# Systematic names for the hinting nop instructions ; These should be last in the file HINT_NOP0 rm16 [m: o16 0f 18 /0] P6,UNDOC From cd26fccab48bc35465e68d44a7432d1b1cca4d7e Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 25 Jun 2018 17:15:08 -0700 Subject: [PATCH 31/83] asm: support the +n syntax for register sets Support the +n syntax for multiple contiguous registers, and emit it in the output from ndisasm as well. Signed-off-by: H. Peter Anvin (Intel) --- asm/assemble.c | 23 ++++++++++++++++------- asm/parser.c | 30 ++++++++++++++++++++++++++---- disasm/disasm.c | 3 +++ include/opflags.h | 20 +++++++++++++++++++- test/v4.asm | 12 ++++++++++++ x86/insns.dat | 12 ++++++------ 6 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 test/v4.asm diff --git a/asm/assemble.c b/asm/assemble.c index a6bb0ee5..7196f911 100644 --- a/asm/assemble.c +++ b/asm/assemble.c @@ -208,6 +208,8 @@ enum match_result { MERR_ENCMISMATCH, MERR_BADBND, MERR_BADREPNE, + MERR_REGSETSIZE, + MERR_REGSET, /* * Matching success; the conditional ones first */ @@ -792,6 +794,12 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction) (has_prefix(instruction, PPS_REP, P_REPNE) ? "repne" : "repnz")); break; + case MERR_REGSETSIZE: + nasm_error(ERR_NONFATAL, "invalid register set size"); + break; + case MERR_REGSET: + nasm_error(ERR_NONFATAL, "register set not valid for operand"); + break; default: nasm_error(ERR_NONFATAL, "invalid combination of opcode and operands"); @@ -2162,7 +2170,6 @@ static enum match_result matches(const struct itemplate *itemp, insn *instruction, int bits) { opflags_t size[MAX_OPERANDS], asize; - bool opsizemissing = false; int i, oprs; /* @@ -2323,9 +2330,14 @@ static enum match_result matches(const struct itemplate *itemp, if (~ideco & deco & (Z_MASK|STATICRND_MASK|SAE_MASK)) return MERR_DECONOTHERE; - if (itemp->opd[i] & ~type & ~SIZE_MASK) { + if (itemp->opd[i] & ~type & ~(SIZE_MASK|REGSET_MASK)) return MERR_INVALOP; - } else if (template_opsize) { + + if (~itemp->opd[i] & type & REGSET_MASK) + return (itemp->opd[i] & REGSET_MASK) + ? MERR_REGSETSIZE : MERR_REGSET; + + if (template_opsize) { if (template_opsize != insn_opsize) { if (insn_opsize) { return MERR_INVALOP; @@ -2335,7 +2347,7 @@ static enum match_result matches(const struct itemplate *itemp, * so "missing operand size" for a register should be * considered a wildcard match rather than an error. */ - opsizemissing = true; + return MERR_OPSIZEMISSING; } } else if (is_broadcast && (brcast_num != @@ -2351,9 +2363,6 @@ static enum match_result matches(const struct itemplate *itemp, } } - if (opsizemissing) - return MERR_OPSIZEMISSING; - /* * Check operand sizes */ diff --git a/asm/parser.c b/asm/parser.c index 64d7a024..2643099b 100644 --- a/asm/parser.c +++ b/asm/parser.c @@ -1078,6 +1078,7 @@ is_expression: } } else { /* it's a register */ opflags_t rs; + uint64_t regset_size = 0; if (value->type >= EXPR_SIMPLE || value->value != 1) { nasm_error(ERR_NONFATAL, "invalid operand type"); @@ -1085,13 +1086,32 @@ is_expression: } /* - * check that its only 1 register, not an expression... + * We do not allow any kind of expression, except for + * reg+value in which case it is a register set. */ - for (i = 1; value[i].type; i++) - if (value[i].value) { + for (i = 1; value[i].type; i++) { + if (!value[i].value) + continue; + + switch (value[i].type) { + case EXPR_SIMPLE: + if (!regset_size) { + regset_size = value[i].value + 1; + break; + } + /* fallthrough */ + default: nasm_error(ERR_NONFATAL, "invalid operand type"); goto fail; } + } + + if ((regset_size & (regset_size - 1)) || + regset_size >= (UINT64_C(1) << REGSET_BITS)) { + nasm_error(ERR_NONFATAL | ERR_PASS2, + "invalid register set size"); + regset_size = 0; + } /* clear overrides, except TO which applies to FPU regs */ if (op->type & ~TO) { @@ -1100,12 +1120,14 @@ is_expression: * is different from the register size */ rs = op->type & SIZE_MASK; - } else + } else { rs = 0; + } op->type &= TO; op->type |= REGISTER; op->type |= nasm_reg_flags[value->type]; + op->type |= (regset_size >> 1) << REGSET_SHIFT; op->decoflags |= brace_flags; op->basereg = value->type; diff --git a/disasm/disasm.c b/disasm/disasm.c index a75d839e..fa52d30f 100644 --- a/disasm/disasm.c +++ b/disasm/disasm.c @@ -1431,6 +1431,9 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, slen += snprintf(output + slen, outbufsize - slen, "to "); slen += snprintf(output + slen, outbufsize - slen, "%s", nasm_reg_names[reg-EXPR_REG_START]); + if (t & REGSET_MASK) + slen += snprintf(output + slen, outbufsize - slen, "+%d", + (int)((t & REGSET_MASK) >> (REGSET_SHIFT-1))-1); if (is_evex && deco) slen += append_evex_reg_deco(output + slen, outbufsize - slen, deco, ins.evex_p); diff --git a/include/opflags.h b/include/opflags.h index ef2838c1..469e2b91 100644 --- a/include/opflags.h +++ b/include/opflags.h @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * * - * Copyright 1996-2013 The NASM Authors - All Rights Reserved + * Copyright 1996-2018 The NASM Authors - All Rights Reserved * See the file AUTHORS included with the NASM distribution for * the specific copyright holders. * @@ -117,6 +117,16 @@ #define SIZE_MASK OP_GENMASK(SIZE_BITS, SIZE_SHIFT) #define GEN_SIZE(bit) OP_GENBIT(bit, SIZE_SHIFT) +/* + * Register set count + * + * Bits: 47 - 43 + */ +#define REGSET_SHIFT (43) +#define REGSET_BITS (5) +#define REGSET_MASK OP_GENMASK(REGSET_BITS, REGSET_SHIFT) +#define GEN_REGSET(bit) OP_GENBIT(bit, REGSET_SHIFT) + /* * Bits distribution (counted from 0) * @@ -131,6 +141,7 @@ * .......................................11111111................. subclasses * ................................1111111......................... specials * .....................11111111111................................ sizes + * ................11111........................................... regset count */ #define REGISTER GEN_OPTYPE(0) /* register number in 'basereg' */ @@ -268,4 +279,11 @@ #define ZMM0 (GEN_SUBCLASS(1) | GEN_SUBCLASS(6) | ZMMREG) /* ZMM register zero */ #define ZMM_L16 ( GEN_SUBCLASS(6) | ZMMREG) /* ZMM register 0 ~ 15 */ +/* Register set sizes */ +#define RS2 GEN_REGSET(0) +#define RS4 GEN_REGSET(1) +#define RS8 GEN_REGSET(2) +#define RS16 GEN_REGSET(3) +#define RS32 GEN_REGSET(4) + #endif /* NASM_OPFLAGS_H */ diff --git a/test/v4.asm b/test/v4.asm new file mode 100644 index 00000000..a64d3c66 --- /dev/null +++ b/test/v4.asm @@ -0,0 +1,12 @@ + bits 64 + v4fmaddps zmm0,zmm1+3,[rax] + v4fnmaddps zmm2,zmm3,[rax] + v4fmaddss zmm4,zmm5+3,[rax] + v4fnmaddss zmm6,zmm7+3,[rax] + + v4dpwssds zmm8,zmm9,[rax] + v4dpwssd zmm10,zmm11+3,[rax] + v4dpwssd zmm10+0,zmm11+3,[rax] +; v4dpwssd zmm10+1,zmm11+3,[rax] +; v4dpwssd zmm10,zmm11+4,[rax] +; v4dpwssd zmm10,zmm11+7,[rax] diff --git a/x86/insns.dat b/x86/insns.dat index 22af9f5f..af454efc 100644 --- a/x86/insns.dat +++ b/x86/insns.dat @@ -5333,14 +5333,14 @@ VPSHUFBITQMB kreg|mask,ymmreg,ymmrm256 [rvm:fvm: evex.nds.256.66.0f38.w0 8f /r VPSHUFBITQMB kreg|mask,zmmreg,zmmrm512 [rvm:fvm: evex.nds.512.66.0f38.w0 8f /r] AVX512BITALG,FUTURE ;# AVX512 4-iteration Multiply-Add -V4FMADDPS zmmreg|mask|z,zmmreg,mem128 [rvm:m128:evex.dds.512.f2.0f38.w0 9a /r] AVX5124FMAPS,FUTURE -V4FNMADDPS zmmreg|mask|z,zmmreg,mem128 [rvm:m128:evex.dds.512.f2.0f38.w0 9a /r] AVX5124FMAPS,FUTURE -V4FMADDSS zmmreg|mask|z,zmmreg,mem128 [rvm:m128:evex.dds.512.f2.0f38.w0 9b /r] AVX5124FMAPS,FUTURE -V4FNMADDSS zmmreg|mask|z,zmmreg,mem128 [rvm:m128:evex.dds.512.f2.0f38.w0 9b /r] AVX5124FMAPS,FUTURE +V4FMADDPS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 9a /r] AVX5124FMAPS,FUTURE,SO +V4FNMADDPS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 9a /r] AVX5124FMAPS,FUTURE,SO +V4FMADDSS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 9b /r] AVX5124FMAPS,FUTURE,SO +V4FNMADDSS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 9b /r] AVX5124FMAPS,FUTURE,SO ;# AVX512 4-iteration Dot Product -V4DPWSSDS zmmreg|mask|z,zmmreg,mem128 [rvm:m128:evex.dds.512.f2.0f38.w0 53 /r] AVX5124VNNIW,FUTURE -V4DPWSSD zmmreg|mask|z,zmmreg,mem128 [rvm:m128:evex.dds.512.f2.0f38.w0 52 /r] AVX5124VNNIW,FUTURE +V4DPWSSDS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 53 /r] AVX5124VNNIW,FUTURE,SO +V4DPWSSD zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 52 /r] AVX5124VNNIW,FUTURE,SO ;# Systematic names for the hinting nop instructions ; These should be last in the file From 01192c0c4e1b03c34baaf559e154689bf28df596 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 25 Jun 2018 17:17:02 -0700 Subject: [PATCH 32/83] NASM 2.14rc9 --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 696c44e7..ac50a64a 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.14rc8 +2.14rc9 From bac9023d1c3b9e5dbd18da43cea507c0055c9e97 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 25 Jun 2018 17:22:41 -0700 Subject: [PATCH 33/83] insns.dat: fix the opcodes for the V4FNM* instructions The two V4FNM* instructions had the wrong opcodes. Signed-off-by: H. Peter Anvin (Intel) --- x86/insns.dat | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x86/insns.dat b/x86/insns.dat index af454efc..0becfbc9 100644 --- a/x86/insns.dat +++ b/x86/insns.dat @@ -5334,9 +5334,9 @@ VPSHUFBITQMB kreg|mask,zmmreg,zmmrm512 [rvm:fvm: evex.nds.512.66.0f38.w0 8f /r ;# AVX512 4-iteration Multiply-Add V4FMADDPS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 9a /r] AVX5124FMAPS,FUTURE,SO -V4FNMADDPS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 9a /r] AVX5124FMAPS,FUTURE,SO +V4FNMADDPS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 aa /r] AVX5124FMAPS,FUTURE,SO V4FMADDSS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 9b /r] AVX5124FMAPS,FUTURE,SO -V4FNMADDSS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 9b /r] AVX5124FMAPS,FUTURE,SO +V4FNMADDSS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 ab /r] AVX5124FMAPS,FUTURE,SO ;# AVX512 4-iteration Dot Product V4DPWSSDS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 53 /r] AVX5124VNNIW,FUTURE,SO From 717d87831497fb0f747f03f0253cc2808d37d17d Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 25 Jun 2018 17:24:10 -0700 Subject: [PATCH 34/83] NASM 2.14rc10 --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index ac50a64a..f1912f12 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.14rc9 +2.14rc10 From 70c09f0aac79167a68e51b78b0d4f0061cb79f25 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Mon, 25 Jun 2018 18:06:40 -0700 Subject: [PATCH 35/83] insns.dat: V4F(N)MADDSS are .lig not .512 These instructions ignore vector length. Signed-off-by: H. Peter Anvin (Intel) --- x86/insns.dat | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x86/insns.dat b/x86/insns.dat index 0becfbc9..01d82dc6 100644 --- a/x86/insns.dat +++ b/x86/insns.dat @@ -5335,8 +5335,8 @@ VPSHUFBITQMB kreg|mask,zmmreg,zmmrm512 [rvm:fvm: evex.nds.512.66.0f38.w0 8f /r ;# AVX512 4-iteration Multiply-Add V4FMADDPS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 9a /r] AVX5124FMAPS,FUTURE,SO V4FNMADDPS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 aa /r] AVX5124FMAPS,FUTURE,SO -V4FMADDSS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 9b /r] AVX5124FMAPS,FUTURE,SO -V4FNMADDSS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 ab /r] AVX5124FMAPS,FUTURE,SO +V4FMADDSS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.lig.f2.0f38.w0 9b /r] AVX5124FMAPS,FUTURE,SO +V4FNMADDSS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.lig.f2.0f38.w0 ab /r] AVX5124FMAPS,FUTURE,SO ;# AVX512 4-iteration Dot Product V4DPWSSDS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 53 /r] AVX5124VNNIW,FUTURE,SO From d558598ebe15279f346f748e8581de24ca63a0c1 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Mon, 25 Jun 2018 18:19:15 -0700 Subject: [PATCH 36/83] doc: add a few more updates In particular, document the new behavior of EXTERN, GLOBAL and COMMON. Signed-off-by: H. Peter Anvin (Intel) --- doc/changes.src | 24 ++++++++++++------------ doc/nasmdoc.src | 20 ++++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/doc/changes.src b/doc/changes.src index 7c272e0a..8c2d7f18 100644 --- a/doc/changes.src +++ b/doc/changes.src @@ -11,12 +11,12 @@ since 2007. \b Fixed \c{subsections_via_symbols} for \c{macho} object format. -\b Support to mangle labels based on the types through \c{%pragma}. See -\k{mangling}. - \b Added the \c{--gprefix}, \c{--gpostfix}, \c{--lprefix}, and \c{--lpostfix} command line options, to allow command line base symbol -mangling. See \k{opt-pfix}. +renaming. See \k{opt-pfix}. + +\b Allow label renaming to be specified by \c{%pragma} in addition to +from the command line. See \k{mangling}. \b Supported generic \c{%pragma} namespaces, \c{output} and \c{debug}. See \k{gen-namespace}. @@ -34,6 +34,13 @@ Instruction) instructions. \b Added the \c{STATIC} directive for local symbols that should be renamed using global-symbol rules. See \k{static}. +\b Allow a symbol to be defined as \c{EXTERN} and then later +overridden as \c{GLOBAL} or \c{COMMON}. Furthermore, a symbol declared +\c{EXTERN} and then defined will be treated as \c{GLOBAL}. See \k{extern}. + +\b The \c{GLOBAL} directive no longer is required to precede the +definition of the symbol. + \b Support \c{private_extern} as \c{macho} specific extension to the \c{GLOBAL} directive. See \k{macho-pext}. @@ -42,14 +49,7 @@ renamed using global-symbol rules. See \k{static}. \b Added the \c{--limit-X} command line option to set execution limits. See \k{opt-limit}. -\b Fixed \c{CPU} directive case insensitive - -\b Fixed modules name for \c{ELF}, \c{IEEE}, \c{macho}, \c{obj} output format - -\b Fixed to build \c{rdoff} tool and resolve to handle dependencies correctly -with \c{Microsoft Visual Studio} - -\b Fixed \c{Codeview} version number to be aligned with \c{MASM}. +\b Updated the \c{Codeview} version number to be aligned with \c{MASM}. \b Added the \c{--keep-all} command line option to preserve output files. See \k{opt-keep-all}. diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src index b0db9d59..c2e80a8f 100644 --- a/doc/nasmdoc.src +++ b/doc/nasmdoc.src @@ -4604,8 +4604,12 @@ only in that it can take only one argument at a time: the support for multiple arguments is implemented at the preprocessor level. You can declare the same variable as \c{EXTERN} more than once: NASM -will quietly ignore the second and later redeclarations. You can't -declare a variable as \c{EXTERN} as well as something else, though. +will quietly ignore the second and later redeclarations. + +If a variable is declared both \c{GLOBAL} and \c{EXTERN}, or if it is +declared as \c{EXTERN} and then defined, it will be treated as +\c{GLOBAL}. If a variable is declared both as \c{COMMON} and +\c{EXTERN}, it will be treated as \c{COMMON}. \H{global} \i\c{GLOBAL}: \i{Exporting Symbols} to Other Modules @@ -4616,9 +4620,6 @@ linker errors, some other module must actually \e{define} the symbol and declare it as \c{GLOBAL}. Some assemblers use the name \i\c{PUBLIC} for this purpose. -The \c{GLOBAL} directive applying to a symbol must appear \e{before} -the definition of the symbol. - \c{GLOBAL} uses the same syntax as \c{EXTERN}, except that it must refer to symbols which \e{are} defined in the same module as the \c{GLOBAL} directive. For example: @@ -4673,11 +4674,10 @@ only one argument at a time. \H{static} \i\c{STATIC}: Local Symbols within Modules -Opposite to \c{EXTERN} and \c{GLOBAL}, \c{STATIC} is local symbol, -but should be named according to the global mangling rules (named -by analogy with the C keyword "static" as applied to the functions). -And like \c{GLOBAL} directive, the directive applying to a symbol -should be \i{before} the definition of the symbol. For example: +Opposite to \c{EXTERN} and \c{GLOBAL}, \c{STATIC} is local symbol, but +should be named according to the global mangling rules (named by +analogy with the C keyword \c{static} as applied to functions or +global variables). \c static foo \c foo: From 8df822f79f9e01736ccecd8bf5f8cdc4aaa90b59 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Mon, 25 Jun 2018 23:09:38 -0700 Subject: [PATCH 37/83] insns.dat: add Intel Software Guard Extensions (SGX) instructions Add SGX instructions ENCLS, ENCLU, ENCLV. Bug report: https://bugzilla.nasm.us/show_bug.cgi?id=3392492 Reported-by: ff_ff Signed-off-by: H. Peter Anvin (Intel) --- x86/insns-iflags.ph | 1 + x86/insns.dat | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/x86/insns-iflags.ph b/x86/insns-iflags.ph index 1042f0f5..c5311c6c 100644 --- a/x86/insns-iflags.ph +++ b/x86/insns-iflags.ph @@ -150,6 +150,7 @@ my %insns_flag_bit = ( "AVX512VPOPCNTDQ" => [$f++, "AVX-512 VPOPCNTD/VPOPCNTQ"], "AVX5124FMAPS" => [$f++, "AVX-512 4-iteration multiply-add"], "AVX5124VNNIW" => [$f++, "AVX-512 4-iteration dot product"], + "SGX" => [$f++, "Intel Software Guard Extensions (SGX)"], # Put these last "OBSOLETE" => [$f++, "Instruction removed from architecture"], diff --git a/x86/insns.dat b/x86/insns.dat index 01d82dc6..e9e45567 100644 --- a/x86/insns.dat +++ b/x86/insns.dat @@ -5342,6 +5342,11 @@ V4FNMADDSS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.lig.f2.0f38.w0 ab / V4DPWSSDS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 53 /r] AVX5124VNNIW,FUTURE,SO V4DPWSSD zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 52 /r] AVX5124VNNIW,FUTURE,SO +;# Intel Software Guard Extensions (SGX) +ENCLS void [ np 0f 01 cf] SGX,FUTURE +ENCLU void [ np 0f 01 d7] SGX,FUTURE +ENCLV void [ np 0f 01 c0] SGX,FUTURE + ;# Systematic names for the hinting nop instructions ; These should be last in the file HINT_NOP0 rm16 [m: o16 0f 18 /0] P6,UNDOC From f388b4d8626186cf48ab9686fd75383045020405 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Mon, 25 Jun 2018 23:11:46 -0700 Subject: [PATCH 38/83] NASM 2.14rc11 --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index f1912f12..75eba9a1 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.14rc10 +2.14rc11 From 58a275c3e917c083b4b165c53cce47dc830492b7 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Mon, 25 Jun 2018 23:13:59 -0700 Subject: [PATCH 39/83] doc/rdsrc.pl: fix unescaped brace The latest version of Perl complains about an unescaped brace in a regexp and states that it will be a fatal error in Perl 5.30. Fix it now before it becomes a problem. Signed-off-by: H. Peter Anvin (Intel) --- doc/rdsrc.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/rdsrc.pl b/doc/rdsrc.pl index 1ca71681..447bb9d4 100644 --- a/doc/rdsrc.pl +++ b/doc/rdsrc.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl ## -------------------------------------------------------------------------- ## -## Copyright 1996-2017 The NASM Authors - All Rights Reserved +## Copyright 1996-2018 The NASM Authors - All Rights Reserved ## See the file AUTHORS included with the NASM distribution for ## the specific copyright holders. ## @@ -325,7 +325,7 @@ sub got_para { $snum = 0; $xref = "section-$cnum.$hnum"; $pflags = "head $cnum.$hnum :$xref"; - die "badly formatted heading: $_\n" if !/^\\[HP]{([^\}]*)}\s*(.*)$/; + die "badly formatted heading: $_\n" if !/^\\[HP]\{([^\}]*)\}\s*(.*)$/; $refs{$1} = "section $cnum.$hnum"; $node = "Section $cnum.$hnum"; &add_item($node, 2); From 12810fac9294cd205f3d7a4a1ce9fab480e42f89 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Wed, 27 Jun 2018 20:17:33 -0700 Subject: [PATCH 40/83] nasm.c: min 2 optimization passes, don't re-run pass 1 We may not even have the most basic stabilization done unless we run at least two optimization passes, e.g. in the case of subsections. However, we cannot run more than one stabilization pass (pass0 == 1); for one thing we'll call ofmt->symdef() multiple times on the same symbol, which is not allowed. If we haven't achieved stability by the time we decide to run a stabilization pass, plod on and hope for the best. Signed-off-by: H. Peter Anvin (Intel) --- asm/nasm.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/asm/nasm.c b/asm/nasm.c index f9bd3db0..5290b078 100644 --- a/asm/nasm.c +++ b/asm/nasm.c @@ -1620,7 +1620,14 @@ static void assemble_file(const char *fname, StrList **depend_ptr) if (pass1 == 1) preproc->cleanup(1); - if ((passn > 1 && !global_offset_changed) || pass0 == 2) { + /* + * Always run at least two optimization passes (pass0 == 0); + * things like subsections will fail miserably without that. + * Once we commit to a stabilization pass (pass0 == 1), we can't + * go back, and if something goes bad, we can only hope + * that we don't end up with a phase error at the end. + */ + if ((passn > 1 && !global_offset_changed) || pass0 > 0) { pass0++; } else if (global_offset_changed && global_offset_changed < prev_offset_changed) { From d644119ded5aa963e334ec035f782c0b244d855c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Wed, 27 Jun 2018 20:20:21 -0700 Subject: [PATCH 41/83] subsections: don't lose the offset in the parent section We don't want to lose the offset into the parent section when we create a subsection, at least not for the MachO backend which is currently the only user of subsections. Allow ofmt->herelabel() to set a flag to copy the section offset from the previous section. Signed-off-by: H. Peter Anvin (Intel) --- asm/labels.c | 12 ++++++++++-- include/nasm.h | 7 ++++++- output/outdbg.c | 7 +++++-- output/outmacho.c | 8 +++++--- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/asm/labels.c b/asm/labels.c index 93a687ea..fbc4396b 100644 --- a/asm/labels.c +++ b/asm/labels.c @@ -351,15 +351,23 @@ handle_herelabel(union label *lptr, int32_t *segment, int64_t *offset) if (oldseg == location.segment && *offset == location.offset) { /* This label is defined at this location */ int32_t newseg; + bool copyoffset = false; nasm_assert(lptr->defn.mangled); newseg = ofmt->herelabel(lptr->defn.mangled, lptr->defn.type, - oldseg, &lptr->defn.subsection); + oldseg, &lptr->defn.subsection, ©offset); if (likely(newseg == oldseg)) return; *segment = newseg; - *offset = switch_segment(newseg); + if (copyoffset) { + /* Maintain the offset from the old to the new segment */ + switch_segment(newseg); + location.offset = *offset; + } else { + /* Keep a separate offset for the new segment */ + *offset = switch_segment(newseg); + } } } diff --git a/include/nasm.h b/include/nasm.h index 9eae9b8b..b9f730c8 100644 --- a/include/nasm.h +++ b/include/nasm.h @@ -911,9 +911,14 @@ struct ofmt { * The offset isn't passed; and may not be stable at this point. * The subsection number is a field available for use by the * backend. It is initialized to NO_SEG. + * + * If "copyoffset" is set by the backend then the offset is + * copied from the previous segment, otherwise the new segment + * is treated as a new segment the normal way. */ int32_t (*herelabel)(const char *name, enum label_type type, - int32_t seg, int32_t *subsection); + int32_t seg, int32_t *subsection, + bool *copyoffset); /* * This procedure is called to modify section alignment, diff --git a/output/outdbg.c b/output/outdbg.c index a28e85f7..debe30f7 100644 --- a/output/outdbg.c +++ b/output/outdbg.c @@ -137,14 +137,17 @@ static int32_t dbg_section_names(char *name, int pass, int *bits) } static int32_t dbg_herelabel(const char *name, enum label_type type, - int32_t oldseg, int32_t *subsection) + int32_t oldseg, int32_t *subsection, + bool *copyoffset) { int32_t newseg = oldseg; if (subsections_via_symbols && type != LBL_LOCAL) { newseg = *subsection; - if (newseg == NO_SEG) + if (newseg == NO_SEG) { newseg = *subsection = seg_alloc(); + *copyoffset = true; /* Minic MachO for now */ + } } fprintf(ofile, "herelabel %s type %d (seg %08x) -> %08x\n", name, type, oldseg, newseg); diff --git a/output/outmacho.c b/output/outmacho.c index 75650b47..93b4768e 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -1018,7 +1018,8 @@ static int32_t macho_section(char *name, int pass, int *bits) } static int32_t macho_herelabel(const char *name, enum label_type type, - int32_t section, int32_t *subsection) + int32_t section, int32_t *subsection, + bool *copyoffset) { struct section *s; int32_t subsec; @@ -1043,6 +1044,7 @@ static int32_t macho_herelabel(const char *name, enum label_type type, } s->subsection = subsec; + *copyoffset = true; /* Maintain previous offset */ return subsec; } @@ -1055,8 +1057,8 @@ static void macho_symdef(char *name, int32_t section, int64_t offset, #if defined(DEBUG) && DEBUG>2 nasm_error(ERR_DEBUG, - " macho_symdef: %s, sec=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n", - name, section, offset, is_global, special); + " macho_symdef: %s, pass0=%d, passn=%"PRId64", sec=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n", + name, pass0, passn, section, offset, is_global, special); #endif if (is_global == 3) { From b28ff3a51fbcd2fe7b6074f7553b439b014acb7b Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Wed, 27 Jun 2018 20:25:52 -0700 Subject: [PATCH 42/83] NASM 2.14rc12 --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 75eba9a1..8416f43e 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.14rc11 +2.14rc12 From b45c03ab429ae417ed77232750d2d8ac2666aacf Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Wed, 27 Jun 2018 21:03:38 -0700 Subject: [PATCH 43/83] asm: add a default-off warning for phase error in pass 1 Add a default-off warning for phase error in pass 1. This is default off because of the lateness in the release cycle, but cases where we have such instability should be investigated further. For now, the warning is here so we can debug these problems in the field. Signed-off-by: H. Peter Anvin (Intel) --- asm/error.c | 1 + asm/nasm.c | 20 +++++++++++++++++--- include/error.h | 3 ++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/asm/error.c b/asm/error.c index 3fdaa027..73db7443 100644 --- a/asm/error.c +++ b/asm/error.c @@ -69,6 +69,7 @@ const struct warning warnings[ERR_WARN_ALL+1] = { {"not-my-pragma", "%pragma not applicable to this compilation", false}, {"unknown-warning", "unknown warning in -W/-w or warning directive", false}, {"negative-rep", "regative %rep count", true}, + {"phase", "phase error during stabilization", false}, /* THIS ENTRY MUST COME LAST */ {"all", "all possible warnings", false} diff --git a/asm/nasm.c b/asm/nasm.c index 5290b078..55e4a8cf 100644 --- a/asm/nasm.c +++ b/asm/nasm.c @@ -1613,9 +1613,23 @@ static void assemble_file(const char *fname, StrList **depend_ptr) nasm_free(line); } /* end while (line = preproc->getline... */ - if (pass0 == 2 && global_offset_changed && !terminate_after_phase) - nasm_error(ERR_NONFATAL, - "phase error detected at end of assembly."); + if (global_offset_changed && !terminate_after_phase) { + switch (pass0) { + case 1: + nasm_error(ERR_WARNING|ERR_WARN_PHASE, + "phase error during stabilization pass, hoping for the best"); + break; + + case 2: + nasm_error(ERR_NONFATAL, + "phase error during code generation pass"); + break; + + default: + /* This is normal, we'll keep going... */ + break; + } + } if (pass1 == 1) preproc->cleanup(1); diff --git a/include/error.h b/include/error.h index 83b28da0..139400db 100644 --- a/include/error.h +++ b/include/error.h @@ -113,9 +113,10 @@ static inline vefunc nasm_set_verror(vefunc ve) #define ERR_WARN_NOTMY_PRAGMA WARN(19) /* pragma inapplicable */ #define ERR_WARN_UNK_WARNING WARN(20) /* unknown warning */ #define ERR_WARN_NEG_REP WARN(21) /* negative repeat count */ +#define ERR_WARN_PHASE WARN(22) /* phase error in pass 1 */ /* The "all" warning acts as a global switch, it must come last */ -#define ERR_WARN_ALL 22 /* Do not use WARN() here */ +#define ERR_WARN_ALL 23 /* Do not use WARN() here */ struct warning { const char *name; From 94acb7b5d0774eb4a3eb6a915144553b85104cbf Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Wed, 27 Jun 2018 21:05:18 -0700 Subject: [PATCH 44/83] NASM 2.14rc13 --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 8416f43e..11e0d1ad 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.14rc12 +2.14rc13 From e8ceba5979c011ee56214944bc68e2dfdc5824f0 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Thu, 28 Jun 2018 02:20:11 -0700 Subject: [PATCH 45/83] assemble: defer MERR_OPSIZEMISSING In order for the machinery that deduces memory operand sizes when they are not provided to work correctly, we need to make sure that MERR_OPSIZEMISSING is only issued by matches() as the last resort; that way all other error conditions will have been filtered out and we know at the very end if we have exactly one option left. This is a partial revert of cd26fccab48bc35465e68d44a7432d1b1cca4d7e, but does not affect the functionality introduced by that patch. Reported-by: Cyrill Gorcunov Signed-off-by: H. Peter Anvin (Intel) --- asm/assemble.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/asm/assemble.c b/asm/assemble.c index 7196f911..5dd0d476 100644 --- a/asm/assemble.c +++ b/asm/assemble.c @@ -2170,6 +2170,7 @@ static enum match_result matches(const struct itemplate *itemp, insn *instruction, int bits) { opflags_t size[MAX_OPERANDS], asize; + bool opsizemissing = false; int i, oprs; /* @@ -2347,7 +2348,7 @@ static enum match_result matches(const struct itemplate *itemp, * so "missing operand size" for a register should be * considered a wildcard match rather than an error. */ - return MERR_OPSIZEMISSING; + opsizemissing = true; } } else if (is_broadcast && (brcast_num != @@ -2363,6 +2364,9 @@ static enum match_result matches(const struct itemplate *itemp, } } + if (opsizemissing) + return MERR_OPSIZEMISSING; + /* * Check operand sizes */ From 5ce549c354d37ed225f2eff17fedcc04903a6530 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Thu, 28 Jun 2018 02:26:09 -0700 Subject: [PATCH 46/83] NASM 2.14rc14 --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 11e0d1ad..a751f7d8 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.14rc13 +2.14rc14 From a8e3d6a83681a757c4123289b517cf68acd332ee Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 30 Jun 2018 20:02:24 +0300 Subject: [PATCH 47/83] labels: Shrink declare_label No need to pass unused 'created', find_label can handle nil here. Signed-off-by: Cyrill Gorcunov --- asm/labels.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/asm/labels.c b/asm/labels.c index fbc4396b..ab27a614 100644 --- a/asm/labels.c +++ b/asm/labels.c @@ -417,10 +417,7 @@ static bool declare_label_lptr(union label *lptr, bool declare_label(const char *label, enum label_type type, const char *special) { - union label *lptr; - bool created; - - lptr = find_label(label, true, &created); + union label *lptr = find_label(label, true, NULL); return declare_label_lptr(lptr, type, special); } From 70d429676bd5db1a5d437ee6f796fd4f0e122434 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sun, 1 Jul 2018 01:59:07 +0300 Subject: [PATCH 48/83] labels: Add missing backend type for extern symbols Typo in 98578071b9d71ecaa2344dd9c185237c1765041e https://bugzilla.nasm.us/show_bug.cgi?id=3392494 Signed-off-by: Cyrill Gorcunov --- asm/labels.c | 1 + 1 file changed, 1 insertion(+) diff --git a/asm/labels.c b/asm/labels.c index ab27a614..aad473ec 100644 --- a/asm/labels.c +++ b/asm/labels.c @@ -175,6 +175,7 @@ static void out_symdef(union label *lptr) /* Clean up this hack... */ switch(lptr->defn.type) { case LBL_GLOBAL: + case LBL_EXTERN: backend_type = 1; backend_offset = lptr->defn.offset; break; From c7c28357c85fb0bf4105419195bc204aea0fef35 Mon Sep 17 00:00:00 2001 From: Adam Majer Date: Thu, 5 Jul 2018 17:40:24 +0200 Subject: [PATCH 49/83] asm/float.c: fix buffer underflow in float parsing When we suffer an underflow that cross limb boundaries, it is possible to end up with a stack underflow. Put in an explicit check for this case (the mantissa will be zero in this case.) https://bugzilla.nasm.us/show_bug.cgi?id=3392445 Signed-off-by: H. Peter Anvin (Intel) diff --git a/asm/float.c b/asm/float.c index dcf69fea..2965d3db 100644 --- a/asm/float.c +++ b/asm/float.c @@ -608,6 +608,8 @@ static void ieee_shr(fp_limb *mant, int i) if (offs) for (j = MANT_LIMBS-1; j >= offs; j--) mant[j] = mant[j-offs]; + } else if (MANT_LIMBS-1-offs < 0) { + j = MANT_LIMBS-1; } else { n = mant[MANT_LIMBS-1-offs] >> sr; for (j = MANT_LIMBS-1; j > offs; j--) { --- asm/float.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/asm/float.c b/asm/float.c index fd66ef38..87db8561 100644 --- a/asm/float.c +++ b/asm/float.c @@ -608,6 +608,8 @@ static void ieee_shr(fp_limb *mant, int i) if (offs) for (j = MANT_LIMBS-1; j >= offs; j--) mant[j] = mant[j-offs]; + } else if (MANT_LIMBS-1-offs < 0) { + j = MANT_LIMBS-1; } else { n = mant[MANT_LIMBS-1-offs] >> sr; for (j = MANT_LIMBS-1; j > offs; j--) { From af59af466a58c0d22a6d48f0c6cfd2b79ddde39e Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 6 Jul 2018 03:11:52 -0700 Subject: [PATCH 50/83] float: fix bogus pass flags for errors and warnings Formatting errors -- syntax errors -- are errors, no matter which pass they end up in. ERR_PASS1 is just plain crazy: if we end up with a formatting error on the code-generation pass, we are in a world of hurt. Defer warnings to the code-generation pass; that's the pass which matters value-wise, and that way we get the warnings in the list file, too. Signed-off-by: H. Peter Anvin (Intel) --- asm/float.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/asm/float.c b/asm/float.c index 87db8561..37f5585a 100644 --- a/asm/float.c +++ b/asm/float.c @@ -182,7 +182,7 @@ static int32_t read_exponent(const char *string, int32_t max) } else if (*string == '_') { /* do nothing */ } else { - nasm_error(ERR_NONFATAL|ERR_PASS1, + nasm_error(ERR_NONFATAL, "invalid character in floating-point constant %s: '%c'", "exponent", *string); return INT32_MAX; @@ -219,7 +219,7 @@ static bool ieee_flconvert(const char *string, fp_limb *mant, if (!seendot) { seendot = true; } else { - nasm_error(ERR_NONFATAL|ERR_PASS1, + nasm_error(ERR_NONFATAL, "too many periods in floating-point constant"); return false; } @@ -234,7 +234,7 @@ static bool ieee_flconvert(const char *string, fp_limb *mant, *p++ = *string - '0'; } else { if (!warned) { - nasm_error(ERR_WARNING|ERR_WARN_FL_TOOLONG|ERR_PASS1, + nasm_error(ERR_WARNING|ERR_WARN_FL_TOOLONG|ERR_PASS2, "floating-point constant significand contains " "more than %i digits", MANT_DIGITS); warned = true; @@ -247,7 +247,7 @@ static bool ieee_flconvert(const char *string, fp_limb *mant, } else if (*string == '_') { /* do nothing */ } else { - nasm_error(ERR_NONFATAL|ERR_PASS1, + nasm_error(ERR_NONFATAL|ERR_PASS2, "invalid character in floating-point constant %s: '%c'", "significand", *string); return false; @@ -533,7 +533,7 @@ static bool ieee_flconvert_bin(const char *string, int bits, if (!seendot) seendot = true; else { - nasm_error(ERR_NONFATAL|ERR_PASS1, + nasm_error(ERR_NONFATAL, "too many periods in floating-point constant"); return false; } @@ -575,7 +575,7 @@ static bool ieee_flconvert_bin(const char *string, int bits, } else if (c == '_') { /* ignore */ } else { - nasm_error(ERR_NONFATAL|ERR_PASS1, + nasm_error(ERR_NONFATAL, "floating-point constant: `%c' is invalid character", c); return false; } @@ -675,7 +675,7 @@ static int to_packed_bcd(const char *str, const char *p, int tv = -1; if (fmt != &ieee_80) { - nasm_error(ERR_NONFATAL|ERR_PASS1, + nasm_error(ERR_NONFATAL, "packed BCD requires an 80-bit format"); return 0; } @@ -685,7 +685,7 @@ static int to_packed_bcd(const char *str, const char *p, if (c >= '0' && c <= '9') { if (tv < 0) { if (n == 9) { - nasm_error(ERR_WARNING|ERR_PASS1, + nasm_error(ERR_WARNING|ERR_PASS2, "packed BCD truncated to 18 digits"); } tv = c-'0'; @@ -698,7 +698,7 @@ static int to_packed_bcd(const char *str, const char *p, } else if (c == '_') { /* do nothing */ } else { - nasm_error(ERR_NONFATAL|ERR_PASS1, + nasm_error(ERR_NONFATAL, "invalid character `%c' in packed BCD constant", c); return 0; } @@ -763,7 +763,7 @@ static int to_float(const char *str, int s, uint8_t *result, type = FL_INFINITY; break; default: - nasm_error(ERR_NONFATAL|ERR_PASS1, + nasm_error(ERR_NONFATAL, "internal error: unknown FP constant token `%s'\n", str); type = FL_QNAN; break; @@ -811,7 +811,7 @@ static int to_float(const char *str, int s, uint8_t *result, type = FL_NORMAL; } else if (exponent > 0) { if (pass0 == 1) - nasm_error(ERR_WARNING|ERR_WARN_FL_OVERFLOW|ERR_PASS1, + nasm_error(ERR_WARNING|ERR_WARN_FL_OVERFLOW|ERR_PASS2, "overflow in floating-point constant"); type = FL_INFINITY; } else { @@ -846,11 +846,11 @@ static int to_float(const char *str, int s, uint8_t *result, } else { if (daz || is_zero(mant)) { /* Flush denormals to zero */ - nasm_error(ERR_WARNING|ERR_WARN_FL_UNDERFLOW|ERR_PASS1, + nasm_error(ERR_WARNING|ERR_WARN_FL_UNDERFLOW|ERR_PASS2, "underflow in floating-point constant"); goto zero; } else { - nasm_error(ERR_WARNING|ERR_WARN_FL_DENORM|ERR_PASS1, + nasm_error(ERR_WARNING|ERR_WARN_FL_DENORM|ERR_PASS2, "denormal floating-point constant"); } } @@ -866,7 +866,7 @@ static int to_float(const char *str, int s, uint8_t *result, ieee_shr(mant, 1); exponent++; if (exponent >= (expmax << 1)-1) { - nasm_error(ERR_WARNING|ERR_WARN_FL_OVERFLOW|ERR_PASS1, + nasm_error(ERR_WARNING|ERR_WARN_FL_OVERFLOW|ERR_PASS2, "overflow in floating-point constant"); type = FL_INFINITY; goto overflow; From ccd2d5c542c27c53f8dd547c817303845c7ca6dc Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 6 Jul 2018 03:14:31 -0700 Subject: [PATCH 51/83] NASM 2.14rc15 --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index a751f7d8..65323e69 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.14rc14 +2.14rc15 From a578634b61615a4a0d5e51b1d1b046efdbd9867d Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Wed, 15 Aug 2018 23:22:21 +0300 Subject: [PATCH 52/83] optimization: Introduce new flag to turn-off selectively While configuring optimization in a level is conventional, a certain optimization tends to conflict with some pragma. For example, jump match conflicts with Mach-O's "subsections-via-symbols" macro. This configurability will workaround such conflicts. Signed-off-by: Chang S. Bae --- asm/assemble.c | 6 +++--- asm/nasm.c | 21 +++++++++++---------- asm/parser.c | 4 ++-- doc/opt_var.txt | 6 ++++-- include/nasm.h | 16 +++++++++++++++- 5 files changed, 35 insertions(+), 18 deletions(-) diff --git a/asm/assemble.c b/asm/assemble.c index 5dd0d476..30dc047e 100644 --- a/asm/assemble.c +++ b/asm/assemble.c @@ -528,9 +528,9 @@ static bool jmp_match(int32_t segment, int64_t offset, int bits, if (((c & ~1) != 0370) || (ins->oprs[0].type & STRICT)) return false; - if (!optimizing) + if (!optimizing.level || (optimizing.flag & OPTIM_DISABLE_JMP_MATCH)) return false; - if (optimizing < 0 && c == 0371) + if (optimizing.level < 0 && c == 0371) return false; isize = calcsize(segment, offset, bits, ins, temp); @@ -2188,7 +2188,7 @@ static enum match_result matches(const struct itemplate *itemp, /* * Is it legal? */ - if (!(optimizing > 0) && itemp_has(itemp, IF_OPT)) + if (!(optimizing.level > 0) && itemp_has(itemp, IF_OPT)) return MERR_INVALOP; /* diff --git a/asm/nasm.c b/asm/nasm.c index 55e4a8cf..0c1df9fb 100644 --- a/asm/nasm.c +++ b/asm/nasm.c @@ -117,7 +117,8 @@ const struct dfmt *dfmt; static FILE *error_file; /* Where to write error messages */ FILE *ofile = NULL; -int optimizing = MAX_OPTIMIZE; /* number of optimization passes to take */ +struct optimization optimizing = + { MAX_OPTIMIZE, OPTIM_ALL_ENABLED }; /* number of optimization passes to take */ static int cmd_sb = 16; /* by default */ iflag_t cpu; @@ -867,7 +868,7 @@ static bool process_arg(char *p, char *q, int pass) if (!*param) { /* Naked -O == -Ox */ - optimizing = MAX_OPTIMIZE; + optimizing.level = MAX_OPTIMIZE; } else { while (*param) { switch (*param) { @@ -875,12 +876,12 @@ static bool process_arg(char *p, char *q, int pass) case '5': case '6': case '7': case '8': case '9': opt = strtoul(param, ¶m, 10); - /* -O0 -> optimizing == -1, 0.98 behaviour */ - /* -O1 -> optimizing == 0, 0.98.09 behaviour */ + /* -O0 -> optimizing.level == -1, 0.98 behaviour */ + /* -O1 -> optimizing.level == 0, 0.98.09 behaviour */ if (opt < 2) - optimizing = opt - 1; + optimizing.level = opt - 1; else - optimizing = opt; + optimizing.level = opt; break; case 'v': @@ -891,7 +892,7 @@ static bool process_arg(char *p, char *q, int pass) case 'x': param++; - optimizing = MAX_OPTIMIZE; + optimizing.level = MAX_OPTIMIZE; break; default: @@ -901,8 +902,8 @@ static bool process_arg(char *p, char *q, int pass) break; } } - if (optimizing > MAX_OPTIMIZE) - optimizing = MAX_OPTIMIZE; + if (optimizing.level > MAX_OPTIMIZE) + optimizing.level = MAX_OPTIMIZE; } } break; @@ -1448,7 +1449,7 @@ static void assemble_file(const char *fname, StrList **depend_ptr) /* Not a directive, or even something that starts with [ */ parse_line(pass1, line, &output_ins); - if (optimizing > 0) { + if (optimizing.level > 0) { if (forwref != NULL && globallineno == forwref->lineno) { output_ins.forw_ref = true; do { diff --git a/asm/parser.c b/asm/parser.c index 2643099b..90e43372 100644 --- a/asm/parser.c +++ b/asm/parser.c @@ -1028,7 +1028,7 @@ is_expression: op->segment = NO_SEG; /* don't care again */ op->wrt = NO_SEG; /* still don't care */ - if(optimizing >= 0 && !(op->type & STRICT)) { + if(optimizing.level >= 0 && !(op->type & STRICT)) { /* Be optimistic */ op->type |= UNITY | SBYTEWORD | SBYTEDWORD | UDWORD | SDWORD; @@ -1045,7 +1045,7 @@ is_expression: if (is_simple(value)) { if (n == 1) op->type |= UNITY; - if (optimizing >= 0 && !(op->type & STRICT)) { + if (optimizing.level >= 0 && !(op->type & STRICT)) { if ((uint32_t) (n + 128) <= 255) op->type |= SBYTEDWORD; if ((uint16_t) (n + 128) <= 255) diff --git a/doc/opt_var.txt b/doc/opt_var.txt index 4482e5d8..af15c03d 100644 --- a/doc/opt_var.txt +++ b/doc/opt_var.txt @@ -6,7 +6,8 @@ GLOBAL variables: - optimizing -1 flags nasm 0.98 compatible operation; + optimizing optimization meta data (with level and flag info) + .level -1 flags nasm 0.98 compatible operation; offsets usually are explicit (short/near) no optimization passes 0 flags non-optimized assembly; forward @@ -17,7 +18,8 @@ GLOBAL variables: the actual recommended minimum setting optimization passes (2 or more, plus passes 1 and 2 will be required) - + .flag 0 allow all optimizations + 1 disallow jump match optimization pass0 0 flags an optimizer pass (multiple passes) 1 flags pass1 (define labels) diff --git a/include/nasm.h b/include/nasm.h index b9f730c8..020e363b 100644 --- a/include/nasm.h +++ b/include/nasm.h @@ -1248,11 +1248,25 @@ enum decorator_tokens { * 2 = pass 2 */ +/* + * flag to disable optimizations selectively + * this is useful to turn-off certain optimizations + */ +enum optimization_disable_flag { + OPTIM_ALL_ENABLED = 0, + OPTIM_DISABLE_JMP_MATCH = 1 +}; + +struct optimization { + int level; + int flag; +}; + extern int pass0; extern int64_t passn; /* Actual pass number */ extern bool tasm_compatible_mode; -extern int optimizing; +extern struct optimization optimizing; extern int globalbits; /* 16, 32 or 64-bit mode */ extern int globalrel; /* default to relative addressing? */ extern int globalbnd; /* default to using bnd prefix? */ From b8d153eb4dee2ac22fc09cfba99dbae48c724b88 Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Mon, 13 Aug 2018 13:50:18 -0700 Subject: [PATCH 53/83] macho: Turn off jump-match optimization for subsections_via_symbols The jump-match optimization tends to remove labels. When the "subsections_via_symbols" pragma is declared, all the labels should be emitted. Disabling the optimization (only) makes the pragma effective. It might be cleaner to extend the OFMT interface to support callback function. In this case, the reconfiguration can be done through the callback interface, rather than direct access to the global variable. Signed-off-by: Chang S. Bae --- output/outmacho.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/output/outmacho.c b/output/outmacho.c index 93b4768e..d092cf23 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -1891,6 +1891,9 @@ macho_pragma(const struct pragma *pragma) if (real) head_flags |= MH_SUBSECTIONS_VIA_SYMBOLS; + /* Jmp-match optimization conflicts */ + optimizing.flag |= OPTIM_DISABLE_JMP_MATCH; + return DIRR_OK; case D_NO_DEAD_STRIP: From 55d09bbf6f7087339277b1e3b17c134b2afb2510 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 15 Aug 2018 01:12:19 +0300 Subject: [PATCH 54/83] disasm: Fix buffer overread in ndisasm https://nvd.nist.gov/vuln/detail/CVE-2018-10254 https://sourceforge.net/p/nasm/bugs/561/ Signed-off-by: Cyrill Gorcunov --- disasm/disasm.c | 31 +++++++++++++++++++++++++++++-- disasm/disasm.h | 4 ++-- disasm/ndisasm.c | 5 ++--- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/disasm/disasm.c b/disasm/disasm.c index fa52d30f..fd3eb42a 100644 --- a/disasm/disasm.c +++ b/disasm/disasm.c @@ -49,6 +49,15 @@ #include "regdis.h" #include "disp8.h" +#define fetch_safe(_start, _ptr, _size, _need, _op) \ + do { \ + if (((_ptr) - (_start)) >= ((_size) - (_need))) \ + _op; \ + } while (0) + +#define fetch_or_return(_start, _ptr, _size, _need) \ + fetch_safe(_start, _ptr, _size, _need, return 0) + /* * Flags that go into the `segment' field of `insn' structures * during disassembly. @@ -1108,8 +1117,8 @@ static const char * const condition_name[16] = { "s", "ns", "pe", "po", "l", "nl", "ng", "g" }; -int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, - int64_t offset, int autosync, iflag_t *prefer) +int32_t disasm(uint8_t *data, int32_t data_size, char *output, int outbufsize, int segsize, + int64_t offset, int autosync, iflag_t *prefer) { const struct itemplate * const *p, * const *best_p; const struct disasm_index *ix; @@ -1144,41 +1153,52 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, switch (*data) { case 0xF2: case 0xF3: + fetch_or_return(origdata, data, data_size, 1); prefix.rep = *data++; break; case 0x9B: + fetch_or_return(origdata, data, data_size, 1); prefix.wait = *data++; break; case 0xF0: + fetch_or_return(origdata, data, data_size, 1); prefix.lock = *data++; break; case 0x2E: + fetch_or_return(origdata, data, data_size, 1); segover = "cs", prefix.seg = *data++; break; case 0x36: + fetch_or_return(origdata, data, data_size, 1); segover = "ss", prefix.seg = *data++; break; case 0x3E: + fetch_or_return(origdata, data, data_size, 1); segover = "ds", prefix.seg = *data++; break; case 0x26: + fetch_or_return(origdata, data, data_size, 1); segover = "es", prefix.seg = *data++; break; case 0x64: + fetch_or_return(origdata, data, data_size, 1); segover = "fs", prefix.seg = *data++; break; case 0x65: + fetch_or_return(origdata, data, data_size, 1); segover = "gs", prefix.seg = *data++; break; case 0x66: + fetch_or_return(origdata, data, data_size, 1); prefix.osize = (segsize == 16) ? 32 : 16; prefix.osp = *data++; break; case 0x67: + fetch_or_return(origdata, data, data_size, 1); prefix.asize = (segsize == 32) ? 16 : 32; prefix.asp = *data++; break; @@ -1186,6 +1206,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, case 0xC4: case 0xC5: if (segsize == 64 || (data[1] & 0xc0) == 0xc0) { + fetch_or_return(origdata, data, data_size, 2); prefix.vex[0] = *data++; prefix.vex[1] = *data++; @@ -1193,6 +1214,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, prefix.vex_c = RV_VEX; if (prefix.vex[0] == 0xc4) { + fetch_or_return(origdata, data, data_size, 1); prefix.vex[2] = *data++; prefix.rex |= (~prefix.vex[1] >> 5) & 7; /* REX_RXB */ prefix.rex |= (prefix.vex[2] >> (7-3)) & REX_W; @@ -1214,6 +1236,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, case 0x62: { if (segsize == 64 || ((data[1] & 0xc0) == 0xc0)) { + fetch_or_return(origdata, data, data_size, 4); data++; /* 62h EVEX prefix */ prefix.evex[0] = *data++; prefix.evex[1] = *data++; @@ -1237,6 +1260,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, case 0x8F: if ((data[1] & 030) != 0 && (segsize == 64 || (data[1] & 0xc0) == 0xc0)) { + fetch_or_return(origdata, data, data_size, 3); prefix.vex[0] = *data++; prefix.vex[1] = *data++; prefix.vex[2] = *data++; @@ -1272,6 +1296,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, case REX_P + 0xE: case REX_P + 0xF: if (segsize == 64) { + fetch_or_return(origdata, data, data_size, 1); prefix.rex = *data++; if (prefix.rex & REX_W) prefix.osize = 64; @@ -1293,8 +1318,10 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, return 0; /* No instruction table at all... */ dp = data; + fetch_or_return(origdata, dp, data_size, 1); ix += *dp++; while (ix->n == -1) { + fetch_or_return(origdata, dp, data_size, 1); ix = (const struct disasm_index *)ix->p + *dp++; } diff --git a/disasm/disasm.h b/disasm/disasm.h index 6c89293e..053474d2 100644 --- a/disasm/disasm.h +++ b/disasm/disasm.h @@ -42,8 +42,8 @@ #define INSN_MAX 32 /* one instruction can't be longer than this */ -int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, - int64_t offset, int autosync, iflag_t *prefer); +int32_t disasm(uint8_t *data, int32_t data_size, char *output, int outbufsize, int segsize, + int64_t offset, int autosync, iflag_t *prefer); int32_t eatbyte(uint8_t *data, char *output, int outbufsize, int segsize); #endif diff --git a/disasm/ndisasm.c b/disasm/ndisasm.c index a4a217db..2d0cf153 100644 --- a/disasm/ndisasm.c +++ b/disasm/ndisasm.c @@ -316,9 +316,8 @@ int main(int argc, char **argv) nextsync = next_sync(offset, &synclen); } while (p > q && (p - q >= INSN_MAX || lenread == 0)) { - lendis = - disasm((uint8_t *) q, outbuf, sizeof(outbuf), bits, - offset, autosync, &prefer); + lendis = disasm((uint8_t *)q, INSN_MAX, outbuf, sizeof(outbuf), + bits, offset, autosync, &prefer); if (!lendis || lendis > (p - q) || ((nextsync || synclen) && (uint32_t)lendis > nextsync - offset)) From 1fd4c45c96994896995c9654aa24d114777d6df5 Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Thu, 23 Aug 2018 14:13:46 -0700 Subject: [PATCH 55/83] doc: Fix macho section name for code While today's manual lists "text" as the code section name, "code" has been effectively named from d1da074. Reported-by: Signed-off-by: Chang S. Bae --- doc/nasmdoc.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src index c2e80a8f..fb140e99 100644 --- a/doc/nasmdoc.src +++ b/doc/nasmdoc.src @@ -5778,7 +5778,7 @@ comma. The following flags can also be specified: \b \c{data} - this section contains initialized data items -\b \c{text} - this section contains code exclusively +\b \c{code} - this section contains code exclusively \b \c{mixed} - this section contains both code and data From b10435f06e65df9e8fd2e1d8e8e62524e79ebec2 Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Thu, 23 Aug 2018 14:13:45 -0700 Subject: [PATCH 56/83] macho: Fix relocation type for relative direct branch Previously, X86_64_RELOC_BRANCH is only set for external relocations. Internal relocation also needs this type to be set, instead of the default (X86_64_RELOC_SIGNED) or anything. Reported-by: Signed-off-by: Chang S. Bae --- output/outmacho.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/output/outmacho.c b/output/outmacho.c index d092cf23..cb566f0d 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -559,6 +559,8 @@ static int64_t add_reloc(struct section *sect, int32_t section, /* local */ r->ext = 0; r->snum = fi; + if (reltype == RL_BRANCH) + r->type = X86_64_RELOC_BRANCH; adjust = -sect->size; } break; From 17ffc1704b31654e3378626ca2a78cc85aed8e43 Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Fri, 14 Sep 2018 18:51:56 +0000 Subject: [PATCH 57/83] obj: Fix to initialize segment list Recent labeling mechanism changes seem to bring the case, where segment() procedure is called when the segment list is empty. Now, it will simply check and initalize the segment list. Reported-by: Ozkan Sezer Signed-off-by: Chang S. Bae --- output/outobj.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/output/outobj.c b/output/outobj.c index a223c60a..beb1615c 100644 --- a/output/outobj.c +++ b/output/outobj.c @@ -1392,9 +1392,10 @@ static int32_t obj_segment(char *name, int pass, int *bits) attrs++; } - obj_idx = 1; - for (seg = seghead; seg; seg = seg->next) { - obj_idx++; + for (seg = seghead, obj_idx = 1; ; seg = seg->next, obj_idx++) { + if (!seg) + break; + if (!strcmp(seg->name, name)) { if (attrs > 0 && pass == 1) nasm_error(ERR_WARNING, "segment attributes specified on" @@ -1415,7 +1416,7 @@ static int32_t obj_segment(char *name, int pass, int *bits) seg->obj_index = obj_idx; seg->grp = NULL; any_segs = true; - seg->name = NULL; + seg->name = nasm_strdup(name); seg->currentpos = 0; seg->align = 1; /* default */ seg->use32 = false; /* default */ From 69bb052e004fb374e2e0073d7b30ab495effaa99 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 22 Sep 2018 13:46:45 +0300 Subject: [PATCH 58/83] asm: Restore showing output for preproc mode in stdout Before the commit 81b62b9f54ac8e4019a9b2ec2b95ec0faa86bd2a we've been always putting -E,-e results into stdout if no output file provded. So bring this backward compatibility back. Signed-off-by: Cyrill Gorcunov --- asm/nasm.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/asm/nasm.c b/asm/nasm.c index 0c1df9fb..acce3b83 100644 --- a/asm/nasm.c +++ b/asm/nasm.c @@ -481,9 +481,15 @@ int main(int argc, char **argv) if (ofmt->stdmac) preproc->extra_stdmac(ofmt->stdmac); - /* no output file name? */ - if (!outname) - outname = filename_set_extension(inname, ofmt->extension); + /* + * If no output file name provided and this + * is not preprocess mode, we're perfectly + * fine to output into stdout + */ + if (!outname) { + if (!(operating_mode & OP_PREPROCESS)) + outname = filename_set_extension(inname, ofmt->extension); + } /* define some macros dependent of command-line */ define_macros_late(); From da3780dc224a539df5de360e24560924e2d6eca4 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 22 Sep 2018 14:10:36 +0300 Subject: [PATCH 59/83] Fix small typo in comment Signed-off-by: Cyrill Gorcunov --- asm/nasm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/asm/nasm.c b/asm/nasm.c index acce3b83..0deec783 100644 --- a/asm/nasm.c +++ b/asm/nasm.c @@ -483,8 +483,8 @@ int main(int argc, char **argv) /* * If no output file name provided and this - * is not preprocess mode, we're perfectly - * fine to output into stdout + * is a preprocess mode, we're perfectly + * fine to output into stdout. */ if (!outname) { if (!(operating_mode & OP_PREPROCESS)) From 10c0f665709f99cb901786154ce39474aff32e38 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sun, 23 Sep 2018 23:30:44 +0300 Subject: [PATCH 60/83] doc: changes -- Add a few more bullets Signed-off-by: Cyrill Gorcunov --- doc/changes.src | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/changes.src b/doc/changes.src index 8c2d7f18..facc7432 100644 --- a/doc/changes.src +++ b/doc/changes.src @@ -9,6 +9,12 @@ since 2007. \S{cl-2.14} Version 2.14 +\b Fixed buffer underflow in float parsing. + +\b Added \c{SGX} (Intel Software Guard Extensions) instructions. + +\b Added \c{+n} syntax for multiple contiguous registers. + \b Fixed \c{subsections_via_symbols} for \c{macho} object format. \b Added the \c{--gprefix}, \c{--gpostfix}, \c{--lprefix}, and From ab2c4dfff9b51b3a1a3768c5ed75f4ed870d9743 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 24 Sep 2018 18:02:22 -0700 Subject: [PATCH 61/83] pspdf.pl: GhostScript font integration seems broken with -dSAFER -dSAFER seems to break font integration on some systems. Furthermore, once given -dSAFER seems to not be possible to override, so instead of calling via the ps2pdf script, call GhostScript explicitly with the equivalent options, sans -dSAFER. Signed-off-by: H. Peter Anvin --- doc/pspdf.pl | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/doc/pspdf.pl b/doc/pspdf.pl index 23880668..ef9f2900 100755 --- a/doc/pspdf.pl +++ b/doc/pspdf.pl @@ -23,6 +23,9 @@ while ($ARGV[0] =~ /^-(.*)$/) { } } +# Ghostscript executable name. "gs" on Unix-based systems. +my $gs = 'gs'; + my ($in, $out) = @ARGV; if (!defined($out)) { @@ -70,6 +73,17 @@ sub win32_gs_help() { $ENV{'PATH'} .= ';' . $gs[0]->{'/GS_LIB'}; $ENV{'GS_FONTPATH'} .= (defined($ENV{'GS_FONTPATH'}) ? ';' : '') . $ENV{'windir'}.'\\fonts'; + + my $gsp = undef; + foreach my $p (split(/\;/, $gs[0]->{'/GS_LIB'})) { + foreach my $exe ('gswin64c.exe', 'gswin32c.exe', 'gs.exe') { + last if (defined($gsp)); + my $e = File::Spec->catpath($p, $exe); + $gsp = $e if (-f $e && -x _); + } + } + + $gs = $gsp if (defined($gsp)); } # Remove output file @@ -80,13 +94,19 @@ my $r = system('acrodist', '-n', '-q', '--nosecurity', '-o', $out, $in); exit 0 if ( !$r && -f $out ); # 2. ps2pdf (from Ghostscript) -# The -I clause helps Ghostscript pick up the Fontdir file written by findfont.ph -# GhostScript uses # rather than - to separate options and values on Windows, it seems... +# +# GhostScript uses # rather than = to separate options and values on Windows, +# it seems. Call gs directly rather than ps2pdf, because -dSAFER +# breaks font discovery on some systems, apparently. win32_gs_help(); -my $o = $win32_ok ? '#' : '-'; -my $r = system('ps2pdf', "-dOptimize${o}true", "-dEmbedAllFonts${o}true", +my $o = $win32_ok ? '#' : '='; +my $r = system($gs, "-dCompatibilityLevel${o}1.4", "-q", + "-P-", "-dNOPAUSE", "-dBATCH", "-sDEVICE${o}pdfwrite", + "-sstdout${o}%stderr", "-sOutputFile${o}${out}", + "-dOptimize${o}true", "-dEmbedAllFonts${o}true", "-dCompressPages${o}" . ($compress ? 'true' : 'false'), - "-dUseFlateCompression${o}true", $in, $out); + "-dUseFlateCompression${o}true", + "-c", ".setpdfwrite", "-f", $in); exit 0 if ( !$r && -f $out ); # 3. pstopdf (BSD/MacOS X utility) From c713b5f994cf7b29164c3b6838b91f0499591434 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 29 Sep 2018 14:30:14 +0300 Subject: [PATCH 62/83] preproc: parse_size -- Check for string provided In case if the string is nil we will have sigsegv. https://bugzilla.nasm.us/show_bug.cgi?id=3392507 Signed-off-by: Cyrill Gorcunov --- asm/preproc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/asm/preproc.c b/asm/preproc.c index 8e1e6369..b6bed9d9 100644 --- a/asm/preproc.c +++ b/asm/preproc.c @@ -2210,8 +2210,7 @@ static int parse_size(const char *str) { { "byte", "dword", "oword", "qword", "tword", "word", "yword" }; static const int sizes[] = { 0, 1, 4, 16, 8, 10, 2, 32 }; - - return sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1]; + return str ? sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1] : 0; } /* From 0bdd7f15463529f22d2bf00a3af6514019e8417a Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 1 Oct 2018 01:09:43 +0300 Subject: [PATCH 63/83] opflags: Style unification No func change. Signed-off-by: Cyrill Gorcunov --- include/opflags.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/opflags.h b/include/opflags.h index 469e2b91..8311dcf6 100644 --- a/include/opflags.h +++ b/include/opflags.h @@ -122,10 +122,10 @@ * * Bits: 47 - 43 */ -#define REGSET_SHIFT (43) -#define REGSET_BITS (5) -#define REGSET_MASK OP_GENMASK(REGSET_BITS, REGSET_SHIFT) -#define GEN_REGSET(bit) OP_GENBIT(bit, REGSET_SHIFT) +#define REGSET_SHIFT (43) +#define REGSET_BITS (5) +#define REGSET_MASK OP_GENMASK(REGSET_BITS, REGSET_SHIFT) +#define GEN_REGSET(bit) OP_GENBIT(bit, REGSET_SHIFT) /* * Bits distribution (counted from 0) @@ -280,10 +280,10 @@ #define ZMM_L16 ( GEN_SUBCLASS(6) | ZMMREG) /* ZMM register 0 ~ 15 */ /* Register set sizes */ -#define RS2 GEN_REGSET(0) -#define RS4 GEN_REGSET(1) -#define RS8 GEN_REGSET(2) -#define RS16 GEN_REGSET(3) -#define RS32 GEN_REGSET(4) +#define RS2 GEN_REGSET(0) +#define RS4 GEN_REGSET(1) +#define RS8 GEN_REGSET(2) +#define RS16 GEN_REGSET(3) +#define RS32 GEN_REGSET(4) #endif /* NASM_OPFLAGS_H */ From bffd2b7deffd9060159cd816db561ed2f89baf06 Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Mon, 8 Oct 2018 18:49:49 -0700 Subject: [PATCH 64/83] macho/sym: Record initial symbol number always The special segment may need this information for future fix-ups. Based-on-code-from: zenith432 Signed-off-by: Chang S. Bae --- output/outmacho.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/output/outmacho.c b/output/outmacho.c index cb566f0d..9fa12988 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -1123,6 +1123,9 @@ static void macho_symdef(char *name, int32_t section, int64_t offset, special_used = true; } + /* track the initially allocated symbol number for use in future fix-ups */ + sym->initial_snum = nsyms; + if (section == NO_SEG) { /* symbols in no section get absolute */ sym->type |= N_ABS; @@ -1137,9 +1140,6 @@ static void macho_symdef(char *name, int32_t section, int64_t offset, /* get the in-file index of the section the symbol was defined in */ sym->sect = s ? s->fileindex : NO_SECT; - /* track the initially allocated symbol number for use in future fix-ups */ - sym->initial_snum = nsyms; - if (!s) { /* remember symbol number of references to external ** symbols, this works because every external symbol gets From 4cbbb3940d8f1b63b8d5e7c48731830dfcb6c49a Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Mon, 8 Oct 2018 18:49:50 -0700 Subject: [PATCH 65/83] macho/reloc: Simplified relocation for REL/BRANCH It seems like the relocation for the relative reference to absolute addresses only cares external reference info. Instead of exiting, reset the external reference flag. Based-on-code-from: zenith432 Signed-off-by: Chang S. Bae --- output/outmacho.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/output/outmacho.c b/output/outmacho.c index 9fa12988..711fe31a 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -531,22 +531,8 @@ static int64_t add_reloc(struct section *sect, int32_t section, r->type = fmt.reloc_rel; r->pcrel = 1; if (section == NO_SEG) { - /* absolute - seems to produce garbage no matter what */ - nasm_error(ERR_NONFATAL, "Mach-O does not support relative " - "references to absolute addresses"); - goto bail; -#if 0 - /* This "seems" to be how it ought to work... */ - - struct symbol *sym = macho_find_sym(&absolute_sect, offset, - false, false); - if (!sym) - goto bail; - - sect->extreloc = 1; - r->snum = NO_SECT; - adjust = -sect->size; -#endif + /* may optionally be converted below by fmt.forcesym */ + r->ext = 0; } else if (fi == NO_SECT) { /* external */ sect->extreloc = 1; From e859ece3784245b1bd19f19bacc1f510f84c8d07 Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Mon, 8 Oct 2018 18:49:51 -0700 Subject: [PATCH 66/83] macho/reloc: Fixed in handling GOT/GOTLOAD/TLV relocations - Changed to search all symbols, instead of only global symbols. - Will do immediate exits when unsupported use of WRT - Fixed to mark (got)pcrel flag only for macho64 output. GOT is supported only for 64-bit. Based-on-code-from: zenith432 Signed-off-by: Chang S. Bae --- output/outmacho.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/output/outmacho.c b/output/outmacho.c index 711fe31a..368a56a4 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -569,18 +569,22 @@ static int64_t add_reloc(struct section *sect, int32_t section, goto needsym; needsym: - r->pcrel = 1; + r->pcrel = (fmt.ptrsize == 8 ? 1 : 0); if (section == NO_SEG) { nasm_error(ERR_NONFATAL, "Unsupported use of use of WRT"); + goto bail; } else if (fi == NO_SECT) { /* external */ r->snum = raa_read(extsyms, section); } else { - /* internal - does it really need to be global? */ - struct symbol *sym = macho_find_sym(s, offset, true, - reltype != RL_TLV); - if (!sym) + /* internal - GOTPCREL doesn't need to be in global */ + struct symbol *sym = macho_find_sym(s, offset, + false, /* reltype != RL_TLV */ + true); + if (!sym) { + nasm_error(ERR_NONFATAL, "Symbol for WRT not found"); goto bail; + } r->snum = sym->initial_snum; } From 625ea1ca4784f05bccab90a259c301d03f5149bb Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Mon, 8 Oct 2018 18:49:52 -0700 Subject: [PATCH 67/83] macho/reloc: Adjust SUB relocation information As SUB relocation getting deprecated, reset external reference seems to be enough. Also, print a warning message for this. Based-on-code-from: zenith432 Signed-off-by: Chang S. Bae --- output/outmacho.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/output/outmacho.c b/output/outmacho.c index 368a56a4..784ad0fe 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -551,8 +551,10 @@ static int64_t add_reloc(struct section *sect, int32_t section, } break; - case RL_SUB: - r->pcrel = 0; + case RL_SUB: /* obsolete */ + nasm_error(ERR_WARNING, "relcation with subtraction" + "becomes to be obsolete"); + r->ext = 0; r->type = X86_64_RELOC_SUBTRACTOR; break; From 960efc3ff2c8a4ecf8b968c6e485b4addd33c92f Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Mon, 8 Oct 2018 18:49:53 -0700 Subject: [PATCH 68/83] macho/reloc: Allow absolute relocation when forcing a symbol reference The (fake) section for absolute symbols is not in the linked list. So, when the section is not found from the index, now it simply points to the special section. Based-on-code-from: zenith432 Signed-off-by: Chang S. Bae --- output/outmacho.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/output/outmacho.c b/output/outmacho.c index 784ad0fe..b7bf9813 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -514,7 +514,6 @@ static int64_t add_reloc(struct section *sect, int32_t section, if (section == NO_SEG) { /* absolute (can this even happen?) */ r->ext = 0; - r->snum = NO_SECT; } else if (fi == NO_SECT) { /* external */ r->snum = raa_read(extsyms, section); @@ -593,9 +592,13 @@ static int64_t add_reloc(struct section *sect, int32_t section, break; } - /* For 64-bit Mach-O, force a symbol reference if at all possible */ - if (!r->ext && r->snum != NO_SECT && fmt.forcesym) { - struct symbol *sym = macho_find_sym(s, offset, false, false); + /* + * For 64-bit Mach-O, force a symbol reference if at all possible + * Allow for r->snum == R_ABS by searching absolute_sect + */ + if (!r->ext && fmt.forcesym) { + struct symbol *sym = macho_find_sym(s ? s : &absolute_sect, + offset, false, false); if (sym) { adjust = bytes - sym->symv[0].key; r->snum = sym->initial_snum; From f63d211bcf9a2015276682ce4a9be5960b0aaad4 Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Mon, 8 Oct 2018 18:49:54 -0700 Subject: [PATCH 69/83] macho/reloc: Fixed offset adjustment in add_reloc() If the target symbol is in the same file, add_reloc() emits an internal reloc for the target section, and the offset written is the offset in the target section. If the target symbol is external, its offset is zero (or an explicit addend), and add_reloc() emits an external reloc for the symbol. Based-on-code-from: zenith432 Signed-off-by: Chang S. Bae --- output/outmacho.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/output/outmacho.c b/output/outmacho.c index b7bf9813..d1f81803 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -495,7 +495,7 @@ static int64_t add_reloc(struct section *sect, int32_t section, r = nasm_malloc(sizeof(struct reloc)); r->addr = sect->size & ~R_SCATTERED; r->ext = 1; - adjust = bytes; + adjust = 0; /* match byte count 1, 2, 4, 8 to length codes 0, 1, 2, 3 respectively */ r->length = ilog2_32(bytes); @@ -521,7 +521,6 @@ static int64_t add_reloc(struct section *sect, int32_t section, /* local */ r->ext = 0; r->snum = fi; - adjust = -sect->size; } break; @@ -538,15 +537,12 @@ static int64_t add_reloc(struct section *sect, int32_t section, r->snum = raa_read(extsyms, section); if (reltype == RL_BRANCH) r->type = X86_64_RELOC_BRANCH; - else if (r->type == GENERIC_RELOC_VANILLA) - adjust = -sect->size; } else { /* local */ r->ext = 0; r->snum = fi; if (reltype == RL_BRANCH) r->type = X86_64_RELOC_BRANCH; - adjust = -sect->size; } break; @@ -587,6 +583,7 @@ static int64_t add_reloc(struct section *sect, int32_t section, goto bail; } + adjust -= sym->symv[0].key; r->snum = sym->initial_snum; } break; @@ -600,12 +597,15 @@ static int64_t add_reloc(struct section *sect, int32_t section, struct symbol *sym = macho_find_sym(s ? s : &absolute_sect, offset, false, false); if (sym) { - adjust = bytes - sym->symv[0].key; + adjust -= sym->symv[0].key; r->snum = sym->initial_snum; r->ext = 1; } } + if (r->pcrel) + adjust += ((r->ext && fmt.ptrsize == 8) ? bytes : -(int64_t)sect->size); + /* NeXT as puts relocs in reversed order (address-wise) into the ** files, so we do the same, doesn't seem to make much of a ** difference either way */ From 195e735a81d6b07e62d606558fb3a5cb8f0f2d4a Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Mon, 8 Oct 2018 18:49:55 -0700 Subject: [PATCH 70/83] macho/reloc: Fix macho_output() to get the offset adjustments by add_reloc() Unlike the relative relocations, OUT_ADDRESS had ignored the adjustments made by add_reloc(), and writes the offset of the target symbol in the target section. Based-on-code-from: zenith432 Signed-off-by: Chang S. Bae --- output/outmacho.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/output/outmacho.c b/output/outmacho.c index d1f81803..45f91b0d 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -705,8 +705,11 @@ static void macho_output(int32_t secto, const void *data, "Mach-O 64-bit format does not support" " 32-bit absolute addresses"); } else { - add_reloc(s, section, addr, RL_ABS, asize); + addr += add_reloc(s, section, addr, RL_ABS, asize); } + } else if (wrt == macho_tlvp_sect && fmt.ptrsize != 8 && + asize == (int) fmt.ptrsize) { + addr += add_reloc(s, section, addr, RL_TLV, asize); } else { nasm_error(ERR_NONFATAL, "Mach-O format does not support" " this use of WRT"); From 7fcf32ba3105f4eee9ac08ac21e5116835639fc2 Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Mon, 8 Oct 2018 18:49:56 -0700 Subject: [PATCH 71/83] macho/reloc: Fix addr size sensitive conditions TLVP relocation helps GOT that is 64-bit only. Based-on-code-from: zenith432 Signed-off-by: Chang S. Bae --- output/outmacho.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/output/outmacho.c b/output/outmacho.c index 45f91b0d..4ec85690 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -795,7 +795,7 @@ static void macho_output(int32_t secto, const void *data, reltype = RL_GOTLOAD; } } - } else if (wrt == macho_tlvp_sect) { + } else if (wrt == macho_tlvp_sect && fmt.ptrsize == 8) { reltype = RL_TLV; } else { nasm_error(ERR_NONFATAL, "Mach-O format does not support" From 703e5658498222c3aa77e57fefb466d264abbe58 Mon Sep 17 00:00:00 2001 From: "Chang S. Bae" Date: Mon, 8 Oct 2018 18:49:57 -0700 Subject: [PATCH 72/83] macho: Add warning message in macho_output() Based-on-code-from: zenith432 Signed-off-by: Chang S. Bae --- output/outmacho.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/output/outmacho.c b/output/outmacho.c index 4ec85690..e78623e3 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -665,6 +665,9 @@ static void macho_output(int32_t secto, const void *data, if (is_bss && type != OUT_RESERVE) { nasm_error(ERR_WARNING, "attempt to initialize memory in " "BSS section: ignored"); + /* FIXME */ + nasm_error(ERR_WARNING, "section size may be negative" + "with address symbols"); s->size += realsize(type, size); return; } From e996d28c70d45008085322b442b44a9224308548 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 13 Oct 2018 16:18:16 +0300 Subject: [PATCH 73/83] labels: Don't nil dereference if no label provided An equ without label may cause nil dereference | equ 0x100 Fixes 98578071b9d71ecaa2344dd9c185237c1765041e Signed-off-by: Cyrill Gorcunov --- asm/nasm.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/asm/nasm.c b/asm/nasm.c index 0deec783..ae90b89c 100644 --- a/asm/nasm.c +++ b/asm/nasm.c @@ -1481,13 +1481,11 @@ static void assemble_file(const char *fname, StrList **depend_ptr) /* forw_ref */ if (output_ins.opcode == I_EQU) { - if (!output_ins.label) - nasm_error(ERR_NONFATAL, - "EQU not preceded by label"); - - if (output_ins.operands == 1 && - (output_ins.oprs[0].type & IMMEDIATE) && - output_ins.oprs[0].wrt == NO_SEG) { + if (!output_ins.label) { + nasm_error(ERR_NONFATAL, "EQU not preceded by label"); + } else if (output_ins.operands == 1 && + (output_ins.oprs[0].type & IMMEDIATE) && + output_ins.oprs[0].wrt == NO_SEG) { define_label(output_ins.label, output_ins.oprs[0].segment, output_ins.oprs[0].offset, false); From 8e740c677345540985eba92462f44e4b272a7652 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 13 Oct 2018 17:18:05 +0300 Subject: [PATCH 74/83] labels: Make sure nil label is never passed We already catched a case where we've missed test for non nil label and in result got sigsegv, lets rather panic next time. Signed-off-by: Cyrill Gorcunov --- asm/labels.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/asm/labels.c b/asm/labels.c index aad473ec..c00d6e5b 100644 --- a/asm/labels.c +++ b/asm/labels.c @@ -219,6 +219,8 @@ static union label *find_label(const char *label, bool create, bool *created) char *label_str = NULL; struct hash_insert ip; + nasm_assert(label != NULL); + if (islocal(label)) label = label_str = nasm_strcat(prevlabel, label); From a28c40d54602429c2458a95a62b1fab5142ffb9e Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 13 Oct 2018 18:10:26 +0300 Subject: [PATCH 75/83] parser: Fix sigsegv on certain equ instruction parsing We should check for bounds when accessing nasm_reg_flags. Seems this bug was for long time already. https://bugzilla.nasm.us/show_bug.cgi?id=3392516 Reported-by: Jordan Zebor Signed-off-by: Cyrill Gorcunov --- asm/parser.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/asm/parser.c b/asm/parser.c index 90e43372..297af262 100644 --- a/asm/parser.c +++ b/asm/parser.c @@ -1124,6 +1124,23 @@ is_expression: rs = 0; } + /* + * Make sure we're not out of nasm_reg_flags, still + * probably this should be fixed when we're defining + * the label. + * + * An easy trigger is + * + * e equ 0x80000000:0 + * pshufw word e-0 + * + */ + if (value->type < EXPR_REG_START || + value->type > EXPR_REG_END) { + nasm_error(ERR_NONFATAL, "invalid operand type"); + goto fail; + } + op->type &= TO; op->type |= REGISTER; op->type |= nasm_reg_flags[value->type]; From a98a84b0d57d057ed7ec8eb401fd69407e709fca Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 13 Oct 2018 18:15:36 +0300 Subject: [PATCH 76/83] doc: Update changes Signed-off-by: Cyrill Gorcunov --- doc/changes.src | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/changes.src b/doc/changes.src index facc7432..80415f8a 100644 --- a/doc/changes.src +++ b/doc/changes.src @@ -9,6 +9,8 @@ since 2007. \S{cl-2.14} Version 2.14 +\b Fixed out of bound access in certain \c{EQU} parsing. + \b Fixed buffer underflow in float parsing. \b Added \c{SGX} (Intel Software Guard Extensions) instructions. From 67f2ca2b3fb4e009ef3f7885e848b99e6a81ab29 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 13 Oct 2018 19:41:01 +0300 Subject: [PATCH 77/83] preproc: Fix out of range access in expand mmacro On specially crafetd malformed input file the params might be zapped (say due to invalid syntax) so we might access out of bound having nil dereference in best case. Note the later code in this helper uses tok_isnt_ helper which already has similar check. https://bugzilla.nasm.us/show_bug.cgi?id=3392518 Reported-by: Jordan Zebor Signed-off-by: Cyrill Gorcunov --- asm/preproc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/asm/preproc.c b/asm/preproc.c index b6bed9d9..0ceb2434 100644 --- a/asm/preproc.c +++ b/asm/preproc.c @@ -3947,6 +3947,8 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last) * only first token will be passed. */ tm = mac->params[(fst + mac->rotate) % mac->nparam]; + if (!tm) + goto err; head = new_Token(NULL, tm->type, tm->text, 0); tt = &head->next, tm = tm->next; while (tok_isnt_(tm, ",")) { From 3c755dac88039b718d52ef56e8f74b5f65f3b55b Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 13 Oct 2018 22:57:30 +0300 Subject: [PATCH 78/83] opflags: Convert is_class and is_reg_class to helpers So we can test for out of bound access and make helpers safe to use. https://bugzilla.nasm.us/show_bug.cgi?id=3392447 Reported-by: Jun Signed-off-by: Cyrill Gorcunov --- include/opflags.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/include/opflags.h b/include/opflags.h index 8311dcf6..28bb236f 100644 --- a/include/opflags.h +++ b/include/opflags.h @@ -40,6 +40,7 @@ #include "compiler.h" #include "tables.h" /* for opflags_t and nasm_reg_flags[] */ +#include "regs.h" /* * Here we define the operand types. These are implemented as bit @@ -176,8 +177,17 @@ #define REG_CLASS_OPMASK GEN_REG_CLASS(8) #define REG_CLASS_BND GEN_REG_CLASS(9) -#define is_class(class, op) (!((opflags_t)(class) & ~(opflags_t)(op))) -#define is_reg_class(class, reg) is_class((class), nasm_reg_flags[(reg)]) +static inline bool is_class(opflags_t class, opflags_t op) +{ + return !(class & ~op); +} + +static inline bool is_reg_class(opflags_t class, opflags_t reg) +{ + if (reg >= EXPR_REG_START && reg <= EXPR_REG_END) + return is_class(class, nasm_reg_flags[reg]); + return false; +} #define IS_SREG(reg) is_reg_class(REG_SREG, (reg)) #define IS_FSGS(reg) is_reg_class(REG_FSGS, (reg)) From d94402d6f7f10ad1536a767c18c830ca7d0823a8 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 13 Oct 2018 23:03:24 +0300 Subject: [PATCH 79/83] doc: Update changes Signed-off-by: Cyrill Gorcunov --- doc/changes.src | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/changes.src b/doc/changes.src index 80415f8a..5852bc05 100644 --- a/doc/changes.src +++ b/doc/changes.src @@ -9,6 +9,8 @@ since 2007. \S{cl-2.14} Version 2.14 +\b Fixed out of bound access in processing of malformed segment override. + \b Fixed out of bound access in certain \c{EQU} parsing. \b Fixed buffer underflow in float parsing. From ceec0d818798aeaa75ed4907e6135b0247ed46b2 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sun, 14 Oct 2018 01:26:19 +0300 Subject: [PATCH 80/83] eval: Eliminate division by zero When doing division we should detect if the value we're divided by is not zero. Instead of is_unknown() helper we should use is_just_unknown(). https://bugzilla.nasm.us/show_bug.cgi?id=3392515 https://bugzilla.nasm.us/show_bug.cgi?id=3392473 Reported-by: Jun Reported-by: stuartly Signed-off-by: Cyrill Gorcunov --- asm/eval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asm/eval.c b/asm/eval.c index 1a6680f2..7e727a4e 100644 --- a/asm/eval.c +++ b/asm/eval.c @@ -580,7 +580,7 @@ static expr *expr5(int critical) " scalar values"); return NULL; } - if (j != '*' && !is_unknown(f) && reloc_value(f) == 0) { + if (j != '*' && !is_just_unknown(f) && reloc_value(f) == 0) { nasm_error(ERR_NONFATAL, "division by zero"); return NULL; } From 980dd658b521afe4a688c4195410c4449a8e2468 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sun, 14 Oct 2018 19:25:32 +0300 Subject: [PATCH 81/83] preproc: expand_smacro -- Fix nil dereference on error path When error happened earlier we might have a.mac already handled and set to nil. https://bugzilla.nasm.us/show_bug.cgi?id=3392508 Signed-off-by: Cyrill Gorcunov --- asm/preproc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/asm/preproc.c b/asm/preproc.c index 0ceb2434..cdf03bc1 100644 --- a/asm/preproc.c +++ b/asm/preproc.c @@ -4473,7 +4473,9 @@ again: } if (tline->type == TOK_SMAC_END) { - tline->a.mac->in_progress = false; + /* On error path it might already be dropped */ + if (tline->a.mac) + tline->a.mac->in_progress = false; tline = delete_Token(tline); } else { t = *tail = tline; From 1cbd48ad488cbbaafb7db65de2c6238f27267ec4 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sun, 14 Oct 2018 21:09:30 +0300 Subject: [PATCH 82/83] doc: Update changes Signed-off-by: Cyrill Gorcunov --- doc/changes.src | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/changes.src b/doc/changes.src index 5852bc05..b2f092c2 100644 --- a/doc/changes.src +++ b/doc/changes.src @@ -9,6 +9,10 @@ since 2007. \S{cl-2.14} Version 2.14 +\b Fixed null dereference in corrupted invalid single line macros. + +\b Fixed division by zero which may happen if source code is malformed. + \b Fixed out of bound access in processing of malformed segment override. \b Fixed out of bound access in certain \c{EQU} parsing. From 28b69e2a633a850e724f309a5ec81bac8638084a Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 15 Oct 2018 00:26:52 +0300 Subject: [PATCH 83/83] NASM 2.14rc16 --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 65323e69..258d9f0f 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.14rc15 +2.14rc16