From 0304109b3d40c3a46e383cadaeae365c66e1b0e4 Mon Sep 17 00:00:00 2001 From: Jin Kyu Song Date: Tue, 15 Oct 2013 19:38:51 -0700 Subject: [PATCH] MPX: Add BND prefix for branch instructions BND prefix is used for adding bounds checking protection across flow control changes such as call, ret, jmp and jcc calls. Signed-off-by: Jin Kyu Song --- assemble.c | 13 +++++++++++-- disasm.c | 5 +++++ insns.dat | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ insns.pl | 1 + nasm.h | 1 + nasmlib.c | 2 +- parser.c | 1 + tokens.dat | 1 + 8 files changed, 75 insertions(+), 3 deletions(-) diff --git a/assemble.c b/assemble.c index d913495..d1234ee 100644 --- a/assemble.c +++ b/assemble.c @@ -162,6 +162,7 @@ * \367 - address-size prefix (0x67) used as opcode extension * \370,\371 - match only if operand 0 meets byte jump criteria. * 370 is used for Jcc, 371 is used for JMP. + * \372 - BND prefix (0xF2 byte) used for preserving bnd0..3 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32; * used for conditional jump over longer jump * \374 - this instruction takes an XMM VSIB memory EA @@ -193,6 +194,7 @@ enum match_result { MERR_BADMODE, MERR_BADHLE, MERR_ENCMISMATCH, + MERR_BADBND, /* * Matching success; the conditional ones first */ @@ -547,6 +549,7 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, iflags_t cp, case P_REPNE: case P_REPNZ: case P_XACQUIRE: + case P_BND: c = 0xF2; break; case P_REPE: @@ -1739,8 +1742,7 @@ static void gencode(int32_t segment, int64_t offset, int bits, offset += 1; break; - case 0370: - case 0371: + case3(0370): break; case 0373: @@ -2227,6 +2229,13 @@ static enum match_result matches(const struct itemplate *itemp, if ((itemp->code[0] & ~1) == 0370) return MOK_JUMP; + /* + * Check if BND prefix is allowed + */ + if ((itemp->code[0] != 0372) && + has_prefix(instruction, PPS_REP, P_BND)) + return MERR_BADBND; + return MOK_GOOD; } diff --git a/disasm.c b/disasm.c index f50ceb9..eace1e9 100644 --- a/disasm.c +++ b/disasm.c @@ -862,6 +862,11 @@ static int matches(const struct itemplate *t, uint8_t *data, case 0371: break; + case 0372: + if (prefix->rep == 0xF2) + drep = P_BND; + break; + case 0374: eat = EA_XMMVSIB; break; diff --git a/insns.dat b/insns.dat index b1a1aac..8462211 100644 --- a/insns.dat +++ b/insns.dat @@ -275,6 +275,24 @@ CALL mem [m: odf ff /2] 8086 CALL rm16 [m: o16 ff /2] 8086,NOLONG CALL rm32 [m: o32 ff /2] 386,NOLONG CALL rm64 [m: o64nw ff /2] X64 +; BND + CALL +CALL imm [i: bnd odf e8 rel] 8086,MPX +CALL imm|near [i: bnd odf e8 rel] 8086,ND,MPX +CALL imm16 [i: bnd o16 e8 rel] 8086,NOLONG,MPX +CALL imm16|near [i: bnd o16 e8 rel] 8086,ND,NOLONG,MPX +CALL imm32 [i: bnd o32 e8 rel] 386,NOLONG,MPX +CALL imm32|near [i: bnd o32 e8 rel] 386,ND,NOLONG,MPX +CALL imm64 [i: bnd o64nw e8 rel] X64,MPX +CALL imm64|near [i: bnd o64nw e8 rel] X64,ND,MPX +CALL mem|near [m: bnd odf ff /2] 8086,ND,MPX +CALL rm16|near [m: bnd o16 ff /2] 8086,NOLONG,ND,MPX +CALL rm32|near [m: bnd o32 ff /2] 386,NOLONG,ND,MPX +CALL rm64|near [m: bnd o64nw ff /2] X64,ND,MPX +CALL mem [m: bnd odf ff /2] 8086,MPX +CALL rm16 [m: bnd o16 ff /2] 8086,NOLONG,MPX +CALL rm32 [m: bnd o32 ff /2] 386,NOLONG,MPX +CALL rm64 [m: bnd o64nw ff /2] X64,MPX + CBW void [ o16 98] 8086 CDQ void [ o32 99] 386 CDQE void [ o64 98] X64 @@ -708,6 +726,24 @@ JMP mem [m: odf ff /4] 8086 JMP rm16 [m: o16 ff /4] 8086,NOLONG JMP rm32 [m: o32 ff /4] 386,NOLONG JMP rm64 [m: o64nw ff /4] X64 +; BND + JMP +JMP imm [i: bnd odf e9 rel] 8086,MPX +JMP imm|near [i: bnd odf e9 rel] 8086,ND,MPX +JMP imm16 [i: bnd o16 e9 rel] 8086,NOLONG,MPX +JMP imm16|near [i: bnd o16 e9 rel] 8086,ND,NOLONG,MPX +JMP imm32 [i: bnd o32 e9 rel] 386,NOLONG,MPX +JMP imm32|near [i: bnd o32 e9 rel] 386,ND,NOLONG,MPX +JMP imm64 [i: bnd o64nw e9 rel] X64,MPX +JMP imm64|near [i: bnd o64nw e9 rel] X64,ND,MPX +JMP mem|near [m: bnd odf ff /4] 8086,ND,MPX +JMP rm16|near [m: bnd o16 ff /4] 8086,NOLONG,ND,MPX +JMP rm32|near [m: bnd o32 ff /4] 386,NOLONG,ND,MPX +JMP rm64|near [m: bnd o64nw ff /4] X64,ND,MPX +JMP mem [m: bnd odf ff /4] 8086,MPX +JMP rm16 [m: bnd o16 ff /4] 8086,NOLONG,MPX +JMP rm32 [m: bnd o32 ff /4] 386,NOLONG,MPX +JMP rm64 [m: bnd o64nw ff /4] X64,MPX + JMPE imm [i: odf 0f b8 rel] IA64 JMPE imm16 [i: o16 0f b8 rel] IA64 JMPE imm32 [i: o32 0f b8 rel] IA64 @@ -1119,6 +1155,12 @@ RETF void [ cb] 8086 RETF imm [i: ca iw] 8086,SW RETN void [ c3] 8086 RETN imm [i: c2 iw] 8086,SW +; BND + RET +RET void [ bnd c3] 8086,MPX +RET imm [i: bnd c2 iw] 8086,SW,MPX +RETN void [ bnd c3] 8086,MPX +RETN imm [i: bnd c2 iw] 8086,SW,MPX + ROL rm8,unity [m-: d0 /0] 8086 ROL rm8,reg_cl [m-: d2 /0] 8086 ROL rm8,imm8 [mi: c0 /0 ib,u] 186 @@ -1485,6 +1527,18 @@ Jcc imm [i: jcc8 70+c rel8] 8086,ND Jcc imm [i: 0f 80+c rel] 386,ND Jcc imm [i: 71+c jlen e9 rel] 8086,ND Jcc imm [i: 70+c rel8] 8086 +; BND + Jcc +Jcc imm|near [i: bnd odf 0f 80+c rel] 386,MPX +Jcc imm16|near [i: bnd o16 0f 80+c rel] 386,NOLONG,MPX +Jcc imm32|near [i: bnd o32 0f 80+c rel] 386,NOLONG,MPX +Jcc imm64|near [i: bnd o64nw 0f 80+c rel] X64,MPX +Jcc imm|short [i: bnd 70+c rel8] 8086,ND,MPX +; TODO: check if bnd and jcc8 can be used together +;Jcc imm [i: bnd jcc8 70+c rel8] 8086,ND,MPX +Jcc imm [i: bnd 0f 80+c rel] 386,ND,MPX +Jcc imm [i: bnd 71+c jlen e9 rel] 8086,ND,MPX +Jcc imm [i: bnd 70+c rel8] 8086,MPX + SETcc mem [m: 0f 90+c /0] 386,SB SETcc reg8 [m: 0f 90+c /0] 386 diff --git a/insns.pl b/insns.pl index 8bd76ab..2953a4d 100755 --- a/insns.pl +++ b/insns.pl @@ -765,6 +765,7 @@ sub byte_code_compile($$) { 'resb' => 0340, 'jcc8' => 0370, # Match only if Jcc possible with single byte 'jmp8' => 0371, # Match only if JMP possible with single byte + 'bnd' => 0372, # BND (0xF2) prefix available 'jlen' => 0373, # Length of jump 'hlexr' => 0271, 'hlenl' => 0272, diff --git a/nasm.h b/nasm.h index 50e4b63..5ca2aa5 100644 --- a/nasm.h +++ b/nasm.h @@ -552,6 +552,7 @@ enum prefixes { /* instruction prefixes */ P_WAIT, P_XACQUIRE, P_XRELEASE, + P_BND, PREFIX_ENUM_LIMIT }; diff --git a/nasmlib.c b/nasmlib.c index e145a76..ec1460b 100644 --- a/nasmlib.c +++ b/nasmlib.c @@ -564,7 +564,7 @@ void standard_extension(char *inname, char *outname, char *extension) static const char *prefix_names[] = { "a16", "a32", "a64", "asp", "lock", "o16", "o32", "o64", "osp", "rep", "repe", "repne", "repnz", "repz", "times", "wait", - "xacquire", "xrelease" + "xacquire", "xrelease", "bnd" }; const char *prefix_name(int token) diff --git a/parser.c b/parser.c index 0068ca3..e61d0a6 100644 --- a/parser.c +++ b/parser.c @@ -89,6 +89,7 @@ static int prefix_slot(int prefix) case P_REPNZ: case P_XACQUIRE: case P_XRELEASE: + case P_BND: return PPS_REP; case P_O16: case P_O32: diff --git a/tokens.dat b/tokens.dat index d12b296..211eb09 100644 --- a/tokens.dat +++ b/tokens.dat @@ -54,6 +54,7 @@ times wait xacquire xrelease +bnd % TOKEN_SPECIAL, 0, 0, S_* abs -- 2.7.4