On Mon, Oct 29, 2018 at 13:59:03 +0300, Pavel Dovgalyuk wrote: > > From: Emilio G. Cota [mailto:c...@braap.org] > > Signed-off-by: Emilio G. Cota <c...@braap.org> (snip) > Thanks for the series. > Can you provide more plugin examples for better understanding of > double-translate idea? > E.g., plugins that hook specific instructions or addresses.
Here's a plugin that at TB translation time, disassembles the instructions provided via capstone. It doesn't do anything with that info (vcpu_tb_exec is empty), but say a simulator would pass via the *udata pointer some descriptor (allocated at translation time) based on the instructions in the TB. Note that the disassembly happens because we already have a fully formed TB thanks to the 2-pass translation. Without it, we'd have to (1) perform additional loads in the guest to read instructions given the PC, and (2) guess when the TB would end (recall that when to finish a TB is a decision internal to QEMU). Thanks, Emilio PS. Compile with -lcapstone --- #include <inttypes.h> #include <assert.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <stdio.h> #include <capstone/capstone.h> #include <qemu-plugin.h> struct tb { size_t n_insns; }; static csh cap_handle; static cs_insn *cap_insn; static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo, uint64_t vaddr, void *udata) { } static void vcpu_tb_exec(unsigned int cpu_index, void *udata) { } static void vcpu_tb_trans(qemu_plugin_id_t id, unsigned int cpu_index, struct qemu_plugin_tb *tb) { struct tb *desc; size_t n = qemu_plugin_tb_n_insns(tb); size_t i; for (i = 0; i < n; i++) { struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i); size_t size = qemu_plugin_insn_size(insn); const uint8_t *code = qemu_plugin_insn_data(insn); uint64_t offset = 0; bool success; success = cs_disasm_iter(cap_handle, &code, &size, &offset, cap_insn); assert(success); qemu_plugin_register_vcpu_mem_cb(insn, vcpu_mem, QEMU_PLUGIN_CB_NO_REGS, NULL); } desc = malloc(sizeof(*desc)); assert(desc); desc->n_insns = n; qemu_plugin_register_vcpu_tb_exec_cb(tb, vcpu_tb_exec, QEMU_PLUGIN_CB_NO_REGS, desc); } QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, int argc, char **argv) { if (cs_open(CS_ARCH_X86, CS_MODE_64, &cap_handle) != CS_ERR_OK) { return -1; } cap_insn = cs_malloc(cap_handle); if (cap_insn == NULL) { return -1; } qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); return 0; }