diff --git a/clients/drcachesim/drpt2trace/pt2ir.cpp b/clients/drcachesim/drpt2trace/pt2ir.cpp index 45397d96350..4a5ad88f293 100644 --- a/clients/drcachesim/drpt2trace/pt2ir.cpp +++ b/clients/drcachesim/drpt2trace/pt2ir.cpp @@ -388,9 +388,6 @@ pt2ir_t::convert(DR_PARAM_IN const uint8_t *pt_data, DR_PARAM_IN size_t pt_data_ instr_valid = true; instr_set_translation(instr, (app_pc)insn.ip); instr_allocate_raw_bits(drir.get_drcontext(), instr, insn.size); - /* TODO i#2103: Currently, the PT raw data may contain 'STAC' and 'CLAC' - * instructions that are not supported by Dynamorio. - */ if (!instr_valid) { /* The decode() function will not correctly identify the raw bits for * invalid instruction. So we need to set the raw bits of instr manually. diff --git a/core/ir/instr_api.h b/core/ir/instr_api.h index 148190886e9..9fc140d7a36 100644 --- a/core/ir/instr_api.h +++ b/core/ir/instr_api.h @@ -2550,6 +2550,7 @@ instr_is_reg_spill_or_restore(void *drcontext, instr_t *instr, bool *tls DR_PARA # define EFLAGS_READ_OF 0x00000100 /**< Reads OF (Overflow Flag). */ # define EFLAGS_READ_NT 0x00000200 /**< Reads NT (Nested Task). */ # define EFLAGS_READ_RF 0x00000400 /**< Reads RF (Resume Flag). */ + # define EFLAGS_WRITE_CF 0x00000800 /**< Writes CF (Carry Flag). */ # define EFLAGS_WRITE_PF 0x00001000 /**< Writes PF (Parity Flag). */ # define EFLAGS_WRITE_AF 0x00002000 /**< Writes AF (Auxiliary Carry Flag). */ @@ -2562,9 +2563,18 @@ instr_is_reg_spill_or_restore(void *drcontext, instr_t *instr, bool *tls DR_PARA # define EFLAGS_WRITE_NT 0x00100000 /**< Writes NT (Nested Task). */ # define EFLAGS_WRITE_RF 0x00200000 /**< Writes RF (Resume Flag). */ -# define EFLAGS_READ_ALL 0x000007ff /**< Reads all flags. */ +/* TODO i#6485: Re-number the following when a major binary compatibility break + * is more convenient. + */ +/* OP_clac and OP_stac both write the AC flag. Even though we do not have an + * opcode that reads it, we still add EFLAGS_READ_AC for parity. + */ +# define EFLAGS_READ_AC 0x00400000 /**< Reads AC (Alignment Check Flag). */ +# define EFLAGS_WRITE_AC 0x00800000 /**< Writes AC (Alignment Check Flag). */ + +# define EFLAGS_READ_ALL 0x004007ff /**< Reads all flags. */ # define EFLAGS_READ_NON_PRED EFLAGS_READ_ALL /**< Flags not read by predicates. */ -# define EFLAGS_WRITE_ALL 0x003ff800 /**< Writes all flags. */ +# define EFLAGS_WRITE_ALL 0x00bff800 /**< Writes all flags. */ /* 6 most common flags ("arithmetic flags"): CF, PF, AF, ZF, SF, OF */ /** Reads all 6 arithmetic flags (CF, PF, AF, ZF, SF, OF). */ # define EFLAGS_READ_6 0x0000011f @@ -2577,9 +2587,13 @@ instr_is_reg_spill_or_restore(void *drcontext, instr_t *instr, bool *tls DR_PARA # define EFLAGS_WRITE_ARITH EFLAGS_WRITE_6 /** Converts an EFLAGS_WRITE_* value to the corresponding EFLAGS_READ_* value. */ -# define EFLAGS_WRITE_TO_READ(x) ((x) >> 11) +# define EFLAGS_WRITE_TO_READ(x) \ + ((((x) & ((EFLAGS_WRITE_ALL) & ~(EFLAGS_WRITE_AC))) >> 11) | \ + (((x) & (EFLAGS_WRITE_AC)) >> 1)) /** Converts an EFLAGS_READ_* value to the corresponding EFLAGS_WRITE_* value. */ -# define EFLAGS_READ_TO_WRITE(x) ((x) << 11) +# define EFLAGS_READ_TO_WRITE(x) \ + ((((x) & ((EFLAGS_READ_ALL) & ~(EFLAGS_READ_AC))) << 11) | \ + (((x) & (EFLAGS_READ_AC)) << 1)) /** * The actual bits in the eflags register that we care about:\n
diff --git a/core/ir/x86/decode_fast.c b/core/ir/x86/decode_fast.c index 7662bb15df4..0a2686e3d00 100644 --- a/core/ir/x86/decode_fast.c +++ b/core/ir/x86/decode_fast.c @@ -1,5 +1,5 @@ /* ********************************************************** - * Copyright (c) 2011-2022 Google, Inc. All rights reserved. + * Copyright (c) 2011-2023 Google, Inc. All rights reserved. * Copyright (c) 2001-2010 VMware, Inc. All rights reserved. * **********************************************************/ diff --git a/core/ir/x86/decode_table.c b/core/ir/x86/decode_table.c index 408d529e9f3..0c505cb13ec 100644 --- a/core/ir/x86/decode_table.c +++ b/core/ir/x86/decode_table.c @@ -1623,6 +1623,10 @@ const instr_info_t * const op_instr[] = /* AVX512 VPOPCNTDQ */ /* OP_vpopcntd, */ &evex_Wb_extensions[274][0], /* OP_vpopcntq, */ &evex_Wb_extensions[274][2], + + /* Supervisor Mode Access Prevention (SMAP) */ + /* OP_clac */ &rm_extensions[1][2], + /* OP_stac */ &rm_extensions[1][3] }; @@ -2079,6 +2083,7 @@ const instr_info_t * const op_instr[] = #define fRO EFLAGS_READ_OF #define fRN EFLAGS_READ_NT #define fRR EFLAGS_READ_RF +#define fRAC EFLAGS_READ_AC #define fRX EFLAGS_READ_ALL #define fR6 EFLAGS_READ_6 #define fWC EFLAGS_WRITE_CF @@ -2092,6 +2097,7 @@ const instr_info_t * const op_instr[] = #define fWO EFLAGS_WRITE_OF #define fWN EFLAGS_WRITE_NT #define fWR EFLAGS_WRITE_RF +#define fWAC EFLAGS_WRITE_AC #define fWX EFLAGS_WRITE_ALL #define fW6 EFLAGS_WRITE_6 /* flags affected by OP_int* @@ -7019,8 +7025,8 @@ const instr_info_t rm_extensions[][8] = { /* XXX i#4013: Treat address in xax as IR memref? */ {OP_monitor, 0xc80f0171, catUncategorized, "monitor", xx, xx, axAX, ecx, edx, mrm, x, END_LIST}, {OP_mwait, 0xc90f0171, catUncategorized, "mwait", xx, xx, eax, ecx, xx, mrm, x, END_LIST}, - {INVALID, 0x0f0131, catUncategorized, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, - {INVALID, 0x0f0131, catUncategorized, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, + {OP_clac, 0xca0f0171, catUncategorized, "clac", xx, xx, xx, xx, xx, no, fWAC, NA}, + {OP_stac, 0xcb0f0171, catUncategorized, "stac", xx, xx, xx, xx, xx, no, fWAC, NA}, {INVALID, 0x0f0131, catUncategorized, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, {INVALID, 0x0f0131, catUncategorized, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, {INVALID, 0x0f0131, catUncategorized, "(bad)", xx, xx, xx, xx, xx, no, x, NA}, diff --git a/core/ir/x86/instr_create_api.h b/core/ir/x86/instr_create_api.h index 7afdbee971f..8444dd6b8c8 100644 --- a/core/ir/x86/instr_create_api.h +++ b/core/ir/x86/instr_create_api.h @@ -1,5 +1,5 @@ /* ********************************************************** - * Copyright (c) 2011-2022 Google, Inc. All rights reserved. + * Copyright (c) 2011-2023 Google, Inc. All rights reserved. * Copyright (c) 2002-2010 VMware, Inc. All rights reserved. * **********************************************************/ @@ -527,6 +527,8 @@ #define INSTR_CREATE_vzeroupper(dc) instr_create_0dst_0src((dc), OP_vzeroupper) #define INSTR_CREATE_vzeroall(dc) instr_create_0dst_0src((dc), OP_vzeroall) #define INSTR_CREATE_xtest(dc) instr_create_0dst_0src((dc), OP_xtest) +#define INSTR_CREATE_clac(dc) instr_create_0dst_0src((dc), OP_clac) +#define INSTR_CREATE_stac(dc) instr_create_0dst_0src((dc), OP_stac) /** @} */ /* end doxygen group */ /* no destination, 1 source */ diff --git a/core/ir/x86/opcode_api.h b/core/ir/x86/opcode_api.h index 58bf150d868..4272edd1976 100644 --- a/core/ir/x86/opcode_api.h +++ b/core/ir/x86/opcode_api.h @@ -1,5 +1,5 @@ /* ********************************************************** - * Copyright (c) 2011-2021 Google, Inc. All rights reserved. + * Copyright (c) 2011-2023 Google, Inc. All rights reserved. * Copyright (c) 2000-2010 VMware, Inc. All rights reserved. * **********************************************************/ @@ -1614,6 +1614,9 @@ enum { /* 1433 */ OP_vpopcntd, /**< IA-32/AMD64 vpopcntd opcode. */ /* 1434 */ OP_vpopcntq, /**< IA-32/AMD64 vpopcntd opcode. */ + /* Supervisor Mode Access Prevention (SMAP) */ + /* 1435 */ OP_clac, + /* 1436 */ OP_stac, OP_AFTER_LAST, OP_FIRST = OP_add, /**< First real opcode. */ OP_LAST = OP_AFTER_LAST - 1, /**< Last real opcode. */ diff --git a/suite/tests/api/ir_x86_0args.h b/suite/tests/api/ir_x86_0args.h index 6c98022acc2..34a544ab536 100644 --- a/suite/tests/api/ir_x86_0args.h +++ b/suite/tests/api/ir_x86_0args.h @@ -1,5 +1,5 @@ /* ********************************************************** - * Copyright (c) 2011-2016 Google, Inc. All rights reserved. + * Copyright (c) 2011-2023 Google, Inc. All rights reserved. * Copyright (c) 2008-2010 VMware, Inc. All rights reserved. * **********************************************************/ @@ -197,3 +197,6 @@ OPCODE(xtest, xtest, xtest, 0) OPCODE(rdpkru, rdpkru, rdpkru, 0) OPCODE(wrpkru, wrpkru, wrpkru, 0) + +OPCODE(clac, clac, clac, 0) +OPCODE(stac, stac, stac, 0) diff --git a/third_party/binutils/test_decenc/drdecode_decenc_x86.expect b/third_party/binutils/test_decenc/drdecode_decenc_x86.expect index c9059243d82..1801e89ca5f 100644 --- a/third_party/binutils/test_decenc/drdecode_decenc_x86.expect +++ b/third_party/binutils/test_decenc/drdecode_decenc_x86.expect @@ -138762,6 +138762,8 @@ test_s: 7b 00 00 00 62 f2 7d 29 91 b4 f5 vpgatherqd 0x0000007b(%ebp,%ymm6,8), %ymm6 {%k1} {%k1} 7b 00 00 00 + 0f 01 ca clac + 0f 01 cb stac 90 nop 90 nop 90 nop diff --git a/third_party/binutils/test_decenc/drdecode_decenc_x86_64.expect b/third_party/binutils/test_decenc/drdecode_decenc_x86_64.expect index 2b19bc9c36e..04fa5247dd0 100644 --- a/third_party/binutils/test_decenc/drdecode_decenc_x86_64.expect +++ b/third_party/binutils/test_decenc/drdecode_decenc_x86_64.expect @@ -102826,6 +102826,8 @@ test_x86_64_s: c4 e2 59 53 11 vpdpwssds %xmm4, (%rcx), %xmm2 62 b2 5d 08 53 d6 vpdpwssds %xmm4, %xmm22, %xmm2 {%k0} 62 d2 5d 08 50 d4 vpdpbusd %xmm4, %xmm12, %xmm2 {%k0} + 0f 01 ca clac + 0f 01 cb stac 90 nop 90 nop 90 nop diff --git a/third_party/binutils/test_decenc/test_decenc_x86.asm b/third_party/binutils/test_decenc/test_decenc_x86.asm index 1aa50c20c99..1a0ee210522 100644 --- a/third_party/binutils/test_decenc/test_decenc_x86.asm +++ b/third_party/binutils/test_decenc/test_decenc_x86.asm @@ -298,10 +298,6 @@ GLOBAL_LABEL(FUNCNAME:) /* arch_13.s */ - /* clac, CPL 0 instruction. */ - /* RAW(0f) RAW(01) RAW(ca) */ - /* stac, CPL 0 instruction. */ - /* RAW(0f) RAW(01) RAW(cb) */ RAW(66) RAW(0f) RAW(38) RAW(f6) RAW(ca) RAW(f3) RAW(0f) RAW(38) RAW(f6) RAW(ca) RAW(0f) RAW(c7) RAW(f8) @@ -139592,6 +139588,16 @@ GLOBAL_LABEL(FUNCNAME:) RAW(7b) RAW(00) RAW(00) RAW(00) RAW(62) RAW(f2) RAW(7d) RAW(29) RAW(91) RAW(b4) RAW(f5) RAW(7b) RAW(00) RAW(00) RAW(00) + + /* TODO i#5505: Move the following back under + * arch_13.s in a separate PR to keep the huge + * diff isolated from PR #6484. + */ + /* clac, CPL 0 instruction. */ + RAW(0f) RAW(01) RAW(ca) + /* stac, CPL 0 instruction. */ + RAW(0f) RAW(01) RAW(cb) + END_OF_SUBTEST_MARKER #ifdef DISABLED_UNTIL_BUG_3577_IS_FIXED diff --git a/third_party/binutils/test_decenc/test_decenc_x86_64.asm b/third_party/binutils/test_decenc/test_decenc_x86_64.asm index d2be83ac5e0..3527f297855 100644 --- a/third_party/binutils/test_decenc/test_decenc_x86_64.asm +++ b/third_party/binutils/test_decenc/test_decenc_x86_64.asm @@ -220,10 +220,6 @@ GLOBAL_LABEL(FUNCNAME:) /* x86_64_arch_3.s */ - /* clac, CPL 0 instruction. */ - /* RAW(0f) RAW(01) RAW(ca) */ - /* stac, CPL 0 instruction. */ - /* RAW(0f) RAW(01) RAW(cb) */ RAW(66) RAW(0f) RAW(38) RAW(f6) RAW(ca) RAW(f3) RAW(0f) RAW(38) RAW(f6) RAW(ca) RAW(0f) RAW(c7) RAW(f8) @@ -106655,5 +106651,14 @@ GLOBAL_LABEL(FUNCNAME:) RAW(62) RAW(b2) RAW(5d) RAW(08) RAW(53) RAW(d6) RAW(62) RAW(d2) RAW(5d) RAW(08) RAW(50) RAW(d4) + /* TODO i#5505: Move the following back under + * x86_64_arch_3.s in a separate PR to keep the huge + * diff isolated from PR #6484. + */ + /* clac, CPL 0 instruction. */ + RAW(0f) RAW(01) RAW(ca) + /* stac, CPL 0 instruction. */ + RAW(0f) RAW(01) RAW(cb) + END_OF_FUNCTION_MARKER END_FUNC(FUNCNAME)