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: Andrii Nakryiko <andriin@fb.com> Acked-by: Yonghong Song <yhs@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
02c874460f
commit
ae4ab4b411
@ -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 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
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,
|
|||||||
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 {
|
|||||||
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,
|
|||||||
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);
|
||||||
@ -646,7 +643,7 @@ static int btf_ext_copy_info(struct btf_ext *btf_ext,
|
|||||||
if (record_size < ext_sec->min_rec_size ||
|
if (record_size < ext_sec->min_rec_size ||
|
||||||
record_size & 0x03) {
|
record_size & 0x03) {
|
||||||
pr_debug("%s section in .BTF.ext has invalid record size %u\n",
|
pr_debug("%s section in .BTF.ext has invalid record size %u\n",
|
||||||
ext_sec->desc, record_size);
|
ext_sec->desc, record_size);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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, ¶m);
|
return btf_ext_setup_info(btf_ext, ¶m);
|
||||||
}
|
}
|
||||||
|
|
||||||
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, ¶m);
|
return btf_ext_setup_info(btf_ext, ¶m);
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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_copy_line_info(btf_ext, data, size);
|
err = btf_ext_setup_func_info(btf_ext);
|
||||||
|
if (err)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
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)
|
|||||||
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,
|
|||||||
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
|
|||||||
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,
|
|||||||
|
|
||||||
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 {
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user