Skip to content

Commit 094ddd7

Browse files
committed
feat(bpf2go): Export go binding generation
Moves the code to generate go bindings to its own dedicated package and export the necessary functions to use it in bpf2go. This change will make it possible to reuse this code in other tools, without having to compile the C programs. The behaviour of bpf2go is unchanged. Two additional changes were made: 1. The 'Module' parameter has been made an input to the code generation. Otherwise embedding the bindings package in another module would lead to incorrect import statements in the generated code. I fail to see the value of the 'debug' lookup, the only valid value is "github.com/cilium/ebpf", but maybe there are some cilium internal build constraints, so I left it configurable. 2. The function which transforms type names to go identifiers has been updated to deal with all caps names. These shouldn't be present in C code, but appear when using rust. The change ensures the field names in the bindings are idiomatic Go field names. Signed-off-by: Wouter Dullaert <[email protected]>
1 parent b8dc0ee commit 094ddd7

File tree

7 files changed

+59
-47
lines changed

7 files changed

+59
-47
lines changed

cmd/bpf2go/output.go renamed to bindings/output.go

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package main
1+
package bindings
22

33
import (
44
"bytes"
@@ -71,38 +71,43 @@ func (n templateName) CloseHelper() string {
7171
return "_" + toUpperFirst(string(n)) + "Close"
7272
}
7373

74-
type outputArgs struct {
74+
type GenerateArgs struct {
75+
// The package containing the go ebpf code. "github.com/cilium/ebpf" if left empty
76+
Module string
7577
// Package of the resulting file.
76-
pkg string
78+
Pkg string
7779
// The prefix of all names declared at the top-level.
78-
stem string
79-
// Build constraints included in the resulting file.
80-
constraints constraint.Expr
80+
Stem string
81+
// Build Constraints included in the resulting file.
82+
Constraints constraint.Expr
8183
// Maps to be emitted.
82-
maps []string
84+
Maps []string
8385
// Programs to be emitted.
84-
programs []string
86+
Programs []string
8587
// Types to be emitted.
86-
types []btf.Type
88+
Types []btf.Type
8789
// Filename of the ELF object to embed.
88-
obj string
89-
out io.Writer
90+
Obj string
91+
Out io.Writer
9092
}
9193

92-
func output(args outputArgs) error {
94+
func Generate(args GenerateArgs) error {
95+
if args.Module == "" {
96+
args.Module = "github.com/cilium/ebpf"
97+
}
9398
maps := make(map[string]string)
94-
for _, name := range args.maps {
99+
for _, name := range args.Maps {
95100
maps[name] = internal.Identifier(name)
96101
}
97102

98103
programs := make(map[string]string)
99-
for _, name := range args.programs {
104+
for _, name := range args.Programs {
100105
programs[name] = internal.Identifier(name)
101106
}
102107

103108
typeNames := make(map[btf.Type]string)
104-
for _, typ := range args.types {
105-
typeNames[typ] = args.stem + internal.Identifier(typ.TypeName())
109+
for _, typ := range args.Types {
110+
typeNames[typ] = args.Stem + internal.Identifier(typ.TypeName())
106111
}
107112

108113
// Ensure we don't have conflicting names and generate a sorted list of
@@ -112,8 +117,6 @@ func output(args outputArgs) error {
112117
return err
113118
}
114119

115-
module := currentModule()
116-
117120
gf := &btf.GoFormatter{
118121
Names: typeNames,
119122
Identifier: internal.Identifier,
@@ -132,26 +135,26 @@ func output(args outputArgs) error {
132135
File string
133136
}{
134137
gf,
135-
module,
136-
args.pkg,
137-
args.constraints,
138-
templateName(args.stem),
138+
args.Module,
139+
args.Pkg,
140+
args.Constraints,
141+
templateName(args.Stem),
139142
maps,
140143
programs,
141144
types,
142145
typeNames,
143-
args.obj,
146+
args.Obj,
144147
}
145148

146149
var buf bytes.Buffer
147150
if err := commonTemplate.Execute(&buf, &ctx); err != nil {
148151
return fmt.Errorf("can't generate types: %s", err)
149152
}
150153

151-
return internal.WriteFormatted(buf.Bytes(), args.out)
154+
return internal.WriteFormatted(buf.Bytes(), args.Out)
152155
}
153156

154-
func collectFromSpec(spec *ebpf.CollectionSpec, cTypes []string, skipGlobalTypes bool) (maps, programs []string, types []btf.Type, _ error) {
157+
func CollectFromSpec(spec *ebpf.CollectionSpec, cTypes []string, skipGlobalTypes bool) (maps, programs []string, types []btf.Type, _ error) {
155158
for name := range spec.Maps {
156159
// Skip .rodata, .data, .bss, etc. sections
157160
if !strings.HasPrefix(name, ".") {
File renamed without changes.

cmd/bpf2go/output_test.go renamed to bindings/output_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package main
1+
package bindings
22

33
import (
44
"testing"
@@ -75,21 +75,21 @@ func TestCollectFromSpec(t *testing.T) {
7575

7676
map1 := spec.Maps["map1"]
7777

78-
maps, programs, types, err := collectFromSpec(spec, nil, false)
78+
maps, programs, types, err := CollectFromSpec(spec, nil, false)
7979
if err != nil {
8080
t.Fatal(err)
8181
}
8282
qt.Assert(t, qt.ContentEquals(maps, []string{"map1"}))
8383
qt.Assert(t, qt.ContentEquals(programs, []string{"filter"}))
8484
qt.Assert(t, qt.CmpEquals(types, []btf.Type{map1.Key, map1.Value}, typesEqualComparer))
8585

86-
_, _, types, err = collectFromSpec(spec, nil, true)
86+
_, _, types, err = CollectFromSpec(spec, nil, true)
8787
if err != nil {
8888
t.Fatal(err)
8989
}
9090
qt.Assert(t, qt.CmpEquals[[]btf.Type](types, nil, typesEqualComparer))
9191

92-
_, _, types, err = collectFromSpec(spec, []string{"barfoo"}, true)
92+
_, _, types, err = CollectFromSpec(spec, []string{"barfoo"}, true)
9393
if err != nil {
9494
t.Fatal(err)
9595
}

bindings/tools.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package bindings
2+
3+
import (
4+
"unicode"
5+
"unicode/utf8"
6+
)
7+
8+
func toUpperFirst(str string) string {
9+
first, n := utf8.DecodeRuneInString(str)
10+
return string(unicode.ToUpper(first)) + str[n:]
11+
}

cmd/bpf2go/main.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"strings"
1919

2020
"github.com/cilium/ebpf"
21+
"github.com/cilium/ebpf/bindings"
2122
)
2223

2324
const helpText = `Usage: %[1]s [options] <ident> <source file> [-- <C flags>]
@@ -389,7 +390,7 @@ func (b2g *bpf2go) convert(tgt target, goarches []goarch) (err error) {
389390
return fmt.Errorf("can't load BPF from ELF: %s", err)
390391
}
391392

392-
maps, programs, types, err := collectFromSpec(spec, b2g.cTypes, b2g.skipGlobalTypes)
393+
maps, programs, types, err := bindings.CollectFromSpec(spec, b2g.cTypes, b2g.skipGlobalTypes)
393394
if err != nil {
394395
return err
395396
}
@@ -402,15 +403,16 @@ func (b2g *bpf2go) convert(tgt target, goarches []goarch) (err error) {
402403
}
403404
defer removeOnError(goFile)
404405

405-
err = output(outputArgs{
406-
pkg: b2g.pkg,
407-
stem: b2g.identStem,
408-
constraints: constraints,
409-
maps: maps,
410-
programs: programs,
411-
types: types,
412-
obj: filepath.Base(objFileName),
413-
out: goFile,
406+
err = bindings.Generate(bindings.GenerateArgs{
407+
Module: currentModule(),
408+
Pkg: b2g.pkg,
409+
Stem: b2g.identStem,
410+
Constraints: constraints,
411+
Maps: maps,
412+
Programs: programs,
413+
Types: types,
414+
Obj: filepath.Base(objFileName),
415+
Out: goFile,
414416
})
415417
if err != nil {
416418
return fmt.Errorf("can't write %s: %s", goFileName, err)

cmd/bpf2go/tools.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import (
55
"fmt"
66
"runtime/debug"
77
"strings"
8-
"unicode"
9-
"unicode/utf8"
108
)
119

1210
func splitCFlagsFromArgs(in []string) (args, cflags []string) {
@@ -78,11 +76,6 @@ func splitArguments(in string) ([]string, error) {
7876
return result, nil
7977
}
8078

81-
func toUpperFirst(str string) string {
82-
first, n := utf8.DecodeRuneInString(str)
83-
return string(unicode.ToUpper(first)) + str[n:]
84-
}
85-
8679
func currentModule() string {
8780
bi, ok := debug.ReadBuildInfo()
8881
if !ok {

internal/output.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ func Identifier(str string) string {
1818
// See https://golang.org/ref/spec#Identifiers
1919
switch {
2020
case unicode.IsLetter(r):
21-
if prev == -1 {
21+
switch {
22+
case prev == -1:
2223
r = unicode.ToUpper(r)
24+
case unicode.IsUpper(r):
25+
r = unicode.ToLower(r)
2326
}
2427

2528
case r == '_':

0 commit comments

Comments
 (0)