1 /* 2 * Copyright 2008, François Revol, revol@free.fr 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <OS.h> 7 #include <KernelExport.h> 8 9 #include <debug.h> 10 #include <stdio.h> 11 12 #include "Zycore/Format.h" 13 #include "Zydis/Zydis.h" 14 15 #include "disasm_arch.h" 16 #include "elf.h" 17 18 19 static ZydisDecoder sDecoder; 20 static ZydisFormatter sFormatter; 21 static ZydisFormatterFunc sDefaultPrintAddressAbsolute; 22 23 24 static ZyanStatus 25 ZydisFormatterPrintAddressAbsolute(const ZydisFormatter* formatter, ZydisFormatterBuffer* buffer, 26 ZydisFormatterContext* context) 27 { 28 ZyanU64 address; 29 ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 30 context->runtime_address, &address)); 31 32 const char* symbolName; 33 addr_t baseAddress; 34 status_t error; 35 36 if (IS_KERNEL_ADDRESS(address)) { 37 error = elf_debug_lookup_symbol_address(address, &baseAddress, 38 &symbolName, NULL, NULL); 39 } else { 40 error = elf_debug_lookup_user_symbol_address( 41 debug_get_debugged_thread()->team, address, &baseAddress, 42 &symbolName, NULL, NULL); 43 } 44 45 if (error == B_OK) { 46 ZYAN_CHECK(ZydisFormatterBufferAppend(buffer, ZYDIS_TOKEN_SYMBOL)); 47 ZyanString* string; 48 ZYAN_CHECK(ZydisFormatterBufferGetString(buffer, &string)); 49 int64_t offset = address - baseAddress; 50 if (offset == 0) 51 return ZyanStringAppendFormat(string, "<%s>", symbolName); 52 return ZyanStringAppendFormat(string, "<%s+0x%" B_PRIx64 ">", symbolName, offset); 53 } 54 55 return sDefaultPrintAddressAbsolute(formatter, buffer, context); 56 } 57 58 59 extern "C" void 60 diasm_arch_assert_fail(const char* assertion, const char* file, unsigned int line, 61 const char* function) 62 { 63 kprintf("assert_fail: %s\n", assertion); 64 while (true) 65 ; 66 } 67 68 69 extern "C" void 70 disasm_arch_assert(const char *condition) 71 { 72 kprintf("assert: %s\n", condition); 73 } 74 75 76 status_t 77 disasm_arch_dump_insns(addr_t where, int count, addr_t baseAddress, 78 int backCount) 79 { 80 ZyanU8 buffer[ZYDIS_MAX_INSTRUCTION_LENGTH]; 81 ZydisDecodedInstruction instruction; 82 int skipCount = 0; 83 84 if (backCount > 0) { 85 // count the instructions from base address to start address 86 addr_t address = baseAddress; 87 88 int baseCount = 0; 89 90 while (address < where 91 && debug_memcpy(B_CURRENT_TEAM, &buffer, (const void*)address, sizeof(buffer)) == B_OK 92 && ZYAN_SUCCESS(ZydisDecoderDecodeInstruction(&sDecoder, 93 (ZydisDecoderContext*)ZYAN_NULL, buffer, sizeof(buffer), &instruction))) { 94 address += instruction.length; 95 baseCount++; 96 } 97 98 if (address == where) { 99 if (baseCount > backCount) 100 skipCount = baseCount - backCount; 101 count += baseCount; 102 } else 103 baseAddress = where; 104 } else 105 baseAddress = where; 106 107 ZyanUSize offset = 0; 108 109 for (int i = 0; i < count; i++, offset += instruction.length) { 110 if (debug_memcpy(B_CURRENT_TEAM, &buffer, (const void*)(baseAddress + offset), 111 sizeof(buffer)) 112 != B_OK) { 113 kprintf("<read fault>\n"); 114 break; 115 } 116 ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; 117 if (!ZYAN_SUCCESS(ZydisDecoderDecodeFull(&sDecoder, buffer, sizeof(buffer), &instruction, 118 operands))) { 119 break; 120 } 121 if (skipCount > 0) { 122 skipCount--; 123 continue; 124 } 125 126 addr_t address = baseAddress + offset; 127 if (address == where) 128 kprintf("\x1b[34m"); 129 130 char hexString[32]; 131 char* srcHex = hexString; 132 for (ZyanUSize i = 0; i < instruction.length; i++) { 133 sprintf(srcHex, "%02" PRIx8, buffer[i]); 134 srcHex += 2; 135 } 136 137 char formatted[1024]; 138 if (ZYAN_SUCCESS(ZydisFormatterFormatInstruction(&sFormatter, &instruction, operands, 139 instruction.operand_count_visible, formatted, sizeof(formatted), 140 baseAddress + offset, NULL))) { 141 kprintf("%#16llx: %16.16s\t%s\n", static_cast<unsigned long long>(address), hexString, 142 formatted); 143 } else { 144 kprintf("%#16llx: failed-to-format\n", static_cast<unsigned long long>(address)); 145 } 146 if (address == where) 147 kprintf("\x1b[m"); 148 } 149 return B_OK; 150 } 151 152 153 status_t 154 disasm_arch_init() 155 { 156 #ifdef __x86_64__ 157 ZydisDecoderInit(&sDecoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64); 158 #else 159 ZydisDecoderInit(&sDecoder, ZYDIS_MACHINE_MODE_LEGACY_32, ZYDIS_STACK_WIDTH_32); 160 #endif 161 162 ZydisFormatterInit(&sFormatter, ZYDIS_FORMATTER_STYLE_ATT); 163 ZydisFormatterSetProperty(&sFormatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE); 164 ZydisFormatterSetProperty(&sFormatter, ZYDIS_FORMATTER_PROP_HEX_UPPERCASE, ZYAN_FALSE); 165 ZydisFormatterSetProperty(&sFormatter, ZYDIS_FORMATTER_PROP_ADDR_PADDING_ABSOLUTE, 166 ZYDIS_PADDING_DISABLED); 167 ZydisFormatterSetProperty(&sFormatter, ZYDIS_FORMATTER_PROP_ADDR_PADDING_RELATIVE, 168 ZYDIS_PADDING_DISABLED); 169 ZydisFormatterSetProperty(&sFormatter, ZYDIS_FORMATTER_PROP_DISP_PADDING, 170 ZYDIS_PADDING_DISABLED); 171 ZydisFormatterSetProperty(&sFormatter, ZYDIS_FORMATTER_PROP_IMM_PADDING, 172 ZYDIS_PADDING_DISABLED); 173 174 sDefaultPrintAddressAbsolute = (ZydisFormatterFunc)&ZydisFormatterPrintAddressAbsolute; 175 ZydisFormatterSetHook(&sFormatter, ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS, 176 (const void**)&sDefaultPrintAddressAbsolute); 177 178 // XXX: check for AMD and set sVendor; 179 return B_OK; 180 } 181 182 183 status_t 184 disasm_arch_fini() 185 { 186 return B_OK; 187 } 188 189 190