Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/lib/bpf/btf_iter.c
26282 views
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
}
178
179