disas: Use translator_st to get disassembly data
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>
This commit is contained in:
		| @@ -231,7 +231,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, | ||||
|             if (!ops->disas_log || | ||||
|                 !ops->disas_log(db, cpu, logfile)) { | ||||
|                 fprintf(logfile, "IN: %s\n", lookup_symbol(db->pc_first)); | ||||
|                 target_disas(logfile, cpu, db->pc_first, db->tb->size); | ||||
|                 target_disas(logfile, cpu, db); | ||||
|             } | ||||
|             fprintf(logfile, "\n"); | ||||
|             qemu_log_unlock(logfile); | ||||
|   | ||||
| @@ -8,25 +8,12 @@ | ||||
| #include "disas/capstone.h" | ||||
| #include "hw/core/cpu.h" | ||||
| #include "exec/tswap.h" | ||||
| #include "exec/memory.h" | ||||
| #include "disas-internal.h" | ||||
|  | ||||
|  | ||||
| /* Filled in by elfload.c.  Simplistic, but will do for now. */ | ||||
| struct syminfo *syminfos = NULL; | ||||
|  | ||||
| /* | ||||
|  * Get LENGTH bytes from info's buffer, at target address memaddr. | ||||
|  * Transfer them to myaddr. | ||||
|  */ | ||||
| static int target_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, | ||||
|                               struct disassemble_info *info) | ||||
| { | ||||
|     CPUDebug *s = container_of(info, CPUDebug, info); | ||||
|     int r = cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0); | ||||
|     return r ? EIO : 0; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Print an error message.  We can assume that this is in response to | ||||
|  * an error return from {host,target}_read_memory. | ||||
| @@ -73,7 +60,6 @@ void disas_initialize_debug_target(CPUDebug *s, CPUState *cpu) | ||||
|     disas_initialize_debug(s); | ||||
|  | ||||
|     s->cpu = cpu; | ||||
|     s->info.read_memory_func = target_read_memory; | ||||
|     s->info.print_address_func = print_address; | ||||
|     if (target_words_bigendian()) { | ||||
|         s->info.endian = BFD_ENDIAN_BIG; | ||||
|   | ||||
| @@ -11,6 +11,19 @@ | ||||
| #include "hw/core/cpu.h" | ||||
| #include "monitor/monitor.h" | ||||
|  | ||||
| /* | ||||
|  * Get LENGTH bytes from info's buffer, at target address memaddr. | ||||
|  * Transfer them to myaddr. | ||||
|  */ | ||||
| static int | ||||
| virtual_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, | ||||
|                     struct disassemble_info *info) | ||||
| { | ||||
|     CPUDebug *s = container_of(info, CPUDebug, info); | ||||
|     int r = cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0); | ||||
|     return r ? EIO : 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, | ||||
|                      struct disassemble_info *info) | ||||
| @@ -38,6 +51,8 @@ void monitor_disas(Monitor *mon, CPUState *cpu, uint64_t pc, | ||||
|  | ||||
|     if (is_physical) { | ||||
|         s.info.read_memory_func = physical_read_memory; | ||||
|     } else { | ||||
|         s.info.read_memory_func = virtual_read_memory; | ||||
|     } | ||||
|     s.info.buffer_vma = pc; | ||||
|  | ||||
|   | ||||
| @@ -6,16 +6,28 @@ | ||||
| #include "qemu/osdep.h" | ||||
| #include "disas/disas.h" | ||||
| #include "disas/capstone.h" | ||||
| #include "exec/translator.h" | ||||
| #include "disas-internal.h" | ||||
|  | ||||
|  | ||||
| void target_disas(FILE *out, CPUState *cpu, uint64_t code, size_t size) | ||||
| static int translator_read_memory(bfd_vma memaddr, bfd_byte *myaddr, | ||||
|                                   int length, struct disassemble_info *info) | ||||
| { | ||||
|     const DisasContextBase *db = info->application_data; | ||||
|     return translator_st(db, myaddr, memaddr, length) ? 0 : EIO; | ||||
| } | ||||
|  | ||||
| void target_disas(FILE *out, CPUState *cpu, const struct DisasContextBase *db) | ||||
| { | ||||
|     uint64_t code = db->pc_first; | ||||
|     size_t size = translator_st_len(db); | ||||
|     uint64_t pc; | ||||
|     int count; | ||||
|     CPUDebug s; | ||||
|  | ||||
|     disas_initialize_debug_target(&s, cpu); | ||||
|     s.info.read_memory_func = translator_read_memory; | ||||
|     s.info.application_data = (void *)db; | ||||
|     s.info.fprintf_func = fprintf; | ||||
|     s.info.stream = out; | ||||
|     s.info.buffer_vma = code; | ||||
| @@ -58,12 +70,15 @@ static void plugin_print_address(bfd_vma addr, struct disassemble_info *info) | ||||
|  * there is left over it usually indicates the front end has read more | ||||
|  * bytes than it needed. | ||||
|  */ | ||||
| char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size) | ||||
| char *plugin_disas(CPUState *cpu, const DisasContextBase *db, | ||||
|                    uint64_t addr, size_t size) | ||||
| { | ||||
|     CPUDebug s; | ||||
|     GString *ds = g_string_new(NULL); | ||||
|  | ||||
|     disas_initialize_debug_target(&s, cpu); | ||||
|     s.info.read_memory_func = translator_read_memory; | ||||
|     s.info.application_data = (void *)db; | ||||
|     s.info.fprintf_func = disas_gstring_printf; | ||||
|     s.info.stream = (FILE *)ds;  /* abuse this slot */ | ||||
|     s.info.buffer_vma = addr; | ||||
|   | ||||
| @@ -4,14 +4,15 @@ | ||||
| /* Disassemble this for me please... (debugging). */ | ||||
| #ifdef CONFIG_TCG | ||||
| void disas(FILE *out, const void *code, size_t size); | ||||
| void target_disas(FILE *out, CPUState *cpu, uint64_t code, size_t size); | ||||
| void target_disas(FILE *out, CPUState *cpu, const DisasContextBase *db); | ||||
| #endif | ||||
|  | ||||
| void monitor_disas(Monitor *mon, CPUState *cpu, uint64_t pc, | ||||
|                    int nb_insn, bool is_physical); | ||||
|  | ||||
| #ifdef CONFIG_PLUGIN | ||||
| char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size); | ||||
| char *plugin_disas(CPUState *cpu, const DisasContextBase *db, | ||||
|                    uint64_t addr, size_t size); | ||||
| #endif | ||||
|  | ||||
| /* Look up symbol for debugging purpose.  Returns "" if unknown. */ | ||||
|   | ||||
| @@ -79,7 +79,7 @@ typedef enum DisasJumpType { | ||||
|  * | ||||
|  * Architecture-agnostic disassembly context. | ||||
|  */ | ||||
| typedef struct DisasContextBase { | ||||
| struct DisasContextBase { | ||||
|     TranslationBlock *tb; | ||||
|     vaddr pc_first; | ||||
|     vaddr pc_next; | ||||
| @@ -103,7 +103,7 @@ typedef struct DisasContextBase { | ||||
|     int record_start; | ||||
|     int record_len; | ||||
|     uint8_t record[32]; | ||||
| } DisasContextBase; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * TranslatorOps: | ||||
|   | ||||
| @@ -42,6 +42,7 @@ typedef struct CPUPluginState CPUPluginState; | ||||
| typedef struct CPUState CPUState; | ||||
| typedef struct DeviceState DeviceState; | ||||
| typedef struct DirtyBitmapSnapshot DirtyBitmapSnapshot; | ||||
| typedef struct DisasContextBase DisasContextBase; | ||||
| typedef struct DisplayChangeListener DisplayChangeListener; | ||||
| typedef struct DriveInfo DriveInfo; | ||||
| typedef struct DumpState DumpState; | ||||
|   | ||||
| @@ -271,8 +271,8 @@ void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn) | ||||
|  | ||||
| char *qemu_plugin_insn_disas(const struct qemu_plugin_insn *insn) | ||||
| { | ||||
|     CPUState *cpu = current_cpu; | ||||
|     return plugin_disas(cpu, insn->vaddr, insn->len); | ||||
|     return plugin_disas(tcg_ctx->cpu, tcg_ctx->plugin_db, | ||||
|                         insn->vaddr, insn->len); | ||||
| } | ||||
|  | ||||
| const char *qemu_plugin_insn_symbol(const struct qemu_plugin_insn *insn) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user