3

I'm trying to print out the binary buffers of some read() and write() calls with dtrace. The problem with just using printf() and %s is that the string is terminated at null bytes. (\000) There is also tracemem() but it can only print out fixed size buffers and I like to get the size of the buffer out of the size argument of the read and write function calls. Moreover the output of dtrace should be machine-readable and tracemem() is not. My current approach looks like this:

syscall::write:return,
syscall::write_nocancel:return,
syscall::read:return,
syscall::read_nocancel:return
/self->start != 0 && arg0 != -1/
{
    this->content = (char*) copyin(self->arg1,arg0);
    printf("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", this->    content[0],this->content[1],this->content[2],this->content[3],this->content[4],this->content[5],this->content[6],this->content[7],this->content[8]    ,this->content[9],this->content[10],this->content[11],this->content[12],this->content[13],this->content[14],this->content[15],this->content[16],this-    >content[17],this->content[18],this->content[19],this->content[20],this->content[21],this->content[22],this->content[23],this->content[24],this->    content[25],this->content[26],this->content[27],this->content[28],this->content[29],this->content[30],this->content[31],this->content[32],this->    content[33],this->content[34],this->content[35],this->content[36],this->content[37],this->content[38],this->content[39],this->content[40],this->    content[41],this->content[42],this->content[43],this->content[44],this->content[45],this->content[46],this->content[47],this->content[48],this->    content[49],this->content[50],this->content[51],this->content[52],this->content[53],this->content[54],this->content[55],this->content[56],this->    content[57],this->content[58],this->content[59],this->content[60],this->content[61],this->content[62],this->content[63]);
}

This kind of works if the read() or write() command never uses more then 64 byte. Of course, this is no optimal solution.

Any ideas?

dax
  • 143
  • 4

1 Answers1

2

There's the tracemem action, though that also takes a size, it's certainly easier to read: http://docs.oracle.com/cd/E19253-01/819-5488/gcgge/index.html

illumos added an optional 3rd argument that lets you specify both a maximum size (the 2nd argument) and the size to actually display (the 3rd), but I'm not sure who else supports that.

The basic problem is that the architecture of DTrace is such that it can't read a variable amount of data, that is, that the 2nd argument to tracemem must be constant, and so won't help you beyond making your code a bit tidier. If you need to actually display variable amounts of stuff I don't think a workaround exists to not having the 3-argument tracemem

richlowe
  • 61
  • 2
  • I tried to use something like `printf("%lu %.*s\n", arg0, arg0, this->content);` on Solaris 10 - but apparently Dtrace's printf doesn't implement `%.*s` correctly - it still only prints the string until the first 0 byte. – maxschlepzig Jan 01 '17 at 12:59