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