From: Pavel Dovgalyuk <pavel.dovga...@gmail.com> This is a samples of the instrumenting interface and implementation of some instruction tracing tasks.
Signed-off-by: Pavel Dovgalyuk <pavel.dovga...@ispras.ru> --- accel/tcg/translator.c | 5 +++++ include/qemu/instrument.h | 7 +++++++ plugins/helper.h | 1 + plugins/plugins.c | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 include/qemu/instrument.h create mode 100644 plugins/helper.h diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 0f9dca9..48773ac 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -17,6 +17,7 @@ #include "exec/gen-icount.h" #include "exec/log.h" #include "exec/translator.h" +#include "qemu/instrument.h" /* Pairs with tcg_clear_temp_count. To be called by #TranslatorOps.{translate_insn,tb_stop} if @@ -89,6 +90,10 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, } } + if (plugins_need_before_insn(db->pc_next, cpu)) { + plugins_instrument_before_insn(db->pc_next, cpu); + } + /* Disassemble one instruction. The translate_insn hook should update db->pc_next and db->is_jmp to indicate what should be done next -- either exiting this loop or locate the start of diff --git a/include/qemu/instrument.h b/include/qemu/instrument.h new file mode 100644 index 0000000..e8f279f --- /dev/null +++ b/include/qemu/instrument.h @@ -0,0 +1,7 @@ +#ifndef INSTRUMENT_H +#define INSTRUMENT_H + +bool plugins_need_before_insn(target_ulong pc, CPUState *cpu); +void plugins_instrument_before_insn(target_ulong pc, CPUState *cpu); + +#endif /* INSTRUMENT_H */ diff --git a/plugins/helper.h b/plugins/helper.h new file mode 100644 index 0000000..007b395 --- /dev/null +++ b/plugins/helper.h @@ -0,0 +1 @@ +DEF_HELPER_2(before_insn, void, tl, ptr) diff --git a/plugins/plugins.c b/plugins/plugins.c index eabc931..5a08e71 100644 --- a/plugins/plugins.c +++ b/plugins/plugins.c @@ -1,8 +1,13 @@ #include "qemu/osdep.h" #include "qemu-common.h" +#include "cpu.h" #include "qemu/error-report.h" #include "qemu/plugins.h" +#include "qemu/instrument.h" +#include "tcg/tcg.h" +#include "tcg/tcg-op.h" #include "qemu/queue.h" +#include "qemu/option.h" #include <gmodule.h> typedef bool (*PluginInitFunc)(const char *); @@ -80,6 +85,40 @@ void qemu_plugin_load(const char *filename, const char *args) return; } +bool plugins_need_before_insn(target_ulong pc, CPUState *cpu) +{ + QemuPluginInfo *info; + QLIST_FOREACH(info, &qemu_plugins, next) { + if (info->needs_before_insn && info->needs_before_insn(pc, cpu)) { + return true; + } + } + + return false; +} + +void plugins_instrument_before_insn(target_ulong pc, CPUState *cpu) +{ + TCGv t_pc = tcg_const_tl(pc); + TCGv_ptr t_cpu = tcg_const_ptr(cpu); + /* We will dispatch plugins' callbacks in our own helper below */ + gen_helper_before_insn(t_pc, t_cpu); + tcg_temp_free(t_pc); + tcg_temp_free_ptr(t_cpu); +} + +void helper_before_insn(target_ulong pc, void *cpu) +{ + QemuPluginInfo *info; + QLIST_FOREACH(info, &qemu_plugins, next) { + if (info->needs_before_insn && info->needs_before_insn(pc, cpu)) { + if (info->before_insn) { + info->before_insn(pc, cpu); + } + } + } +} + void qemu_plugins_init(void) { QemuPluginInfo *info; @@ -88,4 +127,6 @@ void qemu_plugins_init(void) info->init(info->args); } } + +#include "exec/helper-register.h" }