This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
Debugging uprobes with SystemTap
- From: Jim Keniston <jkenisto at us dot ibm dot com>
- To: systemtap <systemtap at sources dot redhat dot com>
- Date: Sat, 09 Jun 2007 15:20:43 -0700
- Subject: Debugging uprobes with SystemTap
FWIW, here's the stap script I ended up with while chasing down the bug
fixed by today's uprobes patch. I'd actually been using a
bare-knuckles-kprobes module for quite a while, but it was getting more
and more crufty as I tried out different things.
The ability to get the entry-time value of an arg ($regs) at
function-return time was key. The fact that $regs->eip gave me the
entry-time value of eip was a nuisance that had to be worked around.
And bz1155 is a pain (gcc inlines functions that I don't declare inline,
and then the dwarf info isn't sufficient for stap to get the args).
Jim
----- cut here -----
%{
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/ptrace.h>
#include <asm/mman.h>
%}
global signals_since_register
probe begin {
printf("Probing...\n");
}
probe kernel.function("register_uprobe"),
kernel.function("unregister_uprobe")
{
printf("%d: %s\n", tid(), probefunc());
}
probe kernel.function("register_uprobe").return
{
printf("%d: %s returns %d\n", tid(), probefunc(), $return);
}
probe kernel.function("unregister_uprobe").return
{
printf("%d: %s returns\n", tid(), probefunc());
}
probe kernel.function("register_uprobe")
{
signals_since_register = 0
}
probe kernel.function("uprobe_report_signal")
{
signals_since_register++;
if (signals_since_register <= 10)
printf("%d: In %s, eip=%#x, esp=%#x, signo=%d\n",
tid(), probefunc(), $regs->eip, $regs->esp,
$info->si_signo);
}
/* Is there a more straightforward way to do this? */
function regs_eip:long(regs:long)
%{
struct pt_regs *r = (struct pt_regs*)(long)THIS->regs;
THIS->__retvalue = (long) r->eip;
%}
function regs_esp:long(regs:long)
%{
struct pt_regs *r = (struct pt_regs*)(long)THIS->regs;
THIS->__retvalue = (long) r->esp;
%}
probe kernel.function("uprobe_report_signal").return
{
if (signals_since_register <= 10)
printf("%d: %s returns %#x; eip=%#x, esp=%#x\n",
tid(), probefunc(), $return,
regs_eip($regs), regs_esp($regs));
}
function trampoline_addr:long()
%{
THIS->__retvalue = (long) current->mm->context.uprobes_ssol_area;
%}
/* gcc inlines this, and can't tell us uproc's value. Dang. */
probe kernel.inline("uretprobe_set_trampoline")
{
printf("%d: %s called; area->insns=%#x\n",
tid(), probefunc(), trampoline_addr());
}