Computes the length of a single instruction. * Based on a snippet by Nicolas Capens (which he released to the public domain) * Taken from Hourglass */ _declspec(noinline) inline
| 68 | */ |
| 69 | //_declspec(noinline) inline |
| 70 | static int instruction_length(const unsigned char *func, instr_info *instr) |
| 71 | { |
| 72 | const unsigned char *funcstart = func; |
| 73 | |
| 74 | // Create a struct if non passed |
| 75 | instr_info local_instr; |
| 76 | if (!instr) { |
| 77 | instr = &local_instr; |
| 78 | } |
| 79 | |
| 80 | // Default values |
| 81 | instr->is_fpu = false; |
| 82 | instr->operand_size_prefix = false; |
| 83 | instr->quad_prefix = false; |
| 84 | instr->multibyte_opcode = 0; |
| 85 | instr->modRM = 0; |
| 86 | |
| 87 | int operandSizeDouble = 4; // operand size for instructions that depend only on 16-bit prefix, and cannot be promoted by REX.W 64-bit |
| 88 | int operandSize = 4; // operand size for instructions that depend on both operand-size prefixes |
| 89 | |
| 90 | // Skip prefixes F0h, F2h, F3h, 66h, 67h, D8h-DFh, 2Eh, 36h, 3Eh, 26h, 64h and 65h |
| 91 | while(*func == 0xF0 || |
| 92 | *func == 0xF2 || |
| 93 | *func == 0xF3 || |
| 94 | (*func & 0xFC) == 0x64 || |
| 95 | (*func & 0xF8) == 0xD8 || |
| 96 | (*func & 0x7E) == 0x62) |
| 97 | { |
| 98 | if(*func == 0x66) |
| 99 | { |
| 100 | instr->operand_size_prefix = true; |
| 101 | operandSize = 2; |
| 102 | operandSizeDouble = 2; |
| 103 | } |
| 104 | else if((*func & 0xF8) == 0xD8) |
| 105 | { |
| 106 | instr->is_fpu = true; |
| 107 | func++; |
| 108 | break; |
| 109 | } |
| 110 | |
| 111 | func++; |
| 112 | } |
| 113 | |
| 114 | /* Add x86_64 4xh prefixes */ |
| 115 | # ifdef __x86_64__ |
| 116 | while((*func & 0xF0) == 0x40) |
| 117 | { |
| 118 | if (*func & 0b00001000) { |
| 119 | instr->quad_prefix = true; |
| 120 | operandSize = 8; |
| 121 | } |
| 122 | func++; |
| 123 | } |
| 124 | # endif |
| 125 | |
| 126 | // Skip two-byte opcode byte |
| 127 | if(*func == 0x0F) |
no outgoing calls
no test coverage detected