Dtrace on OpenSolaris!

Since I last updated this page, I have installed OpenSolaris (x86) – it’s rather cool. I now dual boot Ubuntu and OpenSolaris .. if someone wants to know how, leave a comment and I’ll write up a post.

What this post concentrates on though, is dtrace. I was really keen on learning how to use this – it was one of the primary motivations in installing Solaris!

So what is Dtrace? It’s a dynamic tracing facility supported by Solaris – allows you to trace both user programs and the operating system – even on production servers without introducing any overheads. At the moment all I am interested is in the ability to see the parameters being passed to functions in my process. I work on a product which continuously runs in the background, and bugs can be triggered by anything at any point. It isn’t always possible to build the whole product in debug mode and attach a debugger (especially for customer reported bugs), so I really am interested in dtrace. This post isn’t really a tutorial though – it’s for people like me who read the initial documentation but still struggled to understand how it would help them as developers and its really targeted only at the pid provider..

I have a very simple (read dumb :)) example. I have a small program, where I call function xyz(100) in main. I have built this program without debug mode, and want to see the parameters being passed to it.

My C code looks like this:
xyz(int x)
{ /* do something */ }
main()
{
xyz(100);
}
and the corresponding dtrace output looks like this:
dtrace: script './test1_1.d' matched 4 probes
CPU ID FUNCTION:NAME
1 65820 xyz:entry pid 11735 called xyz, parameters 100, cwd = /export/home/ssalunke/prog/dtrace_tests

The Dtrace script to monitor this program:

#!/usr/sbin/dtrace -s
pid$1:a.out::entry
/ execname == "test1" /
{
printf ("pid %d called %s, parameters %d, cwd = %s\n", pid, probefunc, arg0, cwd );
}

pid$1:a.out::entry is the probe description. Let’s dissect this.

  1. pid$1: is the provider – where $1 is the pid I pass as a commandline parameter.
  2. a.out: is the module loaded – in this case, the executable itself. If you wanted to trace any libc calls made, you would put libc there.
  3. : blank – means any function call. If I put say main there, main would be traced.
  4. entry: states that the probe will be fired when the function is entered. If you want to know when the function returns, use return. If you want to trace an instruction at offset 4, use 4

/ execname == “test1” / is called a predicate – this ensures that the actions are performed only when the condition is true. Adding it to my example is not really necessary, but it does ensure that whatever pid I pass as a parameter, the actions will be performed only if that is the pid of a process whose name is “test1”

Everything inside the {} defines the actions to be taken when the probe is ‘fired’. In my example I use some predefined variables – pid, probefunc, arg0, cwd. You can check what these mean in the dtrace manual. arg0, no points for guessing, is the 0th argument.

Variant:
#!/usr/sbin/dtrace -s
pid$target:a.out::entry
{
printf ("pid %d called %s, parameters %d, cwd = %s\n", pid, probefunc, arg0, cwd );
}

For this variant, you can call the script as ./test1.d -c ./test1
where test1.d is your dtrace script, and test1 the program you want to trace. No need to find the pid here.

You can read up on a much more complete example here: Solaris dtrace realworld example.

4 thoughts on “Dtrace on OpenSolaris!

  1. Question!

    > 4. entry: states that the probe will be fired when the function is entered.
    > If you want to know when the function returns, use return. If you want to
    > trace an instruction at offset 4, use 4

    Can you have multiple rules in the dtrace script? For example, is it possible to say, trace the entry as well as the return of all functions?

  2. Too cool 😉 Be sure to check out the other providers like proc and vminfo too. There is a lot of interesting detail that could be dug out with DTrace !

Leave a reply to Ananth Cancel reply