TODO handle imms for MPX args For most instructions, instruction_index == operand_index, but some instructions (floating point, some others) have an implicit first operand (st0), so we have to remap things a bit Instruction index represents the 'nth' argument/opcode in the instruction, whereas the operand index is index that XED holds that operand in the instruction
| 52 | // For most instructions, instruction_index == operand_index, but some instructions (floating point, some others) have an implicit first operand (st0), so we have to remap things a bit |
| 53 | // Instruction index represents the 'nth' argument/opcode in the instruction, whereas the operand index is index that XED holds that operand in the instruction |
| 54 | static size_t GetILOperandMemoryAddress(LowLevelILFunction& il, const xed_decoded_inst_t* xedd, const uint64_t addr, const size_t instruction_index, const size_t operand_index) |
| 55 | { |
| 56 | const xed_inst_t* xi = xed_decoded_inst_inst(xedd); |
| 57 | const xed_operand_t* op = xed_inst_operand(xi, (unsigned)operand_index); |
| 58 | const xed_operand_values_t* ov = xed_decoded_inst_operands_const(xedd); |
| 59 | const xed_operand_enum_t op_name = xed_operand_name(op); |
| 60 | size_t offset = BN_INVALID_EXPR; |
| 61 | const size_t addrSize = xed_decoded_inst_get_machine_mode_bits(xedd) / 8; |
| 62 | |
| 63 | switch(op_name) |
| 64 | { |
| 65 | case XED_OPERAND_AGEN: |
| 66 | case XED_OPERAND_MEM0: |
| 67 | { |
| 68 | const int64_t disp = xed_decoded_inst_get_memory_displacement(xedd, 0); |
| 69 | |
| 70 | // [reg] if reg != instruction_pointer |
| 71 | const xed_reg_enum_t base = xed_decoded_inst_get_base_reg(xedd, 0); |
| 72 | if ((base != XED_REG_INVALID) && !((base == XED_REG_RIP) || (base == XED_REG_EIP) || (base == XED_REG_IP))) |
| 73 | { |
| 74 | offset = il.Register(addrSize, base); |
| 75 | } |
| 76 | else if ((base == XED_REG_RIP) || (base == XED_REG_EIP) || (base == XED_REG_IP)) // Resolve RIP to a constant |
| 77 | { |
| 78 | if (xed_operand_values_has_memory_displacement(ov) && (disp != 0)) |
| 79 | return il.Operand(instruction_index, il.ConstPointer(addrSize, disp + addr + xed_decoded_inst_get_length(xedd))); |
| 80 | else |
| 81 | return il.Operand(instruction_index, il.ConstPointer(addrSize, addr + xed_decoded_inst_get_length(xedd))); |
| 82 | } |
| 83 | |
| 84 | // [...+reg] or [...+reg*const] or [reg*const] |
| 85 | const xed_reg_enum_t index = xed_decoded_inst_get_index_reg(xedd, 0); |
| 86 | bool constIsPointer = false; |
| 87 | if (index != XED_REG_INVALID) |
| 88 | if (!xed_decoded_inst_get_attribute(xedd, XED_ATTRIBUTE_INDEX_REG_IS_POINTER)) // MPX...TODO (extra registers) |
| 89 | { |
| 90 | const unsigned int scale = xed_decoded_inst_get_scale(xedd, 0); |
| 91 | if (scale != 1) |
| 92 | { |
| 93 | unsigned short shift = 0; |
| 94 | if (scale == 2) |
| 95 | shift = 1; |
| 96 | else if (scale == 4) |
| 97 | shift = 2; |
| 98 | else if (scale == 8) |
| 99 | shift = 3; |
| 100 | if (offset != BN_INVALID_EXPR) |
| 101 | offset = il.Add(addrSize, |
| 102 | offset, |
| 103 | il.ShiftLeft(addrSize, |
| 104 | il.Register(addrSize, index), |
| 105 | il.Const(1, shift))); |
| 106 | else |
| 107 | { |
| 108 | // case for [...+reg*const] so we know that the const must be a pointer |
| 109 | constIsPointer = true; |
| 110 | offset = il.ShiftLeft(addrSize, |
| 111 | il.Register(addrSize, index), |
no test coverage detected