I am trying to use dtrace via libdtrace (on Snow Leopard, 10.6.4). I want to catch the printed output of my dtrace script in my own program. One way to do this is to force the output to go to a temporary file and read it from there. However, libdtrace does support a callback function to catch the result I would prefer.
I assumed that the callback would just give me formatted strings that I could use, but that doesn't seem to be the case. For example, in the test program below, I expect the printout to be "process pid = 86138." However, it always prints "process pid = 1" (dtrace script works fine when it works with "dtrace -n").
What am I doing wrong? How should I use the data passed to the buffer handler? (In particular, I'm interested in data from printf and tracemem).
#include <dtrace.h> #include <stdio.h> #include <stdlib.h> #include <mach/mach.h> #include <mach-o/loader.h> #include <mach-o/dyld.h> #include <mach-o/fat.h> #include <sys/sysctl.h> #include <signal.h> static const char *g_prog = "pid86138::write:entry" "{" " printf(\"process pid = %d\\n\", pid);" "}"; static int dcmdbuffered(const dtrace_bufdata_t *bufdata, void *arg) { if((bufdata->dtbda_recdesc != NULL) && (bufdata->dtbda_recdesc->dtrd_action == DTRACEACT_PRINTF)) printf("BUF: %s\n", bufdata->dtbda_buffered); return DTRACE_HANDLE_OK; } static int chew(const dtrace_probedata_t *data, void *arg) { return DTRACE_CONSUME_THIS; } static int chewrec(const dtrace_probedata_t *data, const dtrace_recdesc_t *rec, void *arg) { if(rec == NULL) return (DTRACE_CONSUME_NEXT); return (DTRACE_CONSUME_THIS); } int main(int argc, char **argv) { int err, done = 0; dtrace_proginfo_t info; dtrace_hdl_t *g_dtp = dtrace_open(DTRACE_VERSION, DTRACE_O_ILP32, &err); dtrace_prog_t *prog = dtrace_program_strcompile(g_dtp, g_prog, DTRACE_PROBESPEC_NAME, 0, 0, NULL); dtrace_handle_buffered(g_dtp, dcmdbuffered, NULL); dtrace_program_exec(g_dtp, prog, &info); dtrace_setopt(g_dtp, "strsize", "4096"); dtrace_setopt(g_dtp, "bufsize", "4m"); dtrace_setopt(g_dtp, "arch", "x86_64"); dtrace_go(g_dtp); while(dtrace_work(g_dtp, NULL, chew, chewrec, NULL) == DTRACE_WORKSTATUS_OKAY) dtrace_sleep(g_dtp); dtrace_stop(g_dtp); dtrace_close(g_dtp); return 0; }