Bpftrace: A way to print arbitrary binary data safely?

Created on 21 May 2019  路  5Comments  路  Source: iovisor/bpftrace

I want to see a sample of the data that's being written to disk, but I don't want to accidentally print some binary junk and kill my terminal with unintended ANSI control characters. I'd love some kind of formatting option like Python's %r where non-text bytes are replaced with \xNN escape codes :)

$ python -c 'print("%r" % open("/dev/urandom").read(16))'
'GtlR\xb2\x03n\x18\xda)\xe9#\x85"\xca\xda'
enhancement

Most helpful comment

It's hacky but it is possible to write

tracepoint:syscalls:sys_enter_sendto {
  $len = args->len;
  $p = args->buff;
  $i = (uint64)0;
  unroll(20) {
    if ($i < $len) {
      $c = *(uint8*)$p;
      if ($c >= 32 && $c <= 126) {
        printf("%c", $c);
      } else {
        printf("\\x%02x", $c);
      }
    }
    $p += 1;
    $i += 1;
  }
  printf("\n");
}
% sudo ./src/bpftrace sendto.bt -c "ping 8.8.8.8 -c1"
Attaching 1 probe...
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
\x08\x00\xba/O\xf6\x00\x01+n\x01^\x00\x00\x00\x00\x01:\x01\x00
64 bytes from 8.8.8.8: icmp_seq=1 ttl=63 time=13.3 ms

If printf() supports %r, then we can write bpftrace -e 'tracepoint:syscalls:sys_enter_sendto { printf("%r\n", str(args->buff, args->len)); }'

All 5 comments

Sounds pretty reasonable to me.

same for tracepoints like sys_enter_sendto, where there is a void * buff. It would be nice, to print the content of buff.

It's hacky but it is possible to write

tracepoint:syscalls:sys_enter_sendto {
  $len = args->len;
  $p = args->buff;
  $i = (uint64)0;
  unroll(20) {
    if ($i < $len) {
      $c = *(uint8*)$p;
      if ($c >= 32 && $c <= 126) {
        printf("%c", $c);
      } else {
        printf("\\x%02x", $c);
      }
    }
    $p += 1;
    $i += 1;
  }
  printf("\n");
}
% sudo ./src/bpftrace sendto.bt -c "ping 8.8.8.8 -c1"
Attaching 1 probe...
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
\x08\x00\xba/O\xf6\x00\x01+n\x01^\x00\x00\x00\x00\x01:\x01\x00
64 bytes from 8.8.8.8: icmp_seq=1 ttl=63 time=13.3 ms

If printf() supports %r, then we can write bpftrace -e 'tracepoint:syscalls:sys_enter_sendto { printf("%r\n", str(args->buff, args->len)); }'

thanks for the great hint @mmisono

I need this too and will work on implementing it in printf

Was this page helpful?
0 / 5 - 0 ratings

Related issues

brendangregg picture brendangregg  路  8Comments

Brother-Lal picture Brother-Lal  路  6Comments

psanford picture psanford  路  7Comments

alejandrox1 picture alejandrox1  路  4Comments

tty5 picture tty5  路  3Comments