Exploring a limitation of the DTrace fbt provider (on x86)
The fine documentation for DTrace's kernel function tracer contains a little note that you might easily miss if, like me, you were just skimming:
For each instruction set, there are a small number of functions that do not call other functions and are highly optimized by the compiler (so-called leaf functions) that cannot be instrumented by FBT.
The first thing to know is that DTrace does not have any useful error messages when you run into this. Instead of a helpful note about, say, 'this function exists but cannot be traced', you get the generic report 'probe description fbt:<X>:entry does not match any probes'. If you know that the function exists, this is what you're running into.
(And speaking from personal experience, it is very puzzling and annoying if you've run into it and you didn't notice the note in the documentation. I spent rather a lot of time beating my head against this.)
The 'x86 Limitations' section of the fbt documentation has slightly more detail about what is going on; the real condition is that any function that doesn't create a stack frame can't be traced. 'Highly optimized' is a little bit of a misnomer, as I suspect that the real condition is closer to 'doesn't do very much'.
(In the case that I ran into yesterday, the function just did some very simple math with some global variables in order to return a boolean yes/no value.)
Why this limitation exists is that DTrace's fbt provider works by overwriting a bit of the function prequel so that it invokes DTrace hooks instead. Of course the DTrace hooks then have to do what the overwritten code would have done, and this only works if they know what that is and can easily duplicate it. On x86, the interception is done in part of the standard instruction sequence that sets up the function's stack frame; a function with no stack frame has no standard instruction sequence to set it up and thus no place for DTrace to safely overwrite.
Specifically, on 64-bit x86 DTrace overwrites
pushq %rbp with
$0x3. You can actually see this in action with
mdb -k if you want
to by disassembling the first instruction of the function (with
func/i') before and after you add a DTrace probe on the function.
Note that fbt instruments both function entry and function returns
no matter which you asked for.
This provides a convenient way to both check to see if a function exists
and if it can be traced by fbt; start up
mdb -k and disassemble the
start of the function, looking for the
pushq. If mdb can't find the
function at all, there's a difference between the OpenSolaris code
you're looking at and the Solaris that you're running.
(More details about this are in uts/intel/dtrace/fbt.c in the OpenSolaris code.)
PS: I'm aware that using '
mdb -k' instead of just having DTrace dump
all fbt hooks is only convenient for a certain sort of person. I just
happen to be that sort of person.