mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/stefanha/tags/tracing-pull-request' into staging
Tracing pull request * remotes/stefanha/tags/tracing-pull-request: virtio-rng: add some trace events trace: add some tcg tracing support trace: teach lttng backend to use format strings trace: [tcg] Include TCG-tracing header on all targets trace: [tcg] Include event definitions in "trace.h" trace: [tcg] Generate TCG tracing routines trace: [tcg] Include TCG-tracing helpers trace: [tcg] Define TCG tracing helper routine wrappers trace: [tcg] Define TCG tracing helper routines trace: [tcg] Declare TCG tracing helper routines trace: [tcg] Add 'tcg' event property trace: [tcg] Argument type transformation machinery trace: [tcg] Argument type transformation rules trace: [tcg] Add documentation trace: install simpletrace SystemTap tapset simpletrace: add simpletrace.py --no-header option trace: add tracetool simpletrace_stap format trace: extract stap_escape() function for reuse Conflicts: Makefile.objs
This commit is contained in:
@@ -11,6 +11,10 @@
|
||||
/trace/generated-tracers.dtrace
|
||||
/trace/generated-events.h
|
||||
/trace/generated-events.c
|
||||
/trace/generated-helpers-wrappers.h
|
||||
/trace/generated-helpers.h
|
||||
/trace/generated-helpers.c
|
||||
/trace/generated-tcg-tracers.h
|
||||
/trace/generated-ust-provider.h
|
||||
/trace/generated-ust.c
|
||||
/libcacard/trace/generated-tracers.c
|
||||
|
||||
@@ -57,6 +57,12 @@ GENERATED_HEADERS += trace/generated-tracers-dtrace.h
|
||||
endif
|
||||
GENERATED_SOURCES += trace/generated-tracers.c
|
||||
|
||||
GENERATED_HEADERS += trace/generated-tcg-tracers.h
|
||||
|
||||
GENERATED_HEADERS += trace/generated-helpers-wrappers.h
|
||||
GENERATED_HEADERS += trace/generated-helpers.h
|
||||
GENERATED_SOURCES += trace/generated-helpers.c
|
||||
|
||||
ifeq ($(findstring ust,$(TRACE_BACKENDS)),ust)
|
||||
GENERATED_HEADERS += trace/generated-ust-provider.h
|
||||
GENERATED_SOURCES += trace/generated-ust.c
|
||||
|
||||
+6
-1
@@ -1,7 +1,7 @@
|
||||
#######################################################################
|
||||
# Common libraries for tools and emulators
|
||||
stub-obj-y = stubs/
|
||||
util-obj-y = util/ qobject/ qapi/ trace/ qapi-types.o qapi-visit.o qapi-event.o
|
||||
util-obj-y = util/ qobject/ qapi/ qapi-types.o qapi-visit.o qapi-event.o
|
||||
|
||||
#######################################################################
|
||||
# block-obj-y is code used by both qemu system emulation and qemu-img
|
||||
@@ -100,6 +100,11 @@ common-obj-y += disas/
|
||||
version-obj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.o
|
||||
version-lobj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.lo
|
||||
|
||||
######################################################################
|
||||
# tracing
|
||||
util-obj-y += trace/
|
||||
target-obj-y += trace/
|
||||
|
||||
######################################################################
|
||||
# guest agent
|
||||
|
||||
|
||||
+14
-1
@@ -38,7 +38,7 @@ config-target.h: config-target.h-timestamp
|
||||
config-target.h-timestamp: config-target.mak
|
||||
|
||||
ifdef CONFIG_TRACE_SYSTEMTAP
|
||||
stap: $(QEMU_PROG).stp-installed $(QEMU_PROG).stp
|
||||
stap: $(QEMU_PROG).stp-installed $(QEMU_PROG).stp $(QEMU_PROG)-simpletrace.stp
|
||||
|
||||
ifdef CONFIG_USER_ONLY
|
||||
TARGET_TYPE=user
|
||||
@@ -64,6 +64,13 @@ $(QEMU_PROG).stp: $(SRC_PATH)/trace-events
|
||||
--target-type=$(TARGET_TYPE) \
|
||||
< $< > $@," GEN $(TARGET_DIR)$(QEMU_PROG).stp")
|
||||
|
||||
$(QEMU_PROG)-simpletrace.stp: $(SRC_PATH)/trace-events
|
||||
$(call quiet-command,$(TRACETOOL) \
|
||||
--format=simpletrace-stap \
|
||||
--backends=$(TRACE_BACKENDS) \
|
||||
--probe-prefix=qemu.$(TARGET_TYPE).$(TARGET_NAME) \
|
||||
< $< > $@," GEN $(TARGET_DIR)$(QEMU_PROG)-simpletrace.stp")
|
||||
|
||||
else
|
||||
stap:
|
||||
endif
|
||||
@@ -152,15 +159,20 @@ endif # CONFIG_SOFTMMU
|
||||
dummy := $(call unnest-vars,,obj-y)
|
||||
all-obj-y := $(obj-y)
|
||||
|
||||
target-obj-y :=
|
||||
block-obj-y :=
|
||||
common-obj-y :=
|
||||
include $(SRC_PATH)/Makefile.objs
|
||||
dummy := $(call unnest-vars,,target-obj-y)
|
||||
target-obj-y-save := $(target-obj-y)
|
||||
dummy := $(call unnest-vars,.., \
|
||||
block-obj-y \
|
||||
block-obj-m \
|
||||
common-obj-y \
|
||||
common-obj-m)
|
||||
target-obj-y := $(target-obj-y-save)
|
||||
all-obj-y += $(common-obj-y)
|
||||
all-obj-y += $(target-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y)
|
||||
|
||||
# build either PROG or PROGW
|
||||
@@ -191,6 +203,7 @@ endif
|
||||
ifdef CONFIG_TRACE_SYSTEMTAP
|
||||
$(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset"
|
||||
$(INSTALL_DATA) $(QEMU_PROG).stp-installed "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset/$(QEMU_PROG).stp"
|
||||
$(INSTALL_DATA) $(QEMU_PROG)-simpletrace.stp "$(DESTDIR)$(qemu_datadir)/../systemtap/tapset/$(QEMU_PROG)-simpletrace.stp"
|
||||
endif
|
||||
|
||||
GENERATED_HEADERS += config-target.h
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include "trace.h"
|
||||
#include "disas/disas.h"
|
||||
#include "tcg.h"
|
||||
#include "qemu/atomic.h"
|
||||
@@ -168,6 +169,9 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr)
|
||||
#endif /* DEBUG_DISAS */
|
||||
|
||||
next_tb = tcg_qemu_tb_exec(env, tb_ptr);
|
||||
trace_exec_tb_exit((void *) (next_tb & ~TB_EXIT_MASK),
|
||||
next_tb & TB_EXIT_MASK);
|
||||
|
||||
if ((next_tb & TB_EXIT_MASK) > TB_EXIT_IDX1) {
|
||||
/* We didn't start executing this TB (eg because the instruction
|
||||
* counter hit zero); we must restore the guest PC to the address
|
||||
@@ -208,6 +212,7 @@ static void cpu_exec_nocache(CPUArchState *env, int max_cycles,
|
||||
max_cycles);
|
||||
cpu->current_tb = tb;
|
||||
/* execute the generated code */
|
||||
trace_exec_tb_nocache(tb, tb->pc);
|
||||
cpu_tb_exec(cpu, tb->tc_ptr);
|
||||
cpu->current_tb = NULL;
|
||||
tb_phys_invalidate(tb, -1);
|
||||
@@ -749,6 +754,7 @@ int cpu_exec(CPUArchState *env)
|
||||
cpu->current_tb = tb;
|
||||
barrier();
|
||||
if (likely(!cpu->exit_request)) {
|
||||
trace_exec_tb(tb, tb->pc);
|
||||
tc_ptr = tb->tc_ptr;
|
||||
/* execute the generated code */
|
||||
next_tb = cpu_tb_exec(cpu, tc_ptr);
|
||||
|
||||
@@ -307,3 +307,43 @@ 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).
|
||||
|
||||
=== "tcg" ===
|
||||
|
||||
Guest code generated by TCG can be traced by defining an event with the "tcg"
|
||||
event property. Internally, this property generates two events:
|
||||
"<eventname>_trans" to trace the event at translation time, and
|
||||
"<eventname>_exec" to trace the event at execution time.
|
||||
|
||||
Instead of using these two events, you should instead use the function
|
||||
"trace_<eventname>_tcg" during translation (TCG code generation). This function
|
||||
will automatically call "trace_<eventname>_trans", and will generate the
|
||||
necessary TCG code to call "trace_<eventname>_exec" during guest code execution.
|
||||
|
||||
Events with the "tcg" property can be declared in the "trace-events" file with a
|
||||
mix of native and TCG types, and "trace_<eventname>_tcg" will gracefully forward
|
||||
them to the "<eventname>_trans" and "<eventname>_exec" events. Since TCG values
|
||||
are not known at translation time, these are ignored by the "<eventname>_trans"
|
||||
event. Because of this, the entry in the "trace-events" file needs two printing
|
||||
formats (separated by a comma):
|
||||
|
||||
tcg foo(uint8_t a1, TCGv_i32 a2) "a1=%d", "a1=%d a2=%d"
|
||||
|
||||
For example:
|
||||
|
||||
#include "trace-tcg.h"
|
||||
|
||||
void some_disassembly_func (...)
|
||||
{
|
||||
uint8_t a1 = ...;
|
||||
TCGv_i32 a2 = ...;
|
||||
trace_foo_tcg(a1, a2);
|
||||
}
|
||||
|
||||
This will immediately call:
|
||||
|
||||
void trace_foo_trans(uint8_t a1);
|
||||
|
||||
and will generate the TCG code to call:
|
||||
|
||||
void trace_foo(uint8_t a1, uint32_t a2);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "hw/virtio/virtio-rng.h"
|
||||
#include "sysemu/rng.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "trace.h"
|
||||
|
||||
static bool is_guest_ready(VirtIORNG *vrng)
|
||||
{
|
||||
@@ -24,6 +25,7 @@ static bool is_guest_ready(VirtIORNG *vrng)
|
||||
&& (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
||||
return true;
|
||||
}
|
||||
trace_virtio_rng_guest_not_ready(vrng);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -62,6 +64,7 @@ static void chr_read(void *opaque, const void *buf, size_t size)
|
||||
offset += len;
|
||||
|
||||
virtqueue_push(vrng->vq, &elem, len);
|
||||
trace_virtio_rng_pushed(vrng, len);
|
||||
}
|
||||
virtio_notify(vdev, vrng->vq);
|
||||
}
|
||||
@@ -81,6 +84,9 @@ static void virtio_rng_process(VirtIORNG *vrng)
|
||||
quota = MIN((uint64_t)vrng->quota_remaining, (uint64_t)UINT32_MAX);
|
||||
}
|
||||
size = get_request_size(vrng->vq, quota);
|
||||
|
||||
trace_virtio_rng_request(vrng, size, quota);
|
||||
|
||||
size = MIN(vrng->quota_remaining, size);
|
||||
if (size) {
|
||||
rng_backend_request_entropy(vrng->rng, size, chr_read, vrng);
|
||||
|
||||
@@ -57,6 +57,8 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
}
|
||||
|
||||
#include "helper.h"
|
||||
#include "trace/generated-helpers.h"
|
||||
#include "trace/generated-helpers-wrappers.h"
|
||||
#include "tcg-runtime.h"
|
||||
|
||||
#undef DEF_HELPER_FLAGS_0
|
||||
|
||||
@@ -27,6 +27,7 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
|
||||
dh_ctype(t4), dh_ctype(t5));
|
||||
|
||||
#include "helper.h"
|
||||
#include "trace/generated-helpers.h"
|
||||
#include "tcg-runtime.h"
|
||||
|
||||
#undef DEF_HELPER_FLAGS_0
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
| dh_sizemask(t5, 5) },
|
||||
|
||||
#include "helper.h"
|
||||
#include "trace/generated-helpers.h"
|
||||
#include "tcg-runtime.h"
|
||||
|
||||
#undef DEF_HELPER_FLAGS_0
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef TRACE_TCG_H
|
||||
#define TRACE_TCG_H
|
||||
|
||||
#include "trace/generated-tcg-tracers.h"
|
||||
#include "trace/generated-events.h"
|
||||
|
||||
#endif /* TRACE_TCG_H */
|
||||
@@ -2,5 +2,6 @@
|
||||
#define TRACE_H
|
||||
|
||||
#include "trace/generated-tracers.h"
|
||||
#include "trace/generated-events.h"
|
||||
|
||||
#endif /* TRACE_H */
|
||||
|
||||
+17
-7
@@ -58,8 +58,8 @@ def read_record(edict, fobj):
|
||||
rechdr = read_header(fobj, rec_header_fmt)
|
||||
return get_record(edict, rechdr, fobj) # return tuple of record elements
|
||||
|
||||
def read_trace_file(edict, fobj):
|
||||
"""Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6)."""
|
||||
def read_trace_header(fobj):
|
||||
"""Read and verify trace file header"""
|
||||
header = read_header(fobj, log_header_fmt)
|
||||
if header is None or \
|
||||
header[0] != header_event_id or \
|
||||
@@ -73,6 +73,8 @@ def read_trace_file(edict, fobj):
|
||||
raise ValueError('Log format %d not supported with this QEMU release!'
|
||||
% log_version)
|
||||
|
||||
def read_trace_records(edict, fobj):
|
||||
"""Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6)."""
|
||||
while True:
|
||||
rec = read_record(edict, fobj)
|
||||
if rec is None:
|
||||
@@ -102,13 +104,16 @@ class Analyzer(object):
|
||||
"""Called at the end of the trace."""
|
||||
pass
|
||||
|
||||
def process(events, log, analyzer):
|
||||
def process(events, log, analyzer, read_header=True):
|
||||
"""Invoke an analyzer on each event in a log."""
|
||||
if isinstance(events, str):
|
||||
events = _read_events(open(events, 'r'))
|
||||
if isinstance(log, str):
|
||||
log = open(log, 'rb')
|
||||
|
||||
if read_header:
|
||||
read_trace_header(log)
|
||||
|
||||
dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)")
|
||||
edict = {dropped_event_id: dropped_event}
|
||||
|
||||
@@ -137,7 +142,7 @@ def process(events, log, analyzer):
|
||||
|
||||
analyzer.begin()
|
||||
fn_cache = {}
|
||||
for rec in read_trace_file(edict, log):
|
||||
for rec in read_trace_records(edict, log):
|
||||
event_num = rec[0]
|
||||
event = edict[event_num]
|
||||
if event_num not in fn_cache:
|
||||
@@ -152,12 +157,17 @@ def run(analyzer):
|
||||
advanced scripts will want to call process() instead."""
|
||||
import sys
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
sys.stderr.write('usage: %s <trace-events> <trace-file>\n' % sys.argv[0])
|
||||
read_header = True
|
||||
if len(sys.argv) == 4 and sys.argv[1] == '--no-header':
|
||||
read_header = False
|
||||
del sys.argv[1]
|
||||
elif len(sys.argv) != 3:
|
||||
sys.stderr.write('usage: %s [--no-header] <trace-events> ' \
|
||||
'<trace-file>\n' % sys.argv[0])
|
||||
sys.exit(1)
|
||||
|
||||
events = _read_events(open(sys.argv[1], 'r'))
|
||||
process(events, sys.argv[2], analyzer)
|
||||
process(events, sys.argv[2], analyzer, read_header=read_header)
|
||||
|
||||
if __name__ == '__main__':
|
||||
class Formatter(Analyzer):
|
||||
|
||||
@@ -15,9 +15,11 @@ __email__ = "stefanha@linux.vnet.ibm.com"
|
||||
|
||||
import re
|
||||
import sys
|
||||
import weakref
|
||||
|
||||
import tracetool.format
|
||||
import tracetool.backend
|
||||
import tracetool.transform
|
||||
|
||||
|
||||
def error_write(*lines):
|
||||
@@ -108,6 +110,18 @@ class Arguments:
|
||||
"""List of argument types."""
|
||||
return [ type_ for type_, _ in self._args ]
|
||||
|
||||
def transform(self, *trans):
|
||||
"""Return a new Arguments instance with transformed types.
|
||||
|
||||
The types in the resulting Arguments instance are transformed according
|
||||
to tracetool.transform.transform_type.
|
||||
"""
|
||||
res = []
|
||||
for type_, name in self._args:
|
||||
res.append((tracetool.transform.transform_type(type_, *trans),
|
||||
name))
|
||||
return Arguments(res)
|
||||
|
||||
|
||||
class Event(object):
|
||||
"""Event description.
|
||||
@@ -122,13 +136,21 @@ class Event(object):
|
||||
Properties of the event.
|
||||
args : Arguments
|
||||
The event arguments.
|
||||
arg_fmts : str
|
||||
The format strings for each argument.
|
||||
"""
|
||||
|
||||
_CRE = re.compile("((?P<props>.*)\s+)?(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?")
|
||||
_CRE = re.compile("((?P<props>.*)\s+)?"
|
||||
"(?P<name>[^(\s]+)"
|
||||
"\((?P<args>[^)]*)\)"
|
||||
"\s*"
|
||||
"(?:(?:(?P<fmt_trans>\".+),)?\s*(?P<fmt>\".+))?"
|
||||
"\s*")
|
||||
_FMT = re.compile("(%\w+|%.*PRI\S+)")
|
||||
|
||||
_VALID_PROPS = set(["disable"])
|
||||
_VALID_PROPS = set(["disable", "tcg", "tcg-trans", "tcg-exec"])
|
||||
|
||||
def __init__(self, name, props, fmt, args):
|
||||
def __init__(self, name, props, fmt, args, arg_fmts, orig=None):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
@@ -136,20 +158,32 @@ class Event(object):
|
||||
Event name.
|
||||
props : list of str
|
||||
Property names.
|
||||
fmt : str
|
||||
Event printing format.
|
||||
fmt : str, list of str
|
||||
Event printing format (or formats).
|
||||
args : Arguments
|
||||
Event arguments.
|
||||
arg_fmts : list of str
|
||||
Format strings for each argument.
|
||||
orig : Event or None
|
||||
Original Event before transformation.
|
||||
|
||||
"""
|
||||
self.name = name
|
||||
self.properties = props
|
||||
self.fmt = fmt
|
||||
self.args = args
|
||||
self.arg_fmts = arg_fmts
|
||||
|
||||
if orig is None:
|
||||
self.original = weakref.ref(self)
|
||||
else:
|
||||
self.original = orig
|
||||
|
||||
unknown_props = set(self.properties) - self._VALID_PROPS
|
||||
if len(unknown_props) > 0:
|
||||
raise ValueError("Unknown properties: %s"
|
||||
% ", ".join(unknown_props))
|
||||
assert isinstance(self.fmt, str) or len(self.fmt) == 2
|
||||
|
||||
def copy(self):
|
||||
"""Create a new copy."""
|
||||
@@ -172,24 +206,50 @@ class Event(object):
|
||||
name = groups["name"]
|
||||
props = groups["props"].split()
|
||||
fmt = groups["fmt"]
|
||||
fmt_trans = groups["fmt_trans"]
|
||||
if len(fmt_trans) > 0:
|
||||
fmt = [fmt_trans, fmt]
|
||||
args = Arguments.build(groups["args"])
|
||||
arg_fmts = Event._FMT.findall(fmt)
|
||||
|
||||
return Event(name, props, fmt, args)
|
||||
if "tcg-trans" in props:
|
||||
raise ValueError("Invalid property 'tcg-trans'")
|
||||
if "tcg-exec" in props:
|
||||
raise ValueError("Invalid property 'tcg-exec'")
|
||||
if "tcg" not in props and not isinstance(fmt, str):
|
||||
raise ValueError("Only events with 'tcg' property can have two formats")
|
||||
if "tcg" in props and isinstance(fmt, str):
|
||||
raise ValueError("Events with 'tcg' property must have two formats")
|
||||
|
||||
return Event(name, props, fmt, args, arg_fmts)
|
||||
|
||||
def __repr__(self):
|
||||
"""Evaluable string representation for this object."""
|
||||
if isinstance(self.fmt, str):
|
||||
fmt = self.fmt
|
||||
else:
|
||||
fmt = "%s, %s" % (self.fmt[0], self.fmt[1])
|
||||
return "Event('%s %s(%s) %s')" % (" ".join(self.properties),
|
||||
self.name,
|
||||
self.args,
|
||||
self.fmt)
|
||||
fmt)
|
||||
|
||||
QEMU_TRACE = "trace_%(name)s"
|
||||
QEMU_TRACE_TCG = QEMU_TRACE + "_tcg"
|
||||
|
||||
def api(self, fmt=None):
|
||||
if fmt is None:
|
||||
fmt = Event.QEMU_TRACE
|
||||
return fmt % {"name": self.name}
|
||||
|
||||
def transform(self, *trans):
|
||||
"""Return a new Event with transformed Arguments."""
|
||||
return Event(self.name,
|
||||
list(self.properties),
|
||||
self.fmt,
|
||||
self.args.transform(*trans),
|
||||
self)
|
||||
|
||||
|
||||
def _read_events(fobj):
|
||||
res = []
|
||||
@@ -272,4 +332,35 @@ def generate(fevents, format, backends,
|
||||
|
||||
events = _read_events(fevents)
|
||||
|
||||
# transform TCG-enabled events
|
||||
new_events = []
|
||||
for event in events:
|
||||
if "tcg" not in event.properties:
|
||||
new_events.append(event)
|
||||
else:
|
||||
event_trans = event.copy()
|
||||
event_trans.name += "_trans"
|
||||
event_trans.properties += ["tcg-trans"]
|
||||
event_trans.fmt = event.fmt[0]
|
||||
args_trans = []
|
||||
for atrans, aorig in zip(
|
||||
event_trans.transform(tracetool.transform.TCG_2_HOST).args,
|
||||
event.args):
|
||||
if atrans == aorig:
|
||||
args_trans.append(atrans)
|
||||
event_trans.args = Arguments(args_trans)
|
||||
event_trans = event_trans.copy()
|
||||
|
||||
event_exec = event.copy()
|
||||
event_exec.name += "_exec"
|
||||
event_exec.properties += ["tcg-exec"]
|
||||
event_exec.fmt = event.fmt[1]
|
||||
event_exec = event_exec.transform(tracetool.transform.TCG_2_HOST)
|
||||
|
||||
new_event = [event_trans, event_exec]
|
||||
event.event_trans, event.event_exec = new_event
|
||||
|
||||
new_events.extend(new_event)
|
||||
events = new_events
|
||||
|
||||
tracetool.format.generate(events, format, backend)
|
||||
|
||||
@@ -40,6 +40,11 @@ def generate(events, backend):
|
||||
enabled = 0
|
||||
else:
|
||||
enabled = 1
|
||||
if "tcg-trans" in e.properties:
|
||||
# a single define for the two "sub-events"
|
||||
out('#define TRACE_%(name)s_ENABLED %(enabled)d',
|
||||
name=e.original.original.name.upper(),
|
||||
enabled=enabled)
|
||||
out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled))
|
||||
|
||||
out('#include "trace/event-internal.h"',
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Generate .stp file that outputs simpletrace binary traces (DTrace with SystemTAP only).
|
||||
"""
|
||||
|
||||
__author__ = "Stefan Hajnoczi <redhat.com>"
|
||||
__copyright__ = "Copyright (C) 2014, Red Hat, Inc."
|
||||
__license__ = "GPL version 2 or (at your option) any later version"
|
||||
|
||||
__maintainer__ = "Stefan Hajnoczi"
|
||||
__email__ = "stefanha@redhat.com"
|
||||
|
||||
|
||||
from tracetool import out
|
||||
from tracetool.backend.dtrace import binary, probeprefix
|
||||
from tracetool.backend.simple import is_string
|
||||
from tracetool.format.stap import stap_escape
|
||||
|
||||
|
||||
def generate(events, backend):
|
||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||
'')
|
||||
|
||||
for event_id, e in enumerate(events):
|
||||
if 'disable' in e.properties:
|
||||
continue
|
||||
|
||||
out('probe %(probeprefix)s.simpletrace.%(name)s = %(probeprefix)s.%(name)s ?',
|
||||
'{',
|
||||
probeprefix=probeprefix(),
|
||||
name=e.name)
|
||||
|
||||
# Calculate record size
|
||||
sizes = ['24'] # sizeof(TraceRecord)
|
||||
for type_, name in e.args:
|
||||
name = stap_escape(name)
|
||||
if is_string(type_):
|
||||
out(' try {',
|
||||
' arg%(name)s_str = %(name)s ? user_string_n(%(name)s, 512) : "<null>"',
|
||||
' } catch {}',
|
||||
' arg%(name)s_len = strlen(arg%(name)s_str)',
|
||||
name=name)
|
||||
sizes.append('4 + arg%s_len' % name)
|
||||
else:
|
||||
sizes.append('8')
|
||||
sizestr = ' + '.join(sizes)
|
||||
|
||||
# Generate format string and value pairs for record header and arguments
|
||||
fields = [('8b', str(event_id)),
|
||||
('8b', 'gettimeofday_ns()'),
|
||||
('4b', sizestr),
|
||||
('4b', 'pid()')]
|
||||
for type_, name in e.args:
|
||||
name = stap_escape(name)
|
||||
if is_string(type_):
|
||||
fields.extend([('4b', 'arg%s_len' % name),
|
||||
('.*s', 'arg%s_len, arg%s_str' % (name, name))])
|
||||
else:
|
||||
fields.append(('8b', name))
|
||||
|
||||
# Emit the entire record in a single SystemTap printf()
|
||||
fmt_str = '%'.join(fmt for fmt, _ in fields)
|
||||
arg_str = ', '.join(arg for _, arg in fields)
|
||||
out(' printf("%%%(fmt_str)s", %(arg_str)s)',
|
||||
fmt_str=fmt_str, arg_str=arg_str)
|
||||
|
||||
out('}')
|
||||
|
||||
out()
|
||||
@@ -27,6 +27,13 @@ RESERVED_WORDS = (
|
||||
)
|
||||
|
||||
|
||||
def stap_escape(identifier):
|
||||
# Append underscore to reserved keywords
|
||||
if identifier in RESERVED_WORDS:
|
||||
return identifier + '_'
|
||||
return identifier
|
||||
|
||||
|
||||
def generate(events, backend):
|
||||
events = [e for e in events
|
||||
if "disable" not in e.properties]
|
||||
@@ -45,9 +52,7 @@ def generate(events, backend):
|
||||
i = 1
|
||||
if len(e.args) > 0:
|
||||
for name in e.args.names():
|
||||
# Append underscore to reserved keywords
|
||||
if name in RESERVED_WORDS:
|
||||
name += '_'
|
||||
name = stap_escape(name)
|
||||
out(' %s = $arg%d;' % (name, i))
|
||||
i += 1
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Generate .h file for TCG code generation.
|
||||
"""
|
||||
|
||||
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
|
||||
__copyright__ = "Copyright 2012-2014, 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 generate(events, backend):
|
||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||
'/* You must include this file after the inclusion of helper.h */',
|
||||
'',
|
||||
'#ifndef TRACE__GENERATED_TCG_TRACERS_H',
|
||||
'#define TRACE__GENERATED_TCG_TRACERS_H',
|
||||
'',
|
||||
'#include <stdint.h>',
|
||||
'',
|
||||
'#include "trace.h"',
|
||||
'#include "exec/helper-proto.h"',
|
||||
'',
|
||||
)
|
||||
|
||||
for e in events:
|
||||
# just keep one of them
|
||||
if "tcg-trans" not in e.properties:
|
||||
continue
|
||||
|
||||
# get the original event definition
|
||||
e = e.original.original
|
||||
|
||||
out('static inline void %(name_tcg)s(%(args)s)',
|
||||
'{',
|
||||
name_tcg=e.api(e.QEMU_TRACE_TCG),
|
||||
args=e.args)
|
||||
|
||||
if "disable" not in e.properties:
|
||||
out(' %(name_trans)s(%(argnames_trans)s);',
|
||||
' gen_helper_%(name_exec)s(%(argnames_exec)s);',
|
||||
name_trans=e.event_trans.api(e.QEMU_TRACE),
|
||||
name_exec=e.event_exec.api(e.QEMU_TRACE),
|
||||
argnames_trans=", ".join(e.event_trans.args.names()),
|
||||
argnames_exec=", ".join(e.event_exec.args.names()))
|
||||
|
||||
out('}')
|
||||
|
||||
out('',
|
||||
'#endif /* TRACE__GENERATED_TCG_TRACERS_H */')
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Generate trace/generated-helpers.c.
|
||||
"""
|
||||
|
||||
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
|
||||
__copyright__ = "Copyright 2012-2014, 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
|
||||
from tracetool.transform import *
|
||||
|
||||
|
||||
def generate(events, backend):
|
||||
events = [e for e in events
|
||||
if "disable" not in e.properties]
|
||||
|
||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||
'',
|
||||
'#include "qemu-common.h"',
|
||||
'#include "trace.h"',
|
||||
'#include "exec/helper-proto.h"',
|
||||
'',
|
||||
)
|
||||
|
||||
for e in events:
|
||||
if "tcg-exec" not in e.properties:
|
||||
continue
|
||||
|
||||
# tracetool.generate always transforms types to host
|
||||
e_args = e.original.args
|
||||
|
||||
values = ["(%s)%s" % (t, n)
|
||||
for t, n in e.args.transform(TCG_2_TCG_HELPER_DEF)]
|
||||
|
||||
out('void %(name_tcg)s(%(args)s)',
|
||||
'{',
|
||||
' %(name)s(%(values)s);',
|
||||
'}',
|
||||
name_tcg="helper_%s_proxy" % e.api(),
|
||||
name=e.api(),
|
||||
args=e_args.transform(HOST_2_TCG_COMPAT, TCG_2_TCG_HELPER_DEF),
|
||||
values=", ".join(values),
|
||||
)
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Generate trace/generated-helpers.h.
|
||||
"""
|
||||
|
||||
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
|
||||
__copyright__ = "Copyright 2012-2014, 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
|
||||
from tracetool.transform import *
|
||||
|
||||
|
||||
def generate(events, backend):
|
||||
events = [e for e in events
|
||||
if "disable" not in e.properties]
|
||||
|
||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||
'',
|
||||
)
|
||||
|
||||
for e in events:
|
||||
if "tcg-exec" not in e.properties:
|
||||
continue
|
||||
|
||||
# tracetool.generate always transforms types to host
|
||||
e_args = e.original.args
|
||||
|
||||
# TCG helper proxy declaration
|
||||
fmt = "DEF_HELPER_FLAGS_%(argc)d(%(name)s, %(flags)svoid%(types)s)"
|
||||
args = e_args.transform(HOST_2_TCG_COMPAT, HOST_2_TCG,
|
||||
TCG_2_TCG_HELPER_DECL)
|
||||
types = ", ".join(args.types())
|
||||
if types != "":
|
||||
types = ", " + types
|
||||
|
||||
flags = "TCG_CALL_NO_RWG, "
|
||||
|
||||
out(fmt,
|
||||
flags=flags,
|
||||
argc=len(args),
|
||||
name=e.api() + "_proxy",
|
||||
types=types,
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user