]> Git Repo - linux.git/blob - tools/lib/bpf/btf_iter.c
Linux 6.14-rc3
[linux.git] / tools / lib / bpf / btf_iter.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 #else
12 #include "btf.h"
13 #include "libbpf_internal.h"
14 #endif
15
16 int 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 }
This page took 0.040672 seconds and 4 git commands to generate.