libbpf: Add enum64 parsing and new enum64 public API
Add enum64 parsing support and two new enum64 public APIs: btf__add_enum64 btf__add_enum64_value Also add support of signedness for BTF_KIND_ENUM. The BTF_KIND_ENUM API signatures are not changed. The signedness will be changed from unsigned to signed if btf__add_enum_value() finds any negative values. Acked-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/r/20220607062621.3719391-1-yhs@fb.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
8479aa7522
commit
dffbbdc2d9
@ -305,6 +305,8 @@ static int btf_type_size(const struct btf_type *t)
|
||||
return base_size + sizeof(__u32);
|
||||
case BTF_KIND_ENUM:
|
||||
return base_size + vlen * sizeof(struct btf_enum);
|
||||
case BTF_KIND_ENUM64:
|
||||
return base_size + vlen * sizeof(struct btf_enum64);
|
||||
case BTF_KIND_ARRAY:
|
||||
return base_size + sizeof(struct btf_array);
|
||||
case BTF_KIND_STRUCT:
|
||||
@ -334,6 +336,7 @@ static void btf_bswap_type_base(struct btf_type *t)
|
||||
static int btf_bswap_type_rest(struct btf_type *t)
|
||||
{
|
||||
struct btf_var_secinfo *v;
|
||||
struct btf_enum64 *e64;
|
||||
struct btf_member *m;
|
||||
struct btf_array *a;
|
||||
struct btf_param *p;
|
||||
@ -361,6 +364,13 @@ static int btf_bswap_type_rest(struct btf_type *t)
|
||||
e->val = bswap_32(e->val);
|
||||
}
|
||||
return 0;
|
||||
case BTF_KIND_ENUM64:
|
||||
for (i = 0, e64 = btf_enum64(t); i < vlen; i++, e64++) {
|
||||
e64->name_off = bswap_32(e64->name_off);
|
||||
e64->val_lo32 = bswap_32(e64->val_lo32);
|
||||
e64->val_hi32 = bswap_32(e64->val_hi32);
|
||||
}
|
||||
return 0;
|
||||
case BTF_KIND_ARRAY:
|
||||
a = btf_array(t);
|
||||
a->type = bswap_32(a->type);
|
||||
@ -611,6 +621,7 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
|
||||
case BTF_KIND_STRUCT:
|
||||
case BTF_KIND_UNION:
|
||||
case BTF_KIND_ENUM:
|
||||
case BTF_KIND_ENUM64:
|
||||
case BTF_KIND_DATASEC:
|
||||
case BTF_KIND_FLOAT:
|
||||
size = t->size;
|
||||
@ -658,6 +669,7 @@ int btf__align_of(const struct btf *btf, __u32 id)
|
||||
switch (kind) {
|
||||
case BTF_KIND_INT:
|
||||
case BTF_KIND_ENUM:
|
||||
case BTF_KIND_ENUM64:
|
||||
case BTF_KIND_FLOAT:
|
||||
return min(btf_ptr_sz(btf), (size_t)t->size);
|
||||
case BTF_KIND_PTR:
|
||||
@ -2176,6 +2188,10 @@ static int btf_add_enum_common(struct btf *btf, const char *name, __u32 byte_sz,
|
||||
*/
|
||||
int btf__add_enum(struct btf *btf, const char *name, __u32 byte_sz)
|
||||
{
|
||||
/*
|
||||
* set the signedness to be unsigned, it will change to signed
|
||||
* if any later enumerator is negative.
|
||||
*/
|
||||
return btf_add_enum_common(btf, name, byte_sz, false, BTF_KIND_ENUM);
|
||||
}
|
||||
|
||||
@ -2226,6 +2242,82 @@ int btf__add_enum_value(struct btf *btf, const char *name, __s64 value)
|
||||
t = btf_last_type(btf);
|
||||
btf_type_inc_vlen(t);
|
||||
|
||||
/* if negative value, set signedness to signed */
|
||||
if (value < 0)
|
||||
t->info = btf_type_info(btf_kind(t), btf_vlen(t), true);
|
||||
|
||||
btf->hdr->type_len += sz;
|
||||
btf->hdr->str_off += sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append new BTF_KIND_ENUM64 type with:
|
||||
* - *name* - name of the enum, can be NULL or empty for anonymous enums;
|
||||
* - *byte_sz* - size of the enum, in bytes.
|
||||
* - *is_signed* - whether the enum values are signed or not;
|
||||
*
|
||||
* Enum initially has no enum values in it (and corresponds to enum forward
|
||||
* declaration). Enumerator values can be added by btf__add_enum64_value()
|
||||
* immediately after btf__add_enum64() succeeds.
|
||||
*
|
||||
* Returns:
|
||||
* - >0, type ID of newly added BTF type;
|
||||
* - <0, on error.
|
||||
*/
|
||||
int btf__add_enum64(struct btf *btf, const char *name, __u32 byte_sz,
|
||||
bool is_signed)
|
||||
{
|
||||
return btf_add_enum_common(btf, name, byte_sz, is_signed,
|
||||
BTF_KIND_ENUM64);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append new enum value for the current ENUM64 type with:
|
||||
* - *name* - name of the enumerator value, can't be NULL or empty;
|
||||
* - *value* - integer value corresponding to enum value *name*;
|
||||
* Returns:
|
||||
* - 0, on success;
|
||||
* - <0, on error.
|
||||
*/
|
||||
int btf__add_enum64_value(struct btf *btf, const char *name, __u64 value)
|
||||
{
|
||||
struct btf_enum64 *v;
|
||||
struct btf_type *t;
|
||||
int sz, name_off;
|
||||
|
||||
/* last type should be BTF_KIND_ENUM64 */
|
||||
if (btf->nr_types == 0)
|
||||
return libbpf_err(-EINVAL);
|
||||
t = btf_last_type(btf);
|
||||
if (!btf_is_enum64(t))
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
/* non-empty name */
|
||||
if (!name || !name[0])
|
||||
return libbpf_err(-EINVAL);
|
||||
|
||||
/* decompose and invalidate raw data */
|
||||
if (btf_ensure_modifiable(btf))
|
||||
return libbpf_err(-ENOMEM);
|
||||
|
||||
sz = sizeof(struct btf_enum64);
|
||||
v = btf_add_type_mem(btf, sz);
|
||||
if (!v)
|
||||
return libbpf_err(-ENOMEM);
|
||||
|
||||
name_off = btf__add_str(btf, name);
|
||||
if (name_off < 0)
|
||||
return name_off;
|
||||
|
||||
v->name_off = name_off;
|
||||
v->val_lo32 = (__u32)value;
|
||||
v->val_hi32 = value >> 32;
|
||||
|
||||
/* update parent type's vlen */
|
||||
t = btf_last_type(btf);
|
||||
btf_type_inc_vlen(t);
|
||||
|
||||
btf->hdr->type_len += sz;
|
||||
btf->hdr->str_off += sz;
|
||||
return 0;
|
||||
@ -4737,6 +4829,7 @@ int btf_type_visit_type_ids(struct btf_type *t, type_id_visit_fn visit, void *ct
|
||||
case BTF_KIND_INT:
|
||||
case BTF_KIND_FLOAT:
|
||||
case BTF_KIND_ENUM:
|
||||
case BTF_KIND_ENUM64:
|
||||
return 0;
|
||||
|
||||
case BTF_KIND_FWD:
|
||||
@ -4831,6 +4924,16 @@ int btf_type_visit_str_offs(struct btf_type *t, str_off_visit_fn visit, void *ct
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTF_KIND_ENUM64: {
|
||||
struct btf_enum64 *m = btf_enum64(t);
|
||||
|
||||
for (i = 0, n = btf_vlen(t); i < n; i++, m++) {
|
||||
err = visit(&m->name_off, ctx);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTF_KIND_FUNC_PROTO: {
|
||||
struct btf_param *m = btf_params(t);
|
||||
|
||||
|
@ -215,6 +215,8 @@ LIBBPF_API int btf__add_field(struct btf *btf, const char *name, int field_type_
|
||||
/* enum construction APIs */
|
||||
LIBBPF_API int btf__add_enum(struct btf *btf, const char *name, __u32 bytes_sz);
|
||||
LIBBPF_API int btf__add_enum_value(struct btf *btf, const char *name, __s64 value);
|
||||
LIBBPF_API int btf__add_enum64(struct btf *btf, const char *name, __u32 bytes_sz, bool is_signed);
|
||||
LIBBPF_API int btf__add_enum64_value(struct btf *btf, const char *name, __u64 value);
|
||||
|
||||
enum btf_fwd_kind {
|
||||
BTF_FWD_STRUCT = 0,
|
||||
@ -454,6 +456,11 @@ static inline bool btf_is_enum(const struct btf_type *t)
|
||||
return btf_kind(t) == BTF_KIND_ENUM;
|
||||
}
|
||||
|
||||
static inline bool btf_is_enum64(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_ENUM64;
|
||||
}
|
||||
|
||||
static inline bool btf_is_fwd(const struct btf_type *t)
|
||||
{
|
||||
return btf_kind(t) == BTF_KIND_FWD;
|
||||
@ -549,6 +556,11 @@ static inline struct btf_enum *btf_enum(const struct btf_type *t)
|
||||
return (struct btf_enum *)(t + 1);
|
||||
}
|
||||
|
||||
static inline struct btf_enum64 *btf_enum64(const struct btf_type *t)
|
||||
{
|
||||
return (struct btf_enum64 *)(t + 1);
|
||||
}
|
||||
|
||||
static inline struct btf_member *btf_members(const struct btf_type *t)
|
||||
{
|
||||
return (struct btf_member *)(t + 1);
|
||||
|
@ -462,6 +462,8 @@ LIBBPF_0.8.0 {
|
||||
|
||||
LIBBPF_1.0.0 {
|
||||
global:
|
||||
btf__add_enum64;
|
||||
btf__add_enum64_value;
|
||||
libbpf_bpf_attach_type_str;
|
||||
libbpf_bpf_link_type_str;
|
||||
libbpf_bpf_map_type_str;
|
||||
|
Loading…
Reference in New Issue
Block a user