Chromium Code Reviews| Index: syzygy/core/disassembler_util.cc |
| diff --git a/syzygy/core/disassembler_util.cc b/syzygy/core/disassembler_util.cc |
| index 7be5c8781853644f4d74abb1c39bed05a1411cca..a0cd5d19e35d33ae4cba11325b3057656536889f 100644 |
| --- a/syzygy/core/disassembler_util.cc |
| +++ b/syzygy/core/disassembler_util.cc |
| @@ -47,21 +47,47 @@ namespace { |
| // |
| // See http://wiki.osdev.org/X86-64_Instruction_Encoding#Three_byte_VEX_escape_prefix |
| // for more details. |
| +// |
| +// NOTE: Most of these instructions can have a variable length because they use |
| +// ModRM:r/m, we only support the variants that have been observed in Chrome. |
| size_t Get3ByteVexEncodedInstructionSize(_CodeInfo* ci) { |
|
chrisha
2017/04/26 15:09:10
This is no longer just 3byte VEX instructions? Or
|
| + const uint8_t kModRMMask = 0xC0; |
| + |
| DCHECK_EQ(0xC4, ci->code[0]); |
| // Switch case based on the opcode map used by this instruction. |
| switch (ci->code[1] & 0x1F) { |
| case 0x02: { |
| switch (ci->code[3]) { |
| - case 0x13: return 5; // vcvtps2ps |
| - case 0x18: return 5; // vbroadcastss |
| - case 0x36: return 5; // vpermd |
| - case 0x58: return 6; // vpbroadcastd |
| + case 0x13: return 5; // vcvtph2ps |
| + case 0x18: { // vbroadcastss |
| + CHECK((ci->code[4] & kModRMMask) != 0) << |
|
huangs
2017/04/25 22:14:20
Perhaps this should be
CHECK((ci->code[4] & kMod
|
| + "Unsupported variant of the vbroadcastss instruction"; |
| + return 5; |
| + } |
| + case 0x36: { // vpermd |
| + CHECK((ci->code[4] & kModRMMask) != 0) << |
| + "Unsupported variant of the vpermd instruction"; |
| + return 5; |
| + } |
| + case 0x58: // vpbroadcastb |
| + case 0x78: { // vpbroadcastd |
| + if ((ci->code[4] & kModRMMask) != kModRMMask) { |
| + return 6; |
|
huangs
2017/04/25 22:14:20
Cannot guarantee 6, due to possibility of SIB. For
|
| + } else { |
| + return 5; |
| + } |
| + } |
| case 0x5A: return 6; // vbroadcasti128 |
| - case 0x78: return 5; // vpbroadcastb |
| - case 0x8C: return 5; // vpmaskmovd |
| - case 0x8E: return 5; // vpmaskmovd |
| - case 0x90: return 6; // vpgatherdd |
| + case 0x8C: { // vpmaskmovd |
| + CHECK((ci->code[4] & kModRMMask) == 0) << |
| + "Unsupported variant of the vpmaskmovd instruction"; |
| + return 5; |
| + } |
| + case 0x90: { // vpgatherdd |
| + CHECK((ci->code[4] & kModRMMask) == 0) << |
| + "Unsupported variant of the vpgatherdd instruction"; |
| + return 6; |
| + } |
| default: |
| break; |
| } |
| @@ -71,8 +97,16 @@ size_t Get3ByteVexEncodedInstructionSize(_CodeInfo* ci) { |
| switch (ci->code[3]) { |
| case 0x00: return 6; // vpermq |
| case 0x1D: return 6; // vcvtps2ph |
| - case 0x38: return 7; // vinserti128 |
| - case 0x39: return 6; // vextracti128 |
| + case 0x38: { // vinserti128 |
| + CHECK((ci->code[4] & kModRMMask) == 0) << |
| + "Unsupported variant of the vinserti128 instruction"; |
| + return 7; |
| + } |
| + case 0x39: { // vextracti128 |
| + CHECK((ci->code[4] & kModRMMask) != 0) << |
| + "Unsupported variant of the vextracti128 instruction"; |
| + return 6; |
| + } |
| default: break; |
| } |
| break; |
| @@ -150,10 +184,9 @@ bool HandleBadDecode(_CodeInfo* ci, |
| return true; |
| } |
| - } |
| - |
| - if (ci->code[0] == 0xC4) |
| + } else if (ci->code[0] == 0xC4) { |
| size = Get3ByteVexEncodedInstructionSize(ci); |
| + } |
| if (size == 0) |
| return false; |