Skip to content

Commit 521eecf

Browse files
committed
symbol API implementation for interacting with static/global vars [test missing]
Signed-off-by: Simone Magnani <[email protected]>
1 parent da7a3b8 commit 521eecf

File tree

7 files changed

+402
-12
lines changed

7 files changed

+402
-12
lines changed

cmd/bpf2go/gen/output.go

+17
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ func (n templateName) MapSpecs() string {
4949
return string(n) + "MapSpecs"
5050
}
5151

52+
func (n templateName) VariableSpecs() string {
53+
return string(n) + "VariableSpecs"
54+
}
55+
5256
func (n templateName) Load() string {
5357
return n.maybeExport("load" + toUpperFirst(string(n)))
5458
}
@@ -65,6 +69,10 @@ func (n templateName) Maps() string {
6569
return string(n) + "Maps"
6670
}
6771

72+
func (n templateName) Variables() string {
73+
return string(n) + "Variables"
74+
}
75+
6876
func (n templateName) Programs() string {
6977
return string(n) + "Programs"
7078
}
@@ -82,6 +90,8 @@ type GenerateArgs struct {
8290
Constraints constraint.Expr
8391
// Maps to be emitted.
8492
Maps []string
93+
// Variables to be emitted.
94+
Variables []string
8595
// Programs to be emitted.
8696
Programs []string
8797
// Types to be emitted.
@@ -116,6 +126,11 @@ func Generate(args GenerateArgs) error {
116126
maps[name] = internal.Identifier(name)
117127
}
118128

129+
vars := make(map[string]string)
130+
for _, name := range args.Variables {
131+
vars[name] = internal.Identifier(name)
132+
}
133+
119134
programs := make(map[string]string)
120135
for _, name := range args.Programs {
121136
programs[name] = internal.Identifier(name)
@@ -146,6 +161,7 @@ func Generate(args GenerateArgs) error {
146161
Constraints constraint.Expr
147162
Name templateName
148163
Maps map[string]string
164+
Variables map[string]string
149165
Programs map[string]string
150166
Types []btf.Type
151167
TypeNames map[btf.Type]string
@@ -157,6 +173,7 @@ func Generate(args GenerateArgs) error {
157173
args.Constraints,
158174
templateName(args.Stem),
159175
maps,
176+
vars,
160177
programs,
161178
types,
162179
typeNames,

cmd/bpf2go/gen/output.tpl

+29
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ func {{ .Name.LoadObjects }}(obj interface{}, opts *ebpf.CollectionOptions) (err
5454
type {{ .Name.Specs }} struct {
5555
{{ .Name.ProgramSpecs }}
5656
{{ .Name.MapSpecs }}
57+
{{ .Name.VariableSpecs }}
5758
}
5859

5960
// {{ .Name.Specs }} contains programs before they are loaded into the kernel.
@@ -80,12 +81,14 @@ type {{ .Name.MapSpecs }} struct {
8081
type {{ .Name.Objects }} struct {
8182
{{ .Name.Programs }}
8283
{{ .Name.Maps }}
84+
{{ .Name.Variables }}
8385
}
8486

8587
func (o *{{ .Name.Objects }}) Close() error {
8688
return {{ .Name.CloseHelper }}(
8789
&o.{{ .Name.Programs }},
8890
&o.{{ .Name.Maps }},
91+
&o.{{ .Name.Variables }},
8992
)
9093
}
9194

@@ -106,6 +109,32 @@ func (m *{{ .Name.Maps }}) Close() error {
106109
)
107110
}
108111

112+
// {{ .Name.VariableSpecs }} contains variables before they are loaded into the kernel.
113+
//
114+
// It can be passed ebpf.CollectionSpec.Assign.
115+
type {{ .Name.VariableSpecs }} struct {
116+
{{- range $name, $id := .Variables }}
117+
{{ $id }} *ebpf.VariableSpec `ebpf:"{{ $name }}"`
118+
{{- end }}
119+
}
120+
121+
// {{ .Name.Variables }} contains all variables after they have been loaded into the kernel.
122+
//
123+
// It can be passed to {{ .Name.LoadObjects }} or ebpf.CollectionSpec.LoadAndAssign.
124+
type {{ .Name.Variables }} struct {
125+
{{- range $name, $id := .Variables }}
126+
{{ $id }} *ebpf.Variable `ebpf:"{{ $name }}"`
127+
{{- end }}
128+
}
129+
130+
func (m *{{ .Name.Variables }}) Close() error {
131+
return {{ .Name.CloseHelper }}(
132+
{{- range $id := .Variables }}
133+
m.{{ $id }},
134+
{{- end }}
135+
)
136+
}
137+
109138
// {{ .Name.Programs }} contains all programs after they have been loaded into the kernel.
110139
//
111140
// It can be passed to {{ .Name.LoadObjects }} or ebpf.CollectionSpec.LoadAndAssign.

cmd/bpf2go/main.go

+6
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,11 @@ func (b2g *bpf2go) convert(tgt gen.Target, goarches gen.GoArches) (err error) {
370370
}
371371
}
372372

373+
var vars []string
374+
for name := range spec.Variables {
375+
vars = append(vars, name)
376+
}
377+
373378
var programs []string
374379
for name := range spec.Programs {
375380
programs = append(programs, name)
@@ -397,6 +402,7 @@ func (b2g *bpf2go) convert(tgt gen.Target, goarches gen.GoArches) (err error) {
397402
Stem: b2g.identStem,
398403
Constraints: constraints,
399404
Maps: maps,
405+
Variables: vars,
400406
Programs: programs,
401407
Types: types,
402408
ObjectFile: filepath.Base(objFileName),

collection.go

+74-11
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ import (
1818
//
1919
// Maps and Programs are passed to NewMapWithOptions and NewProgramsWithOptions.
2020
type CollectionOptions struct {
21-
Maps MapOptions
22-
Programs ProgramOptions
21+
Maps MapOptions
22+
Variables VariableOptions
23+
Programs ProgramOptions
2324

2425
// MapReplacements takes a set of Maps that will be used instead of
2526
// creating new ones when loading the CollectionSpec.
@@ -35,8 +36,9 @@ type CollectionOptions struct {
3536

3637
// CollectionSpec describes a collection.
3738
type CollectionSpec struct {
38-
Maps map[string]*MapSpec
39-
Programs map[string]*ProgramSpec
39+
Maps map[string]*MapSpec
40+
Variables map[string]*VariableSpec
41+
Programs map[string]*ProgramSpec
4042

4143
// Types holds type information about Maps and Programs.
4244
// Modifications to Types are currently undefined behaviour.
@@ -55,6 +57,7 @@ func (cs *CollectionSpec) Copy() *CollectionSpec {
5557

5658
cpy := CollectionSpec{
5759
Maps: make(map[string]*MapSpec, len(cs.Maps)),
60+
Variables: make(map[string]*VariableSpec, len(cs.Variables)),
5861
Programs: make(map[string]*ProgramSpec, len(cs.Programs)),
5962
ByteOrder: cs.ByteOrder,
6063
Types: cs.Types.Copy(),
@@ -64,6 +67,10 @@ func (cs *CollectionSpec) Copy() *CollectionSpec {
6467
cpy.Maps[name] = spec.Copy()
6568
}
6669

70+
for name, spec := range cs.Variables {
71+
cpy.Variables[name] = spec.Copy()
72+
}
73+
6774
for name, spec := range cs.Programs {
6875
cpy.Programs[name] = spec.Copy()
6976
}
@@ -285,6 +292,7 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions)
285292

286293
// Support assigning Programs and Maps, lazy-loading the required objects.
287294
assignedMaps := make(map[string]bool)
295+
assignedVars := make(map[string]bool)
288296
assignedProgs := make(map[string]bool)
289297

290298
getValue := func(typ reflect.Type, name string) (interface{}, error) {
@@ -298,6 +306,10 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions)
298306
assignedMaps[name] = true
299307
return loader.loadMap(name)
300308

309+
case reflect.TypeOf((*Variable)(nil)):
310+
assignedVars[name] = true
311+
return loader.loadVariable(name)
312+
301313
default:
302314
return nil, fmt.Errorf("unsupported type %s", typ)
303315
}
@@ -335,18 +347,21 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions)
335347
for m := range assignedMaps {
336348
delete(loader.maps, m)
337349
}
350+
for v := range assignedVars {
351+
delete(loader.vars, v)
352+
}
338353
for p := range assignedProgs {
339354
delete(loader.programs, p)
340355
}
341356

342357
return nil
343358
}
344359

345-
// Collection is a collection of Programs and Maps associated
346-
// with their symbols
360+
// Collection is a collection of Programs and Maps associated with their varaibles
347361
type Collection struct {
348-
Programs map[string]*Program
349-
Maps map[string]*Map
362+
Programs map[string]*Program
363+
Maps map[string]*Map
364+
Variables map[string]*Variable
350365
}
351366

352367
// NewCollection creates a Collection from the given spec, creating and
@@ -376,6 +391,11 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Co
376391
return nil, err
377392
}
378393
}
394+
for varName := range spec.Variables {
395+
if _, err := loader.loadVariable(varName); err != nil {
396+
return nil, err
397+
}
398+
}
379399

380400
for progName, prog := range spec.Programs {
381401
if prog.Type == UnspecifiedProgram {
@@ -393,20 +413,22 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Co
393413
return nil, err
394414
}
395415

396-
// Prevent loader.cleanup from closing maps and programs.
397-
maps, progs := loader.maps, loader.programs
398-
loader.maps, loader.programs = nil, nil
416+
// Prevent loader.cleanup from closing maps, vars and programs.
417+
maps, vars, progs := loader.maps, loader.vars, loader.programs
418+
loader.maps, loader.vars, loader.programs = nil, nil, nil
399419

400420
return &Collection{
401421
progs,
402422
maps,
423+
vars,
403424
}, nil
404425
}
405426

406427
type collectionLoader struct {
407428
coll *CollectionSpec
408429
opts *CollectionOptions
409430
maps map[string]*Map
431+
vars map[string]*Variable
410432
programs map[string]*Program
411433
}
412434

@@ -431,6 +453,7 @@ func newCollectionLoader(coll *CollectionSpec, opts *CollectionOptions) (*collec
431453
coll,
432454
opts,
433455
make(map[string]*Map),
456+
make(map[string]*Variable),
434457
make(map[string]*Program),
435458
}, nil
436459
}
@@ -445,6 +468,35 @@ func (cl *collectionLoader) close() {
445468
}
446469
}
447470

471+
func (cl *collectionLoader) loadVariable(varName string) (*Variable, error) {
472+
if s := cl.vars[varName]; s != nil {
473+
return s, nil
474+
}
475+
476+
varSpec := cl.coll.Variables[varName]
477+
if varSpec == nil {
478+
return nil, fmt.Errorf("missing variable %s", varName)
479+
}
480+
481+
m := cl.maps[varSpec.MapName]
482+
if m == nil {
483+
return nil, fmt.Errorf("map %s for variable %s not found", varSpec.MapName, varName)
484+
}
485+
486+
mc, err := m.Clone()
487+
if err != nil {
488+
return nil, err
489+
}
490+
491+
v, err := newVariableWithOptions(varSpec, mc, cl.opts.Variables)
492+
if err != nil {
493+
return nil, fmt.Errorf("variable %v: %w", varName, err)
494+
}
495+
496+
cl.vars[varName] = v
497+
return v, nil
498+
}
499+
448500
func (cl *collectionLoader) loadMap(mapName string) (*Map, error) {
449501
if m := cl.maps[mapName]; m != nil {
450502
return m, nil
@@ -722,6 +774,7 @@ func LoadCollection(file string) (*Collection, error) {
722774
// for any successful assigns. On error `to` is left in an undefined state.
723775
func (coll *Collection) Assign(to interface{}) error {
724776
assignedMaps := make(map[string]bool)
777+
assignedVars := make(map[string]bool)
725778
assignedProgs := make(map[string]bool)
726779

727780
// Assign() only transfers already-loaded Maps and Programs. No extra
@@ -743,6 +796,13 @@ func (coll *Collection) Assign(to interface{}) error {
743796
}
744797
return nil, fmt.Errorf("missing map %q", name)
745798

799+
case reflect.TypeOf((*Variable)(nil)):
800+
if v := coll.Variables[name]; v != nil {
801+
assignedVars[name] = true
802+
return v, nil
803+
}
804+
return nil, fmt.Errorf("missing variable %q", name)
805+
746806
default:
747807
return nil, fmt.Errorf("unsupported type %s", typ)
748808
}
@@ -756,6 +816,9 @@ func (coll *Collection) Assign(to interface{}) error {
756816
for p := range assignedProgs {
757817
delete(coll.Programs, p)
758818
}
819+
for s := range assignedVars {
820+
delete(coll.Variables, s)
821+
}
759822
for m := range assignedMaps {
760823
delete(coll.Maps, m)
761824
}

collection_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ func TestCollectionSpecCopy(t *testing.T) {
6666
MaxEntries: 1,
6767
},
6868
},
69+
map[string]*VariableSpec{
70+
"test": {
71+
Name: "test",
72+
MapName: ".rodata",
73+
Offset: 0,
74+
Size: 4,
75+
},
76+
},
6977
map[string]*ProgramSpec{
7078
"test": {
7179
Type: SocketFilter,

0 commit comments

Comments
 (0)