diff mbox

[07/13] instrument: Add generic command line library loader

Message ID 150091744146.30739.9284399356256394869.stgit@frigg.lan (mailing list archive)
State New, archived
Headers show

Commit Message

Lluís Vilanova July 24, 2017, 5:30 p.m. UTC
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 instrument/Makefile.objs |    1 
 instrument/cmdline.c     |  117 ++++++++++++++++++++++++++++++++++++++++++++++
 instrument/cmdline.h     |   58 +++++++++++++++++++++++
 3 files changed, 176 insertions(+)
 create mode 100644 instrument/cmdline.c
 create mode 100644 instrument/cmdline.h
diff mbox

Patch

diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs
index 244936aa8c..aa6db29ff4 100644
--- a/instrument/Makefile.objs
+++ b/instrument/Makefile.objs
@@ -43,3 +43,4 @@  $(obj)/qemu-instr/events.h-timestamp: $(BUILD_DIR)/trace-events-all $(BUILD_DIR)
 # Control code
 
 target-obj-y += control.o
+target-obj-y += cmdline.o
diff --git a/instrument/cmdline.c b/instrument/cmdline.c
new file mode 100644
index 0000000000..e0c0e9ce1b
--- /dev/null
+++ b/instrument/cmdline.c
@@ -0,0 +1,117 @@ 
+/*
+ * Control dynamic trace instrumentation during program (de)initialization.
+ *
+ * Copyright (C) 2012-2017 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include <dlfcn.h>
+#include "instrument/cmdline.h"
+#include "instrument/control.h"
+#include "qemu/config-file.h"
+#include "qemu/error-report.h"
+
+
+QemuOptsList qemu_instr_opts = {
+    .name = "instrument",
+    .implied_opt_name = "file",
+    .merge_lists = true,
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_instr_opts.head),
+    .desc = {
+        {
+            .name = "file",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "arg",
+            .type = QEMU_OPT_STRING,
+        },
+        { /* end of list */ }
+    },
+};
+
+void instr_opt_parse(const char *optarg, char **path,
+                     int *argc, const char ***argv)
+{
+    const char *arg;
+    QemuOptsIter iter;
+    QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("instrument"),
+                                             optarg, true);
+    if (!opts) {
+        exit(1);
+    } else {
+#if !defined(CONFIG_INSTRUMENT)
+        error_report("instrumentation not enabled on this build");
+        exit(1);
+#endif
+    }
+
+
+    arg = qemu_opt_get(opts, "file");
+    if (arg != NULL) {
+        g_free(*path);
+        *path = g_strdup(arg);
+    }
+
+    qemu_opt_iter_init(&iter, opts, "arg");
+    while ((arg = qemu_opt_iter_next(&iter)) != NULL) {
+        *argv = realloc(*argv, sizeof(**argv) * (*argc + 1));
+        (*argv)[*argc] = g_strdup(arg);
+        (*argc)++;
+    }
+
+    qemu_opts_del(opts);
+}
+
+
+void instr_init(const char *path, int argc, const char **argv)
+{
+    InstrLoadError err;
+    int64_t handle;
+
+    if (path == NULL) {
+        return;
+    }
+
+    if (atexit(instr_fini) != 0) {
+        fprintf(stderr, "error: atexit: %s\n", strerror(errno));
+        abort();
+    }
+
+    err = instr_load(path, argc, argv, &handle);
+    switch (err) {
+    case INSTR_LOAD_OK:
+        return;
+    case INSTR_LOAD_UNAVAILABLE:
+        error_report("instrument: not available");
+        break;
+    case INSTR_LOAD_ERROR:
+        error_report("instrument: error loading library: %s", dlerror());
+        break;
+    }
+
+    exit(1);
+}
+
+void instr_fini(void)
+{
+    InstrUnloadError err = instr_unload_all();
+
+    switch (err) {
+    case INSTR_UNLOAD_OK:
+        return;
+    case INSTR_UNLOAD_UNAVAILABLE:
+        error_report("instrument: not available");
+        break;
+    case INSTR_UNLOAD_INVALID:
+        /* the user might have already unloaded it */
+        return;
+    case INSTR_UNLOAD_ERROR:
+        error_report("instrument: error unloading library: %s", dlerror());
+        break;
+    }
+
+    exit(1);
+}
diff --git a/instrument/cmdline.h b/instrument/cmdline.h
new file mode 100644
index 0000000000..c5eebf8b58
--- /dev/null
+++ b/instrument/cmdline.h
@@ -0,0 +1,58 @@ 
+/*
+ * Control dynamic trace instrumentation during program (de)initialization.
+ *
+ * Copyright (C) 2012-2017 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef INSTRUMENT__CMDLINE_H
+#define INSTRUMENT__CMDLINE_H
+
+
+/**
+ * Definition of QEMU options describing instrumentation subsystem
+ * configuration.
+ */
+extern QemuOptsList qemu_instr_opts;
+
+/**
+ * instr_opt_parse:
+ * @optarg: A string argument of --instrument command line argument
+ *
+ * Initialize instrument subsystem.
+ */
+void instr_opt_parse(const char *optarg, char **path,
+                     int *argc, const char ***argv);
+
+/**
+ * instr_init:
+ * @path: Path to dynamic trace instrumentation library.
+ * @argc: Number of arguments to the library's #qi_init routine.
+ * @argv: Arguments to the library's #qi_init routine.
+ *
+ * Load and initialize the given instrumentation library.
+ *
+ * Automatically installs #instr_fini as an atexit callback.
+ *
+ * If path is %NULL and we're running with static instrumentation, the library
+ * is not loaded but just initialized.
+ *
+ * Pre-condition: There is no library already loaded.
+ */
+void instr_init(const char *path, int argc, const char **argv);
+
+/**
+ * instr_fini:
+ *
+ * Deinitialize and unload the current instrumentation library.
+ *
+ * If we're running with static instrumentation, the library is not unloaded but
+ * just deinitialized.
+ *
+ * Pre-condition: There is an already loaded library.
+ */
+void instr_fini(void);
+
+#endif  /* INSTRUMENT__CMDLINE_H */