]>
Commit | Line | Data |
---|---|---|
e22d3c48 TH |
1 | /* |
2 | * Functions related to disassembly from the monitor | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0-or-later | |
5 | */ | |
6 | ||
7 | #include "qemu/osdep.h" | |
8 | #include "disas-internal.h" | |
9 | #include "disas/disas.h" | |
10 | #include "exec/memory.h" | |
11 | #include "hw/core/cpu.h" | |
12 | #include "monitor/monitor.h" | |
13 | ||
4c833c60 RH |
14 | /* |
15 | * Get LENGTH bytes from info's buffer, at target address memaddr. | |
16 | * Transfer them to myaddr. | |
17 | */ | |
18 | static int | |
19 | virtual_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, | |
20 | struct disassemble_info *info) | |
21 | { | |
22 | CPUDebug *s = container_of(info, CPUDebug, info); | |
23 | int r = cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0); | |
24 | return r ? EIO : 0; | |
25 | } | |
26 | ||
e22d3c48 TH |
27 | static int |
28 | physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, | |
29 | struct disassemble_info *info) | |
30 | { | |
31 | CPUDebug *s = container_of(info, CPUDebug, info); | |
32 | MemTxResult res; | |
33 | ||
34 | res = address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED, | |
35 | myaddr, length); | |
36 | return res == MEMTX_OK ? 0 : EIO; | |
37 | } | |
38 | ||
39 | /* Disassembler for the monitor. */ | |
40 | void monitor_disas(Monitor *mon, CPUState *cpu, uint64_t pc, | |
41 | int nb_insn, bool is_physical) | |
42 | { | |
43 | int count, i; | |
44 | CPUDebug s; | |
45 | g_autoptr(GString) ds = g_string_new(""); | |
46 | ||
47 | disas_initialize_debug_target(&s, cpu); | |
48 | s.info.fprintf_func = disas_gstring_printf; | |
49 | s.info.stream = (FILE *)ds; /* abuse this slot */ | |
13af3af1 | 50 | s.info.show_opcodes = true; |
e22d3c48 TH |
51 | |
52 | if (is_physical) { | |
53 | s.info.read_memory_func = physical_read_memory; | |
4c833c60 RH |
54 | } else { |
55 | s.info.read_memory_func = virtual_read_memory; | |
e22d3c48 TH |
56 | } |
57 | s.info.buffer_vma = pc; | |
58 | ||
59 | if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) { | |
60 | monitor_puts(mon, ds->str); | |
61 | return; | |
62 | } | |
63 | ||
64 | if (!s.info.print_insn) { | |
65 | monitor_printf(mon, "0x%08" PRIx64 | |
66 | ": Asm output not supported on this arch\n", pc); | |
67 | return; | |
68 | } | |
69 | ||
70 | for (i = 0; i < nb_insn; i++) { | |
71 | g_string_append_printf(ds, "0x%08" PRIx64 ": ", pc); | |
72 | count = s.info.print_insn(pc, &s.info); | |
73 | g_string_append_c(ds, '\n'); | |
74 | if (count < 0) { | |
75 | break; | |
76 | } | |
77 | pc += count; | |
78 | } | |
79 | ||
80 | monitor_puts(mon, ds->str); | |
81 | } |