All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: qemu-devel@nongnu.org
Cc: fam@euphon.net, berrange@redhat.com, f4bug@amsat.org,
	stefanha@redhat.com, crosa@redhat.com, pbonzini@redhat.com,
	"Mahmoud Mandour" <ma.mandourr@gmail.com>,
	"Alexandre Iooss" <erdnaxe@crans.org>,
	"Alex Bennée" <alex.bennee@linaro.org>,
	aurelien@aurel32.net
Subject: [PATCH v1 33/39] contrib/plugins: add execlog to log instruction execution and memory access
Date: Tue,  6 Jul 2021 15:58:11 +0100	[thread overview]
Message-ID: <20210706145817.24109-34-alex.bennee@linaro.org> (raw)
In-Reply-To: <20210706145817.24109-1-alex.bennee@linaro.org>

From: Alexandre Iooss <erdnaxe@crans.org>

Log instruction execution and memory access to a file.
This plugin can be used for reverse engineering or for side-channel analysis
using QEMU.

Signed-off-by: Alexandre Iooss <erdnaxe@crans.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20210702081307.1653644-2-erdnaxe@crans.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 contrib/plugins/execlog.c | 153 ++++++++++++++++++++++++++++++++++++++
 MAINTAINERS               |   1 +
 contrib/plugins/Makefile  |   1 +
 3 files changed, 155 insertions(+)
 create mode 100644 contrib/plugins/execlog.c

diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c
new file mode 100644
index 0000000000..2de9f0d7d4
--- /dev/null
+++ b/contrib/plugins/execlog.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2021, Alexandre Iooss <erdnaxe@crans.org>
+ *
+ * Log instruction execution with memory access.
+ *
+ * License: GNU GPL, version 2 or later.
+ *   See the COPYING file in the top-level directory.
+ */
+#include <glib.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <qemu-plugin.h>
+
+QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
+
+/* Store last executed instruction on each vCPU as a GString */
+GArray *last_exec;
+
+/**
+ * Add memory read or write information to current instruction log
+ */
+static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t info,
+                     uint64_t vaddr, void *udata)
+{
+    GString *s;
+
+    /* Find vCPU in array */
+    g_assert(cpu_index < last_exec->len);
+    s = g_array_index(last_exec, GString *, cpu_index);
+
+    /* Indicate type of memory access */
+    if (qemu_plugin_mem_is_store(info)) {
+        g_string_append(s, ", store");
+    } else {
+        g_string_append(s, ", load");
+    }
+
+    /* If full system emulation log physical address and device name */
+    struct qemu_plugin_hwaddr *hwaddr = qemu_plugin_get_hwaddr(info, vaddr);
+    if (hwaddr) {
+        uint64_t addr = qemu_plugin_hwaddr_phys_addr(hwaddr);
+        const char *name = qemu_plugin_hwaddr_device_name(hwaddr);
+        g_string_append_printf(s, ", 0x%08"PRIx64", %s", addr, name);
+    } else {
+        g_string_append_printf(s, ", 0x%08"PRIx64, vaddr);
+    }
+}
+
+/**
+ * Log instruction execution
+ */
+static void vcpu_insn_exec(unsigned int cpu_index, void *udata)
+{
+    GString *s;
+
+    /* Find or create vCPU in array */
+    while (cpu_index >= last_exec->len) {
+        s = g_string_new(NULL);
+        g_array_append_val(last_exec, s);
+    }
+    s = g_array_index(last_exec, GString *, cpu_index);
+
+    /* Print previous instruction in cache */
+    if (s->len) {
+        qemu_plugin_outs(s->str);
+        qemu_plugin_outs("s\n");
+    }
+
+    /* Store new instruction in cache */
+    /* vcpu_mem will add memory access information to last_exec */
+    g_string_printf(s, "%u, ", cpu_index);
+    g_string_append(s, (char *)udata);
+}
+
+/**
+ * On translation block new translation
+ *
+ * QEMU convert code by translation block (TB). By hooking here we can then hook
+ * a callback on each instruction and memory access.
+ */
+static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
+{
+    struct qemu_plugin_insn *insn;
+    uint64_t insn_vaddr;
+    uint32_t insn_opcode;
+    char *insn_disas;
+
+    size_t n = qemu_plugin_tb_n_insns(tb);
+    for (size_t i = 0; i < n; i++) {
+        /*
+         * `insn` is shared between translations in QEMU, copy needed data here.
+         * `output` is never freed as it might be used multiple times during
+         * the emulation lifetime.
+         * We only consider the first 32 bits of the instruction, this may be
+         * a limitation for CISC architectures.
+         */
+        insn = qemu_plugin_tb_get_insn(tb, i);
+        insn_vaddr = qemu_plugin_insn_vaddr(insn);
+        insn_opcode = *((uint32_t *)qemu_plugin_insn_data(insn));
+        insn_disas = qemu_plugin_insn_disas(insn);
+        char *output = g_strdup_printf("0x%"PRIx64", 0x%"PRIx32", \"%s\"",
+                                       insn_vaddr, insn_opcode, insn_disas);
+
+        /* Register callback on memory read or write */
+        qemu_plugin_register_vcpu_mem_cb(insn, vcpu_mem,
+                                         QEMU_PLUGIN_CB_NO_REGS,
+                                         QEMU_PLUGIN_MEM_RW, NULL);
+
+        /* Register callback on instruction */
+        qemu_plugin_register_vcpu_insn_exec_cb(insn, vcpu_insn_exec,
+                                               QEMU_PLUGIN_CB_NO_REGS, output);
+    }
+}
+
+/**
+ * On plugin exit, print last instruction in cache
+ */
+static void plugin_exit(qemu_plugin_id_t id, void *p)
+{
+    guint i;
+    GString *s;
+    for (i = 0; i < last_exec->len; i++) {
+        s = g_array_index(last_exec, GString *, i);
+        if (s->str) {
+            qemu_plugin_outs(s->str);
+            qemu_plugin_outs("\n");
+        }
+    }
+}
+
+/**
+ * Install the plugin
+ */
+QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
+                                           const qemu_info_t *info, int argc,
+                                           char **argv)
+{
+    /*
+     * Initialize dynamic array to cache vCPU instruction. In user mode
+     * we don't know the size before emulation.
+     */
+    last_exec = g_array_new(FALSE, FALSE, sizeof(GString *));
+
+    /* Register translation block and exit callbacks */
+    qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
+    qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);
+
+    return 0;
+}
diff --git a/MAINTAINERS b/MAINTAINERS
index 684142e12e..ee456e5fb4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2981,6 +2981,7 @@ F: include/tcg/
 
 TCG Plugins
 M: Alex Bennée <alex.bennee@linaro.org>
+R: Alexandre Iooss <erdnaxe@crans.org>
 S: Maintained
 F: docs/devel/tcg-plugins.rst
 F: plugins/
diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile
index 17e6e2ec4f..6ac67aacaf 100644
--- a/contrib/plugins/Makefile
+++ b/contrib/plugins/Makefile
@@ -13,6 +13,7 @@ include $(BUILD_DIR)/config-host.mak
 VPATH += $(SRC_PATH)/contrib/plugins
 
 NAMES :=
+NAMES += execlog
 NAMES += hotblocks
 NAMES += hotpages
 NAMES += howvec
-- 
2.20.1



  parent reply	other threads:[~2021-07-06 15:28 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-06 14:57 [PATCH v1 00/39] final pre-PR for 6.1 (testing and plugins) Alex Bennée
2021-07-06 14:57 ` [PATCH v1 01/39] Jobs based on custom runners: documentation and configuration placeholder Alex Bennée
2021-07-06 14:57 ` [PATCH v1 02/39] Jobs based on custom runners: build environment docs and playbook Alex Bennée
2021-07-06 14:57 ` [PATCH v1 03/39] Jobs based on custom runners: docs and gitlab-runner setup playbook Alex Bennée
2021-07-06 14:57 ` [PATCH v1 04/39] Jobs based on custom runners: add job definitions for QEMU's machines Alex Bennée
2021-07-06 14:57 ` [PATCH v1 05/39] tests/tcg: generalise the disabling of the signals test Alex Bennée
2021-07-08 15:29   ` Peter Maydell
2021-07-06 14:57 ` [PATCH v1 06/39] build: validate that system capstone works before using it Alex Bennée
2021-07-06 14:57 ` [PATCH v1 07/39] gitlab: support for FreeBSD 12, 13 and macOS 11 via cirrus-run Alex Bennée
2021-07-06 14:57 ` [PATCH v1 08/39] cirrus: delete FreeBSD and macOS jobs Alex Bennée
2021-07-06 14:57 ` [PATCH v1 09/39] hw/usb/ccid: remove references to NSS Alex Bennée
2021-07-06 14:57 ` [PATCH v1 10/39] tests/docker: don't use BUILDKIT in GitLab either Alex Bennée
2021-07-06 14:57 ` [PATCH v1 11/39] tests/docker: use project specific container registries Alex Bennée
2021-07-06 14:57 ` [PATCH v1 12/39] tests/docker: use explicit docker.io registry Alex Bennée
2021-07-06 14:57 ` [PATCH v1 13/39] tests/docker: remove FEATURES env var from templates Alex Bennée
2021-07-06 14:57 ` [PATCH v1 14/39] tests/docker: fix sorting in package lists Alex Bennée
2021-07-06 14:57 ` [PATCH v1 15/39] tests/docker: fix mistakes in centos " Alex Bennée
2021-07-06 14:57 ` [PATCH v1 16/39] tests/docker: fix mistakes in fedora package list Alex Bennée
2021-07-06 14:57 ` [PATCH v1 17/39] tests/docker: fix mistakes in ubuntu package lists Alex Bennée
2021-07-07 14:41   ` Philippe Mathieu-Daudé
2021-07-07 14:49     ` Daniel P. Berrangé
2021-07-06 14:57 ` [PATCH v1 18/39] tests/docker: remove mingw packages from Fedora Alex Bennée
2021-07-06 14:57 ` [PATCH v1 19/39] tests/docker: expand centos8 package list Alex Bennée
2021-07-06 14:57 ` [PATCH v1 20/39] tests/docker: expand fedora " Alex Bennée
2021-07-06 14:57 ` [PATCH v1 21/39] tests/docker: expand ubuntu1804 " Alex Bennée
2021-07-06 14:58 ` [PATCH v1 22/39] tests/docker: expand ubuntu2004 " Alex Bennée
2021-07-06 14:58 ` [PATCH v1 23/39] tests/docker: expand opensuse-leap " Alex Bennée
2021-07-06 14:58 ` [PATCH v1 24/39] tests/vm: update NetBSD to 9.2 Alex Bennée
2021-07-06 14:58 ` [PATCH v1 25/39] tests/vm: update openbsd to release 6.9 Alex Bennée
2021-07-06 14:58 ` [PATCH v1 26/39] tests/tcg: make test-mmap a little less aggressive Alex Bennée
2021-07-06 14:58 ` [PATCH v1 27/39] plugins: fix-up handling of internal hostaddr for 32 bit Alex Bennée
2021-07-06 14:58 ` [PATCH v1 28/39] meson.build: move TCG plugin summary output Alex Bennée
2021-07-06 14:58 ` [PATCH v1 29/39] configure: don't allow plugins to be enabled for a non-TCG build Alex Bennée
2021-07-07  4:17   ` Thomas Huth
2021-07-06 14:58 ` [PATCH v1 30/39] configure: stop user enabling plugins on Windows for now Alex Bennée
2021-07-07  4:24   ` Thomas Huth
2021-07-06 14:58 ` [PATCH v1 31/39] tcg/plugins: enable by default for TCG builds Alex Bennée
2021-07-07  4:32   ` Thomas Huth
2021-07-06 14:58 ` [PATCH v1 32/39] contrib/plugins: enable -Wall for building plugins Alex Bennée
2021-07-07  4:36   ` Thomas Huth
2021-07-06 14:58 ` Alex Bennée [this message]
2021-07-06 14:58 ` [PATCH v1 34/39] docs/devel: tcg-plugins: add execlog plugin description Alex Bennée
2021-07-06 14:58 ` [PATCH v1 35/39] plugins: Added a new cache modelling plugin Alex Bennée
2021-07-06 14:58 ` [PATCH v1 36/39] plugins/cache: Enable cache parameterization Alex Bennée
2021-07-06 14:58 ` [PATCH v1 37/39] plugins/cache: Added FIFO and LRU eviction policies Alex Bennée
2021-07-06 14:58 ` [PATCH v1 38/39] docs/devel: Added cache plugin to the plugins docs Alex Bennée
2021-07-06 14:58 ` [PATCH v1 39/39] MAINTAINTERS: Added myself as a reviewer for TCG Plugins Alex Bennée
2021-07-06 15:35   ` Peter Maydell
2021-07-07  8:33 ` [PATCH v1 00/39] final pre-PR for 6.1 (testing and plugins) Philippe Mathieu-Daudé

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210706145817.24109-34-alex.bennee@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=aurelien@aurel32.net \
    --cc=berrange@redhat.com \
    --cc=crosa@redhat.com \
    --cc=erdnaxe@crans.org \
    --cc=f4bug@amsat.org \
    --cc=fam@euphon.net \
    --cc=ma.mandourr@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.