diff mbox

[1/2] Add a DTrace tracing backend targetted for SystemTAP compatability

Message ID 1289244788-19961-2-git-send-email-berrange@redhat.com
State New
Headers show

Commit Message

Daniel P. Berrangé Nov. 8, 2010, 7:33 p.m. UTC
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

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 .gitignore    |    2 +
 Makefile      |   23 +++++++++++
 Makefile.objs |    4 ++
 configure     |   14 ++++++-
 tracetool     |  116 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 5 files changed, 148 insertions(+), 11 deletions(-)

Comments

Anthony Liguori Nov. 16, 2010, 3:46 p.m. UTC | #1
On 11/08/2010 01:33 PM, Daniel P. Berrange wrote:
> 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
>
> Signed-off-by: Daniel P. Berrange<berrange@redhat.com>
>    

Applied both.  Thanks.

Regards,

Anthony Liguori

> ---
>   .gitignore    |    2 +
>   Makefile      |   23 +++++++++++
>   Makefile.objs |    4 ++
>   configure     |   14 ++++++-
>   tracetool     |  116 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
>   5 files changed, 148 insertions(+), 11 deletions(-)
>
> diff --git a/.gitignore b/.gitignore
> index a43e4d1..3efb4ec 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -4,6 +4,8 @@ config-host.*
>   config-target.*
>   trace.h
>   trace.c
> +trace-dtrace.h
> +trace-dtrace.dtrace
>   *-timestamp
>   *-softmmu
>   *-darwin-user
> diff --git a/Makefile b/Makefile
> index 02698e9..554ad97 100644
> --- a/Makefile
> +++ b/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; \
> diff --git a/Makefile.objs b/Makefile.objs
> index faf485e..84fc80e 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -285,11 +285,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)
>
> diff --git a/configure b/configure
> index 7025d2b..f8dad3e 100755
> --- a/configure
> +++ b/configure
> @@ -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
> diff --git a/tracetool b/tracetool
> index 7010858..5b6636a 100755
> --- a/tracetool
> +++ b/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,87 @@ 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
> +
> +    # 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 +408,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 +445,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 +465,7 @@ shift
>   case "$1" in
>   "-h") tracetoh ;;
>   "-c") tracetoc ;;
> +"-d") tracetod ;;
>   "--check-backend") exit 0 ;; # used by ./configure to test for backend
>   *) usage ;;
>   esac
>
Peter Maydell Nov. 16, 2010, 5:43 p.m. UTC | #2
On 16 November 2010 15:46, Anthony Liguori <anthony@codemonkey.ws> wrote:
> On 11/08/2010 01:33 PM, Daniel P. Berrange wrote:
>> This introduces a new tracing backend that targets the SystemTAP
>> implementation of DTrace userspace tracing.

> Applied both.  Thanks.

Unfortunately these commits:
2834c3e Add support for generating a systemtap tapset static probes
4addb11 Add a DTrace tracing backend targetted for SystemTAP compatability

seem to have broken building on x86:
 git clone git://git.qemu.org/qemu.git
 cd qemu
 ./configure
 make

fails with
  LINK  i386-softmmu/trace
/usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib/crt1.o: In
function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status

Incidentally, although trace.c is autogenerated, if you delete it and
then type make this does not cause it to be regenerated, which
seems wrong to me.

-- PMM
Anthony Liguori Nov. 16, 2010, 6:10 p.m. UTC | #3
On 11/16/2010 11:43 AM, Peter Maydell wrote:
> On 16 November 2010 15:46, Anthony Liguori<anthony@codemonkey.ws>  wrote:
>    
>> On 11/08/2010 01:33 PM, Daniel P. Berrange wrote:
>>      
>>> This introduces a new tracing backend that targets the SystemTAP
>>> implementation of DTrace userspace tracing.
>>>        
>    
>> Applied both.  Thanks.
>>      
> Unfortunately these commits:
> 2834c3e Add support for generating a systemtap tapset static probes
> 4addb11 Add a DTrace tracing backend targetted for SystemTAP compatability
>    

What's your configure output?

I don't have the right environment to build with systemtap support, but 
--trace-backend=nop should work regardless.

Regards,

Anthony Liguori

> seem to have broken building on x86:
>   git clone git://git.qemu.org/qemu.git
>   cd qemu
>   ./configure
>   make
>
> fails with
>    LINK  i386-softmmu/trace
> /usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../../lib/crt1.o: In
> function `_start':
> (.text+0x20): undefined reference to `main'
> collect2: ld returned 1 exit status
>
> Incidentally, although trace.c is autogenerated, if you delete it and
> then type make this does not cause it to be regenerated, which
> seems wrong to me.
>
> -- PMM
>
Peter Maydell Nov. 16, 2010, 6:54 p.m. UTC | #4
On 16 November 2010 18:10, Anthony Liguori <anthony@codemonkey.ws> wrote:
> On 11/16/2010 11:43 AM, Peter Maydell wrote:
>> Unfortunately these commits:
>> 2834c3e Add support for generating a systemtap tapset static probes
>> 4addb11 Add a DTrace tracing backend targetted for SystemTAP compatability
>
> What's your configure output?

I've attached it; the trace related bits are:
Trace backend     nop
Trace output file trace-<pid>

> I don't have the right environment to build with systemtap support, but
> --trace-backend=nop should work regardless.

I'm using the nop backend, yes.

I think the problem is that commit 2834c3e adds a target 'trace:' to the
Makefile.target which looks like it's intended to be a phony target. However
it isn't marked as such, so make actually tries to create a binary 'trace'
by falling back to its default rules (since there's a "trace.c" in the root
directory):

petmay01@LinaroE102767:~/qemu-test/qemu/i386-softmmu$ make -n trace
echo "  CC    trace.o" && gcc -I/home/petmay01/qemu-test/qemu/slirp
-Werror -m64 -I. -I/home/petmay01/qemu-test/qemu -D_FORTIFY_SOURCE=2
-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
-Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wendif-labels
-Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing
-fstack-protector-all -Wempty-body -Wnested-externs -Wformat-security
-Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration
-Wold-style-definition -Wtype-limits -DHAS_AUDIO -DHAS_AUDIO_CHOICE
-I/home/petmay01/qemu-test/qemu/fpu
-I/home/petmay01/qemu-test/qemu/tcg
-I/home/petmay01/qemu-test/qemu/tcg/i386  -DTARGET_PHYS_ADDR_BITS=32
-I.. -I/home/petmay01/qemu-test/qemu/target-i386 -DNEED_CPU_H     -MMD
-MP -MT trace.o -MF ./trace.d -O2 -g  -c -o trace.o
/home/petmay01/qemu-test/qemu/trace.c
echo "  LINK  trace" && gcc -I/home/petmay01/qemu-test/qemu/slirp
-Werror -m64 -I. -I/home/petmay01/qemu-test/qemu -D_FORTIFY_SOURCE=2
-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
-Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wendif-labels
-Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing
-fstack-protector-all -Wempty-body -Wnested-externs -Wformat-security
-Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration
-Wold-style-definition -Wtype-limits -DHAS_AUDIO -DHAS_AUDIO_CHOICE
-I/home/petmay01/qemu-test/qemu/fpu
-I/home/petmay01/qemu-test/qemu/tcg
-I/home/petmay01/qemu-test/qemu/tcg/i386  -DTARGET_PHYS_ADDR_BITS=32
-I.. -I/home/petmay01/qemu-test/qemu/target-i386 -DNEED_CPU_H     -O2
-g  -Wl,--warn-common -m64 -g   -o trace trace.o -lrt -lpthread
-lutil -lcurl   -lncurses  -luuid -lpng -lsasl2 -lgnutls   -lSDL
-lX11  -laio -lm -lz

...and linking only trace.o into a binary 'trace' fails because
trace.c doesn't have a main() (or indeed any functions at all).

If I add a ".PHONY: trace" or change the "trace" target
name to "tracexyzzy" then this fixes the problem.

-- PMM
Anthony Liguori Nov. 16, 2010, 6:58 p.m. UTC | #5
On 11/16/2010 12:54 PM, Peter Maydell wrote:
> On 16 November 2010 18:10, Anthony Liguori<anthony@codemonkey.ws>  wrote:
>    
>> On 11/16/2010 11:43 AM, Peter Maydell wrote:
>>      
>>> Unfortunately these commits:
>>> 2834c3e Add support for generating a systemtap tapset static probes
>>> 4addb11 Add a DTrace tracing backend targetted for SystemTAP compatability
>>>        
>> What's your configure output?
>>      
> I've attached it; the trace related bits are:
> Trace backend     nop
> Trace output file trace-<pid>
>
>    
>> I don't have the right environment to build with systemtap support, but
>> --trace-backend=nop should work regardless.
>>      
> I'm using the nop backend, yes.
>
> I think the problem is that commit 2834c3e adds a target 'trace:' to the
> Makefile.target which looks like it's intended to be a phony target. However
> it isn't marked as such, so make actually tries to create a binary 'trace'
> by falling back to its default rules (since there's a "trace.c" in the root
> directory):
>
> petmay01@LinaroE102767:~/qemu-test/qemu/i386-softmmu$ make -n trace
> echo "  CC    trace.o"&&  gcc -I/home/petmay01/qemu-test/qemu/slirp
> -Werror -m64 -I. -I/home/petmay01/qemu-test/qemu -D_FORTIFY_SOURCE=2
> -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
> -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wendif-labels
> -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing
> -fstack-protector-all -Wempty-body -Wnested-externs -Wformat-security
> -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration
> -Wold-style-definition -Wtype-limits -DHAS_AUDIO -DHAS_AUDIO_CHOICE
> -I/home/petmay01/qemu-test/qemu/fpu
> -I/home/petmay01/qemu-test/qemu/tcg
> -I/home/petmay01/qemu-test/qemu/tcg/i386  -DTARGET_PHYS_ADDR_BITS=32
> -I.. -I/home/petmay01/qemu-test/qemu/target-i386 -DNEED_CPU_H     -MMD
> -MP -MT trace.o -MF ./trace.d -O2 -g  -c -o trace.o
> /home/petmay01/qemu-test/qemu/trace.c
> echo "  LINK  trace"&&  gcc -I/home/petmay01/qemu-test/qemu/slirp
> -Werror -m64 -I. -I/home/petmay01/qemu-test/qemu -D_FORTIFY_SOURCE=2
> -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
> -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wendif-labels
> -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing
> -fstack-protector-all -Wempty-body -Wnested-externs -Wformat-security
> -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration
> -Wold-style-definition -Wtype-limits -DHAS_AUDIO -DHAS_AUDIO_CHOICE
> -I/home/petmay01/qemu-test/qemu/fpu
> -I/home/petmay01/qemu-test/qemu/tcg
> -I/home/petmay01/qemu-test/qemu/tcg/i386  -DTARGET_PHYS_ADDR_BITS=32
> -I.. -I/home/petmay01/qemu-test/qemu/target-i386 -DNEED_CPU_H     -O2
> -g  -Wl,--warn-common -m64 -g   -o trace trace.o -lrt -lpthread
> -lutil -lcurl   -lncurses  -luuid -lpng -lsasl2 -lgnutls   -lSDL
> -lX11  -laio -lm -lz
>
> ...and linking only trace.o into a binary 'trace' fails because
> trace.c doesn't have a main() (or indeed any functions at all).
>
> If I add a ".PHONY: trace" or change the "trace" target
> name to "tracexyzzy" then this fixes the problem.
>    

Curious, care to send a patch?  I think I'm not seeing this because I 
build with srcdir != objdir.

Regards,

Anthony Liguori

> -- PMM
>
Peter Maydell Nov. 16, 2010, 8:22 p.m. UTC | #6
On 16 November 2010 18:58, Anthony Liguori <anthony@codemonkey.ws> wrote:
> On 11/16/2010 12:54 PM, Peter Maydell wrote:
>> If I add a ".PHONY: trace" or change the "trace" target
>> name to "tracexyzzy" then this fixes the problem.
>
> Curious, care to send a patch?  I think I'm not seeing this because I build
> with srcdir != objdir.

Ah, yes, if I build in a different directory to the sources I can build
without having to patch the makefiles. (That feature of configure
doesn't seem to be documented anywhere, unless I've missed
something.)

Anyway, patch sent. I opted to tidy up the makefile a little to avoid
either an ugly target name or a GNU-makeism. I fiddled configure
so I could test the CONFIG_SYSTEMTAP_TRACE bit despite
not having systemtap on this machine, but it would be good if
a real systemtap user could check it.

A couple of oddities I noticed along the way:

(1) How do you get configure to enable CONFIG_SYSTEMTAP_TRACE?
The condition is:
if test "$trace_backend" = "dtrace" -a "$trace_backend_stap" = "yes" ; then
  echo "CONFIG_SYSTEMTAP_TRACE=y" >> $config_host_mak
fi
but trace_backend_stap is only set inside code guarded by
if test "$trace_backend" = "ust"
...
so as far as I can tell the two halves of the -a will never
both be true.

(2) in Makefile.target, the blank line after the all: line:
> all: $(PROGS) $(STPFILES)
>
> # Dummy command so that make thinks it has done something
>         @true

is I think a bit misleading although it is valid makefile syntax.
I suspect it got added by accident.

-- PMM
Daniel P. Berrangé Nov. 17, 2010, 11:35 a.m. UTC | #7
On Tue, Nov 16, 2010 at 09:46:20AM -0600, Anthony Liguori wrote:
> On 11/08/2010 01:33 PM, Daniel P. Berrange wrote:
> >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
> >
> >Signed-off-by: Daniel P. Berrange<berrange@redhat.com>
> >   
> 
> Applied both.  Thanks.


I'm afraid you have applied an old version of the patches. Please
revert these, and apply version 6, from Nov 12th

http://lists.gnu.org/archive/html/qemu-devel/2010-11/msg01033.html

Regards,
Daniel
Daniel P. Berrangé Nov. 17, 2010, 11:36 a.m. UTC | #8
On Tue, Nov 16, 2010 at 06:54:57PM +0000, Peter Maydell wrote:
> On 16 November 2010 18:10, Anthony Liguori <anthony@codemonkey.ws> wrote:
> > On 11/16/2010 11:43 AM, Peter Maydell wrote:
> >> Unfortunately these commits:
> >> 2834c3e Add support for generating a systemtap tapset static probes
> >> 4addb11 Add a DTrace tracing backend targetted for SystemTAP compatability
> >
> > What's your configure output?
> 
> I've attached it; the trace related bits are:
> Trace backend     nop
> Trace output file trace-<pid>
> 
> > I don't have the right environment to build with systemtap support, but
> > --trace-backend=nop should work regardless.
> 
> I'm using the nop backend, yes.
> 
> I think the problem is that commit 2834c3e adds a target 'trace:' to the
> Makefile.target which looks like it's intended to be a phony target. However
> it isn't marked as such, so make actually tries to create a binary 'trace'
> by falling back to its default rules (since there's a "trace.c" in the root
> directory):

This Makefile problem was fixed in the v6 patches I posted on Nov 12th

http://lists.gnu.org/archive/html/qemu-devel/2010-11/msg01033.html

Unfortunately the v5 patches were applied by mistake.

Regards,
Daniel
Anthony Liguori Nov. 18, 2010, midnight UTC | #9
On 11/17/2010 05:35 AM, Daniel P. Berrange wrote:
> On Tue, Nov 16, 2010 at 09:46:20AM -0600, Anthony Liguori wrote:
>    
>> On 11/08/2010 01:33 PM, Daniel P. Berrange wrote:
>>      
>>> 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
>>>
>>> Signed-off-by: Daniel P. Berrange<berrange@redhat.com>
>>>
>>>        
>> Applied both.  Thanks.
>>      
>
> I'm afraid you have applied an old version of the patches. Please
> revert these, and apply version 6, from Nov 12th
>    

Sure, sorry about that.

But in the future, please indicate the version somewhere in the patch 
(preferrably the header).

Regards,

Anthony Liguori

> http://lists.gnu.org/archive/html/qemu-devel/2010-11/msg01033.html
>
> Regards,
> Daniel
>
Stefan Hajnoczi Nov. 18, 2010, 3:58 p.m. UTC | #10
On Thu, Nov 18, 2010 at 12:00 AM, Anthony Liguori <anthony@codemonkey.ws> wrote:
>>> Applied both.  Thanks.
>>>
>>
>> I'm afraid you have applied an old version of the patches. Please
>> revert these, and apply version 6, from Nov 12th
>>
>
> Sure, sorry about that.
>
> But in the future, please indicate the version somewhere in the patch
> (preferrably the header).

Here's the changelog from v5 to v6:

 - Fix handling of probes with no-args in DTrace provider
 - Generate one tapset per target, for both system and user
  emulators
 - Re-write command line arg parsing in tracetool so it
  doesn't assume a particular ordering of args
 - Change '-s' to '--stap' in tracetool to avoid confusion
 - Pass full binary name into tracetool

It would be nice to have v6.  Is it possible to revert v5 and apply v6 instead?

Stefan
diff mbox

Patch

diff --git a/.gitignore b/.gitignore
index a43e4d1..3efb4ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,8 @@  config-host.*
 config-target.*
 trace.h
 trace.c
+trace-dtrace.h
+trace-dtrace.dtrace
 *-timestamp
 *-softmmu
 *-darwin-user
diff --git a/Makefile b/Makefile
index 02698e9..554ad97 100644
--- a/Makefile
+++ b/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; \
diff --git a/Makefile.objs b/Makefile.objs
index faf485e..84fc80e 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -285,11 +285,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)
 
diff --git a/configure b/configure
index 7025d2b..f8dad3e 100755
--- a/configure
+++ b/configure
@@ -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
diff --git a/tracetool b/tracetool
index 7010858..5b6636a 100755
--- a/tracetool
+++ b/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,87 @@  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
+
+    # 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 +408,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 +445,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 +465,7 @@  shift
 case "$1" in
 "-h") tracetoh ;;
 "-c") tracetoc ;;
+"-d") tracetod ;;
 "--check-backend") exit 0 ;; # used by ./configure to test for backend
 *) usage ;;
 esac