Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/813082/?format=api
{ "id": 813082, "url": "http://patchwork.ozlabs.org/api/patches/813082/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/150525082913.15988.6500475428955069862.stgit@frigg.lan/", "project": { "id": 14, "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api", "name": "QEMU Development", "link_name": "qemu-devel", "list_id": "qemu-devel.nongnu.org", "list_email": "qemu-devel@nongnu.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<150525082913.15988.6500475428955069862.stgit@frigg.lan>", "list_archive_url": null, "date": "2017-09-12T21:13:49", "name": "[v5,03/22] instrument: Add generic library loader", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "f995bcc19643212a8a8229d54b174a579896f880", "submitter": { "id": 9099, "url": "http://patchwork.ozlabs.org/api/people/9099/?format=api", "name": "Lluís Vilanova", "email": "vilanova@ac.upc.edu" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/150525082913.15988.6500475428955069862.stgit@frigg.lan/mbox/", "series": [ { "id": 2775, "url": "http://patchwork.ozlabs.org/api/series/2775/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=2775", "date": "2017-09-12T21:01:42", "name": "instrument: Add basic event instrumentation", "version": 5, "mbox": "http://patchwork.ozlabs.org/series/2775/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/813082/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/813082/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)", "Received": [ "from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xsHd21chPz9t2Z\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 13 Sep 2017 07:15:16 +1000 (AEST)", "from localhost ([::1]:38642 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1drsWW-00025Q-Fk\n\tfor incoming@patchwork.ozlabs.org; Tue, 12 Sep 2017 17:15:12 -0400", "from eggs.gnu.org ([2001:4830:134:3::10]:57939)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <vilanova@ac.upc.edu>) id 1drsVP-0001RX-KM\n\tfor qemu-devel@nongnu.org; Tue, 12 Sep 2017 17:14:05 -0400", "from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <vilanova@ac.upc.edu>) id 1drsVM-0005HW-HO\n\tfor qemu-devel@nongnu.org; Tue, 12 Sep 2017 17:14:03 -0400", "from roura.ac.upc.edu ([147.83.33.10]:57255 helo=roura.ac.upc.es)\n\tby eggs.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <vilanova@ac.upc.edu>) id 1drsVL-0005GQ-UA\n\tfor qemu-devel@nongnu.org; Tue, 12 Sep 2017 17:14:00 -0400", "from correu-1.ac.upc.es (correu-1.ac.upc.es [147.83.30.91])\n\tby roura.ac.upc.es (8.13.8/8.13.8) with ESMTP id v8CLDuQA021763;\n\tTue, 12 Sep 2017 23:13:56 +0200", "from localhost (unknown [31.210.187.58])\n\tby correu-1.ac.upc.es (Postfix) with ESMTPSA id 85264201;\n\tTue, 12 Sep 2017 23:13:50 +0200 (CEST)" ], "From": "=?utf-8?b?TGx1w61z?= Vilanova <vilanova@ac.upc.edu>", "To": "qemu-devel@nongnu.org", "Date": "Wed, 13 Sep 2017 00:13:49 +0300", "Message-Id": "<150525082913.15988.6500475428955069862.stgit@frigg.lan>", "X-Mailer": "git-send-email 2.14.1", "In-Reply-To": "<150525010239.15988.8172586618197849619.stgit@frigg.lan>", "References": "<150525010239.15988.8172586618197849619.stgit@frigg.lan>", "User-Agent": "StGit/0.18", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "quoted-printable", "X-MIME-Autoconverted": "from 8bit to quoted-printable by roura.ac.upc.es id\n\tv8CLDuQA021763", "X-detected-operating-system": "by eggs.gnu.org: GNU/Linux 2.6.x [fuzzy]", "X-Received-From": "147.83.33.10", "Subject": "[Qemu-devel] [PATCH v5 03/22] instrument: Add generic library loader", "X-BeenThere": "qemu-devel@nongnu.org", "X-Mailman-Version": "2.1.21", "Precedence": "list", "List-Id": "<qemu-devel.nongnu.org>", "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>", "List-Archive": "<http://lists.nongnu.org/archive/html/qemu-devel/>", "List-Post": "<mailto:qemu-devel@nongnu.org>", "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>", "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>", "Cc": "Markus Armbruster <armbru@redhat.com>, \"Emilio G. Cota\" <cota@braap.org>,\n\tStefan Hajnoczi <stefanha@redhat.com>,\n\tPaolo Bonzini <pbonzini@redhat.com>, =?utf-8?q?Llu=C3=ADs_Vilanova?=\n\t<vilanova@ac.upc.edu>", "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org", "Sender": "\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>" }, "content": "Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>\n---\n MAINTAINERS | 1 \n Makefile.objs | 4 +\n configure | 3 +\n instrument/Makefile.objs | 4 +\n instrument/cmdline.c | 128 +++++++++++++++++++++++++++++++++++\n instrument/cmdline.h | 51 ++++++++++++++\n instrument/load.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++\n instrument/load.h | 88 ++++++++++++++++++++++++\n stubs/Makefile.objs | 1 \n stubs/instrument.c | 18 +++++\n 10 files changed, 464 insertions(+)\n create mode 100644 instrument/Makefile.objs\n create mode 100644 instrument/cmdline.c\n create mode 100644 instrument/cmdline.h\n create mode 100644 instrument/load.c\n create mode 100644 instrument/load.h\n create mode 100644 stubs/instrument.c", "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex fb0eaee06a..6c0b12a69a 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -1491,6 +1491,7 @@ M: Lluís Vilanova <vilanova@ac.upc.edu>\n M: Stefan Hajnoczi <stefanha@redhat.com>\n S: Maintained\n F: docs/instrument.txt\n+F: instrument/\n \n TPM\n S: Orphan\ndiff --git a/Makefile.objs b/Makefile.objs\nindex 24a4ea08b8..81a9218e14 100644\n--- a/Makefile.objs\n+++ b/Makefile.objs\n@@ -97,6 +97,10 @@ version-obj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.o\n util-obj-y += trace/\n target-obj-y += trace/\n \n+######################################################################\n+# instrument\n+target-obj-y += instrument/\n+\n ######################################################################\n # guest agent\n \ndiff --git a/configure b/configure\nindex a21d1bceb9..5175151317 100755\n--- a/configure\n+++ b/configure\n@@ -6025,6 +6025,9 @@ fi\n echo \"CONFIG_TRACE_FILE=$trace_file\" >> $config_host_mak\n \n if test \"$instrument\" = \"yes\"; then\n+ LDFLAGS=\"-rdynamic $LDFLAGS\" # limit symbols available to clients\n+ QEMU_CFLAGS=\"-fvisibility=hidden $QEMU_CFLAGS\"\n+ LIBS=\"-ldl $LIBS\"\n echo \"CONFIG_INSTRUMENT=y\" >> $config_host_mak\n fi\n \ndiff --git a/instrument/Makefile.objs b/instrument/Makefile.objs\nnew file mode 100644\nindex 0000000000..71994a4c85\n--- /dev/null\n+++ b/instrument/Makefile.objs\n@@ -0,0 +1,4 @@\n+# -*- mode: makefile -*-\n+\n+target-obj-$(CONFIG_INSTRUMENT) += cmdline.o\n+target-obj-$(CONFIG_INSTRUMENT) += load.o\ndiff --git a/instrument/cmdline.c b/instrument/cmdline.c\nnew file mode 100644\nindex 0000000000..da7a7cbceb\n--- /dev/null\n+++ b/instrument/cmdline.c\n@@ -0,0 +1,128 @@\n+/*\n+ * Control instrumentation during program (de)initialization.\n+ *\n+ * Copyright (C) 2012-2017 Lluís Vilanova <vilanova@ac.upc.edu>\n+ *\n+ * This work is licensed under the terms of the GNU GPL, version 2 or later.\n+ * See the COPYING file in the top-level directory.\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include <dlfcn.h>\n+#include \"instrument/cmdline.h\"\n+#include \"instrument/load.h\"\n+#include \"qemu/config-file.h\"\n+#include \"qemu/error-report.h\"\n+\n+\n+QemuOptsList qemu_instr_opts = {\n+ .name = \"instrument\",\n+ .implied_opt_name = \"file\",\n+ .merge_lists = true,\n+ .head = QTAILQ_HEAD_INITIALIZER(qemu_instr_opts.head),\n+ .desc = {\n+ {\n+ .name = \"file\",\n+ .type = QEMU_OPT_STRING,\n+ },{\n+ .name = \"arg\",\n+ .type = QEMU_OPT_STRING,\n+ },\n+ { /* end of list */ }\n+ },\n+};\n+\n+void instr_opt_parse(const char *optarg, char **path,\n+ int *argc, const char ***argv)\n+{\n+ const char *arg;\n+ QemuOptsIter iter;\n+ QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts(\"instrument\"),\n+ optarg, true);\n+ if (!opts) {\n+ exit(1);\n+ } else {\n+#if !defined(CONFIG_INSTRUMENT)\n+ error_report(\"instrumentation not enabled on this build\");\n+ exit(1);\n+#endif\n+ }\n+\n+\n+ arg = qemu_opt_get(opts, \"file\");\n+ if (arg != NULL) {\n+ g_free(*path);\n+ *path = g_strdup(arg);\n+ }\n+\n+ qemu_opt_iter_init(&iter, opts, \"arg\");\n+ while ((arg = qemu_opt_iter_next(&iter)) != NULL) {\n+ *argv = realloc(*argv, sizeof(**argv) * (*argc + 1));\n+ (*argv)[*argc] = g_strdup(arg);\n+ (*argc)++;\n+ }\n+\n+ qemu_opts_del(opts);\n+}\n+\n+void instr_init(const char *path, int argc, const char **argv)\n+{\n+#if defined(CONFIG_INSTRUMENT)\n+ InstrLoadError err;\n+\n+ if (path == NULL) {\n+ return;\n+ }\n+\n+ if (atexit(instr_fini) != 0) {\n+ fprintf(stderr, \"error: atexit: %s\\n\", strerror(errno));\n+ abort();\n+ }\n+\n+ const char *id = \"cmdline\";\n+ err = instr_load(path, argc, argv, &id);\n+ switch (err) {\n+ case INSTR_LOAD_OK:\n+ error_report(\"instrument: loaded library with ID '%s'\", id);\n+ return;\n+ case INSTR_LOAD_TOO_MANY:\n+ error_report(\"instrument: tried to load too many libraries\");\n+ break;\n+ case INSTR_LOAD_ID_EXISTS:\n+ g_assert_not_reached();\n+ break;\n+ case INSTR_LOAD_ERROR:\n+ error_report(\"instrument: library initialization returned non-zero\");\n+ break;\n+ case INSTR_LOAD_DLERROR:\n+ error_report(\"instrument: error loading library: %s\", dlerror());\n+ break;\n+ }\n+#else\n+ error_report(\"instrument: not available\");\n+#endif\n+\n+ exit(1);\n+}\n+\n+void instr_fini(void)\n+{\n+#if defined(CONFIG_INSTRUMENT)\n+ InstrUnloadError err = instr_unload_all();\n+\n+ switch (err) {\n+ case INSTR_UNLOAD_OK:\n+ return;\n+ case INSTR_UNLOAD_INVALID:\n+ /* the user might have already unloaded it */\n+ return;\n+ case INSTR_UNLOAD_DLERROR:\n+ error_report(\"instrument: error unloading library: %s\", dlerror());\n+ break;\n+ }\n+#else\n+ error_report(\"instrument: not available\");\n+#endif\n+\n+ exit(1);\n+}\ndiff --git a/instrument/cmdline.h b/instrument/cmdline.h\nnew file mode 100644\nindex 0000000000..3734f5f438\n--- /dev/null\n+++ b/instrument/cmdline.h\n@@ -0,0 +1,51 @@\n+/*\n+ * Control instrumentation during program (de)initialization.\n+ *\n+ * Copyright (C) 2012-2017 Lluís Vilanova <vilanova@ac.upc.edu>\n+ *\n+ * This work is licensed under the terms of the GNU GPL, version 2 or later.\n+ * See the COPYING file in the top-level directory.\n+ */\n+\n+#ifndef INSTRUMENT__CMDLINE_H\n+#define INSTRUMENT__CMDLINE_H\n+\n+#include \"qemu/typedefs.h\"\n+\n+\n+/**\n+ * Definition of QEMU options describing instrumentation subsystem\n+ * configuration.\n+ */\n+extern QemuOptsList qemu_instr_opts;\n+\n+/**\n+ * instr_opt_parse:\n+ * @optarg: A string argument of --instrument command line argument\n+ *\n+ * Initialize instrument subsystem.\n+ */\n+void instr_opt_parse(const char *optarg, char **path,\n+ int *argc, const char ***argv);\n+\n+/**\n+ * instr_init:\n+ * @path: Path to dynamic trace instrumentation library.\n+ * @argc: Number of arguments to the library's #qi_init routine.\n+ * @argv: Arguments to the library's #qi_init routine.\n+ *\n+ * Load and initialize the given instrumentation library. Calls exit() if the\n+ * library's initialization function returns a non-zero value.\n+ *\n+ * Installs instr_fini() as an atexit() callback.\n+ */\n+void instr_init(const char *path, int argc, const char **argv);\n+\n+/**\n+ * instr_fini:\n+ *\n+ * Deinitialize and unload all instrumentation libraries.\n+ */\n+void instr_fini(void);\n+\n+#endif /* INSTRUMENT__CMDLINE_H */\ndiff --git a/instrument/load.c b/instrument/load.c\nnew file mode 100644\nindex 0000000000..af98f4ce38\n--- /dev/null\n+++ b/instrument/load.c\n@@ -0,0 +1,166 @@\n+/*\n+ * Interface for (un)loading instrumentation libraries.\n+ *\n+ * Copyright (C) 2012-2017 Lluís Vilanova <vilanova@ac.upc.edu>\n+ *\n+ * This work is licensed under the terms of the GNU GPL, version 2 or later.\n+ * See the COPYING file in the top-level directory.\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"qemu-common.h\"\n+\n+#include <dlfcn.h>\n+#include \"instrument/load.h\"\n+#include \"qemu/config-file.h\"\n+#include \"qemu/error-report.h\"\n+\n+\n+typedef struct InstrHandle {\n+ char *id;\n+ void *dlhandle;\n+ QLIST_ENTRY(InstrHandle) list;\n+} InstrHandle;\n+\n+\n+static unsigned int handle_auto_id;\n+static QLIST_HEAD(, InstrHandle) handles = QLIST_HEAD_INITIALIZER(handles);\n+static QemuMutex instr_lock;\n+\n+\n+static InstrHandle *handle_new(const char **id)\n+{\n+ /* instr_lock is locked */\n+ InstrHandle *res = g_malloc0(sizeof(InstrHandle));\n+ if (!*id) {\n+ *id = g_strdup_printf(\"lib%d\", handle_auto_id);\n+ handle_auto_id++;\n+ }\n+ res->id = g_strdup(*id);\n+ QLIST_INSERT_HEAD(&handles, res, list);\n+ return res;\n+}\n+\n+static void handle_destroy(InstrHandle *handle)\n+{\n+ /* instr_lock is locked */\n+ QLIST_REMOVE(handle, list);\n+ g_free(handle->id);\n+ g_free(handle);\n+}\n+\n+static InstrHandle *handle_find(const char *id)\n+{\n+ /* instr_lock is locked */\n+ InstrHandle *handle;\n+ QLIST_FOREACH(handle, &handles, list) {\n+ if (strcmp(handle->id, id) == 0) {\n+ return handle;\n+ }\n+ }\n+ return NULL;\n+}\n+\n+InstrLoadError instr_load(const char *path, int argc, const char **argv,\n+ const char **id)\n+{\n+ InstrLoadError res;\n+ InstrHandle *handle;\n+ int (*main_cb)(int, const char **);\n+ int main_res;\n+\n+ qemu_rec_mutex_lock(&instr_lock);\n+\n+ if (*id && handle_find(*id)) {\n+ res = INSTR_LOAD_ID_EXISTS;\n+ goto out;\n+ }\n+\n+ if (!QLIST_EMPTY(&handles) > 0) {\n+ /* XXX: This is in fact a hard-coded limit, but there's no reason why a\n+ * real multi-library implementation should fail.\n+ */\n+ res = INSTR_LOAD_TOO_MANY;\n+ goto out;\n+ }\n+\n+ handle = handle_new(id);\n+ handle->dlhandle = dlopen(path, RTLD_NOW);\n+ if (handle->dlhandle == NULL) {\n+ res = INSTR_LOAD_DLERROR;\n+ goto err;\n+ }\n+\n+ main_cb = dlsym(handle->dlhandle, \"main\");\n+ if (main_cb == NULL) {\n+ res = INSTR_LOAD_DLERROR;\n+ goto err;\n+ }\n+\n+ main_res = main_cb(argc, argv);\n+\n+ if (main_res != 0) {\n+ res = INSTR_LOAD_ERROR;\n+ goto err;\n+ }\n+\n+ res = INSTR_LOAD_OK;\n+ goto out;\n+\n+err:\n+ handle_destroy(handle);\n+out:\n+ qemu_rec_mutex_unlock(&instr_lock);\n+ return res;\n+}\n+\n+InstrUnloadError instr_unload(const char *id)\n+{\n+ InstrUnloadError res;\n+\n+ qemu_rec_mutex_lock(&instr_lock);\n+\n+ InstrHandle *handle = handle_find(id);\n+ if (handle == NULL) {\n+ res = INSTR_UNLOAD_INVALID;\n+ goto out;\n+ }\n+\n+ /* this should never fail */\n+ if (dlclose(handle->dlhandle) < 0) {\n+ res = INSTR_UNLOAD_DLERROR;\n+ } else {\n+ res = INSTR_UNLOAD_OK;\n+ }\n+ handle_destroy(handle);\n+\n+out:\n+ qemu_rec_mutex_unlock(&instr_lock);\n+ return res;\n+}\n+\n+InstrUnloadError instr_unload_all(void)\n+{\n+ InstrUnloadError res = INSTR_UNLOAD_OK;\n+\n+ qemu_rec_mutex_lock(&instr_lock);\n+ while (true) {\n+ InstrHandle *handle = QLIST_FIRST(&handles);\n+ if (handle == NULL) {\n+ break;\n+ } else {\n+ res = instr_unload(handle->id);\n+ if (res != INSTR_UNLOAD_OK) {\n+ break;\n+ }\n+ }\n+ }\n+ qemu_rec_mutex_unlock(&instr_lock);\n+\n+ return res;\n+}\n+\n+static void __attribute__((constructor)) instr_lock_init(void)\n+{\n+ qemu_rec_mutex_init(&instr_lock);\n+}\ndiff --git a/instrument/load.h b/instrument/load.h\nnew file mode 100644\nindex 0000000000..162e09f9c9\n--- /dev/null\n+++ b/instrument/load.h\n@@ -0,0 +1,88 @@\n+/*\n+ * Interface for (un)loading instrumentation libraries.\n+ *\n+ * Copyright (C) 2012-2017 Lluís Vilanova <vilanova@ac.upc.edu>\n+ *\n+ * This work is licensed under the terms of the GNU GPL, version 2 or later.\n+ * See the COPYING file in the top-level directory.\n+ */\n+\n+\n+#ifndef INSTRUMENT_LOAD_H\n+#define INSTRUMENT_LOAD_H\n+\n+#include \"qemu/osdep.h\"\n+\n+#include \"qapi-types.h\"\n+#include \"qemu/queue.h\"\n+#include \"qemu/thread.h\"\n+\n+\n+/**\n+ * InstrLoadError:\n+ * @INSTR_LOAD_OK: Correctly loaded.\n+ * @INSTR_LOAD_ID_EXISTS: Tried to load an instrumentation libraries with an\n+ * existing ID.\n+ * @INSTR_LOAD_TOO_MANY: Tried to load too many instrumentation libraries.\n+ * @INSTR_LOAD_ERROR: The library's main() function returned a non-zero value.\n+ * @INSTR_LOAD_DLERROR: Error with libdl (see dlerror).\n+ *\n+ * Error codes for instr_load().\n+ */\n+typedef enum {\n+ INSTR_LOAD_OK,\n+ INSTR_LOAD_ID_EXISTS,\n+ INSTR_LOAD_TOO_MANY,\n+ INSTR_LOAD_ERROR,\n+ INSTR_LOAD_DLERROR,\n+} InstrLoadError;\n+\n+/**\n+ * InstrUnloadError:\n+ * @INSTR_UNLOAD_OK: Correctly unloaded.\n+ * @INSTR_UNLOAD_INVALID: Invalid handle.\n+ * @INSTR_UNLOAD_DLERROR: Error with libdl (see dlerror).\n+ *\n+ * Error codes for instr_unload().\n+ */\n+typedef enum {\n+ INSTR_UNLOAD_OK,\n+ INSTR_UNLOAD_INVALID,\n+ INSTR_UNLOAD_DLERROR,\n+} InstrUnloadError;\n+\n+/**\n+ * instr_load:\n+ * @path: Path to the shared library to load.\n+ * @argc: Number of arguments passed to the initialization function of the\n+ * library.\n+ * @argv: Arguments passed to the initialization function of the library.\n+ * @id: Instrumentation library id.\n+ *\n+ * Load a dynamic trace instrumentation library.\n+ *\n+ * Returns: Whether the library could be loaded.\n+ */\n+InstrLoadError instr_load(const char *path, int argc, const char **argv,\n+ const char **id);\n+\n+/**\n+ * instr_unload:\n+ * @id: Instrumentation library id passed to instr_load().\n+ *\n+ * Unload the given instrumentation library.\n+ *\n+ * Returns: Whether the library could be unloaded.\n+ */\n+InstrUnloadError instr_unload(const char *id);\n+\n+/**\n+ * instr_unload_all:\n+ *\n+ * Unload all instrumentation libraries.\n+ *\n+ * Returns: Whether any library could not be unloaded.\n+ */\n+InstrUnloadError instr_unload_all(void);\n+\n+#endif /* INSTRUMENT_LOAD_H */\ndiff --git a/stubs/Makefile.objs b/stubs/Makefile.objs\nindex 4a33495911..4bf342cb96 100644\n--- a/stubs/Makefile.objs\n+++ b/stubs/Makefile.objs\n@@ -13,6 +13,7 @@ stub-obj-y += error-printf.o\n stub-obj-y += fdset.o\n stub-obj-y += gdbstub.o\n stub-obj-y += get-vm-name.o\n+stub-obj-y += instrument.o\n stub-obj-y += iothread.o\n stub-obj-y += iothread-lock.o\n stub-obj-y += is-daemonized.o\ndiff --git a/stubs/instrument.c b/stubs/instrument.c\nnew file mode 100644\nindex 0000000000..7d66f75454\n--- /dev/null\n+++ b/stubs/instrument.c\n@@ -0,0 +1,18 @@\n+/*\n+ * Instrumentation placeholders.\n+ *\n+ * Copyright (C) 2017 Lluís Vilanova <vilanova@ac.upc.edu>\n+ *\n+ * This work is licensed under the terms of the GNU GPL, version 2 or later.\n+ * See the COPYING file in the top-level directory.\n+ */\n+\n+#include \"instrument/cmdline.h\"\n+\n+\n+void instr_init(const char *path, int argc, const char **argv)\n+{\n+}\n+void instr_fini(void)\n+{\n+}\n", "prefixes": [ "v5", "03/22" ] }