LLVM ends a cleanup landing pad with a call to _Unwind_Resume, the unwind ABI's name for carrying an unwind on. The kernel's kfunc is bpf_unwind_resume: _Unwind_Resume in the kernel's own symbol table, for a function whose body never runs, would only confuse. The compiler emits the call but no declaration, and libbpf refuses an extern it has no BTF for, so the program declares it itself (extern void _Unwind_Resume(void *) __ksym;), as a language runtime has to. libbpf only translates the name, both where it resolves the kfunc itself and where it records the name for a light skeleton's loader to resolve. Signed-off-by: Yonghong Song --- tools/lib/bpf/libbpf.c | 45 ++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index cb09ded90773..5f41d3ba2822 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -9187,6 +9187,23 @@ static void fixup_verifier_log(struct bpf_program *prog, char *buf, size_t buf_s } } +/* + * LLVM terminates a cleanup landing pad with a call to _Unwind_Resume, the + * base unwind ABI's entry point for carrying an unwind on once a frame's + * cleanups have run. The kernel knows it as bpf_unwind_resume. Any other + * extern, and a variable of that name, is looked up by @name unchanged. + */ +static const char *kern_extern_name(const struct bpf_object *obj, + const struct extern_desc *ext, const char *name) +{ + const char *essent = ext->essent_name ?: ext->name; + + if (!btf_is_func(btf__type_by_id(obj->btf, ext->btf_id)) || + strcmp(essent, "_Unwind_Resume")) + return name; + return "bpf_unwind_resume"; +} + static int bpf_program_record_relos(struct bpf_program *prog) { struct bpf_object *obj = prog->obj; @@ -9195,6 +9212,7 @@ static int bpf_program_record_relos(struct bpf_program *prog) for (i = 0; i < prog->nr_reloc; i++) { struct reloc_desc *relo = &prog->reloc_desc[i]; struct extern_desc *ext = &obj->externs[relo->ext_idx]; + const char *name; int kind; switch (relo->type) { @@ -9203,14 +9221,14 @@ static int bpf_program_record_relos(struct bpf_program *prog) continue; kind = btf_is_var(btf__type_by_id(obj->btf, ext->btf_id)) ? BTF_KIND_VAR : BTF_KIND_FUNC; - bpf_gen__record_extern(obj->gen_loader, ext->name, - ext->is_weak, !ext->ksym.type_id, - true, kind, relo->insn_idx); + name = kern_extern_name(obj, ext, ext->name); + bpf_gen__record_extern(obj->gen_loader, name, ext->is_weak, + !ext->ksym.type_id, true, kind, relo->insn_idx); break; case RELO_EXTERN_CALL: - bpf_gen__record_extern(obj->gen_loader, ext->name, - ext->is_weak, false, false, BTF_KIND_FUNC, - relo->insn_idx); + name = kern_extern_name(obj, ext, ext->name); + bpf_gen__record_extern(obj->gen_loader, name, ext->is_weak, false, + false, BTF_KIND_FUNC, relo->insn_idx); break; case RELO_CORE: { struct bpf_core_relo cr = { @@ -9684,17 +9702,24 @@ static int bpf_object__resolve_ksym_func_btf_id(struct bpf_object *obj, struct module_btf *mod_btf = NULL; const struct btf_type *kern_func; struct btf *kern_btf = NULL; + const char *local_name, *kern_name; int ret; local_func_proto_id = ext->ksym.type_id; - kfunc_id = find_ksym_btf_id(obj, ext->essent_name ?: ext->name, BTF_KIND_FUNC, &kern_btf, - &mod_btf); + local_name = ext->essent_name ?: ext->name; + kern_name = kern_extern_name(obj, ext, local_name); + + kfunc_id = find_ksym_btf_id(obj, kern_name, BTF_KIND_FUNC, &kern_btf, &mod_btf); if (kfunc_id < 0) { if (kfunc_id == -ESRCH && ext->is_weak) return 0; - pr_warn("extern (func ksym) '%s': not found in kernel or module BTFs\n", - ext->name); + if (kern_name != local_name) + pr_warn("extern (func ksym) '%s' ('%s' in the kernel): not found in kernel or module BTFs\n", + ext->name, kern_name); + else + pr_warn("extern (func ksym) '%s': not found in kernel or module BTFs\n", + ext->name); return kfunc_id; } -- 2.53.0-Meta