@@ -2,6 +2,8 @@ config-devices.*
config-all-devices.*
config-host.*
config-target.*
+trace.h
+trace.c
*-softmmu
*-darwin-user
*-linux-user
@@ -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.
@@ -130,16 +130,24 @@ bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
iov.o: iov.c iov.h
+trace.h: trace-events
+ $(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -h < $< > $@," GEN $@")
+
+trace.c: trace-events
+ $(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -c < $< > $@," GEN $@")
+
+trace.o: trace.c
+
######################################################################
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 $@")
@@ -157,6 +165,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
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; \
@@ -248,6 +248,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)
@@ -294,6 +294,7 @@ $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
obj-y += $(addprefix ../, $(common-obj-y))
obj-y += $(addprefix ../libdis/, $(libdis-y))
+obj-y += $(addprefix ../, $(trace-obj-y))
obj-y += $(libobj-y)
obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))
@@ -299,6 +299,7 @@ pkgversion=""
check_utests="no"
user_pie="no"
zero_malloc=""
+trace_backend="nop"
# OS specific
if check_define __linux__ ; then
@@ -494,6 +495,8 @@ for opt do
;;
--target-list=*) target_list="$optarg"
;;
+ --trace-backend=*) trace_backend="$optarg"
+ ;;
--enable-gprof) gprof="yes"
;;
--static)
@@ -826,6 +829,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
@@ -1914,6 +1918,18 @@ if compile_prog "" "" ; then
fdatasync=yes
fi
+##########################################
+# check if trace backend exists
+
+sh 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
@@ -2041,6 +2057,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"
@@ -2284,6 +2301,8 @@ bsd)
;;
esac
+echo "TRACE_BACKEND=$trace_backend" >> $config_host_mak
+
tools=
if test `expr "$target_list" : ".*softmmu.*"` != 0 ; then
tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
new file mode 100644
@@ -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.
new file mode 100755
@@ -0,0 +1,162 @@
+#!/bin/sh
+
+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 first field name
+ for field in $(get_args "$1"); do
+ # Drop pointer star
+ field=${field#\*}
+
+ # Only argument names have commas at the end
+ name=${field%,}
+ test "$field" = "$name" && continue
+
+ echo -n "$name, "
+ done
+ echo -n "$name"
+}
+
+# Get the format string for a trace event
+get_fmt()
+{
+ local fmt
+ fmt=${1#*\"}
+ fmt=${fmt%\"*}
+ echo "$fmt"
+}
+
+warn_autogen_c()
+{
+ echo "/* This file is autogenerated by tracetool, do not edit. */"
+}
+
+warn_autogen_h()
+{
+ echo "/* This file is autogenerated by tracetool, do not edit. */"
+}
+
+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"
+
+ warn_autogen_$1
+ "$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()
+{
+ echo "#ifndef TRACE_H"
+ echo "#define TRACE_H"
+ echo
+ convert h
+ echo "#endif /* TRACE_H */"
+}
+
+tracetoc()
+{
+ 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