diff options
Diffstat (limited to 'disassembler')
-rw-r--r-- | disassembler/Android.mk | 4 | ||||
-rw-r--r-- | disassembler/disassembler.h | 2 | ||||
-rw-r--r-- | disassembler/disassembler_arm.cc | 49 | ||||
-rw-r--r-- | disassembler/disassembler_arm64.h | 3 | ||||
-rw-r--r-- | disassembler/disassembler_x86.cc | 108 |
5 files changed, 95 insertions, 71 deletions
diff --git a/disassembler/Android.mk b/disassembler/Android.mk index eb3b024..f2dd1ee 100644 --- a/disassembler/Android.mk +++ b/disassembler/Android.mk @@ -84,11 +84,11 @@ define build-libart-disassembler LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk include external/libcxx/libcxx.mk + # For disassembler_arm64. + LOCAL_SHARED_LIBRARIES += libvixl ifeq ($$(art_target_or_host),target) - LOCAL_SHARED_LIBRARIES += libcutils libvixl include $(BUILD_SHARED_LIBRARY) else # host - LOCAL_STATIC_LIBRARIES += libcutils libvixl include $(BUILD_HOST_SHARED_LIBRARY) endif endef diff --git a/disassembler/disassembler.h b/disassembler/disassembler.h index 1d827ba..966ee3a 100644 --- a/disassembler/disassembler.h +++ b/disassembler/disassembler.h @@ -21,8 +21,8 @@ #include <iosfwd> +#include "arch/instruction_set.h" #include "base/macros.h" -#include "instruction_set.h" namespace art { diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc index ee652b3..9243b1a 100644 --- a/disassembler/disassembler_arm.cc +++ b/disassembler/disassembler_arm.cc @@ -125,8 +125,10 @@ static const char* kThumbReverseOperations[] = { }; struct ArmRegister { - explicit ArmRegister(uint32_t r) : r(r) { CHECK_LE(r, 15U); } - ArmRegister(uint32_t instruction, uint32_t at_bit) : r((instruction >> at_bit) & 0xf) { CHECK_LE(r, 15U); } + explicit ArmRegister(uint32_t r_in) : r(r_in) { CHECK_LE(r_in, 15U); } + ArmRegister(uint32_t instruction, uint32_t at_bit) : r((instruction >> at_bit) & 0xf) { + CHECK_LE(r, 15U); + } uint32_t r; }; std::ostream& operator<<(std::ostream& os, const ArmRegister& r) { @@ -390,7 +392,7 @@ uint32_t VFPExpand32(uint32_t imm8) { return (bit_a << 31) | ((1 << 30) - (bit_b << 25)) | (slice << 19); } -uint64_t VFPExpand64(uint32_t imm8) { +static uint64_t VFPExpand64(uint32_t imm8) { CHECK_EQ(imm8 & 0xffu, imm8); uint64_t bit_a = (imm8 >> 7) & 1; uint64_t bit_b = (imm8 >> 6) & 1; @@ -398,45 +400,6 @@ uint64_t VFPExpand64(uint32_t imm8) { return (bit_a << 31) | ((UINT64_C(1) << 62) - (bit_b << 54)) | (slice << 48); } -uint64_t AdvSIMDExpand(uint32_t op, uint32_t cmode, uint32_t imm8) { - CHECK_EQ(op & 1, op); - CHECK_EQ(cmode & 0xf, cmode); - CHECK_EQ(imm8 & 0xff, imm8); - int32_t cmode321 = cmode >> 1; - if (imm8 == 0 && cmode321 != 0 && cmode321 != 4 && cmode321 != 7) { - return INT64_C(0x00000000deadbeef); // UNPREDICTABLE - } - uint64_t imm = imm8; - switch (cmode321) { - case 3: imm <<= 8; FALLTHROUGH_INTENDED; - case 2: imm <<= 8; FALLTHROUGH_INTENDED; - case 1: imm <<= 8; FALLTHROUGH_INTENDED; - case 0: return static_cast<int64_t>((imm << 32) | imm); - case 5: imm <<= 8; FALLTHROUGH_INTENDED; - case 4: return static_cast<int64_t>((imm << 48) | (imm << 32) | (imm << 16) | imm); - case 6: - imm = ((imm + 1u) << ((cmode & 1) != 0 ? 16 : 8)) - 1u; // Add 8 or 16 ones. - return static_cast<int64_t>((imm << 32) | imm); - default: - CHECK_EQ(cmode321, 7); - if ((cmode & 1) == 0 && op == 0) { - imm = (imm << 8) | imm; - return static_cast<int64_t>((imm << 48) | (imm << 32) | (imm << 16) | imm); - } else if ((cmode & 1) == 0 && op != 0) { - for (int i = 1; i != 8; ++i) { - imm |= ((imm >> i) & UINT64_C(1)) << (i * 8); - } - imm = imm & ~UINT64_C(0xfe); - return static_cast<int64_t>((imm << 8) - imm); - } else if ((cmode & 1) != 0 && op == 0) { - imm = static_cast<uint32_t>(VFPExpand32(imm8)); - return static_cast<int64_t>((imm << 32) | imm); - } else { - return INT64_C(0xdeadbeef00000000); // UNDEFINED - } - } -} - size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr) { uint32_t instr = (ReadU16(instr_ptr) << 16) | ReadU16(instr_ptr + 2); // |111|1 1|1000000|0000|1111110000000000| @@ -1359,8 +1322,6 @@ size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr) } } else { // STR Rt, [Rn, Rm, LSL #imm2] - 111 11 000 010 0 nnnn tttt 000000iimmmm - ArmRegister Rn(instr, 16); - ArmRegister Rt(instr, 12); ArmRegister Rm(instr, 0); uint32_t imm2 = (instr >> 4) & 3; opcode << "str.w"; diff --git a/disassembler/disassembler_arm64.h b/disassembler/disassembler_arm64.h index 96a4dd0..a370b8d 100644 --- a/disassembler/disassembler_arm64.h +++ b/disassembler/disassembler_arm64.h @@ -19,8 +19,11 @@ #include "disassembler.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" #include "a64/decoder-a64.h" #include "a64/disasm-a64.h" +#pragma GCC diagnostic pop namespace art { namespace arm64 { diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc index b9e98f6..b3af8a6 100644 --- a/disassembler/disassembler_x86.cc +++ b/disassembler/disassembler_x86.cc @@ -159,7 +159,6 @@ size_t DisassemblerX86::DumpInstruction(std::ostream& os, const uint8_t* instr) const uint8_t* begin_instr = instr; bool have_prefixes = true; uint8_t prefix[4] = {0, 0, 0, 0}; - const char** modrm_opcodes = NULL; do { switch (*instr) { // Group 1 - lock and repeat prefixes: @@ -197,6 +196,7 @@ size_t DisassemblerX86::DumpInstruction(std::ostream& os, const uint8_t* instr) if (rex != 0) { instr++; } + const char** modrm_opcodes = nullptr; bool has_modrm = false; bool reg_is_opcode = false; size_t immediate_bytes = 0; @@ -205,7 +205,9 @@ size_t DisassemblerX86::DumpInstruction(std::ostream& os, const uint8_t* instr) bool store = false; // stores to memory (ie rm is on the left) bool load = false; // loads from memory (ie rm is on the right) bool byte_operand = false; // true when the opcode is dealing with byte operands - bool byte_second_operand = false; // true when the source operand is a byte register but the target register isn't (ie movsxb/movzxb). + // true when the source operand is a byte register but the target register isn't + // (ie movsxb/movzxb). + bool byte_second_operand = false; bool target_specific = false; // register name depends on target (64 vs 32 bits). bool ax = false; // implicit use of ax bool cx = false; // implicit use of cx @@ -629,7 +631,9 @@ DISASSEMBLER_ENTRY(cmp, } else { dst_reg_file = MMX; } - static const char* x71_opcodes[] = {"unknown-71", "unknown-71", "psrlw", "unknown-71", "psraw", "unknown-71", "psllw", "unknown-71"}; + static const char* x71_opcodes[] = { + "unknown-71", "unknown-71", "psrlw", "unknown-71", + "psraw", "unknown-71", "psllw", "unknown-71"}; modrm_opcodes = x71_opcodes; reg_is_opcode = true; has_modrm = true; @@ -643,7 +647,9 @@ DISASSEMBLER_ENTRY(cmp, } else { dst_reg_file = MMX; } - static const char* x72_opcodes[] = {"unknown-72", "unknown-72", "psrld", "unknown-72", "psrad", "unknown-72", "pslld", "unknown-72"}; + static const char* x72_opcodes[] = { + "unknown-72", "unknown-72", "psrld", "unknown-72", + "psrad", "unknown-72", "pslld", "unknown-72"}; modrm_opcodes = x72_opcodes; reg_is_opcode = true; has_modrm = true; @@ -657,7 +663,9 @@ DISASSEMBLER_ENTRY(cmp, } else { dst_reg_file = MMX; } - static const char* x73_opcodes[] = {"unknown-73", "unknown-73", "psrlq", "psrldq", "unknown-73", "unknown-73", "psllq", "unknown-73"}; + static const char* x73_opcodes[] = { + "unknown-73", "unknown-73", "psrlq", "psrldq", + "unknown-73", "unknown-73", "psllq", "unknown-73"}; modrm_opcodes = x73_opcodes; reg_is_opcode = true; has_modrm = true; @@ -698,7 +706,7 @@ DISASSEMBLER_ENTRY(cmp, case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D: case 0x9E: case 0x9F: opcode << "set" << condition_codes[*instr & 0xF]; - modrm_opcodes = NULL; + modrm_opcodes = nullptr; reg_is_opcode = true; has_modrm = true; store = true; @@ -730,7 +738,9 @@ DISASSEMBLER_ENTRY(cmp, case 0xAE: if (prefix[0] == 0xF3) { prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode - static const char* xAE_opcodes[] = {"rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase", "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE"}; + static const char* xAE_opcodes[] = { + "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase", + "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE"}; modrm_opcodes = xAE_opcodes; reg_is_opcode = true; has_modrm = true; @@ -757,7 +767,9 @@ DISASSEMBLER_ENTRY(cmp, break; } } else { - static const char* xAE_opcodes[] = {"unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE", "lfence", "mfence", "sfence"}; + static const char* xAE_opcodes[] = { + "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE", + "unknown-AE", "lfence", "mfence", "sfence"}; modrm_opcodes = xAE_opcodes; reg_is_opcode = true; has_modrm = true; @@ -765,13 +777,44 @@ DISASSEMBLER_ENTRY(cmp, no_ops = true; } break; - case 0xAF: opcode << "imul"; has_modrm = true; load = true; break; - case 0xB1: opcode << "cmpxchg"; has_modrm = true; store = true; break; - case 0xB6: opcode << "movzxb"; has_modrm = true; load = true; byte_second_operand = true; break; - case 0xB7: opcode << "movzxw"; has_modrm = true; load = true; break; - case 0xBE: opcode << "movsxb"; has_modrm = true; load = true; byte_second_operand = true; rex |= (rex == 0 ? 0 : REX_W); break; - case 0xBF: opcode << "movsxw"; has_modrm = true; load = true; break; - case 0xC3: opcode << "movnti"; store = true; has_modrm = true; break; + case 0xAF: + opcode << "imul"; + has_modrm = true; + load = true; + break; + case 0xB1: + opcode << "cmpxchg"; + has_modrm = true; + store = true; + break; + case 0xB6: + opcode << "movzxb"; + has_modrm = true; + load = true; + byte_second_operand = true; + break; + case 0xB7: + opcode << "movzxw"; + has_modrm = true; + load = true; + break; + case 0xBE: + opcode << "movsxb"; + has_modrm = true; + load = true; + byte_second_operand = true; + rex |= (rex == 0 ? 0 : REX_W); + break; + case 0xBF: + opcode << "movsxw"; + has_modrm = true; + load = true; + break; + case 0xC3: + opcode << "movnti"; + store = true; + has_modrm = true; + break; case 0xC5: if (prefix[2] == 0x66) { opcode << "pextrw"; @@ -797,7 +840,9 @@ DISASSEMBLER_ENTRY(cmp, immediate_bytes = 1; break; case 0xC7: - static const char* x0FxC7_opcodes[] = { "unknown-0f-c7", "cmpxchg8b", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7" }; + static const char* x0FxC7_opcodes[] = { + "unknown-0f-c7", "cmpxchg8b", "unknown-0f-c7", "unknown-0f-c7", + "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7"}; modrm_opcodes = x0FxC7_opcodes; has_modrm = true; reg_is_opcode = true; @@ -973,7 +1018,9 @@ DISASSEMBLER_ENTRY(cmp, break; case 0xC3: opcode << "ret"; break; case 0xC6: - static const char* c6_opcodes[] = {"mov", "unknown-c6", "unknown-c6", "unknown-c6", "unknown-c6", "unknown-c6", "unknown-c6", "unknown-c6"}; + static const char* c6_opcodes[] = {"mov", "unknown-c6", "unknown-c6", + "unknown-c6", "unknown-c6", "unknown-c6", + "unknown-c6", "unknown-c6"}; modrm_opcodes = c6_opcodes; store = true; immediate_bytes = 1; @@ -982,7 +1029,9 @@ DISASSEMBLER_ENTRY(cmp, byte_operand = true; break; case 0xC7: - static const char* c7_opcodes[] = {"mov", "unknown-c7", "unknown-c7", "unknown-c7", "unknown-c7", "unknown-c7", "unknown-c7", "unknown-c7"}; + static const char* c7_opcodes[] = {"mov", "unknown-c7", "unknown-c7", + "unknown-c7", "unknown-c7", "unknown-c7", + "unknown-c7", "unknown-c7"}; modrm_opcodes = c7_opcodes; store = true; immediate_bytes = 4; @@ -1012,21 +1061,27 @@ DISASSEMBLER_ENTRY(cmp, } break; case 0xDB: - static const char* db_opcodes[] = {"fildl", "unknown-db", "unknown-db", "unknown-db", "unknown-db", "unknown-db", "unknown-db", "unknown-db"}; + static const char* db_opcodes[] = {"fildl", "unknown-db", "unknown-db", + "unknown-db", "unknown-db", "unknown-db", + "unknown-db", "unknown-db"}; modrm_opcodes = db_opcodes; load = true; has_modrm = true; reg_is_opcode = true; break; case 0xDD: - static const char* dd_opcodes[] = {"fldl", "fisttp", "fstl", "fstpl", "frstor", "unknown-dd", "fnsave", "fnstsw"}; + static const char* dd_opcodes[] = {"fldl", "fisttp", "fstl", + "fstpl", "frstor", "unknown-dd", + "fnsave", "fnstsw"}; modrm_opcodes = dd_opcodes; store = true; has_modrm = true; reg_is_opcode = true; break; case 0xDF: - static const char* df_opcodes[] = {"fild", "unknown-df", "unknown-df", "unknown-df", "unknown-df", "fildll", "unknown-df", "unknown-df"}; + static const char* df_opcodes[] = {"fild", "unknown-df", "unknown-df", + "unknown-df", "unknown-df", "fildll", + "unknown-df", "unknown-df"}; modrm_opcodes = df_opcodes; load = true; has_modrm = true; @@ -1038,7 +1093,10 @@ DISASSEMBLER_ENTRY(cmp, case 0xEB: opcode << "jmp"; branch_bytes = 1; break; case 0xF5: opcode << "cmc"; break; case 0xF6: case 0xF7: - static const char* f7_opcodes[] = {"test", "unknown-f7", "not", "neg", "mul edx:eax, eax *", "imul edx:eax, eax *", "div edx:eax, edx:eax /", "idiv edx:eax, edx:eax /"}; + static const char* f7_opcodes[] = { + "test", "unknown-f7", "not", "neg", "mul edx:eax, eax *", + "imul edx:eax, eax *", "div edx:eax, edx:eax /", + "idiv edx:eax, edx:eax /"}; modrm_opcodes = f7_opcodes; has_modrm = true; reg_is_opcode = true; @@ -1047,7 +1105,9 @@ DISASSEMBLER_ENTRY(cmp, break; case 0xFF: { - static const char* ff_opcodes[] = {"inc", "dec", "call", "call", "jmp", "jmp", "push", "unknown-ff"}; + static const char* ff_opcodes[] = { + "inc", "dec", "call", "call", + "jmp", "jmp", "push", "unknown-ff"}; modrm_opcodes = ff_opcodes; has_modrm = true; reg_is_opcode = true; @@ -1148,7 +1208,7 @@ DISASSEMBLER_ENTRY(cmp, } } - if (reg_is_opcode && modrm_opcodes != NULL) { + if (reg_is_opcode && modrm_opcodes != nullptr) { opcode << modrm_opcodes[reg_or_opcode]; } |