bpftrace / bpftrace

High-level tracing language for Linux
Apache License 2.0
8.47k stars 1.33k forks source link

Allow variable printf format #1452

Open albancrommer opened 4 years ago

albancrommer commented 4 years ago

bpftrace --info

Debian Buster version 0.8+git60-gccac69c2239b-2

Use Case

Say you want to write a BT program with many probes, all of them printing identically formated lines, for example "TIME PID SRC COMM ARGS" with sources like tcp, blk, etc.

To avoid repeating yourself for every probe, you want to have the printf format as a variable used for every printf statement, like

BEGIN
{
  @fmtstr = "%-8s\t%-6s\t%-16s\t%-16s\t%-32s\n";
}

tracepoint:syscalls:sys_enter_open {
  printf(@fmtstr, ... );
}

What reproduces the bug?

Using a string variable as first parameter (i.e. the format) with printf.

Expected result The string variable should be accepted.

Actual result BT returns the error printf() expects a string literal (string provided)

#!/usr/bin/env bpftrace

BEGIN
{
  @fmtstr = "%s\n";
  printf( @fmtstr, "This does not work.");
}
fbs commented 4 years ago

For your use case a define seems better:

$ sudo bpftrace -e '#define FMT "%d\n"
>
> i:ms:100 { printf(FMT, @); @++ }'
Attaching 1 probe...
0
1
2
3
4

Probe wildcards might also work in your case, avoids having to dupe a lot of code.

Having a way to define global constants (which we can optimize at compile time) sounds like a good thing to add, something like

let VAR="%d\n"

k:f { printf(VAR, @) }
albancrommer commented 4 years ago

Thanks for yout feedback.

It might be worth mentioning that the define way works on 0.11 but not on Buster's 0.8 ;)

danobi commented 4 years ago

Having a way to define global constants (which we can optimize at compile time) sounds like a good thing to add, something like

Yeah, and functions would be nice too.