btf_ext
struct btf_ext *btf_ext = NULL;
btf = btf__parse(obj_path, &btf_ext);
if (!btf_ext) {
if (btf_ext->core_relo_info.len == 0) {
seg = &btf_ext->core_relo_info;
btf_ext__free(btf_ext);
struct btf_ext **btf_ext)
if (btf_ext && secs.btf_ext_data) {
*btf_ext = btf_ext__new(secs.btf_ext_data->d_buf, secs.btf_ext_data->d_size);
if (IS_ERR(*btf_ext)) {
err = PTR_ERR(*btf_ext);
} else if (btf_ext) {
*btf_ext = NULL;
if (btf_ext)
btf_ext__free(*btf_ext);
struct btf *btf__parse_elf(const char *path, struct btf_ext **btf_ext)
return libbpf_ptr(btf_parse_elf(path, NULL, btf_ext));
static struct btf *btf_parse(const char *path, struct btf *base_btf, struct btf_ext **btf_ext)
if (btf_ext)
*btf_ext = NULL;
return btf_parse_elf(path, base_btf, btf_ext);
struct btf *btf__parse(const char *path, struct btf_ext **btf_ext)
return libbpf_ptr(btf_parse(path, NULL, btf_ext));
static int btf_ext_parse_sec_info(struct btf_ext *btf_ext,
info = btf_ext->data + btf_ext->hdr->hdr_len + ext_sec->off;
if (btf_ext->data + btf_ext->data_size < info + ext_sec->len) {
static int btf_ext_parse_info(struct btf_ext *btf_ext, bool is_native)
.off = btf_ext->hdr->func_info_off,
.len = btf_ext->hdr->func_info_len,
.ext_info = &btf_ext->func_info,
.off = btf_ext->hdr->line_info_off,
.len = btf_ext->hdr->line_info_len,
.ext_info = &btf_ext->line_info,
.ext_info = &btf_ext->core_relo_info,
err = btf_ext_parse_sec_info(btf_ext, &func_info, is_native);
err = btf_ext_parse_sec_info(btf_ext, &line_info, is_native);
if (btf_ext->hdr->hdr_len < offsetofend(struct btf_ext_header, core_relo_len))
core_relo.off = btf_ext->hdr->core_relo_off;
core_relo.len = btf_ext->hdr->core_relo_len;
err = btf_ext_parse_sec_info(btf_ext, &core_relo, is_native);
static void btf_ext_bswap_info(struct btf_ext *btf_ext, void *data)
const bool is_native = btf_ext->swapped_endian;
static int btf_ext_parse(struct btf_ext *btf_ext)
__u32 hdr_len, data_size = btf_ext->data_size;
struct btf_ext_header *hdr = btf_ext->hdr;
btf_ext_bswap_hdr(btf_ext->hdr);
err = btf_ext_parse_info(btf_ext, !swapped_endian);
btf_ext_bswap_info(btf_ext, btf_ext->data);
btf_ext->swapped_endian = swapped_endian;
void btf_ext__free(struct btf_ext *btf_ext)
if (IS_ERR_OR_NULL(btf_ext))
free(btf_ext->func_info.sec_idxs);
free(btf_ext->line_info.sec_idxs);
free(btf_ext->core_relo_info.sec_idxs);
free(btf_ext->data);
free(btf_ext->data_swapped);
free(btf_ext);
struct btf_ext *btf_ext__new(const __u8 *data, __u32 size)
struct btf_ext *btf_ext;
btf_ext = calloc(1, sizeof(struct btf_ext));
if (!btf_ext)
btf_ext->data_size = size;
btf_ext->data = malloc(size);
if (!btf_ext->data) {
memcpy(btf_ext->data, data, size);
err = btf_ext_parse(btf_ext);
btf_ext__free(btf_ext);
return btf_ext;
static void *btf_ext_raw_data(const struct btf_ext *btf_ext_ro, bool swap_endian)
struct btf_ext *btf_ext = (struct btf_ext *)btf_ext_ro;
const __u32 data_sz = btf_ext->data_size;
return btf_ext->data;
else if (btf_ext->data_swapped)
return btf_ext->data_swapped;
memcpy(data, btf_ext->data, data_sz);
btf_ext_bswap_info(btf_ext, data);
btf_ext->data_swapped = data;
const void *btf_ext__raw_data(const struct btf_ext *btf_ext, __u32 *size)
data = btf_ext_raw_data(btf_ext, btf_ext->swapped_endian);
*size = btf_ext->data_size;
const void *btf_ext__get_raw_data(const struct btf_ext *btf_ext, __u32 *size);
enum btf_endianness btf_ext__endianness(const struct btf_ext *btf_ext)
return btf_ext->swapped_endian ? BTF_LITTLE_ENDIAN : BTF_BIG_ENDIAN;
return btf_ext->swapped_endian ? BTF_BIG_ENDIAN : BTF_LITTLE_ENDIAN;
int btf_ext__set_endianness(struct btf_ext *btf_ext, enum btf_endianness endian)
btf_ext->swapped_endian = is_host_big_endian() != (endian == BTF_BIG_ENDIAN);
if (!btf_ext->swapped_endian) {
free(btf_ext->data_swapped);
btf_ext->data_swapped = NULL;
struct btf_ext *btf_ext;
d->btf_ext = OPTS_GET(opts, btf_ext, NULL);
if (!d->btf_ext)
r = btf_ext_visit_str_offs(d->btf_ext, fn, ctx);
if (!d->btf_ext)
r = btf_ext_visit_type_ids(d->btf_ext, btf_dedup_remap_type_id, d);
int btf_ext_visit_type_ids(struct btf_ext *btf_ext, type_id_visit_fn visit, void *ctx)
seg = &btf_ext->func_info;
seg = &btf_ext->core_relo_info;
int btf_ext_visit_str_offs(struct btf_ext *btf_ext, str_off_visit_fn visit, void *ctx)
seg = &btf_ext->func_info;
seg = &btf_ext->line_info;
seg = &btf_ext->core_relo_info;
struct btf_ext *btf_ext;
btf_ext = OPTS_GET(opts, btf_ext, NULL);
if (btf_ext) {
err = btf_ext_visit_type_ids(btf_ext, btf_permute_remap_type_id, &p);
LIBBPF_API struct btf *btf__parse(const char *path, struct btf_ext **btf_ext);
LIBBPF_API struct btf *btf__parse_elf(const char *path, struct btf_ext **btf_ext);
LIBBPF_API struct btf_ext *btf_ext__new(const __u8 *data, __u32 size);
LIBBPF_API void btf_ext__free(struct btf_ext *btf_ext);
LIBBPF_API const void *btf_ext__raw_data(const struct btf_ext *btf_ext, __u32 *size);
LIBBPF_API enum btf_endianness btf_ext__endianness(const struct btf_ext *btf_ext);
LIBBPF_API int btf_ext__set_endianness(struct btf_ext *btf_ext,
struct btf_ext;
struct btf_ext *btf_ext;
struct btf_ext *btf_ext;
#define btf_permute_opts__last_field btf_ext
obj->btf_ext = btf_ext__new(btf_ext_data->d_buf, btf_ext_data->d_size);
err = libbpf_get_error(obj->btf_ext);
obj->btf_ext = NULL;
ext_segs[0] = &obj->btf_ext->func_info;
ext_segs[1] = &obj->btf_ext->line_info;
ext_segs[2] = &obj->btf_ext->core_relo_info;
if (obj->btf_ext && obj->btf_ext->core_relo_info.len && !obj->btf_custom_path)
if (obj->btf_ext->core_relo_info.len == 0)
seg = &obj->btf_ext->core_relo_info;
if (!obj->btf_ext || !kernel_supports(obj, FEAT_BTF_FUNC))
err = adjust_prog_btf_ext_info(obj, prog, &obj->btf_ext->func_info,
err = adjust_prog_btf_ext_info(obj, prog, &obj->btf_ext->line_info,
if (!obj->btf_ext || !prog->func_info)
struct btf_ext *btf_ext;
if (obj->btf_ext) {
btf_ext__free(obj->btf_ext);
int btf_ext_visit_type_ids(struct btf_ext *btf_ext, type_id_visit_fn visit, void *ctx);
int btf_ext_visit_str_offs(struct btf_ext *btf_ext, str_off_visit_fn visit, void *ctx);
struct btf_ext;
LIBBPF_API const void *btf_ext__get_raw_data(const struct btf_ext *btf_ext, __u32 *size);
if (!obj->btf_ext)
err = err ?: btf_ext_visit_type_ids(obj->btf_ext, check_btf_type_id, obj->btf);
err = err ?: btf_ext_visit_str_offs(obj->btf_ext, check_btf_str_off, obj->btf);
struct btf_ext *btf_ext;
btf_ext__free(linker->btf_ext);
if (!obj->btf_ext)
rec_sz = obj->btf_ext->func_info.rec_size;
for_each_btf_ext_sec(&obj->btf_ext->func_info, ext_sec) {
for_each_btf_ext_rec(&obj->btf_ext->func_info, ext_sec, i, src_rec) {
rec_sz = obj->btf_ext->line_info.rec_size;
for_each_btf_ext_sec(&obj->btf_ext->line_info, ext_sec) {
for_each_btf_ext_rec(&obj->btf_ext->line_info, ext_sec, i, src_rec) {
rec_sz = obj->btf_ext->core_relo_info.rec_size;
for_each_btf_ext_sec(&obj->btf_ext->core_relo_info, ext_sec) {
for_each_btf_ext_rec(&obj->btf_ext->core_relo_info, ext_sec, i, src_rec) {
opts.btf_ext = linker->btf_ext;
if (linker->btf_ext)
btf_ext__set_endianness(linker->btf_ext, link_endianness);
if (linker->btf_ext) {
raw_data = btf_ext__raw_data(linker->btf_ext, &raw_sz);
linker->btf_ext = btf_ext__new(data, total_sz);
err = libbpf_get_error(linker->btf_ext);
linker->btf_ext = NULL;
btf_ext__free(obj.btf_ext);
struct btf_ext *btf_ext;
obj->btf_ext = btf_ext__new(data->d_buf, shdr->sh_size);
err = libbpf_get_error(obj->btf_ext);
struct btf_ext *btf_ext = NULL;
btf = btf__parse_elf(test->file, &btf_ext);
has_btf_ext = btf_ext != NULL;
btf_ext__free(btf_ext);