@@ -18,39 +18,57 @@ type structOpsProgMeta struct {
18
18
modBtfObjID uint32
19
19
}
20
20
21
- // structOpsKernTypes holds information about kernel types related to struct_ops
21
+ // structOpsKernTypes groups all kernel-side BTF artefacts that belong to a
22
+ // resolved struct_ops.
22
23
type structOpsKernTypes struct {
23
24
spec * btf.Spec
24
- // The target kernel struct type
25
- typ * btf.Struct
26
- // The BTF type ID of the target kernel struct
25
+ // target kernel struct type (e.g. tcp_congestion_ops).
26
+ typ * btf.Struct
27
27
typeID btf.TypeID
28
- // The wrapper struct type that contains the target struct
28
+ // wrapper struct "bpf_struct_ops_<name>" that contains typ.
29
29
valueType * btf.Struct
30
- // The member within ValueType that holds the target struct
30
+ // The *btf.Member within valueType that embeds typ.
31
31
dataMember * btf.Member
32
- // mod_btf
32
+ // The BTF object ID of the module where the type was found
33
+ // 0 if resolved in vmlinux.
33
34
modBtfObjId uint32
34
35
}
35
36
36
37
// used to holds "environment specific" data
37
38
type structOpsSpec struct {
38
- // attachType -> programSpec
39
+ // programName keeps track of program symbols by attach order.
39
40
programName []string
41
+
42
+ // kernFuncOff contains the byte offsets into kernVData where
43
+ // program FDs must be written for function pointer members.
40
44
kernFuncOff []int
41
- /* e.g. struct bpf_struct_ops_tcp_congestion_ops in
42
- * btf_vmlinux's format.
43
- * struct bpf_struct_ops_tcp_congestion_ops {
44
- * [... some other kernel fields ...]
45
- * struct tcp_congestion_ops data;
46
- * }
47
- * kern_vdata-size == sizeof(struct bpf_struct_ops_tcp_congestion_ops)
48
- * bpf_map__init_kern_struct_ops() will populate the "kern_vdata"
49
- * from "data".
45
+
46
+ /*
47
+ * kernVData mirrors the kernel-side representation of the
48
+ * struct_ops type, including its nested data. For example:
49
+ *
50
+ * struct bpf_struct_ops_tcp_congestion_ops {
51
+ * [... kernel internal fields ...]
52
+ * struct tcp_congestion_ops data;
53
+ * }
54
+ *
55
+ * In this case, len(kernVData) == sizeof(struct bpf_struct_ops_tcp_congestion_ops).
56
+ * copyDataMember() will copy user-supplied data
57
+ * into kernVData, which is then pushed into the map.
50
58
*/
51
- kernVData []byte
52
- kernTypes * structOpsKernTypes
53
- progAttachType map [string ]sys.AttachType
59
+ kernVData []byte
60
+
61
+ // kernTypes describes the BTF types of the target struct_ops
62
+ // object and its nested members, used for resolving offsets
63
+ // and function pointer
64
+ kernTypes * structOpsKernTypes
65
+
66
+ // progAttachType maps program names to the sys.AttachType
67
+ // expected by the kernel when attaching each function pointer.
68
+ progAttachType map [string ]sys.AttachType
69
+
70
+ // progAttachBtfID holds the BTF type ID of the struct_ops
71
+ // target in vmlinux
54
72
progAttachBtfID btf.TypeID
55
73
}
56
74
@@ -69,11 +87,8 @@ type structOpsMeta struct {
69
87
data []byte
70
88
}
71
89
72
- // extractStructOpsMeta returns the *structops.Meta embedded in a MapSpec’s Contents
73
- // according to the struct-ops convention:
74
- //
75
- // contents[0].Key == uint32(0)
76
- // contents[0].Value == *structopsMeta
90
+ // extractStructOpsMeta retrieves the structOpsMeta value embedded in a
91
+ // MapSpec's Contents, following the struct_ops map convention.
77
92
func extractStructOpsMeta (contents []MapKV ) (* structOpsMeta , error ) {
78
93
if len (contents ) == 0 {
79
94
return nil , fmt .Errorf ("struct_ops: missing meta at Contents[0]" )
@@ -92,11 +107,15 @@ func extractStructOpsMeta(contents []MapKV) (*structOpsMeta, error) {
92
107
return & meta , nil
93
108
}
94
109
95
- // findByTypeFromStruct searches the given BTF struct `st` for the * first* member
96
- // whose BTF type **sidentity** equals `typ` (after resolving modifiers) .
110
+ // findByTypeFromStruct searches for the first member of a struct whose
111
+ // resolved BTF type ID matches the given typ .
97
112
//
98
- // The comparison is done via TypeID equality inside the same Spec, so a
99
- // typedef chain that ultimately refers to the same concrete type will match.
113
+ // It resolves the BTF type ID of typ and compares it against each
114
+ // member’s TypeID in st.Members. If a match is found, the corresponding
115
+ // *btf.Member is returned.
116
+ //
117
+ // Returns an error if typ cannot be resolved, if any member type
118
+ // resolution fails, or if no member with the requested type exists.
100
119
func findByTypeFromStruct (spec * btf.Spec , st * btf.Struct , typ btf.Type ) (* btf.Member , error ) {
101
120
typeId , err := spec .TypeID (typ )
102
121
if err != nil {
@@ -116,20 +135,45 @@ func findByTypeFromStruct(spec *btf.Spec, st *btf.Struct, typ btf.Type) (*btf.Me
116
135
return nil , fmt .Errorf ("member of type %s not found in %s" , typ .TypeName (), st .Name )
117
136
}
118
137
119
- // findStructByNameWithPrefix looks up a BTF struct whose name is the given `name`
120
- // prefixed by `structOpsValuePrefix` (“bpf_dummy_ops” → “bpf_struct_ops_bpf_dummy_ops”).
138
+ // findStructByNameWithPrefix resolves a struct_ops "value" type by name,
139
+ // after applying the standard prefix convention.
140
+ //
141
+ // It expects val to be the user-visible struct type (e.g. "bpf_dummy_ops")
142
+ // and looks up the kernel-side wrapper name:
143
+ //
144
+ // "bpf_dummy_ops" -> "bpf_struct_ops_bpf_dummy_ops"
145
+ //
146
+ // Returns the matching *btf.Struct, the *btf.Spec it was found in (either the
147
+ // base vmlinux spec or a module spec), and the module BTF ID (0 for vmlinux).
148
+ // See doFindStructTypeByName for resolution details and error behavior.
121
149
func findStructByNameWithPrefix (s * btf.Spec , val * btf.Struct ) (* btf.Struct , * btf.Spec , uint32 , error ) {
122
150
return doFindStructTypeByName (s , structOpsValuePrefix + val .TypeName ())
123
151
}
124
152
125
- // findStructTypeByName iterates over *all* BTF types contained in the given Spec and
126
- // returns the first *btf.Struct whose TypeName() exactly matches `name`.
153
+ // findStructTypeByName resolves the exact BTF struct type that corresponds
154
+ // to typ.TypeName() by searching first in vmlinux and then across all loaded
155
+ // kernel modules.
156
+ //
157
+ // Returns the first *btf.Struct that matches the name verbatim, the *btf.Spec
158
+ // where it was found, and the module BTF ID (0 if found in vmlinux).
159
+ // If no matching struct exists anywhere, btf.ErrNotFound is returned.
127
160
func findStructTypeByName (s * btf.Spec , typ * btf.Struct ) (* btf.Struct , * btf.Spec , uint32 , error ) {
128
161
return doFindStructTypeByName (s , typ .TypeName ())
129
162
}
130
163
131
- // doFindStructTypeByName iterates over *all* BTF types contained in the given Spec and
132
- // returns the first *btf.Struct whose TypeName() exactly matches `name`.
164
+ // doFindStructTypeByName looks up a struct type with the exact name in the
165
+ // provided base BTF spec, and falls back to scanning all loaded module BTFs
166
+ // if it is not present in vmlinux.
167
+ //
168
+ // Search order and behavior:
169
+ // 1. vmlinux (base spec): try AnyTypeByName(name). If it exists and is a
170
+ // *btf.Struct, return it immediately with moduleID=0.
171
+ // - If AnyTypeByName returns a non-notfound error, the error is propagated.
172
+ // - If a type is found but is not a *btf.Struct, we fall back to modules.
173
+ // 2. modules: see findStructTypeByNameFromModule.
174
+ //
175
+ // Returns (*btf.Struct, *btf.Spec, moduleID, nil) on success, or btf.ErrNotFound
176
+ // if no matching struct is present in vmlinux or any module.
133
177
func doFindStructTypeByName (s * btf.Spec , name string ) (* btf.Struct , * btf.Spec , uint32 , error ) {
134
178
if s == nil {
135
179
return nil , nil , 0 , fmt .Errorf ("nil BTF: %w" , btf .ErrNotFound )
@@ -146,8 +190,13 @@ func doFindStructTypeByName(s *btf.Spec, name string) (*btf.Struct, *btf.Spec, u
146
190
return findStructTypeByNameFromModule (s , name )
147
191
}
148
192
149
- // findStructTypeByNameFromModule walks over the BTF info of loaded modules and
150
- // searches for struct `name`.
193
+ // findStructTypeByNameFromModule scans all loaded kernel modules and tries
194
+ // to resolve a struct type with the exact name. The iteration uses the base
195
+ // vmlinux spec for string/ID interning as required by btf.Handle.Spec(base).
196
+ //
197
+ // For the first module where AnyTypeByName(name) returns a *btf.Struct,
198
+ // the function returns that struct, the module's *btf.Spec, and its BTF ID.
199
+ // If the type is not found in any module, btf.ErrNotFound is returned.
151
200
func findStructTypeByNameFromModule (base * btf.Spec , name string ) (* btf.Struct , * btf.Spec , uint32 , error ) {
152
201
it := new (btf.HandleIterator )
153
202
@@ -184,9 +233,9 @@ func findStructTypeByNameFromModule(base *btf.Spec, name string) (*btf.Struct, *
184
233
return nil , nil , 0 , btf .ErrNotFound
185
234
}
186
235
187
- // findStructOpsKernTypes discovers all kernel-side BTF artefacts related to a given
188
- //
189
- // *struct_ops* family identified by its **base name** (e.g. "tcp_congestion_ops").
236
+ // findStructOpsKernTypes discovers all kernel-side BTF artifacts that belong to
237
+ // a given struct_ops, identified by the user-visible base struct name
238
+ // (e.g., "tcp_congestion_ops").
190
239
func findStructOpsKernTypes (userStructType * btf.Struct ) (* structOpsKernTypes , error ) {
191
240
spec , err := btf .LoadKernelSpec ()
192
241
if err != nil {
@@ -227,16 +276,14 @@ func findStructOpsKernTypes(userStructType *btf.Struct) (*structOpsKernTypes, er
227
276
}, nil
228
277
}
229
278
230
- // skipModsAndTypedefs returns the **next underlying type** by peeling off a
231
- // single layer of “type wrappers” in BTF:
232
- //
233
- // - btf.Typedef
234
- // - btf.Const
235
- // - btf.Volatile
236
- // - btf.Restrict
279
+ // skipModsAndTypedefs resolves a single layer of BTF indirection/qualification
280
+ // for the given type within the provided *btf.Spec.
237
281
//
238
- // If `typ` is already a concrete type (struct, int, ptr, etc.) it is returned
239
- // unchanged.
282
+ // Behavior:
283
+ // - Uses s.TypeID(typ) and s.TypeByID(id) to canonicalize the type within s.
284
+ // - If the resolved type is a Typedef or C qualifier (Const/Volatile/Restrict),
285
+ // returns its immediate underlying type (one level).
286
+ // - Otherwise returns the resolved type as-is.
240
287
func skipModsAndTypedefs (s * btf.Spec , typ btf.Type ) (btf.Type , error ) {
241
288
typeID , err := s .TypeID (typ )
242
289
if err != nil {
@@ -269,6 +316,7 @@ func getStructMemberByName(s *btf.Struct, name string) (btf.Member, error) {
269
316
if member .Name == name {
270
317
return member , nil
271
318
}
319
+ // target kernel struct type (e.g. tcp_congestion_ops).
272
320
}
273
321
return btf.Member {}, fmt .Errorf ("member %s not found in struct %s" , name , s .Name )
274
322
}
0 commit comments