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 /gas/config | |
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 'gas/config')
-rw-r--r-- | gas/config/tc-i386.c | 75 |
1 files changed, 58 insertions, 17 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 6250793..6c1091e 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -66,8 +66,11 @@ #define HLE_PREFIX REP_PREFIX #define BND_PREFIX REP_PREFIX #define LOCK_PREFIX 5 -#define REX_PREFIX 6 /* must come last. */ -#define MAX_PREFIXES 7 /* max prefixes per opcode */ +/* Only one of NOTRACK_PREFIX and SEG_PREFIX can be used at the same + time. */ +#define NOTRACK_PREFIX 6 +#define REX_PREFIX 7 /* must come last. */ +#define MAX_PREFIXES 8 /* max prefixes per opcode */ /* we define the syntax here (modulo base,index,scale syntax) */ #define REGISTER_PREFIX '%' @@ -388,6 +391,9 @@ struct _i386_insn /* Have BND prefix. */ const char *bnd_prefix; + /* Have NOTRACK prefix. */ + const char *notrack_prefix; + /* Error message. */ enum i386_error error; }; @@ -2144,6 +2150,7 @@ enum PREFIX_GROUP PREFIX_EXIST = 0, PREFIX_LOCK, PREFIX_REP, + PREFIX_DS, PREFIX_OTHER }; @@ -2152,7 +2159,8 @@ enum PREFIX_GROUP same class already exists. b. PREFIX_LOCK if lock prefix is added. c. PREFIX_REP if rep/repne prefix is added. - d. PREFIX_OTHER if other prefix is added. + d. PREFIX_DS if ds prefix is added. + e. PREFIX_OTHER if other prefix is added. */ static enum PREFIX_GROUP @@ -2177,8 +2185,10 @@ add_prefix (unsigned int prefix) default: abort (); - case CS_PREFIX_OPCODE: case DS_PREFIX_OPCODE: + ret = PREFIX_DS; + /* Fall through. */ + case CS_PREFIX_OPCODE: case ES_PREFIX_OPCODE: case FS_PREFIX_OPCODE: case GS_PREFIX_OPCODE: @@ -3702,6 +3712,15 @@ md_assemble (char *line) if (i.bnd_prefix && !i.tm.opcode_modifier.bndprefixok) as_bad (_("expecting valid branch instruction after `bnd'")); + /* Check NOTRACK prefix. */ + if (i.notrack_prefix + && (!i.tm.opcode_modifier.notrackprefixok + || i.reg_operands != 1 + || i.disp_operands != 0 + || i.mem_operands != 0 + || i.imm_operands != 0)) + as_bad (_("expecting register indirect branch instruction after `notrack'")); + if (i.tm.cpu_flags.bitfield.cpumpx) { if (flag_code == CODE_64BIT && i.prefix[ADDR_PREFIX]) @@ -3964,20 +3983,42 @@ parse_insn (char *line, char *mnemonic) else { /* Add prefix, checking for repeated prefixes. */ - switch (add_prefix (current_templates->start->base_opcode)) + enum PREFIX_GROUP p + = add_prefix (current_templates->start->base_opcode); + if (p == PREFIX_DS + && current_templates->start->cpu_flags.bitfield.cpucet) { - case PREFIX_EXIST: - return NULL; - case PREFIX_REP: - if (current_templates->start->cpu_flags.bitfield.cpuhle) - i.hle_prefix = current_templates->start->name; - else if (current_templates->start->cpu_flags.bitfield.cpumpx) - i.bnd_prefix = current_templates->start->name; - else - i.rep_prefix = current_templates->start->name; - break; - default: - break; + i.notrack_prefix = current_templates->start->name; + /* Move NOTRACK_PREFIX_OPCODE to NOTRACK_PREFIX slot so + that it is placed before others. */ + i.prefix[SEG_PREFIX] = 0; + i.prefix[NOTRACK_PREFIX] = NOTRACK_PREFIX_OPCODE; + } + else + { + switch (p) + { + case PREFIX_EXIST: + return NULL; + case PREFIX_REP: + if (current_templates->start->cpu_flags.bitfield.cpuhle) + i.hle_prefix = current_templates->start->name; + else if (current_templates->start->cpu_flags.bitfield.cpumpx) + i.bnd_prefix = current_templates->start->name; + else + i.rep_prefix = current_templates->start->name; + break; + default: + break; + } + + if (i.notrack_prefix != NULL) + { + /* There must be no other prefixes after NOTRACK + prefix. */ + as_bad (_("expecting no other prefixes after `notrack'")); + return NULL; + } } } /* Skip past PREFIX_SEPARATOR and reset token_start. */ |