Adam Leventhal's blog

Search
Close this search box.

the pid provider and > 10 arguments

April 4, 2005

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 <arg14) or ((this->arg14 <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:

7 Responses

  1. 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.

  2. 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?

  3. 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).

  4. 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

Recent Posts

April 17, 2024
January 13, 2024
December 29, 2023
February 12, 2017
December 18, 2016

Archives

Archives