 4c833c60e0
			
		
	
	
		4c833c60e0
		
	
	
	
	
		
			
			Read from already translated pages, or saved mmio data. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
		
			
				
	
	
		
			105 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Common routines for disassembly.
 | |
|  * SPDX-License-Identifier: GPL-2.0-or-later
 | |
|  */
 | |
| 
 | |
| #include "qemu/osdep.h"
 | |
| #include "disas/disas.h"
 | |
| #include "disas/capstone.h"
 | |
| #include "hw/core/cpu.h"
 | |
| #include "exec/tswap.h"
 | |
| #include "disas-internal.h"
 | |
| 
 | |
| 
 | |
| /* Filled in by elfload.c.  Simplistic, but will do for now. */
 | |
| struct syminfo *syminfos = NULL;
 | |
| 
 | |
| /*
 | |
|  * Print an error message.  We can assume that this is in response to
 | |
|  * an error return from {host,target}_read_memory.
 | |
|  */
 | |
| static void perror_memory(int status, bfd_vma memaddr,
 | |
|                           struct disassemble_info *info)
 | |
| {
 | |
|     if (status != EIO) {
 | |
|         /* Can't happen.  */
 | |
|         info->fprintf_func(info->stream, "Unknown error %d\n", status);
 | |
|     } else {
 | |
|         /* Address between memaddr and memaddr + len was out of bounds.  */
 | |
|         info->fprintf_func(info->stream,
 | |
|                            "Address 0x%" PRIx64 " is out of bounds.\n",
 | |
|                            memaddr);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* Print address in hex. */
 | |
| static void print_address(bfd_vma addr, struct disassemble_info *info)
 | |
| {
 | |
|     info->fprintf_func(info->stream, "0x%" PRIx64, addr);
 | |
| }
 | |
| 
 | |
| /* Stub prevents some fruitless earching in optabs disassemblers. */
 | |
| static int symbol_at_address(bfd_vma addr, struct disassemble_info *info)
 | |
| {
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| void disas_initialize_debug(CPUDebug *s)
 | |
| {
 | |
|     memset(s, 0, sizeof(*s));
 | |
|     s->info.arch = bfd_arch_unknown;
 | |
|     s->info.cap_arch = -1;
 | |
|     s->info.cap_insn_unit = 4;
 | |
|     s->info.cap_insn_split = 4;
 | |
|     s->info.memory_error_func = perror_memory;
 | |
|     s->info.symbol_at_address_func = symbol_at_address;
 | |
| }
 | |
| 
 | |
| void disas_initialize_debug_target(CPUDebug *s, CPUState *cpu)
 | |
| {
 | |
|     disas_initialize_debug(s);
 | |
| 
 | |
|     s->cpu = cpu;
 | |
|     s->info.print_address_func = print_address;
 | |
|     if (target_words_bigendian()) {
 | |
|         s->info.endian = BFD_ENDIAN_BIG;
 | |
|     } else {
 | |
|         s->info.endian =  BFD_ENDIAN_LITTLE;
 | |
|     }
 | |
| 
 | |
|     CPUClass *cc = CPU_GET_CLASS(cpu);
 | |
|     if (cc->disas_set_info) {
 | |
|         cc->disas_set_info(cpu, &s->info);
 | |
|     }
 | |
| }
 | |
| 
 | |
| int disas_gstring_printf(FILE *stream, const char *fmt, ...)
 | |
| {
 | |
|     /* We abuse the FILE parameter to pass a GString. */
 | |
|     GString *s = (GString *)stream;
 | |
|     int initial_len = s->len;
 | |
|     va_list va;
 | |
| 
 | |
|     va_start(va, fmt);
 | |
|     g_string_append_vprintf(s, fmt, va);
 | |
|     va_end(va);
 | |
| 
 | |
|     return s->len - initial_len;
 | |
| }
 | |
| 
 | |
| /* Look up symbol for debugging purpose.  Returns "" if unknown. */
 | |
| const char *lookup_symbol(uint64_t orig_addr)
 | |
| {
 | |
|     const char *symbol = "";
 | |
|     struct syminfo *s;
 | |
| 
 | |
|     for (s = syminfos; s; s = s->next) {
 | |
|         symbol = s->lookup_symbol(s, orig_addr);
 | |
|         if (symbol[0] != '\0') {
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return symbol;
 | |
| }
 |