Commit dffbbdc2 authored by Yonghong Song's avatar Yonghong Song Committed by Alexei Starovoitov
Browse files

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: default avatarAndrii Nakryiko <andrii@kernel.org>
Signed-off-by: default avatarYonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/r/20220607062621.3719391-1-yhs@fb.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 8479aa75
Loading
Loading
Loading
Loading
+103 −0
Original line number Diff line number Diff line
@@ -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);

+12 −0
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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;