2 * Common routines for 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 "hw/core/cpu.h"
10 #include "exec/tswap.h"
11 #include "disas-internal.h"
14 /* Filled in by elfload.c. Simplistic, but will do for now. */
15 struct syminfo
*syminfos
= NULL
;
18 * Print an error message. We can assume that this is in response to
19 * an error return from {host,target}_read_memory.
21 static void perror_memory(int status
, bfd_vma memaddr
,
22 struct disassemble_info
*info
)
26 info
->fprintf_func(info
->stream
, "Unknown error %d\n", status
);
28 /* Address between memaddr and memaddr + len was out of bounds. */
29 info
->fprintf_func(info
->stream
,
30 "Address 0x%" PRIx64
" is out of bounds.\n",
35 /* Print address in hex. */
36 static void print_address(bfd_vma addr
, struct disassemble_info
*info
)
38 info
->fprintf_func(info
->stream
, "0x%" PRIx64
, addr
);
41 /* Stub prevents some fruitless earching in optabs disassemblers. */
42 static int symbol_at_address(bfd_vma addr
, struct disassemble_info
*info
)
47 void disas_initialize_debug(CPUDebug
*s
)
49 memset(s
, 0, sizeof(*s
));
50 s
->info
.arch
= bfd_arch_unknown
;
51 s
->info
.cap_arch
= -1;
52 s
->info
.cap_insn_unit
= 4;
53 s
->info
.cap_insn_split
= 4;
54 s
->info
.memory_error_func
= perror_memory
;
55 s
->info
.symbol_at_address_func
= symbol_at_address
;
58 void disas_initialize_debug_target(CPUDebug
*s
, CPUState
*cpu
)
60 disas_initialize_debug(s
);
63 s
->info
.print_address_func
= print_address
;
64 if (target_words_bigendian()) {
65 s
->info
.endian
= BFD_ENDIAN_BIG
;
67 s
->info
.endian
= BFD_ENDIAN_LITTLE
;
70 CPUClass
*cc
= CPU_GET_CLASS(cpu
);
71 if (cc
->disas_set_info
) {
72 cc
->disas_set_info(cpu
, &s
->info
);
76 int disas_gstring_printf(FILE *stream
, const char *fmt
, ...)
78 /* We abuse the FILE parameter to pass a GString. */
79 GString
*s
= (GString
*)stream
;
80 int initial_len
= s
->len
;
84 g_string_append_vprintf(s
, fmt
, va
);
87 return s
->len
- initial_len
;
90 /* Look up symbol for debugging purpose. Returns "" if unknown. */
91 const char *lookup_symbol(uint64_t orig_addr
)
93 const char *symbol
= "";
96 for (s
= syminfos
; s
; s
= s
->next
) {
97 symbol
= s
->lookup_symbol(s
, orig_addr
);
98 if (symbol
[0] != '\0') {