Commit 1c508843 authored by Alexei Starovoitov's avatar Alexei Starovoitov
Browse files

Merge branch 'bpf: add support for BTF_KIND_DECL_TAG typedef'

Yonghong Song says:

====================

Latest upstream llvm-project added support for btf_decl_tag attributes
for typedef declarations ([1], [2]). Similar to other btf_decl_tag cases,
func/func_param/global_var/struct/union/field, btf_decl_tag with typedef
declaration can carry information from kernel source to clang compiler
and then to dwarf/BTF, for bpf verification or other use cases.

This patch set added kernel support for BTF_KIND_DECL_TAG to typedef
declaration (Patch 1). Additional selftests are added to cover
unit testing, dedup, or bpf program usage of btf_decl_tag with typedef.
(Patches 2, 3 and 4). The btf documentation is updated to include
BTF_KIND_DECL_TAG typedef (Patch 5).

  [1] https://reviews.llvm.org/D110127
  [2] https://reviews.llvm.org/D112259


====================

Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents a33f607f 5a867134
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -474,7 +474,7 @@ No additional type data follow ``btf_type``.
 * ``info.kind_flag``: 0
 * ``info.kind``: BTF_KIND_DECL_TAG
 * ``info.vlen``: 0
 * ``type``: ``struct``, ``union``, ``func`` or ``var``
 * ``type``: ``struct``, ``union``, ``func``, ``var`` or ``typedef``

``btf_type`` is followed by ``struct btf_decl_tag``.::

@@ -483,8 +483,8 @@ No additional type data follow ``btf_type``.
    };

The ``name_off`` encodes btf_decl_tag attribute string.
The ``type`` should be ``struct``, ``union``, ``func`` or ``var``.
For ``var`` type, ``btf_decl_tag.component_idx`` must be ``-1``.
The ``type`` should be ``struct``, ``union``, ``func``, ``var`` or ``typedef``.
For ``var`` or ``typedef`` type, ``btf_decl_tag.component_idx`` must be ``-1``.
For the other three types, if the btf_decl_tag attribute is
applied to the ``struct``, ``union`` or ``func`` itself,
``btf_decl_tag.component_idx`` must be ``-1``. Otherwise,
+2 −2
Original line number Diff line number Diff line
@@ -468,7 +468,7 @@ static bool btf_type_is_decl_tag(const struct btf_type *t)
static bool btf_type_is_decl_tag_target(const struct btf_type *t)
{
	return btf_type_is_func(t) || btf_type_is_struct(t) ||
	       btf_type_is_var(t);
	       btf_type_is_var(t) || btf_type_is_typedef(t);
}

u32 btf_nr_types(const struct btf *btf)
@@ -3885,7 +3885,7 @@ static int btf_decl_tag_resolve(struct btf_verifier_env *env,

	component_idx = btf_type_decl_tag(t)->component_idx;
	if (component_idx != -1) {
		if (btf_type_is_var(next_type)) {
		if (btf_type_is_var(next_type) || btf_type_is_typedef(next_type)) {
			btf_verifier_log_type(env, v->t, "Invalid component_idx");
			return -EINVAL;
		}
+77 −6
Original line number Diff line number Diff line
@@ -3903,6 +3903,42 @@ static struct btf_raw_test raw_tests[] = {
	.btf_load_err = true,
	.err_str = "Invalid component_idx",
},
{
	.descr = "decl_tag test #13, typedef, well-formed",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPEDEF_ENC(NAME_TBD, 1),			/* [2] */
		BTF_DECL_TAG_ENC(NAME_TBD, 2, -1),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0t\0tag"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "tag_type_check_btf",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 1,
},
{
	.descr = "decl_tag test #14, typedef, invalid component_idx",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPEDEF_ENC(NAME_TBD, 1),			/* [2] */
		BTF_DECL_TAG_ENC(NAME_TBD, 2, 0),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0local\0tag"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "tag_type_check_btf",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid component_idx",
},

}; /* struct btf_raw_test raw_tests[] */

@@ -6841,11 +6877,12 @@ const struct btf_dedup_test dedup_tests[] = {
				BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 8),
			BTF_FUNC_ENC(NAME_TBD, 12),					/* [13] func */
			BTF_TYPE_FLOAT_ENC(NAME_TBD, 2),				/* [14] float */
			BTF_DECL_TAG_ENC(NAME_TBD, 13, -1),				/* [15] tag */
			BTF_DECL_TAG_ENC(NAME_TBD, 13, 1),				/* [16] tag */
			BTF_DECL_TAG_ENC(NAME_TBD, 13, -1),				/* [15] decl_tag */
			BTF_DECL_TAG_ENC(NAME_TBD, 13, 1),				/* [16] decl_tag */
			BTF_DECL_TAG_ENC(NAME_TBD, 7, -1),				/* [17] decl_tag */
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P"),
		BTF_STR_SEC("\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P\0Q"),
	},
	.expect = {
		.raw_types = {
@@ -6869,11 +6906,12 @@ const struct btf_dedup_test dedup_tests[] = {
				BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 8),
			BTF_FUNC_ENC(NAME_TBD, 12),					/* [13] func */
			BTF_TYPE_FLOAT_ENC(NAME_TBD, 2),				/* [14] float */
			BTF_DECL_TAG_ENC(NAME_TBD, 13, -1),				/* [15] tag */
			BTF_DECL_TAG_ENC(NAME_TBD, 13, 1),				/* [16] tag */
			BTF_DECL_TAG_ENC(NAME_TBD, 13, -1),				/* [15] decl_tag */
			BTF_DECL_TAG_ENC(NAME_TBD, 13, 1),				/* [16] decl_tag */
			BTF_DECL_TAG_ENC(NAME_TBD, 7, -1),				/* [17] decl_tag */
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P"),
		BTF_STR_SEC("\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M\0N\0O\0P\0Q"),
	},
	.opts = {
		.dont_resolve_fwds = false,
@@ -7168,6 +7206,39 @@ const struct btf_dedup_test dedup_tests[] = {
		.dont_resolve_fwds = false,
	},
},
{
	.descr = "dedup: typedef tags",
	.input = {
		.raw_types = {
			/* int */
			BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
			BTF_TYPEDEF_ENC(NAME_NTH(1), 1),		/* [2] */
			BTF_TYPEDEF_ENC(NAME_NTH(1), 1),		/* [3] */
			/* tag -> t: tag1, tag2 */
			BTF_DECL_TAG_ENC(NAME_NTH(2), 2, -1),		/* [4] */
			BTF_DECL_TAG_ENC(NAME_NTH(3), 2, -1),		/* [5] */
			/* tag -> t: tag1, tag3 */
			BTF_DECL_TAG_ENC(NAME_NTH(2), 3, -1),		/* [6] */
			BTF_DECL_TAG_ENC(NAME_NTH(4), 3, -1),		/* [7] */
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0t\0tag1\0tag2\0tag3"),
	},
	.expect = {
		.raw_types = {
			BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
			BTF_TYPEDEF_ENC(NAME_NTH(1), 1),		/* [2] */
			BTF_DECL_TAG_ENC(NAME_NTH(2), 2, -1),		/* [3] */
			BTF_DECL_TAG_ENC(NAME_NTH(3), 2, -1),		/* [4] */
			BTF_DECL_TAG_ENC(NAME_NTH(4), 2, -1),		/* [5] */
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0t\0tag1\0tag2\0tag3"),
	},
	.opts = {
		.dont_resolve_fwds = false,
	},
},

};

+7 −2
Original line number Diff line number Diff line
@@ -24,18 +24,23 @@ struct key_t {
	int c;
} __tag1 __tag2;

typedef struct {
	int a;
	int b;
} value_t __tag1 __tag2;

struct {
	__uint(type, BPF_MAP_TYPE_HASH);
	__uint(max_entries, 3);
	__type(key, struct key_t);
	__type(value, __u64);
	__type(value, value_t);
} hashmap1 SEC(".maps");


static __noinline int foo(int x __tag1 __tag2) __tag1 __tag2
{
	struct key_t key;
	__u64 val = 1;
	value_t val = {};

	key.a = key.b = key.c = x;
	bpf_map_update_elem(&hashmap1, &key, &val, 0);