2 * Routines for target 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 "exec/translator.h"
10 #include "disas-internal.h"
13 static int translator_read_memory(bfd_vma memaddr
, bfd_byte
*myaddr
,
14 int length
, struct disassemble_info
*info
)
16 const DisasContextBase
*db
= info
->application_data
;
17 return translator_st(db
, myaddr
, memaddr
, length
) ? 0 : EIO
;
20 void target_disas(FILE *out
, CPUState
*cpu
, const struct DisasContextBase
*db
)
22 uint64_t code
= db
->pc_first
;
23 size_t size
= translator_st_len(db
);
28 disas_initialize_debug_target(&s
, cpu
);
29 s
.info
.read_memory_func
= translator_read_memory
;
30 s
.info
.application_data
= (void *)db
;
31 s
.info
.fprintf_func
= fprintf
;
33 s
.info
.buffer_vma
= code
;
34 s
.info
.buffer_length
= size
;
35 s
.info
.show_opcodes
= true;
37 if (s
.info
.cap_arch
>= 0 && cap_disas_target(&s
.info
, code
, size
)) {
41 if (s
.info
.print_insn
== NULL
) {
42 s
.info
.print_insn
= print_insn_od_target
;
45 for (pc
= code
; size
> 0; pc
+= count
, size
-= count
) {
46 fprintf(out
, "0x%08" PRIx64
": ", pc
);
47 count
= s
.info
.print_insn(pc
, &s
.info
);
54 "Disassembler disagrees with translator over instruction "
56 "Please report this to qemu-devel@nongnu.org\n");
63 static void plugin_print_address(bfd_vma addr
, struct disassemble_info
*info
)
69 * We should only be dissembling one instruction at a time here. If
70 * there is left over it usually indicates the front end has read more
71 * bytes than it needed.
73 char *plugin_disas(CPUState
*cpu
, const DisasContextBase
*db
,
74 uint64_t addr
, size_t size
)
77 GString
*ds
= g_string_new(NULL
);
79 disas_initialize_debug_target(&s
, cpu
);
80 s
.info
.read_memory_func
= translator_read_memory
;
81 s
.info
.application_data
= (void *)db
;
82 s
.info
.fprintf_func
= disas_gstring_printf
;
83 s
.info
.stream
= (FILE *)ds
; /* abuse this slot */
84 s
.info
.buffer_vma
= addr
;
85 s
.info
.buffer_length
= size
;
86 s
.info
.print_address_func
= plugin_print_address
;
88 if (s
.info
.cap_arch
>= 0 && cap_disas_plugin(&s
.info
, addr
, size
)) {
90 } else if (s
.info
.print_insn
) {
91 s
.info
.print_insn(addr
, &s
.info
);
93 ; /* cannot disassemble -- return empty string */
96 /* Return the buffer, freeing the GString container. */
97 return g_string_free(ds
, false);
99 #endif /* CONFIG_PLUGIN */