On Wed, 2024-04-24 at 16:47 +0100, Alan Maguire wrote: [...] > @@ -1301,23 +1302,42 @@ static struct btf *btf_parse(const char *path, struct btf *base_btf, struct btf_ > if (btf_ext) > *btf_ext = NULL; > > - btf = btf_parse_raw(path, base_btf); > - err = libbpf_get_error(btf); > - if (!err) > - return btf; > - if (err != -EPROTO) > - return ERR_PTR(err); > - return btf_parse_elf(path, base_btf, btf_ext); > + if (!btf_elf_sec) { > + btf = btf_parse_raw(path, base_btf); > + err = libbpf_get_error(btf); > + if (!err) > + return btf; > + if (err != -EPROTO) > + return ERR_PTR(err); > + } > + if (!btf_elf_sec) > + btf_elf_sec = BTF_ELF_SEC; > + > + return btf_parse_elf(path, btf_elf_sec, base_btf, btf_ext); > +} > + > +struct btf *btf__parse_opts(const char *path, struct btf_parse_opts *opts) > +{ > + struct btf *base_btf; > + const char *btf_sec; > + struct btf_ext **btf_ext; > + > + if (!OPTS_VALID(opts, btf_parse_opts)) > + return libbpf_err_ptr(-EINVAL); > + base_btf = OPTS_GET(opts, base_btf, NULL); > + btf_sec = OPTS_GET(opts, btf_sec, NULL); > + btf_ext = OPTS_GET(opts, btf_ext, NULL); > + return libbpf_ptr(btf_parse(path, btf_sec, base_btf, btf_ext)); > } > I think that btf_parse() should be inlined into btf__parse_opts() and removed. As a proxy for passing btf_parse_opts fields as parameters it does not make much sense. [...]