Skip to content

Commit 5de6180

Browse files
feat: add array support and sched example (#2)
* feat: add support getting member from arrays with integer and enum fields indexes * feat: add scheduler related probes example * feat: distinguish not found from other errors when enum is not found * ci: enrich unit-tests to include array indexing and inline structs * feat: license sched example and add collision detection for the base name of produced stripped btfs * feat: add README.md for sched example * fix: typos in sched example README.md
1 parent f57f307 commit 5de6180

File tree

11 files changed

+737
-38
lines changed

11 files changed

+737
-38
lines changed

errors.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,6 @@ var (
4646
ErrMissingSymbolNames = errors.New("missing symbol names")
4747
// ErrUnsupportedWrapType means that the wrap type is not supported.
4848
ErrUnsupportedWrapType = errors.New("unsupported wrap type")
49+
// ErrArrayIndexInvalidField means that the field specified as an array index is invalid.
50+
ErrArrayIndexInvalidField = errors.New("array index invalid field")
4951
)

examples/sched/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
## Example: Sched related symbols
2+
3+
In this example we process all btf files of the btfhub-archive repo to keep only the minimum amount of btf files required to capture all the possible variations, in terms of fetch arg field offsets, of the following two symbols `wake_up_new_task`, `taskstats_exit`. Also, all found btf files are going to get stripped, so they contain only the btf types required of the former three symbols.
4+
5+
#### Prepare [btfhub-archive](https://github.com/aquasecurity/btfhub-archive) repo:
6+
```shell
7+
git clone https://github.com/aquasecurity/btfhub-archive.git
8+
cd btfhub-archive
9+
export BTFHUB_ARCHIVE_REPO=$PWD
10+
find . -iname "*.btf.tar.xz" -exec sh -c 'tar xvf {} -C $(dirname {})' \;
11+
```
12+
13+
#### Run the sched symbols offset extractor:
14+
```shell
15+
go run ./examples/sched/main.go -repo ${BTFHUB_ARCHIVE_REPO}
16+
```

examples/sched/main.go

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
// Licensed to Elasticsearch B.V. under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Elasticsearch B.V. licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package main
19+
20+
import (
21+
"flag"
22+
"io/fs"
23+
"log"
24+
"log/slog"
25+
"os"
26+
"path/filepath"
27+
"strings"
28+
29+
tkbtf "github.com/elastic/tk-btf"
30+
)
31+
32+
func loadWakeUpNewTaskSymbol(symbolMap map[string]*tkbtf.Symbol) {
33+
wakeUpNewTaskSymbol := tkbtf.NewSymbol("wake_up_new_task").AddProbes(
34+
tkbtf.NewKProbe().SetRef("wake_up_new_task").AddFetchArgs(
35+
tkbtf.NewFetchArg("tid", "s32").FuncParamWithName("p", "pid").FuncParamWithName("p", "", "pid"),
36+
tkbtf.NewFetchArg("tgid", "s32").FuncParamWithName("p", "tgid").FuncParamWithName("p", "", "tgid"),
37+
tkbtf.NewFetchArg("ppid", "s32").FuncParamWithName("p", "group_leader", "real_parent", "tgid").FuncParamWithName("p", "", "group_leader", "", "real_parent", "", "tgid"),
38+
tkbtf.NewFetchArg("stime", "u64").
39+
FuncParamWithName("p", "group_leader", "start_time").
40+
FuncParamWithName("p", "", "group_leader", "", "start_time"),
41+
tkbtf.NewFetchArg("pgid", "s32").
42+
FuncParamWithName("p", "group_leader", "pids", "enum:pid_type:PIDTYPE_PGID", "pid", "numbers", "index:0", "nr").
43+
FuncParamWithName("p", "", "group_leader", "", "pids", "enum:pid_type:PIDTYPE_PGID", "pid", "numbers", "index:0", "nr").
44+
FuncParamWithName("p", "group_leader", "signal", "pids", "enum:pid_type:PIDTYPE_PGID", "numbers", "index:0", "nr").
45+
FuncParamWithName("p", "", "group_leader", "", "signal", "pids", "enum:pid_type:PIDTYPE_PGID", "numbers", "index:0", "nr"),
46+
tkbtf.NewFetchArg("sid", "s32").
47+
FuncParamWithName("p", "group_leader", "pids", "enum:pid_type:PIDTYPE_SID", "pid", "numbers", "index:0", "nr").
48+
FuncParamWithName("p", "", "group_leader", "", "pids", "enum:pid_type:PIDTYPE_SID", "pid", "numbers", "index:0", "nr").
49+
FuncParamWithName("p", "group_leader", "signal", "pids", "enum:pid_type:PIDTYPE_SID", "numbers", "index:0", "nr").
50+
FuncParamWithName("p", "", "group_leader", "", "signal", "pids", "enum:pid_type:PIDTYPE_SID", "numbers", "index:0", "nr"),
51+
tkbtf.NewFetchArg("cuid", "u32").
52+
FuncParamWithName("p", "cred", "uid", "val").
53+
FuncParamWithName("p", "", "cred", "uid", "val").
54+
FuncParamWithName("p", "cred", "uid").
55+
FuncParamWithName("p", "", "cred", "uid"),
56+
tkbtf.NewFetchArg("cgid", "u32").
57+
FuncParamWithName("p", "cred", "gid", "val").
58+
FuncParamWithName("p", "", "cred", "gid", "val").
59+
FuncParamWithName("p", "cred", "gid").
60+
FuncParamWithName("p", "", "cred", "gid"),
61+
tkbtf.NewFetchArg("ceuid", "u32").
62+
FuncParamWithName("p", "cred", "euid", "val").
63+
FuncParamWithName("p", "", "cred", "euid", "val").
64+
FuncParamWithName("p", "cred", "euid").
65+
FuncParamWithName("p", "", "cred", "euid"),
66+
tkbtf.NewFetchArg("cegid", "u32").
67+
FuncParamWithName("p", "cred", "egid", "val").
68+
FuncParamWithName("p", "", "cred", "egid", "val").
69+
FuncParamWithName("p", "cred", "egid").
70+
FuncParamWithName("p", "", "cred", "egid"),
71+
tkbtf.NewFetchArg("csuid", "u32").
72+
FuncParamWithName("p", "cred", "suid", "val").
73+
FuncParamWithName("p", "", "cred", "suid", "val").
74+
FuncParamWithName("p", "cred", "suid").
75+
FuncParamWithName("p", "", "cred", "suid"),
76+
tkbtf.NewFetchArg("csgid", "u32").
77+
FuncParamWithName("p", "cred", "sgid", "val").
78+
FuncParamWithName("p", "", "cred", "sgid", "val").
79+
FuncParamWithName("p", "cred", "sgid").
80+
FuncParamWithName("p", "", "cred", "sgid"),
81+
),
82+
)
83+
84+
symbolMap["wake_up_new_task"] = wakeUpNewTaskSymbol
85+
}
86+
87+
func loadTaskStatsExitSymbol(symbolMap map[string]*tkbtf.Symbol) {
88+
taskStatsExitSymbol := tkbtf.NewSymbol("taskstats_exit").AddProbes(
89+
tkbtf.NewKProbe().SetRef("taskstats_exit").AddFetchArgs(
90+
tkbtf.NewFetchArg("tid", "s32").FuncParamWithName("tsk", "pid").FuncParamWithName("tsk", "", "pid"),
91+
tkbtf.NewFetchArg("tgid", "s32").FuncParamWithName("tsk", "tgid").FuncParamWithName("tsk", "", "tgid"),
92+
tkbtf.NewFetchArg("ppid", "s32").FuncParamWithName("tsk", "group_leader", "real_parent", "tgid").FuncParamWithName("tsk", "", "group_leader", "", "real_parent", "", "tgid"),
93+
tkbtf.NewFetchArg("stime", "u64").
94+
FuncParamWithName("tsk", "group_leader", "start_time").
95+
FuncParamWithName("tsk", "", "group_leader", "", "start_time"),
96+
tkbtf.NewFetchArg("pgid", "s32").
97+
FuncParamWithName("tsk", "group_leader", "pids", "enum:pid_type:PIDTYPE_PGID", "pid", "numbers", "index:0", "nr").
98+
FuncParamWithName("tsk", "", "group_leader", "", "pids", "enum:pid_type:PIDTYPE_PGID", "pid", "numbers", "index:0", "nr").
99+
FuncParamWithName("tsk", "group_leader", "signal", "pids", "enum:pid_type:PIDTYPE_PGID", "numbers", "index:0", "nr").
100+
FuncParamWithName("tsk", "", "group_leader", "", "signal", "pids", "enum:pid_type:PIDTYPE_PGID", "numbers", "index:0", "nr"),
101+
tkbtf.NewFetchArg("sid", "s32").
102+
FuncParamWithName("tsk", "group_leader", "pids", "enum:pid_type:PIDTYPE_SID", "pid", "numbers", "index:0", "nr").
103+
FuncParamWithName("tsk", "", "group_leader", "", "pids", "enum:pid_type:PIDTYPE_SID", "pid", "numbers", "index:0", "nr").
104+
FuncParamWithName("tsk", "group_leader", "signal", "pids", "enum:pid_type:PIDTYPE_SID", "numbers", "index:0", "nr").
105+
FuncParamWithName("tsk", "", "group_leader", "", "signal", "pids", "enum:pid_type:PIDTYPE_SID", "numbers", "index:0", "nr"),
106+
tkbtf.NewFetchArg("gd", "s32").FuncParamWithName("group_dead"),
107+
tkbtf.NewFetchArg("cuid", "u32").
108+
FuncParamWithName("tsk", "cred", "uid", "val").
109+
FuncParamWithName("tsk", "", "cred", "uid", "val").
110+
FuncParamWithName("tsk", "cred", "uid").
111+
FuncParamWithName("tsk", "", "cred", "uid"),
112+
tkbtf.NewFetchArg("cgid", "u32").
113+
FuncParamWithName("tsk", "cred", "gid", "val").
114+
FuncParamWithName("tsk", "", "cred", "gid", "val").
115+
FuncParamWithName("tsk", "cred", "gid").
116+
FuncParamWithName("tsk", "", "cred", "gid"),
117+
tkbtf.NewFetchArg("ceuid", "u32").
118+
FuncParamWithName("tsk", "cred", "euid", "val").
119+
FuncParamWithName("tsk", "", "cred", "euid", "val").
120+
FuncParamWithName("tsk", "cred", "euid").
121+
FuncParamWithName("tsk", "", "cred", "euid"),
122+
tkbtf.NewFetchArg("cegid", "u32").
123+
FuncParamWithName("tsk", "cred", "egid", "val").
124+
FuncParamWithName("tsk", "", "cred", "egid", "val").
125+
FuncParamWithName("tsk", "cred", "egid").
126+
FuncParamWithName("tsk", "", "cred", "egid"),
127+
tkbtf.NewFetchArg("csuid", "u32").
128+
FuncParamWithName("tsk", "cred", "suid", "val").
129+
FuncParamWithName("tsk", "", "cred", "suid", "val").
130+
FuncParamWithName("tsk", "cred", "suid").
131+
FuncParamWithName("tsk", "", "cred", "suid"),
132+
tkbtf.NewFetchArg("csgid", "u32").
133+
FuncParamWithName("tsk", "cred", "sgid", "val").
134+
FuncParamWithName("tsk", "", "cred", "sgid", "val").
135+
FuncParamWithName("tsk", "cred", "sgid").
136+
FuncParamWithName("tsk", "", "cred", "sgid"),
137+
),
138+
)
139+
140+
symbolMap["taskstats_exit"] = taskStatsExitSymbol
141+
}
142+
143+
func main() {
144+
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
145+
symbolMap := make(map[string]*tkbtf.Symbol)
146+
147+
var btfHubArchiveRepoPath string
148+
var validate bool
149+
flag.StringVar(&btfHubArchiveRepoPath, "repo", "", "path to the root folder of the btfhub-archive repository")
150+
flag.BoolVar(&validate, "validate", false, "if set, the tkbtf definitions are gonna be rebuilt against each generated stripped btf file")
151+
152+
flag.Parse()
153+
154+
if btfHubArchiveRepoPath == "" {
155+
flag.Usage()
156+
os.Exit(1)
157+
}
158+
159+
loadWakeUpNewTaskSymbol(symbolMap)
160+
loadTaskStatsExitSymbol(symbolMap)
161+
162+
probesTracingMap := make(map[string]struct{})
163+
164+
seenBTFnames := make(map[string]interface{})
165+
strippedBTFsCount := 0
166+
err := filepath.Walk(btfHubArchiveRepoPath, func(path string, info fs.FileInfo, err error) error {
167+
if !strings.HasSuffix(path, ".btf") {
168+
return nil
169+
}
170+
171+
if err != nil {
172+
logger.Warn("error walking path", slog.String("path", path), slog.Any("err", err))
173+
return nil
174+
}
175+
176+
spec, err := tkbtf.NewSpecFromPath(path, nil)
177+
if err != nil {
178+
logger.Warn("error loading spec", slog.String("path", path), slog.Any("err", err))
179+
return nil
180+
}
181+
182+
var symbolsToKeep []*tkbtf.Symbol
183+
var newTracingProbe bool
184+
for symbolName, symbol := range symbolMap {
185+
err = spec.BuildSymbol(symbol)
186+
if err != nil {
187+
logger.Warn("error building symbol", slog.String("path", path), slog.String("symbol", symbolName), slog.Any("err", err))
188+
continue
189+
}
190+
191+
symbolsToKeep = append(symbolsToKeep, symbol)
192+
193+
for _, p := range symbol.GetProbes() {
194+
probeKey := p.GetSymbolName() + p.GetTracingEventProbe() + p.GetTracingEventFilter()
195+
196+
if _, exists := probesTracingMap[probeKey]; !exists {
197+
probesTracingMap[probeKey] = struct{}{}
198+
newTracingProbe = true
199+
}
200+
}
201+
}
202+
203+
if !newTracingProbe {
204+
return nil
205+
}
206+
207+
strippedSpecPath := path + ".sched.stripped"
208+
if err := spec.StripAndSave(strippedSpecPath, symbolsToKeep...); err != nil {
209+
logger.Warn("error stripping spec", slog.String("path", strippedSpecPath), slog.Any("err", err))
210+
return nil
211+
}
212+
logger.Info("produced stripped spec", slog.String("path", strippedSpecPath), slog.Int("count", strippedBTFsCount))
213+
strippedBTFsCount++
214+
215+
strippedSpecBase := filepath.Base(strippedSpecPath)
216+
if _, exists := seenBTFnames[strippedSpecBase]; exists {
217+
logger.Warn("name collision", slog.String("name", strippedSpecBase))
218+
}
219+
seenBTFnames[strippedSpecBase] = struct{}{}
220+
221+
if !validate {
222+
return nil
223+
}
224+
225+
strippedSpec, err := tkbtf.NewSpecFromPath(strippedSpecPath, nil)
226+
if err != nil {
227+
logger.Warn("error loading spec from stripped btf", slog.String("path", strippedSpecPath), slog.Any("err", err))
228+
return nil
229+
}
230+
231+
for symbolName, symbol := range symbolMap {
232+
if err := strippedSpec.BuildSymbol(symbol); err != nil {
233+
logger.Warn("error building symbol", slog.String("path", strippedSpecPath), slog.String("symbol", symbolName), slog.Any("err", err))
234+
continue
235+
}
236+
}
237+
238+
return nil
239+
})
240+
241+
if err != nil {
242+
log.Fatal(err)
243+
}
244+
}

0 commit comments

Comments
 (0)