1#include <linux/types.h> 2 3#include "opcode.h" 4 5static bool opcode_is_prefix(uint8_t b) 6{ 7 return 8 /* Group 1 */ 9 b == 0xf0 || b == 0xf2 || b == 0xf3 10 /* Group 2 */ 11 || b == 0x2e || b == 0x36 || b == 0x3e || b == 0x26 12 || b == 0x64 || b == 0x65 13 /* Group 3 */ 14 || b == 0x66 15 /* Group 4 */ 16 || b == 0x67; 17} 18 19#ifdef CONFIG_X86_64 20static bool opcode_is_rex_prefix(uint8_t b) 21{ 22 return (b & 0xf0) == 0x40; 23} 24#else 25static bool opcode_is_rex_prefix(uint8_t b) 26{ 27 return false; 28} 29#endif 30 31#define REX_W (1 << 3) 32 33/* 34 * This is a VERY crude opcode decoder. We only need to find the size of the 35 * load/store that caused our #PF and this should work for all the opcodes 36 * that we care about. Moreover, the ones who invented this instruction set 37 * should be shot. 38 */ 39void kmemcheck_opcode_decode(const uint8_t *op, unsigned int *size) 40{ 41 /* Default operand size */ 42 int operand_size_override = 4; 43 44 /* prefixes */ 45 for (; opcode_is_prefix(*op); ++op) { 46 if (*op == 0x66) 47 operand_size_override = 2; 48 } 49 50 /* REX prefix */ 51 if (opcode_is_rex_prefix(*op)) { 52 uint8_t rex = *op; 53 54 ++op; 55 if (rex & REX_W) { 56 switch (*op) { 57 case 0x63: 58 *size = 4; 59 return; 60 case 0x0f: 61 ++op; 62 63 switch (*op) { 64 case 0xb6: 65 case 0xbe: 66 *size = 1; 67 return; 68 case 0xb7: 69 case 0xbf: 70 *size = 2; 71 return; 72 } 73 74 break; 75 } 76 77 *size = 8; 78 return; 79 } 80 } 81 82 /* escape opcode */ 83 if (*op == 0x0f) { 84 ++op; 85 86 /* 87 * This is move with zero-extend and sign-extend, respectively; 88 * we don't have to think about 0xb6/0xbe, because this is 89 * already handled in the conditional below. 90 */ 91 if (*op == 0xb7 || *op == 0xbf) 92 operand_size_override = 2; 93 } 94 95 *size = (*op & 1) ? operand_size_override : 1; 96} 97 98const uint8_t *kmemcheck_opcode_get_primary(const uint8_t *op) 99{ 100 /* skip prefixes */ 101 while (opcode_is_prefix(*op)) 102 ++op; 103 if (opcode_is_rex_prefix(*op)) 104 ++op; 105 return op; 106} 107