diff --git a/.gitignore b/.gitignore index 881ebb58..afdd62cd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,15 @@ *.a *.bin +*.coff *.dbg +*.dep *.exe *.lib *.i +*.ith *.lst +*.mo32 +*.mo64 *.o *.o64 *.obj @@ -13,10 +18,14 @@ *.orig *.out *.pdb +*.rdf *.rej *.s +*.srec *.si *.swp +*.win32 +*.win64 *.xml .*swo *~ diff --git a/asm/assemble.c b/asm/assemble.c index 6d3e25ee..fc72065e 100644 --- a/asm/assemble.c +++ b/asm/assemble.c @@ -302,14 +302,6 @@ static void warn_overflow_const(int64_t data, int size) warn_overflow(size); } -static void warn_overflow_opd(const struct operand *o, int size) -{ - if (absolute_op(o)) { - if (overflow_general(o->offset, size)) - warn_overflow(size); - } -} - static void warn_overflow_out(int64_t data, int size, enum out_sign sign) { bool err; @@ -630,6 +622,9 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction) size_t blk = 0; /* Buffered I/O block size */ size_t m = 0; /* Bytes last read */ + if (!t) + goto done; + fp = nasm_open_read(fname, NF_BINARY|NF_FORMAP); if (!fp) { nasm_error(ERR_NONFATAL, "`incbin': unable to open file `%s'", @@ -1603,21 +1598,14 @@ static void gencode(struct out_data *data, insn *ins) break; case4(020): - if (opx->offset < -256 || opx->offset > 255) - nasm_error(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV, - "byte value exceeds bounds"); out_imm(data, opx, 1, OUT_WRAP); break; case4(024): - if (opx->offset < 0 || opx->offset > 255) - nasm_error(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV, - "unsigned byte value exceeds bounds"); out_imm(data, opx, 1, OUT_UNSIGNED); break; case4(030): - warn_overflow_opd(opx, 2); out_imm(data, opx, 2, OUT_WRAP); break; @@ -1626,18 +1614,15 @@ static void gencode(struct out_data *data, insn *ins) size = (opx->type & BITS16) ? 2 : 4; else size = (bits == 16) ? 2 : 4; - warn_overflow_opd(opx, size); out_imm(data, opx, size, OUT_WRAP); break; case4(040): - warn_overflow_opd(opx, 4); out_imm(data, opx, 4, OUT_WRAP); break; case4(044): size = ins->addr_size >> 3; - warn_overflow_opd(opx, size); out_imm(data, opx, size, OUT_WRAP); break; diff --git a/asm/directiv.c b/asm/directiv.c index 21f70e56..937f17af 100644 --- a/asm/directiv.c +++ b/asm/directiv.c @@ -230,7 +230,7 @@ bool process_directives(char *directive) case D_SEGMENT: /* [SEGMENT n] */ case D_SECTION: { - int sb; + int sb = globalbits; int32_t seg = ofmt->section(value, pass2, &sb); if (seg == NO_SEG) { @@ -239,6 +239,7 @@ bool process_directives(char *directive) } else { in_absolute = false; location.segment = seg; + globalbits = sb; } break; } diff --git a/asm/parser.c b/asm/parser.c index 62104e12..2ad37ceb 100644 --- a/asm/parser.c +++ b/asm/parser.c @@ -515,9 +515,8 @@ restart_parse: result->times = 1L; } else { result->times = value->value; - if (value->value < 0 && pass0 == 2) { - nasm_error(ERR_NONFATAL, "TIMES value %"PRId64" is negative", - value->value); + if (value->value < 0) { + nasm_error(ERR_NONFATAL|ERR_PASS2, "TIMES value %"PRId64" is negative", value->value); result->times = 0; } } diff --git a/asm/preproc.c b/asm/preproc.c index a8388bcb..475926d8 100644 --- a/asm/preproc.c +++ b/asm/preproc.c @@ -948,7 +948,9 @@ static Token *tokenize(char *line) case '\'': case '\"': case '`': - p = nasm_skip_string(p - 1) + 1; + p = nasm_skip_string(p - 1); + if (*p) + p++; break; default: break; @@ -1252,7 +1254,8 @@ static char *detoken(Token * tlist, bool expand_locals) int len = 0; list_for_each(t, tlist) { - if (t->type == TOK_PREPROC_ID && t->text[1] == '!') { + if (t->type == TOK_PREPROC_ID && t->text && + t->text[0] && t->text[1] == '!') { char *v; char *q = t->text; @@ -1936,9 +1939,11 @@ static bool if_condition(Token * tline, enum preproc_token ct) nasm_error(ERR_NONFATAL, "unable to parse parameter count `%s'", tline->text); - if (searching.nparam_min > searching.nparam_max) + if (searching.nparam_min > searching.nparam_max) { nasm_error(ERR_NONFATAL, "minimum parameter count exceeds maximum"); + searching.nparam_max = searching.nparam_min; + } } } if (tline && tok_is_(tline->next, "+")) { @@ -2167,6 +2172,7 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive) } if (def->nparam_min > def->nparam_max) { nasm_error(ERR_NONFATAL, "minimum parameter count exceeds maximum"); + def->nparam_max = def->nparam_min; } } } @@ -3709,6 +3715,8 @@ static int find_cc(Token * t) return -1; /* Probably a %+ without a space */ skip_white_(t); + if (!t) + return -1; if (t->type != TOK_ID) return -1; tt = t->next; @@ -3841,8 +3849,8 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m, next = next->next; } - /* No match */ - if (tok == next) + /* No match or no text to process */ + if (tok == next || len == 0) break; len += strlen(tok->text); @@ -4425,6 +4433,16 @@ again: ttt->text, 0); ptail = &pt->next; ttt = ttt->next; + if (!ttt && i > 0) { + /* + * FIXME: Need to handle more gracefully, + * exiting early on agruments analysis. + */ + nasm_error(ERR_FATAL, + "macro `%s' expects %d args", + mstart->text, + (int)paramsize[t->type - TOK_SMAC_PARAM]); + } } tline = pcopy; } else if (t->type == TOK_PREPROC_Q) { diff --git a/configure.ac b/configure.ac index 8ac4994f..7268eaaf 100644 --- a/configure.ac +++ b/configure.ac @@ -29,14 +29,19 @@ dnl to either -O3 (normal) or -O0 (for debugging) PA_ARG_DISABLED([optimization], [compile without optimization (-O0) to help debugging], [pa_optimize=-O0], [pa_optimize=-O3]) -AS_IF([test x"$pa_init_cflags" = x], - [CFLAGS=`echo "$CFLAGS" | sed -e "s/-O2/$pa_optimize/"`]) dnl Compile and link with dwarf debug PA_ARG_ENABLED([gdb], [disable optimization and compile with extra debug information for GDB debugger], - [CFLAGS=`echo "$CFLAGS" | sed -e "s/\(-O2\|-O3\)/-O0/"` - PA_ADD_CLDFLAGS([-ggdb3])]) + [pa_optimize='-O0' + PA_ADD_CFLAGS([-ggdb3]) + ]) + +AS_IF([test x"$pa_init_cflags" = x], + [CFLAGS=`echo "$CFLAGS" | sed -e "s/-O2/$pa_optimize/"`]) + +AS_IF([test x"$pa_optimize" = "x-O0"], + [PA_ADD_CFLAGS([-fno-omit-frame-pointer])]) dnl Check for library extension PA_LIBEXT @@ -206,7 +211,7 @@ PA_FUNC_ATTRIBUTE(pure) PA_FUNC_ATTRIBUTE_ERROR dnl -dnl support function sections +dnl support function sections (if available) dnl PA_ARG_ENABLED([sections], [compile with function/data section support], @@ -214,6 +219,7 @@ PA_ARG_ENABLED([sections], PA_ADD_CLDFLAGS([-fdata-sections]) PA_ADD_CLDFLAGS([-Wl,--gc-sections])], []) + dnl dnl support LTO dnl @@ -228,6 +234,15 @@ PA_ARG_ENABLED([lto], AC_CHECK_PROGS(CC_RANLIB, [${ccbase}-ranlib], [$ac_cv_prog_RANLIB]) RANLIB="$CC_RANLIB"], []) +dnl +dnl support sanitizers (if available) +dnl +PA_ARG_ENABLED([sanitizer], + [compile with sanitizers enabled], + [PA_ADD_CFLAGS([-fno-omit-frame-pointer]) + PA_ADD_CLDFLAGS([-fsanitize=address]) + PA_ADD_CLDFLAGS([-fsanitize=undefined])]) + dnl If we have gcc, add appropriate code cleanliness options PA_ADD_CFLAGS([-W]) PA_ADD_CFLAGS([-Wall]) diff --git a/include/nasmlib.h b/include/nasmlib.h index f0a670be..8ea17503 100644 --- a/include/nasmlib.h +++ b/include/nasmlib.h @@ -366,7 +366,7 @@ static inline bool const_func overflow_general(int64_t value, int bytes) sbit = (bytes << 3) - 1; vmax = ((int64_t)2 << sbit) - 1; - vmin = -((int64_t)1 << sbit); + vmin = -((int64_t)2 << sbit); return value < vmin || value > vmax; } diff --git a/macros/smartalign.mac b/macros/smartalign.mac index e5c0b99a..0f81ae87 100644 --- a/macros/smartalign.mac +++ b/macros/smartalign.mac @@ -1,6 +1,6 @@ ;; -------------------------------------------------------------------------- ;; -;; Copyright 1996-2016 The NASM Authors - All Rights Reserved +;; Copyright 1996-2017 The NASM Authors - All Rights Reserved ;; See the file AUTHORS included with the NASM distribution for ;; the specific copyright holders. ;; @@ -173,7 +173,6 @@ USE: smartalign jmp %$end ; We can't re-use %$pad here as $ will have changed! times (((%1) - (($-$$) % (%1))) % (%1)) nop -%$end: %else times (%$pad / __ALIGN_%[__BITS__]BIT_GROUP__) \ db __ALIGN_%[__BITS__]BIT_%[__ALIGN_%[__BITS__]BIT_GROUP__]B__ @@ -182,6 +181,7 @@ USE: smartalign db __ALIGN_%[__BITS__]BIT_%[%$pad]B__ %endif %endif +%$end: %pop %endif %endmacro diff --git a/output/outelf.c b/output/outelf.c index b786989d..6d0ce56f 100644 --- a/output/outelf.c +++ b/output/outelf.c @@ -3163,6 +3163,8 @@ static void dwarf_generate(void) saa_write8(pabbrev,DW_AT_frame_base); saa_write8(pabbrev,DW_FORM_data4); saa_write16(pabbrev,0); /* end of entry */ + /* Terminal zero entry */ + saa_write8(pabbrev,0); abbrevlen = saalen = pabbrev->datalen; abbrevbuf = pbuf = nasm_malloc(saalen); saa_rnbytes(pabbrev, pbuf, saalen); diff --git a/output/outmacho.c b/output/outmacho.c index d3a1d84d..4aefe3f3 100644 --- a/output/outmacho.c +++ b/output/outmacho.c @@ -288,10 +288,16 @@ static uint64_t seg_vmsize = 0; static uint32_t seg_nsects = 0; static uint64_t rel_padcnt = 0; -#define xstrncpy(xdst, xsrc) \ - memset(xdst, '\0', sizeof(xdst)); /* zero out whole buffer */ \ - strncpy(xdst, xsrc, sizeof(xdst)); /* copy over string */ \ - xdst[sizeof(xdst) - 1] = '\0'; /* proper null-termination */ +/* + * Functions for handling fixed-length zero-padded string + * fields, that may or may not be null-terminated. + */ + +/* Copy a string into a zero-padded fixed-length field */ +#define xstrncpy(xdst, xsrc) strncpy(xdst, xsrc, sizeof(xdst)) + +/* Compare a fixed-length field with a string */ +#define xstrncmp(xdst, xsrc) strncmp(xdst, xsrc, sizeof(xdst)) #define alignint32_t(x) \ ALIGN(x, sizeof(int32_t)) /* align x to int32_t boundary */ @@ -308,7 +314,7 @@ static struct section *get_section_by_name(const char *segname, struct section *s; for (s = sects; s != NULL; s = s->next) - if (!strcmp(s->segname, segname) && !strcmp(s->sectname, sectname)) + if (!xstrncmp(s->segname, segname) && !xstrncmp(s->sectname, sectname)) break; return s; @@ -806,6 +812,7 @@ static const struct sect_attribs { { "no_dead_strip", NO_TYPE|S_ATTR_NO_DEAD_STRIP }, { "live_support", NO_TYPE|S_ATTR_LIVE_SUPPORT }, { "strip_static_syms", NO_TYPE|S_ATTR_STRIP_STATIC_SYMS }, + { "debug", NO_TYPE|S_ATTR_DEBUG }, { NULL, 0 } }; @@ -848,14 +855,14 @@ static int32_t macho_section(char *name, int pass, int *bits) len = strlen(segment); if (len == 0) { nasm_error(ERR_NONFATAL, "empty segment name\n"); - } else if (len >= 16) { + } else if (len > 16) { nasm_error(ERR_NONFATAL, "segment name %s too long\n", segment); } len = strlen(section); if (len == 0) { nasm_error(ERR_NONFATAL, "empty section name\n"); - } else if (len >= 16) { + } else if (len > 16) { nasm_error(ERR_NONFATAL, "section name %s too long\n", section); } @@ -1321,8 +1328,8 @@ static uint32_t macho_write_segment (uint64_t offset) s->flags |= S_ATTR_LOC_RELOC; if (s->extreloc) s->flags |= S_ATTR_EXT_RELOC; - } else if (!strcmp(s->segname, "__DATA") && - !strcmp(s->sectname, "__const") && + } else if (!xstrncmp(s->segname, "__DATA") && + !xstrncmp(s->sectname, "__const") && !s->by_name && !get_section_by_name("__TEXT", "__const")) { /* @@ -2040,6 +2047,8 @@ static void macho_dbg_generate(void) saa_write16(p_abbrev, DW_END_default); + saa_write8(p_abbrev, 0); /* Terminal zero entry */ + saa_len = p_abbrev->datalen; p_buf = nasm_malloc(saa_len); diff --git a/test/Makefile b/test/Makefile index 7a6dfe24..ebd8c3f3 100644 --- a/test/Makefile +++ b/test/Makefile @@ -29,6 +29,9 @@ $(NASM): %.obj: %.asm $(NASMDEP) $(NASM) $(NASMOPT) -f obj -o $@ -MD $@.dep -l $*.lst $< +%.rdf: %.asm $(NASMDEP) + $(NASM) $(NASMOPT) -f rdf -o $@ -MD $@.dep -l $*.lst $< + %.od: %.obj ../misc/omfdump ../misc/omfdump $< > $@ @@ -69,7 +72,7 @@ diff: performtest.pl $(NASMDEP) $(TESTS) clean: $(RM_F) *.com *.o *.o64 *.obj *.win32 *.win64 *.exe *.lst *.bin - $(RM_F) *.dbg *.coff *.ith *.srec *.mo32 *.mo64 *.i *.dep + $(RM_F) *.dbg *.coff *.ith *.srec *.mo32 *.mo64 *.i *.dep *.rdf $(RM_RF) testresults $(RM_F) elftest elftest64 diff --git a/test/br3392411.asm b/test/br3392411.asm new file mode 100644 index 00000000..02071a88 --- /dev/null +++ b/test/br3392411.asm @@ -0,0 +1,22 @@ +bits 64 +default rel + +%use smartalign + +section .text code align=32 + +align 32 + +nop +jz LDone + +%rep 10 + nop +%endrep + +align 16 +%rep 115 + nop +%endrep + +LDone: diff --git a/test/br3392418.asm b/test/br3392418.asm new file mode 100644 index 00000000..7139870d --- /dev/null +++ b/test/br3392418.asm @@ -0,0 +1,3 @@ + section __LD,__compact_unwind data debug + + dd 0 diff --git a/test/br3392439.asm b/test/br3392439.asm new file mode 100644 index 00000000..1af47084 --- /dev/null +++ b/test/br3392439.asm @@ -0,0 +1,25 @@ +segment _TEXT class=CODE USE32 align=1 CPU=686 + +extern _entry + +start: + mov ax, 0x18 + mov ds, ax + mov es, ax + mov ss, ax + xor eax, eax + mov ax, 0x1234 + shl eax, 4 + add eax, 0x3000 + mov esp, [eax] + + call _entry + +.infloop: + hlt + jmp .infloop + + +global _ret_16 +_ret_16: + jmp dword 0x10:0x8000 diff --git a/test/br3392442.asm b/test/br3392442.asm new file mode 100644 index 00000000..e7a0511c --- /dev/null +++ b/test/br3392442.asm @@ -0,0 +1,6 @@ + ;; Bug report 3392442: invalid warning + + and byte [0], ~80h + and byte [0], 0xfff + and byte [0], -256 + and byte [0], -257 diff --git a/test/pextrw.asm b/test/pextrw.asm new file mode 100644 index 00000000..41c50b7a --- /dev/null +++ b/test/pextrw.asm @@ -0,0 +1,3 @@ + bits 64 + + pextrw rax,xmm0,0 diff --git a/test/timesneg.asm b/test/timesneg.asm new file mode 100644 index 00000000..9f16dbaa --- /dev/null +++ b/test/timesneg.asm @@ -0,0 +1,3 @@ + bits 32 + times -1 db 0 + times -1 incbin "timesneg.asm" diff --git a/x86/insns.dat b/x86/insns.dat index 1ed79f7a..b5c723b0 100644 --- a/x86/insns.dat +++ b/x86/insns.dat @@ -1703,8 +1703,10 @@ PCMPGTB xmmreg,xmmrm [rm: 66 0f 64 /r] WILLAMETTE,SSE2,SO PCMPGTW xmmreg,xmmrm [rm: 66 0f 65 /r] WILLAMETTE,SSE2,SO PCMPGTD xmmreg,xmmrm [rm: 66 0f 66 /r] WILLAMETTE,SSE2,SO PEXTRW reg32,xmmreg,imm [rmi: 66 0f c5 /r ib,u] WILLAMETTE,SSE2,SB,AR2 +PEXTRW reg64,xmmreg,imm [rmi: 66 0f c5 /r ib,u] X64,SSE2,SB,AR2,ND PINSRW xmmreg,reg16,imm [rmi: 66 0f c4 /r ib,u] WILLAMETTE,SSE2,SB,AR2 PINSRW xmmreg,reg32,imm [rmi: 66 0f c4 /r ib,u] WILLAMETTE,SSE2,SB,AR2,ND +PINSRW xmmreg,reg64,imm [rmi: 66 0f c4 /r ib,u] X64,SSE2,SB,AR2,ND PINSRW xmmreg,mem,imm [rmi: 66 0f c4 /r ib,u] WILLAMETTE,SSE2,SB,AR2 PINSRW xmmreg,mem16,imm [rmi: 66 0f c4 /r ib,u] WILLAMETTE,SSE2,SB,AR2 PMADDWD xmmreg,xmmrm [rm: 66 0f f5 /r] WILLAMETTE,SSE2,SO @@ -1957,8 +1959,8 @@ PBLENDW xmmreg,xmmrm,imm [rmi: 66 0f 3a 0e /r ib,u] SSE41 PCMPEQQ xmmreg,xmmrm [rm: 66 0f 38 29 /r] SSE41 PEXTRB reg32,xmmreg,imm [mri: 66 0f 3a 14 /r ib,u] SSE41 PEXTRB mem8,xmmreg,imm [mri: 66 0f 3a 14 /r ib,u] SSE41 -PEXTRB reg64,xmmreg,imm [mri: o64 66 0f 3a 14 /r ib,u] SSE41,X64 -PEXTRD rm32,xmmreg,imm [mri: norexw 66 0f 3a 16 /r ib,u] SSE41 +PEXTRB reg64,xmmreg,imm [mri: o64nw 66 0f 3a 14 /r ib,u] SSE41,X64 +PEXTRD rm32,xmmreg,imm [mri: norexw 66 0f 3a 16 /r ib,u] SSE41 PEXTRQ rm64,xmmreg,imm [mri: o64 66 0f 3a 16 /r ib,u] SSE41,X64 PEXTRW reg32,xmmreg,imm [mri: 66 0f 3a 15 /r ib,u] SSE41 PEXTRW mem16,xmmreg,imm [mri: 66 0f 3a 15 /r ib,u] SSE41 @@ -1967,8 +1969,8 @@ PHMINPOSUW xmmreg,xmmrm [rm: 66 0f 38 41 /r] SSE41 PINSRB xmmreg,mem,imm [rmi: 66 0f 3a 20 /r ib,u] SSE41,SB,AR2 PINSRB xmmreg,rm8,imm [rmi: nohi 66 0f 3a 20 /r ib,u] SSE41,SB,AR2 PINSRB xmmreg,reg32,imm [rmi: 66 0f 3a 20 /r ib,u] SSE41,SB,AR2 -PINSRD xmmreg,mem,imm [rmi: norexw 66 0f 3a 22 /r ib,u] SSE41,SB,AR2 -PINSRD xmmreg,rm32,imm [rmi: norexw 66 0f 3a 22 /r ib,u] SSE41,SB,AR2 +PINSRD xmmreg,mem,imm [rmi: norexw 66 0f 3a 22 /r ib,u] SSE41,SB,AR2 +PINSRD xmmreg,rm32,imm [rmi: norexw 66 0f 3a 22 /r ib,u] SSE41,SB,AR2 PINSRQ xmmreg,mem,imm [rmi: o64 66 0f 3a 22 /r ib,u] SSE41,X64,SB,AR2 PINSRQ xmmreg,rm64,imm [rmi: o64 66 0f 3a 22 /r ib,u] SSE41,X64,SB,AR2 PMAXSB xmmreg,xmmrm [rm: 66 0f 38 3c /r] SSE41