Wednesday Jan 26, 2005

Absent leaves

Finally getting to add an entry. Solaris being an ongoing development I've lost time to update this blog. Making some time for this will be my new endeavor (hopefully).

With that I ran into (and solved with dtrace) a little problem here. Wanting to see if a particular program was calling a particular libc(3LIB) function, setlocale(2) as it happened. We could use apptrace(1) but the program was being run from within a suite of software and this suite wasn't easy (or we were unwilling) to change it to use apptrace(1). Using dtrace to find if a process is calling a particular funcion is dead easy;

# dtrace -n 'pid$target::read:entry{}' -p 15250
dtrace: description 'pid$target::read:entry' matched 4 probes
CPU     ID                    FUNCTION:NAME
  1  46195                       read:entry 
#
But what of when a process would load a library after dtrace is tracing it ? This came up in the dtrace forum on this thread. Bryan, of course, came up with an answer. That and with Morgan Herrington's help, aka script-reuse, the following three dtrace scripts were written. The first, master.d, would watch for the invocation of a particular program. It would then stop the program via the dtrace function, stop() and also fork off the second dtrace script, mon_pre.d. This second dtrace script then starts the program again via prun, but stops it when the program enters main(). Finally it would fork off the last dtrace script, mon.d. Finally the third and last dtrace script would watch for particular functions being called.

master.d

#!/usr/sbin/dtrace -s

#pragma D option destructive

syscall::exece:return
/execname == $$1/
{
        stop();

        printf("%d %s\n", pid, execname);
        printf("forking pre-monitor to watch ...%s\n\n", $$1);
        printf("./mon_pre.d %d &\n\n", pid);

        system("./mon_pre.d %d &", pid); 
        exit(0);
}
mon_pre.d
#!/usr/sbin/dtrace -Fs

#pragma D option destructive

BEGIN
{
        printf("pruning process %d \n", $1);
        system("prun %d", $1);
}

pid$1::main:entry
{
        stop();
        printf("forking final monitor to watch %d\n\n", $1);
        system("./mon.d %d &", pid);
        exit(0);
}
and finally mon.d
#!/usr/sbin/dtrace -Fs

#pragma D option destructive

BEGIN
{
        printf("pruning %d process\n", $1);
        system("prun %d", $1);
} 

pid$1:libc:setlocale:entry,
pid$1:libc:textdomain:entry
{
        @[probefunc] = count();
}

pid$1::exit:entry
{
        exit(0);
}
One thing these scripts show is the use of the destructive mode of dtrace. Which should be used very very carefully lest one hangs ones system or worse. Credit is due to Morgan who wrote these scripts. Thanks Morgan !

Comments:

trest

Posted by sean on January 28, 2005 at 07:04 AM GMT #

Post a Comment:
  • HTML Syntax: NOT allowed