summaryrefslogtreecommitdiff
path: root/vendor/github.com/cilium/ebpf/btf/format.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/cilium/ebpf/btf/format.go')
-rw-r--r--vendor/github.com/cilium/ebpf/btf/format.go319
1 files changed, 0 insertions, 319 deletions
diff --git a/vendor/github.com/cilium/ebpf/btf/format.go b/vendor/github.com/cilium/ebpf/btf/format.go
deleted file mode 100644
index e7688a2a6..000000000
--- a/vendor/github.com/cilium/ebpf/btf/format.go
+++ /dev/null
@@ -1,319 +0,0 @@
-package btf
-
-import (
- "errors"
- "fmt"
- "strings"
-)
-
-var errNestedTooDeep = errors.New("nested too deep")
-
-// GoFormatter converts a Type to Go syntax.
-//
-// A zero GoFormatter is valid to use.
-type GoFormatter struct {
- w strings.Builder
-
- // Types present in this map are referred to using the given name if they
- // are encountered when outputting another type.
- Names map[Type]string
-
- // Identifier is called for each field of struct-like types. By default the
- // field name is used as is.
- Identifier func(string) string
-
- // EnumIdentifier is called for each element of an enum. By default the
- // name of the enum type is concatenated with Identifier(element).
- EnumIdentifier func(name, element string) string
-}
-
-// TypeDeclaration generates a Go type declaration for a BTF type.
-func (gf *GoFormatter) TypeDeclaration(name string, typ Type) (string, error) {
- gf.w.Reset()
- if err := gf.writeTypeDecl(name, typ); err != nil {
- return "", err
- }
- return gf.w.String(), nil
-}
-
-func (gf *GoFormatter) identifier(s string) string {
- if gf.Identifier != nil {
- return gf.Identifier(s)
- }
-
- return s
-}
-
-func (gf *GoFormatter) enumIdentifier(name, element string) string {
- if gf.EnumIdentifier != nil {
- return gf.EnumIdentifier(name, element)
- }
-
- return name + gf.identifier(element)
-}
-
-// writeTypeDecl outputs a declaration of the given type.
-//
-// It encodes https://golang.org/ref/spec#Type_declarations:
-//
-// type foo struct { bar uint32; }
-// type bar int32
-func (gf *GoFormatter) writeTypeDecl(name string, typ Type) error {
- if name == "" {
- return fmt.Errorf("need a name for type %s", typ)
- }
-
- switch v := skipQualifiers(typ).(type) {
- case *Enum:
- fmt.Fprintf(&gf.w, "type %s ", name)
- switch v.Size {
- case 1:
- gf.w.WriteString("int8")
- case 2:
- gf.w.WriteString("int16")
- case 4:
- gf.w.WriteString("int32")
- case 8:
- gf.w.WriteString("int64")
- default:
- return fmt.Errorf("%s: invalid enum size %d", typ, v.Size)
- }
-
- if len(v.Values) == 0 {
- return nil
- }
-
- gf.w.WriteString("; const ( ")
- for _, ev := range v.Values {
- id := gf.enumIdentifier(name, ev.Name)
- fmt.Fprintf(&gf.w, "%s %s = %d; ", id, name, ev.Value)
- }
- gf.w.WriteString(")")
-
- return nil
-
- default:
- fmt.Fprintf(&gf.w, "type %s ", name)
- return gf.writeTypeLit(v, 0)
- }
-}
-
-// writeType outputs the name of a named type or a literal describing the type.
-//
-// It encodes https://golang.org/ref/spec#Types.
-//
-// foo (if foo is a named type)
-// uint32
-func (gf *GoFormatter) writeType(typ Type, depth int) error {
- typ = skipQualifiers(typ)
-
- name := gf.Names[typ]
- if name != "" {
- gf.w.WriteString(name)
- return nil
- }
-
- return gf.writeTypeLit(typ, depth)
-}
-
-// writeTypeLit outputs a literal describing the type.
-//
-// The function ignores named types.
-//
-// It encodes https://golang.org/ref/spec#TypeLit.
-//
-// struct { bar uint32; }
-// uint32
-func (gf *GoFormatter) writeTypeLit(typ Type, depth int) error {
- depth++
- if depth > maxTypeDepth {
- return errNestedTooDeep
- }
-
- var err error
- switch v := skipQualifiers(typ).(type) {
- case *Int:
- gf.writeIntLit(v)
-
- case *Enum:
- gf.w.WriteString("int32")
-
- case *Typedef:
- err = gf.writeType(v.Type, depth)
-
- case *Array:
- fmt.Fprintf(&gf.w, "[%d]", v.Nelems)
- err = gf.writeType(v.Type, depth)
-
- case *Struct:
- err = gf.writeStructLit(v.Size, v.Members, depth)
-
- case *Union:
- // Always choose the first member to represent the union in Go.
- err = gf.writeStructLit(v.Size, v.Members[:1], depth)
-
- case *Datasec:
- err = gf.writeDatasecLit(v, depth)
-
- default:
- return fmt.Errorf("type %T: %w", v, ErrNotSupported)
- }
-
- if err != nil {
- return fmt.Errorf("%s: %w", typ, err)
- }
-
- return nil
-}
-
-func (gf *GoFormatter) writeIntLit(i *Int) {
- // NB: Encoding.IsChar is ignored.
- if i.Encoding.IsBool() && i.Size == 1 {
- gf.w.WriteString("bool")
- return
- }
-
- bits := i.Size * 8
- if i.Encoding.IsSigned() {
- fmt.Fprintf(&gf.w, "int%d", bits)
- } else {
- fmt.Fprintf(&gf.w, "uint%d", bits)
- }
-}
-
-func (gf *GoFormatter) writeStructLit(size uint32, members []Member, depth int) error {
- gf.w.WriteString("struct { ")
-
- prevOffset := uint32(0)
- skippedBitfield := false
- for i, m := range members {
- if m.BitfieldSize > 0 {
- skippedBitfield = true
- continue
- }
-
- offset := m.Offset.Bytes()
- if n := offset - prevOffset; skippedBitfield && n > 0 {
- fmt.Fprintf(&gf.w, "_ [%d]byte /* unsupported bitfield */; ", n)
- } else {
- gf.writePadding(n)
- }
-
- size, err := Sizeof(m.Type)
- if err != nil {
- return fmt.Errorf("field %d: %w", i, err)
- }
- prevOffset = offset + uint32(size)
-
- if err := gf.writeStructField(m, depth); err != nil {
- return fmt.Errorf("field %d: %w", i, err)
- }
- }
-
- gf.writePadding(size - prevOffset)
- gf.w.WriteString("}")
- return nil
-}
-
-func (gf *GoFormatter) writeStructField(m Member, depth int) error {
- if m.BitfieldSize > 0 {
- return fmt.Errorf("bitfields are not supported")
- }
- if m.Offset%8 != 0 {
- return fmt.Errorf("unsupported offset %d", m.Offset)
- }
-
- if m.Name == "" {
- // Special case a nested anonymous union like
- // struct foo { union { int bar; int baz }; }
- // by replacing the whole union with its first member.
- union, ok := m.Type.(*Union)
- if !ok {
- return fmt.Errorf("anonymous fields are not supported")
-
- }
-
- if len(union.Members) == 0 {
- return errors.New("empty anonymous union")
- }
-
- depth++
- if depth > maxTypeDepth {
- return errNestedTooDeep
- }
-
- m := union.Members[0]
- size, err := Sizeof(m.Type)
- if err != nil {
- return err
- }
-
- if err := gf.writeStructField(m, depth); err != nil {
- return err
- }
-
- gf.writePadding(union.Size - uint32(size))
- return nil
-
- }
-
- fmt.Fprintf(&gf.w, "%s ", gf.identifier(m.Name))
-
- if err := gf.writeType(m.Type, depth); err != nil {
- return err
- }
-
- gf.w.WriteString("; ")
- return nil
-}
-
-func (gf *GoFormatter) writeDatasecLit(ds *Datasec, depth int) error {
- gf.w.WriteString("struct { ")
-
- prevOffset := uint32(0)
- for i, vsi := range ds.Vars {
- v := vsi.Type.(*Var)
- if v.Linkage != GlobalVar {
- // Ignore static, extern, etc. for now.
- continue
- }
-
- if v.Name == "" {
- return fmt.Errorf("variable %d: empty name", i)
- }
-
- gf.writePadding(vsi.Offset - prevOffset)
- prevOffset = vsi.Offset + vsi.Size
-
- fmt.Fprintf(&gf.w, "%s ", gf.identifier(v.Name))
-
- if err := gf.writeType(v.Type, depth); err != nil {
- return fmt.Errorf("variable %d: %w", i, err)
- }
-
- gf.w.WriteString("; ")
- }
-
- gf.writePadding(ds.Size - prevOffset)
- gf.w.WriteString("}")
- return nil
-}
-
-func (gf *GoFormatter) writePadding(bytes uint32) {
- if bytes > 0 {
- fmt.Fprintf(&gf.w, "_ [%d]byte; ", bytes)
- }
-}
-
-func skipQualifiers(typ Type) Type {
- result := typ
- for depth := 0; depth <= maxTypeDepth; depth++ {
- switch v := (result).(type) {
- case qualifier:
- result = v.qualify()
- default:
- return result
- }
- }
- return &cycle{typ}
-}