Add a DTrace tracing backend targetted for SystemTAP compatability
This introduces a new tracing backend that targets the SystemTAP implementation of DTrace userspace tracing. The core functionality should be applicable and standard across any DTrace implementation on Solaris, OS-X, *BSD, but the Makefile rules will likely need some small additional changes to cope with OS specific build requirements. This backend builds a little differently from the other tracing backends. Specifically there is no 'trace.c' file, because the 'dtrace' command line tool generates a '.o' file directly from the dtrace probe definition file. The probe definition is usually named with a '.d' extension but QEMU uses '.d' files for its external makefile dependancy tracking, so this uses '.dtrace' as the extension for the probe definition file. The 'tracetool' program gains the ability to generate a trace.h file for DTrace, and also to generate the trace.d file containing the dtrace probe definition. Example usage of a dtrace probe in systemtap looks like: probe process("qemu").mark("qemu_malloc") { printf("Malloc %d %p\n", $arg1, $arg2); } * .gitignore: Ignore trace-dtrace.* * Makefile: Extra rules for generating DTrace files * Makefile.obj: Don't build trace.o for DTrace, use trace-dtrace.o generated by 'dtrace' instead * tracetool: Support for generating DTrace data files Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
06da6e44d7
commit
b3d08c029d
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,6 +4,8 @@ config-host.*
|
||||
config-target.*
|
||||
trace.h
|
||||
trace.c
|
||||
trace-dtrace.h
|
||||
trace-dtrace.dtrace
|
||||
*-timestamp
|
||||
*-softmmu
|
||||
*-darwin-user
|
||||
|
23
Makefile
23
Makefile
@ -1,6 +1,9 @@
|
||||
# Makefile for QEMU.
|
||||
|
||||
GENERATED_HEADERS = config-host.h trace.h qemu-options.def
|
||||
ifeq ($(TRACE_BACKEND),dtrace)
|
||||
GENERATED_HEADERS += trace-dtrace.h
|
||||
endif
|
||||
|
||||
ifneq ($(wildcard config-host.mak),)
|
||||
# Put the all: rule here so that config-host.mak can contain dependencies.
|
||||
@ -108,7 +111,11 @@ ui/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
|
||||
|
||||
bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
|
||||
|
||||
ifeq ($(TRACE_BACKEND),dtrace)
|
||||
trace.h: trace.h-timestamp trace-dtrace.h
|
||||
else
|
||||
trace.h: trace.h-timestamp
|
||||
endif
|
||||
trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak
|
||||
$(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -h < $< > $@," GEN trace.h")
|
||||
@cmp -s $@ trace.h || cp $@ trace.h
|
||||
@ -120,6 +127,20 @@ trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak
|
||||
|
||||
trace.o: trace.c $(GENERATED_HEADERS)
|
||||
|
||||
trace-dtrace.h: trace-dtrace.dtrace
|
||||
$(call quiet-command,dtrace -o $@ -h -s $<, " GEN trace-dtrace.h")
|
||||
|
||||
# Normal practice is to name DTrace probe file with a '.d' extension
|
||||
# but that gets picked up by QEMU's Makefile as an external dependancy
|
||||
# rule file. So we use '.dtrace' instead
|
||||
trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
|
||||
trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events config-host.mak
|
||||
$(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace")
|
||||
@cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace
|
||||
|
||||
trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS)
|
||||
$(call quiet-command,dtrace -o $@ -G -s $<, " GEN trace-dtrace.o")
|
||||
|
||||
simpletrace.o: simpletrace.c $(GENERATED_HEADERS)
|
||||
|
||||
version.o: $(SRC_PATH)/version.rc config-host.mak
|
||||
@ -157,6 +178,8 @@ clean:
|
||||
rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d
|
||||
rm -f qemu-img-cmds.h
|
||||
rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp
|
||||
rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp
|
||||
rm -f trace-dtrace.h trace-dtrace.h-timestamp
|
||||
$(MAKE) -C tests clean
|
||||
for d in $(ALL_SUBDIRS) libhw32 libhw64 libuser libdis libdis-user; do \
|
||||
if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
|
||||
|
@ -286,11 +286,15 @@ libdis-$(CONFIG_SPARC_DIS) += sparc-dis.o
|
||||
######################################################################
|
||||
# trace
|
||||
|
||||
ifeq ($(TRACE_BACKEND),dtrace)
|
||||
trace-obj-y = trace-dtrace.o
|
||||
else
|
||||
trace-obj-y = trace.o
|
||||
ifeq ($(TRACE_BACKEND),simple)
|
||||
trace-obj-y += simpletrace.o
|
||||
user-obj-y += qemu-timer-common.o
|
||||
endif
|
||||
endif
|
||||
|
||||
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
|
||||
|
||||
|
14
configure
vendored
14
configure
vendored
@ -929,7 +929,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 " --trace-backend=B Trace backend nop simple ust"
|
||||
echo " --trace-backend=B Trace backend nop simple ust dtrace"
|
||||
echo " --trace-file=NAME Full PATH,NAME of file to store traces"
|
||||
echo " Default:trace-<pid>"
|
||||
echo " --disable-spice disable spice"
|
||||
@ -2193,6 +2193,18 @@ EOF
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# For 'dtrace' backend, test if 'dtrace' command is present
|
||||
if test "$trace_backend" = "dtrace"; then
|
||||
if ! has 'dtrace' ; then
|
||||
echo
|
||||
echo "Error: dtrace command is not found in PATH $PATH"
|
||||
echo
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# End of CC checks
|
||||
# After here, no more $cc or $ld runs
|
||||
|
122
tracetool
122
tracetool
@ -20,10 +20,12 @@ Backends:
|
||||
--nop Tracing disabled
|
||||
--simple Simple built-in backend
|
||||
--ust LTTng User Space Tracing backend
|
||||
--dtrace DTrace/SystemTAP backend
|
||||
|
||||
Output formats:
|
||||
-h Generate .h file
|
||||
-c Generate .c file
|
||||
-d Generate .d file (DTrace only)
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
@ -46,8 +48,9 @@ get_args()
|
||||
# Get the argument name list of a trace event
|
||||
get_argnames()
|
||||
{
|
||||
local nfields field name
|
||||
local nfields field name sep
|
||||
nfields=0
|
||||
sep="$2"
|
||||
for field in $(get_args "$1"); do
|
||||
nfields=$((nfields + 1))
|
||||
|
||||
@ -58,7 +61,7 @@ get_argnames()
|
||||
name=${field%,}
|
||||
test "$field" = "$name" && continue
|
||||
|
||||
printf "%s" "$name, "
|
||||
printf "%s%s " $name $sep
|
||||
done
|
||||
|
||||
# Last argument name
|
||||
@ -73,7 +76,7 @@ get_argc()
|
||||
{
|
||||
local name argc
|
||||
argc=0
|
||||
for name in $(get_argnames "$1"); do
|
||||
for name in $(get_argnames "$1", ","); do
|
||||
argc=$((argc + 1))
|
||||
done
|
||||
echo $argc
|
||||
@ -154,7 +157,7 @@ EOF
|
||||
cast_args_to_uint64_t()
|
||||
{
|
||||
local arg
|
||||
for arg in $(get_argnames "$1"); do
|
||||
for arg in $(get_argnames "$1", ","); do
|
||||
printf "%s" "(uint64_t)(uintptr_t)$arg"
|
||||
done
|
||||
}
|
||||
@ -247,7 +250,7 @@ linetoh_ust()
|
||||
local name args argnames
|
||||
name=$(get_name "$1")
|
||||
args=$(get_args "$1")
|
||||
argnames=$(get_argnames "$1")
|
||||
argnames=$(get_argnames "$1", ",")
|
||||
|
||||
cat <<EOF
|
||||
DECLARE_TRACE(ust_$name, TP_PROTO($args), TP_ARGS($argnames));
|
||||
@ -274,7 +277,7 @@ linetoc_ust()
|
||||
local name args argnames fmt
|
||||
name=$(get_name "$1")
|
||||
args=$(get_args "$1")
|
||||
argnames=$(get_argnames "$1")
|
||||
argnames=$(get_argnames "$1", ",")
|
||||
fmt=$(get_fmt "$1")
|
||||
|
||||
cat <<EOF
|
||||
@ -306,6 +309,93 @@ EOF
|
||||
echo "}"
|
||||
}
|
||||
|
||||
linetoh_begin_dtrace()
|
||||
{
|
||||
cat <<EOF
|
||||
#include "trace-dtrace.h"
|
||||
EOF
|
||||
}
|
||||
|
||||
linetoh_dtrace()
|
||||
{
|
||||
local name args argnames state nameupper
|
||||
name=$(get_name "$1")
|
||||
args=$(get_args "$1")
|
||||
argnames=$(get_argnames "$1", ",")
|
||||
state=$(get_state "$1")
|
||||
if [ "$state" = "0" ] ; then
|
||||
name=${name##disable }
|
||||
fi
|
||||
|
||||
nameupper=`echo $name | tr '[:lower:]' '[:upper:]'`
|
||||
|
||||
# Define an empty function for the trace event
|
||||
cat <<EOF
|
||||
static inline void trace_$name($args) {
|
||||
if (QEMU_${nameupper}_ENABLED()) {
|
||||
QEMU_${nameupper}($argnames);
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
linetoh_end_dtrace()
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
linetoc_begin_dtrace()
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
linetoc_dtrace()
|
||||
{
|
||||
# No need for function definitions in dtrace backend
|
||||
return
|
||||
}
|
||||
|
||||
linetoc_end_dtrace()
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
linetod_begin_dtrace()
|
||||
{
|
||||
cat <<EOF
|
||||
provider qemu {
|
||||
EOF
|
||||
}
|
||||
|
||||
linetod_dtrace()
|
||||
{
|
||||
local name args state
|
||||
name=$(get_name "$1")
|
||||
args=$(get_args "$1")
|
||||
state=$(get_state "$1")
|
||||
if [ "$state" = "0" ] ; then
|
||||
name=${name##disable }
|
||||
fi
|
||||
|
||||
# DTrace provider syntax expects foo() for empty
|
||||
# params, not foo(void)
|
||||
if [ "$args" = "void" ]; then
|
||||
args=""
|
||||
fi
|
||||
|
||||
# Define prototype for probe arguments
|
||||
cat <<EOF
|
||||
probe $name($args);
|
||||
EOF
|
||||
}
|
||||
|
||||
linetod_end_dtrace()
|
||||
{
|
||||
cat <<EOF
|
||||
};
|
||||
EOF
|
||||
}
|
||||
|
||||
# Process stdin by calling begin, line, and end functions for the backend
|
||||
convert()
|
||||
{
|
||||
@ -324,9 +414,10 @@ convert()
|
||||
disable=${str%%disable *}
|
||||
echo
|
||||
if test -z "$disable"; then
|
||||
# Pass the disabled state as an arg to lineto$1_simple().
|
||||
# For all other cases, call lineto$1_nop()
|
||||
if [ $backend = "simple" ]; then
|
||||
# Pass the disabled state as an arg for the simple
|
||||
# or DTrace backends which handle it dynamically.
|
||||
# For all other backends, call lineto$1_nop()
|
||||
if [ $backend = "simple" -o "$backend" = "dtrace" ]; then
|
||||
"$process_line" "$str"
|
||||
else
|
||||
"lineto$1_nop" "${str##disable }"
|
||||
@ -360,9 +451,19 @@ tracetoc()
|
||||
convert c
|
||||
}
|
||||
|
||||
tracetod()
|
||||
{
|
||||
if [ $backend != "dtrace" ]; then
|
||||
echo "DTrace probe generator not applicable to $backend backend"
|
||||
exit 1
|
||||
fi
|
||||
echo "/* This file is autogenerated by tracetool, do not edit. */"
|
||||
convert d
|
||||
}
|
||||
|
||||
# Choose backend
|
||||
case "$1" in
|
||||
"--nop" | "--simple" | "--ust") backend="${1#--}" ;;
|
||||
"--nop" | "--simple" | "--ust" | "--dtrace") backend="${1#--}" ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
shift
|
||||
@ -370,6 +471,7 @@ shift
|
||||
case "$1" in
|
||||
"-h") tracetoh ;;
|
||||
"-c") tracetoc ;;
|
||||
"-d") tracetod ;;
|
||||
"--check-backend") exit 0 ;; # used by ./configure to test for backend
|
||||
*) usage ;;
|
||||
esac
|
||||
|
Loading…
Reference in New Issue
Block a user