This mode uses a function pointer in "trace_*" routines. By default, it points to the original tracing function (now "_backend__trace_*").
Signed-off-by: Lluís Vilanova <vilan...@ac.upc.edu> --- .gitignore | 3 + Makefile | 26 ++++++++++- Makefile.objs | 4 ++ configure | 9 ++++ instrument/Makefile.objs | 12 +++++ scripts/tracetool/__init__.py | 3 + scripts/tracetool/backend/instr_dynamic.py | 67 ++++++++++++++++++++++++++++ scripts/tracetool/format/instr_c.py | 44 ++++++++++++++++++ scripts/tracetool/format/instr_tcg_c.py | 40 +++++++++++++++++ 9 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 scripts/tracetool/backend/instr_dynamic.py create mode 100644 scripts/tracetool/format/instr_c.py create mode 100644 scripts/tracetool/format/instr_tcg_c.py diff --git a/.gitignore b/.gitignore index 068dc1c1ae..ee2768cb05 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,9 @@ /config.status /config-temp /instrument-root.h +/instrument-root.c /instrument/generated-tcg-tracers.h +/instrument/generated-tcg-tracers.c /trace-events-all /trace/generated-events.h /trace/generated-events.c @@ -119,6 +121,7 @@ TAGS docker-src.* *~ instrument.h +instrument.c trace.h trace.c trace-ust.h diff --git a/Makefile b/Makefile index 375bd313d7..fb226bf54b 100644 --- a/Makefile +++ b/Makefile @@ -193,8 +193,11 @@ trace-dtrace-root.o: trace-dtrace-root.dtrace INSTRUMENT_HEADERS = instrument-root.h $(trace-events-subdirs:%=%/instrument.h) INSTRUMENT_HEADERS += instrument/generated-tcg-tracers.h +INSTRUMENT_SOURCES = instrument-root.c $(trace-events-subdirs:%=%/instrument.c) +INSTRUMENT_SOURCES += instrument/generated-tcg-tracers.c GENERATED_FILES += $(INSTRUMENT_HEADERS) +GENERATED_FILES += $(INSTRUMENT_SOURCES) %/instrument.h: %/instrument.h-timestamp @cmp $< $@ >/dev/null 2>&1 || cp $< $@ @@ -205,6 +208,15 @@ GENERATED_FILES += $(INSTRUMENT_HEADERS) --backends=$(TRACE_INSTRUMENT_BACKEND) \ $< > $@,"GEN","$(@:%-timestamp=%)") +%/instrument.c: %/instrument.c-timestamp + @cmp $< $@ >/dev/null 2>&1 || cp $< $@ +%/instrument.c-timestamp: $(SRC_PATH)/%/trace-events $(BUILD_DIR)/config-host.mak $(tracetool-y) + $(call quiet-command,$(TRACETOOL) \ + --group=$(call trace-group-name,$@) \ + --format=instr-c \ + --backends=$(TRACE_INSTRUMENT_BACKEND) \ + $< > $@,"GEN","$(@:%-timestamp=%)") + instrument-root.h: instrument-root.h-timestamp @cmp $< $@ >/dev/null 2>&1 || cp $< $@ instrument-root.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak $(tracetool-y) @@ -214,6 +226,15 @@ instrument-root.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.m --backends=$(TRACE_INSTRUMENT_BACKEND) \ $< > $@,"GEN","$(@:%-timestamp=%)") +instrument-root.c: instrument-root.c-timestamp + @cmp $< $@ >/dev/null 2>&1 || cp $< $@ +instrument-root.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak $(tracetool-y) + $(call quiet-command,$(TRACETOOL) \ + --group=root \ + --format=instr-c \ + --backends=$(TRACE_INSTRUMENT_BACKEND) \ + $< > $@,"GEN","$(@:%-timestamp=%)") + # Don't try to regenerate Makefile or configure # We don't generate any of them Makefile: ; @@ -390,7 +411,7 @@ Makefile: $(version-obj-y) # Build libraries libqemustub.a: $(stub-obj-y) -libqemuutil.a: $(util-obj-y) $(trace-obj-y) +libqemuutil.a: $(util-obj-y) $(trace-obj-y) $(instr-obj-y) ###################################################################### @@ -830,7 +851,8 @@ endif .SECONDARY: $(TRACE_HEADERS) $(TRACE_HEADERS:%=%-timestamp) \ $(TRACE_SOURCES) $(TRACE_SOURCES:%=%-timestamp) \ $(TRACE_DTRACE) $(TRACE_DTRACE:%=%-timestamp) \ - $(INSTRUMENT_HEADERS) $(INSTRUMENT_HEADERS:%=%-timestamp) + $(INSTRUMENT_HEADERS) $(INSTRUMENT_HEADERS:%=%-timestamp) \ + $(INSTRUMENT_SOURCES) $(INSTRUMENT_SOURCES:%=%-timestamp) # Include automatically generated dependency files # Dependencies in Makefile.objs files come from our recursive subdir rules diff --git a/Makefile.objs b/Makefile.objs index 8e2b3770c4..e36a519952 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -100,6 +100,7 @@ target-obj-y += trace/ ###################################################################### # instrumentation util-obj-y += instrument/ +target-obj-y += instrument/ ###################################################################### # guest agent @@ -180,3 +181,6 @@ trace-obj-y += $(trace-events-subdirs:%=%/trace.o) trace-obj-$(CONFIG_TRACE_UST) += trace-ust-all.o trace-obj-$(CONFIG_TRACE_DTRACE) += trace-dtrace-root.o trace-obj-$(CONFIG_TRACE_DTRACE) += $(trace-events-subdirs:%=%/trace-dtrace.o) + +instr-obj-$(CONFIG_INSTRUMENT) = instrument-root.o +instr-obj-y += $(trace-events-subdirs:%=%/instrument.o) diff --git a/configure b/configure index 75d899b40c..13191052cb 100755 --- a/configure +++ b/configure @@ -897,6 +897,10 @@ for opt do ;; --with-trace-file=*) trace_file="$optarg" ;; + --enable-trace-instrument) + trace_instrument="yes" + trace_instrument_backend="dynamic" + ;; --enable-gprof) gprof="yes" ;; --enable-gcov) gcov="yes" @@ -1427,6 +1431,8 @@ Advanced options (experts only): Available backends: $trace_backend_list --with-trace-file=NAME Full PATH,NAME of file to store traces Default:trace-<pid> + --enable-trace-instrument + Enable trace instrumentation --disable-slirp disable SLIRP userspace network connectivity --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI) --oss-lib path to OSS library @@ -5995,6 +6001,9 @@ QEMU_INCLUDES="-I\$(SRC_PATH)/tcg $QEMU_INCLUDES" ########################################## # trace instrumentation echo "TRACE_INSTRUMENT_BACKEND=instr-$trace_instrument_backend" >> $config_host_mak +if test "$trace_instrument" = "yes"; then + echo "CONFIG_INSTRUMENT=y" >> $config_host_mak +fi ########################################## echo "TOOLS=$tools" >> $config_host_mak diff --git a/instrument/Makefile.objs b/instrument/Makefile.objs index d1edd1696e..c548bbdd8a 100644 --- a/instrument/Makefile.objs +++ b/instrument/Makefile.objs @@ -12,3 +12,15 @@ $(obj)/generated-tcg-tracers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/ --format=instr-tcg-h \ --backend=$(TRACE_INSTRUMENT_BACKEND) \ $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + +$(obj)/generated-tcg-tracers.c: $(obj)/generated-tcg-tracers.c-timestamp + @cmp $< $@ >/dev/null 2>&1 || cp $< $@ +$(obj)/generated-tcg-tracers.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak $(tracetool-y) + @mkdir -p $(dir $@) + $(call quiet-command,$(TRACETOOL) \ + --group=root \ + --format=instr-tcg-c \ + --backend=$(TRACE_INSTRUMENT_BACKEND) \ + $< > $@,"GEN","$(patsubst %-timestamp,%,$@)") + +target-obj-$(CONFIG_INSTRUMENT) += generated-tcg-tracers.o diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py index 6d382157c0..e65349bc33 100644 --- a/scripts/tracetool/__init__.py +++ b/scripts/tracetool/__init__.py @@ -275,6 +275,9 @@ class Event(object): QEMU_DSTATE = "_TRACE_%(NAME)s_DSTATE" QEMU_EVENT = "_TRACE_%(NAME)s_EVENT" + QI_TRACE_INSTRUMENT = "qi_event_%(name)s" + QI_TRACE_INSTRUMENT_TCG = QI_TRACE_INSTRUMENT + "_tcg" + def api(self, fmt=None): if fmt is None: fmt = Event.QEMU_TRACE_BACKEND diff --git a/scripts/tracetool/backend/instr_dynamic.py b/scripts/tracetool/backend/instr_dynamic.py new file mode 100644 index 0000000000..f42d3afa8f --- /dev/null +++ b/scripts/tracetool/backend/instr_dynamic.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Dynamic instrumentation proxy. + +""" + +__author__ = "Lluís Vilanova <vilan...@ac.upc.edu>" +__copyright__ = "Copyright 2012-2017, Lluís Vilanova <vilan...@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefa...@linux.vnet.ibm.com" + + +from tracetool import out +from tracetool.transform import * +import tracetool.vcpu + + +################################################## +# instr-h + +def generate_instr_h_begin(events, group): + for event in events: + if "instrument" not in event.properties: + continue + out('extern void * %(qi)s_cb;', + qi=event.api(event.QI_TRACE_INSTRUMENT)) + out('') + + +def generate_instr_h(event, group): + argtypes = ", ".join(event.args.types()) + if argtypes == "": + argtypes = "void" + out(' void (*func)(%(argtypes)s) = %(qi)s_cb;', + ' func(%(argnames)s);', + qi=event.api(event.QI_TRACE_INSTRUMENT), + args=event.args, + argnames=", ".join(event.args.names()), + argtypes=argtypes) + + +################################################## +# instr-tcg-h + +def generate_instr_tcg_h_begin(events, group): + for event in events: + if "instrument" not in event.properties: + continue + out('extern void * %(qi)s_cb;', + qi=event.api(event.QI_TRACE_INSTRUMENT_TCG)) + out('') + + +def generate_instr_tcg_h(event, group): + argtypes = ", ".join(event.args.types()) + if argtypes == "": + argtypes = "void" + out(' void (*func)(%(argtypes)s) = %(qi)s_cb;', + ' func(%(argnames)s);', + qi=event.api(event.QI_TRACE_INSTRUMENT_TCG), + args=event.args, + argnames=", ".join(event.args.names()), + argtypes=argtypes) diff --git a/scripts/tracetool/format/instr_c.py b/scripts/tracetool/format/instr_c.py new file mode 100644 index 0000000000..987ecbf5c2 --- /dev/null +++ b/scripts/tracetool/format/instr_c.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +/instrument-root.c +.../instrument.c + +""" + +__author__ = "Lluís Vilanova <vilan...@ac.upc.edu>" +__copyright__ = "Copyright 2012-2017, Lluís Vilanova <vilan...@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefa...@linux.vnet.ibm.com" + + +from tracetool import out +from tracetool.transform import * + + +def generate(events, backend, group): + events = [e for e in events + if "tcg-trans" not in e.properties and + "instrument" in e.properties] + + if group == "root": + header = "trace-root.h" + else: + header = "trace.h" + + out('/* This file is autogenerated by tracetool, do not edit. */', + '', + '#include "qemu/osdep.h"', + '#include "%s"' % header, + '') + backend.generate_begin(events, group) + + for e in events: + out('void *%(qi_cb)s_cb = %(qi_trace)s;', + qi_cb=e.api(e.QI_TRACE_INSTRUMENT), + qi_trace=e.api(e.QEMU_TRACE_BACKEND)) + + backend.generate_end(events, group) diff --git a/scripts/tracetool/format/instr_tcg_c.py b/scripts/tracetool/format/instr_tcg_c.py new file mode 100644 index 0000000000..382709d0bd --- /dev/null +++ b/scripts/tracetool/format/instr_tcg_c.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +instrument/generated-tcg-tracers.c + +""" + +__author__ = "Lluís Vilanova <vilan...@ac.upc.edu>" +__copyright__ = "Copyright 2012-2017, Lluís Vilanova <vilan...@ac.upc.edu>" +__license__ = "GPL version 2 or (at your option) any later version" + +__maintainer__ = "Stefan Hajnoczi" +__email__ = "stefa...@linux.vnet.ibm.com" + + +from tracetool import out +from tracetool.transform import * + + +def generate(events, backend, group): + events = [e.original for e in events + if "tcg-trans" in e.properties and + "instrument" in e.properties] + + out('/* This file is autogenerated by tracetool, do not edit. */', + '', + '#include "qemu/osdep.h"', + '#include "cpu.h"', + '#include "tcg-op.h"', + '#include "trace-tcg.h"', + '') + backend.generate_begin(events, group) + + for e in events: + out('void *%(qi_cb)s_cb = %(qi_trace)s;', + qi_cb=e.api(e.QI_TRACE_INSTRUMENT_TCG), + qi_trace=e.api(e.QEMU_TRACE_TCG_BACKEND)) + + backend.generate_end(events, group)