Add QMP commands to control (un)loading of dynamic instrumentation library.
Signed-off-by: Lluís Vilanova <vilan...@ac.upc.edu> --- include/qapi/qmp/qerror.h | 9 +++++ instrument/Makefile.objs | 1 + instrument/qapi-schema.json | 33 ++++++++++++++++++++ instrument/qmp.c | 70 ++++++++++++++++++++++++++++++++++++++++++ qapi-schema.json | 2 + qmp-commands.hx | 71 +++++++++++++++++++++++++++++++++++++++++++ qmp.c | 4 ++ 7 files changed, 190 insertions(+) create mode 100644 instrument/qapi-schema.json create mode 100644 instrument/qmp.c diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h index 6c0a18d..67b4528 100644 --- a/include/qapi/qmp/qerror.h +++ b/include/qapi/qmp/qerror.h @@ -129,6 +129,15 @@ void assert_no_error(Error *err); #define QERR_FEATURE_DISABLED \ ERROR_CLASS_GENERIC_ERROR, "The feature '%s' is not enabled" +#define QERR_INSTR_LOAD_DL \ + ERROR_CLASS_GENERIC_ERROR, "Error loading dynamic library: %s" + +#define QERR_INSTR_LOAD_LOADED \ + ERROR_CLASS_GENERIC_ERROR, "Already loaded" + +#define QERR_INSTR_LOAD_UNLOADED \ + ERROR_CLASS_GENERIC_ERROR, "Already unloaded" + #define QERR_INVALID_BLOCK_FORMAT \ ERROR_CLASS_GENERIC_ERROR, "Invalid block format '%s'" diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs index 02cc5b7..e3d4e9b 100644 --- a/instrument/Makefile.objs +++ b/instrument/Makefile.objs @@ -68,3 +68,4 @@ endif target-obj-y += control.o common-obj-$(CONFIG_SOFTMMU) += hmp.o +common-obj-$(CONFIG_SOFTMMU) += qmp.o diff --git a/instrument/qapi-schema.json b/instrument/qapi-schema.json new file mode 100644 index 0000000..0ecf31f --- /dev/null +++ b/instrument/qapi-schema.json @@ -0,0 +1,33 @@ +# *-*- Mode: Python -*-* + +## +# @instr-dynamic: +# +# Whether dynamic trace instrumentation is available. +# +# Since: 1.5 +## +{ 'command': 'instr-dynamic', + 'returns': 'bool' } + +## +# @instr-load: +# +# Load a dynamic instrumentation library. +# +# @path: path to the dynamic instrumentation library +# @iargs: arguments to the dynamic instrumentation library +# +# Since: 1.5 +## +{ 'command': 'instr-load', + 'data': { 'path': 'str', 'iargs': ['String'] } } + +## +# @instr-unload: +# +# Unload the current dynamic instrumentation library. +# +# Since: 1.5 +## +{ 'command': 'instr-unload' } diff --git a/instrument/qmp.c b/instrument/qmp.c new file mode 100644 index 0000000..f744250 --- /dev/null +++ b/instrument/qmp.c @@ -0,0 +1,70 @@ +/* + * QMP interface for dynamic trace instrumentation control commands. + * + * Copyright (C) 2012-2013 Lluís Vilanova <vilan...@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-common.h" +#include "qapi/qmp/qerror.h" +#include "qmp-commands.h" + +#include <dlfcn.h> + +#include "instrument/control.h" + + + +bool qmp_instr_dynamic(Error **errp) +{ + return instr_dynamic(); +} + +void qmp_instr_load(const char * path, StringList * iargs, Error **errp) +{ + int argc = 0; + const char **argv = NULL; + + StringList *entry; + while (entry != NULL) { + argv = realloc(argv, sizeof(*argv) * (argc + 1)); + argv[argc] = entry->value->str; + argc++; + entry = entry->next; + } + + InstrLoadError err = instr_load(path, argc, argv); + switch (err) { + case INSTR_LOAD_OK: + break; + case INSTR_LOAD_UNAVAILABLE: + error_set(errp, QERR_UNSUPPORTED); + break; + case INSTR_LOAD_LOADED: + error_set(errp, QERR_INSTR_LOAD_LOADED); + break; + case INSTR_LOAD_DL: + error_set(errp, QERR_INSTR_LOAD_DL, dlerror()); + break; + } +} + +void qmp_instr_unload(Error **errp) +{ + InstrLoadError err = instr_unload(); + switch (err) { + case INSTR_UNLOAD_OK: + break; + case INSTR_UNLOAD_UNAVAILABLE: + error_set(errp, QERR_UNSUPPORTED); + break; + case INSTR_UNLOAD_UNLOADED: + error_set(errp, QERR_INSTR_LOAD_UNLOADED); + break; + case INSTR_UNLOAD_DL: + error_set(errp, QERR_INSTR_LOAD_DL, dlerror()); + break; + } +} diff --git a/qapi-schema.json b/qapi-schema.json index db542f6..bc5fe06 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -3513,3 +3513,5 @@ '*asl_compiler_rev': 'uint32', '*file': 'str', '*data': 'str' }} + +input("instrument/qapi-schema.json") diff --git a/qmp-commands.hx b/qmp-commands.hx index 1e0e11e..1ea6c38 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -1510,6 +1510,77 @@ Notes: o Commands that prompt the user for data (eg. 'cont' when the block device is encrypted) don't currently work +instr-dynamic +------------- + +Whether dynamic trace instrumentation is available. + +Arguments: None. + +Example: + +-> { "execute": "instr-dyanmic" } +<- { "return": true } + +EQMP + + { + .name = "instr-dynamic", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_instr_dynamic, + }, + + +SQMP + +instr-load +---------- + +Load a dynamic instrumentation library. + +Arguments: + +- path: path to the dynamic instrumentation library +- args: arguments to the dynamic instrumentation library + +Example: + +-> { "execute": "instr-load", "arguments": { "path": "/tmp/libtrace-instrument.so" } } +<- { "return": {} } + +EQMP + + { + .name = "instr-load", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_instr_load, + }, + + +SQMP + +instr-unload +------------ + +Unload the current dynamic instrumentation library. + +Arguments: None. + +Example: + +-> { "execute": "instr-unload" } +<- { "return": {} } + +EQMP + + { + .name = "instr-unload", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_instr_unload, + }, + + +SQMP 3. Query Commands ================= diff --git a/qmp.c b/qmp.c index 55b056b..72abe03 100644 --- a/qmp.c +++ b/qmp.c @@ -24,6 +24,10 @@ #include "hw/qdev.h" #include "sysemu/blockdev.h" #include "qom/qom-qobject.h" +#if defined(TRACE_INSTRUMENT_DYNAMIC) +#include "instrument/qi-qmp-commands.h" +#endif + NameInfo *qmp_query_name(Error **errp) {