2 * Routines for host instruction disassembly.
3 * SPDX-License-Identifier: GPL-2.0-or-later
6 #include "qemu/osdep.h"
7 #include "disas/disas.h"
8 #include "disas/capstone.h"
9 #include "disas-internal.h"
13 * Get LENGTH bytes from info's buffer, at host address memaddr.
14 * Transfer them to myaddr.
16 static int host_read_memory(bfd_vma memaddr
, bfd_byte
*myaddr
, int length
,
17 struct disassemble_info
*info
)
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. */
24 memcpy (myaddr
, info
->buffer
+ (memaddr
- info
->buffer_vma
), length
);
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
)
31 info
->fprintf_func(info
->stream
, "0x%" PRIxPTR
, (uintptr_t)addr
);
34 static void initialize_debug_host(CPUDebug
*s
)
36 disas_initialize_debug(s
);
38 s
->info
.read_memory_func
= host_read_memory
;
39 s
->info
.print_address_func
= host_print_address
;
41 s
->info
.endian
= BFD_ENDIAN_BIG
;
43 s
->info
.endian
= BFD_ENDIAN_LITTLE
;
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
;
62 s
->info
.cap_mode
= CS_MODE_64
;
64 #elif defined(__riscv)
65 #if defined(_ILP32) || (__riscv_xlen == 32)
66 s
->info
.print_insn
= print_insn_riscv32
;
68 s
->info
.print_insn
= print_insn_riscv64
;
70 #error unsupported RISC-V ABI
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
;
99 /* Disassemble this for me please... (debugging). */
100 void disas(FILE *out
, const void *code
, size_t size
)
106 initialize_debug_host(&s
);
107 s
.info
.fprintf_func
= fprintf
;
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;
114 if (s
.info
.cap_arch
>= 0 && cap_disas_host(&s
.info
, code
, size
)) {
118 if (s
.info
.print_insn
== NULL
) {
119 s
.info
.print_insn
= print_insn_od_host
;
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
);