This is on BPF tasks #574 as string factory (stringmap). Can we propose a minimal set of functions we'd like, to begin with? Here's my list:
Examples of current workarounds: strcmp():
strlcat():
This emits arguments one by one. This is tricky, since we need to walk argv[] (currently using an unrolled loop). I was thinking strlcat() would let us build a concatenated args string, but it might need strlen() at some point. A basic snprintf() sounds much better, but .. gah this is awful.
How about a helper just for the argv[] case? :) Ie, take an argv[] argument and return a truncated string of the arguments. bpf_strarray_to_str().
Then, in lieu of another use case, my list is just:
@4ast may have another thread of discussion about this. I'm posting this here as it was suggested in IRC.
Thanks for filing this issue. /cc @alban @asymmetric @alepuccetti @iaguis @2opremio
I'd really like strcpy, which is very needed in argdist (see #607) so we don't do aggregations based on extraneous characters (which almost always leads to wrong results when aggregating on strings without specifying the exact string size).
from @goldshtn on #759:
So, I ran a little test. It looks like we can definitely use loops that implement strcmp manually if the string is known at compile-time. This opens up a bunch of use cases for scripts where we don't really need to compare two run-time strings, but rather compare one run-time string to one compile-time string (like your example above).
Here's a function that compares a run-time string to "true". It can be used from a bcc program.
static inline bool equal_to_true(char *str) {
char comparand[4];
bpf_probe_read(&comparand, sizeof(comparand), str);
char compare[] = "true";
for (int i = 0; i < 4; ++i)
if (compare[i] != comparand[i])
return false;
return true;
}
This can be generalized into a macro:
#include <linux/ptrace.h>
#define DECLARE_EQUAL_TO(s) static inline bool equal_to_##s(char *str) { \
char comparand[sizeof(#s)]; \
bpf_probe_read(&comparand, sizeof(comparand), str); \
char compare[] = #s; \
for (int i = 0; i < sizeof(comparand); ++i) \
if (compare[i] != comparand[i]) \
return false; \
return true; \
} \
#define IS_EQUAL_TO(str, s) equal_to_##s(str)
DECLARE_EQUAL_TO(true)
int test_strings(struct pt_regs *ctx, char *str) {
bpf_trace_printk("String printed: %s, equal to 'true': %d\\n",
str, IS_EQUAL_TO(str, true));
return 0;
}
It's not elegant, but seems to be working. I think it can be incorporated into trace and argdist so we can compare strings. Thoughts? :)
Fun workaround, but it would still be nice to see this as a builtin.
Few of my coworkers hit this: @shartse @don-brady
Most helpful comment
Fun workaround, but it would still be nice to see this as a builtin.
Few of my coworkers hit this: @shartse @don-brady