qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v3 10/24] instrument: [dynamic] Call dynamically lin


From: Lluís Vilanova
Subject: [Qemu-devel] [PATCH v3 10/24] instrument: [dynamic] Call dynamically linked user-provided routines
Date: Sun, 21 Apr 2013 21:12:26 +0200
User-agent: StGit/0.16

Provides a mechanism to dynamically change the routine invoked by 'trace_*'.

Signed-off-by: Lluís Vilanova <address@hidden>
---
 .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 0eafd5a..b51436f 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_CONFIG_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 <address@hidden>"
+__copyright__  = "Copyright 2012-2013, Lluís Vilanova <address@hidden>"
+__license__    = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__      = "address@hidden"
+
+
+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 <address@hidden>"
+__copyright__  = "Copyright 2012-2013, Lluís Vilanova <address@hidden>"
+__license__    = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__      = "address@hidden"
+
+
+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 <address@hidden>"
-__copyright__  = "Copyright 2012, Lluís Vilanova <address@hidden>"
+__copyright__  = "Copyright 2012-2013, Lluís Vilanova <address@hidden>"
 __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 <address@hidden>
+ * Copyright (C) 2012-2013 Lluís Vilanova <address@hidden>
  *
  * 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;
 
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]