Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
  2/* Copyright (c) 2021 Facebook */
  3/* Copyright (c) 2024, Oracle and/or its affiliates. */
  4
  5#ifdef __KERNEL__
  6#include <linux/bpf.h>
  7#include <linux/btf.h>
  8
  9#define btf_var_secinfos(t)	(struct btf_var_secinfo *)btf_type_var_secinfo(t)
 10
 11#else
 12#include "btf.h"
 13#include "libbpf_internal.h"
 14#endif
 15
 16int btf_field_iter_init(struct btf_field_iter *it, struct btf_type *t,
 17			enum btf_field_iter_kind iter_kind)
 18{
 19	it->p = NULL;
 20	it->m_idx = -1;
 21	it->off_idx = 0;
 22	it->vlen = 0;
 23
 24	switch (iter_kind) {
 25	case BTF_FIELD_ITER_IDS:
 26		switch (btf_kind(t)) {
 27		case BTF_KIND_UNKN:
 28		case BTF_KIND_INT:
 29		case BTF_KIND_FLOAT:
 30		case BTF_KIND_ENUM:
 31		case BTF_KIND_ENUM64:
 32			it->desc = (struct btf_field_desc) {};
 33			break;
 34		case BTF_KIND_FWD:
 35		case BTF_KIND_CONST:
 36		case BTF_KIND_VOLATILE:
 37		case BTF_KIND_RESTRICT:
 38		case BTF_KIND_PTR:
 39		case BTF_KIND_TYPEDEF:
 40		case BTF_KIND_FUNC:
 41		case BTF_KIND_VAR:
 42		case BTF_KIND_DECL_TAG:
 43		case BTF_KIND_TYPE_TAG:
 44			it->desc = (struct btf_field_desc) { 1, {offsetof(struct btf_type, type)} };
 45			break;
 46		case BTF_KIND_ARRAY:
 47			it->desc = (struct btf_field_desc) {
 48				2, {sizeof(struct btf_type) + offsetof(struct btf_array, type),
 49				sizeof(struct btf_type) + offsetof(struct btf_array, index_type)}
 50			};
 51			break;
 52		case BTF_KIND_STRUCT:
 53		case BTF_KIND_UNION:
 54			it->desc = (struct btf_field_desc) {
 55				0, {},
 56				sizeof(struct btf_member),
 57				1, {offsetof(struct btf_member, type)}
 58			};
 59			break;
 60		case BTF_KIND_FUNC_PROTO:
 61			it->desc = (struct btf_field_desc) {
 62				1, {offsetof(struct btf_type, type)},
 63				sizeof(struct btf_param),
 64				1, {offsetof(struct btf_param, type)}
 65			};
 66			break;
 67		case BTF_KIND_DATASEC:
 68			it->desc = (struct btf_field_desc) {
 69				0, {},
 70				sizeof(struct btf_var_secinfo),
 71				1, {offsetof(struct btf_var_secinfo, type)}
 72			};
 73			break;
 74		default:
 75			return -EINVAL;
 76		}
 77		break;
 78	case BTF_FIELD_ITER_STRS:
 79		switch (btf_kind(t)) {
 80		case BTF_KIND_UNKN:
 81			it->desc = (struct btf_field_desc) {};
 82			break;
 83		case BTF_KIND_INT:
 84		case BTF_KIND_FLOAT:
 85		case BTF_KIND_FWD:
 86		case BTF_KIND_ARRAY:
 87		case BTF_KIND_CONST:
 88		case BTF_KIND_VOLATILE:
 89		case BTF_KIND_RESTRICT:
 90		case BTF_KIND_PTR:
 91		case BTF_KIND_TYPEDEF:
 92		case BTF_KIND_FUNC:
 93		case BTF_KIND_VAR:
 94		case BTF_KIND_DECL_TAG:
 95		case BTF_KIND_TYPE_TAG:
 96		case BTF_KIND_DATASEC:
 97			it->desc = (struct btf_field_desc) {
 98				1, {offsetof(struct btf_type, name_off)}
 99			};
100			break;
101		case BTF_KIND_ENUM:
102			it->desc = (struct btf_field_desc) {
103				1, {offsetof(struct btf_type, name_off)},
104				sizeof(struct btf_enum),
105				1, {offsetof(struct btf_enum, name_off)}
106			};
107			break;
108		case BTF_KIND_ENUM64:
109			it->desc = (struct btf_field_desc) {
110				1, {offsetof(struct btf_type, name_off)},
111				sizeof(struct btf_enum64),
112				1, {offsetof(struct btf_enum64, name_off)}
113			};
114			break;
115		case BTF_KIND_STRUCT:
116		case BTF_KIND_UNION:
117			it->desc = (struct btf_field_desc) {
118				1, {offsetof(struct btf_type, name_off)},
119				sizeof(struct btf_member),
120				1, {offsetof(struct btf_member, name_off)}
121			};
122			break;
123		case BTF_KIND_FUNC_PROTO:
124			it->desc = (struct btf_field_desc) {
125				1, {offsetof(struct btf_type, name_off)},
126				sizeof(struct btf_param),
127				1, {offsetof(struct btf_param, name_off)}
128			};
129			break;
130		default:
131			return -EINVAL;
132		}
133		break;
134	default:
135		return -EINVAL;
136	}
137
138	if (it->desc.m_sz)
139		it->vlen = btf_vlen(t);
140
141	it->p = t;
142	return 0;
143}
144
145__u32 *btf_field_iter_next(struct btf_field_iter *it)
146{
147	if (!it->p)
148		return NULL;
149
150	if (it->m_idx < 0) {
151		if (it->off_idx < it->desc.t_off_cnt)
152			return it->p + it->desc.t_offs[it->off_idx++];
153		/* move to per-member iteration */
154		it->m_idx = 0;
155		it->p += sizeof(struct btf_type);
156		it->off_idx = 0;
157	}
158
159	/* if type doesn't have members, stop */
160	if (it->desc.m_sz == 0) {
161		it->p = NULL;
162		return NULL;
163	}
164
165	if (it->off_idx >= it->desc.m_off_cnt) {
166		/* exhausted this member's fields, go to the next member */
167		it->m_idx++;
168		it->p += it->desc.m_sz;
169		it->off_idx = 0;
170	}
171
172	if (it->m_idx < it->vlen)
173		return it->p + it->desc.m_offs[it->off_idx++];
174
175	it->p = NULL;
176	return NULL;
177}