-
Notifications
You must be signed in to change notification settings - Fork 708
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bpf2go: generate Go types used in global variables
This commit generates Go type declarations for global variables declared in a C BPF program. Some improvements to CollectGlobalTypes were due: - types are now deduplicated by name - types are now selected based on allow-list instead of explicitly rejecting Datasec and Int - the output is sorted by type name - arrays' inner types are now emitted to interact with Variable{Spec} Also added a new btf.QualifiedType(), a subset of btf.UnderlyingType() to remove all qualifiers up to a Typedef, since Typedefs are named, and typically directly point to the anonymous type they alias. Typedefs should only be stripped for evaluating the concrete underlying type, and they should be included when yielding types to the Go renderer. Signed-off-by: Timo Beckers <[email protected]> Co-authored-by: Simone Magnani <[email protected]>
- Loading branch information
1 parent
1e8f079
commit 580ff21
Showing
12 changed files
with
175 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,95 @@ | ||
package gen | ||
|
||
import ( | ||
"cmp" | ||
"slices" | ||
|
||
"github.com/cilium/ebpf" | ||
"github.com/cilium/ebpf/btf" | ||
) | ||
|
||
// CollectGlobalTypes finds all types which are used in the global scope. | ||
// | ||
// This currently includes the types of map keys and values. | ||
// This currently includes the types of variables, map keys and values. | ||
func CollectGlobalTypes(spec *ebpf.CollectionSpec) []btf.Type { | ||
var types []btf.Type | ||
for _, typ := range collectMapTypes(spec.Maps) { | ||
switch btf.UnderlyingType(typ).(type) { | ||
case *btf.Datasec: | ||
// Avoid emitting .rodata, .bss, etc. for now. We might want to | ||
// name these types differently, etc. | ||
continue | ||
|
||
case *btf.Int: | ||
// Don't emit primitive types by default. | ||
continue | ||
} | ||
types = collectMapTypes(types, spec.Maps) | ||
types = collectVariableTypes(types, spec.Variables) | ||
|
||
types = append(types, typ) | ||
} | ||
slices.SortStableFunc(types, func(a, b btf.Type) int { | ||
return cmp.Compare(a.TypeName(), b.TypeName()) | ||
}) | ||
|
||
return types | ||
} | ||
|
||
// collectMapTypes returns a list of all types used as map keys or values. | ||
func collectMapTypes(maps map[string]*ebpf.MapSpec) []btf.Type { | ||
var result []btf.Type | ||
// collectMapTypes collects all types used by MapSpecs. | ||
func collectMapTypes(types []btf.Type, maps map[string]*ebpf.MapSpec) []btf.Type { | ||
for _, m := range maps { | ||
if m.Key != nil && m.Key.TypeName() != "" { | ||
result = append(result, m.Key) | ||
types = addType(types, m.Key) | ||
} | ||
|
||
if m.Value != nil && m.Value.TypeName() != "" { | ||
result = append(result, m.Value) | ||
types = addType(types, m.Value) | ||
} | ||
} | ||
return result | ||
|
||
return types | ||
} | ||
|
||
// collectVariableTypes collects all types used by VariableSpecs. | ||
func collectVariableTypes(types []btf.Type, vars map[string]*ebpf.VariableSpec) []btf.Type { | ||
for _, vs := range vars { | ||
v := vs.Type() | ||
if v == nil { | ||
continue | ||
} | ||
|
||
types = addType(types, v.Type) | ||
} | ||
|
||
return types | ||
} | ||
|
||
// addType adds a type to types if not already present. Types that don't need to | ||
// be generated are not added to types. | ||
func addType(types []btf.Type, incoming btf.Type) []btf.Type { | ||
incoming = selectType(incoming) | ||
if incoming == nil { | ||
return types | ||
} | ||
|
||
// Strip only the qualifiers (not typedefs) from the incoming type. Retain | ||
// typedefs since they carry the name of the anonymous type they point to, | ||
// without which we can't generate a named Go type. | ||
incoming = btf.QualifiedType(incoming) | ||
if incoming.TypeName() == "" { | ||
return types | ||
} | ||
|
||
exists := func(existing btf.Type) bool { | ||
return existing.TypeName() == incoming.TypeName() | ||
} | ||
if !slices.ContainsFunc(types, exists) { | ||
types = append(types, incoming) | ||
} | ||
return types | ||
} | ||
|
||
func selectType(t btf.Type) btf.Type { | ||
// Obtain a concrete type with qualifiers and typedefs stripped. | ||
switch ut := btf.UnderlyingType(t).(type) { | ||
case *btf.Struct, *btf.Union, *btf.Enum: | ||
return t | ||
|
||
// Collect the array's element type. Note: qualifiers on array-type variables | ||
// typically appear after the array, e.g. a const volatile int[4] is actually | ||
// an array of const volatile ints. | ||
case *btf.Array: | ||
return selectType(ut.Type) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Binary file not shown.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters