brintos

brintos / linux-shallow public Read only

0
0
Text · 4.0 KiB · 9a6c822 Raw
178 lines · c
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#else12#include "btf.h"13#include "libbpf_internal.h"14#endif15 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}178