1 /* 2 * Routines for host instruction disassembly. 3 * SPDX-License-Identifier: GPL-2.0-or-later 4 */ 5 6 #include "qemu/osdep.h" 7 #include "disas/disas.h" 8 #include "disas/capstone.h" 9 #include "disas-internal.h" 10 11 12 /* 13 * Get LENGTH bytes from info's buffer, at host address memaddr. 14 * Transfer them to myaddr. 15 */ 16 static int host_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, 17 struct disassemble_info *info) 18 { 19 if (memaddr < info->buffer_vma 20 || memaddr + length > info->buffer_vma + info->buffer_length) { 21 /* Out of bounds. Use EIO because GDB uses it. */ 22 return EIO; 23 } 24 memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length); 25 return 0; 26 } 27 28 /* Print address in hex, truncated to the width of a host virtual address. */ 29 static void host_print_address(bfd_vma addr, struct disassemble_info *info) 30 { 31 info->fprintf_func(info->stream, "0x%" PRIxPTR, (uintptr_t)addr); 32 } 33 34 static void initialize_debug_host(CPUDebug *s) 35 { 36 disas_initialize_debug(s); 37 38 s->info.read_memory_func = host_read_memory; 39 s->info.print_address_func = host_print_address; 40 #if HOST_BIG_ENDIAN 41 s->info.endian = BFD_ENDIAN_BIG; 42 #else 43 s->info.endian = BFD_ENDIAN_LITTLE; 44 #endif 45 #if defined(CONFIG_TCG_INTERPRETER) 46 s->info.print_insn = print_insn_tci; 47 #elif defined(__i386__) 48 s->info.mach = bfd_mach_i386_i386; 49 s->info.cap_arch = CS_ARCH_X86; 50 s->info.cap_mode = CS_MODE_32; 51 s->info.cap_insn_unit = 1; 52 s->info.cap_insn_split = 8; 53 #elif defined(__x86_64__) 54 s->info.mach = bfd_mach_x86_64; 55 s->info.cap_arch = CS_ARCH_X86; 56 s->info.cap_mode = CS_MODE_64; 57 s->info.cap_insn_unit = 1; 58 s->info.cap_insn_split = 8; 59 #elif defined(_ARCH_PPC) 60 s->info.cap_arch = CS_ARCH_PPC; 61 # ifdef _ARCH_PPC64 62 s->info.cap_mode = CS_MODE_64; 63 # endif 64 #elif defined(__riscv) 65 #if defined(_ILP32) || (__riscv_xlen == 32) 66 s->info.print_insn = print_insn_riscv32; 67 #elif defined(_LP64) 68 s->info.print_insn = print_insn_riscv64; 69 #else 70 #error unsupported RISC-V ABI 71 #endif 72 #elif defined(__aarch64__) 73 s->info.cap_arch = CS_ARCH_ARM64; 74 #elif defined(__alpha__) 75 s->info.print_insn = print_insn_alpha; 76 #elif defined(__sparc__) 77 s->info.print_insn = print_insn_sparc; 78 s->info.mach = bfd_mach_sparc_v9b; 79 #elif defined(__arm__) 80 /* TCG only generates code for arm mode. */ 81 s->info.cap_arch = CS_ARCH_ARM; 82 #elif defined(__MIPSEB__) 83 s->info.print_insn = print_insn_big_mips; 84 #elif defined(__MIPSEL__) 85 s->info.print_insn = print_insn_little_mips; 86 #elif defined(__m68k__) 87 s->info.print_insn = print_insn_m68k; 88 #elif defined(__s390__) 89 s->info.cap_arch = CS_ARCH_SYSZ; 90 s->info.cap_insn_unit = 2; 91 s->info.cap_insn_split = 6; 92 #elif defined(__hppa__) 93 s->info.print_insn = print_insn_hppa; 94 #elif defined(__loongarch__) 95 s->info.print_insn = print_insn_loongarch; 96 #endif 97 } 98 99 /* Disassemble this for me please... (debugging). */ 100 void disas(FILE *out, const void *code, size_t size) 101 { 102 uintptr_t pc; 103 int count; 104 CPUDebug s; 105 106 initialize_debug_host(&s); 107 s.info.fprintf_func = fprintf; 108 s.info.stream = out; 109 s.info.buffer = code; 110 s.info.buffer_vma = (uintptr_t)code; 111 s.info.buffer_length = size; 112 s.info.show_opcodes = true; 113 114 if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) { 115 return; 116 } 117 118 if (s.info.print_insn == NULL) { 119 s.info.print_insn = print_insn_od_host; 120 } 121 for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) { 122 fprintf(out, "0x%08" PRIxPTR ": ", pc); 123 count = s.info.print_insn(pc, &s.info); 124 fprintf(out, "\n"); 125 if (count < 0) { 126 break; 127 } 128 } 129 } 130