Systemtap 0.9 – Cast away

Another nice feature for Systemtap 0.9 was added by Josh Stone. Systemtap can collect data from any variable in scope at a probe point using the DWARF debug info. You can even dereference pointers, access struct members, array elements, etc. This is very powerful when collecting data during a trace and the systemtap runtime makes sure all data access is safe. But there were two issues making this less powerful than it could be.

First to the keep the tracing language simple systemtap only supports basic types (integers and strings), associative arrays or aggregates in stap scripts. This means that you could not easily pass program data around to an helper function to manipulate or format. Second sometimes programs “hide” the real type of a variable, or use a void * pointer that gets cast to the right type later on. You could work around this in the past by using embedded C and guru mode, but that wasn’t very nice, and made your script potentially unsafe.

So to make sure you can do this safely Josh added a @cast construct. This allows you to pass around a pointer to program data and interpret it as if it was any type described in the DWARF debuginfo for the program. All accesses are of course still checked for safety by the runtime.

A nice example of this feature in action is the following simple stap script to print the number of incoming connections for an executable by port number. We want to probe the kernel and get the inet_sock from the inet_csk_accept function when it returns successfully. Although this function handles inet sockets (it is part of inet_connection_sock.c), it passes around sock pointers. It can do this since an inet_sock struct starts with a sock pointer, later it will cast this to a full featured inet_sock pointer. So we do the same in our script:

global ports;

probe kernel.function("inet_csk_accept").return
{
  sock = $return
  if (sock != 0)
    {
      port = @cast(sock, "inet_sock")->num;
      ports[execname(), port]++;
    }
}

probe timer.s(30), end
{
  printf("Connections on ports: %s\n", ctime(gettimeofday_s()));
  foreach ([exec, port] in ports-)
    printf("%12s %4d: %4d\n", exec, port, ports[exec, port]);
  delete ports;
}
$ stap ports.stp
Connections on ports: Sat Feb 28 22:49:10 2009
       httpd   80:  172
       spamd  783:   30
        exim   25:   27
     portmap  111:   11
  imap-login  993:    8
      ypserv  818:    7
        sshd   22:    2

There are some more exciting network tracing examples in the Systemtap Examples collection.

One Comment

  1. Frank Ch. Eigler says:

    To clarify, “Systemtap can collect data from any variable in scope at a probe point using the DWARF debug info” is the old news that describes functionality that has been present for years. The new news is the “@cast construct. This allows you to pass around a pointer to program data and interpret it as if it was any type described in the DWARF debuginfo”