Skip to content

Commit fc0e101

Browse files
blakej11Kernel Patches Daemon
authored andcommitted
libbpf: add support for printing BTF character arrays as strings
The BTF dumper code currently displays arrays of characters as just that - arrays, with each character formatted individually. Sometimes this is what makes sense, but it's nice to be able to treat that array as a string. This change adds a special case to the btf_dump functionality to allow 0-terminated arrays of single-byte integer values to be printed as character strings. Characters for which isprint() returns false are printed as hex-escaped values. This is enabled when the new ".emit_strings" is set to 1 in the btf_dump_type_data_opts structure. As an example, here's what it looks like to dump the string "hello" using a few different field values for btf_dump_type_data_opts (.compact = 1): - .emit_strings = 0, .skip_names = 0: (char[6])['h','e','l','l','o',] - .emit_strings = 0, .skip_names = 1: ['h','e','l','l','o',] - .emit_strings = 1, .skip_names = 0: (char[6])"hello" - .emit_strings = 1, .skip_names = 1: "hello" Here's the string "h\xff", dumped with .compact = 1 and .skip_names = 1: - .emit_strings = 0: ['h',-1,] - .emit_strings = 1: "h\xff" Signed-off-by: Blake Jones <[email protected]>
1 parent efe09e8 commit fc0e101

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

tools/lib/bpf/btf.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,9 +326,10 @@ struct btf_dump_type_data_opts {
326326
bool compact; /* no newlines/indentation */
327327
bool skip_names; /* skip member/type names */
328328
bool emit_zeroes; /* show 0-valued fields */
329+
bool emit_strings; /* print char arrays as strings */
329330
size_t :0;
330331
};
331-
#define btf_dump_type_data_opts__last_field emit_zeroes
332+
#define btf_dump_type_data_opts__last_field emit_strings
332333

333334
LIBBPF_API int
334335
btf_dump__dump_type_data(struct btf_dump *d, __u32 id,

tools/lib/bpf/btf_dump.c

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ struct btf_dump_data {
6868
bool compact;
6969
bool skip_names;
7070
bool emit_zeroes;
71+
bool emit_strings;
7172
__u8 indent_lvl; /* base indent level */
7273
char indent_str[BTF_DATA_INDENT_STR_LEN];
7374
/* below are used during iteration */
@@ -2028,6 +2029,52 @@ static int btf_dump_var_data(struct btf_dump *d,
20282029
return btf_dump_dump_type_data(d, NULL, t, type_id, data, 0, 0);
20292030
}
20302031

2032+
static int btf_dump_string_data(struct btf_dump *d,
2033+
const struct btf_type *t,
2034+
__u32 id,
2035+
const void *data)
2036+
{
2037+
const struct btf_array *array = btf_array(t);
2038+
const char *chars = data;
2039+
__u32 i;
2040+
2041+
/* Make sure it is a NUL-terminated string. */
2042+
for (i = 0; i < array->nelems; i++) {
2043+
if ((void *)(chars + i) >= d->typed_dump->data_end)
2044+
return -E2BIG;
2045+
if (chars[i] == '\0')
2046+
break;
2047+
}
2048+
if (i == array->nelems) {
2049+
/* The caller will print this as a regular array. */
2050+
return -EINVAL;
2051+
}
2052+
2053+
btf_dump_data_pfx(d);
2054+
btf_dump_printf(d, "\"");
2055+
2056+
for (i = 0; i < array->nelems; i++) {
2057+
char c = chars[i];
2058+
2059+
if (c == '\0') {
2060+
/*
2061+
* When printing character arrays as strings, NUL bytes
2062+
* are always treated as string terminators; they are
2063+
* never printed.
2064+
*/
2065+
break;
2066+
}
2067+
if (isprint(c))
2068+
btf_dump_printf(d, "%c", c);
2069+
else
2070+
btf_dump_printf(d, "\\x%02x", (__u8)c);
2071+
}
2072+
2073+
btf_dump_printf(d, "\"");
2074+
2075+
return 0;
2076+
}
2077+
20312078
static int btf_dump_array_data(struct btf_dump *d,
20322079
const struct btf_type *t,
20332080
__u32 id,
@@ -2055,8 +2102,13 @@ static int btf_dump_array_data(struct btf_dump *d,
20552102
* char arrays, so if size is 1 and element is
20562103
* printable as a char, we'll do that.
20572104
*/
2058-
if (elem_size == 1)
2105+
if (elem_size == 1) {
2106+
if (d->typed_dump->emit_strings &&
2107+
btf_dump_string_data(d, t, id, data) == 0) {
2108+
return 0;
2109+
}
20592110
d->typed_dump->is_array_char = true;
2111+
}
20602112
}
20612113

20622114
/* note that we increment depth before calling btf_dump_print() below;
@@ -2544,6 +2596,7 @@ int btf_dump__dump_type_data(struct btf_dump *d, __u32 id,
25442596
d->typed_dump->compact = OPTS_GET(opts, compact, false);
25452597
d->typed_dump->skip_names = OPTS_GET(opts, skip_names, false);
25462598
d->typed_dump->emit_zeroes = OPTS_GET(opts, emit_zeroes, false);
2599+
d->typed_dump->emit_strings = OPTS_GET(opts, emit_strings, false);
25472600

25482601
ret = btf_dump_dump_type_data(d, NULL, t, id, data, 0, 0);
25492602

0 commit comments

Comments
 (0)