Skip to content

Commit

Permalink
btf: handle signed enums and fix default signedness
Browse files Browse the repository at this point in the history
Enums now carry signedness encoded in the KindFlag, with the default being
an unsigned enum. This breaks our assumption that enums are signed by default.

Add Enum.Signed and switch EnumValue.Value to uint64. I used uint64 instead of
uint32 since we'll likely need 64 bits to support BTF_KIND_ENUM64 in the future.

Users of bpf2go that generated enums will see their generated types changing from
signed to unsigned types.

Updates #780
  • Loading branch information
lmb committed Sep 5, 2022
1 parent 10b55a9 commit e8a7a73
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 32 deletions.
2 changes: 1 addition & 1 deletion btf/btf_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ type btfVariable struct {

type btfEnum struct {
NameOff uint32
Val int32
Val uint32
}

type btfParam struct {
Expand Down
2 changes: 1 addition & 1 deletion btf/core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ func TestCOREFindEnumValue(t *testing.T) {
name string
local, target Type
acc coreAccessor
localValue, targetValue int32
localValue, targetValue uint64
}{
{"a to b", a, b, coreAccessor{0}, 23, 0},
{"b to a", b, a, coreAccessor{1}, 123, 42},
Expand Down
3 changes: 3 additions & 0 deletions btf/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ func (gf *GoFormatter) writeTypeLit(typ Type, depth int) error {
gf.writeIntLit(v)

case *Enum:
if !v.Signed {
gf.w.WriteRune('u')
}
switch v.Size {
case 1:
gf.w.WriteString("int8")
Expand Down
16 changes: 8 additions & 8 deletions btf/format_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ func TestGoTypeDeclaration(t *testing.T) {
{&Int{Size: 8}, "type t uint64"},
{&Typedef{Name: "frob", Type: &Int{Size: 8}}, "type t uint64"},
{&Int{Size: 16}, "type t uint128"},
{&Enum{Values: []EnumValue{{"FOO", 32}}, Size: 4}, "type t int32; const ( tFOO t = 32; )"},
{&Enum{Values: []EnumValue{{"BAR", 1}}, Size: 1}, "type t int8; const ( tBAR t = 1; )"},
{&Enum{Values: []EnumValue{{"FOO", 32}}, Size: 4}, "type t uint32; const ( tFOO t = 32; )"},
{&Enum{Values: []EnumValue{{"BAR", 1}}, Size: 1, Signed: true}, "type t int8; const ( tBAR t = 1; )"},
{
&Struct{
Name: "enum literals",
Size: 1,
Size: 2,
Members: []Member{
{Name: "enum", Type: &Enum{Values: []EnumValue{{"BAR", 1}}, Size: 1}, Offset: 0},
{Name: "enum", Type: &Enum{Values: []EnumValue{{"BAR", 1}}, Size: 2}, Offset: 0},
},
},
"type t struct { enum int8; }",
"type t struct { enum uint16; }",
},
{&Array{Nelems: 2, Type: &Int{Size: 1}}, "type t [2]uint8"},
{
Expand Down Expand Up @@ -165,12 +165,12 @@ func TestGoTypeDeclarationNamed(t *testing.T) {
named []Type
output string
}{
{e1, []Type{e1}, "type t int32"},
{e1, []Type{e1}, "type t uint32"},
{s1, []Type{e1, s1}, "type t struct { frob E1; }"},
{s2, []Type{e1}, "type t struct { frood struct { frob E1; }; }"},
{s2, []Type{e1, s1}, "type t struct { frood S1; }"},
{td, nil, "type t int32"},
{td, []Type{td}, "type t int32"},
{td, nil, "type t uint32"},
{td, []Type{td}, "type t uint32"},
{arr, []Type{td}, "type t [1]TD"},
}

Expand Down
19 changes: 12 additions & 7 deletions btf/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,9 @@ type Member struct {
type Enum struct {
Name string
// Size of the enum value in bytes.
Size uint32
Size uint32
// True if the values should be interpreted as signed integers.
Signed bool
Values []EnumValue
}

Expand All @@ -288,7 +290,7 @@ func (e *Enum) TypeName() string { return e.Name }
// Is is not a valid Type
type EnumValue struct {
Name string
Value int32
Value uint64
}

func (e *Enum) size() uint32 { return e.Size }
Expand Down Expand Up @@ -993,17 +995,20 @@ func inflateRawTypes(rawTypes []rawType, baseTypes types, rawStrings *stringTabl
case kindEnum:
rawvals := raw.data.([]btfEnum)
vals := make([]EnumValue, 0, len(rawvals))
signed := raw.KindFlag()
for i, btfVal := range rawvals {
name, err := rawStrings.Lookup(btfVal.NameOff)
if err != nil {
return nil, fmt.Errorf("get name for enum value %d: %s", i, err)
}
vals = append(vals, EnumValue{
Name: name,
Value: btfVal.Val,
})
value := uint64(btfVal.Val)
if signed {
// Sign extend values to 64 bit.
value = uint64(int32(btfVal.Val))
}
vals = append(vals, EnumValue{name, value})
}
typ = &Enum{name, raw.Size(), vals}
typ = &Enum{name, raw.Size(), signed, vals}

case kindForward:
if raw.KindFlag() {
Expand Down
2 changes: 1 addition & 1 deletion cmd/bpf2go/test/test_bpfeb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cmd/bpf2go/test/test_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 13 additions & 13 deletions internal/sys/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e8a7a73

Please sign in to comment.