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