bpftool: Handle multi-split BTF by supporting multiple base BTFs

For bpftool to be able to dump .BTF.inline data in
/sys/kernel/btf/foo.inline for module foo, it needs to support
multi-split BTF because the parent-child relationship of BTF
inline data for modules is

vmlinux BTF data
	module BTF data
		module BTF inline data

So for example to dump BTF inline info for xfs we would run

$ bpftool btf dump -B /sys/kernel/btf/vmlinux -B /sys/kernel/btf/xfs file /sys/kernel/btf/xfs.inline

Multiple bases are specified with the vmlinux base BTF first (parent)
followed by the xfs BTF (child), and finally the XFS BTF inline info.

Update help text accordingly to reflect the ability to specify multiple
in-order root-to-branch bases.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20260924111428.75957-8-alan.maguire@oracle.com
This commit is contained in:
Alan Maguire 2026-09-24 12:14:24 +01:00 committed by Alexei Starovoitov
parent 49a4c23a22
commit 7890a57356
No known key found for this signature in database
2 changed files with 22 additions and 4 deletions

View File

@ -1545,7 +1545,7 @@ static int do_help(int argc, char **argv)
" " HELP_SPEC_MAP "\n"
" " HELP_SPEC_PROGRAM "\n"
" " HELP_SPEC_OPTIONS " |\n"
" {-B|--base-btf} }\n"
" {[{-B|--base-btf} FILE]... }}\n"
"",
bin_name, "btf");

View File

@ -466,6 +466,7 @@ int main(int argc, char **argv)
{ "base-btf", required_argument, NULL, 'B' },
{ 0 }
};
struct btf *new_base_btf = NULL, *root_base_btf = NULL;
bool version_requested = false;
int opt, ret;
@ -515,12 +516,16 @@ int main(int argc, char **argv)
verifier_logs = true;
break;
case 'B':
base_btf = btf__parse(optarg, NULL);
if (!base_btf) {
/* handle multi-split BTF */
new_base_btf = btf__parse_split(optarg, base_btf);
if (!new_base_btf) {
p_err("failed to parse base BTF at '%s': %d\n",
optarg, -errno);
return -1;
}
base_btf = new_base_btf;
if (!root_base_btf)
root_base_btf = base_btf;
break;
case 'L':
use_loader = true;
@ -567,7 +572,20 @@ int main(int argc, char **argv)
if (json_output)
jsonw_destroy(&json_wtr);
btf__free(base_btf);
while (base_btf) {
bool is_root = base_btf == root_base_btf;
new_base_btf = (struct btf *)btf__base_btf(base_btf);
btf__free(base_btf);
/*
* Do not free base BTF that is an owned .BTF.base ; leads
* to a double-free, so only free as far as the root base
* we explicitly read with -B above.
*/
if (is_root)
break;
base_btf = new_base_btf;
}
return ret;
}