Skip to content

Commit

Permalink
trace: Add trace-events file for declaring trace events
Browse files Browse the repository at this point in the history
This patch introduces the trace-events file where trace events can be
declared like so:

qemu_malloc(size_t size) "size %zu"
qemu_free(void *ptr) "ptr %p"

These trace event declarations are processed by a new tool called
tracetool to generate code for the trace events.  Trace event
declarations are independent of the backend tracing system (LTTng User
Space Tracing, ftrace markers, DTrace).

The default "nop" backend generates empty trace event functions.
Therefore trace events are disabled by default.

The trace-events file serves two purposes:

1. Adding trace events is easy.  It is not necessary to understand the
   details of a backend tracing system.  The trace-events file is a
   single location where trace events can be declared without code
   duplication.

2. QEMU is not tightly coupled to one particular backend tracing system.
   In order to support tracing across QEMU host platforms and to
   anticipate new backend tracing systems that are currently maturing,
   it is important to be flexible and not tied to one system.

This commit includes fixes from Prerna Saxena
<[email protected]> and Blue Swirl <[email protected]>.

Signed-off-by: Stefan Hajnoczi <[email protected]>
  • Loading branch information
Stefan Hajnoczi authored and Anthony Liguori committed Sep 9, 2010
1 parent ef9d48d commit 94a420b
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 4 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ config-devices.*
config-all-devices.*
config-host.*
config-target.*
trace.h
trace.c
*-softmmu
*-darwin-user
*-linux-user
Expand Down
17 changes: 13 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Makefile for QEMU.

GENERATED_HEADERS = config-host.h
GENERATED_HEADERS = config-host.h trace.h

ifneq ($(wildcard config-host.mak),)
# Put the all: rule here so that config-host.mak can contain dependencies.
Expand Down Expand Up @@ -104,16 +104,24 @@ ui/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS)

bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)

trace.h: $(SRC_PATH)/trace-events config-host.mak
$(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -h < $< > $@," GEN $@")

trace.c: $(SRC_PATH)/trace-events config-host.mak
$(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -c < $< > $@," GEN $@")

trace.o: trace.c $(GENERATED_HEADERS)

######################################################################

qemu-img.o: qemu-img-cmds.h
qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o: $(GENERATED_HEADERS)

qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(block-obj-y) $(qobject-obj-y)
qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-obj-y) $(qobject-obj-y)

qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o qemu-error.o $(block-obj-y) $(qobject-obj-y)
qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-obj-y) $(qobject-obj-y)

qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(block-obj-y) $(qobject-obj-y)
qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-obj-y) $(qobject-obj-y)

qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $@")
Expand All @@ -133,6 +141,7 @@ clean:
rm -f *.o *.d *.a $(TOOLS) TAGS cscope.* *.pod *~ */*~
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
$(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; \
Expand Down
5 changes: 5 additions & 0 deletions Makefile.objs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ libdis-$(CONFIG_S390_DIS) += s390-dis.o
libdis-$(CONFIG_SH4_DIS) += sh4-dis.o
libdis-$(CONFIG_SPARC_DIS) += sparc-dis.o

######################################################################
# trace

trace-obj-y = trace.o

vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)

vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
Expand Down
1 change: 1 addition & 0 deletions Makefile.target
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))

endif # CONFIG_SOFTMMU

obj-y += $(addprefix ../, $(trace-obj-y))
obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o

$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
Expand Down
18 changes: 18 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ pkgversion=""
check_utests="no"
user_pie="no"
zero_malloc=""
trace_backend="nop"

# OS specific
if check_define __linux__ ; then
Expand Down Expand Up @@ -519,6 +520,8 @@ for opt do
;;
--target-list=*) target_list="$optarg"
;;
--trace-backend=*) trace_backend="$optarg"
;;
--enable-gprof) gprof="yes"
;;
--static)
Expand Down Expand Up @@ -897,6 +900,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"
echo ""
echo "NOTE: The object files are built at the place where configure is launched"
exit 1
Expand Down Expand Up @@ -2059,6 +2063,18 @@ if compile_prog "" "" ; then
fdatasync=yes
fi

##########################################
# check if trace backend exists

sh "$source_path/tracetool" "--$trace_backend" --check-backend > /dev/null 2> /dev/null
if test "$?" -ne 0 ; then
echo
echo "Error: invalid trace backend"
echo "Please choose a supported trace backend."
echo
exit 1
fi

# End of CC checks
# After here, no more $cc or $ld runs

Expand Down Expand Up @@ -2189,6 +2205,7 @@ echo "preadv support $preadv"
echo "fdatasync $fdatasync"
echo "uuid support $uuid"
echo "vhost-net support $vhost_net"
echo "Trace backend $trace_backend"

if test $sdl_too_old = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
Expand Down Expand Up @@ -2450,6 +2467,7 @@ bsd)
;;
esac

echo "TRACE_BACKEND=$trace_backend" >> $config_host_mak
echo "TOOLS=$tools" >> $config_host_mak
echo "ROMS=$roms" >> $config_host_mak
echo "MAKE=$make" >> $config_host_mak
Expand Down
24 changes: 24 additions & 0 deletions trace-events
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Trace events for debugging and performance instrumentation
#
# This file is processed by the tracetool script during the build.
#
# To add a new trace event:
#
# 1. Choose a name for the trace event. Declare its arguments and format
# string.
#
# 2. Call the trace event from code using trace_##name, e.g. multiwrite_cb() ->
# trace_multiwrite_cb(). The source file must #include "trace.h".
#
# Format of a trace event:
#
# <name>(<type1> <arg1>[, <type2> <arg2>] ...) "<format-string>"
#
# Example: qemu_malloc(size_t size) "size %zu"
#
# The <name> must be a valid as a C function name.
#
# Types should be standard C types. Use void * for pointers because the trace
# system may not have the necessary headers included.
#
# The <format-string> should be a sprintf()-compatible format string.
175 changes: 175 additions & 0 deletions tracetool
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#!/bin/sh
#
# Code generator for trace events
#
# Copyright IBM, Corp. 2010
#
# This work is licensed under the terms of the GNU GPL, version 2. See
# the COPYING file in the top-level directory.

# Disable pathname expansion, makes processing text with '*' characters simpler
set -f

usage()
{
cat >&2 <<EOF
usage: $0 --nop [-h | -c]
Generate tracing code for a file on stdin.
Backends:
--nop Tracing disabled
Output formats:
-h Generate .h file
-c Generate .c file
EOF
exit 1
}

# Get the name of a trace event
get_name()
{
echo ${1%%\(*}
}

# Get the argument list of a trace event, including types and names
get_args()
{
local args
args=${1#*\(}
args=${args%)*}
echo "$args"
}

# Get the argument name list of a trace event
get_argnames()
{
local nfields field name
nfields=0
for field in $(get_args "$1"); do
nfields=$((nfields + 1))

# Drop pointer star
field=${field#\*}

# Only argument names have commas at the end
name=${field%,}
test "$field" = "$name" && continue

printf "%s" "$name, "
done

# Last argument name
if [ "$nfields" -gt 1 ]
then
printf "%s" "$name"
fi
}

# Get the format string for a trace event
get_fmt()
{
local fmt
fmt=${1#*\"}
fmt=${fmt%\"*}
echo "$fmt"
}

linetoh_begin_nop()
{
return
}

linetoh_nop()
{
local name args
name=$(get_name "$1")
args=$(get_args "$1")

# Define an empty function for the trace event
cat <<EOF
static inline void trace_$name($args)
{
}
EOF
}

linetoh_end_nop()
{
return
}

linetoc_begin_nop()
{
return
}

linetoc_nop()
{
# No need for function definitions in nop backend
return
}

linetoc_end_nop()
{
return
}

# Process stdin by calling begin, line, and end functions for the backend
convert()
{
local begin process_line end
begin="lineto$1_begin_$backend"
process_line="lineto$1_$backend"
end="lineto$1_end_$backend"

"$begin"

while read -r str; do
# Skip comments and empty lines
str=${str%%#*}
test -z "$str" && continue

echo
"$process_line" "$str"
done

echo
"$end"
}

tracetoh()
{
cat <<EOF
#ifndef TRACE_H
#define TRACE_H
/* This file is autogenerated by tracetool, do not edit. */
#include "qemu-common.h"
EOF
convert h
echo "#endif /* TRACE_H */"
}

tracetoc()
{
echo "/* This file is autogenerated by tracetool, do not edit. */"
convert c
}

# Choose backend
case "$1" in
"--nop") backend="${1#--}" ;;
*) usage ;;
esac
shift

case "$1" in
"-h") tracetoh ;;
"-c") tracetoc ;;
"--check-backend") exit 0 ;; # used by ./configure to test for backend
*) usage ;;
esac

exit 0

0 comments on commit 94a420b

Please sign in to comment.