From 4abc892362f8282450f18c4e45c5b0534461d01e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2024 21:24:52 -1000 Subject: plugins: Copy memory in qemu_plugin_insn_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of returning a host pointer, copy the data into storage provided by the caller. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- plugins/api.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'plugins/api.c') diff --git a/plugins/api.c b/plugins/api.c index 2144da1fe8..5ff4e9d325 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -216,9 +216,12 @@ qemu_plugin_tb_get_insn(const struct qemu_plugin_tb *tb, size_t idx) * instruction being translated. */ -const void *qemu_plugin_insn_data(const struct qemu_plugin_insn *insn) +size_t qemu_plugin_insn_data(const struct qemu_plugin_insn *insn, + void *dest, size_t len) { - return insn->data->data; + len = MIN(len, insn->data->len); + memcpy(dest, insn->data->data, len); + return len; } size_t qemu_plugin_insn_size(const struct qemu_plugin_insn *insn) -- cgit 1.4.1 From 36bc99bc789fd564facea93feb2a22e4942b84d0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2024 09:20:06 -1000 Subject: plugins: Use translator_st for qemu_plugin_insn_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the bytes that we record for the entire TB, rather than a per-insn GByteArray. Record the length of the insn in plugin_gen_insn_end rather than infering from the length of the array. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- accel/tcg/plugin-gen.c | 7 +++++-- accel/tcg/translator.c | 26 -------------------------- include/qemu/plugin.h | 14 +------------- plugins/api.c | 12 +++++++----- tcg/tcg.c | 3 +-- 5 files changed, 14 insertions(+), 48 deletions(-) (limited to 'plugins/api.c') diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c index 842da97204..716c8ec753 100644 --- a/accel/tcg/plugin-gen.c +++ b/accel/tcg/plugin-gen.c @@ -346,11 +346,9 @@ void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db) ptb->n = n; if (n <= ptb->insns->len) { insn = g_ptr_array_index(ptb->insns, n - 1); - g_byte_array_set_size(insn->data, 0); } else { assert(n - 1 == ptb->insns->len); insn = g_new0(struct qemu_plugin_insn, 1); - insn->data = g_byte_array_sized_new(4); g_ptr_array_add(ptb->insns, insn); } @@ -389,6 +387,11 @@ void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db) void plugin_gen_insn_end(void) { + const DisasContextBase *db = tcg_ctx->plugin_db; + struct qemu_plugin_insn *pinsn = tcg_ctx->plugin_insn; + + pinsn->len = db->fake_insn ? db->record_len : db->pc_next - pinsn->vaddr; + tcg_gen_plugin_cb(PLUGIN_GEN_AFTER_INSN); } diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 01e1f0977b..986045154c 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -409,27 +409,6 @@ bool translator_st(const DisasContextBase *db, void *dest, return false; } -static void plugin_insn_append(vaddr pc, const void *from, size_t size) -{ -#ifdef CONFIG_PLUGIN - struct qemu_plugin_insn *insn = tcg_ctx->plugin_insn; - size_t off; - - if (insn == NULL) { - return; - } - off = pc - insn->vaddr; - if (off < insn->data->len) { - g_byte_array_set_size(insn->data, off); - } else if (off > insn->data->len) { - /* we have an unexpected gap */ - g_assert_not_reached(); - } - - insn->data = g_byte_array_append(insn->data, from, size); -#endif -} - uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, vaddr pc) { uint8_t raw; @@ -438,7 +417,6 @@ uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, vaddr pc) raw = cpu_ldub_code(env, pc); record_save(db, pc, &raw, sizeof(raw)); } - plugin_insn_append(pc, &raw, sizeof(raw)); return raw; } @@ -453,7 +431,6 @@ uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, vaddr pc) raw = tswap16(tgt); record_save(db, pc, &raw, sizeof(raw)); } - plugin_insn_append(pc, &raw, sizeof(raw)); return tgt; } @@ -468,7 +445,6 @@ uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, vaddr pc) raw = tswap32(tgt); record_save(db, pc, &raw, sizeof(raw)); } - plugin_insn_append(pc, &raw, sizeof(raw)); return tgt; } @@ -483,7 +459,6 @@ uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, vaddr pc) raw = tswap64(tgt); record_save(db, pc, &raw, sizeof(raw)); } - plugin_insn_append(pc, &raw, sizeof(raw)); return tgt; } @@ -492,5 +467,4 @@ void translator_fake_ldb(DisasContextBase *db, vaddr pc, uint8_t insn8) assert(pc >= db->pc_first); db->fake_insn = true; record_save(db, pc, &insn8, sizeof(insn8)); - plugin_insn_append(pc, &insn8, sizeof(insn8)); } diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h index b535bfd5de..c8dd2c42fa 100644 --- a/include/qemu/plugin.h +++ b/include/qemu/plugin.h @@ -98,11 +98,11 @@ struct qemu_plugin_dyn_cb { /* Internal context for instrumenting an instruction */ struct qemu_plugin_insn { - GByteArray *data; uint64_t vaddr; void *haddr; GArray *insn_cbs; GArray *mem_cbs; + uint8_t len; bool calls_helpers; /* if set, the instruction calls helpers that might access guest memory */ @@ -117,18 +117,6 @@ struct qemu_plugin_scoreboard { QLIST_ENTRY(qemu_plugin_scoreboard) entry; }; -/* - * qemu_plugin_insn allocate and cleanup functions. We don't expect to - * cleanup many of these structures. They are reused for each fresh - * translation. - */ - -static inline void qemu_plugin_insn_cleanup_fn(gpointer data) -{ - struct qemu_plugin_insn *insn = (struct qemu_plugin_insn *) data; - g_byte_array_free(insn->data, true); -} - /* Internal context for this TranslationBlock */ struct qemu_plugin_tb { GPtrArray *insns; diff --git a/plugins/api.c b/plugins/api.c index 5ff4e9d325..15467acdfd 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -42,6 +42,7 @@ #include "tcg/tcg.h" #include "exec/exec-all.h" #include "exec/gdbstub.h" +#include "exec/translator.h" #include "disas/disas.h" #include "plugin.h" #ifndef CONFIG_USER_ONLY @@ -219,14 +220,15 @@ qemu_plugin_tb_get_insn(const struct qemu_plugin_tb *tb, size_t idx) size_t qemu_plugin_insn_data(const struct qemu_plugin_insn *insn, void *dest, size_t len) { - len = MIN(len, insn->data->len); - memcpy(dest, insn->data->data, len); - return len; + const DisasContextBase *db = tcg_ctx->plugin_db; + + len = MIN(len, insn->len); + return translator_st(db, dest, insn->vaddr, len) ? len : 0; } size_t qemu_plugin_insn_size(const struct qemu_plugin_insn *insn) { - return insn->data->len; + return insn->len; } uint64_t qemu_plugin_insn_vaddr(const struct qemu_plugin_insn *insn) @@ -242,7 +244,7 @@ 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->data->len); + return plugin_disas(cpu, insn->vaddr, insn->len); } const char *qemu_plugin_insn_symbol(const struct qemu_plugin_insn *insn) diff --git a/tcg/tcg.c b/tcg/tcg.c index d827c6d431..71daa5d268 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -765,8 +765,7 @@ static void alloc_tcg_plugin_context(TCGContext *s) { #ifdef CONFIG_PLUGIN s->plugin_tb = g_new0(struct qemu_plugin_tb, 1); - s->plugin_tb->insns = - g_ptr_array_new_with_free_func(qemu_plugin_insn_cleanup_fn); + s->plugin_tb->insns = g_ptr_array_new(); #endif } -- cgit 1.4.1 From e501325991815e09297a048ffb0be81411bbe34a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2024 09:31:49 -1000 Subject: plugins: Read mem_only directly from TB cflags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not pass around a boolean between multiple structures, just read it from the TranslationBlock in the TCGContext. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- accel/tcg/plugin-gen.c | 4 +--- accel/tcg/translator.c | 2 +- include/exec/plugin-gen.h | 7 +++---- include/qemu/plugin.h | 3 --- plugins/api.c | 14 +++++++++----- 5 files changed, 14 insertions(+), 16 deletions(-) (limited to 'plugins/api.c') diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c index 716c8ec753..2aa1e08c17 100644 --- a/accel/tcg/plugin-gen.c +++ b/accel/tcg/plugin-gen.c @@ -303,8 +303,7 @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb) } } -bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db, - bool mem_only) +bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db) { bool ret = false; @@ -323,7 +322,6 @@ bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db, ptb->vaddr2 = -1; ptb->haddr1 = db->host_addr[0]; ptb->haddr2 = NULL; - ptb->mem_only = mem_only; ptb->mem_helper = false; tcg_gen_plugin_cb(PLUGIN_GEN_FROM_TB); diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 986045154c..157b447810 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -144,7 +144,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns, ops->tb_start(db, cpu); tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ - plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY); + plugin_enabled = plugin_gen_tb_start(cpu, db); db->plugin_enabled = plugin_enabled; while (true) { diff --git a/include/exec/plugin-gen.h b/include/exec/plugin-gen.h index f333f33198..cbb2ca2131 100644 --- a/include/exec/plugin-gen.h +++ b/include/exec/plugin-gen.h @@ -18,8 +18,7 @@ struct DisasContextBase; #ifdef CONFIG_PLUGIN -bool plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db, - bool supress); +bool plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db); void plugin_gen_tb_end(CPUState *cpu, size_t num_insns); void plugin_gen_insn_start(CPUState *cpu, const struct DisasContextBase *db); void plugin_gen_insn_end(void); @@ -28,8 +27,8 @@ void plugin_gen_disable_mem_helpers(void); #else /* !CONFIG_PLUGIN */ -static inline bool -plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db, bool sup) +static inline +bool plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db) { return false; } diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h index c8dd2c42fa..c28d0ca31c 100644 --- a/include/qemu/plugin.h +++ b/include/qemu/plugin.h @@ -107,8 +107,6 @@ struct qemu_plugin_insn { /* if set, the instruction calls helpers that might access guest memory */ bool mem_helper; - - bool mem_only; }; /* A scoreboard is an array of values, indexed by vcpu_index */ @@ -125,7 +123,6 @@ struct qemu_plugin_tb { uint64_t vaddr2; void *haddr1; void *haddr2; - bool mem_only; /* if set, the TB calls helpers that might access guest memory */ bool mem_helper; diff --git a/plugins/api.c b/plugins/api.c index 15467acdfd..9e4aa9d2d9 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -87,12 +87,17 @@ void qemu_plugin_register_vcpu_exit_cb(qemu_plugin_id_t id, plugin_register_cb(id, QEMU_PLUGIN_EV_VCPU_EXIT, cb); } +static bool tb_is_mem_only(void) +{ + return tb_cflags(tcg_ctx->gen_tb) & CF_MEMI_ONLY; +} + void qemu_plugin_register_vcpu_tb_exec_cb(struct qemu_plugin_tb *tb, qemu_plugin_vcpu_udata_cb_t cb, enum qemu_plugin_cb_flags flags, void *udata) { - if (!tb->mem_only) { + if (!tb_is_mem_only()) { plugin_register_dyn_cb__udata(&tb->cbs, cb, flags, udata); } } @@ -103,7 +108,7 @@ void qemu_plugin_register_vcpu_tb_exec_inline_per_vcpu( qemu_plugin_u64 entry, uint64_t imm) { - if (!tb->mem_only) { + if (!tb_is_mem_only()) { plugin_register_inline_op_on_entry(&tb->cbs, 0, op, entry, imm); } } @@ -113,7 +118,7 @@ void qemu_plugin_register_vcpu_insn_exec_cb(struct qemu_plugin_insn *insn, enum qemu_plugin_cb_flags flags, void *udata) { - if (!insn->mem_only) { + if (!tb_is_mem_only()) { plugin_register_dyn_cb__udata(&insn->insn_cbs, cb, flags, udata); } } @@ -124,7 +129,7 @@ void qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu( qemu_plugin_u64 entry, uint64_t imm) { - if (!insn->mem_only) { + if (!tb_is_mem_only()) { plugin_register_inline_op_on_entry(&insn->insn_cbs, 0, op, entry, imm); } } @@ -206,7 +211,6 @@ qemu_plugin_tb_get_insn(const struct qemu_plugin_tb *tb, size_t idx) return NULL; } insn = g_ptr_array_index(tb->insns, idx); - insn->mem_only = tb->mem_only; return insn; } -- cgit 1.4.1 From d3ace105900c43d1eb034b81ce0951e6110ab990 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2024 09:54:43 -1000 Subject: plugins: Use DisasContextBase for qemu_plugin_insn_haddr We can delay the computation of haddr until the plugin actually requests it. Reviewed-by: Pierrick Bouvier Signed-off-by: Richard Henderson --- accel/tcg/plugin-gen.c | 20 -------------------- include/qemu/plugin.h | 4 ---- plugins/api.c | 25 ++++++++++++++++++++++++- 3 files changed, 24 insertions(+), 25 deletions(-) (limited to 'plugins/api.c') diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c index 2aa1e08c17..c36632e8df 100644 --- a/accel/tcg/plugin-gen.c +++ b/accel/tcg/plugin-gen.c @@ -319,9 +319,6 @@ bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db) ret = true; ptb->vaddr = db->pc_first; - ptb->vaddr2 = -1; - ptb->haddr1 = db->host_addr[0]; - ptb->haddr2 = NULL; ptb->mem_helper = false; tcg_gen_plugin_cb(PLUGIN_GEN_FROM_TB); @@ -363,23 +360,6 @@ void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db) pc = db->pc_next; insn->vaddr = pc; - /* - * Detect page crossing to get the new host address. - * Note that we skip this when haddr1 == NULL, e.g. when we're - * fetching instructions from a region not backed by RAM. - */ - if (ptb->haddr1 == NULL) { - insn->haddr = NULL; - } else if (is_same_page(db, db->pc_next)) { - insn->haddr = ptb->haddr1 + pc - ptb->vaddr; - } else { - if (ptb->vaddr2 == -1) { - ptb->vaddr2 = TARGET_PAGE_ALIGN(db->pc_first); - get_page_addr_code_hostp(cpu_env(cpu), ptb->vaddr2, &ptb->haddr2); - } - insn->haddr = ptb->haddr2 + pc - ptb->vaddr2; - } - tcg_gen_plugin_cb(PLUGIN_GEN_FROM_INSN); } diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h index c28d0ca31c..da0f37e269 100644 --- a/include/qemu/plugin.h +++ b/include/qemu/plugin.h @@ -99,7 +99,6 @@ struct qemu_plugin_dyn_cb { /* Internal context for instrumenting an instruction */ struct qemu_plugin_insn { uint64_t vaddr; - void *haddr; GArray *insn_cbs; GArray *mem_cbs; uint8_t len; @@ -120,9 +119,6 @@ struct qemu_plugin_tb { GPtrArray *insns; size_t n; uint64_t vaddr; - uint64_t vaddr2; - void *haddr1; - void *haddr2; /* if set, the TB calls helpers that might access guest memory */ bool mem_helper; diff --git a/plugins/api.c b/plugins/api.c index 9e4aa9d2d9..0ae19774df 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -242,7 +242,30 @@ uint64_t qemu_plugin_insn_vaddr(const struct qemu_plugin_insn *insn) void *qemu_plugin_insn_haddr(const struct qemu_plugin_insn *insn) { - return insn->haddr; + const DisasContextBase *db = tcg_ctx->plugin_db; + vaddr page0_last = db->pc_first | ~TARGET_PAGE_MASK; + + if (db->fake_insn) { + return NULL; + } + + /* + * ??? The return value is not intended for use of host memory, + * but as a proxy for address space and physical address. + * Thus we are only interested in the first byte and do not + * care about spanning pages. + */ + if (insn->vaddr <= page0_last) { + if (db->host_addr[0] == NULL) { + return NULL; + } + return db->host_addr[0] + insn->vaddr - db->pc_first; + } else { + if (db->host_addr[1] == NULL) { + return NULL; + } + return db->host_addr[1] + insn->vaddr - (page0_last + 1); + } } char *qemu_plugin_insn_disas(const struct qemu_plugin_insn *insn) -- cgit 1.4.1 From e763953a2445770bb5d1653d0c258dca5a6de5e2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2024 09:59:18 -1000 Subject: plugins: Use DisasContextBase for qemu_plugin_tb_vaddr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We do not need to separately record the start of the TB. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- accel/tcg/plugin-gen.c | 3 +-- include/qemu/plugin.h | 1 - plugins/api.c | 3 ++- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'plugins/api.c') diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c index c36632e8df..b54494712a 100644 --- a/accel/tcg/plugin-gen.c +++ b/accel/tcg/plugin-gen.c @@ -188,7 +188,7 @@ static void plugin_gen_inject(struct qemu_plugin_tb *plugin_tb) int insn_idx = -1; if (unlikely(qemu_loglevel_mask(LOG_TB_OP_PLUGIN) - && qemu_log_in_addr_range(plugin_tb->vaddr))) { + && qemu_log_in_addr_range(tcg_ctx->plugin_db->pc_first))) { FILE *logfile = qemu_log_trylock(); if (logfile) { fprintf(logfile, "OP before plugin injection:\n"); @@ -318,7 +318,6 @@ bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db) ret = true; - ptb->vaddr = db->pc_first; ptb->mem_helper = false; tcg_gen_plugin_cb(PLUGIN_GEN_FROM_TB); diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h index da0f37e269..7fda6ef126 100644 --- a/include/qemu/plugin.h +++ b/include/qemu/plugin.h @@ -118,7 +118,6 @@ struct qemu_plugin_scoreboard { struct qemu_plugin_tb { GPtrArray *insns; size_t n; - uint64_t vaddr; /* if set, the TB calls helpers that might access guest memory */ bool mem_helper; diff --git a/plugins/api.c b/plugins/api.c index 0ae19774df..02014d4c6e 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -200,7 +200,8 @@ size_t qemu_plugin_tb_n_insns(const struct qemu_plugin_tb *tb) uint64_t qemu_plugin_tb_vaddr(const struct qemu_plugin_tb *tb) { - return tb->vaddr; + const DisasContextBase *db = tcg_ctx->plugin_db; + return db->pc_first; } struct qemu_plugin_insn * -- cgit 1.4.1 From 4c833c60e0479d4eec5384fa9ede11ebab78a304 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2024 23:44:53 -1000 Subject: disas: Use translator_st to get disassembly data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Read from already translated pages, or saved mmio data. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- accel/tcg/translator.c | 2 +- disas/disas-common.c | 14 -------------- disas/disas-mon.c | 15 +++++++++++++++ disas/disas-target.c | 19 +++++++++++++++++-- include/disas/disas.h | 5 +++-- include/exec/translator.h | 4 ++-- include/qemu/typedefs.h | 1 + plugins/api.c | 4 ++-- 8 files changed, 41 insertions(+), 23 deletions(-) (limited to 'plugins/api.c') diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index ccd22dcd95..00322c6fd9 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -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); diff --git a/disas/disas-common.c b/disas/disas-common.c index ce9f82b711..de61f6d8a1 100644 --- a/disas/disas-common.c +++ b/disas/disas-common.c @@ -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; diff --git a/disas/disas-mon.c b/disas/disas-mon.c index 5d6d9aa02d..37bf16ac79 100644 --- a/disas/disas-mon.c +++ b/disas/disas-mon.c @@ -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; diff --git a/disas/disas-target.c b/disas/disas-target.c index 82313b2a67..48f3a365dc 100644 --- a/disas/disas-target.c +++ b/disas/disas-target.c @@ -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; diff --git a/include/disas/disas.h b/include/disas/disas.h index 54a5e68443..c702b1effc 100644 --- a/include/disas/disas.h +++ b/include/disas/disas.h @@ -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. */ diff --git a/include/exec/translator.h b/include/exec/translator.h index 31c39ab63c..411ce2b47e 100644 --- a/include/exec/translator.h +++ b/include/exec/translator.h @@ -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: diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index b47e7179e2..9d222dc376 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -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; diff --git a/plugins/api.c b/plugins/api.c index 02014d4c6e..b04c5e1928 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -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) -- cgit 1.4.1