Better stap scripting
Mark Wielaard
mjw@redhat.com
Tue Dec 13 16:43:00 GMT 2011
Hi,
As a workaround for PR13467 - user array indexing pointer_array.exp
testcase fails on s390x needs @user($ptr), I added a new test that
excersises array indexing from some kernel variables. It implements
the kallsyms data decompression inside a stap script since that used
a couple of (nested) array indexes. Not that I suspected that to be
broken, but I wanted to has an explicit test for it if I KFAILed
pointer_array.exp for s390x. And it was fun to write :)
Attached is the script. I am posting it to see if I (we) can do
some things to make stap scripting even more convenient.
First, it would have been convenient to have @user($ptr) as described
in the PR. Then we could have just used pointer_array.stp directly
for the test. And in general it would make some scripts cleaner.
As can be seen from the script it is an almost direct translation
of the C source code. So much so, that I just copy/pasted it and
then tweaked it till it was a legal stap script.
Is there a better way to derefence an unsigned type?
The script uses: len = kernel_char(data) & 0xff;
At first I forgot the masking and would get signed results...
Should we just introduce [user|kernel]_u[char|short|int|log](ptr)?
Or is there a more elegant way?
We are lucky in this script that we are only doing pointer
arithmetic on char* (data++ and tptr++). But things get somewhat
cumbersome if one has a pointer to something with sizeof != 1.
What would be a good solution for this? Some kind of @sizeof?
Finally this was written directly inside the probe handler.
This mixes the probe logic with the extraction logic a bit.
It would be nice to separate out the decompression logic in
its own function. But that quickly makes things ugly because
one cannot pass around typed (dwarf) variables. So you end up
with lots of casts. In general it would be nice to have something
like what is proposed in PR11096 @global() through which one
can at least access the module/file static globals. Or is there
some other nice way to separate out the extraction logic from
the probe without needing too many manual casts? (Maybe I am
making too much a deal out of needing to type @cast a lot. That
is mostly because I was so pleased with how little changes I
needed from the original C code.)
Any other thoughts on how something like this could be written
more clearly with existing or future stap script features?
Cheers,
Mark
-------------- next part --------------
# Test various array operations on a kernel variable.
# This is a pretty direct translation of the C source code of
# kernel/kallsyms.c (kallsyms_expand_symbol).
global symbols = 0;
probe kernel.function("kallsyms_expand_symbol")
{
/* We are only interested in the head -10 symbols for comparison. */
if (target() != pid()) next;
skipped_first = 0;
/* Get the compressed symbol length from the first symbol byte. */
data = &$kallsyms_names[$off];
len = kernel_char(data) & 0xff;
data++;
/*
* Update the offset to return the offset for the next symbol on
* the compressed stream.
*/
off += len + 1;
/*
* For every byte on the compressed symbol data, copy the table
* entry for that byte.
*/
while (len)
{
idx = kernel_char(data) & 0xff;
tptr = &$kallsyms_token_table[$kallsyms_token_index[idx]];
data++;
len--;
t = kernel_char(tptr) & 0xff;
while (t)
{
if (skipped_first)
{
printf("%c", t);
}
else
skipped_first = 1;
tptr++;
t = kernel_char(tptr) & 0xff;
}
}
printf("\n");
/* Are we done yet? */
symbols++;
if (symbols == 10) exit();
}
More information about the Systemtap
mailing list