aboutsummaryrefslogtreecommitdiff
path: root/opcodes/i386-dis.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2016-10-20 15:07:42 -0700
committerH.J. Lu <hjl.tools@gmail.com>2016-10-20 15:26:23 -0700
commit9889cbb14ebea4b281408afcfd94ad6646ab370a (patch)
treeffad5e2435f482ae1392027828b13905776e5890 /opcodes/i386-dis.c
parentf90fd8c2f17c7631915103ce5b760830a156ee93 (diff)
downloadgdb-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.c51
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: