Commit ae4ab4b4 authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Alexei Starovoitov

btf: expose API to work with raw btf_ext data

This patch changes struct btf_ext to retain original data in sequential
block of memory, which makes it possible to expose
btf_ext__get_raw_data() interface similar to btf__get_raw_data(), allowing
users of libbpf to get access to raw representation of .BTF.ext section.
Signed-off-by: default avatarAndrii Nakryiko <andriin@fb.com>
Acked-by: default avatarYonghong Song <yhs@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 02c87446
...@@ -42,9 +42,8 @@ struct btf { ...@@ -42,9 +42,8 @@ struct btf {
struct btf_ext_info { struct btf_ext_info {
/* /*
* info points to a deep copy of the individual info section * info points to the individual info section (e.g. func_info and
* (e.g. func_info and line_info) from the .BTF.ext. * line_info) from the .BTF.ext. It does not include the __u32 rec_size.
* It does not include the __u32 rec_size.
*/ */
void *info; void *info;
__u32 rec_size; __u32 rec_size;
...@@ -52,8 +51,13 @@ struct btf_ext_info { ...@@ -52,8 +51,13 @@ struct btf_ext_info {
}; };
struct btf_ext { struct btf_ext {
union {
struct btf_ext_header *hdr;
void *data;
};
struct btf_ext_info func_info; struct btf_ext_info func_info;
struct btf_ext_info line_info; struct btf_ext_info line_info;
__u32 data_size;
}; };
struct btf_ext_info_sec { struct btf_ext_info_sec {
...@@ -596,7 +600,7 @@ int btf__get_map_kv_tids(const struct btf *btf, const char *map_name, ...@@ -596,7 +600,7 @@ int btf__get_map_kv_tids(const struct btf *btf, const char *map_name,
return 0; return 0;
} }
struct btf_ext_sec_copy_param { struct btf_ext_sec_setup_param {
__u32 off; __u32 off;
__u32 len; __u32 len;
__u32 min_rec_size; __u32 min_rec_size;
...@@ -604,20 +608,14 @@ struct btf_ext_sec_copy_param { ...@@ -604,20 +608,14 @@ struct btf_ext_sec_copy_param {
const char *desc; const char *desc;
}; };
static int btf_ext_copy_info(struct btf_ext *btf_ext, static int btf_ext_setup_info(struct btf_ext *btf_ext,
__u8 *data, __u32 data_size, struct btf_ext_sec_setup_param *ext_sec)
struct btf_ext_sec_copy_param *ext_sec)
{ {
const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
const struct btf_ext_info_sec *sinfo; const struct btf_ext_info_sec *sinfo;
struct btf_ext_info *ext_info; struct btf_ext_info *ext_info;
__u32 info_left, record_size; __u32 info_left, record_size;
/* The start of the info sec (including the __u32 record_size). */ /* The start of the info sec (including the __u32 record_size). */
const void *info; void *info;
/* data and data_size do not include btf_ext_header from now on */
data = data + hdr->hdr_len;
data_size -= hdr->hdr_len;
if (ext_sec->off & 0x03) { if (ext_sec->off & 0x03) {
pr_debug(".BTF.ext %s section is not aligned to 4 bytes\n", pr_debug(".BTF.ext %s section is not aligned to 4 bytes\n",
...@@ -625,16 +623,15 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext, ...@@ -625,16 +623,15 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
return -EINVAL; return -EINVAL;
} }
if (data_size < ext_sec->off || info = btf_ext->data + btf_ext->hdr->hdr_len + ext_sec->off;
ext_sec->len > data_size - ext_sec->off) { info_left = ext_sec->len;
if (btf_ext->data + btf_ext->data_size < info + ext_sec->len) {
pr_debug("%s section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n", pr_debug("%s section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n",
ext_sec->desc, ext_sec->off, ext_sec->len); ext_sec->desc, ext_sec->off, ext_sec->len);
return -EINVAL; return -EINVAL;
} }
info = data + ext_sec->off;
info_left = ext_sec->len;
/* At least a record size */ /* At least a record size */
if (info_left < sizeof(__u32)) { if (info_left < sizeof(__u32)) {
pr_debug(".BTF.ext %s record size not found\n", ext_sec->desc); pr_debug(".BTF.ext %s record size not found\n", ext_sec->desc);
...@@ -692,42 +689,35 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext, ...@@ -692,42 +689,35 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
ext_info = ext_sec->ext_info; ext_info = ext_sec->ext_info;
ext_info->len = ext_sec->len - sizeof(__u32); ext_info->len = ext_sec->len - sizeof(__u32);
ext_info->rec_size = record_size; ext_info->rec_size = record_size;
ext_info->info = malloc(ext_info->len); ext_info->info = info + sizeof(__u32);
if (!ext_info->info)
return -ENOMEM;
memcpy(ext_info->info, info + sizeof(__u32), ext_info->len);
return 0; return 0;
} }
static int btf_ext_copy_func_info(struct btf_ext *btf_ext, static int btf_ext_setup_func_info(struct btf_ext *btf_ext)
__u8 *data, __u32 data_size)
{ {
const struct btf_ext_header *hdr = (struct btf_ext_header *)data; struct btf_ext_sec_setup_param param = {
struct btf_ext_sec_copy_param param = { .off = btf_ext->hdr->func_info_off,
.off = hdr->func_info_off, .len = btf_ext->hdr->func_info_len,
.len = hdr->func_info_len,
.min_rec_size = sizeof(struct bpf_func_info_min), .min_rec_size = sizeof(struct bpf_func_info_min),
.ext_info = &btf_ext->func_info, .ext_info = &btf_ext->func_info,
.desc = "func_info" .desc = "func_info"
}; };
return btf_ext_copy_info(btf_ext, data, data_size, &param); return btf_ext_setup_info(btf_ext, &param);
} }
static int btf_ext_copy_line_info(struct btf_ext *btf_ext, static int btf_ext_setup_line_info(struct btf_ext *btf_ext)
__u8 *data, __u32 data_size)
{ {
const struct btf_ext_header *hdr = (struct btf_ext_header *)data; struct btf_ext_sec_setup_param param = {
struct btf_ext_sec_copy_param param = { .off = btf_ext->hdr->line_info_off,
.off = hdr->line_info_off, .len = btf_ext->hdr->line_info_len,
.len = hdr->line_info_len,
.min_rec_size = sizeof(struct bpf_line_info_min), .min_rec_size = sizeof(struct bpf_line_info_min),
.ext_info = &btf_ext->line_info, .ext_info = &btf_ext->line_info,
.desc = "line_info", .desc = "line_info",
}; };
return btf_ext_copy_info(btf_ext, data, data_size, &param); return btf_ext_setup_info(btf_ext, &param);
} }
static int btf_ext_parse_hdr(__u8 *data, __u32 data_size) static int btf_ext_parse_hdr(__u8 *data, __u32 data_size)
...@@ -767,9 +757,7 @@ void btf_ext__free(struct btf_ext *btf_ext) ...@@ -767,9 +757,7 @@ void btf_ext__free(struct btf_ext *btf_ext)
{ {
if (!btf_ext) if (!btf_ext)
return; return;
free(btf_ext->data);
free(btf_ext->func_info.info);
free(btf_ext->line_info.info);
free(btf_ext); free(btf_ext);
} }
...@@ -786,13 +774,23 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size) ...@@ -786,13 +774,23 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size)
if (!btf_ext) if (!btf_ext)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
err = btf_ext_copy_func_info(btf_ext, data, size); btf_ext->data_size = size;
if (err) { btf_ext->data = malloc(size);
btf_ext__free(btf_ext); if (!btf_ext->data) {
return ERR_PTR(err); err = -ENOMEM;
goto done;
} }
memcpy(btf_ext->data, data, size);
err = btf_ext_setup_func_info(btf_ext);
if (err)
goto done;
err = btf_ext_copy_line_info(btf_ext, data, size); err = btf_ext_setup_line_info(btf_ext);
if (err)
goto done;
done:
if (err) { if (err) {
btf_ext__free(btf_ext); btf_ext__free(btf_ext);
return ERR_PTR(err); return ERR_PTR(err);
...@@ -801,6 +799,12 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size) ...@@ -801,6 +799,12 @@ struct btf_ext *btf_ext__new(__u8 *data, __u32 size)
return btf_ext; return btf_ext;
} }
const void *btf_ext__get_raw_data(const struct btf_ext *btf_ext, __u32 *size)
{
*size = btf_ext->data_size;
return btf_ext->data;
}
static int btf_ext_reloc_info(const struct btf *btf, static int btf_ext_reloc_info(const struct btf *btf,
const struct btf_ext_info *ext_info, const struct btf_ext_info *ext_info,
const char *sec_name, __u32 insns_cnt, const char *sec_name, __u32 insns_cnt,
...@@ -849,7 +853,8 @@ static int btf_ext_reloc_info(const struct btf *btf, ...@@ -849,7 +853,8 @@ static int btf_ext_reloc_info(const struct btf *btf,
return -ENOENT; return -ENOENT;
} }
int btf_ext__reloc_func_info(const struct btf *btf, const struct btf_ext *btf_ext, int btf_ext__reloc_func_info(const struct btf *btf,
const struct btf_ext *btf_ext,
const char *sec_name, __u32 insns_cnt, const char *sec_name, __u32 insns_cnt,
void **func_info, __u32 *cnt) void **func_info, __u32 *cnt)
{ {
...@@ -857,7 +862,8 @@ int btf_ext__reloc_func_info(const struct btf *btf, const struct btf_ext *btf_ex ...@@ -857,7 +862,8 @@ int btf_ext__reloc_func_info(const struct btf *btf, const struct btf_ext *btf_ex
insns_cnt, func_info, cnt); insns_cnt, func_info, cnt);
} }
int btf_ext__reloc_line_info(const struct btf *btf, const struct btf_ext *btf_ext, int btf_ext__reloc_line_info(const struct btf *btf,
const struct btf_ext *btf_ext,
const char *sec_name, __u32 insns_cnt, const char *sec_name, __u32 insns_cnt,
void **line_info, __u32 *cnt) void **line_info, __u32 *cnt)
{ {
......
...@@ -78,6 +78,8 @@ LIBBPF_API int btf__get_map_kv_tids(const struct btf *btf, const char *map_name, ...@@ -78,6 +78,8 @@ LIBBPF_API int btf__get_map_kv_tids(const struct btf *btf, const char *map_name,
LIBBPF_API struct btf_ext *btf_ext__new(__u8 *data, __u32 size); LIBBPF_API struct btf_ext *btf_ext__new(__u8 *data, __u32 size);
LIBBPF_API void btf_ext__free(struct btf_ext *btf_ext); LIBBPF_API void btf_ext__free(struct btf_ext *btf_ext);
LIBBPF_API const void *btf_ext__get_raw_data(const struct btf_ext* btf_ext,
__u32 *size);
LIBBPF_API int btf_ext__reloc_func_info(const struct btf *btf, LIBBPF_API int btf_ext__reloc_func_info(const struct btf *btf,
const struct btf_ext *btf_ext, const struct btf_ext *btf_ext,
const char *sec_name, __u32 insns_cnt, const char *sec_name, __u32 insns_cnt,
......
...@@ -141,6 +141,7 @@ LIBBPF_0.0.2 { ...@@ -141,6 +141,7 @@ LIBBPF_0.0.2 {
btf__load; btf__load;
btf_ext__free; btf_ext__free;
btf_ext__func_info_rec_size; btf_ext__func_info_rec_size;
btf_ext__get_raw_data;
btf_ext__line_info_rec_size; btf_ext__line_info_rec_size;
btf_ext__new; btf_ext__new;
btf_ext__reloc_func_info; btf_ext__reloc_func_info;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment