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 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 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 */ 50 s.info.show_opcodes = true; 51 52 if (is_physical) { 53 s.info.read_memory_func = physical_read_memory; 54 } else { 55 s.info.read_memory_func = virtual_read_memory; 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 } 82