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