This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 2/2][RFC] user space instruction tracing example


This patch is an example of how to use the usr_itrace.stp tapset for doing user space instruction tracing on x86.
diff -paurN ../null/Makefile ./Makefile
--- ../null/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ ./Makefile	2007-10-08 13:48:58.000000000 -0700
@@ -0,0 +1,10 @@
+PWD := $(shell pwd)
+
+PROGS=probeme4
+
+default: progs
+
+progs: $(PROGS)
+
+probeme4: probeme4.o
+	cc -g probeme4.c -o probeme4
diff -paurN ../null/README ./README
--- ../null/README	1969-12-31 16:00:00.000000000 -0800
+++ ./README	2007-10-17 13:19:23.000000000 -0700
@@ -0,0 +1,62 @@
+The current support for uprobes in SystemTap requires you to provide the pid
+of the user program and the vaddr of the probe address.  This example tapset
+takes command line arguments pid ($1) and proc_vaddr($2) to set up uprobe
+points to turn on and off user space instruction tracing of a subprogram
+using the usr_itrace.stp tapset interface.  The user program must start up
+(so that it's pid is known) before starting the tapscript, and it must be
+delayed so that it doesn't get past the call to the subprogram being traced.
+
+The simple_usr_itrace_handler() routine in this example simply prints out the ip
+and opcode of each traced instruction.  More elaborate trace data gathering
+routines need to be developed as well as post processing programs to get usable
+results.
+
+To run this example:
+1) build user code
+mkdir usr_itrace
+mv usr_itrace.stp usr_itrace/
+make
+2) find the vaddr of a subprogram to trace
+nm probeme4 | awk '$3=="doit" {print "0x" $1}' > vaddr
+=========== window 1 ===================
+% ./probeme4 1
+I am process 12228
+:
+=========== window 2 ===================
+% stap -g sstep.stp -I usr_itrace 12228 `cat vaddr`
+sstep:usr_itrace_init completed; continue user program
+=========== window 1 ===================
+<hit ENTER to let user program run>
+1 interations in 0.000318 sec
+318.000000 usec per iteration
+sum = 1
+=========== window 2 ===================
+usr_itrace_on(12228)
+sstep:usr_itrace_on(804855e) completed for pid=12228
+ip=8048560 opcode=0x83
+ip=8048563 opcode=0xc7
+ip=804856a opcode=0xc7
+ip=8048571 opcode=0xeb
+ip=8048585 opcode=0x8b
+ip=8048588 opcode=0x3b
+ip=804858b opcode=0x7e
+ip=8048573 opcode=0x8b
+ip=8048576 opcode=0x8b
+ip=8048579 opcode=0xe8
+ip=8048544 opcode=0x55
+ip=8048545 opcode=0x89
+ip=8048547 opcode=0x83
+ip=804854a opcode=0x89
+ip=804854d opcode=0x89
+ip=8048550 opcode=0x8b
+ip=8048553 opcode=0x03
+ip=8048556 opcode=0xc9
+ip=8048557 opcode=0xc3
+ip=804857e opcode=0x89
+ip=8048581 opcode=0x83
+ip=8048585 opcode=0x8b
+ip=8048588 opcode=0x3b
+ip=804858b opcode=0x7e
+ip=804858d opcode=0xe8
+ip=8048558 opcode=0xcc
+sstep:usr_itrace_off(8048592) completed for pid=12228
diff -paurN ../null/probeme4.c ./probeme4.c
--- ../null/probeme4.c	1969-12-31 16:00:00.000000000 -0800
+++ ./probeme4.c	2007-10-12 21:45:22.000000000 -0700
@@ -0,0 +1,53 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include <ucontext.h>
+
+#define noinline __attribute__((noinline))
+#define fastcall __attribute__((regparm(3)))
+
+noinline fastcall static int add(int n1, int n2)
+{
+	return n1 + n2;
+}
+
+noinline int doit(int n)
+{
+	int sum = 0;
+	int i;
+
+	for (i = 1; i <= n; i++) {
+		sum = add(sum, i);
+	}
+	return sum;
+}
+
+main(int argc, char **argv)
+{
+	int n, sum;
+	char line[100];
+	struct timeval start, finish;
+	long usec;
+
+	if (argc != 2 || (n = atoi(argv[1])) <= 0) {
+		fprintf(stderr, "Usage: %s niter\n", argv[0]);
+		exit(1);
+	}
+
+
+	fprintf(stderr, "I am process %d\n:", getpid());
+	fgets(line, 100, stdin);
+
+	(void) gettimeofday(&start, NULL);
+	sum = doit(n);
+	(void) gettimeofday(&finish, NULL);
+	usec = 1000*1000*(finish.tv_sec - start.tv_sec)
+		+ (finish.tv_usec - start.tv_usec);
+	printf("%d interations in %.6f sec\n", n, ((double)usec) / (1000*1000));
+	printf("%.6f usec per iteration\n", ((double)usec) / n);
+	printf("sum = %d\n", sum);
+	exit(0);
+}
diff -paurN ../null/sstep.stp ./sstep.stp
--- ../null/sstep.stp	1969-12-31 16:00:00.000000000 -0800
+++ ./sstep.stp	2007-10-17 13:14:00.000000000 -0700
@@ -0,0 +1,61 @@
+%{
+/* example script that uses user space instruction tracing
+ * Copyright (C) 2005, 2006, 2007 IBM Corp.
+ *
+ * You can redistribute it and/or modify it under the terms of the GNU General
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
+/*
+ * This sample script for doing user space instruction tracing takes 2 command
+ * line arguments to the stap invocation:
+ * 	stap -g sstep.stp <pid> <proc_vaddr>
+ * where
+ *	<pid> is the pid of the user program you are tracing
+ * 	<proc_vaddr> is the vaddr of the subprogram you want to trace
+ *
+ * It requires you to manually determine the vaddr range to tracing and some
+ * way of suspending your user program before you get to the subprogram that
+ * you are tracing, so that you can invoke the stap command.
+ * Unfortunately I couldn't find any way of setting the uprobe using the
+ * tap function target() when using the -c option.  This problem will probably
+ * be solved when full support for uprobes is added to SystemTap.
+ */
+
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+
+static void
+simple_usr_itrace_handler(struct task_struct *tsk, struct pt_regs *regs)
+{
+	unsigned char opcode = *((unsigned char *)instruction_pointer(regs));
+	_stp_printf("ip=%lx opcode=%#2.2x\n",
+				instruction_pointer(regs), opcode);
+}
+%}
+
+function simple_usr_itrace_handler_address:long ()
+%{
+	THIS->__retvalue = (long)&simple_usr_itrace_handler;
+%}
+
+probe process($1).statement($2).absolute
+{
+	if (usr_itrace_on($1))
+		printf("sstep:usr_itrace_on(%x) completed for tid=%d\n", $2, $1)
+}
+
+probe process($1).statement($2).absolute.return
+{
+	usr_itrace_off($1)
+	printf("sstep:usr_itrace_off(%x) completed for tid=%d\n", $2, $1)
+}
+
+probe begin
+{
+	if (usr_itrace_init("single_step", simple_usr_itrace_handler_address()))
+		printf("sstep:usr_itrace_init completed; continue user program\n")
+	else
+		exit()
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]