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