Skip to content

Commit fb03be7

Browse files
anakryikoAlexei Starovoitov
authored andcommitted
libbpf: move exception callbacks assignment logic into relocation step
Move the logic of finding and assigning exception callback indices from BTF sanitization step to program relocations step, which seems more logical and will unblock moving BTF loading to after relocation step. Exception callbacks discovery and assignment has no dependency on BTF being loaded into the kernel, it only uses BTF information. It does need to happen before subprogram relocations happen, though. Which is why the split. No functional changes. Acked-by: Jiri Olsa <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent dac645b commit fb03be7

File tree

1 file changed

+85
-80
lines changed

1 file changed

+85
-80
lines changed

tools/lib/bpf/libbpf.c

Lines changed: 85 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -3192,86 +3192,6 @@ static int bpf_object__sanitize_and_load_btf(struct bpf_object *obj)
31923192
}
31933193
}
31943194

3195-
if (!kernel_supports(obj, FEAT_BTF_DECL_TAG))
3196-
goto skip_exception_cb;
3197-
for (i = 0; i < obj->nr_programs; i++) {
3198-
struct bpf_program *prog = &obj->programs[i];
3199-
int j, k, n;
3200-
3201-
if (prog_is_subprog(obj, prog))
3202-
continue;
3203-
n = btf__type_cnt(obj->btf);
3204-
for (j = 1; j < n; j++) {
3205-
const char *str = "exception_callback:", *name;
3206-
size_t len = strlen(str);
3207-
struct btf_type *t;
3208-
3209-
t = btf_type_by_id(obj->btf, j);
3210-
if (!btf_is_decl_tag(t) || btf_decl_tag(t)->component_idx != -1)
3211-
continue;
3212-
3213-
name = btf__str_by_offset(obj->btf, t->name_off);
3214-
if (strncmp(name, str, len))
3215-
continue;
3216-
3217-
t = btf_type_by_id(obj->btf, t->type);
3218-
if (!btf_is_func(t) || btf_func_linkage(t) != BTF_FUNC_GLOBAL) {
3219-
pr_warn("prog '%s': exception_callback:<value> decl tag not applied to the main program\n",
3220-
prog->name);
3221-
return -EINVAL;
3222-
}
3223-
if (strcmp(prog->name, btf__str_by_offset(obj->btf, t->name_off)))
3224-
continue;
3225-
/* Multiple callbacks are specified for the same prog,
3226-
* the verifier will eventually return an error for this
3227-
* case, hence simply skip appending a subprog.
3228-
*/
3229-
if (prog->exception_cb_idx >= 0) {
3230-
prog->exception_cb_idx = -1;
3231-
break;
3232-
}
3233-
3234-
name += len;
3235-
if (str_is_empty(name)) {
3236-
pr_warn("prog '%s': exception_callback:<value> decl tag contains empty value\n",
3237-
prog->name);
3238-
return -EINVAL;
3239-
}
3240-
3241-
for (k = 0; k < obj->nr_programs; k++) {
3242-
struct bpf_program *subprog = &obj->programs[k];
3243-
3244-
if (!prog_is_subprog(obj, subprog))
3245-
continue;
3246-
if (strcmp(name, subprog->name))
3247-
continue;
3248-
/* Enforce non-hidden, as from verifier point of
3249-
* view it expects global functions, whereas the
3250-
* mark_btf_static fixes up linkage as static.
3251-
*/
3252-
if (!subprog->sym_global || subprog->mark_btf_static) {
3253-
pr_warn("prog '%s': exception callback %s must be a global non-hidden function\n",
3254-
prog->name, subprog->name);
3255-
return -EINVAL;
3256-
}
3257-
/* Let's see if we already saw a static exception callback with the same name */
3258-
if (prog->exception_cb_idx >= 0) {
3259-
pr_warn("prog '%s': multiple subprogs with same name as exception callback '%s'\n",
3260-
prog->name, subprog->name);
3261-
return -EINVAL;
3262-
}
3263-
prog->exception_cb_idx = k;
3264-
break;
3265-
}
3266-
3267-
if (prog->exception_cb_idx >= 0)
3268-
continue;
3269-
pr_warn("prog '%s': cannot find exception callback '%s'\n", prog->name, name);
3270-
return -ENOENT;
3271-
}
3272-
}
3273-
skip_exception_cb:
3274-
32753195
sanitize = btf_needs_sanitization(obj);
32763196
if (sanitize) {
32773197
const void *raw_data;
@@ -6661,6 +6581,88 @@ static void bpf_object__sort_relos(struct bpf_object *obj)
66616581
}
66626582
}
66636583

6584+
static int bpf_prog_assign_exc_cb(struct bpf_object *obj, struct bpf_program *prog)
6585+
{
6586+
const char *str = "exception_callback:";
6587+
size_t pfx_len = strlen(str);
6588+
int i, j, n;
6589+
6590+
if (!obj->btf || !kernel_supports(obj, FEAT_BTF_DECL_TAG))
6591+
return 0;
6592+
6593+
n = btf__type_cnt(obj->btf);
6594+
for (i = 1; i < n; i++) {
6595+
const char *name;
6596+
struct btf_type *t;
6597+
6598+
t = btf_type_by_id(obj->btf, i);
6599+
if (!btf_is_decl_tag(t) || btf_decl_tag(t)->component_idx != -1)
6600+
continue;
6601+
6602+
name = btf__str_by_offset(obj->btf, t->name_off);
6603+
if (strncmp(name, str, pfx_len) != 0)
6604+
continue;
6605+
6606+
t = btf_type_by_id(obj->btf, t->type);
6607+
if (!btf_is_func(t) || btf_func_linkage(t) != BTF_FUNC_GLOBAL) {
6608+
pr_warn("prog '%s': exception_callback:<value> decl tag not applied to the main program\n",
6609+
prog->name);
6610+
return -EINVAL;
6611+
}
6612+
if (strcmp(prog->name, btf__str_by_offset(obj->btf, t->name_off)) != 0)
6613+
continue;
6614+
/* Multiple callbacks are specified for the same prog,
6615+
* the verifier will eventually return an error for this
6616+
* case, hence simply skip appending a subprog.
6617+
*/
6618+
if (prog->exception_cb_idx >= 0) {
6619+
prog->exception_cb_idx = -1;
6620+
break;
6621+
}
6622+
6623+
name += pfx_len;
6624+
if (str_is_empty(name)) {
6625+
pr_warn("prog '%s': exception_callback:<value> decl tag contains empty value\n",
6626+
prog->name);
6627+
return -EINVAL;
6628+
}
6629+
6630+
for (j = 0; j < obj->nr_programs; j++) {
6631+
struct bpf_program *subprog = &obj->programs[j];
6632+
6633+
if (!prog_is_subprog(obj, subprog))
6634+
continue;
6635+
if (strcmp(name, subprog->name) != 0)
6636+
continue;
6637+
/* Enforce non-hidden, as from verifier point of
6638+
* view it expects global functions, whereas the
6639+
* mark_btf_static fixes up linkage as static.
6640+
*/
6641+
if (!subprog->sym_global || subprog->mark_btf_static) {
6642+
pr_warn("prog '%s': exception callback %s must be a global non-hidden function\n",
6643+
prog->name, subprog->name);
6644+
return -EINVAL;
6645+
}
6646+
/* Let's see if we already saw a static exception callback with the same name */
6647+
if (prog->exception_cb_idx >= 0) {
6648+
pr_warn("prog '%s': multiple subprogs with same name as exception callback '%s'\n",
6649+
prog->name, subprog->name);
6650+
return -EINVAL;
6651+
}
6652+
prog->exception_cb_idx = j;
6653+
break;
6654+
}
6655+
6656+
if (prog->exception_cb_idx >= 0)
6657+
continue;
6658+
6659+
pr_warn("prog '%s': cannot find exception callback '%s'\n", prog->name, name);
6660+
return -ENOENT;
6661+
}
6662+
6663+
return 0;
6664+
}
6665+
66646666
static int
66656667
bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_path)
66666668
{
@@ -6721,6 +6723,9 @@ bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_path)
67216723
return err;
67226724
}
67236725

6726+
err = bpf_prog_assign_exc_cb(obj, prog);
6727+
if (err)
6728+
return err;
67246729
/* Now, also append exception callback if it has not been done already. */
67256730
if (prog->exception_cb_idx >= 0) {
67266731
struct bpf_program *subprog = &obj->programs[prog->exception_cb_idx];

0 commit comments

Comments
 (0)