1 /* 2 * Routines for target instruction disassembly. 3 * SPDX-License-Identifier: GPL-2.0-or-later 4 */ 5 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" 11 12 13 static int translator_read_memory(bfd_vma memaddr, bfd_byte *myaddr, 14 int length, struct disassemble_info *info) 15 { 16 const DisasContextBase *db = info->application_data; 17 return translator_st(db, myaddr, memaddr, length) ? 0 : EIO; 18 } 19 20 void target_disas(FILE *out, CPUState *cpu, const struct DisasContextBase *db) 21 { 22 uint64_t code = db->pc_first; 23 size_t size = translator_st_len(db); 24 uint64_t pc; 25 int count; 26 CPUDebug s; 27 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; 32 s.info.stream = out; 33 s.info.buffer_vma = code; 34 s.info.buffer_length = size; 35 s.info.show_opcodes = true; 36 37 if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) { 38 return; 39 } 40 41 if (s.info.print_insn == NULL) { 42 s.info.print_insn = print_insn_od_target; 43 } 44 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); 48 fprintf(out, "\n"); 49 if (count < 0) { 50 break; 51 } 52 if (size < count) { 53 fprintf(out, 54 "Disassembler disagrees with translator over instruction " 55 "decoding\n" 56 "Please report this to qemu-devel@nongnu.org\n"); 57 break; 58 } 59 } 60 } 61 62 #ifdef CONFIG_PLUGIN 63 static void plugin_print_address(bfd_vma addr, struct disassemble_info *info) 64 { 65 /* does nothing */ 66 } 67 68 /* 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. 72 */ 73 char *plugin_disas(CPUState *cpu, const DisasContextBase *db, 74 uint64_t addr, size_t size) 75 { 76 CPUDebug s; 77 GString *ds = g_string_new(NULL); 78 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; 87 88 if (s.info.cap_arch >= 0 && cap_disas_plugin(&s.info, addr, size)) { 89 ; /* done */ 90 } else if (s.info.print_insn) { 91 s.info.print_insn(addr, &s.info); 92 } else { 93 ; /* cannot disassemble -- return empty string */ 94 } 95 96 /* Return the buffer, freeing the GString container. */ 97 return g_string_free(ds, false); 98 } 99 #endif /* CONFIG_PLUGIN */ 100