1 /* 2 * Common routines for 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 "hw/core/cpu.h" 10 #include "disas-internal.h" 11 12 13 /* Filled in by elfload.c. Simplistic, but will do for now. */ 14 struct syminfo *syminfos = NULL; 15 16 /* 17 * Print an error message. We can assume that this is in response to 18 * an error return from {host,target}_read_memory. 19 */ 20 static void perror_memory(int status, bfd_vma memaddr, 21 struct disassemble_info *info) 22 { 23 if (status != EIO) { 24 /* Can't happen. */ 25 info->fprintf_func(info->stream, "Unknown error %d\n", status); 26 } else { 27 /* Address between memaddr and memaddr + len was out of bounds. */ 28 info->fprintf_func(info->stream, 29 "Address 0x%" PRIx64 " is out of bounds.\n", 30 memaddr); 31 } 32 } 33 34 /* Print address in hex. */ 35 static void print_address(bfd_vma addr, struct disassemble_info *info) 36 { 37 info->fprintf_func(info->stream, "0x%" PRIx64, addr); 38 } 39 40 /* Stub prevents some fruitless earching in optabs disassemblers. */ 41 static int symbol_at_address(bfd_vma addr, struct disassemble_info *info) 42 { 43 return 1; 44 } 45 46 void disas_initialize_debug(CPUDebug *s) 47 { 48 memset(s, 0, sizeof(*s)); 49 s->info.arch = bfd_arch_unknown; 50 s->info.cap_arch = -1; 51 s->info.cap_insn_unit = 4; 52 s->info.cap_insn_split = 4; 53 s->info.memory_error_func = perror_memory; 54 s->info.symbol_at_address_func = symbol_at_address; 55 } 56 57 void disas_initialize_debug_target(CPUDebug *s, CPUState *cpu) 58 { 59 disas_initialize_debug(s); 60 61 s->cpu = cpu; 62 s->info.print_address_func = print_address; 63 s->info.endian = BFD_ENDIAN_UNKNOWN; 64 65 CPUClass *cc = CPU_GET_CLASS(cpu); 66 if (cc->disas_set_info) { 67 cc->disas_set_info(cpu, &s->info); 68 g_assert(s->info.endian != BFD_ENDIAN_UNKNOWN); 69 } 70 } 71 72 int disas_gstring_printf(FILE *stream, const char *fmt, ...) 73 { 74 /* We abuse the FILE parameter to pass a GString. */ 75 GString *s = (GString *)stream; 76 int initial_len = s->len; 77 va_list va; 78 79 va_start(va, fmt); 80 g_string_append_vprintf(s, fmt, va); 81 va_end(va); 82 83 return s->len - initial_len; 84 } 85 86 /* Look up symbol for debugging purpose. Returns "" if unknown. */ 87 const char *lookup_symbol(uint64_t orig_addr) 88 { 89 const char *symbol = ""; 90 struct syminfo *s; 91 92 for (s = syminfos; s; s = s->next) { 93 symbol = s->lookup_symbol(s, orig_addr); 94 if (symbol[0] != '\0') { 95 break; 96 } 97 } 98 99 return symbol; 100 } 101