qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [RFC 48/48] plugin: add a couple of very simple example


From: Emilio G. Cota
Subject: Re: [Qemu-devel] [RFC 48/48] plugin: add a couple of very simple examples
Date: Mon, 29 Oct 2018 12:38:50 -0400
User-agent: Mutt/1.9.4 (2018-02-28)

On Mon, Oct 29, 2018 at 13:59:03 +0300, Pavel Dovgalyuk wrote:
> > From: Emilio G. Cota [mailto:address@hidden
> > Signed-off-by: Emilio G. Cota <address@hidden>
(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;
}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]