xref: /openbmc/qemu/disas/disas-target.c (revision c0d691ab)
1*c0d691abSRichard Henderson /*
2*c0d691abSRichard Henderson  * Routines for target instruction disassembly.
3*c0d691abSRichard Henderson  * SPDX-License-Identifier: GPL-2.0-or-later
4*c0d691abSRichard Henderson  */
5*c0d691abSRichard Henderson 
6*c0d691abSRichard Henderson #include "qemu/osdep.h"
7*c0d691abSRichard Henderson #include "disas/disas.h"
8*c0d691abSRichard Henderson #include "disas/capstone.h"
9*c0d691abSRichard Henderson #include "disas-internal.h"
10*c0d691abSRichard Henderson 
11*c0d691abSRichard Henderson 
12*c0d691abSRichard Henderson void target_disas(FILE *out, CPUState *cpu, uint64_t code, size_t size)
13*c0d691abSRichard Henderson {
14*c0d691abSRichard Henderson     uint64_t pc;
15*c0d691abSRichard Henderson     int count;
16*c0d691abSRichard Henderson     CPUDebug s;
17*c0d691abSRichard Henderson 
18*c0d691abSRichard Henderson     disas_initialize_debug_target(&s, cpu);
19*c0d691abSRichard Henderson     s.info.fprintf_func = fprintf;
20*c0d691abSRichard Henderson     s.info.stream = out;
21*c0d691abSRichard Henderson     s.info.buffer_vma = code;
22*c0d691abSRichard Henderson     s.info.buffer_length = size;
23*c0d691abSRichard Henderson     s.info.show_opcodes = true;
24*c0d691abSRichard Henderson 
25*c0d691abSRichard Henderson     if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) {
26*c0d691abSRichard Henderson         return;
27*c0d691abSRichard Henderson     }
28*c0d691abSRichard Henderson 
29*c0d691abSRichard Henderson     if (s.info.print_insn == NULL) {
30*c0d691abSRichard Henderson         s.info.print_insn = print_insn_od_target;
31*c0d691abSRichard Henderson     }
32*c0d691abSRichard Henderson 
33*c0d691abSRichard Henderson     for (pc = code; size > 0; pc += count, size -= count) {
34*c0d691abSRichard Henderson         fprintf(out, "0x%08" PRIx64 ":  ", pc);
35*c0d691abSRichard Henderson         count = s.info.print_insn(pc, &s.info);
36*c0d691abSRichard Henderson         fprintf(out, "\n");
37*c0d691abSRichard Henderson         if (count < 0) {
38*c0d691abSRichard Henderson             break;
39*c0d691abSRichard Henderson         }
40*c0d691abSRichard Henderson         if (size < count) {
41*c0d691abSRichard Henderson             fprintf(out,
42*c0d691abSRichard Henderson                     "Disassembler disagrees with translator over instruction "
43*c0d691abSRichard Henderson                     "decoding\n"
44*c0d691abSRichard Henderson                     "Please report this to qemu-devel@nongnu.org\n");
45*c0d691abSRichard Henderson             break;
46*c0d691abSRichard Henderson         }
47*c0d691abSRichard Henderson     }
48*c0d691abSRichard Henderson }
49*c0d691abSRichard Henderson 
50*c0d691abSRichard Henderson #ifdef CONFIG_PLUGIN
51*c0d691abSRichard Henderson static void plugin_print_address(bfd_vma addr, struct disassemble_info *info)
52*c0d691abSRichard Henderson {
53*c0d691abSRichard Henderson     /* does nothing */
54*c0d691abSRichard Henderson }
55*c0d691abSRichard Henderson 
56*c0d691abSRichard Henderson /*
57*c0d691abSRichard Henderson  * We should only be dissembling one instruction at a time here. If
58*c0d691abSRichard Henderson  * there is left over it usually indicates the front end has read more
59*c0d691abSRichard Henderson  * bytes than it needed.
60*c0d691abSRichard Henderson  */
61*c0d691abSRichard Henderson char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size)
62*c0d691abSRichard Henderson {
63*c0d691abSRichard Henderson     CPUDebug s;
64*c0d691abSRichard Henderson     GString *ds = g_string_new(NULL);
65*c0d691abSRichard Henderson 
66*c0d691abSRichard Henderson     disas_initialize_debug_target(&s, cpu);
67*c0d691abSRichard Henderson     s.info.fprintf_func = disas_gstring_printf;
68*c0d691abSRichard Henderson     s.info.stream = (FILE *)ds;  /* abuse this slot */
69*c0d691abSRichard Henderson     s.info.buffer_vma = addr;
70*c0d691abSRichard Henderson     s.info.buffer_length = size;
71*c0d691abSRichard Henderson     s.info.print_address_func = plugin_print_address;
72*c0d691abSRichard Henderson 
73*c0d691abSRichard Henderson     if (s.info.cap_arch >= 0 && cap_disas_plugin(&s.info, addr, size)) {
74*c0d691abSRichard Henderson         ; /* done */
75*c0d691abSRichard Henderson     } else if (s.info.print_insn) {
76*c0d691abSRichard Henderson         s.info.print_insn(addr, &s.info);
77*c0d691abSRichard Henderson     } else {
78*c0d691abSRichard Henderson         ; /* cannot disassemble -- return empty string */
79*c0d691abSRichard Henderson     }
80*c0d691abSRichard Henderson 
81*c0d691abSRichard Henderson     /* Return the buffer, freeing the GString container.  */
82*c0d691abSRichard Henderson     return g_string_free(ds, false);
83*c0d691abSRichard Henderson }
84*c0d691abSRichard Henderson #endif /* CONFIG_PLUGIN */
85