* [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines
@ 2013-04-16 13:49 Lluís Vilanova
2013-04-16 13:49 ` [Qemu-devel] [PATCH v2 01/23] instrument: Add documentation Lluís Vilanova
` (23 more replies)
0 siblings, 24 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:49 UTC (permalink / raw)
To: qemu-devel
TODO: Make sure no TCG code is executing during 'instr_unload' (qemu_cpu_kick?
tb_lock?)
The whole set of patch series is available at:
https://projects.gso.ac.upc.edu/projects/qemu-dbi
Adds the "instrument" event property to declare which tracing events in QEMU
must be instrumentable. Still, in case the user only wants to wrap around the
tracing events, the original tracing implementation is accessible through the
appropriate routines.
The instrumentation can be performed either through a dynamically-loaded library
or through user-provided code that is compiled into QEMU itself (useful when
instrumenting high-frequency events, as the fast-path of the instrumentation can
be inlined into QEMU).
As a side-effect this series adds an API for the instrumentation code to have
some basic interaction with QEMU.
See the documentation added in the first patch for more information.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
Changes in v2:
* Rebased on latest master (e2ec3f9).
* Added "libqemutools.a".
* Have 'tracetool' forbid certain event argument names.
* Fixed title in path for "linux-headers" include path (Peter Maydell).
* Small fixes to qapi/qmp (Eric Blake).
* Have 'qi_init' accept a list of strings as arguments (Eric Blake)
Lluís Vilanova (23):
instrument: Add documentation
trace: [simple] Do not include "trace/simple.h" in generated tracer headers
trace: Let the user specify her own trace-events file
tracetool: Use method 'Event.api' to get the name of public routines
trace: Minimize inclusions of "qemu-common.h" to avoid inclusion loops
instrument: [none] Add null instrumentation
system: [linux] Use absolute include path for linux-headers
instrument: [static] Call statically linked user-provided routines
build: Add variable 'tools-obj-y' for tool-only files
instrument: [dynamic] Call dynamically linked user-provided routines
instrument: Add internal control interface
instrument: [hmp] Add control interface
qapi: Add a primitive to include other files from a QAPI schema file
[trivial] Set the input root directory when parsing QAPI files
instrument: [qmp, qapi] Add control interface
Let makefiles add entries to the set of target architecture objects
instrument: Add commandline options to start with an instrumentation library
instrument: Add client-side API to enumerate events
instrument: Add client-side API to control tracing state of events
instrument: Add client-side API to control event instrumentation
build: Fix installation of target-dependant files
instrument: Install headers for dynamic instrumentation clients
trace: Do not use the word 'new' in event arguments
.gitignore | 4
Makefile | 57 +++
Makefile.objs | 9
Makefile.target | 7
bsd-user/main.c | 25 +
bsd-user/syscall.c | 5
configure | 96 +++++
docs/instrumentation.txt | 496 +++++++++++++++++++++++++++
docs/tracing.txt | 9
hmp-commands.hx | 42 ++
hw/virtio/virtio.c | 1
include/qapi/qmp/qerror.h | 9
include/trace.h | 2
instrument/Makefile.objs | 87 +++++
instrument/api-control.c | 14 +
instrument/api-trace.c | 14 +
instrument/cmdline.c | 101 +++++
instrument/cmdline.h | 52 +++
instrument/control-internal.h | 38 ++
instrument/control.c | 139 ++++++++
instrument/control.h | 134 +++++++
instrument/hmp.c | 66 ++++
instrument/hmp.h | 21 +
instrument/qapi-schema.json | 33 ++
instrument/qemu-instr/control-internal.h | 69 ++++
instrument/qemu-instr/control.h | 185 ++++++++++
instrument/qemu-instr/trace-internal.h | 32 ++
instrument/qemu-instr/trace.h | 91 +++++
instrument/qemu-instr/visibility-internal.h | 94 +++++
instrument/qmp.c | 70 ++++
libcacard/Makefile | 4
linux-user/main.c | 30 ++
linux-user/syscall.c | 4
monitor.c | 5
qapi-schema.json | 2
qemu-options.hx | 18 +
qmp-commands.hx | 71 ++++
qmp.c | 4
rules.mak | 3
scripts/qapi-commands.py | 10 -
scripts/qapi-types.py | 10 -
scripts/qapi-visit.py | 10 -
scripts/qapi.py | 12 +
scripts/tracetool.py | 14 +
scripts/tracetool/__init__.py | 44 ++
scripts/tracetool/backend/dtrace.py | 6
scripts/tracetool/backend/instr_dynamic.py | 93 +++++
scripts/tracetool/backend/instr_none.py | 44 ++
scripts/tracetool/backend/instr_static.py | 82 ++++
scripts/tracetool/backend/simple.py | 13 -
scripts/tracetool/backend/stderr.py | 5
scripts/tracetool/backend/ust.py | 8
scripts/tracetool/format/api_c.py | 24 +
scripts/tracetool/format/api_events_h.py | 56 +++
scripts/tracetool/format/api_h.py | 39 ++
scripts/tracetool/format/events_c.py | 42 ++
scripts/tracetool/format/h.py | 15 +
scripts/tracetool/format/qemu_h.py | 68 ++++
trace-events | 8
trace/Makefile.objs | 10 -
trace/control-internal.h | 4
trace/control.c | 4
trace/control.h | 9
trace/default.c | 4
trace/event-internal.h | 17 +
trace/simple.c | 6
trace/simple.h | 1
trace/stderr.c | 4
vl.c | 41 ++
69 files changed, 2774 insertions(+), 72 deletions(-)
create mode 100644 docs/instrumentation.txt
create mode 100644 instrument/Makefile.objs
create mode 100644 instrument/api-control.c
create mode 100644 instrument/api-trace.c
create mode 100644 instrument/cmdline.c
create mode 100644 instrument/cmdline.h
create mode 100644 instrument/control-internal.h
create mode 100644 instrument/control.c
create mode 100644 instrument/control.h
create mode 100644 instrument/hmp.c
create mode 100644 instrument/hmp.h
create mode 100644 instrument/qapi-schema.json
create mode 100644 instrument/qemu-instr/control-internal.h
create mode 100644 instrument/qemu-instr/control.h
create mode 100644 instrument/qemu-instr/trace-internal.h
create mode 100644 instrument/qemu-instr/trace.h
create mode 100644 instrument/qemu-instr/visibility-internal.h
create mode 100644 instrument/qmp.c
create mode 100644 scripts/tracetool/backend/instr_dynamic.py
create mode 100644 scripts/tracetool/backend/instr_none.py
create mode 100644 scripts/tracetool/backend/instr_static.py
create mode 100644 scripts/tracetool/format/api_c.py
create mode 100644 scripts/tracetool/format/api_events_h.py
create mode 100644 scripts/tracetool/format/api_h.py
create mode 100644 scripts/tracetool/format/qemu_h.py
To: qemu-devel@nongnu.org
Cc: Stefan Hajnoczi <stefanha@gmail.com>
Cc: Blue Swirl <blauwirbel@gmail.com>
^ permalink raw reply [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 01/23] instrument: Add documentation
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
@ 2013-04-16 13:49 ` Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 02/23] trace: [simple] Do not include "trace/simple.h" in generated tracer headers Lluís Vilanova
` (22 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:49 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
docs/instrumentation.txt | 496 ++++++++++++++++++++++++++++++++++++++++++++++
docs/tracing.txt | 9 +
2 files changed, 505 insertions(+)
create mode 100644 docs/instrumentation.txt
diff --git a/docs/instrumentation.txt b/docs/instrumentation.txt
new file mode 100644
index 0000000..8b33d76
--- /dev/null
+++ b/docs/instrumentation.txt
@@ -0,0 +1,496 @@
+= Trace instrumentation =
+
+== Introduction ==
+
+This document describes how the events provided by the tracing infrastructure
+(described in the document "tracing.txt") can be extended with user-provided
+code.
+
+Instrumentation comes in two (three) flavours; dynamic and static (and none at
+all). Both provide means for you to associate code to specific tracing events
+that have the "instrument" property in the "trace-events" file.
+
+As opposed to using tracing backends that can dynamically load user-defined code
+into the tracing events (e.g., "dtrace"), trace instrumentation provides a
+well-defined API for the user-provided code to interact with QEMU.
+
+In the case of dynamic instrumentation, you can load and unload a shared object
+(a dynamic library) to establish your instrumentation callbacks. This mechanism
+provides a trade-off between performance and the simplicity of reusing the same
+QEMU binary for different instrumentation scenarios.
+
+In the case of static instrumentation, you must provide a static library that is
+compiled directly into QEMU. This mechanism can provide better performance, at
+the expense of having to recompile QEMU for each different instrumentation
+scenario.
+
+
+
+== Selecting the events to instrument ==
+
+You must declare which events to instrument before compiling QEMU.
+
+This can be done by adding the "instrument" property (and removing the "disable"
+property, if any) in the events listed in the "trace-events" file.
+
+In order to avoid modifying the QEMU sources, you can simply create a new
+trace-events file with your modifications:
+
+ cp /path/to/qemu-source/trace-events /tmp/trace-events
+ sed -i -e "s/qemu_vmalloc(/instrument qemu_vmalloc(/g" /tmp/trace-events
+
+Note: You must remove the "disable" property (if any) if you want to add the
+"instrument" property of an event, as these are mutually exclusive.
+
+
+== Pre-defined instrumentation callbacks ==
+
+If you are using dynamic auto-instrumentation (see 'QI_CTRL_INSTR_AUTO' below)
+or static instrumentation, your callbacks must follow a specific naming scheme:
+'qi_event_${event}'.
+
+Two other default callbacks are provided by QEMU:
+
+* 'qi_event_${event}_nop'
+
+ Does nothing.
+
+ This is the default callback for all instrumentable events when using dynamic
+ instrumentation.
+
+* 'qi_event_${event}_trace'
+
+ Call QEMU's tracing backend. That is, trace the event using whatever tracing
+ backend QEMU has been configured with.
+
+ See document "tracing.txt" to learn more about tracing events with QEMU (e.g.,
+ write events into a file or print them on the screen).
+
+All these callbacks are declared in the "qemu-instr/events.h" header.
+
+
+== Dynamic instrumentation ==
+
+Dynamic instrumentation is based on dynamically loadable libraries that can be
+loaded and unloaded from QEMU at any point in time. This also includes an API to
+dynamically set the per-event tracing instrumentation callback at any point in
+time.
+
+Being able to load and unload an instrumentation library provides a comfortable
+mechanism to test multiple instrumentation approaches without having to
+recompile or restart QEMU between instrumentation tests.
+
+Note: By default, events are set to use the 'qi_event_${event}_nop' callback.
+
+
+=== Example ===
+
+1. Select the events to instrument in file "trace-events" (see above).
+
+2. Build QEMU with dynamic trace intrumentation:
+
+ mkdir -p /tmp/qemu-build
+ cd /tmp/qemu-build
+ /path/to/qemu-source/configure \
+ --with-trace-events=/tmp/trace-events \
+ --with-trace-instrument=dynamic \
+ --enable-trace-backend=stderr \
+ --prefix=/tmp/qemu-install
+ make
+ make install
+
+3. Create the "Makefile" to build the instrumentation library:
+
+ mkdir -p /tmp/my-dinstrument
+
+ cat > /tmp/my-dinstrument/Makefile <<EOF
+ QEMU_PATH=/tmp/qemu-install/
+
+ CFLAGS += -O3
+ CFLAGS += -Werror -Wall
+ CFLAGS += -I$(QEMU_PATH)/include
+
+ all: libtrace-instrument.la
+
+ libtrace-instrument.la: instrument.lo
+ libtool --mode=link --tag=CC $(CC) -module -rpath /usr/local/lib -o $@ $^
+
+ %.lo: %.c
+ libtool --mode=compile --tag=CC $(CC) $(CFLAGS) -c $^
+
+ clean:
+ $(RM) -f *.o *.so *.lo
+ $(RM) -Rf .libs
+ EOF
+
+4. Create the necessary source code files to implement your event instrumentation:
+
+ cat > /tmp/my-dinstrument/instrument.c <<EOF
+ #include <stdio.h>
+ #include <assert.h>
+
+ /* get event declarations */
+ #include <qemu-instr/events.h>
+
+ /* enumerate events and manipulate their instrumentation callbacks */
+ #include <qemu-instr/control.h>
+
+ /* manipulate the dynamic tracing state of events */
+ #include <qemu-instr/trace.h>
+
+ /* define instrumentation callbacks during event execution:
+ * qi_event_${event}
+ */
+
+ /* called every time QEMU traces event 'qemu_vmalloc' */
+ void qi_event_qemu_vmalloc(size_t size, void *ptr)
+ {
+ fprintf(stderr, "qemu_vmalloc! [instrument]\n");
+
+ /* call the original tracing routine */
+ qi_event_qemu_vmalloc_trace(size, ptr);
+
+ /* disable instrumentation and tracing after 10 calls */
+ static int c = 0;
+ if (c++ > 10) {
+ QIEvent *ev = qi_ctrl_event_id(QI_EVENT_QEMU_VMALLOC);
+ qi_ctrl_event_set(ev, QI_CTRL_INSTR_NOP);
+ qi_trace_event_set_state_dynamic(ev, false);
+ }
+ }
+
+
+
+ /* mandatory initialization callback */
+ void qi_init(int argc, const char *argv)
+ {
+ int i;
+ fprintf(stderr, "init!\n");
+ fprintf(stderr, " argc :: %d\n", argc);
+ for (i = 0; i < argc; i++) {
+ fprintf(stderr, " -> %s\n", argv[i]);
+ }
+
+ /* iterate on all trace events */
+ QIEvent *ev = NULL;
+ while ((ev = qi_ctrl_event_pattern("*", ev)) != NULL) {
+
+ /* auto-instrument all events instrumentable at execution time */
+ if (qi_ctrl_event_is_available(ev)) {
+
+ printf("[exec] instrumenting '%s'\n",
+ qi_ctrl_event_get_name(ev));
+
+ /* auto-detect instrumentation routines */
+ bool instrumented = qi_ctrl_event_set(ev, QI_CTRL_INSTR_AUTO);
+ assert(instrumented);
+
+ /* activate tracing for that event
+ * (otherwise qi_event_${event}_trace does nothing when using
+ * the 'stderr' backend)
+ */
+ qi_trace_event_set_state_dynamic(ev, true);
+ }
+ }
+ }
+
+ /* mandatory finalization callback */
+ void qi_fini(void)
+ {
+ fprintf(stderr, "fini!\n");
+
+ /* ensure all tracing is disabled */
+ QIEvent *ev = NULL;
+ while ((ev = qi_ctrl_event_pattern("*", ev)) != NULL) {
+ qi_trace_event_set_state_dynamic(ev, false);
+ }
+
+ /* instrumentation callbacks are automatically reset by QEMU */
+ }
+ EOF
+
+5. Compile the instrumentation library:
+
+ make -C /tmp/my-dinstrument
+
+6. Start QEMU with the instrumentation library:
+
+ /tmp/qemu-install/bin/qemu-system-x86_64 \
+ -instr file=/tmp/my-dinstrument/.libs/libtrace-instrument.so
+
+
+Alternatively, you can explicitly set which events and with which callback you
+want to instrument them:
+
+ /* ... */
+ void qi_init(int argc, const char *argv)
+ {
+ int i;
+ fprintf(stderr, "init!\n");
+ fprintf(stderr, " argc :: %d\n", argc);
+ for (i = 0; i < argc; i++) {
+ fprintf(stderr, " -> %s\n", argv[i]);
+ }
+
+ QIEvent *ev;
+ bool instrumented;
+
+ /* NOTE: the callbacks can be pointers to arbitrary routines;
+ * there's no need to follow the 'qi_event_${event}' naming
+ * scheme if you're not using QI_CTRL_INSTR_AUTO.
+ */
+
+ ev = qi_ctrl_event_id(QI_EVENT_QEMU_VMALLOC);
+ assert(ev);
+ printf("[exec] instrumenting '%s'\n",
+ qi_ctrl_event_get_name(ev));
+ instrumented = qi_ctrl_event_set(ev, execute_qemu_vmalloc);
+ assert(instrumented);
+ qi_trace_event_set_state_dynamic(ev, true);
+ }
+ /* ... */
+
+
+
+== Static instrumentation ==
+
+Static instrumentation relies on you providing a directory that QEMU will
+compile on to produce a static library. The instrumentation library is compiled
+during the compilation of QEMU's target-dependant code, and the directory you
+provided will be present on the include path. This static library will then be
+linked into QEMU itself.
+
+This mechanism allows you to inline your own instrumentation code into the QEMU
+tracing routines. This requires the (partial) recompilation of QEMU whenever the
+instrumentation analysis code changes, and is thus intended for
+performance-critical event instrumentation analysis.
+
+For this reason, you can prototype your analysis using dynamic instrumentation
+before moving to static instrumentation.
+
+
+=== Example ===
+
+1. Select the events to instrument in file "trace-events" (see above).
+
+2. Create the "Makefile" to build the instrumentation library:
+
+ mkdir -p /tmp/my-sinstrument
+
+ cat > /tmp/my-sinstrument/Makefile <<EOF
+ include $(BUILD_DIR)/config-host.mak
+ include $(BUILD_DIR)/$(TARGET_DIR)../config-target.mak
+ include $(SRC_PATH)/rules.mak
+
+ vpath %.c /tmp/my-sinstrument
+
+ libtrace-instrument.a: CFLAGS += -I$(SRC_PATH)/instrument
+ libtrace-instrument.a: CFLAGS += -I$(BUILD_DIR)/instrument
+ libtrace-instrument.a: instrument.o
+
+ # Include automatically generated dependency files
+ -include $(wildcard *.d)
+ EOF
+
+3. Create the necessary source code files to implement the event instrumentation.
+
+ The same code on the dynamic instrumentation example can be used, eliminating
+ calls to 'qi_ctrl_event_set'.
+
+ See below for a description on how to reuse the same code to work with both
+ instrumentation types.
+
+4. Build QEMU with static trace intrumentation:
+
+ mkdir -p /tmp/qemu-build
+ cd /tmp/qemu-build
+ /path/to/qemu-source/configure \
+ --with-trace-events=/tmp/trace-events \
+ --with-trace-instrument=static \
+ --with-trace-instrument-path=/tmp/my-sinstrument \
+ --enable-trace-backend=stderr \
+ --prefix=/tmp/qemu-install
+ make
+ make install
+
+
+=== Performance optimizations ===
+
+You can create a few header files in the user-provided instrumentation path
+('--with-trace-instrument-path') to further optimize static instrumentation:
+
+* "events-pre.h"
+
+ Included before the code of the in-QEMU and tracing backend-specific header
+ ("trace.h").
+
+ This header can contain per-event defines to allow the user to provide an
+ inlined version of the instrumentation routine (see "events-post.h"):
+
+ #define QI_EVENT_${EVENT}_INLINE 1
+
+ Example:
+
+ #ifndef EVENTS_PRE_H
+ #define EVENTS_PRE_H
+
+ #define QI_EVENT_QEMU_VMALLOC_INLINE 1
+
+ #endif /* EVENTS_PRE_H */
+
+* "events-post.h"
+
+ Included after the code of the in-QEMU and tracing backend-specific header
+ ("trace.h").
+
+ This header can contain arbitrary user-provided code that will be inlined into
+ all QEMU files using tracing events. This includes inlined versions of the
+ instrumentation routines.
+
+ For example, inlining the fast-path of the instrumentation code:
+
+ #ifndef EVENTS_POST_H
+ #define EVENTS_POST_H
+
+ #include <qemu-instr/events.h>
+
+ // file residing in "/tmp/my-sinstrument/my-header.h",
+ // which declares 'my_trace_qemu_vmalloc_slow'
+ #include "my-header.h"
+
+
+ // requires "#define QI_EVENT_QEMU_VMALLOC_INLINE 1" in "events-pre.h"
+ static inline void qi_event_qemu_vmalloc(size_t size, void *ptr)
+ {
+ if (/* ... performance-critical condition ... */) {
+ /* ... performance-critical code ... */
+ } else {
+ my_trace_qemu_vmalloc_slow(size, ptr);
+ }
+ }
+
+ #endif /* EVENTS_POST_H */
+
+Note: All these headers are completely optional, and will only be used if they
+exist at compile time.
+
+
+
+== Loading and unloading instrumentation libraries ==
+
+QEMU starts with all instrumentation callbacks set to their default value, which
+corresponds to a call to 'qi_event_${event}_nop'.
+
+To load a dynamic instrumentation library, the user can either use the "-instr"
+command line argument, or the "instr-load" command available in the QEMU
+monitor, QAPI and QMP.
+
+Once loaded, QEMU will call the 'qi_init' routine in the instrumentation library.
+
+To unload a dynamic instrumentation library, the user can use the "instr-unload"
+command.
+
+When unloading, QEMU will call the 'qi_fini' routine in the instrumentation
+library, and immediately after restore all the instrumentation callbacks to
+their default value.
+
+In the case of static instrumentation, the commands "instr-load" and
+"instr-unload" are not available, and thus the instrumentation library is
+already loaded when QEMU starts, and is unloaded when QEMU exits.
+
+
+
+== Instrumentation API ==
+
+Both dynamic and static trace instrumentation libraries can interact with QEMU
+using the API provided in the headers found under the "qemu-instr" directory
+(installed alongside QEMU).
+
+
+=== Event enumeration ===
+
+Events can be obtained either by identifier or by name. Identifiers are values
+of the enumeration 'QIEventID' and follow the naming scheme 'QI_EVENT_${EVENT}'
+(e.g., 'QI_EVENT_QEMU_VMALLOC' for the "qemu_vmalloc" event).
+
+Identifiers, together with defines indicating if an event is enabled at
+compile-time ('QI_EVENT_${EVENT}_ENABLED') are located in the
+"qemu-instr/events-list.h" header.
+
+The interface to obtain and enumerate these events is located in the
+"qemu-instr/control.h" header.
+
+
+=== Event tracing ===
+
+You can interact with the state of QEMU's event tracing backend (see document
+"tracing.txt") through the API in the "qemu-instr/trace.h" header.
+
+
+=== Event instrumentation ===
+
+You can control the instrumentation callbacks of events through the API in the
+"qemu-instr/control.h" header.
+
+
+=== Instrumentation type discrimination ===
+
+The same source code for an instrumentation library can result in different code
+depending on the current instrumentation type (either dynamic or static):
+
+* "qemu-instr/config.h"
+
+ The define QI_TYPE_STATIC (QI_TYPE_DYNAMIC) will be available and set to 1 if
+ QEMU has been compiled with static (dynamic) instrumentation.
+
+* "qemu-instr/control.h"
+
+ Routine 'qi_ctrl_dynamic' can be used to discriminate if dynamic
+ instrumentation is available.
+
+ Similarly, routine 'qi_ctrl_event_is_available' indicates whether the given
+ event is available for instrumentation (both static and dynamic).
+
+With this, you can ensure the same code will work under both instrumentation
+types.
+
+Example initialization:
+
+ #if defined(QI_TYPE_DYNAMIC)
+ #include "events-post.h"
+ #endif
+
+ void qi_init(int argc, const char *argv)
+ {
+ int i;
+ fprintf(stderr, "init!\n");
+ fprintf(stderr, " argc :: %d\n", argc);
+ for (i = 0; i < argc; i++) {
+ fprintf(stderr, " -> %s\n", argv[i]);
+ }
+
+ QIEvent *ev = NULL;
+ while ((ev = qi_ctrl_event_pattern("*", ev)) != NULL) {
+
+ if (qi_ctrl_event_is_available(ev)) {
+
+ /* changing the callback will fail during static instrumentation */
+ if (qi_ctrl_dynamic()) {
+ bool instrumented = qi_ctrl_event_set(ev, QI_CTRL_INSTR_AUTO);
+ assert(instrumented);
+ }
+
+ qi_trace_event_set_state_dynamic(ev, true);
+ }
+ }
+ }
+
+Example "events-post.h":
+
+ #if defined(QI_TYPE_STATIC)
+ static inline
+ #endif
+ void qi_event_qemu_vmalloc(size_t size, void *ptr)
+ {
+ /* ... */
+ }
diff --git a/docs/tracing.txt b/docs/tracing.txt
index cf53c17..d33717b 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -255,3 +255,12 @@ guard such computations and avoid its compilation when the event is disabled:
You can check both if the event has been disabled and is dynamically enabled at
the same time using the 'trace_event_get_state' routine (see header
"trace/control.h" for more information).
+
+=== "instrument" ===
+
+When compiling QEMU with trace instrumentation enabled, the "instrument"
+property lets you provide your own implementation for that trace event. This
+implementation can override and/or wrap the backend-specific tracing code
+(regardless of the tracing backend).
+
+See the document "instrumentation.txt" for more information.
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 02/23] trace: [simple] Do not include "trace/simple.h" in generated tracer headers
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
2013-04-16 13:49 ` [Qemu-devel] [PATCH v2 01/23] instrument: Add documentation Lluís Vilanova
@ 2013-04-16 13:50 ` Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 03/23] trace: Let the user specify her own trace-events file Lluís Vilanova
` (21 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:50 UTC (permalink / raw)
To: qemu-devel
The header is not necessary, given that the simple backend does not define any
inlined tracing routines.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
scripts/tracetool/backend/simple.py | 5 +----
trace/simple.c | 2 ++
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py
index 37ef599..e754f0d 100644
--- a/scripts/tracetool/backend/simple.py
+++ b/scripts/tracetool/backend/simple.py
@@ -6,7 +6,7 @@ Simple built-in backend.
"""
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi"
@@ -93,9 +93,6 @@ def c(events):
def h(events):
- out('#include "trace/simple.h"',
- '')
-
for event in events:
out('void trace_%(name)s(%(args)s);',
name = event.name,
diff --git a/trace/simple.c b/trace/simple.c
index 1e3f691..8b59760 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -8,6 +8,8 @@
*
*/
+#include "trace/simple.h"
+
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 03/23] trace: Let the user specify her own trace-events file
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
2013-04-16 13:49 ` [Qemu-devel] [PATCH v2 01/23] instrument: Add documentation Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 02/23] trace: [simple] Do not include "trace/simple.h" in generated tracer headers Lluís Vilanova
@ 2013-04-16 13:50 ` Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 04/23] tracetool: Use method 'Event.api' to get the name of public routines Lluís Vilanova
` (20 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:50 UTC (permalink / raw)
To: qemu-devel
With this option the user can perform multiple builds of QEMU with different
tracing event properties.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
Makefile.target | 2 +-
configure | 19 +++++++++++++++++++
trace/Makefile.objs | 10 +++++-----
3 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/Makefile.target b/Makefile.target
index 2bd6d14..f382559 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -47,7 +47,7 @@ else
TARGET_TYPE=system
endif
-$(QEMU_PROG).stp: $(SRC_PATH)/trace-events
+$(QEMU_PROG).stp: $(TRACE_EVENTS)
$(call quiet-command,$(TRACETOOL) \
--format=stap \
--backend=$(TRACE_BACKEND) \
diff --git a/configure b/configure
index 73df181..a3bd336 100755
--- a/configure
+++ b/configure
@@ -221,6 +221,7 @@ blobs="yes"
pkgversion=""
pie=""
zero_malloc=""
+trace_events=`dirname $0`/trace-events
trace_backend="nop"
trace_file="trace"
spice=""
@@ -639,6 +640,8 @@ for opt do
;;
--target-list=*) target_list="$optarg"
;;
+ --with-trace-events=*) trace_events="$optarg"
+ ;;
--enable-trace-backend=*) trace_backend="$optarg"
;;
--with-trace-file=*) trace_file="$optarg"
@@ -1158,6 +1161,7 @@ echo " --enable-docs enable documentation build"
echo " --disable-docs disable documentation build"
echo " --disable-vhost-net disable vhost-net acceleration support"
echo " --enable-vhost-net enable vhost-net acceleration support"
+echo " --with-trace-events=PATH file with tracing events description (default: $trace_events)"
echo " --enable-trace-backend=B Set trace backend"
echo " Available backends:" $($python "$source_path"/scripts/tracetool.py --list-backends)
echo " --with-trace-file=NAME Full PATH,NAME of file to store traces"
@@ -3009,6 +3013,18 @@ if compile_prog "" "" ; then
fi
##########################################
+# check if trace-events file exists
+
+if test ! -f "$trace_events"; then
+ echo
+ echo "Error: the given trace-events file does not exist"
+ echo
+ exit 1
+else
+ trace_events=`readlink -f "$trace_events"`
+fi
+
+##########################################
# check if trace backend exists
$python "$source_path/scripts/tracetool.py" "--backend=$trace_backend" --check-backend > /dev/null 2> /dev/null
@@ -3418,6 +3434,7 @@ echo "sigev_thread_id $sigev_thread_id"
echo "uuid support $uuid"
echo "libcap-ng support $cap_ng"
echo "vhost-net support $vhost_net"
+echo "Trace events $trace_events"
echo "Trace backend $trace_backend"
echo "Trace output file $trace_file-<pid>"
echo "spice support $spice ($spice_protocol_version/$spice_server_version)"
@@ -3810,6 +3827,8 @@ bsd)
;;
esac
+echo "TRACE_EVENTS=$trace_events" >> $config_host_mak
+
# use default implementation for tracing backend-specific routines
trace_default=yes
echo "TRACE_BACKEND=$trace_backend" >> $config_host_mak
diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index a043072..bf0a965 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -4,7 +4,7 @@
# Auto-generated event descriptions
$(obj)/generated-events.h: $(obj)/generated-events.h-timestamp
-$(obj)/generated-events.h-timestamp: $(SRC_PATH)/trace-events
+$(obj)/generated-events.h-timestamp: $(TRACE_EVENTS)
$(call quiet-command,$(TRACETOOL) \
--format=events-h \
--backend=events \
@@ -12,7 +12,7 @@ $(obj)/generated-events.h-timestamp: $(SRC_PATH)/trace-events
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
$(obj)/generated-events.c: $(obj)/generated-events.c-timestamp $(BUILD_DIR)/config-host.mak
-$(obj)/generated-events.c-timestamp: $(SRC_PATH)/trace-events
+$(obj)/generated-events.c-timestamp: $(TRACE_EVENTS)
$(call quiet-command,$(TRACETOOL) \
--format=events-c \
--backend=events \
@@ -27,7 +27,7 @@ util-obj-y += generated-events.o
$(obj)/generated-tracers.h: $(obj)/generated-tracers.h-timestamp
@cmp -s $< $@ || cp $< $@
-$(obj)/generated-tracers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
+$(obj)/generated-tracers.h-timestamp: $(TRACE_EVENTS) $(BUILD_DIR)/config-host.mak
$(call quiet-command,$(TRACETOOL) \
--format=h \
--backend=$(TRACE_BACKEND) \
@@ -39,7 +39,7 @@ $(obj)/generated-tracers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/conf
ifneq ($(TRACE_BACKEND),dtrace)
$(obj)/generated-tracers.c: $(obj)/generated-tracers.c-timestamp
@cmp -s $< $@ || cp $< $@
-$(obj)/generated-tracers.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
+$(obj)/generated-tracers.c-timestamp: $(TRACE_EVENTS) $(BUILD_DIR)/config-host.mak
$(call quiet-command,$(TRACETOOL) \
--format=c \
--backend=$(TRACE_BACKEND) \
@@ -57,7 +57,7 @@ endif
# rule file. So we use '.dtrace' instead
ifeq ($(TRACE_BACKEND),dtrace)
$(obj)/generated-tracers.dtrace: $(obj)/generated-tracers.dtrace-timestamp
-$(obj)/generated-tracers.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
+$(obj)/generated-tracers.dtrace-timestamp: $(TRACE_EVENTS) $(BUILD_DIR)/config-host.mak
$(call quiet-command,$(TRACETOOL) \
--format=d \
--backend=$(TRACE_BACKEND) \
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 04/23] tracetool: Use method 'Event.api' to get the name of public routines
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (2 preceding siblings ...)
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 03/23] trace: Let the user specify her own trace-events file Lluís Vilanova
@ 2013-04-16 13:50 ` Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 05/23] trace: Minimize inclusions of "qemu-common.h" to avoid inclusion loops Lluís Vilanova
` (19 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:50 UTC (permalink / raw)
To: qemu-devel
This ensures proper naming across tracing backends, even when someone overrides
the value without backends knowing it.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
scripts/tracetool/__init__.py | 10 +++++++++-
scripts/tracetool/backend/dtrace.py | 6 +++---
scripts/tracetool/backend/simple.py | 8 ++++----
scripts/tracetool/backend/stderr.py | 5 +++--
scripts/tracetool/backend/ust.py | 8 +++++---
scripts/tracetool/format/h.py | 6 +++---
6 files changed, 27 insertions(+), 16 deletions(-)
diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py
index 175df08..7e4d651 100644
--- a/scripts/tracetool/__init__.py
+++ b/scripts/tracetool/__init__.py
@@ -6,7 +6,7 @@ Machinery for generating tracing-related intermediate files.
"""
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi"
@@ -173,6 +173,14 @@ class Event(object):
self.args,
self.fmt)
+
+ QEMU_TRACE = "trace_%(name)s"
+
+ def api(self, fmt = None):
+ if fmt is None:
+ fmt = Event.QEMU_TRACE
+ return fmt % { "name" : self.name }
+
def _read_events(fobj):
res = []
for line in fobj:
diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py
index e31bc79..3a34600 100644
--- a/scripts/tracetool/backend/dtrace.py
+++ b/scripts/tracetool/backend/dtrace.py
@@ -6,7 +6,7 @@ DTrace/SystemTAP backend.
"""
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi"
@@ -44,10 +44,10 @@ def h(events):
'')
for e in events:
- out('static inline void trace_%(name)s(%(args)s) {',
+ out('static inline void %(api)s(%(args)s) {',
' QEMU_%(uppername)s(%(argnames)s);',
'}',
- name = e.name,
+ api = e.api(),
args = e.args,
uppername = e.name.upper(),
argnames = ", ".join(e.args.names()),
diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py
index e754f0d..b7337af 100644
--- a/scripts/tracetool/backend/simple.py
+++ b/scripts/tracetool/backend/simple.py
@@ -34,10 +34,10 @@ def c(events):
)
for num, event in enumerate(events):
- out('void trace_%(name)s(%(args)s)',
+ out('void %(api)s(%(args)s)',
'{',
' TraceBufferRecord rec;',
- name = event.name,
+ api = event.api(),
args = event.args,
)
sizes = []
@@ -94,7 +94,7 @@ def c(events):
def h(events):
for event in events:
- out('void trace_%(name)s(%(args)s);',
- name = event.name,
+ out('void %(api)s(%(args)s);',
+ api = event.api(),
args = event.args,
)
diff --git a/scripts/tracetool/backend/stderr.py b/scripts/tracetool/backend/stderr.py
index 6f93dbd..d9b7121 100644
--- a/scripts/tracetool/backend/stderr.py
+++ b/scripts/tracetool/backend/stderr.py
@@ -6,7 +6,7 @@ Stderr built-in backend.
"""
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi"
@@ -33,13 +33,14 @@ def h(events):
if len(e.args) > 0:
argnames = ", " + argnames
- out('static inline void trace_%(name)s(%(args)s)',
+ out('static inline void %(api)s(%(args)s)',
'{',
' bool _state = trace_event_get_state(%(event_id)s);',
' if (_state) {',
' fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s);',
' }',
'}',
+ api = e.api(),
name = e.name,
args = e.args,
event_id = "TRACE_" + e.name.upper(),
diff --git a/scripts/tracetool/backend/ust.py b/scripts/tracetool/backend/ust.py
index ea36995..2f4cb23 100644
--- a/scripts/tracetool/backend/ust.py
+++ b/scripts/tracetool/backend/ust.py
@@ -6,7 +6,7 @@ LTTng User Space Tracing backend.
"""
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi"
@@ -78,7 +78,8 @@ def h(events):
for e in events:
if len(e.args) > 0:
out('DECLARE_TRACE(ust_%(name)s, TP_PROTO(%(args)s), TP_ARGS(%(argnames)s));',
- '#define trace_%(name)s trace_ust_%(name)s',
+ '#define %(api)s trace_ust_%(name)s',
+ api = e.api(),
name = e.name,
args = e.args,
argnames = ", ".join(e.args.names()),
@@ -86,7 +87,8 @@ def h(events):
else:
out('_DECLARE_TRACEPOINT_NOARGS(ust_%(name)s);',
- '#define trace_%(name)s trace_ust_%(name)s',
+ '#define %(api)s trace_ust_%(name)s',
+ api = e.api(),
name = e.name,
)
diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py
index 93132fc..ed7c8a5 100644
--- a/scripts/tracetool/format/h.py
+++ b/scripts/tracetool/format/h.py
@@ -6,7 +6,7 @@ Generate .h file.
"""
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi"
@@ -30,9 +30,9 @@ def end(events):
def nop(events):
for e in events:
out('',
- 'static inline void trace_%(name)s(%(args)s)',
+ 'static inline void %(api)s(%(args)s)',
'{',
'}',
- name = e.name,
+ api = e.api(),
args = e.args,
)
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 05/23] trace: Minimize inclusions of "qemu-common.h" to avoid inclusion loops
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (3 preceding siblings ...)
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 04/23] tracetool: Use method 'Event.api' to get the name of public routines Lluís Vilanova
@ 2013-04-16 13:50 ` Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 06/23] instrument: [none] Add null instrumentation Lluís Vilanova
` (18 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:50 UTC (permalink / raw)
To: qemu-devel
This problem arises in the following patches.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
hw/virtio/virtio.c | 1 +
monitor.c | 4 +++-
scripts/tracetool/format/h.py | 9 ++++++++-
trace/control-internal.h | 4 +++-
trace/control.c | 4 +++-
trace/control.h | 9 +++++++--
trace/default.c | 4 +++-
trace/simple.c | 4 +++-
trace/simple.h | 1 +
trace/stderr.c | 4 +++-
10 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 1c2282c..a3dda2c 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -14,6 +14,7 @@
#include <inttypes.h>
#include "trace.h"
+#include "qemu-common.h"
#include "qemu/error-report.h"
#include "hw/virtio/virtio.h"
#include "qemu/atomic.h"
diff --git a/monitor.c b/monitor.c
index c897e80..a8f49d9 100644
--- a/monitor.c
+++ b/monitor.c
@@ -22,6 +22,9 @@
* THE SOFTWARE.
*/
#include <dirent.h>
+#define TRACE__CONTROL__USE__TRACE_PRINT_EVENTS
+#include "trace/control.h"
+#undef TRACE__CONTROL__USE__TRACE_PRINT_EVENTS
#include "hw/hw.h"
#include "monitor/qdev.h"
#include "hw/usb.h"
@@ -59,7 +62,6 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "trace.h"
-#include "trace/control.h"
#ifdef CONFIG_TRACE_SIMPLE
#include "trace/simple.h"
#endif
diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py
index ed7c8a5..c98aebd 100644
--- a/scripts/tracetool/format/h.py
+++ b/scripts/tracetool/format/h.py
@@ -22,7 +22,14 @@ def begin(events):
'#ifndef TRACE__GENERATED_TRACERS_H',
'#define TRACE__GENERATED_TRACERS_H',
'',
- '#include "qemu-common.h"')
+ '/* Do not directly include "qemu-common.h" to avoid circular dependencies */',
+ '#include <stdint.h>',
+ '#include <inttypes.h>',
+ '#include <stdbool.h>',
+ '#include <stddef.h>',
+ '#include <unistd.h>',
+ '',
+ )
def end(events):
out('#endif /* TRACE__GENERATED_TRACERS_H */')
diff --git a/trace/control-internal.h b/trace/control-internal.h
index cce2da4..a15a994 100644
--- a/trace/control-internal.h
+++ b/trace/control-internal.h
@@ -1,7 +1,7 @@
/*
* Interface for configuring and controlling the state of tracing events.
*
- * Copyright (C) 2011-2012 Lluís Vilanova <vilanova@ac.upc.edu>
+ * Copyright (C) 2011-2013 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.
@@ -11,6 +11,8 @@
#define TRACE__CONTROL_INTERNAL_H
#include <string.h>
+#include <assert.h>
+#include <stddef.h>
extern TraceEvent trace_events[];
diff --git a/trace/control.c b/trace/control.c
index 49f61e1..dd7b260 100644
--- a/trace/control.c
+++ b/trace/control.c
@@ -1,7 +1,7 @@
/*
* Interface for configuring and controlling the state of tracing events.
*
- * Copyright (C) 2011-2012 Lluís Vilanova <vilanova@ac.upc.edu>
+ * Copyright (C) 2011-2013 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.
@@ -9,6 +9,8 @@
#include "trace/control.h"
+#include "qemu-common.h"
+
TraceEvent *trace_event_name(const char *name)
{
diff --git a/trace/control.h b/trace/control.h
index cde8260..29ff9c1 100644
--- a/trace/control.h
+++ b/trace/control.h
@@ -1,7 +1,7 @@
/*
* Interface for configuring and controlling the state of tracing events.
*
- * Copyright (C) 2011-2012 Lluís Vilanova <vilanova@ac.upc.edu>
+ * Copyright (C) 2011-2013 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.
@@ -10,7 +10,6 @@
#ifndef TRACE__CONTROL_H
#define TRACE__CONTROL_H
-#include "qemu-common.h"
#include "trace/generated-events.h"
@@ -155,6 +154,10 @@ void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state);
+#if defined(TRACE__CONTROL__USE__TRACE_PRINT_EVENTS)
+/* Minimize inclusions of "qemu-common.h" to avoid circular dependencies */
+#include "qemu-common.h"
+
/**
* trace_print_events:
*
@@ -164,6 +167,8 @@ void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state);
*/
void trace_print_events(FILE *stream, fprintf_function stream_printf);
+#endif /* defined(TRACE__CONTROL__USE__TRACE_PRINT_EVENTS) */
+
/**
* trace_backend_init:
* @events: Name of file with events to be enabled at startup; may be NULL.
diff --git a/trace/default.c b/trace/default.c
index 6e07a47..4dbaf11 100644
--- a/trace/default.c
+++ b/trace/default.c
@@ -1,13 +1,15 @@
/*
* Default implementation for backend initialization from commandline.
*
- * Copyright (C) 2011-2012 Lluís Vilanova <vilanova@ac.upc.edu>
+ * Copyright (C) 2011-2013 Lluís Vilanova <vilanova@ac.upc.edu>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*/
+#define TRACE__CONTROL__USE__TRACE_PRINT_EVENTS
#include "trace/control.h"
+#undef TRACE__CONTROL__USE__TRACE_PRINT_EVENTS
void trace_print_events(FILE *stream, fprintf_function stream_printf)
diff --git a/trace/simple.c b/trace/simple.c
index 8b59760..cb4361f 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -19,8 +19,10 @@
#include <pthread.h>
#endif
#include "qemu/timer.h"
-#include "trace.h"
+#define TRACE__CONTROL__USE__TRACE_PRINT_EVENTS
#include "trace/control.h"
+#undef TRACE__CONTROL__USE__TRACE_PRINT_EVENTS
+#include "trace.h"
/** Trace file header event ID */
#define HEADER_EVENT_ID (~(uint64_t)0) /* avoids conflicting with TraceEventIDs */
diff --git a/trace/simple.h b/trace/simple.h
index 5260d9a..1541ea0 100644
--- a/trace/simple.h
+++ b/trace/simple.h
@@ -16,6 +16,7 @@
#include <stdio.h>
#include "trace/generated-events.h"
+#include "qemu-common.h"
void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf);
diff --git a/trace/stderr.c b/trace/stderr.c
index e212efd..3a6f4bd 100644
--- a/trace/stderr.c
+++ b/trace/stderr.c
@@ -1,5 +1,7 @@
-#include "trace.h"
+#define TRACE__CONTROL__USE__TRACE_PRINT_EVENTS
#include "trace/control.h"
+#undef TRACE__CONTROL__USE__TRACE_PRINT_EVENTS
+#include "trace.h"
void trace_print_events(FILE *stream, fprintf_function stream_printf)
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 06/23] instrument: [none] Add null instrumentation
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (4 preceding siblings ...)
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 05/23] trace: Minimize inclusions of "qemu-common.h" to avoid inclusion loops Lluís Vilanova
@ 2013-04-16 13:50 ` Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 07/23] system: [linux] Use absolute include path for linux-headers Lluís Vilanova
` (17 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:50 UTC (permalink / raw)
To: qemu-devel
Splits the QEMU-side tracing interface into different layers (in order of nested
invocation):
* trace_*
The interface used by QEMU code to signal traceable/instrumentable events
(now generated according to the selected instrumentation type).
* qi_event_*
The interface provided by the user's instrumentation code (for which QEMU
provides default implementations depending on the instrumentation type).
* qi_event_*_trace / qi_event_*_nop
The interface provided by QEMU to the user's instrumentation code to invoke
the tracing backend. The nop variant simply does nothing.
* trace_*_backend
The interface provided by the tracing backend in QEMU. Originally exposed as
'trace_*' routines.
The 'none' instrumentation type (this one) skips through the qi_* layers and
directly calls 'trace_*_backend' from the 'trace_*' routines (providing the
original tracing behaviour).
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
.gitignore | 2 +
Makefile | 3 +
configure | 31 ++++++++++++++
include/trace.h | 2 -
instrument/Makefile.objs | 24 +++++++++++
scripts/tracetool/__init__.py | 9 +++-
scripts/tracetool/backend/instr_none.py | 41 +++++++++++++++++++
scripts/tracetool/format/api_h.py | 39 ++++++++++++++++++
scripts/tracetool/format/qemu_h.py | 68 +++++++++++++++++++++++++++++++
9 files changed, 216 insertions(+), 3 deletions(-)
create mode 100644 instrument/Makefile.objs
create mode 100644 scripts/tracetool/backend/instr_none.py
create mode 100644 scripts/tracetool/format/api_h.py
create mode 100644 scripts/tracetool/format/qemu_h.py
diff --git a/.gitignore b/.gitignore
index 487813a..2c9695c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,8 @@ trace/generated-tracers.dtrace
trace/generated-events.h
trace/generated-events.c
libcacard/trace/generated-tracers.c
+instrument/generated-tracers.h
+instrument/qemu-instr/events.h
*-timestamp
*-softmmu
*-darwin-user
diff --git a/Makefile b/Makefile
index 0b6e6a1..028ef83 100644
--- a/Makefile
+++ b/Makefile
@@ -35,6 +35,9 @@ GENERATED_HEADERS = config-host.h qemu-options.def
GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
+GENERATED_HEADERS += instrument/generated-tracers.h
+GENERATED_HEADERS += instrument/qemu-instr/events.h
+
GENERATED_HEADERS += trace/generated-events.h
GENERATED_SOURCES += trace/generated-events.c
diff --git a/configure b/configure
index a3bd336..53b8bed 100755
--- a/configure
+++ b/configure
@@ -224,6 +224,7 @@ zero_malloc=""
trace_events=`dirname $0`/trace-events
trace_backend="nop"
trace_file="trace"
+trace_instrument="none"
spice=""
rbd=""
smartcard_nss=""
@@ -646,6 +647,8 @@ for opt do
;;
--with-trace-file=*) trace_file="$optarg"
;;
+ --with-trace-instrument=*) trace_instrument="$optarg"
+ ;;
--enable-gprof) gprof="yes"
;;
--enable-gcov) gcov="yes"
@@ -1166,6 +1169,8 @@ echo " --enable-trace-backend=B Set trace backend"
echo " Available backends:" $($python "$source_path"/scripts/tracetool.py --list-backends)
echo " --with-trace-file=NAME Full PATH,NAME of file to store traces"
echo " Default:trace-<pid>"
+echo " --with-trace-instrument=TYPE"
+echo " Trace instrumentation type (none; default: $trace_instrument)"
echo " --disable-spice disable spice"
echo " --enable-spice enable spice"
echo " --enable-rbd enable building the rados block device (rbd)"
@@ -3062,6 +3067,15 @@ if test "$trace_backend" = "dtrace"; then
fi
##########################################
+# Check instrumentation type
+case "$trace_instrument" in
+none) ;;
+*) echo "Error: invalid trace instrumentation type: $trace_instrument"
+ exit 1
+ ;;
+esac
+
+##########################################
# __sync_fetch_and_and requires at least -march=i486. Many toolchains
# use i686 as default anyway, but for those that don't, an explicit
# specification is necessary
@@ -3437,6 +3451,7 @@ echo "vhost-net support $vhost_net"
echo "Trace events $trace_events"
echo "Trace backend $trace_backend"
echo "Trace output file $trace_file-<pid>"
+echo "Trace instrument $trace_instrument"
echo "spice support $spice ($spice_protocol_version/$spice_server_version)"
echo "rbd support $rbd"
echo "xfsctl support $xfs"
@@ -3859,6 +3874,22 @@ if test "$trace_default" = "yes"; then
echo "CONFIG_TRACE_DEFAULT=y" >> $config_host_mak
fi
+##########################################
+# trace instrumentation
+config_qi=instrument/qemu-instr/config.h
+mkdir -p `dirname $config_qi`
+echo "/* Automatically generated by configure - do not modify */" > $config_qi
+
+echo "TRACE_INSTRUMENT_BACKEND=instr-$trace_instrument" >> $config_host_mak
+
+if test "$trace_instrument" = "none"; then
+ echo "#define QI_TYPE_NONE 1" >> $config_qi
+ echo "CONFIG_TRACE_INSTRUMENT_NONE=y" >> $config_host_mak
+else
+ echo "CONFIG_TRACE_INSTRUMENT=y" >> $config_host_mak
+fi
+##########################################
+
echo "TOOLS=$tools" >> $config_host_mak
echo "ROMS=$roms" >> $config_host_mak
echo "MAKE=$make" >> $config_host_mak
diff --git a/include/trace.h b/include/trace.h
index c15f498..5cd06c7 100644
--- a/include/trace.h
+++ b/include/trace.h
@@ -1,6 +1,6 @@
#ifndef TRACE_H
#define TRACE_H
-#include "trace/generated-tracers.h"
+#include "instrument/generated-tracers.h"
#endif /* TRACE_H */
diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs
new file mode 100644
index 0000000..9c5d5dc
--- /dev/null
+++ b/instrument/Makefile.objs
@@ -0,0 +1,24 @@
+# -*- mode: makefile -*-
+
+######################################################################
+# QEMU trace->instrument interface
+
+$(obj)/generated-tracers.h: $(obj)/generated-tracers.h-timestamp
+$(obj)/generated-tracers.h-timestamp: $(TRACE_EVENTS) $(BUILD_DIR)/config-host.mak
+ $(call quiet-command,$(TRACETOOL) \
+ --format=qemu-h \
+ --backend=$(TRACE_INSTRUMENT_BACKEND) \
+ < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+
+
+######################################################################
+# User interface
+
+$(obj)/qemu-instr/events.h: $(obj)/qemu-instr/events.h-timestamp
+$(obj)/qemu-instr/events.h-timestamp: $(TRACE_EVENTS) $(BUILD_DIR)/config-host.mak
+ $(call quiet-command,$(TRACETOOL) \
+ --format=api-h \
+ --backend=$(TRACE_INSTRUMENT_BACKEND) \
+ < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py
index 7e4d651..f849e39 100644
--- a/scripts/tracetool/__init__.py
+++ b/scripts/tracetool/__init__.py
@@ -122,7 +122,7 @@ class Event(object):
_CRE = re.compile("((?P<props>.*)\s+)?(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?")
- _VALID_PROPS = set(["disable"])
+ _VALID_PROPS = set(["disable", "instrument"])
def __init__(self, name, props, fmt, args):
"""
@@ -146,6 +146,9 @@ class Event(object):
if len(unknown_props) > 0:
raise ValueError("Unknown properties: %s" % ", ".join(unknown_props))
+ if "instrument" in self.properties and "disable" in self.properties:
+ raise ValueError("Cannot instrument a disabled event: %s" % self.name)
+
@staticmethod
def build(line_str):
"""Build an Event instance from a string.
@@ -175,10 +178,12 @@ class Event(object):
QEMU_TRACE = "trace_%(name)s"
+ QEMU_TRACE_BACKEND = "trace_%(name)s_backend"
+ QI_TRACE_INSTRUMENT = "qi_event_%(name)s"
def api(self, fmt = None):
if fmt is None:
- fmt = Event.QEMU_TRACE
+ fmt = Event.QEMU_TRACE_BACKEND
return fmt % { "name" : self.name }
def _read_events(fobj):
diff --git a/scripts/tracetool/backend/instr_none.py b/scripts/tracetool/backend/instr_none.py
new file mode 100644
index 0000000..a1327c0
--- /dev/null
+++ b/scripts/tracetool/backend/instr_none.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+No-instrumentation proxy.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@linux.vnet.ibm.com"
+
+
+from tracetool import out
+import tracetool.format.qemu_h
+
+
+def qemu_h(events):
+ out('#include "instrument/qemu-instr/events.h"',
+ '',
+ )
+ tracetool.format.qemu_h.process_common(events)
+
+
+def api_h(events):
+ for e in events:
+ if "instrument" not in e.properties:
+ continue
+
+ out('static inline void %(qi)s(%(args)s)',
+ '{',
+ ' %(qemu_backend)s(%(argnames)s);',
+ '}',
+ '',
+ qi = e.api(e.QI_TRACE_INSTRUMENT),
+ args = e.args,
+ qemu_backend = e.api(e.QEMU_TRACE_BACKEND),
+ argnames = ", ".join(e.args.names()),
+ )
diff --git a/scripts/tracetool/format/api_h.py b/scripts/tracetool/format/api_h.py
new file mode 100644
index 0000000..70d8e9f
--- /dev/null
+++ b/scripts/tracetool/format/api_h.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .h for trace instrumentation clients.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@linux.vnet.ibm.com"
+
+
+from tracetool import out
+
+
+def begin(events):
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#ifndef QI__EVENTS_H',
+ '#define QI__EVENTS_H',
+ '',
+ '#ifdef __cplusplus',
+ 'extern "C" {',
+ '#endif',
+ '',
+ '#include <stdint.h>',
+ '',
+ )
+
+def end(events):
+ out('#ifdef __cplusplus',
+ '}',
+ '#endif',
+ '',
+ '#endif /* QI__EVENTS_H */',
+ )
diff --git a/scripts/tracetool/format/qemu_h.py b/scripts/tracetool/format/qemu_h.py
new file mode 100644
index 0000000..51bd02a
--- /dev/null
+++ b/scripts/tracetool/format/qemu_h.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .h for trace instrumentation proxy.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@linux.vnet.ibm.com"
+
+
+from tracetool import out
+
+
+def begin(events):
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#ifndef INSTRUMENT__GENERATED_TRACERS_H',
+ '#define INSTRUMENT__GENERATED_TRACERS_H',
+ '',
+ '#include "trace/generated-tracers.h"',
+ '',
+ )
+
+def end(events):
+ out('#include "trace/generated-events.h"',
+ '',
+ '#endif /* INSTRUMENT__GENERATED_TRACERS_H */',
+ )
+
+def nop(events):
+ for e in events:
+ out('static inline void %(qemu)s(%(args)s)',
+ '{',
+ ' %(qemu_backend)s(%(argnames)s);',
+ '}',
+ '',
+ qemu = e.api(e.QEMU_TRACE),
+ args = e.args,
+ qemu_backend = e.api(e.QEMU_TRACE_BACKEND),
+ argnames = ", ".join(e.args.names()),
+ )
+
+def process_common(events):
+ for e in events:
+ if "instrument" not in e.properties:
+ nop([e])
+ continue
+
+ out('static inline void %(qemu)s(%(args)s)',
+ '{',
+ '#if defined(QEMU_TOOLS)',
+ ' %(backend)s(%(argnames)s);',
+ '#else',
+ ' %(qi)s(%(argnames)s);',
+ '#endif',
+ '}',
+ '',
+ qemu = e.api(e.QEMU_TRACE),
+ args = e.args,
+ qi = e.api(e.QI_TRACE_INSTRUMENT),
+ backend = e.api(e.QEMU_TRACE_BACKEND),
+ argnames = ", ".join(e.args.names()),
+ )
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 07/23] system: [linux] Use absolute include path for linux-headers
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (5 preceding siblings ...)
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 06/23] instrument: [none] Add null instrumentation Lluís Vilanova
@ 2013-04-16 13:50 ` Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 08/23] instrument: [static] Call statically linked user-provided routines Lluís Vilanova
` (16 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:50 UTC (permalink / raw)
To: qemu-devel
Lets the include directive work regardless of the current directory.
This is needed for code compiled in directories deeper than one level from the
build root.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
Makefile.target | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.target b/Makefile.target
index f382559..2f9675a 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -7,7 +7,7 @@ include $(SRC_PATH)/rules.mak
$(call set-vpath, $(SRC_PATH))
ifdef CONFIG_LINUX
-QEMU_CFLAGS += -I../linux-headers
+QEMU_CFLAGS += -I$(BUILD_DIR)/linux-headers
endif
QEMU_CFLAGS += -I.. -I$(SRC_PATH)/target-$(TARGET_BASE_ARCH) -DNEED_CPU_H
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 08/23] instrument: [static] Call statically linked user-provided routines
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (6 preceding siblings ...)
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 07/23] system: [linux] Use absolute include path for linux-headers Lluís Vilanova
@ 2013-04-16 13:50 ` Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 09/23] build: Add variable 'tools-obj-y' for tool-only files Lluís Vilanova
` (15 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:50 UTC (permalink / raw)
To: qemu-devel
Compiles a user-provided static library during QEMU compilation.
This library must provide the implementation of the 'qi_event_*' routines.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
Makefile.target | 2 +
configure | 42 +++++++++++++++-
instrument/Makefile.objs | 27 ++++++++++
scripts/tracetool.py | 14 ++++-
scripts/tracetool/__init__.py | 10 +++-
scripts/tracetool/backend/instr_static.py | 76 +++++++++++++++++++++++++++++
6 files changed, 165 insertions(+), 6 deletions(-)
create mode 100644 scripts/tracetool/backend/instr_static.py
diff --git a/Makefile.target b/Makefile.target
index 2f9675a..114fc39 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -149,6 +149,8 @@ include $(SRC_PATH)/Makefile.objs
all-obj-y = $(obj-y)
all-obj-y += $(addprefix ../, $(common-obj-y))
+all-obj-y += $(LIBTRACE_INSTRUMENT)
+
ifdef QEMU_PROGW
# The linker builds a windows executable. Make also a console executable.
$(QEMU_PROGW): $(all-obj-y) ../libqemuutil.a ../libqemustub.a
diff --git a/configure b/configure
index 53b8bed..94b9491 100755
--- a/configure
+++ b/configure
@@ -225,6 +225,7 @@ trace_events=`dirname $0`/trace-events
trace_backend="nop"
trace_file="trace"
trace_instrument="none"
+trace_instrument_path=""
spice=""
rbd=""
smartcard_nss=""
@@ -649,6 +650,8 @@ for opt do
;;
--with-trace-instrument=*) trace_instrument="$optarg"
;;
+ --with-trace-instrument-path=*) trace_instrument_path="$optarg"
+ ;;
--enable-gprof) gprof="yes"
;;
--enable-gcov) gcov="yes"
@@ -1170,7 +1173,9 @@ echo " Available backends:" $($python "$source_path"/s
echo " --with-trace-file=NAME Full PATH,NAME of file to store traces"
echo " Default:trace-<pid>"
echo " --with-trace-instrument=TYPE"
-echo " Trace instrumentation type (none; default: $trace_instrument)"
+echo " Trace instrumentation type (none static; default: $trace_instrument)"
+echo " --with-trace-instrument-path=PATH"
+echo " Directory to build user-provided static trace event instrumentation library"
echo " --disable-spice disable spice"
echo " --enable-spice enable spice"
echo " --enable-rbd enable building the rados block device (rbd)"
@@ -3069,13 +3074,32 @@ fi
##########################################
# Check instrumentation type
case "$trace_instrument" in
-none) ;;
+none|static) ;;
*) echo "Error: invalid trace instrumentation type: $trace_instrument"
exit 1
;;
esac
##########################################
+# check for a valid directory for static trace instrumentation
+if test "$trace_instrument" = "static" -a -z "$trace_instrument_path"; then
+ echo "Error: must provide '--with-trace-instrument-path' when using static trace instrumentation"
+ exit 1
+fi
+if test "$trace_instrument" != "static" -a -n "$trace_instrument_path"; then
+ echo "Error: cannot provide '--with-trace-instrument-path' when not using static trace instrumentation"
+ exit 1
+fi
+if test "$trace_instrument" = "static" -a ! -f "$trace_instrument_path/Makefile"; then
+ echo
+ echo "Error: cannot make into '$trace_instrument_path'"
+ echo "Please choose a directory where I can run 'make'"
+ echo
+ exit 1
+fi
+trace_instrument_path=`readlink -f "$trace_instrument_path"`
+
+##########################################
# __sync_fetch_and_and requires at least -march=i486. Many toolchains
# use i686 as default anyway, but for those that don't, an explicit
# specification is necessary
@@ -3452,6 +3476,9 @@ echo "Trace events $trace_events"
echo "Trace backend $trace_backend"
echo "Trace output file $trace_file-<pid>"
echo "Trace instrument $trace_instrument"
+if test -n "$trace_instrument_path"; then
+echo "Static instrument $trace_instrument_path"
+fi
echo "spice support $spice ($spice_protocol_version/$spice_server_version)"
echo "rbd support $rbd"
echo "xfsctl support $xfs"
@@ -3888,6 +3915,13 @@ if test "$trace_instrument" = "none"; then
else
echo "CONFIG_TRACE_INSTRUMENT=y" >> $config_host_mak
fi
+if test "$trace_instrument" = "static"; then
+ echo "#define QI_TYPE_STATIC 1" >> $config_qi
+ echo "CONFIG_TRACE_INSTRUMENT_STATIC=y" >> $config_host_mak
+ echo "TRACE_INSTRUMENT_PATH=\"$trace_instrument_path\"" >> $config_host_mak
+ echo "TRACETOOL_INSTR_STATIC=--instr-static-path \"\$(TRACE_INSTRUMENT_PATH)\"" >> $config_host_mak
+ QEMU_CFLAGS="-I\"$trace_instrument_path\" $QEMU_CFLAGS"
+fi
##########################################
echo "TOOLS=$tools" >> $config_host_mak
@@ -4150,6 +4184,10 @@ if [ "$TARGET_BASE_ARCH" = "" ]; then
fi
symlink "$source_path/Makefile.target" "$target_dir/Makefile"
+if test -n "$trace_instrument_path"; then
+ mkdir -p $target_dir/libtrace-instrument
+ symlink $trace_instrument_path/Makefile $target_dir/libtrace-instrument/Makefile
+fi
upper() {
echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]'
diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs
index 9c5d5dc..4102b59 100644
--- a/instrument/Makefile.objs
+++ b/instrument/Makefile.objs
@@ -8,9 +8,15 @@ $(obj)/generated-tracers.h-timestamp: $(TRACE_EVENTS) $(BUILD_DIR)/config-host.m
$(call quiet-command,$(TRACETOOL) \
--format=qemu-h \
--backend=$(TRACE_INSTRUMENT_BACKEND) \
+ $(TRACETOOL_INSTR_STATIC) \
< $< > $@," GEN $(patsubst %-timestamp,%,$@)")
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+ifdef CONFIG_TRACE_INSTRUMENT_STATIC
+# Rebuild to check for user headers
+.PHONY: $(obj)/generated-tracers.h-timestamp
+endif
+
######################################################################
# User interface
@@ -20,5 +26,26 @@ $(obj)/qemu-instr/events.h-timestamp: $(TRACE_EVENTS) $(BUILD_DIR)/config-host.m
$(call quiet-command,$(TRACETOOL) \
--format=api-h \
--backend=$(TRACE_INSTRUMENT_BACKEND) \
+ $(TRACETOOL_INSTR_STATIC) \
< $< > $@," GEN $(patsubst %-timestamp,%,$@)")
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+
+
+######################################################################
+# User code (static instrumentation)
+
+ifdef CONFIG_TRACE_INSTRUMENT_STATIC
+LIBTRACE_INSTRUMENT = libtrace-instrument/libtrace-instrument.a
+
+.PHONY: force
+force:
+
+_libinstrument_cflags = $(subst libtrace-instrument,.,$(subst libtrace-instrument/,.,$(1)))
+$(LIBTRACE_INSTRUMENT): QEMU_CFLAGS += -I$(BUILD_DIR)/
+$(LIBTRACE_INSTRUMENT): VPATH = $(TRACE_INSTRUMENT_PATH)
+$(LIBTRACE_INSTRUMENT): $(dir $(LIBTRACE_INSTRUMENT))/Makefile force
+ $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) \
+ QEMU_CFLAGS="$(call _libinstrument_cflags,$(QEMU_CFLAGS))" \
+ TARGET_DIR=$(TARGET_DIR)$(dir $@)/ VPATH=$(VPATH) \
+ SRC_PATH=$(SRC_PATH) V="$(V)" $(notdir $@))
+endif
diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index a79ec0f..52d2cf4 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -6,7 +6,7 @@ Command-line wrapper for the tracetool machinery.
"""
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi"
@@ -48,7 +48,10 @@ Options:
--target-type <type> QEMU emulator target type ('system' or 'user').
--target-arch <arch> QEMU emulator target arch.
--probe-prefix <prefix> Prefix for dtrace probe names
- (default: qemu-<target-type>-<target-arch>).\
+ (default: qemu-<target-type>-<target-arch>).
+ --instr-static--path <path>
+ Path to directory containing static instrumentation
+ library.\
""" % {
"script" : _SCRIPT,
"backends" : backend_descr,
@@ -67,6 +70,7 @@ def main(args):
long_opts = [ "backend=", "format=", "help", "list-backends", "check-backend" ]
long_opts += [ "binary=", "target-type=", "target-arch=", "probe-prefix=" ]
+ long_opts += [ "instr-static-path=" ]
try:
opts, args = getopt.getopt(args[1:], "", long_opts)
@@ -80,6 +84,7 @@ def main(args):
target_type = None
target_arch = None
probe_prefix = None
+ instr_static_path = None
for opt, arg in opts:
if opt == "--help":
error_opt()
@@ -104,6 +109,8 @@ def main(args):
target_arch = arg
elif opt == '--probe-prefix':
probe_prefix = arg
+ elif opt == '--instr-static-path':
+ instr_static_path = arg
else:
error_opt("unhandled option: %s" % opt)
@@ -130,7 +137,8 @@ def main(args):
try:
tracetool.generate(sys.stdin, arg_format, arg_backend,
- binary = binary, probe_prefix = probe_prefix)
+ binary = binary, probe_prefix = probe_prefix,
+ instr_static_path = instr_static_path)
except tracetool.TracetoolError, e:
error_opt(str(e))
diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py
index f849e39..5406a2b 100644
--- a/scripts/tracetool/__init__.py
+++ b/scripts/tracetool/__init__.py
@@ -180,6 +180,8 @@ class Event(object):
QEMU_TRACE = "trace_%(name)s"
QEMU_TRACE_BACKEND = "trace_%(name)s_backend"
QI_TRACE_INSTRUMENT = "qi_event_%(name)s"
+ QI_TRACE_NOP = "qi_event_%(name)s_nop"
+ QI_TRACE_BACKEND = "qi_event_%(name)s_trace"
def api(self, fmt = None):
if fmt is None:
@@ -229,7 +231,8 @@ def try_import(mod_name, attr_name = None, attr_default = None):
def generate(fevents, format, backend,
- binary = None, probe_prefix = None):
+ binary = None, probe_prefix = None,
+ instr_static_path = None):
"""Generate the output for the given (format, backend) pair.
Parameters
@@ -244,6 +247,8 @@ def generate(fevents, format, backend,
See tracetool.backend.dtrace.BINARY.
probe_prefix : str or None
See tracetool.backend.dtrace.PROBEPREFIX.
+ instr_static_path : str or None
+ See tracetool.backend.instr_static.PATH.
"""
# fix strange python error (UnboundLocalError tracetool)
import tracetool
@@ -270,6 +275,9 @@ def generate(fevents, format, backend,
tracetool.backend.dtrace.BINARY = binary
tracetool.backend.dtrace.PROBEPREFIX = probe_prefix
+ import tracetool.backend.instr_static
+ tracetool.backend.instr_static.PATH = instr_static_path
+
events = _read_events(fevents)
if backend == "nop":
diff --git a/scripts/tracetool/backend/instr_static.py b/scripts/tracetool/backend/instr_static.py
new file mode 100644
index 0000000..b010596
--- /dev/null
+++ b/scripts/tracetool/backend/instr_static.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Static instrumentation proxy.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@linux.vnet.ibm.com"
+
+
+import os
+
+from tracetool import out
+import tracetool.format.qemu_h
+
+
+PATH = None
+
+def _path():
+ if PATH is None:
+ raise ValueError("you must set PATH")
+ return PATH
+
+
+def qemu_h(events):
+ if _path() and os.path.exists(os.sep.join([_path(), "events-pre.h"])):
+ out('#include "events-pre.h"',
+ '',
+ )
+
+ out('#include "instrument/qemu-instr/events.h"',
+ '',
+ )
+ tracetool.format.qemu_h.process_common(events)
+
+ if _path() and os.path.exists(os.sep.join([_path(), "events-post.h"])):
+ out('#include "events-post.h"',
+ '',
+ )
+
+def api_h(events):
+ out('#include "trace/generated-tracers.h"',
+ '',
+ )
+
+ for e in events:
+ if "instrument" not in e.properties:
+ continue
+
+ out('#if defined(QI_EVENT_%(upper_name)s_INLINE)',
+ 'static',
+ '#endif',
+ 'void %(qi)s(%(args)s);',
+ '',
+ 'static inline void %(qi_nop)s(%(args)s)',
+ '{',
+ '}',
+ '',
+ 'static inline void %(qi_backend)s(%(args)s)',
+ '{',
+ ' %(qemu_backend)s(%(argnames)s);',
+ '}',
+ '',
+ qi = e.api(e.QI_TRACE_INSTRUMENT),
+ qi_nop = e.api(e.QI_TRACE_NOP),
+ qi_backend = e.api(e.QI_TRACE_BACKEND),
+ qemu_backend = e.api(e.QEMU_TRACE_BACKEND),
+ args = e.args,
+ argnames = ", ".join(e.args.names()),
+ upper_name = e.name.upper(),
+ )
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 09/23] build: Add variable 'tools-obj-y' for tool-only files
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (7 preceding siblings ...)
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 08/23] instrument: [static] Call statically linked user-provided routines Lluís Vilanova
@ 2013-04-16 13:50 ` Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 10/23] instrument: [dynamic] Call dynamically linked user-provided routines Lluís Vilanova
` (14 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:50 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
Makefile | 11 ++++++-----
libcacard/Makefile | 2 +-
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/Makefile b/Makefile
index 028ef83..2d3431a 100644
--- a/Makefile
+++ b/Makefile
@@ -171,18 +171,19 @@ Makefile: $(version-obj-y)
libqemustub.a: $(stub-obj-y)
libqemuutil.a: $(util-obj-y)
+libqemutools.a: $(tools-obj-y)
######################################################################
qemu-img.o: qemu-img-cmds.h
-qemu-img$(EXESUF): qemu-img.o $(block-obj-y) libqemuutil.a libqemustub.a
-qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) libqemuutil.a libqemustub.a
-qemu-io$(EXESUF): qemu-io.o cmd.o $(block-obj-y) libqemuutil.a libqemustub.a
+qemu-img$(EXESUF): qemu-img.o $(block-obj-y) libqemuutil.a libqemustub.a libqemutools.a
+qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) libqemuutil.a libqemustub.a libqemutools.a
+qemu-io$(EXESUF): qemu-io.o cmd.o $(block-obj-y) libqemuutil.a libqemustub.a libqemutools.a
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
-fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o libqemuutil.a libqemustub.a
+fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o libqemuutil.a libqemustub.a libqemutools.a
fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
@@ -218,7 +219,7 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
-qemu-ga$(EXESUF): $(qga-obj-y) libqemuutil.a libqemustub.a
+qemu-ga$(EXESUF): $(qga-obj-y) libqemuutil.a libqemustub.a libqemutools.a
$(call LINK, $^)
clean:
diff --git a/libcacard/Makefile b/libcacard/Makefile
index 47827a0..c0a5d66 100644
--- a/libcacard/Makefile
+++ b/libcacard/Makefile
@@ -16,7 +16,7 @@ $(libcacard-obj-y): | $(libcacard-lobj-y)
all: libcacard.la libcacard.pc
-vscclient$(EXESUF): libcacard/vscclient.o libcacard.la
+vscclient$(EXESUF): libcacard/vscclient.o libcacard.la libqemutools.a
$(call LINK,$^)
#########################################################################
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 10/23] instrument: [dynamic] Call dynamically linked user-provided routines
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (8 preceding siblings ...)
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 09/23] build: Add variable 'tools-obj-y' for tool-only files Lluís Vilanova
@ 2013-04-16 13:50 ` Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 11/23] instrument: Add internal control interface Lluís Vilanova
` (13 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:50 UTC (permalink / raw)
To: qemu-devel
Provides a mechanism to dynamically change the routine invoked by 'trace_*'.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
.gitignore | 1
Makefile | 4 +
Makefile.objs | 6 ++
configure | 8 ++-
instrument/Makefile.objs | 11 ++++
libcacard/Makefile | 2 -
scripts/tracetool/__init__.py | 1
scripts/tracetool/backend/instr_dynamic.py | 87 ++++++++++++++++++++++++++++
scripts/tracetool/format/api_c.py | 24 ++++++++
scripts/tracetool/format/events_c.py | 36 +++++++++++-
trace/event-internal.h | 12 ++++
11 files changed, 186 insertions(+), 6 deletions(-)
create mode 100644 scripts/tracetool/backend/instr_dynamic.py
create mode 100644 scripts/tracetool/format/api_c.py
diff --git a/.gitignore b/.gitignore
index 2c9695c..2a0ea2f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,7 @@ trace/generated-events.h
trace/generated-events.c
libcacard/trace/generated-tracers.c
instrument/generated-tracers.h
+instrument/generated-tracers.c
instrument/qemu-instr/events.h
*-timestamp
*-softmmu
diff --git a/Makefile b/Makefile
index 2d3431a..cf938be 100644
--- a/Makefile
+++ b/Makefile
@@ -36,6 +36,9 @@ GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
GENERATED_HEADERS += instrument/generated-tracers.h
+ifdef CONFIG_TRACE_INSTRUMENT_DYNAMIC
+GENERATED_SOURCES += instrument/generated-tracers.c
+endif
GENERATED_HEADERS += instrument/qemu-instr/events.h
GENERATED_HEADERS += trace/generated-events.h
@@ -234,6 +237,7 @@ clean:
@# May not be present in GENERATED_HEADERS
rm -f trace/generated-tracers-dtrace.dtrace*
rm -f trace/generated-tracers-dtrace.h*
+ rm -f instrument/generated-tracers.c*
rm -f $(foreach f,$(GENERATED_HEADERS),$(f) $(f)-timestamp)
rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp)
rm -rf qapi-generated
diff --git a/Makefile.objs b/Makefile.objs
index e568c01..5f8ea2d 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -91,6 +91,11 @@ common-obj-y += qom/
common-obj-y += disas/
######################################################################
+# instrumentation
+
+tools-obj-y += instrument/
+
+######################################################################
# guest agent
# FIXME: a few definitions from qapi-types.o/qapi-visit.o are needed
@@ -108,5 +113,6 @@ nested-vars += \
util-obj-y \
qga-obj-y \
block-obj-y \
+ tools-obj-y \
common-obj-y
dummy := $(call unnest-vars)
diff --git a/configure b/configure
index 94b9491..41089cc 100755
--- a/configure
+++ b/configure
@@ -1173,7 +1173,7 @@ echo " Available backends:" $($python "$source_path"/s
echo " --with-trace-file=NAME Full PATH,NAME of file to store traces"
echo " Default:trace-<pid>"
echo " --with-trace-instrument=TYPE"
-echo " Trace instrumentation type (none static; default: $trace_instrument)"
+echo " Trace instrumentation type (none static dynamic; default: $trace_instrument)"
echo " --with-trace-instrument-path=PATH"
echo " Directory to build user-provided static trace event instrumentation library"
echo " --disable-spice disable spice"
@@ -3074,7 +3074,7 @@ fi
##########################################
# Check instrumentation type
case "$trace_instrument" in
-none|static) ;;
+none|static|dynamic) ;;
*) echo "Error: invalid trace instrumentation type: $trace_instrument"
exit 1
;;
@@ -3922,6 +3922,10 @@ if test "$trace_instrument" = "static"; then
echo "TRACETOOL_INSTR_STATIC=--instr-static-path \"\$(TRACE_INSTRUMENT_PATH)\"" >> $config_host_mak
QEMU_CFLAGS="-I\"$trace_instrument_path\" $QEMU_CFLAGS"
fi
+if test "$trace_instrument" = "dynamic"; then
+ echo "#define QI_TYPE_DYNAMIC 1" >> $config_qi
+ echo "CONFIG_TRACE_INSTRUMENT_DYNAMIC=y" >> $config_host_mak
+fi
##########################################
echo "TOOLS=$tools" >> $config_host_mak
diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs
index 4102b59..cae520d 100644
--- a/instrument/Makefile.objs
+++ b/instrument/Makefile.objs
@@ -17,6 +17,17 @@ ifdef CONFIG_TRACE_INSTRUMENT_STATIC
.PHONY: $(obj)/generated-tracers.h-timestamp
endif
+$(obj)/generated-tracers.c: $(obj)/generated-tracers.c-timestamp
+$(obj)/generated-tracers.c-timestamp: $(TRACE_EVENTS) $(BUILD_DIR)/config-host.mak
+ $(call quiet-command,$(TRACETOOL) \
+ --format=api-c \
+ --backend=$(TRACE_INSTRUMENT_BACKEND) \
+ < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+
+tools-obj-$(CONFIG_TRACE_INSTRUMENT_DYNAMIC) += generated-tracers.o
+target-obj-$(CONFIG_TRACE_INSTRUMENT_DYNAMIC) += generated-tracers.o
+
######################################################################
# User interface
diff --git a/libcacard/Makefile b/libcacard/Makefile
index c0a5d66..f3f9f28 100644
--- a/libcacard/Makefile
+++ b/libcacard/Makefile
@@ -7,7 +7,7 @@ libcacard-obj-y = $(stub-obj-y) $(libcacard-y)
libcacard-obj-y += util/osdep.o util/cutils.o util/qemu-timer-common.o util/error.o
libcacard-obj-$(CONFIG_WIN32) += util/oslib-win32.o util/qemu-thread-win32.o
libcacard-obj-$(CONFIG_POSIX) += util/oslib-posix.o util/qemu-thread-posix.o
-libcacard-obj-y += $(filter trace/%, $(util-obj-y))
+libcacard-obj-y += $(filter trace/%, $(util-obj-y)) $(filter instrument/%, $(util-obj-y))
libcacard-lobj-y=$(patsubst %.o,%.lo,$(libcacard-obj-y))
diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py
index 5406a2b..7624982 100644
--- a/scripts/tracetool/__init__.py
+++ b/scripts/tracetool/__init__.py
@@ -182,6 +182,7 @@ class Event(object):
QI_TRACE_INSTRUMENT = "qi_event_%(name)s"
QI_TRACE_NOP = "qi_event_%(name)s_nop"
QI_TRACE_BACKEND = "qi_event_%(name)s_trace"
+ QI_TRACE_CB = QI_TRACE_NOP
def api(self, fmt = None):
if fmt is None:
diff --git a/scripts/tracetool/backend/instr_dynamic.py b/scripts/tracetool/backend/instr_dynamic.py
new file mode 100644
index 0000000..a07ee64
--- /dev/null
+++ b/scripts/tracetool/backend/instr_dynamic.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Dynamic instrumentation proxy.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@linux.vnet.ibm.com"
+
+
+from tracetool import out
+import tracetool.format.qemu_h
+
+
+def qemu_h(events):
+ for e in events:
+ if "instrument" not in e.properties:
+ continue
+
+ out('extern void * %(qi)s_cb;',
+ 'static inline void %(qi)s(%(args)s)',
+ '{',
+ ' ((void (*)(%(argtypes)s))%(qi)s_cb)(%(argnames)s);',
+ '}',
+ qi = e.api(e.QI_TRACE_INSTRUMENT),
+ args = e.args,
+ argnames = ", ".join(e.args.names()),
+ argtypes = ", ".join(e.args.types()),
+ )
+
+ tracetool.format.qemu_h.process_common(events)
+
+
+
+def api_h(events):
+ out('#include <qemu-instr/visibility-internal.h>',
+ '',
+ )
+
+ for e in events:
+ if "instrument" not in e.properties:
+ continue
+
+ out('QI_VPUBLIC void %(qi)s(%(args)s);',
+ 'void %(qi_nop)s(%(args)s);',
+ 'void %(qi_backend)s(%(args)s);',
+ qi = e.api(e.QI_TRACE_INSTRUMENT),
+ qi_nop = e.api(e.QI_TRACE_NOP),
+ qi_backend = e.api(e.QI_TRACE_BACKEND),
+ args = e.args,
+ )
+
+def api_c(events):
+ out('#include "instrument/qemu-instr/events.h"',
+ '',
+ '#include "trace/generated-events.h"',
+ '#include "trace/generated-tracers.h"',
+ '',
+ )
+
+ for e in events:
+ if "instrument" not in e.properties:
+ continue
+
+ out('void %(qi_nop)s(%(args)s)',
+ '{',
+ '}',
+ '',
+ 'void %(qi_backend)s(%(args)s)',
+ '{',
+ ' %(qemu_backend)s(%(argnames)s);',
+ '}',
+ '',
+ 'void * %(qi)s_cb = %(qi_cb)s;',
+ qi = e.api(e.QI_TRACE_INSTRUMENT),
+ qi_nop = e.api(e.QI_TRACE_NOP),
+ qi_backend = e.api(e.QI_TRACE_BACKEND),
+ qi_cb = e.api(e.QI_TRACE_CB),
+ qemu_backend = e.api(e.QEMU_TRACE_BACKEND),
+ args = e.args,
+ argnames = ", ".join(e.args.names()),
+ )
diff --git a/scripts/tracetool/format/api_c.py b/scripts/tracetool/format/api_c.py
new file mode 100644
index 0000000..3787f5d
--- /dev/null
+++ b/scripts/tracetool/format/api_c.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .c for trace instrumentation clients.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@linux.vnet.ibm.com"
+
+
+from tracetool import out
+
+
+def begin(events):
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#include <stdlib.h>',
+ '',
+ )
diff --git a/scripts/tracetool/format/events_c.py b/scripts/tracetool/format/events_c.py
index d670ec8..7531c66 100644
--- a/scripts/tracetool/format/events_c.py
+++ b/scripts/tracetool/format/events_c.py
@@ -6,7 +6,7 @@ Generate .c for event description.
"""
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
__license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi"
@@ -19,17 +19,49 @@ from tracetool import out
def begin(events):
out('/* This file is autogenerated by tracetool, do not edit. */',
'',
+ '#include "config-host.h"',
'#include "trace.h"',
'#include "trace/generated-events.h"',
'#include "trace/control.h"',
'',
)
+ # declarations
+ out('#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)')
+ for e in events:
+ if "instrument" in e.properties:
+ out('void %(nop)s(%(args)s);',
+ 'void %(backend)s(%(args)s);',
+ nop = e.api(e.QI_TRACE_NOP),
+ backend = e.api(e.QI_TRACE_BACKEND),
+ args = e.args,
+ )
+ out('#endif',
+ '',
+ )
+
+ # event state
out('TraceEvent trace_events[TRACE_EVENT_COUNT] = {')
for e in events:
- out(' { .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0 },',
+ cb = cb_nop = cb_backend = "NULL"
+
+ if "instrument" in e.properties:
+ cb = "&%s_cb" % e.api(e.QI_TRACE_INSTRUMENT)
+ cb_nop = e.api(e.QI_TRACE_NOP)
+ cb_backend = e.api(e.QI_TRACE_BACKEND)
+
+ out(' { .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0,',
+ '#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)',
+ ' .instr_cb = %(cb)s,',
+ ' .instr_cb_nop = %(cb_nop)s,',
+ ' .instr_cb_backend = %(cb_backend)s,',
+ '#endif',
+ ' },',
id = "TRACE_" + e.name.upper(),
+ cb = cb,
+ cb_nop = cb_nop,
+ cb_backend = cb_backend,
name = e.name,
sstate = "TRACE_%s_ENABLED" % e.name.upper(),
)
diff --git a/trace/event-internal.h b/trace/event-internal.h
index b2310d9..aed4050 100644
--- a/trace/event-internal.h
+++ b/trace/event-internal.h
@@ -1,7 +1,7 @@
/*
* Interface for configuring and controlling the state of tracing events.
*
- * Copyright (C) 2012 Lluís Vilanova <vilanova@ac.upc.edu>
+ * Copyright (C) 2012-2013 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.
@@ -11,6 +11,7 @@
#define TRACE__EVENT_INTERNAL_H
#include "trace/generated-events.h"
+#include "config-host.h"
/**
@@ -19,6 +20,9 @@
* @name: Event name.
* @sstate: Static tracing state.
* @dstate: Dynamic tracing state.
+ * @instr_cb: Instrumentation callback pointer.
+ * @instr_cb_nop: Instrumentation callback pointer to no-operation.
+ * @instr_cb_backend: Instrumentation callback pointer to tracing backend.
*
* Opaque generic description of a tracing event.
*/
@@ -27,6 +31,12 @@ typedef struct TraceEvent {
const char * name;
const bool sstate;
bool dstate;
+
+#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
+ void **instr_cb;
+ void *instr_cb_nop;
+ void *instr_cb_backend;
+#endif
} TraceEvent;
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 11/23] instrument: Add internal control interface
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (9 preceding siblings ...)
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 10/23] instrument: [dynamic] Call dynamically linked user-provided routines Lluís Vilanova
@ 2013-04-16 13:50 ` Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 12/23] instrument: [hmp] Add " Lluís Vilanova
` (12 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:50 UTC (permalink / raw)
To: qemu-devel
This interface provides two sets of operations:
* Loading/unloading a trace instrumentation library.
* Controls the instrumentation callbacks of the tracing events.
Note that in the case of static instrumentation, the library is not
loaded/unloaded, but is still properly (de)initialized when QEMU starts and
exits.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
Makefile.objs | 2
configure | 3 +
instrument/Makefile.objs | 6 +
instrument/control-internal.h | 38 ++++++++
instrument/control.c | 139 ++++++++++++++++++++++++++++
instrument/control.h | 134 +++++++++++++++++++++++++++
rules.mak | 3 +
scripts/tracetool/backend/instr_dynamic.py | 3 +
scripts/tracetool/backend/instr_static.py | 3 +
scripts/tracetool/format/events_c.py | 6 +
trace/event-internal.h | 5 +
11 files changed, 342 insertions(+)
create mode 100644 instrument/control-internal.h
create mode 100644 instrument/control.c
create mode 100644 instrument/control.h
diff --git a/Makefile.objs b/Makefile.objs
index 5f8ea2d..4fb565b 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -94,6 +94,7 @@ common-obj-y += disas/
# instrumentation
tools-obj-y += instrument/
+target-obj-y += instrument/
######################################################################
# guest agent
@@ -114,5 +115,6 @@ nested-vars += \
qga-obj-y \
block-obj-y \
tools-obj-y \
+ target-obj-y \
common-obj-y
dummy := $(call unnest-vars)
diff --git a/configure b/configure
index 41089cc..d2e0b90 100755
--- a/configure
+++ b/configure
@@ -3925,7 +3925,10 @@ fi
if test "$trace_instrument" = "dynamic"; then
echo "#define QI_TYPE_DYNAMIC 1" >> $config_qi
echo "CONFIG_TRACE_INSTRUMENT_DYNAMIC=y" >> $config_host_mak
+ libs_qga="-ldl $libs_qga"
fi
+# code requiring it is always compiled-in
+LIBS="-ldl $LIBS"
##########################################
echo "TOOLS=$tools" >> $config_host_mak
diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs
index cae520d..e571c71 100644
--- a/instrument/Makefile.objs
+++ b/instrument/Makefile.objs
@@ -60,3 +60,9 @@ $(LIBTRACE_INSTRUMENT): $(dir $(LIBTRACE_INSTRUMENT))/Makefile force
TARGET_DIR=$(TARGET_DIR)$(dir $@)/ VPATH=$(VPATH) \
SRC_PATH=$(SRC_PATH) V="$(V)" $(notdir $@))
endif
+
+
+######################################################################
+# Control code
+
+target-obj-y += control.o
diff --git a/instrument/control-internal.h b/instrument/control-internal.h
new file mode 100644
index 0000000..19b342f
--- /dev/null
+++ b/instrument/control-internal.h
@@ -0,0 +1,38 @@
+/*
+ * Interface for controlling dynamic trace instrumentation.
+ *
+ * Copyright (C) 2012-2013 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__CONTROL_INTERNAL_H
+#define INSTRUMENT__CONTROL_INTERNAL_H
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "config-host.h"
+
+
+static inline bool instr_dynamic(void)
+{
+#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
+ return true;
+#else
+ return false;
+#endif
+}
+
+static inline bool instr_event_available(TraceEvent *ev)
+{
+ assert(ev != NULL);
+#if defined(CONFIG_TRACE_INSTRUMENT_NONE)
+ return false;
+#else
+ return ev->instr;
+#endif
+}
+
+#endif /* INSTRUMENT__CONTROL_INTERNAL_H */
diff --git a/instrument/control.c b/instrument/control.c
new file mode 100644
index 0000000..c6ed36f
--- /dev/null
+++ b/instrument/control.c
@@ -0,0 +1,139 @@
+/*
+ * Interface for controlling dynamic trace instrumentation.
+ *
+ * Copyright (C) 2012-2013 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 "instrument/control.h"
+
+#include <dlfcn.h>
+
+#include "qemu-common.h"
+#include "trace/control.h"
+
+
+#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
+static void *handle = NULL;
+#endif
+
+
+InstrLoadError instr_load(const char * path, int argc, const char ** argv)
+{
+ if (!instr_dynamic()) {
+ return INSTR_LOAD_UNAVAILABLE;
+ }
+
+#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
+ if (handle != NULL) {
+ return INSTR_LOAD_LOADED;
+ }
+
+ handle = dlopen(path, RTLD_NOW);
+
+ if (handle == NULL) {
+ return INSTR_LOAD_DL;
+ }
+
+ void (*init)(int, const char **) = dlsym(handle, "qi_init");
+ if (init == NULL) {
+ return INSTR_LOAD_DL;
+ }
+ void (*fini)(void) = dlsym(handle, "qi_fini");
+ if (fini == NULL) {
+ return INSTR_LOAD_DL;
+ }
+
+ if (init != NULL) {
+ init(argc, argv);
+ }
+#endif
+
+ return INSTR_LOAD_OK;
+}
+
+InstrUnloadError instr_unload(void)
+{
+ if (!instr_dynamic()) {
+ return INSTR_UNLOAD_UNAVAILABLE;
+ }
+
+#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
+ if (handle == NULL) {
+ return INSTR_UNLOAD_UNLOADED;
+ }
+
+ void (*fini)(void) = dlsym(handle, "qi_fini");
+ assert(fini != NULL);
+ fini();
+
+ TraceEvent *ev = NULL;
+ while ((ev = trace_event_pattern("*", ev)) != NULL) {
+ if (instr_event_available(ev)) {
+ instr_event_set(ev, INSTR_CB_NOP);
+ }
+ }
+
+ /* this should never fail */
+ if (dlclose(handle) < 0) {
+ return INSTR_UNLOAD_DL;
+ }
+
+ handle = NULL;
+#endif
+
+ return INSTR_UNLOAD_OK;
+}
+
+#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
+static void *get_event_symbol(TraceEvent *ev, const char *fmt)
+{
+ assert(ev != NULL);
+
+ char name[1024];
+ assert(strlen(trace_event_get_name(ev)) + strlen(fmt) < 1024);
+ sprintf(name, fmt, trace_event_get_name(ev));
+ return dlsym(handle, name);
+}
+
+static void event_set(TraceEvent *ev, void *cb)
+{
+ if (ev->instr_cb == cb) {
+ return;
+ }
+ assert(instr_event_available(ev));
+ *ev->instr_cb = cb;
+}
+#endif
+
+bool instr_event_set(TraceEvent *ev, void *cb)
+{
+ assert(instr_dynamic());
+ assert(ev != NULL);
+ assert(instr_event_available(ev));
+
+#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
+ if (cb == INSTR_CB_NOP) {
+ event_set(ev, ev->instr_cb_nop);
+ return true;
+ } else if (cb == INSTR_CB_NEXT) {
+ event_set(ev, ev->instr_cb_backend);
+ return true;
+ } else if (cb == INSTR_CB_AUTO) {
+ void *ptr = get_event_symbol(ev, "qi_event_%s");
+ if (ptr != NULL) {
+ event_set(ev, ptr);
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ event_set(ev, cb);
+ return true;
+ }
+#else
+ assert(false);
+#endif
+}
diff --git a/instrument/control.h b/instrument/control.h
new file mode 100644
index 0000000..0924fc8
--- /dev/null
+++ b/instrument/control.h
@@ -0,0 +1,134 @@
+/*
+ * Interface for controlling dynamic trace instrumentation.
+ *
+ * Copyright (C) 2012-2013 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__CONTROL_H
+#define INSTRUMENT__CONTROL_H
+
+#include "trace/generated-events.h"
+
+
+/**
+ * InstrLoadError:
+ * @INSTR_LOAD_OK: Correctly loaded.
+ * @INSTR_LOAD_UNAVAILABLE: Service not available.
+ * @INSTR_LOAD_LOADED: Already loaded.
+ * @INSTR_LOAD_DL: Error with libdl (see dlerror).
+ *
+ * Error codes for instr_load().
+ */
+typedef enum {
+ INSTR_LOAD_OK,
+ INSTR_LOAD_UNAVAILABLE,
+ INSTR_LOAD_LOADED,
+ INSTR_LOAD_DL,
+} InstrLoadError;
+
+/**
+ * InstrUnloadError:
+ * @INSTR_UNLOAD_OK: Correctly unloaded.
+ * @INSTR_UNLOAD_UNAVAILABLE: Service not available.
+ * @INSTR_UNLOAD_UNLOADED: Already unloaded.
+ * @INSTR_UNLOAD_DL: Error with libdl (see dlerror).
+ *
+ * Error codes for instr_unload().
+ */
+typedef enum {
+ INSTR_UNLOAD_OK, /*< Correctly unloaded */
+ INSTR_UNLOAD_UNAVAILABLE, /*< Service not available */
+ INSTR_UNLOAD_UNLOADED, /*< Already unloaded */
+ INSTR_UNLOAD_DL, /*< Error with libdl (see dlerror) */
+} InstrUnloadError;
+
+/**
+ * instr_load:
+ * @path: Path to the shared library to load.
+ * @argc: Number of arguments passed to the initialization function of the library.
+ * @argv: Arguments passed to the initialization function of the library.
+ *
+ * Load a dynamic trace instrumentation library.
+ *
+ * Returns: Whether the library could be loaded.
+ */
+InstrLoadError instr_load(const char * path, int argc, const char ** argv);
+
+/**
+ * instr_unload:
+ *
+ * Unload the currently loaded instrumentation library.
+ *
+ * Returns: Whether the library could be unloaded.
+ */
+InstrUnloadError instr_unload(void);
+
+
+/**
+ * instr_dynamic:
+ *
+ * Returns: Whether dynamic trace instrumentation is available.
+ */
+static bool instr_dynamic(void);
+
+/**
+ * instr_event_available:
+ *
+ * Returns: Whether the given event has the 'instrument' property.
+ */
+static bool instr_event_available(TraceEvent *ev);
+
+
+/**
+ * INSTR_CB_NOP:
+ *
+ * Set callback to no-operation.
+ * (qi_event_${name}_nop).
+ */
+#define INSTR_CB_NOP ((void*)NULL)
+
+/**
+ * INSTR_CB_NEXT:
+ *
+ * Set callback to the "next logical step"
+ * (qi_event_${name}_trace).
+ */
+#define INSTR_CB_NEXT ((void*)1)
+
+/**
+ * INSTR_CB_AUTO:
+ *
+ * Automatically set callback to proper routine.
+ *
+ * Looks for a symbol name in the instrumentation library matching the event
+ * name (qi_event_${name}).
+ */
+#define INSTR_CB_AUTO ((void*)2)
+
+/**
+ * instr_event_set:
+ * @ev: Tracing event descriptor.
+ * @cb: Pointer to instrumentation callback.
+ *
+ * Set the instrumentation callback for the given event.
+ *
+ * Argument cb can also be set to any of the INSTR_CB_* special values.
+ *
+ * A negative return value indicates that the instrumentation library does not
+ * export the appropriate symbol for the instrumentation routine.
+ *
+ * Pre-condition: instr_dynamic() == true
+ * Pre-condition: instr_event_available(ev) == true
+ *
+ * Returns: Whether the callback could be set (if cb == INSTR_CB_AUTO, always
+ * true otherwise).
+ */
+bool instr_event_set(TraceEvent *ev, void *cb);
+
+
+#include "instrument/control-internal.h"
+
+#endif /* INSTRUMENT__CONTROL_H */
diff --git a/rules.mak b/rules.mak
index edc2552..e0767a9 100644
--- a/rules.mak
+++ b/rules.mak
@@ -51,6 +51,9 @@ endif
%.o: %.dtrace
$(call quiet-command,dtrace -o $@ -G -s $<, " GEN $(TARGET_DIR)$@")
+ifdef CONFIG_TRACE_INSTRUMENT_DYNAMIC
+%$(EXESUF): LDFLAGS+=-rdynamic
+endif
%$(EXESUF): %.o
$(call LINK,$^)
diff --git a/scripts/tracetool/backend/instr_dynamic.py b/scripts/tracetool/backend/instr_dynamic.py
index a07ee64..12d0503 100644
--- a/scripts/tracetool/backend/instr_dynamic.py
+++ b/scripts/tracetool/backend/instr_dynamic.py
@@ -40,6 +40,9 @@ def qemu_h(events):
def api_h(events):
out('#include <qemu-instr/visibility-internal.h>',
'',
+ 'QI_VPUBLIC void qi_init(int argc, const char **argv);',
+ 'QI_VPUBLIC void qi_fini(void);',
+ '',
)
for e in events:
diff --git a/scripts/tracetool/backend/instr_static.py b/scripts/tracetool/backend/instr_static.py
index b010596..ecebbda 100644
--- a/scripts/tracetool/backend/instr_static.py
+++ b/scripts/tracetool/backend/instr_static.py
@@ -46,6 +46,9 @@ def qemu_h(events):
def api_h(events):
out('#include "trace/generated-tracers.h"',
'',
+ 'void qi_init(int argc, const char **argv);',
+ 'void qi_fini(void);',
+ '',
)
for e in events:
diff --git a/scripts/tracetool/format/events_c.py b/scripts/tracetool/format/events_c.py
index 7531c66..d7b4f86 100644
--- a/scripts/tracetool/format/events_c.py
+++ b/scripts/tracetool/format/events_c.py
@@ -44,14 +44,19 @@ def begin(events):
out('TraceEvent trace_events[TRACE_EVENT_COUNT] = {')
for e in events:
+ instr = "false"
cb = cb_nop = cb_backend = "NULL"
if "instrument" in e.properties:
+ instr = "true"
cb = "&%s_cb" % e.api(e.QI_TRACE_INSTRUMENT)
cb_nop = e.api(e.QI_TRACE_NOP)
cb_backend = e.api(e.QI_TRACE_BACKEND)
out(' { .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0,',
+ '#if !defined(CONFIG_TRACE_INSTRUMENT_NONE)',
+ ' .instr = %(instr)s,',
+ '#endif',
'#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)',
' .instr_cb = %(cb)s,',
' .instr_cb_nop = %(cb_nop)s,',
@@ -59,6 +64,7 @@ def begin(events):
'#endif',
' },',
id = "TRACE_" + e.name.upper(),
+ instr = instr,
cb = cb,
cb_nop = cb_nop,
cb_backend = cb_backend,
diff --git a/trace/event-internal.h b/trace/event-internal.h
index aed4050..415aec6 100644
--- a/trace/event-internal.h
+++ b/trace/event-internal.h
@@ -20,6 +20,7 @@
* @name: Event name.
* @sstate: Static tracing state.
* @dstate: Dynamic tracing state.
+ * @instr: Whether the event is instrumentable.
* @instr_cb: Instrumentation callback pointer.
* @instr_cb_nop: Instrumentation callback pointer to no-operation.
* @instr_cb_backend: Instrumentation callback pointer to tracing backend.
@@ -32,6 +33,10 @@ typedef struct TraceEvent {
const bool sstate;
bool dstate;
+#if !defined(CONFIG_TRACE_INSTRUMENT_NONE)
+ const bool instr;
+#endif
+
#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
void **instr_cb;
void *instr_cb_nop;
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 12/23] instrument: [hmp] Add control interface
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (10 preceding siblings ...)
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 11/23] instrument: Add internal control interface Lluís Vilanova
@ 2013-04-16 13:50 ` Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 13/23] qapi: Add a primitive to include other files from a QAPI schema file Lluís Vilanova
` (11 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:50 UTC (permalink / raw)
To: qemu-devel
Add HMP commands to control (un)loading of dynamic instrumentation library.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
Makefile.objs | 1 +
hmp-commands.hx | 42 +++++++++++++++++++++++++++++
instrument/Makefile.objs | 2 +
instrument/hmp.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++
instrument/hmp.h | 21 +++++++++++++++
monitor.c | 1 +
6 files changed, 133 insertions(+)
create mode 100644 instrument/hmp.c
create mode 100644 instrument/hmp.h
diff --git a/Makefile.objs b/Makefile.objs
index 4fb565b..151183d 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -95,6 +95,7 @@ common-obj-y += disas/
tools-obj-y += instrument/
target-obj-y += instrument/
+common-obj-y += instrument/
######################################################################
# guest agent
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 3d98604..7b5ae2a 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1653,6 +1653,48 @@ STEXI
show available trace events and their state
ETEXI
+ {
+ .name = "instr-dynamic",
+ .args_type = "",
+ .params = "",
+ .help = "whether dynamic trace instrumentation is available",
+ .mhandler.cmd = hmp_instr_dynamic,
+ },
+
+STEXI
+@item instr-dynamic
+@findex instr-dynamic
+Whether dynamic trace instrumentation is available.
+ETEXI
+
+ {
+ .name = "instr-load",
+ .args_type = "path:F,args:s?",
+ .params = "path [args]",
+ .help = "load a dynamic instrumentation library",
+ .mhandler.cmd = hmp_instr_load,
+ },
+
+STEXI
+@item instr-load @var{path} [name=value[,...]]
+@findex instr-load
+Load a dynamic instrumentation library.
+ETEXI
+
+ {
+ .name = "instr-unload",
+ .args_type = "",
+ .params = "",
+ .help = "unload the current dynamic instrumentation library",
+ .mhandler.cmd = hmp_instr_unload,
+ },
+
+STEXI
+@item instr-unload
+@findex instr-unload
+Unload the current dynamic instrumentation library.
+ETEXI
+
STEXI
@end table
ETEXI
diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs
index e571c71..02cc5b7 100644
--- a/instrument/Makefile.objs
+++ b/instrument/Makefile.objs
@@ -66,3 +66,5 @@ endif
# Control code
target-obj-y += control.o
+
+common-obj-$(CONFIG_SOFTMMU) += hmp.o
diff --git a/instrument/hmp.c b/instrument/hmp.c
new file mode 100644
index 0000000..53c2da7
--- /dev/null
+++ b/instrument/hmp.c
@@ -0,0 +1,66 @@
+/*
+ * HMP interface for dynamic trace instrumentation control commands.
+ *
+ * Copyright (C) 2012-2013 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 "instrument/hmp.h"
+
+#include <dlfcn.h>
+
+#include "monitor/monitor.h"
+#include "instrument/control.h"
+
+
+void hmp_instr_dynamic(Monitor *mon, const QDict *qdict)
+{
+ monitor_printf(mon, instr_dynamic() ? "true\n" : "false\n");
+}
+
+void hmp_instr_load(Monitor *mon, const QDict *qdict)
+{
+ /* @todo: Unify with qerror messages? */
+
+ const char *path = qdict_get_try_str(qdict, "path");
+ const char *args = qdict_get_try_str(qdict, "args");
+ const char *argv[1] = {args};
+ InstrLoadError err = instr_load(path, 1, argv);
+ switch (err) {
+ case INSTR_LOAD_OK:
+ monitor_printf(mon, "OK\n");
+ break;
+ case INSTR_LOAD_UNAVAILABLE:
+ monitor_printf(mon, "Not available\n");
+ break;
+ case INSTR_LOAD_LOADED:
+ monitor_printf(mon, "Already loaded\n");
+ break;
+ case INSTR_LOAD_DL:
+ monitor_printf(mon, "Error loading library: %s\n", dlerror());
+ break;
+ }
+}
+
+void hmp_instr_unload(Monitor *mon, const QDict *qdict)
+{
+ /* @todo: Unify with qerror messages? */
+
+ InstrLoadError err = instr_unload();
+ switch (err) {
+ case INSTR_UNLOAD_OK:
+ monitor_printf(mon, "OK\n");
+ break;
+ case INSTR_UNLOAD_UNAVAILABLE:
+ monitor_printf(mon, "Not available\n");
+ break;
+ case INSTR_UNLOAD_UNLOADED:
+ monitor_printf(mon, "Already unloaded\n");
+ break;
+ case INSTR_UNLOAD_DL:
+ monitor_printf(mon, "Error unloading library: %s\n", dlerror());
+ break;
+ }
+}
diff --git a/instrument/hmp.h b/instrument/hmp.h
new file mode 100644
index 0000000..a91b6bc
--- /dev/null
+++ b/instrument/hmp.h
@@ -0,0 +1,21 @@
+/*
+ * HMP interface for dynamic trace instrumentation control commands.
+ *
+ * Copyright (C) 2012-2013 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__HMP_H
+#define INSTRUMENT__HMP_H
+
+#include "qemu-common.h"
+#include "qapi/qmp/qdict.h"
+
+
+void hmp_instr_dynamic(Monitor *mon, const QDict *qdict);
+void hmp_instr_load(Monitor *mon, const QDict *qdict);
+void hmp_instr_unload(Monitor *mon, const QDict *qdict);
+
+#endif /* INSTRUMENT__HMP_H */
diff --git a/monitor.c b/monitor.c
index a8f49d9..22284cb 100644
--- a/monitor.c
+++ b/monitor.c
@@ -69,6 +69,7 @@
#include "exec/memory.h"
#include "qmp-commands.h"
#include "hmp.h"
+#include "instrument/hmp.h"
#include "qemu/thread.h"
/* for pic/irq_info */
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 13/23] qapi: Add a primitive to include other files from a QAPI schema file
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (11 preceding siblings ...)
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 12/23] instrument: [hmp] Add " Lluís Vilanova
@ 2013-04-16 13:51 ` Lluís Vilanova
2013-04-19 2:49 ` Eric Blake
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 14/23] [trivial] Set the input root directory when parsing QAPI files Lluís Vilanova
` (10 subsequent siblings)
23 siblings, 1 reply; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:51 UTC (permalink / raw)
To: qemu-devel
Adds the "input(...)" primitive to the syntax of QAPI schema files.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
scripts/qapi-commands.py | 10 +++++++---
scripts/qapi-types.py | 10 +++++++---
scripts/qapi-visit.py | 10 +++++++---
scripts/qapi.py | 12 +++++++++++-
4 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index e06332b..fa16651 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -386,13 +386,15 @@ def gen_command_def_prologue(prefix="", proxy=False):
try:
- opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:m",
+ opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:i:o:m",
["source", "header", "prefix=",
- "output-dir=", "type=", "middle"])
+ "input-dir=", "output-dir=",
+ "type=", "middle"])
except getopt.GetoptError, err:
print str(err)
sys.exit(1)
+input_dir = ""
output_dir = ""
prefix = ""
dispatch_type = "sync"
@@ -406,6 +408,8 @@ do_h = False
for o, a in opts:
if o in ("-p", "--prefix"):
prefix = a
+ elif o in ("-i", "--input-dir"):
+ input_dir = a
elif o in ("-o", "--output-dir"):
output_dir = a + "/"
elif o in ("-t", "--type"):
@@ -437,7 +441,7 @@ except os.error, e:
if e.errno != errno.EEXIST:
raise
-exprs = parse_schema(sys.stdin)
+exprs = parse_schema(sys.stdin, input_dir)
commands = filter(lambda expr: expr.has_key('command'), exprs)
commands = filter(lambda expr: not expr.has_key('gen'), commands)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 9e19920..ea33668 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -184,13 +184,15 @@ void qapi_free_%(type)s(%(c_type)s obj)
try:
- opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
- ["source", "header", "prefix=", "output-dir="])
+ opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:i:o:",
+ ["source", "header", "prefix=",
+ "input-dir=", "output-dir="])
except getopt.GetoptError, err:
print str(err)
sys.exit(1)
output_dir = ""
+input_dir = ""
prefix = ""
c_file = 'qapi-types.c'
h_file = 'qapi-types.h'
@@ -201,6 +203,8 @@ do_h = False
for o, a in opts:
if o in ("-p", "--prefix"):
prefix = a
+ elif o in ("-i", "--input-dir"):
+ input_dir = a
elif o in ("-o", "--output-dir"):
output_dir = a + "/"
elif o in ("-c", "--source"):
@@ -279,7 +283,7 @@ fdecl.write(mcgen('''
''',
guard=guardname(h_file)))
-exprs = parse_schema(sys.stdin)
+exprs = parse_schema(sys.stdin, input_dir)
exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
for expr in exprs:
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index a276540..c372e99 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -235,12 +235,14 @@ void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **e
name=name)
try:
- opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
- ["source", "header", "prefix=", "output-dir="])
+ opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:i:o:",
+ ["source", "header", "prefix=",
+ "input-dir=", "output-dir="])
except getopt.GetoptError, err:
print str(err)
sys.exit(1)
+input_dir = ""
output_dir = ""
prefix = ""
c_file = 'qapi-visit.c'
@@ -252,6 +254,8 @@ do_h = False
for o, a in opts:
if o in ("-p", "--prefix"):
prefix = a
+ elif o in ("-i", "--input-dir"):
+ input_dir = a
elif o in ("-o", "--output-dir"):
output_dir = a + "/"
elif o in ("-c", "--source"):
@@ -327,7 +331,7 @@ fdecl.write(mcgen('''
''',
prefix=prefix, guard=guardname(h_file)))
-exprs = parse_schema(sys.stdin)
+exprs = parse_schema(sys.stdin, input_dir)
for expr in exprs:
if expr.has_key('type'):
diff --git a/scripts/qapi.py b/scripts/qapi.py
index afc5f32..2d444d9 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -9,8 +9,12 @@
# This work is licensed under the terms of the GNU GPLv2.
# See the COPYING.LIB file in the top-level directory.
+import os
+import re
from ordereddict import OrderedDict
+input_cre = re.compile("\s*input\(\"([^\"]*)\"\)")
+
def tokenize(data):
while len(data):
ch = data[0]
@@ -72,7 +76,7 @@ def parse(tokens):
def evaluate(string):
return parse(map(lambda x: x, tokenize(string)))[0]
-def parse_schema(fp):
+def parse_schema(fp, input_dir):
exprs = []
expr = ''
expr_eval = None
@@ -81,6 +85,12 @@ def parse_schema(fp):
if line.startswith('#') or line == '\n':
continue
+ line_file = input_cre.match(line)
+ if line_file is not None:
+ path = os.sep.join([input_dir, line_file.group(1)])
+ exprs += parse_schema(file(path), input_dir)
+ continue
+
if line.startswith(' '):
expr += line
elif expr:
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 14/23] [trivial] Set the input root directory when parsing QAPI files
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (12 preceding siblings ...)
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 13/23] qapi: Add a primitive to include other files from a QAPI schema file Lluís Vilanova
@ 2013-04-16 13:51 ` Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 15/23] instrument: [qmp, qapi] Add control interface Lluís Vilanova
` (9 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:51 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
Makefile | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/Makefile b/Makefile
index cf938be..8280273 100644
--- a/Makefile
+++ b/Makefile
@@ -211,13 +211,19 @@ $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
qapi-types.c qapi-types.h :\
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." < $<, " GEN $@")
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
+ $(gen-out-type) -o "." -i "$(SRC_PATH)" \
+ < $<, " GEN $@")
qapi-visit.c qapi-visit.h :\
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." < $<, " GEN $@")
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
+ $(gen-out-type) -o "." -i "$(SRC_PATH)" \
+ < $<, " GEN $@")
qmp-commands.h qmp-marshal.c :\
$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@")
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
+ $(gen-out-type) -m -o "." -i "$(SRC_PATH)" \
+ < $<, " GEN $@")
QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 15/23] instrument: [qmp, qapi] Add control interface
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (13 preceding siblings ...)
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 14/23] [trivial] Set the input root directory when parsing QAPI files Lluís Vilanova
@ 2013-04-16 13:51 ` Lluís Vilanova
2013-04-19 3:07 ` Eric Blake
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 16/23] Let makefiles add entries to the set of target architecture objects Lluís Vilanova
` (8 subsequent siblings)
23 siblings, 1 reply; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:51 UTC (permalink / raw)
To: qemu-devel
Add QMP commands to control (un)loading of dynamic instrumentation library.
Signed-off-by: Lluís Vilanova <vilanova@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 <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-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)
{
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 16/23] Let makefiles add entries to the set of target architecture objects
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (14 preceding siblings ...)
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 15/23] instrument: [qmp, qapi] Add control interface Lluís Vilanova
@ 2013-04-16 13:51 ` Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 17/23] instrument: Add commandline options to start with an instrumentation library Lluís Vilanova
` (7 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:51 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
Makefile.target | 1 +
1 file changed, 1 insertion(+)
diff --git a/Makefile.target b/Makefile.target
index 114fc39..fe48432 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -149,6 +149,7 @@ include $(SRC_PATH)/Makefile.objs
all-obj-y = $(obj-y)
all-obj-y += $(addprefix ../, $(common-obj-y))
+all-obj-y += $(target-obj-y)
all-obj-y += $(LIBTRACE_INSTRUMENT)
ifdef QEMU_PROGW
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 17/23] instrument: Add commandline options to start with an instrumentation library
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (15 preceding siblings ...)
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 16/23] Let makefiles add entries to the set of target architecture objects Lluís Vilanova
@ 2013-04-16 13:51 ` Lluís Vilanova
2013-04-19 3:28 ` Eric Blake
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 18/23] instrument: Add client-side API to enumerate events Lluís Vilanova
` (6 subsequent siblings)
23 siblings, 1 reply; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:51 UTC (permalink / raw)
To: qemu-devel
Add commandline options to control initial loading of dynamic instrumentation
library.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
bsd-user/main.c | 25 +++++++++++
bsd-user/syscall.c | 5 ++
instrument/Makefile.objs | 2 +
instrument/cmdline.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++
instrument/cmdline.h | 52 ++++++++++++++++++++++++
linux-user/main.c | 30 ++++++++++++++
linux-user/syscall.c | 4 ++
qemu-options.hx | 18 ++++++++
vl.c | 41 +++++++++++++++++++
9 files changed, 278 insertions(+)
create mode 100644 instrument/cmdline.c
create mode 100644 instrument/cmdline.h
diff --git a/bsd-user/main.c b/bsd-user/main.c
index cc84981..489168a 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -33,6 +33,8 @@
#include "tcg.h"
#include "qemu/timer.h"
#include "qemu/envlist.h"
+#include "instrument/cmdline.h"
+
int singlestep;
#if defined(CONFIG_USE_GUEST_BASE)
@@ -688,6 +690,15 @@ static void usage(void)
#endif
"-bsd type select emulated BSD type FreeBSD/NetBSD/OpenBSD (default)\n"
"\n"
+#if defined(CONFIG_TRACE_INSTRUMENT)
+ "Tracing options:\n"
+#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
+ "-instr path load a dynamic trace instrumentation library\n"
+#endif
+ "-instr-arg string\n"
+ " argument to dynamic trace instrumentation library (can be given multiple times)\n"
+ "\n"
+#endif
"Debug options:\n"
"-d item1[,...] enable logging of specified items\n"
" (use '-d help' for a list of log items)\n"
@@ -743,6 +754,9 @@ int main(int argc, char **argv)
char **target_environ, **wrk;
envlist_t *envlist = NULL;
bsd_type = target_openbsd;
+ char *instrument_path = NULL;
+ int instrument_argc = 0;
+ char **instrument_argv = NULL;
if (argc <= 1)
usage();
@@ -852,6 +866,14 @@ int main(int argc, char **argv)
singlestep = 1;
} else if (!strcmp(r, "strace")) {
do_strace = 1;
+#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
+ } else if (!strcmp(r, "instr")) {
+ instrument_path = argv[optind++];
+#endif
+#if defined(CONFIG_TRACE_INSTRUMENT)
+ } else if (!strcmp(r, "instr-arg")) {
+ instr_parse_args(argv[optind++], &instrument_argc, &instrument_argv);
+#endif
} else
{
usage();
@@ -1135,6 +1157,9 @@ int main(int argc, char **argv)
gdbserver_start (gdbstub_port);
gdb_handlesig(env, 0);
}
+
+ instr_init(instrument_path, instrument_argc, instrument_argv);
+
cpu_loop(env);
/* never exits */
return 0;
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index 18b43f1..dbb6816 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -35,6 +35,8 @@
#include "qemu.h"
#include "qemu-common.h"
+#include "instrument/cmdline.h"
+
//#define DEBUG
@@ -334,6 +336,7 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
_mcleanup();
#endif
gdb_exit(cpu_env, arg1);
+ instr_fini();
/* XXX: should free thread stack and CPU env */
_exit(arg1);
ret = 0; /* avoid warning */
@@ -429,6 +432,7 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
_mcleanup();
#endif
gdb_exit(cpu_env, arg1);
+ instr_fini();
/* XXX: should free thread stack and CPU env */
_exit(arg1);
ret = 0; /* avoid warning */
@@ -501,6 +505,7 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
_mcleanup();
#endif
gdb_exit(cpu_env, arg1);
+ instr_fini();
/* XXX: should free thread stack and CPU env */
_exit(arg1);
ret = 0; /* avoid warning */
diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs
index e3d4e9b..453330f 100644
--- a/instrument/Makefile.objs
+++ b/instrument/Makefile.objs
@@ -65,6 +65,8 @@ endif
######################################################################
# Control code
+target-obj-y += cmdline.o
+
target-obj-y += control.o
common-obj-$(CONFIG_SOFTMMU) += hmp.o
diff --git a/instrument/cmdline.c b/instrument/cmdline.c
new file mode 100644
index 0000000..0f52f60
--- /dev/null
+++ b/instrument/cmdline.c
@@ -0,0 +1,101 @@
+/*
+ * Control dynamic trace instrumentation during program (de)initialization.
+ *
+ * Copyright (C) 2012-2013 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 "instrument/cmdline.h"
+
+#include <dlfcn.h>
+
+#include "qemu-common.h"
+#include "instrument/control.h"
+
+#if defined(CONFIG_TRACE_INSTRUMENT_STATIC)
+#include "instrument/qemu-instr/events.h"
+#endif
+
+
+static bool loaded;
+
+
+void instr_parse_args(const char *args, int *argc, const char ***argv)
+{
+ *argv = realloc(*argv, sizeof(**argv) * (*argc + 1));
+ (*argv)[*argc] = args;
+ (*argc)++;
+}
+
+void instr_init(const char *path, int argc, const char **argv)
+{
+ if (atexit(instr_fini) != 0) {
+ fprintf(stderr, "error: atexit: %s\n", strerror(errno));
+ abort();
+ }
+
+ if (path == NULL) {
+#if defined(CONFIG_TRACE_INSTRUMENT_STATIC)
+ loaded = true;
+ qi_init(argc, argv);
+#endif
+ return;
+ }
+
+ InstrLoadError err = instr_load(path, argc, argv);
+ switch (err) {
+ case INSTR_LOAD_OK:
+ loaded = true;
+ return;
+ case INSTR_LOAD_UNAVAILABLE:
+ fprintf(stderr, "error: instrument: not available\n");
+ break;
+ case INSTR_LOAD_LOADED:
+ fprintf(stderr, "error: instrument: already loaded\n");
+ break;
+ case INSTR_LOAD_DL:
+#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
+ fprintf(stderr, "error: instrument: error loading library: %s\n", dlerror());
+#else
+ abort();
+#endif
+ break;
+ }
+
+ exit(1);
+}
+
+void instr_fini(void)
+{
+ if (!loaded) {
+ return;
+ }
+
+#if defined(CONFIG_TRACE_INSTRUMENT_STATIC)
+ qi_fini();
+ return;
+#endif
+
+ InstrUnloadError err = instr_unload();
+ switch (err) {
+ case INSTR_UNLOAD_OK:
+ return;
+ case INSTR_UNLOAD_UNAVAILABLE:
+ fprintf(stderr, "error: not available\n");
+ break;
+ case INSTR_UNLOAD_UNLOADED:
+ /* the user might have already unloaded it */
+ return;
+ case INSTR_UNLOAD_DL:
+#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
+ fprintf(stderr, "error: error unloading library: %s\n", dlerror());
+#else
+ abort();
+#endif
+ break;
+ }
+
+ exit(1);
+}
diff --git a/instrument/cmdline.h b/instrument/cmdline.h
new file mode 100644
index 0000000..b096793
--- /dev/null
+++ b/instrument/cmdline.h
@@ -0,0 +1,52 @@
+/*
+ * Control dynamic trace instrumentation during program (de)initialization.
+ *
+ * Copyright (C) 2012-2013 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
+
+/**
+ * instr_parse_args:
+ * @args: Input arguments.
+ * @argc: Output argument count.
+ * @argv: Output argument array.
+ *
+ * Adds element @args into the argument array.
+ */
+void instr_parse_args(const char *args, 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 */
diff --git a/linux-user/main.c b/linux-user/main.c
index 4e92a0b..9216e69 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -34,6 +34,8 @@
#include "qemu/timer.h"
#include "qemu/envlist.h"
#include "elf.h"
+#include "instrument/cmdline.h"
+
char *exec_path;
@@ -3327,6 +3329,23 @@ static void handle_arg_reserved_va(const char *arg)
}
#endif
+static const char *instrument_path;
+#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
+static void handle_arg_instrument(const char *arg)
+{
+ instrument_path = arg;
+}
+#endif
+
+static int instrument_argc = 0;
+static const char **instrument_argv = NULL;
+#if defined(CONFIG_TRACE_INSTRUMENT)
+static void handle_arg_instrument_arg(const char *arg)
+{
+ instr_parse_args(arg, &instrument_argc, &instrument_argv);
+}
+#endif
+
static void handle_arg_singlestep(const char *arg)
{
singlestep = 1;
@@ -3378,6 +3397,14 @@ static const struct qemu_argument arg_table[] = {
{"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
"size", "reserve 'size' bytes for guest virtual address space"},
#endif
+#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
+ {"instr", "QEMU_INSTR", true, handle_arg_instrument,
+ "path", "load a dynamic trace instrumentation library"},
+#endif
+#if defined(CONFIG_TRACE_INSTRUMENT)
+ {"instr-arg", "QEMU_INSTR_ARGS", true, handle_arg_instrument_arg,
+ "string", "argument to dynamic trace instrumentation library (can be given multiple times)"},
+#endif
{"d", "QEMU_LOG", true, handle_arg_log,
"item[,...]", "enable logging of specified items "
"(use '-d help' for a list of items)"},
@@ -4071,6 +4098,9 @@ int main(int argc, char **argv, char **envp)
}
gdb_handlesig(env, 0);
}
+
+ instr_init(instrument_path, instrument_argc, instrument_argv);
+
cpu_loop(env);
/* never exits */
return 0;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 1f07621..d55af6c 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -109,6 +109,8 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
#include "cpu-uname.h"
#include "qemu.h"
+#include "instrument/cmdline.h"
+
#if defined(CONFIG_USE_NPTL)
#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
@@ -5248,6 +5250,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
_mcleanup();
#endif
gdb_exit(cpu_env, arg1);
+ instr_fini();
_exit(arg1);
ret = 0; /* avoid warning */
break;
@@ -7028,6 +7031,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
_mcleanup();
#endif
gdb_exit(cpu_env, arg1);
+ instr_fini();
ret = get_errno(exit_group(arg1));
break;
#endif
diff --git a/qemu-options.hx b/qemu-options.hx
index 7cd6002..0f36c1c 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3021,6 +3021,24 @@ the @var{simple} tracing backend.
@end table
ETEXI
+DEF("instr", HAS_ARG, QEMU_OPTION_instr,
+ "-instr file=<file>[,arg=<string>]\n"
+ " load an instrumentation library\n",
+ QEMU_ARCH_ALL)
+STEXI
+@item -instr file=@var{file}[,arg=@var{string}]
+@findex -instr
+
+Load a dynamic trace instrumentation library.
+
+@table @option
+@item file=@var{file}
+Load the given dynamic trace instrumentation library.
+@item arg=@var{string}
+String argument passed as to the library's @code{qi_init} routine (can be given multiple times).
+@end table
+ETEXI
+
HXCOMM Internal use
DEF("qtest", HAS_ARG, QEMU_OPTION_qtest, "", QEMU_ARCH_ALL)
DEF("qtest-log", HAS_ARG, QEMU_OPTION_qtest_log, "", QEMU_ARCH_ALL)
diff --git a/vl.c b/vl.c
index d694a90..e773bb4 100644
--- a/vl.c
+++ b/vl.c
@@ -163,6 +163,7 @@ int main(int argc, char **argv)
#include "trace.h"
#include "trace/control.h"
+#include "instrument/cmdline.h"
#include "qemu/queue.h"
#include "sysemu/cpus.h"
#include "sysemu/arch_init.h"
@@ -352,6 +353,22 @@ static QemuOptsList qemu_trace_opts = {
},
};
+static QemuOptsList qemu_instr_opts = {
+ .name = "instr",
+ .implied_opt_name = "instr",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_instr_opts.head),
+ .desc = {
+ {
+ .name = "file",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "arg",
+ .type = QEMU_OPT_STRING,
+ },
+ { /* end of list */ }
+ },
+};
+
static QemuOptsList qemu_option_rom_opts = {
.name = "option-rom",
.implied_opt_name = "romfile",
@@ -2883,6 +2900,9 @@ int main(int argc, char **argv, char **envp)
};
const char *trace_events = NULL;
const char *trace_file = NULL;
+ const char *instrument_path = NULL;
+ int instrument_argc = 0;
+ const char **instrument_argv = NULL;
atexit(qemu_run_exit_notifiers);
error_set_progname(argv[0]);
@@ -2908,6 +2928,7 @@ int main(int argc, char **argv, char **envp)
qemu_add_opts(&qemu_global_opts);
qemu_add_opts(&qemu_mon_opts);
qemu_add_opts(&qemu_trace_opts);
+ qemu_add_opts(&qemu_instr_opts);
qemu_add_opts(&qemu_option_rom_opts);
qemu_add_opts(&qemu_machine_opts);
qemu_add_opts(&qemu_boot_opts);
@@ -3820,6 +3841,24 @@ int main(int argc, char **argv, char **envp)
trace_file = qemu_opt_get(opts, "file");
break;
}
+ case QEMU_OPTION_instr:
+ {
+ olist = qemu_find_opts("instr");
+ if (!olist) {
+ exit(1);
+ }
+ opts = qemu_opts_parse(olist, optarg, 0);
+ if (!opts) {
+ exit(1);
+ }
+ const char * path = qemu_opt_get(opts, "file");
+ if (path != NULL) {
+ instrument_path = path;
+ }
+ instr_parse_args(qemu_opt_get(opts, "arg"),
+ &instrument_argc, &instrument_argv);
+ break;
+ }
case QEMU_OPTION_readconfig:
{
int ret = qemu_read_config_file(optarg);
@@ -4414,6 +4453,8 @@ int main(int argc, char **argv, char **envp)
}
}
+ instr_init(instrument_path, instrument_argc, instrument_argv);
+
if (incoming) {
Error *local_err = NULL;
qemu_start_incoming_migration(incoming, &local_err);
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 18/23] instrument: Add client-side API to enumerate events
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (16 preceding siblings ...)
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 17/23] instrument: Add commandline options to start with an instrumentation library Lluís Vilanova
@ 2013-04-16 13:51 ` Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 19/23] instrument: Add client-side API to control tracing state of events Lluís Vilanova
` (5 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:51 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
.gitignore | 1
Makefile | 1
configure | 1
instrument/Makefile.objs | 13 +++
instrument/api-control.c | 14 +++
instrument/qemu-instr/control-internal.h | 53 ++++++++++++
instrument/qemu-instr/control.h | 124 +++++++++++++++++++++++++++
instrument/qemu-instr/visibility-internal.h | 94 ++++++++++++++++++++
scripts/tracetool/backend/instr_dynamic.py | 3 +
scripts/tracetool/backend/instr_none.py | 3 +
scripts/tracetool/backend/instr_static.py | 3 +
scripts/tracetool/format/api_events_h.py | 56 ++++++++++++
12 files changed, 366 insertions(+)
create mode 100644 instrument/api-control.c
create mode 100644 instrument/qemu-instr/control-internal.h
create mode 100644 instrument/qemu-instr/control.h
create mode 100644 instrument/qemu-instr/visibility-internal.h
create mode 100644 scripts/tracetool/format/api_events_h.py
diff --git a/.gitignore b/.gitignore
index 2a0ea2f..59acb2a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,7 @@ libcacard/trace/generated-tracers.c
instrument/generated-tracers.h
instrument/generated-tracers.c
instrument/qemu-instr/events.h
+instrument/qemu-instr/events-list.h
*-timestamp
*-softmmu
*-darwin-user
diff --git a/Makefile b/Makefile
index 8280273..7916152 100644
--- a/Makefile
+++ b/Makefile
@@ -40,6 +40,7 @@ ifdef CONFIG_TRACE_INSTRUMENT_DYNAMIC
GENERATED_SOURCES += instrument/generated-tracers.c
endif
GENERATED_HEADERS += instrument/qemu-instr/events.h
+GENERATED_HEADERS += instrument/qemu-instr/events-list.h
GENERATED_HEADERS += trace/generated-events.h
GENERATED_SOURCES += trace/generated-events.c
diff --git a/configure b/configure
index d2e0b90..32142f9 100755
--- a/configure
+++ b/configure
@@ -301,6 +301,7 @@ QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS"
QEMU_CFLAGS="-Wall -Wundef -Wwrite-strings -Wmissing-prototypes $QEMU_CFLAGS"
QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
+QEMU_CFLAGS="-DBUILDING_QEMU $QEMU_CFLAGS"
QEMU_INCLUDES="-I. -I\$(SRC_PATH) -I\$(SRC_PATH)/include"
if test "$debug_info" = "yes"; then
CFLAGS="-g $CFLAGS"
diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs
index 453330f..1438626 100644
--- a/instrument/Makefile.objs
+++ b/instrument/Makefile.objs
@@ -41,6 +41,15 @@ $(obj)/qemu-instr/events.h-timestamp: $(TRACE_EVENTS) $(BUILD_DIR)/config-host.m
< $< > $@," GEN $(patsubst %-timestamp,%,$@)")
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+$(obj)/qemu-instr/events-list.h: $(obj)/qemu-instr/events-list.h-timestamp
+$(obj)/qemu-instr/events-list.h-timestamp: $(TRACE_EVENTS) $(BUILD_DIR)/config-host.mak
+ $(call quiet-command,$(TRACETOOL) \
+ --format=api-events-h \
+ --backend=$(TRACE_INSTRUMENT_BACKEND) \
+ $(TRACETOOL_INSTR_STATIC) \
+ < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
+ @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+
######################################################################
# User code (static instrumentation)
@@ -71,3 +80,7 @@ target-obj-y += control.o
common-obj-$(CONFIG_SOFTMMU) += hmp.o
common-obj-$(CONFIG_SOFTMMU) += qmp.o
+
+target-obj-y += api-control.o
+
+QEMU_CFLAGS += -I$(BUILD_DIR)/instrument -I$(SRC_PATH)/instrument
diff --git a/instrument/api-control.c b/instrument/api-control.c
new file mode 100644
index 0000000..e3aac49
--- /dev/null
+++ b/instrument/api-control.c
@@ -0,0 +1,14 @@
+/*
+ * Interface for controlling the state of events.
+ *
+ * Copyright (C) 2012-2013 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 "instrument/qemu-instr/control.h"
+
+#if defined(QI_TYPE_DYNAMIC)
+#include "instrument/qemu-instr/control-internal.h"
+#endif
diff --git a/instrument/qemu-instr/control-internal.h b/instrument/qemu-instr/control-internal.h
new file mode 100644
index 0000000..6e419e7
--- /dev/null
+++ b/instrument/qemu-instr/control-internal.h
@@ -0,0 +1,53 @@
+/*
+ * Interface for controlling the state of events.
+ *
+ * Copyright (C) 2012-2013 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 QI__CONTROL_INTERNAL_H
+#define QI__CONTROL_INTERNAL_H
+
+#include "trace/control.h"
+
+
+QI_IDEF QIEvent* qi_ctrl_event_id(QIEventID id)
+{
+ return (QIEvent*)trace_event_id(id);
+}
+
+QI_IDEF QIEvent* qi_ctrl_event_name(const char *name)
+{
+ return (QIEvent*)trace_event_name(name);
+}
+
+QI_IDEF QIEvent* qi_ctrl_event_pattern(const char *pat, QIEvent *ev)
+{
+ return (QIEvent*)trace_event_pattern(pat, (TraceEvent*)ev);
+}
+
+QI_IDEF bool qi_ctrl_event_is_pattern(const char *str)
+{
+ return trace_event_is_pattern(str);
+}
+
+QI_IDEF QIEventID qi_ctrl_event_count(void)
+{
+ return (QIEventID)trace_event_count();
+}
+
+
+
+QI_IDEF QIEventID qi_ctrl_event_get_id(QIEvent *ev)
+{
+ return (QIEventID)trace_event_get_id((TraceEvent*)ev);
+}
+
+QI_IDEF const char * qi_ctrl_event_get_name(QIEvent *ev)
+{
+ return trace_event_get_name((TraceEvent*)ev);
+}
+
+#endif /* QI__CONTROL_INTERNAL_H */
diff --git a/instrument/qemu-instr/control.h b/instrument/qemu-instr/control.h
new file mode 100644
index 0000000..d3fadd1
--- /dev/null
+++ b/instrument/qemu-instr/control.h
@@ -0,0 +1,124 @@
+/*
+ * Interface for controlling the state of events.
+ *
+ * Copyright (C) 2012-2013 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 QI__CONTROL_H
+#define QI__CONTROL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+
+#include <qemu-instr/config.h>
+#include <qemu-instr/visibility-internal.h>
+#include <qemu-instr/events-list.h>
+
+
+/**
+ * SECTION:control
+ * @section_id: qi-control
+ * @title: QEMU instrumentation event control interface
+ */
+
+/**
+ * QIEvent:
+ *
+ * Opaque structure defining an instrumentation event.
+ */
+struct QIEvent;
+typedef struct QIEvent QIEvent;
+
+/**
+ * QIEventID:
+ *
+ * Unique instrumentation event identifier.
+ *
+ * These are named as 'QI_EVENT_${EVENT}'.
+ *
+ * See also: qemu-instr/events-list.h
+ */
+
+/**
+ * qi_ctrl_event_id:
+ * @id: Event identifier.
+ *
+ * Get an event by its identifier.
+ *
+ * This routine has a constant cost, as opposed to qi_ctrl_event_name() and
+ * qi_ctrl_event_pattern().
+ *
+ * Pre-conditions: @id is valid.
+ *
+ * Returns: Pointer to selected #QIEvent.
+ *
+ */
+QI_IDECL QIEvent* qi_ctrl_event_id(QIEventID id);
+
+/**
+ * qi_ctrl_event_name:
+ * @id: Event name.
+ *
+ * Search an event by its name.
+ *
+ * Returns: Pointer to #QIEvent or #NULL if not found.
+ */
+QI_IDECL QIEvent* qi_ctrl_event_name(const char *name);
+
+/**
+ * qi_ctrl_event_pattern:
+ * @pat: Event name pattern.
+ * @ev: Event to start searching from (not included).
+ *
+ * Iteratively get all events with a given name pattern.
+ *
+ * Returns: pointer to #TraceEvent or #NULL if not found.
+ */
+QI_IDECL QIEvent* qi_ctrl_event_pattern(const char *pat, QIEvent *ev);
+
+/**
+ * qi_ctrl_event_is_pattern:
+ *
+ * Whether the given string is an event name pattern.
+ */
+QI_IDECL bool qi_ctrl_event_is_pattern(const char *str);
+
+/**
+ * qi_ctrl_event_count:
+ *
+ * Return the number of events.
+ */
+QI_IDECL QIEventID qi_ctrl_event_count(void);
+
+
+
+/**
+ * qi_ctrl_event_get_id:
+ *
+ * Get the identifier of an event.
+ */
+QI_IDECL QIEventID qi_ctrl_event_get_id(QIEvent *ev);
+
+/**
+ * qi_ctrl_event_get_name:
+ *
+ * Get the name of an event.
+ */
+QI_IDECL const char * qi_ctrl_event_get_name(QIEvent *ev);
+
+
+#if !defined(QI_TYPE_DYNAMIC)
+#include "instrument/qemu-instr/control-internal.h"
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* QI__CONTROL_H */
diff --git a/instrument/qemu-instr/visibility-internal.h b/instrument/qemu-instr/visibility-internal.h
new file mode 100644
index 0000000..f5a66da
--- /dev/null
+++ b/instrument/qemu-instr/visibility-internal.h
@@ -0,0 +1,94 @@
+/*
+ * Macros for symbol visibility.
+ *
+ * Copyright (C) 2012-2013 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 of QEMU.
+ */
+
+#ifndef QI__VISIBILITY_INTERNAL_H
+#define QI__VISIBILITY_INTERNAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <qemu-instr/config.h>
+
+
+/**
+ * SECTION:visibility
+ * @section_id: qi-visibility
+ * @title: Symbol visibility
+ *
+ * This code is taken from http://gcc.gnu.org/wiki/Visibility.
+ */
+
+/**
+ * QI_VPUBLIC:
+ *
+ * Make an element public to third-party code.
+ */
+
+/**
+ * QI_VLOCAL:
+ *
+ * Make an element not visible to third-party code.
+ */
+
+#if defined _WIN32 || defined __CYGWIN__
+ #ifdef BUILDING_QEMU
+ #ifdef __GNUC__
+ #define QI_VPUBLIC __attribute__ ((dllexport))
+ #else
+ #define QI_VPUBLIC __declspec(dllexport)
+ #endif
+ #else
+ #ifdef __GNUC__
+ #define QI_VPUBLIC __attribute__ ((dllimport))
+ #else
+ #define QI_VPUBLIC __declspec(dllimport)
+ #endif
+ #endif
+ #define QI_VLOCAL
+#else
+ #if __GNUC__ >= 4
+ #define QI_VPUBLIC __attribute__ ((visibility ("default")))
+ #define QI_VLOCAL __attribute__ ((visibility ("hidden")))
+ #else
+ #define QI_VPUBLIC
+ #define QI_VLOCAL
+ #endif
+#endif
+
+/**
+ * QI_IDECL:
+ *
+ * Instrumentation-type dependant declaration attribute for inlined routines.
+ */
+
+#if defined(QI_TYPE_DYNAMIC)
+#define QI_IDECL QI_VPUBLIC
+#else
+#define QI_IDECL static
+#endif
+
+/**
+ * QI_IDEF:
+ *
+ * Instrumentation-type dependant definition attribute for inlined routines.
+ */
+
+#if defined(QI_TYPE_DYNAMIC)
+#define QI_IDEF
+#else
+#define QI_IDEF static inline
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* QI__VISIBILITY_INTERNAL_H */
diff --git a/scripts/tracetool/backend/instr_dynamic.py b/scripts/tracetool/backend/instr_dynamic.py
index 12d0503..013893a 100644
--- a/scripts/tracetool/backend/instr_dynamic.py
+++ b/scripts/tracetool/backend/instr_dynamic.py
@@ -88,3 +88,6 @@ def api_c(events):
args = e.args,
argnames = ", ".join(e.args.names()),
)
+
+def api_events_h(events):
+ pass
diff --git a/scripts/tracetool/backend/instr_none.py b/scripts/tracetool/backend/instr_none.py
index a1327c0..2c2fe68 100644
--- a/scripts/tracetool/backend/instr_none.py
+++ b/scripts/tracetool/backend/instr_none.py
@@ -39,3 +39,6 @@ def api_h(events):
qemu_backend = e.api(e.QEMU_TRACE_BACKEND),
argnames = ", ".join(e.args.names()),
)
+
+def api_events_h(events):
+ pass
diff --git a/scripts/tracetool/backend/instr_static.py b/scripts/tracetool/backend/instr_static.py
index ecebbda..df99656 100644
--- a/scripts/tracetool/backend/instr_static.py
+++ b/scripts/tracetool/backend/instr_static.py
@@ -77,3 +77,6 @@ def api_h(events):
argnames = ", ".join(e.args.names()),
upper_name = e.name.upper(),
)
+
+def api_events_h(events):
+ pass
diff --git a/scripts/tracetool/format/api_events_h.py b/scripts/tracetool/format/api_events_h.py
new file mode 100644
index 0000000..95a4e93
--- /dev/null
+++ b/scripts/tracetool/format/api_events_h.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .h with event description for trace instrumentation clients.
+"""
+
+__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__ = "Copyright 2012-2013, Lluís Vilanova <vilanova@ac.upc.edu>"
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@linux.vnet.ibm.com"
+
+
+from tracetool import out
+
+
+def begin(events):
+ out('/* This file is autogenerated by tracetool, do not edit. */',
+ '',
+ '#ifndef QI__EVENTS_LIST_H',
+ '#define QI__EVENTS_LIST_H',
+ '',
+ '#ifdef __cplusplus',
+ 'extern "C" {',
+ '#endif',
+ '',
+ )
+
+ # event identifiers
+ out('typedef enum {')
+
+ for e in events:
+ out(' QI_EVENT_%s,' % e.name.upper())
+
+ out(' QI_EVENT_COUNT',
+ '} QIEventID;',
+ '',
+ )
+
+ # static state
+ for e in events:
+ if 'disable' in e.properties:
+ enabled = 0
+ else:
+ enabled = 1
+ out('#define QI_EVENT_%s_ENABLED %d' % (e.name.upper(), enabled))
+
+ out('#ifdef __cplusplus',
+ '}',
+ '#endif',
+ '',
+ '#endif /* QI__EVENTS_LIST_H */',
+ '',
+ )
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 19/23] instrument: Add client-side API to control tracing state of events
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (17 preceding siblings ...)
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 18/23] instrument: Add client-side API to enumerate events Lluís Vilanova
@ 2013-04-16 13:51 ` Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 20/23] instrument: Add client-side API to control event instrumentation Lluís Vilanova
` (4 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:51 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
instrument/Makefile.objs | 1
instrument/api-trace.c | 14 +++++
instrument/qemu-instr/trace-internal.h | 32 +++++++++++
instrument/qemu-instr/trace.h | 91 ++++++++++++++++++++++++++++++++
4 files changed, 138 insertions(+)
create mode 100644 instrument/api-trace.c
create mode 100644 instrument/qemu-instr/trace-internal.h
create mode 100644 instrument/qemu-instr/trace.h
diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs
index 1438626..527d68f 100644
--- a/instrument/Makefile.objs
+++ b/instrument/Makefile.objs
@@ -82,5 +82,6 @@ common-obj-$(CONFIG_SOFTMMU) += hmp.o
common-obj-$(CONFIG_SOFTMMU) += qmp.o
target-obj-y += api-control.o
+target-obj-y += api-trace.o
QEMU_CFLAGS += -I$(BUILD_DIR)/instrument -I$(SRC_PATH)/instrument
diff --git a/instrument/api-trace.c b/instrument/api-trace.c
new file mode 100644
index 0000000..688ac52
--- /dev/null
+++ b/instrument/api-trace.c
@@ -0,0 +1,14 @@
+/*
+ * Interface for controlling the tracing state of events.
+ *
+ * Copyright (C) 2012-2013 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 "instrument/qemu-instr/trace.h"
+
+#if defined(QI_TYPE_DYNAMIC)
+#include "instrument/qemu-instr/trace-internal.h"
+#endif
diff --git a/instrument/qemu-instr/trace-internal.h b/instrument/qemu-instr/trace-internal.h
new file mode 100644
index 0000000..2d6eec4
--- /dev/null
+++ b/instrument/qemu-instr/trace-internal.h
@@ -0,0 +1,32 @@
+/*
+ * Interface for controlling the tracing state of events.
+ *
+ * Copyright (C) 2012-2013 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 QI__TRACE_INTERNAL_H
+#define QI__TRACE_INTERNAL_H
+
+#include "trace/control.h"
+
+
+QI_IDEF bool qi_trace_event_get_state_static(QIEvent *ev)
+{
+ return trace_event_get_state_static((TraceEvent*)ev);
+}
+
+QI_IDEF bool qi_trace_event_get_state_dynamic(QIEvent *ev)
+{
+ return trace_event_get_state_dynamic((TraceEvent*)ev);
+}
+
+QI_IDEF void qi_trace_event_set_state_dynamic(QIEvent *ev, bool state)
+{
+ assert(qi_trace_event_get_state_static(ev));
+ return trace_event_set_state_dynamic((TraceEvent*)ev, state);
+}
+
+#endif /* QI__TRACE_INTERNAL_H */
diff --git a/instrument/qemu-instr/trace.h b/instrument/qemu-instr/trace.h
new file mode 100644
index 0000000..ddd343f
--- /dev/null
+++ b/instrument/qemu-instr/trace.h
@@ -0,0 +1,91 @@
+/*
+ * Interface for controlling the tracing state of events.
+ *
+ * Copyright (C) 2012-2013 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 QI__TRACE_H
+#define QI__TRACE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+
+#include <qemu-instr/control.h>
+
+
+/**
+ * SECTION: trace
+ * @section_id: qi-trace
+ * @title: QEMU tracing event control interface
+ */
+
+/**
+ * qi_trace_event_get_state:
+ * @id: Event identifier.
+ *
+ * Get the tracing state of an event (both static and dynamic).
+ *
+ * If the event has the disabled property, the check will have no performance
+ * impact.
+ *
+ * As a down side, you must always use an immediate #QIEventID value.
+ */
+#define qi_trace_event_get_state(id) \
+ ((id ##_ENABLED) && qi_trace_event_get_state_dynamic(qi_ctrl_event_id(id)))
+
+/**
+ * qi_trace_event_get_state_static:
+ * @id: Event identifier.
+ *
+ * Get the static tracing state of an event.
+ *
+ * Use the define 'QI_EVENT_${EVENT}_ENABLED' for compile-time checks (it will
+ * be set to 1 or 0 according to the presence of the disabled property).
+ */
+QI_IDECL bool qi_trace_event_get_state_static(QIEvent *ev);
+
+/**
+ * qi_trace_event_get_state_dynamic:
+ *
+ * Get the dynamic tracing state of an event.
+ */
+QI_IDECL bool qi_trace_event_get_state_dynamic(QIEvent *ev);
+
+/**
+ * qi_trace_event_set_state:
+ *
+ * Set the tracing state of an event.
+ */
+#define qi_trace_event_set_state(id, state) \
+ do { \
+ if ((id ##_ENABLED)) { \
+ QIEvent *_e = qi_ctrl_event_id(id); \
+ qi_trace_event_set_state_dynamic(_e, state); \
+ } \
+ } while (0)
+
+/**
+ * qi_trace_event_set_state_dynamic:
+ *
+ * Set the dynamic tracing state of an event.
+ *
+ * Pre-condition: qi_trace_event_get_state_static(ev) == true
+ */
+QI_IDECL void qi_trace_event_set_state_dynamic(QIEvent *ev, bool state);
+
+
+#if !defined(QI_TYPE_DYNAMIC)
+#include "instrument/qemu-instr/trace-internal.h"
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* QI__TRACE_H */
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 20/23] instrument: Add client-side API to control event instrumentation
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (18 preceding siblings ...)
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 19/23] instrument: Add client-side API to control tracing state of events Lluís Vilanova
@ 2013-04-16 13:51 ` Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 21/23] build: Fix installation of target-dependant files Lluís Vilanova
` (3 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:51 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
instrument/qemu-instr/control-internal.h | 16 ++++++++
instrument/qemu-instr/control.h | 61 ++++++++++++++++++++++++++++++
2 files changed, 77 insertions(+)
diff --git a/instrument/qemu-instr/control-internal.h b/instrument/qemu-instr/control-internal.h
index 6e419e7..0ddbc74 100644
--- a/instrument/qemu-instr/control-internal.h
+++ b/instrument/qemu-instr/control-internal.h
@@ -11,6 +11,7 @@
#define QI__CONTROL_INTERNAL_H
#include "trace/control.h"
+#include "instrument/control.h"
QI_IDEF QIEvent* qi_ctrl_event_id(QIEventID id)
@@ -38,6 +39,16 @@ QI_IDEF QIEventID qi_ctrl_event_count(void)
return (QIEventID)trace_event_count();
}
+QI_IDEF bool qi_ctrl_dynamic(void)
+{
+ return instr_dynamic();
+}
+
+QI_IDEF bool qi_ctrl_event_is_available(QIEvent *ev)
+{
+ return instr_event_available((TraceEvent*)ev);
+}
+
QI_IDEF QIEventID qi_ctrl_event_get_id(QIEvent *ev)
@@ -50,4 +61,9 @@ QI_IDEF const char * qi_ctrl_event_get_name(QIEvent *ev)
return trace_event_get_name((TraceEvent*)ev);
}
+QI_IDEF bool qi_ctrl_event_set(QIEvent *ev, void *cb)
+{
+ return instr_event_set((TraceEvent*)ev, cb);
+}
+
#endif /* QI__CONTROL_INTERNAL_H */
diff --git a/instrument/qemu-instr/control.h b/instrument/qemu-instr/control.h
index d3fadd1..3509b71 100644
--- a/instrument/qemu-instr/control.h
+++ b/instrument/qemu-instr/control.h
@@ -96,6 +96,13 @@ QI_IDECL bool qi_ctrl_event_is_pattern(const char *str);
*/
QI_IDECL QIEventID qi_ctrl_event_count(void);
+/**
+ * qi_ctrl_dynamic:
+ *
+ * Returns: Whether dynamic trace instrumentation is available.
+ */
+QI_IDECL bool qi_ctrl_dynamic(void);
+
/**
@@ -112,6 +119,60 @@ QI_IDECL QIEventID qi_ctrl_event_get_id(QIEvent *ev);
*/
QI_IDECL const char * qi_ctrl_event_get_name(QIEvent *ev);
+/**
+ * qi_ctrl_event_is_available:
+ *
+ * Returns: Whether the given event has the 'instrument' property.
+ */
+QI_IDECL bool qi_ctrl_event_is_available(QIEvent *ev);
+
+
+/**
+ * QI_CTRL_INSTR_NOP:
+ *
+ * Set instrumentation callback to no-operation.
+ * (qi_event_${name}_nop).
+ */
+#define QI_CTRL_INSTR_NOP ((void*)NULL)
+
+/**
+ * QI_CTRL_INSTR_NEXT:
+ *
+ * Set instrumentation callback to the "next logical step"
+ * (qi_event_${name}_trace).
+ */
+#define QI_CTRL_INSTR_NEXT ((void*)1)
+
+/**
+ * QI_CTRL_INSTR_AUTO:
+ *
+ * Automatically set callback to proper routine.
+ *
+ * Looks for a symbol name in the instrumentation library matching the event
+ * name (qi_event_${name}).
+ */
+#define QI_CTRL_INSTR_AUTO ((void*)2)
+
+/**
+ * qi_ctrl_event_set:
+ * @ev: Event descriptor.
+ * @cb: Pointer to instrumentation callback.
+ *
+ * Set the instrumentation callback for the given event.
+ *
+ * @cb can also be set to any of the QI_CTRL_INSTR_* special values.
+ *
+ * #false indicates that the instrumentation library does not export the
+ * appropriate symbol for the instrumentation routine.
+ *
+ * Pre-condition: qi_ctrl_dynamic() == true
+ * Pre-condition: qi_ctrl_event_is_available(ev) == true
+ *
+ * Returns: Whether the callback could be set (if @cb was QI_CTRL_INSTR_AUTO,
+ * otherwise always #true).
+ */
+QI_IDECL bool qi_ctrl_event_set(QIEvent *ev, void *cb);
+
#if !defined(QI_TYPE_DYNAMIC)
#include "instrument/qemu-instr/control-internal.h"
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 21/23] build: Fix installation of target-dependant files
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (19 preceding siblings ...)
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 20/23] instrument: Add client-side API to control event instrumentation Lluís Vilanova
@ 2013-04-16 13:51 ` Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 22/23] instrument: Install headers for dynamic instrumentation clients Lluís Vilanova
` (2 subsequent siblings)
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:51 UTC (permalink / raw)
To: qemu-devel
Pass all the relevant sub-directory make variables.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
Cc: Anthony Liguori <aliguori@us.ibm.com>
Cc: Paul Brook <paul@codesourcery.com>
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 7916152..ccf6760 100644
--- a/Makefile
+++ b/Makefile
@@ -346,7 +346,7 @@ endif
$(INSTALL_DATA) $(SRC_PATH)/pc-bios/keymaps/$$x "$(DESTDIR)$(qemu_datadir)/keymaps"; \
done
for d in $(TARGET_DIRS); do \
- $(MAKE) -C $$d $@ || exit 1 ; \
+ $(MAKE) $(SUBDIR_MAKEFLAGS) TARGET_DIR=$$d/ -C $$d $@ || exit 1 ; \
done
# various test targets
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 22/23] instrument: Install headers for dynamic instrumentation clients
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (20 preceding siblings ...)
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 21/23] build: Fix installation of target-dependant files Lluís Vilanova
@ 2013-04-16 13:51 ` Lluís Vilanova
2013-04-16 13:52 ` [Qemu-devel] [PATCH v2 23/23] trace: Do not use the word 'new' in event arguments Lluís Vilanova
2013-04-16 20:52 ` [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:51 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
Makefile | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index ccf6760..3fc5fb6 100644
--- a/Makefile
+++ b/Makefile
@@ -324,7 +324,29 @@ install-confdir:
install-sysconfig: install-datadir install-confdir
$(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(DESTDIR)$(qemu_confdir)"
-install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig install-datadir
+install_instrument_find=$(shell find $(1)/instrument/qemu-instr -type f -name \*.h)
+
+install-instrument: INSTALL_FILES =$(call install_instrument_find,$(SRC_PATH))
+install-instrument: INSTALL_FILES+=$(call install_instrument_find,$(BUILD_DIR))
+install-instrument: INSTALL_DIRS:=$(dir $(INSTALL_FILES))
+install-instrument: INSTALL_DIRS:=$(patsubst $(SRC_PATH)/instrument/%,$(DESTDIR)$(includedir)/%,$(INSTALL_DIRS))
+install-instrument: INSTALL_DIRS:=$(patsubst $(BUILD_DIR)/instrument/%,$(DESTDIR)$(includedir)/%,$(INSTALL_DIRS))
+install-instrument: INSTALL_DIRS:=$(sort $(INSTALL_DIRS))
+install-instrument:
+ @for d in $(INSTALL_DIRS); do \
+ echo "$(INSTALL_DIR) \"$$d\""; \
+ $(INSTALL_DIR) "$$d"; \
+ done
+ @for f in $(INSTALL_FILES); do \
+ echo "$(INSTALL_DATA) \"$$f\" \"$(DESTDIR)$(includedir)/qemu-instr/$${f##*qemu-instr/}\""; \
+ $(INSTALL_DATA) "$$f" "$(DESTDIR)$(includedir)/qemu-instr/$${f##*qemu-instr/}"; \
+ done
+
+ifdef CONFIG_TRACE_INSTRUMENT_DYNAMIC
+INSTALL_INSTRUMENT=install-instrument
+endif
+
+install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig install-datadir $(INSTALL_INSTRUMENT)
$(INSTALL_DIR) "$(DESTDIR)$(bindir)"
ifneq ($(TOOLS),)
$(INSTALL_PROG) $(STRIP_OPT) $(TOOLS) "$(DESTDIR)$(bindir)"
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [Qemu-devel] [PATCH v2 23/23] trace: Do not use the word 'new' in event arguments
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (21 preceding siblings ...)
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 22/23] instrument: Install headers for dynamic instrumentation clients Lluís Vilanova
@ 2013-04-16 13:52 ` Lluís Vilanova
2013-04-16 20:52 ` [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 13:52 UTC (permalink / raw)
To: qemu-devel
This lets instrumentation clients in C++ use the auto-generated headers.
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
scripts/tracetool/__init__.py | 16 +++++++++++++++-
trace-events | 8 ++++----
2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py
index 7624982..851be4d 100644
--- a/scripts/tracetool/__init__.py
+++ b/scripts/tracetool/__init__.py
@@ -40,6 +40,14 @@ def out(*lines, **kwargs):
sys.stdout.writelines("\n".join(lines) + "\n")
+FORBIDDEN = [ "new" ]
+
+class ForbiddenArgumentError (Exception):
+ def __init__ (self, name):
+ self.name = name
+ def __str__ (self):
+ return "Cannot use forbidden argument name: %s" % self.name
+
class Arguments:
"""Event arguments description."""
@@ -74,6 +82,9 @@ class Arguments:
else:
arg_type, identifier = arg.rsplit(None, 1)
+ if identifier in FORBIDDEN:
+ raise ForbiddenArgumentError(identifier)
+
res.append((arg_type, identifier))
return Arguments(res)
@@ -165,7 +176,10 @@ class Event(object):
name = groups["name"]
props = groups["props"].split()
fmt = groups["fmt"]
- args = Arguments.build(groups["args"])
+ try:
+ args = Arguments.build(groups["args"])
+ except ForbiddenArgumentError as e:
+ error("Error: event '%s' uses forbidden argument name '%s'" % (name, e.name))
return Event(name, props, fmt, args)
diff --git a/trace-events b/trace-events
index 412f7e4..eb7dd93 100644
--- a/trace-events
+++ b/trace-events
@@ -187,7 +187,7 @@ hd_geometry_guess(void *bs, uint32_t cyls, uint32_t heads, uint32_t secs, int tr
# hw/jazz-led.c
jazz_led_read(uint64_t addr, uint8_t val) "read addr=0x%"PRIx64": 0x%x"
-jazz_led_write(uint64_t addr, uint8_t new) "write addr=0x%"PRIx64": 0x%x"
+jazz_led_write(uint64_t addr, uint8_t new_) "write addr=0x%"PRIx64": 0x%x"
# hw/lance.c
lance_mem_readw(uint64_t addr, uint32_t ret) "addr=%"PRIx64"val=0x%04x"
@@ -285,10 +285,10 @@ usb_port_release(int bus, const char *port) "bus %d, port %s"
usb_ehci_reset(void) "=== RESET ==="
usb_ehci_opreg_read(uint32_t addr, const char *str, uint32_t val) "rd mmio %04x [%s] = %x"
usb_ehci_opreg_write(uint32_t addr, const char *str, uint32_t val) "wr mmio %04x [%s] = %x"
-usb_ehci_opreg_change(uint32_t addr, const char *str, uint32_t new, uint32_t old) "ch mmio %04x [%s] = %x (old: %x)"
+usb_ehci_opreg_change(uint32_t addr, const char *str, uint32_t new_, uint32_t old) "ch mmio %04x [%s] = %x (old: %x)"
usb_ehci_portsc_read(uint32_t addr, uint32_t port, uint32_t val) "rd mmio %04x [port %d] = %x"
usb_ehci_portsc_write(uint32_t addr, uint32_t port, uint32_t val) "wr mmio %04x [port %d] = %x"
-usb_ehci_portsc_change(uint32_t addr, uint32_t port, uint32_t new, uint32_t old) "ch mmio %04x [port %d] = %x (old: %x)"
+usb_ehci_portsc_change(uint32_t addr, uint32_t port, uint32_t new_, uint32_t old) "ch mmio %04x [port %d] = %x (old: %x)"
usb_ehci_usbsts(const char *sts, int state) "usbsts %s %d"
usb_ehci_state(const char *schedule, const char *state) "%s schedule %s"
usb_ehci_qh_ptrs(void *q, uint32_t addr, uint32_t nxt, uint32_t c_qtd, uint32_t n_qtd, uint32_t a_qtd) "q %p - QH @ %08x: next %08x qtds %08x,%08x,%08x"
@@ -530,7 +530,7 @@ qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s
# hw/g364fb.c
g364fb_read(uint64_t addr, uint32_t val) "read addr=0x%"PRIx64": 0x%x"
-g364fb_write(uint64_t addr, uint32_t new) "write addr=0x%"PRIx64": 0x%x"
+g364fb_write(uint64_t addr, uint32_t val) "write addr=0x%"PRIx64": 0x%x"
# hw/grlib_gptimer.c
grlib_gptimer_enable(int id, uint32_t count) "timer:%d set count 0x%x and run"
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
` (22 preceding siblings ...)
2013-04-16 13:52 ` [Qemu-devel] [PATCH v2 23/23] trace: Do not use the word 'new' in event arguments Lluís Vilanova
@ 2013-04-16 20:52 ` Lluís Vilanova
23 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-16 20:52 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanha
Sorry Stefan; I had an error with stg and did not CC you.
Just tell me if you want me to re-send with proper headers.
Lluis
--
"And it's much the same thing with knowledge, for whenever you learn
something new, the whole world becomes that much richer."
-- The Princess of Pure Reason, as told by Norton Juster in The Phantom
Tollbooth
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [PATCH v2 13/23] qapi: Add a primitive to include other files from a QAPI schema file
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 13/23] qapi: Add a primitive to include other files from a QAPI schema file Lluís Vilanova
@ 2013-04-19 2:49 ` Eric Blake
2013-04-19 12:21 ` Lluís Vilanova
0 siblings, 1 reply; 31+ messages in thread
From: Eric Blake @ 2013-04-19 2:49 UTC (permalink / raw)
To: Lluís Vilanova; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 315 bytes --]
On 04/16/2013 07:51 AM, Lluís Vilanova wrote:
> Adds the "input(...)" primitive to the syntax of QAPI schema files.
Interesting idea, but isn't "include(...)" a more common name than
"input(...)"?
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [PATCH v2 15/23] instrument: [qmp, qapi] Add control interface
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 15/23] instrument: [qmp, qapi] Add control interface Lluís Vilanova
@ 2013-04-19 3:07 ` Eric Blake
2013-04-19 23:46 ` Lluís Vilanova
0 siblings, 1 reply; 31+ messages in thread
From: Eric Blake @ 2013-04-19 3:07 UTC (permalink / raw)
To: Lluís Vilanova; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 5217 bytes --]
On 04/16/2013 07:51 AM, Lluís Vilanova wrote:
> Add QMP commands to control (un)loading of dynamic instrumentation library.
>
> Signed-off-by: Lluís Vilanova <vilanova@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"
These days, it is generally easier to just use error_setg() instead of
defining new QERR_ constants, unless you reuse an error so frequently
that having a QERR_ constant ensures that all use sites have consistent
wording of the message.
> +++ b/instrument/qapi-schema.json
> @@ -0,0 +1,33 @@
> +# *-*- Mode: Python -*-*
> +
New files should generally come with a copyright statement and clear
licensing terms. Not entirely your fault since qapi-schema.json lacks a
copyright statement, but worth thinking about.
> +##
> +# @instr-dynamic:
> +#
> +# Whether dynamic trace instrumentation is available.
> +#
> +# Since: 1.5
> +##
> +{ 'command': 'instr-dynamic',
> + 'returns': 'bool' }
Perhaps naming this 'query-instr' is nicer, to match existing qemu
commands that can query state. Then again, keeping all instrumentation
commands under the intsr- prefix makes them group together, while using
query-instr would not.
Is the abbreviation 'intsr-' appropriate, or should we be using the full
word 'instrument-'?
Is returning a bool going to make it harder to expand this command in
the future to return additional (optional) information, such as the name
of the current loaded library? Is it worth returning a full-blown
dictionary type, so that we can add other name-value pairs into the
return as needed? Is it reasonable to give instrumentation libraries a
callback hook that they can use to optionally generate additional
information to be returned as part of this query?
> +
> +##
> +# @instr-load:
> +#
> +# Load a dynamic instrumentation library.
> +#
> +# @path: path to the dynamic instrumentation library
Generally a blank line between arguments.
> +# @iargs: arguments to the dynamic instrumentation library
Any reason you named this 'iargs' instead of the simpler 'args'?
> +#
> +# Since: 1.5
> +##
> +{ 'command': 'instr-load',
> + 'data': { 'path': 'str', 'iargs': ['String'] } }
There's another thread going on right now about fixing the generator to
let us use the much simpler ['str'] instead of having to go through the
extra layer of the wrapper type 'String'.
@iargs should be optional (#optional in the comment, listed as '*iargs'
in the JSON form); where omitting it is shorthand for [ ].
Should you return a handle representing the library that got loaded? By
returning nothing, you have permanently limited this command to only
being able to load one library at a time. But if we return a handle,
and make instr-unload take a handle argument, then even if we choose to
support only one library at a time now, later on, we will have the
option of extending things to support parallel libraries at once without
having to invent new commands.
> +
> +##
> +# @instr-unload:
> +#
> +# Unload the current dynamic instrumentation library.
> +#
> +# Since: 1.5
> +##
> +{ 'command': 'instr-unload' }
See above for comments about whether this should take an argument of the
handle returned from the load command.
> diff --git a/instrument/qmp.c b/instrument/qmp.c
> +++ b/qapi-schema.json
> @@ -3513,3 +3513,5 @@
> '*asl_compiler_rev': 'uint32',
> '*file': 'str',
> '*data': 'str' }}
> +
> +input("instrument/qapi-schema.json")
See my comments on 13/23 about possibly naming this include() instead of
input().
> +Example:
> +
> +-> { "execute": "instr-load", "arguments": { "path": "/tmp/libtrace-instrument.so" } }
This example does not match the JSON listed above, because it omits the
mandatory 'iargs':[ ].
> +++ 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)
I don't know whether qemu coding style prefers to use #ifdef foo instead
of #if defined(foo) when there is only a single item being tested for
definedness.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [PATCH v2 17/23] instrument: Add commandline options to start with an instrumentation library
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 17/23] instrument: Add commandline options to start with an instrumentation library Lluís Vilanova
@ 2013-04-19 3:28 ` Eric Blake
2013-04-20 0:42 ` Lluís Vilanova
0 siblings, 1 reply; 31+ messages in thread
From: Eric Blake @ 2013-04-19 3:28 UTC (permalink / raw)
To: Lluís Vilanova; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 2448 bytes --]
On 04/16/2013 07:51 AM, Lluís Vilanova wrote:
> Add commandline options to control initial loading of dynamic instrumentation
> library.
>
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
> @@ -688,6 +690,15 @@ static void usage(void)
> #endif
> "-bsd type select emulated BSD type FreeBSD/NetBSD/OpenBSD (default)\n"
> "\n"
> +#if defined(CONFIG_TRACE_INSTRUMENT)
> + "Tracing options:\n"
> +#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
> + "-instr path load a dynamic trace instrumentation library\n"
> +#endif
> + "-instr-arg string\n"
> + " argument to dynamic trace instrumentation library (can be given multiple times)\n"
> + "\n"
Why do you document -instr-arg unconditionally, but -instr only when
dynamic trace support is enabled; especially since the text of
-instr-arg mentions that it is tied to dynamic tracing?
> @@ -852,6 +866,14 @@ int main(int argc, char **argv)
> singlestep = 1;
> } else if (!strcmp(r, "strace")) {
> do_strace = 1;
> +#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
> + } else if (!strcmp(r, "instr")) {
> + instrument_path = argv[optind++];
> +#endif
> +#if defined(CONFIG_TRACE_INSTRUMENT)
> + } else if (!strcmp(r, "instr-arg")) {
> + instr_parse_args(argv[optind++], &instrument_argc, &instrument_argv);
> +#endif
At least your parsing code matches your documentation, but it still
feels weird.
> @@ -3378,6 +3397,14 @@ static const struct qemu_argument arg_table[] = {
> {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
> "size", "reserve 'size' bytes for guest virtual address space"},
> #endif
> +#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
> + {"instr", "QEMU_INSTR", true, handle_arg_instrument,
> + "path", "load a dynamic trace instrumentation library"},
> +#endif
> +#if defined(CONFIG_TRACE_INSTRUMENT)
> + {"instr-arg", "QEMU_INSTR_ARGS", true, handle_arg_instrument_arg,
> + "string", "argument to dynamic trace instrumentation library (can be given multiple times)"},
Another case of mentioning the term dynamic even when dynamic
instrumentation is not enabled.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [PATCH v2 13/23] qapi: Add a primitive to include other files from a QAPI schema file
2013-04-19 2:49 ` Eric Blake
@ 2013-04-19 12:21 ` Lluís Vilanova
0 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-19 12:21 UTC (permalink / raw)
To: Eric Blake; +Cc: qemu-devel
Eric Blake writes:
> On 04/16/2013 07:51 AM, Lluís Vilanova wrote:
>> Adds the "input(...)" primitive to the syntax of QAPI schema files.
> Interesting idea, but isn't "include(...)" a more common name than
> "input(...)"?
Indeed it is. Thanks for the catch.
Lluis
--
"And it's much the same thing with knowledge, for whenever you learn
something new, the whole world becomes that much richer."
-- The Princess of Pure Reason, as told by Norton Juster in The Phantom
Tollbooth
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [PATCH v2 15/23] instrument: [qmp, qapi] Add control interface
2013-04-19 3:07 ` Eric Blake
@ 2013-04-19 23:46 ` Lluís Vilanova
0 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-19 23:46 UTC (permalink / raw)
To: Eric Blake; +Cc: qemu-devel
Anything not commented inline has been changed according to your feedback.
Eric Blake writes:
[...]
>> +##
>> +# @instr-dynamic:
>> +#
>> +# Whether dynamic trace instrumentation is available.
>> +#
>> +# Since: 1.5
>> +##
>> +{ 'command': 'instr-dynamic',
>> + 'returns': 'bool' }
> Perhaps naming this 'query-instr' is nicer, to match existing qemu
> commands that can query state. Then again, keeping all instrumentation
> commands under the intsr- prefix makes them group together, while using
> query-instr would not.
I leaned towards having a common prefix for all commands, so that they're easier
to remember/find.
> Is the abbreviation 'intsr-' appropriate, or should we be using the full
> word 'instrument-'?
It uses the same prefix as the C routines, which are shorter to avoid too much
typing.
> Is returning a bool going to make it harder to expand this command in
> the future to return additional (optional) information, such as the name
> of the current loaded library? Is it worth returning a full-blown
> dictionary type, so that we can add other name-value pairs into the
> return as needed?
The command is now 'instr-query', and returns both the available type (none,
static, dynamic), and whether it's currently "active".
> Is it reasonable to give instrumentation libraries a callback hook that they
> can use to optionally generate additional information to be returned as part
> of this query?
Hmmm, letting the instrumentation library to interact both ways with QEMU
through QAPI would be an interesting feature. But I'd like to keep this first
implementation as simple as possible regarding this, and instead concentrate on
the instrumentation functionalities.
Such features can be added later, when the main ideas have been seen fit for
landing upstream.
[...]
>> +# @iargs: arguments to the dynamic instrumentation library
> Any reason you named this 'iargs' instead of the simpler 'args'?
Yes; the auto-generated code already uses "args" internally. I've fixed it to
allow "args".
>> +#
>> +# Since: 1.5
>> +##
>> +{ 'command': 'instr-load',
>> + 'data': { 'path': 'str', 'iargs': ['String'] } }
> There's another thread going on right now about fixing the generator to
> let us use the much simpler ['str'] instead of having to go through the
> extra layer of the wrapper type 'String'.
> @iargs should be optional (#optional in the comment, listed as '*iargs'
> in the JSON form); where omitting it is shorthand for [ ].
Ok, I thought a list was empty by default when no contents were given to it. It
is now optional.
> Should you return a handle representing the library that got loaded? By
> returning nothing, you have permanently limited this command to only
> being able to load one library at a time. But if we return a handle,
> and make instr-unload take a handle argument, then even if we choose to
> support only one library at a time now, later on, we will have the
> option of extending things to support parallel libraries at once without
> having to invent new commands.
The return structure contains an integer handle, now, together with some other
information.
[...]
>> +++ 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)
> I don't know whether qemu coding style prefers to use #ifdef foo instead
> of #if defined(foo) when there is only a single item being tested for
> definedness.
I have no strong opinion on either side, so for now I've left it as it is.
Thanks a lot for the review.
Lluis
--
"And it's much the same thing with knowledge, for whenever you learn
something new, the whole world becomes that much richer."
-- The Princess of Pure Reason, as told by Norton Juster in The Phantom
Tollbooth
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [Qemu-devel] [PATCH v2 17/23] instrument: Add commandline options to start with an instrumentation library
2013-04-19 3:28 ` Eric Blake
@ 2013-04-20 0:42 ` Lluís Vilanova
0 siblings, 0 replies; 31+ messages in thread
From: Lluís Vilanova @ 2013-04-20 0:42 UTC (permalink / raw)
To: Eric Blake; +Cc: qemu-devel
Eric Blake writes:
> On 04/16/2013 07:51 AM, Lluís Vilanova wrote:
>> Add commandline options to control initial loading of dynamic instrumentation
>> library.
>>
>> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
>> ---
>> @@ -688,6 +690,15 @@ static void usage(void)
>> #endif
>> "-bsd type select emulated BSD type FreeBSD/NetBSD/OpenBSD (default)\n"
>> "\n"
>> +#if defined(CONFIG_TRACE_INSTRUMENT)
>> + "Tracing options:\n"
>> +#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
>> + "-instr path load a dynamic trace instrumentation library\n"
>> +#endif
>> + "-instr-arg string\n"
>> + " argument to dynamic trace instrumentation library (can be given multiple times)\n"
>> + "\n"
> Why do you document -instr-arg unconditionally, but -instr only when
> dynamic trace support is enabled; especially since the text of
> -instr-arg mentions that it is tied to dynamic tracing?
>> @@ -852,6 +866,14 @@ int main(int argc, char **argv)
>> singlestep = 1;
>> } else if (!strcmp(r, "strace")) {
>> do_strace = 1;
>> +#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
>> + } else if (!strcmp(r, "instr")) {
>> + instrument_path = argv[optind++];
>> +#endif
>> +#if defined(CONFIG_TRACE_INSTRUMENT)
>> + } else if (!strcmp(r, "instr-arg")) {
>> + instr_parse_args(argv[optind++], &instrument_argc, &instrument_argv);
>> +#endif
> At least your parsing code matches your documentation, but it still
> feels weird.
You cannot load a library in non-dynamic mode, but you can still pass it some
arguments if it's in static mode (CONFIG_TRACE_INSTRUMENT accounts for all
cases), thus the "weirdness" :)
>> @@ -3378,6 +3397,14 @@ static const struct qemu_argument arg_table[] = {
>> {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
>> "size", "reserve 'size' bytes for guest virtual address space"},
>> #endif
>> +#if defined(CONFIG_TRACE_INSTRUMENT_DYNAMIC)
>> + {"instr", "QEMU_INSTR", true, handle_arg_instrument,
>> + "path", "load a dynamic trace instrumentation library"},
>> +#endif
>> +#if defined(CONFIG_TRACE_INSTRUMENT)
>> + {"instr-arg", "QEMU_INSTR_ARGS", true, handle_arg_instrument_arg,
>> + "string", "argument to dynamic trace instrumentation library (can be given multiple times)"},
> Another case of mentioning the term dynamic even when dynamic
> instrumentation is not enabled.
Fixed.
Thanks a lot,
Lluis
--
"And it's much the same thing with knowledge, for whenever you learn
something new, the whole world becomes that much richer."
-- The Princess of Pure Reason, as told by Norton Juster in The Phantom
Tollbooth
^ permalink raw reply [flat|nested] 31+ messages in thread
end of thread, other threads:[~2013-04-20 0:42 UTC | newest]
Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-16 13:49 [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
2013-04-16 13:49 ` [Qemu-devel] [PATCH v2 01/23] instrument: Add documentation Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 02/23] trace: [simple] Do not include "trace/simple.h" in generated tracer headers Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 03/23] trace: Let the user specify her own trace-events file Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 04/23] tracetool: Use method 'Event.api' to get the name of public routines Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 05/23] trace: Minimize inclusions of "qemu-common.h" to avoid inclusion loops Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 06/23] instrument: [none] Add null instrumentation Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 07/23] system: [linux] Use absolute include path for linux-headers Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 08/23] instrument: [static] Call statically linked user-provided routines Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 09/23] build: Add variable 'tools-obj-y' for tool-only files Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 10/23] instrument: [dynamic] Call dynamically linked user-provided routines Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 11/23] instrument: Add internal control interface Lluís Vilanova
2013-04-16 13:50 ` [Qemu-devel] [PATCH v2 12/23] instrument: [hmp] Add " Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 13/23] qapi: Add a primitive to include other files from a QAPI schema file Lluís Vilanova
2013-04-19 2:49 ` Eric Blake
2013-04-19 12:21 ` Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 14/23] [trivial] Set the input root directory when parsing QAPI files Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 15/23] instrument: [qmp, qapi] Add control interface Lluís Vilanova
2013-04-19 3:07 ` Eric Blake
2013-04-19 23:46 ` Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 16/23] Let makefiles add entries to the set of target architecture objects Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 17/23] instrument: Add commandline options to start with an instrumentation library Lluís Vilanova
2013-04-19 3:28 ` Eric Blake
2013-04-20 0:42 ` Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 18/23] instrument: Add client-side API to enumerate events Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 19/23] instrument: Add client-side API to control tracing state of events Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 20/23] instrument: Add client-side API to control event instrumentation Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 21/23] build: Fix installation of target-dependant files Lluís Vilanova
2013-04-16 13:51 ` [Qemu-devel] [PATCH v2 22/23] instrument: Install headers for dynamic instrumentation clients Lluís Vilanova
2013-04-16 13:52 ` [Qemu-devel] [PATCH v2 23/23] trace: Do not use the word 'new' in event arguments Lluís Vilanova
2013-04-16 20:52 ` [Qemu-devel] [RFC][PATCH v2 00/23] instrument: Let the user wrap/override specific event tracing routines Lluís Vilanova
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).