Skip to content

Commit 2cf61df

Browse files
committed
wip symbol API
Signed-off-by: Simone Magnani <[email protected]>
1 parent f1cefad commit 2cf61df

File tree

8 files changed

+258
-12
lines changed

8 files changed

+258
-12
lines changed

Diff for: 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,

Diff for: 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.

Diff for: 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),

Diff for: collection.go

+80-11
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ import (
1919
//
2020
// Maps and Programs are passed to NewMapWithOptions and NewProgramsWithOptions.
2121
type CollectionOptions struct {
22-
Maps MapOptions
23-
Programs ProgramOptions
22+
Maps MapOptions
23+
Variables VariableOptions
24+
Programs ProgramOptions
2425

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

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

4244
// Types holds type information about Maps and Programs.
4345
// Modifications to Types are currently undefined behaviour.
@@ -56,6 +58,7 @@ func (cs *CollectionSpec) Copy() *CollectionSpec {
5658

5759
cpy := CollectionSpec{
5860
Maps: make(map[string]*MapSpec, len(cs.Maps)),
61+
Variables: make(map[string]*VariableSpec, len(cs.Variables)),
5962
Programs: make(map[string]*ProgramSpec, len(cs.Programs)),
6063
ByteOrder: cs.ByteOrder,
6164
Types: cs.Types.Copy(),
@@ -65,6 +68,10 @@ func (cs *CollectionSpec) Copy() *CollectionSpec {
6568
cpy.Maps[name] = spec.Copy()
6669
}
6770

71+
for name, spec := range cs.Variables {
72+
cpy.Variables[name] = spec.Copy()
73+
}
74+
6875
for name, spec := range cs.Programs {
6976
cpy.Programs[name] = spec.Copy()
7077
}
@@ -286,6 +293,7 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions)
286293

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

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

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

343358
return nil
344359
}
345360

346-
// Collection is a collection of Programs and Maps associated
347-
// with their symbols
361+
// Collection is a collection of Programs and Maps associated with their variables
348362
type Collection struct {
349-
Programs map[string]*Program
350-
Maps map[string]*Map
363+
Programs map[string]*Program
364+
Maps map[string]*Map
365+
Variables map[string]*Variable
351366
}
352367

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

381401
for progName, prog := range spec.Programs {
382402
if prog.Type == UnspecifiedProgram {
@@ -394,20 +414,23 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Co
394414
return nil, err
395415
}
396416

397-
// Prevent loader.cleanup from closing maps and programs.
398-
maps, progs := loader.maps, loader.programs
399-
loader.maps, loader.programs = nil, nil
417+
// Prevent loader.cleanup from closing maps, vars and programs.
418+
maps, vars, progs := loader.maps, loader.vars, loader.programs
419+
loader.maps, loader.vars, loader.programs = nil, nil, nil
400420

401421
return &Collection{
402422
progs,
403423
maps,
424+
vars,
404425
}, nil
405426
}
406427

407428
type collectionLoader struct {
408429
coll *CollectionSpec
409430
opts *CollectionOptions
410431
maps map[string]*Map
432+
vars map[string]*Variable
433+
memory map[string]*MapMemory
411434
programs map[string]*Program
412435
}
413436

@@ -432,6 +455,8 @@ func newCollectionLoader(coll *CollectionSpec, opts *CollectionOptions) (*collec
432455
coll,
433456
opts,
434457
make(map[string]*Map),
458+
make(map[string]*Variable),
459+
make(map[string]*MapMemory),
435460
make(map[string]*Program),
436461
}, nil
437462
}
@@ -446,6 +471,39 @@ func (cl *collectionLoader) close() {
446471
}
447472
}
448473

474+
func (cl *collectionLoader) loadVariable(varName string) (*Variable, error) {
475+
if s := cl.vars[varName]; s != nil {
476+
return s, nil
477+
}
478+
479+
varSpec := cl.coll.Variables[varName]
480+
if varSpec == nil {
481+
return nil, fmt.Errorf("missing variable %s", varName)
482+
}
483+
484+
m := cl.maps[varSpec.MapName]
485+
if m == nil {
486+
return nil, fmt.Errorf("map %s for variable %s not found", varSpec.MapName, varName)
487+
}
488+
489+
if _, ok := cl.memory[varSpec.MapName]; !ok {
490+
// TODO: kernel before mmap support will always fail to load a prog with variables
491+
mm, err := m.Memory()
492+
if err != nil {
493+
return nil, err
494+
}
495+
cl.memory[varSpec.MapName] = mm
496+
}
497+
498+
v, err := newVariableWithOptions(varSpec, cl.memory[varSpec.MapName], cl.opts.Variables)
499+
if err != nil {
500+
return nil, fmt.Errorf("variable %v: %w", varName, err)
501+
}
502+
503+
cl.vars[varName] = v
504+
return v, nil
505+
}
506+
449507
func (cl *collectionLoader) loadMap(mapName string) (*Map, error) {
450508
if m := cl.maps[mapName]; m != nil {
451509
return m, nil
@@ -723,6 +781,7 @@ func LoadCollection(file string) (*Collection, error) {
723781
// for any successful assigns. On error `to` is left in an undefined state.
724782
func (coll *Collection) Assign(to interface{}) error {
725783
assignedMaps := make(map[string]bool)
784+
assignedVars := make(map[string]bool)
726785
assignedProgs := make(map[string]bool)
727786

728787
// Assign() only transfers already-loaded Maps and Programs. No extra
@@ -744,6 +803,13 @@ func (coll *Collection) Assign(to interface{}) error {
744803
}
745804
return nil, fmt.Errorf("missing map %q", name)
746805

806+
case reflect.TypeOf((*Variable)(nil)):
807+
if v := coll.Variables[name]; v != nil {
808+
assignedVars[name] = true
809+
return v, nil
810+
}
811+
return nil, fmt.Errorf("missing variable %q", name)
812+
747813
default:
748814
return nil, fmt.Errorf("unsupported type %s", typ)
749815
}
@@ -757,6 +823,9 @@ func (coll *Collection) Assign(to interface{}) error {
757823
for p := range assignedProgs {
758824
delete(coll.Programs, p)
759825
}
826+
for s := range assignedVars {
827+
delete(coll.Variables, s)
828+
}
760829
for m := range assignedMaps {
761830
delete(coll.Maps, m)
762831
}

Diff for: 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)