1 /* 2 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. 3 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. 4 * Copyright 2008, François Revol, revol@free.fr 5 * Copyright 2016, Rene Gollent, rene@gollent.com. 6 * Distributed under the terms of the MIT License. 7 */ 8 9 #include "DisassemblerX8664.h" 10 11 #include <new> 12 13 #include "Zycore/Format.h" 14 #include "Zydis/Zydis.h" 15 16 #include <OS.h> 17 18 19 #include "CpuStateX8664.h" 20 #include "InstructionInfo.h" 21 22 23 void 24 CpuStateToZydisRegContext(CpuStateX8664* state, ZydisRegisterContext* context) 25 { 26 context->values[ZYDIS_REGISTER_RAX] = state->IntRegisterValue(X86_64_REGISTER_RAX); 27 context->values[ZYDIS_REGISTER_RSP] = state->IntRegisterValue(X86_64_REGISTER_RSP); 28 context->values[ZYDIS_REGISTER_RIP] = state->IntRegisterValue(X86_64_REGISTER_RIP); 29 // context->values[ZYDIS_REGISTER_RFLAGS] = eflags; 30 context->values[ZYDIS_REGISTER_RCX] = state->IntRegisterValue(X86_64_REGISTER_RCX); 31 context->values[ZYDIS_REGISTER_RDX] = state->IntRegisterValue(X86_64_REGISTER_RDX); 32 context->values[ZYDIS_REGISTER_RBX] = state->IntRegisterValue(X86_64_REGISTER_RBX); 33 context->values[ZYDIS_REGISTER_RBP] = state->IntRegisterValue(X86_64_REGISTER_RBP); 34 context->values[ZYDIS_REGISTER_RSI] = state->IntRegisterValue(X86_64_REGISTER_RSI); 35 context->values[ZYDIS_REGISTER_RDI] = state->IntRegisterValue(X86_64_REGISTER_RDI); 36 context->values[ZYDIS_REGISTER_R8] = state->IntRegisterValue(X86_64_REGISTER_R8); 37 context->values[ZYDIS_REGISTER_R9] = state->IntRegisterValue(X86_64_REGISTER_R9); 38 context->values[ZYDIS_REGISTER_R10] = state->IntRegisterValue(X86_64_REGISTER_R10); 39 context->values[ZYDIS_REGISTER_R11] = state->IntRegisterValue(X86_64_REGISTER_R11); 40 context->values[ZYDIS_REGISTER_R12] = state->IntRegisterValue(X86_64_REGISTER_R12); 41 context->values[ZYDIS_REGISTER_R13] = state->IntRegisterValue(X86_64_REGISTER_R13); 42 context->values[ZYDIS_REGISTER_R14] = state->IntRegisterValue(X86_64_REGISTER_R14); 43 context->values[ZYDIS_REGISTER_R15] = state->IntRegisterValue(X86_64_REGISTER_R15); 44 } 45 46 47 struct DisassemblerX8664::ZydisData { 48 ZydisDecoder decoder ; 49 ZydisFormatter formatter; 50 ZyanUSize offset; 51 }; 52 53 54 DisassemblerX8664::DisassemblerX8664() 55 : 56 fAddress(0), 57 fCode(NULL), 58 fCodeSize(0), 59 fZydisData(NULL) 60 { 61 } 62 63 64 DisassemblerX8664::~DisassemblerX8664() 65 { 66 delete fZydisData; 67 } 68 69 70 status_t 71 DisassemblerX8664::Init(target_addr_t address, const void* code, size_t codeSize) 72 { 73 // unset old data 74 delete fZydisData; 75 fZydisData = NULL; 76 77 // set new data 78 fZydisData = new(std::nothrow) ZydisData; 79 if (fZydisData == NULL) 80 return B_NO_MEMORY; 81 82 fAddress = address; 83 fCode = (const uint8*)code; 84 fCodeSize = codeSize; 85 86 // init zydis 87 fZydisData->offset = 0; 88 ZydisDecoderInit(&fZydisData->decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64); 89 ZydisFormatterInit(&fZydisData->formatter, ZYDIS_FORMATTER_STYLE_ATT); 90 ZydisFormatterSetProperty(&fZydisData->formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE); 91 ZydisFormatterSetProperty(&fZydisData->formatter, ZYDIS_FORMATTER_PROP_HEX_UPPERCASE, 92 ZYAN_FALSE); 93 ZydisFormatterSetProperty(&fZydisData->formatter, ZYDIS_FORMATTER_PROP_ADDR_PADDING_ABSOLUTE, 94 ZYDIS_PADDING_DISABLED); 95 ZydisFormatterSetProperty(&fZydisData->formatter, ZYDIS_FORMATTER_PROP_ADDR_PADDING_RELATIVE, 96 ZYDIS_PADDING_DISABLED); 97 ZydisFormatterSetProperty(&fZydisData->formatter, ZYDIS_FORMATTER_PROP_DISP_PADDING, 98 ZYDIS_PADDING_DISABLED); 99 ZydisFormatterSetProperty(&fZydisData->formatter, ZYDIS_FORMATTER_PROP_IMM_PADDING, 100 ZYDIS_PADDING_DISABLED); 101 // TODO: Set the correct vendor! 102 103 return B_OK; 104 } 105 106 107 status_t 108 DisassemblerX8664::GetNextInstruction(BString& line, target_addr_t& _address, 109 target_size_t& _size, bool& _breakpointAllowed) 110 { 111 const uint8* buffer = fCode + fZydisData->offset; 112 ZydisDecodedInstruction instruction; 113 ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; 114 if (!ZYAN_SUCCESS(ZydisDecoderDecodeFull(&fZydisData->decoder, buffer, 115 fCodeSize - fZydisData->offset, &instruction, operands))) { 116 return B_ENTRY_NOT_FOUND; 117 } 118 119 target_addr_t address = fAddress + fZydisData->offset; 120 fZydisData->offset += instruction.length; 121 122 char hexString[32]; 123 char* srcHex = hexString; 124 for (ZyanUSize i = 0; i < instruction.length; i++) { 125 sprintf(srcHex, "%02" PRIx8, buffer[i]); 126 srcHex += 2; 127 } 128 129 char formatted[1024]; 130 if (ZYAN_SUCCESS(ZydisFormatterFormatInstruction(&fZydisData->formatter, &instruction, operands, 131 instruction.operand_count_visible, formatted, sizeof(formatted), address, NULL))) { 132 line.SetToFormat("0x%016" B_PRIx64 ": %16.16s %s", address, hexString, formatted); 133 } else { 134 line.SetToFormat("0x%016" B_PRIx64 ": failed-to-format", address); 135 } 136 // TODO: Resolve symbols! 137 138 _address = address; 139 _size = instruction.length; 140 _breakpointAllowed = true; 141 // TODO: Implement (rep!)! 142 143 return B_OK; 144 } 145 146 147 status_t 148 DisassemblerX8664::GetPreviousInstruction(target_addr_t nextAddress, 149 target_addr_t& _address, target_size_t& _size) 150 { 151 if (nextAddress < fAddress || nextAddress > fAddress + fCodeSize) 152 return B_BAD_VALUE; 153 154 // loop until hitting the last instruction 155 while (true) { 156 const uint8* buffer = fCode + fZydisData->offset; 157 ZydisDecodedInstruction instruction; 158 if (!ZYAN_SUCCESS(ZydisDecoderDecodeInstruction(&fZydisData->decoder, 159 (ZydisDecoderContext*)ZYAN_NULL, buffer, fCodeSize - fZydisData->offset, 160 &instruction))) { 161 return B_ENTRY_NOT_FOUND; 162 } 163 164 fZydisData->offset += instruction.length; 165 target_addr_t address = fAddress + fZydisData->offset; 166 if (address == nextAddress) { 167 _address = address; 168 _size = instruction.length; 169 return B_OK; 170 } 171 } 172 } 173 174 175 status_t 176 DisassemblerX8664::GetNextInstructionInfo(InstructionInfo& _info, 177 CpuState* state) 178 { 179 const uint8* buffer = fCode + fZydisData->offset; 180 ZydisDecodedInstruction instruction; 181 ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; 182 if (!ZYAN_SUCCESS(ZydisDecoderDecodeFull(&fZydisData->decoder, buffer, 183 fCodeSize - fZydisData->offset, &instruction, operands))) { 184 return B_ENTRY_NOT_FOUND; 185 } 186 187 target_addr_t address = fAddress + fZydisData->offset; 188 fZydisData->offset += instruction.length; 189 190 char hexString[32]; 191 char* srcHex = hexString; 192 for (ZyanUSize i = 0; i < instruction.length; i++) { 193 sprintf(srcHex, "%02" PRIx8, buffer[i]); 194 srcHex += 2; 195 } 196 197 instruction_type type = INSTRUCTION_TYPE_OTHER; 198 target_addr_t targetAddress = 0; 199 if (instruction.mnemonic == ZYDIS_MNEMONIC_CALL) 200 type = INSTRUCTION_TYPE_SUBROUTINE_CALL; 201 else if (instruction.mnemonic == ZYDIS_MNEMONIC_JMP) 202 type = INSTRUCTION_TYPE_JUMP; 203 if (state != NULL) { 204 CpuStateX8664* x64State = dynamic_cast<CpuStateX8664*>(state); 205 if (x64State != NULL) { 206 ZydisRegisterContext registers; 207 CpuStateToZydisRegContext(x64State, ®isters); 208 ZYAN_CHECK(ZydisCalcAbsoluteAddressEx(&instruction, operands, 209 address, ®isters, &targetAddress)); 210 } 211 } 212 213 char string[1024]; 214 int written = snprintf(string, sizeof(string), "0x%016" B_PRIx64 ": %16.16s ", address, 215 hexString); 216 char* formatted = string + written; 217 if (!ZYAN_SUCCESS(ZydisFormatterFormatInstruction(&fZydisData->formatter, &instruction, 218 operands, instruction.operand_count_visible, formatted, sizeof(string) - written, 219 address, NULL))) { 220 snprintf(string, sizeof(string), "0x%016" B_PRIx64 ": failed-to-format", address); 221 } 222 223 // TODO: Resolve symbols! 224 225 if (!_info.SetTo(address, targetAddress, instruction.length, type, true, string)) 226 return B_NO_MEMORY; 227 228 return B_OK; 229 } 230 231