Commit 2bce2c1c authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Daniel Borkmann
Browse files

libbpf: Make use of BTF field iterator in BPF linker code



Switch all BPF linker code dealing with iterating BTF type ID and string
offset fields to new btf_field_iter facilities.

Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Tested-by: default avatarAlan Maguire <alan.maguire@oracle.com>
Acked-by: default avatarEduard Zingerman <eddyz87@gmail.com>
Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/bpf/20240605001629.4061937-3-andrii@kernel.org
parent 68153bb2
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -5267,7 +5267,7 @@ __u32 *btf_field_iter_next(struct btf_field_iter *it)
		return NULL;

	if (it->m_idx < 0) {
		if (it->off_idx < it->desc.t_cnt)
		if (it->off_idx < it->desc.t_off_cnt)
			return it->p + it->desc.t_offs[it->off_idx++];
		/* move to per-member iteration */
		it->m_idx = 0;
@@ -5281,7 +5281,7 @@ __u32 *btf_field_iter_next(struct btf_field_iter *it)
		return NULL;
	}

	if (it->off_idx >= it->desc.m_cnt) {
	if (it->off_idx >= it->desc.m_off_cnt) {
		/* exhausted this member's fields, go to the next member */
		it->m_idx++;
		it->p += it->desc.m_sz;
+2 −2
Original line number Diff line number Diff line
@@ -515,11 +515,11 @@ enum btf_field_iter_kind {

struct btf_field_desc {
	/* once-per-type offsets */
	int t_cnt, t_offs[2];
	int t_off_cnt, t_offs[2];
	/* member struct size, or zero, if no members */
	int m_sz;
	/* repeated per-member offsets */
	int m_cnt, m_offs[1];
	int m_off_cnt, m_offs[1];
};

struct btf_field_iter {
+36 −22
Original line number Diff line number Diff line
@@ -957,19 +957,33 @@ static int check_btf_str_off(__u32 *str_off, void *ctx)
static int linker_sanity_check_btf(struct src_obj *obj)
{
	struct btf_type *t;
	int i, n, err = 0;
	int i, n, err;

	if (!obj->btf)
		return 0;

	n = btf__type_cnt(obj->btf);
	for (i = 1; i < n; i++) {
		struct btf_field_iter it;
		__u32 *type_id, *str_off;

		t = btf_type_by_id(obj->btf, i);

		err = err ?: btf_type_visit_type_ids(t, check_btf_type_id, obj->btf);
		err = err ?: btf_type_visit_str_offs(t, check_btf_str_off, obj->btf);
		err = btf_field_iter_init(&it, t, BTF_FIELD_ITER_IDS);
		if (err)
			return err;
		while ((type_id = btf_field_iter_next(&it))) {
			if (*type_id >= n)
				return -EINVAL;
		}

		err = btf_field_iter_init(&it, t, BTF_FIELD_ITER_STRS);
		if (err)
			return err;
		while ((str_off = btf_field_iter_next(&it))) {
			if (!btf__str_by_offset(obj->btf, *str_off))
				return -EINVAL;
		}
	}

	return 0;
@@ -2234,26 +2248,10 @@ static int linker_fixup_btf(struct src_obj *obj)
	return 0;
}

static int remap_type_id(__u32 *type_id, void *ctx)
{
	int *id_map = ctx;
	int new_id = id_map[*type_id];

	/* Error out if the type wasn't remapped. Ignore VOID which stays VOID. */
	if (new_id == 0 && *type_id != 0) {
		pr_warn("failed to find new ID mapping for original BTF type ID %u\n", *type_id);
		return -EINVAL;
	}

	*type_id = id_map[*type_id];

	return 0;
}

static int linker_append_btf(struct bpf_linker *linker, struct src_obj *obj)
{
	const struct btf_type *t;
	int i, j, n, start_id, id;
	int i, j, n, start_id, id, err;
	const char *name;

	if (!obj->btf)
@@ -2324,11 +2322,27 @@ static int linker_append_btf(struct bpf_linker *linker, struct src_obj *obj)
	n = btf__type_cnt(linker->btf);
	for (i = start_id; i < n; i++) {
		struct btf_type *dst_t = btf_type_by_id(linker->btf, i);
		struct btf_field_iter it;
		__u32 *type_id;

		err = btf_field_iter_init(&it, dst_t, BTF_FIELD_ITER_IDS);
		if (err)
			return err;

		while ((type_id = btf_field_iter_next(&it))) {
			int new_id = obj->btf_type_map[*type_id];

		if (btf_type_visit_type_ids(dst_t, remap_type_id, obj->btf_type_map))
			/* Error out if the type wasn't remapped. Ignore VOID which stays VOID. */
			if (new_id == 0 && *type_id != 0) {
				pr_warn("failed to find new ID mapping for original BTF type ID %u\n",
					*type_id);
				return -EINVAL;
			}

			*type_id = obj->btf_type_map[*type_id];
		}
	}

	/* Rewrite VAR/FUNC underlying types (i.e., FUNC's FUNC_PROTO and VAR's
	 * actual type), if necessary
	 */