master
c 118 lines 3.32 KB
Raw
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(__x86_64__)
48 s->info.mach = bfd_mach_x86_64;
49 s->info.cap_arch = CS_ARCH_X86;
50 s->info.cap_mode = CS_MODE_64;
51 s->info.cap_insn_unit = 1;
52 s->info.cap_insn_split = 8;
53 #elif defined(_ARCH_PPC64)
54 s->info.cap_arch = CS_ARCH_PPC;
55 s->info.cap_mode = CS_MODE_64;
56 #elif defined(__riscv)
57 #if defined(_ILP32) || (__riscv_xlen == 32)
58 s->info.print_insn = print_insn_riscv32;
59 #elif defined(_LP64)
60 s->info.print_insn = print_insn_riscv64;
61 #else
62 #error unsupported RISC-V ABI
63 #endif
64 #elif defined(__aarch64__)
65 s->info.cap_arch = CS_ARCH_ARM64;
66 #elif defined(__alpha__)
67 s->info.print_insn = print_insn_alpha;
68 #elif defined(__sparc__)
69 s->info.print_insn = print_insn_sparc;
70 s->info.mach = bfd_mach_sparc_v9b;
71 #elif defined(__MIPSEB__)
72 s->info.print_insn = print_insn_big_mips;
73 #elif defined(__MIPSEL__)
74 s->info.print_insn = print_insn_little_mips;
75 #elif defined(__m68k__)
76 s->info.print_insn = print_insn_m68k;
77 #elif defined(__s390x__)
78 s->info.cap_arch = CS_ARCH_SYSTEMZ;
79 s->info.cap_insn_unit = 2;
80 s->info.cap_insn_split = 6;
81 #elif defined(__hppa__)
82 s->info.print_insn = print_insn_hppa;
83 #elif defined(__loongarch__)
84 s->info.print_insn = print_insn_loongarch;
85 #endif
86 }
87
88 /* Disassemble this for me please... (debugging). */
89 void disas(FILE *out, const void *code, size_t size)
90 {
91 uintptr_t pc;
92 int count;
93 CPUDebug s;
94
95 initialize_debug_host(&s);
96 s.info.fprintf_func = fprintf;
97 s.info.stream = out;
98 s.info.buffer = code;
99 s.info.buffer_vma = (uintptr_t)code;
100 s.info.buffer_length = size;
101 s.info.show_opcodes = true;
102
103 if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) {
104 return;
105 }
106
107 if (s.info.print_insn == NULL) {
108 s.info.print_insn = print_insn_od_host;
109 }
110 for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
111 fprintf(out, "0x%08" PRIxPTR ": ", pc);
112 count = s.info.print_insn(pc, &s.info);
113 fprintf(out, "\n");
114 if (count < 0) {
115 break;
116 }
117 }
118 }