|
1 | 1 | package ebpf
|
2 | 2 |
|
3 |
| -import ( |
4 |
| - "errors" |
5 |
| - "fmt" |
6 |
| - |
7 |
| - "github.com/cilium/ebpf/btf" |
8 |
| -) |
| 3 | +import "github.com/cilium/ebpf/btf" |
9 | 4 |
|
10 | 5 | const structOpsValuePrefix = "bpf_struct_ops_"
|
11 | 6 |
|
12 |
| -// findStructTypeByName looks up a struct type with the exact name in the |
13 |
| -// provided base BTF spec, and falls back to scanning all loaded module BTFs |
14 |
| -// if it is not present in vmlinux. |
15 |
| -// |
16 |
| -// Search order and behavior: |
17 |
| -// 1. vmlinux (base spec): try AnyTypeByName(name). If it exists and is a |
18 |
| -// *btf.Struct, return it immediately with moduleID=0. |
19 |
| -// - If AnyTypeByName returns a non-notfound error, the error is propagated. |
20 |
| -// - If a type is found but is not a *btf.Struct, we fall back to modules. |
21 |
| -// 2. modules: see findStructTypeByNameFromModule. |
22 |
| -// |
23 |
| -// Returns (*btf.Struct, *btf.Spec, moduleID, nil) on success, or btf.ErrNotFound |
24 |
| -// if no matching struct is present in vmlinux or any module. |
25 |
| -func findStructTypeByName(s *btf.Spec, name string) (*btf.Struct, *btf.Spec, uint32, error) { |
26 |
| - if s == nil { |
27 |
| - return nil, nil, 0, fmt.Errorf("nil BTF: %w", btf.ErrNotFound) |
28 |
| - } |
29 |
| - |
30 |
| - t, err := s.AnyTypeByName(name) |
31 |
| - if err == nil { |
32 |
| - if typ, ok := btf.As[*btf.Struct](t); ok { |
33 |
| - return typ, s, 0, nil |
34 |
| - } |
35 |
| - } else if !errors.Is(err, btf.ErrNotFound) { |
36 |
| - return nil, nil, 0, err |
37 |
| - } |
38 |
| - return findStructTypeByNameFromModule(s, name) |
39 |
| -} |
40 |
| - |
41 |
| -// findStructTypeByNameFromModule scans all loaded kernel modules and tries |
42 |
| -// to resolve a struct type with the exact name. The iteration uses the base |
43 |
| -// vmlinux spec for string/ID interning as required by btf.Handle.Spec(base). |
44 |
| -// |
45 |
| -// For the first module where AnyTypeByName(name) returns a *btf.Struct, |
46 |
| -// the function returns that struct, the module's *btf.Spec, and its BTF ID. |
47 |
| -// If the type is not found in any module, btf.ErrNotFound is returned. |
48 |
| -func findStructTypeByNameFromModule(base *btf.Spec, name string) (*btf.Struct, *btf.Spec, uint32, error) { |
49 |
| - it := new(btf.HandleIterator) |
50 |
| - |
51 |
| - for it.Next() { |
52 |
| - defer it.Handle.Close() |
53 |
| - |
54 |
| - info, err := it.Handle.Info() |
55 |
| - if err != nil { |
56 |
| - return nil, nil, 0, fmt.Errorf("get info for BTF ID %d: %w", it.ID, err) |
57 |
| - } |
58 |
| - |
59 |
| - if !info.IsModule() { |
60 |
| - continue |
61 |
| - } |
62 |
| - |
63 |
| - spec, err := it.Handle.Spec(base) |
64 |
| - if err != nil { |
65 |
| - return nil, nil, 0, fmt.Errorf("parse types for module %s: %w", info.Name, err) |
66 |
| - } |
67 |
| - |
68 |
| - t, err := spec.AnyTypeByName(name) |
69 |
| - if errors.Is(err, btf.ErrNotFound) { |
70 |
| - continue |
71 |
| - } |
72 |
| - |
73 |
| - if err != nil { |
74 |
| - return nil, nil, 0, fmt.Errorf("lookup type in module %s: %w", info.Name, err) |
75 |
| - } |
76 |
| - |
77 |
| - if typ, ok := btf.As[*btf.Struct](t); ok { |
78 |
| - return typ, spec, uint32(it.ID), nil |
79 |
| - } |
80 |
| - } |
81 |
| - |
82 |
| - return nil, nil, 0, btf.ErrNotFound |
83 |
| -} |
84 |
| - |
85 | 7 | // getStructMemberIndexByName returns the index of `member` within struct `s` by
|
86 | 8 | // comparing the member name.
|
87 | 9 | func getStructMemberIndexByName(s *btf.Struct, name string) int {
|
|
0 commit comments