Skip to content

Commit 9c6c5c4

Browse files
anakryikoAlexei Starovoitov
authored and
Alexei Starovoitov
committed
libbpf: Make btf_dump work with modifiable BTF
Ensure that btf_dump can accommodate new BTF types being appended to BTF instance after struct btf_dump was created. This came up during attemp to use btf_dump for raw type dumping in selftests, but given changes are not excessive, it's good to not have any gotchas in API usage, so I decided to support such use case in general. Signed-off-by: Andrii Nakryiko <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent ea7da1d commit 9c6c5c4

File tree

3 files changed

+65
-22
lines changed

3 files changed

+65
-22
lines changed

tools/lib/bpf/btf.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,23 @@ void *btf_add_mem(void **data, size_t *cap_cnt, size_t elem_sz,
146146
return new_data + cur_cnt * elem_sz;
147147
}
148148

149+
/* Ensure given dynamically allocated memory region has enough allocated space
150+
* to accommodate *need_cnt* elements of size *elem_sz* bytes each
151+
*/
152+
int btf_ensure_mem(void **data, size_t *cap_cnt, size_t elem_sz, size_t need_cnt)
153+
{
154+
void *p;
155+
156+
if (need_cnt <= *cap_cnt)
157+
return 0;
158+
159+
p = btf_add_mem(data, cap_cnt, elem_sz, *cap_cnt, SIZE_MAX, need_cnt - *cap_cnt);
160+
if (!p)
161+
return -ENOMEM;
162+
163+
return 0;
164+
}
165+
149166
static int btf_add_type_idx_entry(struct btf *btf, __u32 type_off)
150167
{
151168
__u32 *p;

tools/lib/bpf/btf_dump.c

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,14 @@ struct btf_dump {
6060
struct btf_dump_opts opts;
6161
int ptr_sz;
6262
bool strip_mods;
63+
int last_id;
6364

6465
/* per-type auxiliary state */
6566
struct btf_dump_type_aux_state *type_states;
67+
size_t type_states_cap;
6668
/* per-type optional cached unique name, must be freed, if present */
6769
const char **cached_names;
70+
size_t cached_names_cap;
6871

6972
/* topo-sorted list of dependent type definitions */
7073
__u32 *emit_queue;
@@ -113,6 +116,7 @@ static void btf_dump_printf(const struct btf_dump *d, const char *fmt, ...)
113116
}
114117

115118
static int btf_dump_mark_referenced(struct btf_dump *d);
119+
static int btf_dump_resize(struct btf_dump *d);
116120

117121
struct btf_dump *btf_dump__new(const struct btf *btf,
118122
const struct btf_ext *btf_ext,
@@ -144,25 +148,8 @@ struct btf_dump *btf_dump__new(const struct btf *btf,
144148
d->ident_names = NULL;
145149
goto err;
146150
}
147-
d->type_states = calloc(1 + btf__get_nr_types(d->btf),
148-
sizeof(d->type_states[0]));
149-
if (!d->type_states) {
150-
err = -ENOMEM;
151-
goto err;
152-
}
153-
d->cached_names = calloc(1 + btf__get_nr_types(d->btf),
154-
sizeof(d->cached_names[0]));
155-
if (!d->cached_names) {
156-
err = -ENOMEM;
157-
goto err;
158-
}
159151

160-
/* VOID is special */
161-
d->type_states[0].order_state = ORDERED;
162-
d->type_states[0].emit_state = EMITTED;
163-
164-
/* eagerly determine referenced types for anon enums */
165-
err = btf_dump_mark_referenced(d);
152+
err = btf_dump_resize(d);
166153
if (err)
167154
goto err;
168155

@@ -172,17 +159,46 @@ struct btf_dump *btf_dump__new(const struct btf *btf,
172159
return ERR_PTR(err);
173160
}
174161

162+
static int btf_dump_resize(struct btf_dump *d)
163+
{
164+
int err, last_id = btf__get_nr_types(d->btf);
165+
166+
if (last_id <= d->last_id)
167+
return 0;
168+
169+
if (btf_ensure_mem((void **)&d->type_states, &d->type_states_cap,
170+
sizeof(*d->type_states), last_id + 1))
171+
return -ENOMEM;
172+
if (btf_ensure_mem((void **)&d->cached_names, &d->cached_names_cap,
173+
sizeof(*d->cached_names), last_id + 1))
174+
return -ENOMEM;
175+
176+
if (d->last_id == 0) {
177+
/* VOID is special */
178+
d->type_states[0].order_state = ORDERED;
179+
d->type_states[0].emit_state = EMITTED;
180+
}
181+
182+
/* eagerly determine referenced types for anon enums */
183+
err = btf_dump_mark_referenced(d);
184+
if (err)
185+
return err;
186+
187+
d->last_id = last_id;
188+
return 0;
189+
}
190+
175191
void btf_dump__free(struct btf_dump *d)
176192
{
177-
int i, cnt;
193+
int i;
178194

179195
if (IS_ERR_OR_NULL(d))
180196
return;
181197

182198
free(d->type_states);
183199
if (d->cached_names) {
184200
/* any set cached name is owned by us and should be freed */
185-
for (i = 0, cnt = btf__get_nr_types(d->btf); i <= cnt; i++) {
201+
for (i = 0; i <= d->last_id; i++) {
186202
if (d->cached_names[i])
187203
free((void *)d->cached_names[i]);
188204
}
@@ -222,6 +238,10 @@ int btf_dump__dump_type(struct btf_dump *d, __u32 id)
222238
if (id > btf__get_nr_types(d->btf))
223239
return -EINVAL;
224240

241+
err = btf_dump_resize(d);
242+
if (err)
243+
return err;
244+
225245
d->emit_queue_cnt = 0;
226246
err = btf_dump_order_type(d, id, false);
227247
if (err < 0)
@@ -251,7 +271,7 @@ static int btf_dump_mark_referenced(struct btf_dump *d)
251271
const struct btf_type *t;
252272
__u16 vlen;
253273

254-
for (i = 1; i <= n; i++) {
274+
for (i = d->last_id + 1; i <= n; i++) {
255275
t = btf__type_by_id(d->btf, i);
256276
vlen = btf_vlen(t);
257277

@@ -306,6 +326,7 @@ static int btf_dump_mark_referenced(struct btf_dump *d)
306326
}
307327
return 0;
308328
}
329+
309330
static int btf_dump_add_emit_queue_id(struct btf_dump *d, __u32 id)
310331
{
311332
__u32 *new_queue;
@@ -1049,11 +1070,15 @@ int btf_dump__emit_type_decl(struct btf_dump *d, __u32 id,
10491070
const struct btf_dump_emit_type_decl_opts *opts)
10501071
{
10511072
const char *fname;
1052-
int lvl;
1073+
int lvl, err;
10531074

10541075
if (!OPTS_VALID(opts, btf_dump_emit_type_decl_opts))
10551076
return -EINVAL;
10561077

1078+
err = btf_dump_resize(d);
1079+
if (err)
1080+
return -EINVAL;
1081+
10571082
fname = OPTS_GET(opts, field_name, "");
10581083
lvl = OPTS_GET(opts, indent_level, 0);
10591084
d->strip_mods = OPTS_GET(opts, strip_mods, false);

tools/lib/bpf/libbpf_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ static inline void *libbpf_reallocarray(void *ptr, size_t nmemb, size_t size)
107107

108108
void *btf_add_mem(void **data, size_t *cap_cnt, size_t elem_sz,
109109
size_t cur_cnt, size_t max_cnt, size_t add_cnt);
110+
int btf_ensure_mem(void **data, size_t *cap_cnt, size_t elem_sz, size_t need_cnt);
110111

111112
static inline bool libbpf_validate_opts(const char *opts,
112113
size_t opts_sz, size_t user_sz,

0 commit comments

Comments
 (0)