2 Replies Latest reply: Jan 11, 2010 11:09 AM by 807559 RSS

    Dtrace giving invalid address

    807559
      Hi,
      I have a problem with the following simple Dtrace script:

      dtrace: error on enabled probe ID 2 (ID 2402: syscall::open:return): invalid address (0x2000) in action #1 at DIF offset 28
      dtrace: error on enabled probe ID 4 (ID 2398: syscall::read:return): invalid address (0x2000) in action #1 at DIF offset 28

      Can someone please tell me why I get invalid address? How do I fix it?

      What it is supposed to do is that everytime there is a successful read (bytes read > 0) by a process (called tail) it is supposed to print out the name of the file read. The script uses the following probes:
      open:entry – save the filename opened into a variable s
      open:return – save the filename into an associative array a where the key is pid “:” filedescriptor
      read:return – if the number of bytes read > 0 then lookup associative array a using a key of pid “:” filedescriptor

      I am told that to test if the array element does not exist then the array element is nominally 0. pid is the built in variable which I assume is in kernel space and therefore should not need copyin.
      ==============================================================================================================
      This is the script:
      !/usr/sbin/dtrace -s

      string a[string];
      self int fd;
      self string s;
      this string s2;

      syscall::open:entry
      /execname=="tail"/
      {
      /* save a copy of the filename */
      s=copyinstr(arg0);
      printf("%s (pid %d) has opened file '%s'\n",execname,pid,s)
      }

      syscall::open:return
      /execname=="tail"/
      {
      /* save a copy of the pid, file descriptor and filename */
      s2=strjoin(stringof(pid),":");
      s2=strjoin(s2,copyinstr(arg0));
      a[s2]=s
      }

      syscall::read:entry
      /execname=="tail"/
      {
      /* save a copy of the file descriptor being read from */
      fd=arg0;
      }

      syscall::read:return
      /execname=="tail" & arg0>0/
      {
      /* If the read was sucessful (0 means that nothing is avaialble say for no wait I/O)
      then print out the file read */
      s2=strjoin(stringof(pid),":");
      s2=strjoin(s2,stringof(fd));
      fn=a[s2]==0 ? "":a[s2];
      printf("%s (pid %d) read from file '%s'\n",execname,pid,fn)
      }
        • 1. Re: Dtrace giving invalid address
          807559
          strjoin() requires its two parameters to be pointers:
               
          string strjoin(char str1, char str2)

          But it seems like a lot of extra work to do that anyway. You can save yourself some trouble with the fds[] array, which is a DTrace built-in. The expression fds[arg0] in your return probes would give you a fileinto_t translation of the descriptor. fileinfo_t is "documented" in /usr/lib/dtrace/io.d. There's a helpful write-up on D translators in general and fds[] specifically by Mike Shapiro, one of the DTrace Three, right here:

          http://blogs.sun.com/mws/entry/dtrace_inlines_translators_and_file

          Also, by using a thread-local variable, you can avoid the need to track the pid or test for the use of tail in each probe.

          Although it's unlikely to be a problem with tail(1), file descriptors don't necessarily refer to the same file for the life of a program. Grabbing the name of the file is much safer, as a matter of habit if nothing else.

          Here's a quick mockup of those ideas put to use. I don't have Solaris running at the moment, so I haven't tested this:

          !/usr/sbin/dtrace -s

          syscall::open:entry
          /execname=="tail"/
          {
          / save a copy of the filename /
          printf("%s (pid %d) has opened file '%s'\n",execname,pid,s)
          self->entered;
          }

          syscall::open:return
          /self->entered/
          {
          / save a copy of the pid, file descriptor and filename /
          self->file = fds[arg0];
          self->entered = 0;
          }

          syscall::read:return
          /self->file && arg0 != 0 && arg1 == 0/
          {
          / If the read was sucessful (0 means that nothing is avaialble say for no wait I/O)
          then print out the file read /
          printf("tail (pid %d) read from file '%s'\n", pid, self->file)
          }
          • 2. Re: Dtrace giving invalid address
            807559
            Oops! Change:

            syscall::open:return
            /self->entered/
            {
            / save a copy of the pid, file descriptor and filename /
            self->file = fds[arg0];
            self->entered = 0;
            }

            to

            syscall::open:return
            /self->entered/
            {
            / save a copy of the pid, file descriptor and filename /
            self->file = fds[arg0].fi_pathname;
            self->entered = 0;
            }