diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2017-05-22 11:02:46 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2017-05-22 11:02:58 -0700 |
commit | 04ef582ace91cad765d056cc95624478e0421144 (patch) | |
tree | ce513249defa49cae554a37f0f532d696a6e788a /opcodes/i386-dis.c | |
parent | 25f94347373b1b6f4bfc79eeb38e79d383195779 (diff) | |
download | gdb-04ef582ace91cad765d056cc95624478e0421144.zip gdb-04ef582ace91cad765d056cc95624478e0421144.tar.gz gdb-04ef582ace91cad765d056cc95624478e0421144.tar.bz2 |
x86: Add NOTRACK prefix support
For register indirect branches, NOTRACK prefix (0x3e), which is also
the DS segment register prefix, can be used to ignore the CET indirect
branch track.
gas/
* config/tc-i386.c (REX_PREFIX): Changed to 7.
(NOTRACK_PREFIX): New.
(MAX_PREFIXES): Changed to 8.
(_i386_insn): Add notrack_prefix.
(PREFIX_GROUP): Add PREFIX_DS.
(add_prefix): Return PREFIX_DS for DS_PREFIX_OPCODE.
(md_assemble): Check if NOTRACK prefix is supported.
(parse_insn): Set notrack_prefix and issue an error for
other prefixes after NOTRACK prefix.
* testsuite/gas/i386/i386.exp: Run tests for NOTRACK prefix.
* testsuite/gas/i386/notrack-intel.d: New file.
* testsuite/gas/i386/notrack.d: Likewise.
* testsuite/gas/i386/notrack.s: Likewise.
* testsuite/gas/i386/notrackbad.l: Likewise.
* testsuite/gas/i386/notrackbad.s: Likewise.
* testsuite/gas/i386/x86-64-notrack-intel.d: Likewise.
* testsuite/gas/i386/x86-64-notrack.d: Likewise.
* testsuite/gas/i386/x86-64-notrack.s: Likewise.
* testsuite/gas/i386/x86-64-notrackbad.l: Likewise.
* testsuite/gas/i386/x86-64-notrackbad.s: Likewise.
include/
* include/opcode/i386.h (NOTRACK_PREFIX_OPCODE): New.
opcodes/
* i386-dis.c (NOTRACK_Fixup): New.
(NOTRACK): Likewise.
(NOTRACK_PREFIX): Likewise.
(last_active_prefix): Likewise.
(reg_table): Use NOTRACK on indirect call and jmp.
(ckprefix): Set last_active_prefix.
(prefix_name): Return "notrack" for NOTRACK_PREFIX.
* i386-gen.c (opcode_modifiers): Add NoTrackPrefixOk.
* i386-opc.h (NoTrackPrefixOk): New.
(i386_opcode_modifier): Add notrackprefixok.
* i386-opc.tbl: Add NoTrackPrefixOk to indirect call and jmp.
Add notrack.
* i386-tbl.h: Regenerated.
Diffstat (limited to 'opcodes/i386-dis.c')
-rw-r--r-- | opcodes/i386-dis.c | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 3980c46..039768b 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -110,6 +110,7 @@ static void CMP_Fixup (int, int); static void BadOp (void); static void REP_Fixup (int, int); static void BND_Fixup (int, int); +static void NOTRACK_Fixup (int, int); static void HLE_Fixup1 (int, int); static void HLE_Fixup2 (int, int); static void HLE_Fixup3 (int, int); @@ -473,6 +474,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define Evh3 { HLE_Fixup3, v_mode } #define BND { BND_Fixup, 0 } +#define NOTRACK { NOTRACK_Fixup, 0 } #define cond_jump_flag { NULL, cond_jump_mode } #define loop_jcxz_flag { NULL, loop_jcxz_mode } @@ -3167,6 +3169,7 @@ static int last_data_prefix; static int last_addr_prefix; static int last_rex_prefix; static int last_seg_prefix; +static int last_active_prefix; static int fwait_prefix; /* The active segment register prefix. */ static int active_seg_prefix; @@ -3549,9 +3552,9 @@ static const struct dis386 reg_table[][8] = { { { "incQ", { Evh1 }, 0 }, { "decQ", { Evh1 }, 0 }, - { "call{&|}", { indirEv, BND }, 0 }, + { "call{&|}", { indirEv, NOTRACK, BND }, 0 }, { MOD_TABLE (MOD_FF_REG_3) }, - { "jmp{&|}", { indirEv, BND }, 0 }, + { "jmp{&|}", { indirEv, NOTRACK, BND }, 0 }, { MOD_TABLE (MOD_FF_REG_5) }, { "pushU", { stackEv }, 0 }, { Bad_Opcode }, @@ -12281,6 +12284,7 @@ static const struct dis386 rm_table[][8] = { #define XACQUIRE_PREFIX (0xf2 | 0x200) #define XRELEASE_PREFIX (0xf3 | 0x400) #define BND_PREFIX (0xf2 | 0x400) +#define NOTRACK_PREFIX (0x3e | 0x100) static int ckprefix (void) @@ -12298,6 +12302,7 @@ ckprefix (void) last_addr_prefix = -1; last_rex_prefix = -1; last_seg_prefix = -1; + last_active_prefix = -1; fwait_prefix = -1; active_seg_prefix = 0; for (i = 0; i < (int) ARRAY_SIZE (all_prefixes); i++) @@ -12410,7 +12415,10 @@ ckprefix (void) return 1; } if (*codep != FWAIT_OPCODE) - all_prefixes[i++] = *codep; + { + last_active_prefix = i; + all_prefixes[i++] = *codep; + } rex = newrex; codep++; length++; @@ -12499,6 +12507,8 @@ prefix_name (int pref, int sizeflag) return "xrelease"; case BND_PREFIX: return "bnd"; + case NOTRACK_PREFIX: + return "notrack"; default: return NULL; } @@ -16789,6 +16799,34 @@ BND_Fixup (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) all_prefixes[last_repnz_prefix] = BND_PREFIX; } +/* For NOTRACK-prefixed instructions, 0x3E prefix should be displayed as + "notrack". */ + +static void +NOTRACK_Fixup (int bytemode ATTRIBUTE_UNUSED, + int sizeflag ATTRIBUTE_UNUSED) +{ + if (modrm.mod == 3 + && active_seg_prefix == PREFIX_DS + && (address_mode != mode_64bit || last_data_prefix < 0)) + { + /* NOTRACK prefix is only valid on register indirect branch + instructions and it must be the last prefix before REX + prefix and opcode. NB: DATA prefix is unsupported for + Intel64. */ + if (last_active_prefix >= 0) + { + int notrack_prefix = last_active_prefix; + if (last_rex_prefix == last_active_prefix) + notrack_prefix--; + if (all_prefixes[notrack_prefix] != NOTRACK_PREFIX_OPCODE) + return; + } + active_seg_prefix = 0; + all_prefixes[last_seg_prefix] = NOTRACK_PREFIX; + } +} + /* Similar to OP_E. But the 0xf2/0xf3 prefixes should be displayed as "xacquire"/"xrelease" for memory operand if there is a LOCK prefix. */ |