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