diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2016-10-20 15:07:42 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2016-10-20 15:26:23 -0700 |
commit | 9889cbb14ebea4b281408afcfd94ad6646ab370a (patch) | |
tree | ffad5e2435f482ae1392027828b13905776e5890 /opcodes/i386-dis.c | |
parent | f90fd8c2f17c7631915103ce5b760830a156ee93 (diff) | |
download | gdb-9889cbb14ebea4b281408afcfd94ad6646ab370a.zip gdb-9889cbb14ebea4b281408afcfd94ad6646ab370a.tar.gz gdb-9889cbb14ebea4b281408afcfd94ad6646ab370a.tar.bz2 |
Check invalid mask registers
In 32-bit, the REX_B bit in the 3-byte VEX prefix is ignored and the
the highest bit in VEX.vvvv is either 1 or ignored. In 64-bit, we
need to check invalid mask registers.
gas/
PR binutis/20705
* testsuite/gas/i386/i386.exp: Run x86-64-opcode-bad.
* testsuite/gas/i386/x86-64-opcode-bad.d: New file.
* testsuite/gas/i386/x86-64-opcode-bad.s: Likewise.
opcodes/
PR binutis/20705
* i386-dis.c (get_valid_dis386): Ignore the REX_B bit and
the highest bit in VEX.vvvv for the 3-byte VEX prefix in
32-bit mode. Don't check vex.register_specifier in 32-bit
mode.
(OP_E_register): Check invalid mask registers.
(OP_G): Likewise.
(OP_VEX): Likewise.
Diffstat (limited to 'opcodes/i386-dis.c')
-rw-r--r-- | opcodes/i386-dis.c | 51 |
1 files changed, 34 insertions, 17 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 4624a6a..1518a1d 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -13022,17 +13022,20 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info) } codep++; vex.w = *codep & 0x80; - if (vex.w && address_mode == mode_64bit) - rex |= REX_W; - - vex.register_specifier = (~(*codep >> 3)) & 0xf; - if (address_mode != mode_64bit - && vex.register_specifier > 0x7) + if (address_mode == mode_64bit) { - dp = &bad_opcode; - return dp; + if (vex.w) + rex |= REX_W; + vex.register_specifier = (~(*codep >> 3)) & 0xf; + } + else + { + /* For the 3-byte VEX prefix in 32-bit mode, the REX_B bit + is ignored, other REX bits are 0 and the highest bit in + VEX.vvvv is also ignored. */ + rex = 0; + vex.register_specifier = (~(*codep >> 3)) & 0x7; } - vex.length = (*codep & 0x4) ? 256 : 128; switch ((*codep & 0x3)) { @@ -13072,16 +13075,10 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info) rex_ignored = rex; rex = (*codep & 0x80) ? 0 : REX_R; + /* For the 2-byte VEX prefix in 32-bit mode, the highest bit in + VEX.vvvv is 1. */ vex.register_specifier = (~(*codep >> 3)) & 0xf; - if (address_mode != mode_64bit - && vex.register_specifier > 0x7) - { - dp = &bad_opcode; - return dp; - } - vex.w = 0; - vex.length = (*codep & 0x4) ? 256 : 128; switch ((*codep & 0x3)) { @@ -15266,6 +15263,11 @@ OP_E_register (int bytemode, int sizeflag) break; case mask_bd_mode: case mask_mode: + if (reg > 0x7) + { + oappend ("(bad)"); + return; + } names = names_mask; break; case 0: @@ -15795,6 +15797,11 @@ OP_G (int bytemode, int sizeflag) break; case mask_bd_mode: case mask_mode: + if ((modrm.reg + add) > 0x7) + { + oappend ("(bad)"); + return; + } oappend (names_mask[modrm.reg + add]); break; default: @@ -17225,6 +17232,11 @@ OP_VEX (int bytemode, int sizeflag ATTRIBUTE_UNUSED) break; case mask_bd_mode: case mask_mode: + if (reg > 0x7) + { + oappend ("(bad)"); + return; + } names = names_mask; break; default: @@ -17245,6 +17257,11 @@ OP_VEX (int bytemode, int sizeflag ATTRIBUTE_UNUSED) break; case mask_bd_mode: case mask_mode: + if (reg > 0x7) + { + oappend ("(bad)"); + return; + } names = names_mask; break; default: |