Zyzik, Matt wrote:
All,

I have the following dtrace script:

syscall::*fork*:entry
/curpsinfo->pr_argc > 0/
{
    this->argp = (uintptr_t)(curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
        *(uint32_t*)copyin(curpsinfo->pr_argv + 0 * 4, 4) :
        *(uint64_t*)copyin(curpsinfo->pr_argv + 0 * 8, 8));
    this->arg1 = copyinstr(this->argp);
    printf("first arg: %s\n", this->arg1); }

I am trying to get the non-truncated first parameter of every process that 
forks. The above script works, except once in a while I get these messages due 
to unmapped pages:

dtrace: error on enabled probe ID 1 (ID 19253: syscall::fork1:entry):
invalid address (0xffbfe000) in action #1 at DIF offset 232

What can I do to avoid this issue? I am on Solaris 10 boxes.
If your script will run before the processes you're interested in, you could do:


proc:::exec
{
     self->name = args[0];
}

proc:::exec-failure
{
    self->name = 0;
}

proc:::exec-success
/self->name != 0/
{
     proc_execname[curpsinfo->pr_addr] = self->name;
     self->name = 0;
}

proc:::create
{
    this->arg0 = proc_arg0[curpsinfo->pr_addr];
    this->arg0 = (this->arg0 != NULL)?
      this->arg0 : strtok(curpsinfo->pr_psargs, " ");
    proc_arg0[args[0]->pr_addr] = this->arg0;

    printf("%s", this->arg0);
}

proc:::exit
{
     proc_arg0[curpsinfo->pr_addr] = 0; }

This will give you the pathname passed to exec, not the value of argv[0].  If 
you want that, replace all of the 'exec*' probes with:

proc:::exec-success
{
     proc_execname[curpsinfo->pr_addr] =
         copyinstr((uintptr_t)(curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
         *(uint32_t*)copyin(curpsinfo->pr_argv + 0 * 4, 4) :
         *(uint64_t*)copyin(curpsinfo->pr_argv + 0 * 8, 8))); }

I agree this solution would work if my dtrace script ran before the processes I 
am interested in, but I don't have that option. I am trying to run this script 
amongst long running daemons. Is there any way to accomplish what I am trying 
to do? I can sleep well if someone confirms it's not possible.

--Matt
Assuming there are no spaces involved, and argv0 is < 80 characters, then:

      this->arg0 = strtok(curpsinfo->pr_psargs, " ");

will work.  Otherwise, there's no great way to do it.

Cheers,
- jonathan
I just want to say to the rest of the mailing list that I am
interested in a "not so great" way to do it. If anyone knows any exotic means 
of force-faulting those pages, please share.
proc:::start
/!progenyof($pid)/
{
      stop();
      system("pargs %d | grep argv.0.: ; prun %d", pid, pid); }

I should also mention that I plan to aggregate on the values, like this: 
"@agg[this->arg1] = count();"; and
print with the "tick-5s" probe. In that case, the above-mentioned method won't 
be useful as I cannot collect
the output from the system(..) function.
What if you did something like this:

system("dd if=/proc/%d/as of=/dev/null bs=1 count=%d skip=%d", pid, object_size, object_addr);

Would it fault in the missing pages for you? If so, you could safely copyin() afterward.

Ryan

_______________________________________________
dtrace-discuss mailing list
[email protected]

Reply via email to