the pid provider and > 10 arguments

A long-time DTrace user was recently examining an ugly C++ application, and this obvious DTrace invocation to trace the 15th argument (zero-indexed) to a particularly ugly function:

# dtrace -n pid123::foobar:entry'{ trace(arg15); }'
dtrace: invalid probe specifier pid380863:::entry{ trace(arg15); }: in action list:
  failed to resolve arg15: Unknown variable name

As described in the Solaris Dynamic Tracing Guide we actually only provide access to arguments 0-9. I suppose you could call this a design oversight, but really it reflects our bias about software -- no one's going to want to call your function if it has a bazillion arguments.

But -- as with most things pertaining to C++ -- sometimes you just have to hold your nose and get it working. If you need to trace arguments past arg9 in functions you're observing with the pid provider, here's how you can do it:

x86 this->argN = \*(uint32_t \*)copyin(uregs[R_SP] + sizeof (uint32_t) \* (this->N + 1), sizeof (uint32_t));
x86-64/AMD64 this->argN = \*(uint64_t \*)copyin(uregs[R_SP] + sizeof (uint64_t) \* (this->N - 5), sizeof (uint64_t));
SPARC 32-bit this->argN = \*(uint32_t \*)copyin(uregs[R_SP] + sizeof (uint32_t) \* (this->N + 17), sizeof (uint32_t));
SPARC 64-bit this->argN = \*(uint64_t \*)copyin(uregs[R_SP] + 0x7ff + sizeof (uint64_t) \* (this->N + 16), sizeof (uint64_t));

Note that for SPARC (32-bit and 64-bit) as well as AMD64, these formulas only work for arguments past the sixth -- but then you should probably be using arg0 .. arg9 when you can.

UPDATE

The methods above only apply for integer arguments; while I think it will work for 32-bit x86, the other architectures can pass floating-point arguments in registers as well as on the stack. Perhaps a future entry will discuss floating-point arguments if anyone cares.

There are a couple of gotchas I neglected to mention. On AMD64 if the argument is less that 64-bits (e.g. an int), the compiler can leave garbage in the upper bits meaning that you have to cast the variable to the appropriate type in DTrace (e.g. trace((int)this->argN)). On both 32-bit architectures, 64-bit arguments are passed in 2 of these 32-bit arguments; to get the full 64-bit value, just shift and or the two arguments together (e.g. ((this->arg13 << 32) | this->arg14) or ((this->arg14 << 32) | this->arg13) for SPARC and x86 respectively). Even for arguments that you can get with the built-in variables, you will need to mash together 64-bit arguments on 32-bit architectures (except on the SPARCv8+ ABI which can pass the first 6 arguments in 64-bit registers).


Technorati tag:
Comments:

ouch, thats not nice. Hopefully I'll never need to use this tip :).

Posted by fintanr on April 04, 2005 at 01:01 PM PDT #

Why not allowing us to type arg00 to arg99 ? It would help MrBenchmark's tiny memory...

Posted by MrBenchmark on April 04, 2005 at 02:52 PM PDT #

Senor Benchmark,
I should have made it clear that I don't think of this as a fix -- more like a stop gap work around. In fact I just opened a bug against DTrace to get this fixed -- it might even be a good bug for someone to get started with on OpenSolaris.

Posted by Adam Leventhal on April 05, 2005 at 04:28 AM PDT #

You're the man ! benoit

Posted by Mr Benchmark on April 05, 2005 at 09:25 AM PDT #

Does this assume that all paramaters to the function are word-size or smaller, and that they are all integer?

The 32-bit x86 ABI makes it easy to get an argument on the stack (at a cost of function call performance). But don't the more modern ABIs of SPARC / AMD64 do things with floating-point and/or large arguments which mess this up?

Posted by eric on April 06, 2005 at 03:17 PM PDT #

Somewhat OT: while doing my first DTrace scripts, I found the examples in /usr/demo to be a great help. I think it would help Solaris users get more out of DTrace if there were even more demo scripts available, which would make a "cookbook" of sorts. Not big fancy scripts, but tidbits of functionality that give users ideas about attacking more complex problems.

It just seems to me that DTrace is so flexible that the bigger the head start for programmers and admins, the more interesting things they can do with it. It would even be really neat in the long term to see the ptools and the \*stat tools expanded with Sun-provided DTrace scripts (i.e., no longer in /usr/demo but in /usr/bin).

Posted by Anon on April 07, 2005 at 07:22 AM PDT #

Eric,
I should have clarified: this is just for integer arguments and for 64-bit arguments on 32-bit architectures you'll need to mash together two of these word-sized arguments. Your comment also made me realize I forgot to include an important AMD64 caveat -- the compiler will sometimes only store 32-bits worth into the 64-bit argument meaning you have to cast it to an int (or uint32_t) or else end up with garbage. I'll update the post accordingly.

Captain Anon,
Glad to hear the scripts in the answer book are helpful (we stuck them in /usr/demo/dtrace/ so they'd always be on hand). We are indeed trying to expand that catalogue. We're also thinking about building -- for lack of a better term -- wizards to sort of guide you along the DTrace process. You might run one script, or -- as you suggest -- another monitoring tool which then leads you to a few pre-packaged D scripts which then lead you to other questions. While I don't think we can ever automate the "DTrace process", we can certainly help novices navigate the straights.

Adam

Posted by Adam Leventhal on April 08, 2005 at 01:36 AM PDT #

Post a Comment:
Comments are closed for this entry.
About

Adam Leventhal, Fishworks engineer

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today