format.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. package btf
  2. import (
  3. "errors"
  4. "fmt"
  5. "strings"
  6. )
  7. var errNestedTooDeep = errors.New("nested too deep")
  8. // GoFormatter converts a Type to Go syntax.
  9. //
  10. // A zero GoFormatter is valid to use.
  11. type GoFormatter struct {
  12. w strings.Builder
  13. // Types present in this map are referred to using the given name if they
  14. // are encountered when outputting another type.
  15. Names map[Type]string
  16. // Identifier is called for each field of struct-like types. By default the
  17. // field name is used as is.
  18. Identifier func(string) string
  19. // EnumIdentifier is called for each element of an enum. By default the
  20. // name of the enum type is concatenated with Identifier(element).
  21. EnumIdentifier func(name, element string) string
  22. }
  23. // TypeDeclaration generates a Go type declaration for a BTF type.
  24. func (gf *GoFormatter) TypeDeclaration(name string, typ Type) (string, error) {
  25. gf.w.Reset()
  26. if err := gf.writeTypeDecl(name, typ); err != nil {
  27. return "", err
  28. }
  29. return gf.w.String(), nil
  30. }
  31. func (gf *GoFormatter) identifier(s string) string {
  32. if gf.Identifier != nil {
  33. return gf.Identifier(s)
  34. }
  35. return s
  36. }
  37. func (gf *GoFormatter) enumIdentifier(name, element string) string {
  38. if gf.EnumIdentifier != nil {
  39. return gf.EnumIdentifier(name, element)
  40. }
  41. return name + gf.identifier(element)
  42. }
  43. // writeTypeDecl outputs a declaration of the given type.
  44. //
  45. // It encodes https://golang.org/ref/spec#Type_declarations:
  46. //
  47. // type foo struct { bar uint32; }
  48. // type bar int32
  49. func (gf *GoFormatter) writeTypeDecl(name string, typ Type) error {
  50. if name == "" {
  51. return fmt.Errorf("need a name for type %s", typ)
  52. }
  53. switch v := skipQualifiers(typ).(type) {
  54. case *Enum:
  55. fmt.Fprintf(&gf.w, "type %s ", name)
  56. switch v.Size {
  57. case 1:
  58. gf.w.WriteString("int8")
  59. case 2:
  60. gf.w.WriteString("int16")
  61. case 4:
  62. gf.w.WriteString("int32")
  63. case 8:
  64. gf.w.WriteString("int64")
  65. default:
  66. return fmt.Errorf("%s: invalid enum size %d", typ, v.Size)
  67. }
  68. if len(v.Values) == 0 {
  69. return nil
  70. }
  71. gf.w.WriteString("; const ( ")
  72. for _, ev := range v.Values {
  73. id := gf.enumIdentifier(name, ev.Name)
  74. fmt.Fprintf(&gf.w, "%s %s = %d; ", id, name, ev.Value)
  75. }
  76. gf.w.WriteString(")")
  77. return nil
  78. default:
  79. fmt.Fprintf(&gf.w, "type %s ", name)
  80. return gf.writeTypeLit(v, 0)
  81. }
  82. }
  83. // writeType outputs the name of a named type or a literal describing the type.
  84. //
  85. // It encodes https://golang.org/ref/spec#Types.
  86. //
  87. // foo (if foo is a named type)
  88. // uint32
  89. func (gf *GoFormatter) writeType(typ Type, depth int) error {
  90. typ = skipQualifiers(typ)
  91. name := gf.Names[typ]
  92. if name != "" {
  93. gf.w.WriteString(name)
  94. return nil
  95. }
  96. return gf.writeTypeLit(typ, depth)
  97. }
  98. // writeTypeLit outputs a literal describing the type.
  99. //
  100. // The function ignores named types.
  101. //
  102. // It encodes https://golang.org/ref/spec#TypeLit.
  103. //
  104. // struct { bar uint32; }
  105. // uint32
  106. func (gf *GoFormatter) writeTypeLit(typ Type, depth int) error {
  107. depth++
  108. if depth > maxTypeDepth {
  109. return errNestedTooDeep
  110. }
  111. var err error
  112. switch v := skipQualifiers(typ).(type) {
  113. case *Int:
  114. gf.writeIntLit(v)
  115. case *Enum:
  116. gf.w.WriteString("int32")
  117. case *Typedef:
  118. err = gf.writeType(v.Type, depth)
  119. case *Array:
  120. fmt.Fprintf(&gf.w, "[%d]", v.Nelems)
  121. err = gf.writeType(v.Type, depth)
  122. case *Struct:
  123. err = gf.writeStructLit(v.Size, v.Members, depth)
  124. case *Union:
  125. // Always choose the first member to represent the union in Go.
  126. err = gf.writeStructLit(v.Size, v.Members[:1], depth)
  127. case *Datasec:
  128. err = gf.writeDatasecLit(v, depth)
  129. default:
  130. return fmt.Errorf("type %T: %w", v, ErrNotSupported)
  131. }
  132. if err != nil {
  133. return fmt.Errorf("%s: %w", typ, err)
  134. }
  135. return nil
  136. }
  137. func (gf *GoFormatter) writeIntLit(i *Int) {
  138. // NB: Encoding.IsChar is ignored.
  139. if i.Encoding.IsBool() && i.Size == 1 {
  140. gf.w.WriteString("bool")
  141. return
  142. }
  143. bits := i.Size * 8
  144. if i.Encoding.IsSigned() {
  145. fmt.Fprintf(&gf.w, "int%d", bits)
  146. } else {
  147. fmt.Fprintf(&gf.w, "uint%d", bits)
  148. }
  149. }
  150. func (gf *GoFormatter) writeStructLit(size uint32, members []Member, depth int) error {
  151. gf.w.WriteString("struct { ")
  152. prevOffset := uint32(0)
  153. skippedBitfield := false
  154. for i, m := range members {
  155. if m.BitfieldSize > 0 {
  156. skippedBitfield = true
  157. continue
  158. }
  159. offset := m.Offset.Bytes()
  160. if n := offset - prevOffset; skippedBitfield && n > 0 {
  161. fmt.Fprintf(&gf.w, "_ [%d]byte /* unsupported bitfield */; ", n)
  162. } else {
  163. gf.writePadding(n)
  164. }
  165. size, err := Sizeof(m.Type)
  166. if err != nil {
  167. return fmt.Errorf("field %d: %w", i, err)
  168. }
  169. prevOffset = offset + uint32(size)
  170. if err := gf.writeStructField(m, depth); err != nil {
  171. return fmt.Errorf("field %d: %w", i, err)
  172. }
  173. }
  174. gf.writePadding(size - prevOffset)
  175. gf.w.WriteString("}")
  176. return nil
  177. }
  178. func (gf *GoFormatter) writeStructField(m Member, depth int) error {
  179. if m.BitfieldSize > 0 {
  180. return fmt.Errorf("bitfields are not supported")
  181. }
  182. if m.Offset%8 != 0 {
  183. return fmt.Errorf("unsupported offset %d", m.Offset)
  184. }
  185. if m.Name == "" {
  186. // Special case a nested anonymous union like
  187. // struct foo { union { int bar; int baz }; }
  188. // by replacing the whole union with its first member.
  189. union, ok := m.Type.(*Union)
  190. if !ok {
  191. return fmt.Errorf("anonymous fields are not supported")
  192. }
  193. if len(union.Members) == 0 {
  194. return errors.New("empty anonymous union")
  195. }
  196. depth++
  197. if depth > maxTypeDepth {
  198. return errNestedTooDeep
  199. }
  200. m := union.Members[0]
  201. size, err := Sizeof(m.Type)
  202. if err != nil {
  203. return err
  204. }
  205. if err := gf.writeStructField(m, depth); err != nil {
  206. return err
  207. }
  208. gf.writePadding(union.Size - uint32(size))
  209. return nil
  210. }
  211. fmt.Fprintf(&gf.w, "%s ", gf.identifier(m.Name))
  212. if err := gf.writeType(m.Type, depth); err != nil {
  213. return err
  214. }
  215. gf.w.WriteString("; ")
  216. return nil
  217. }
  218. func (gf *GoFormatter) writeDatasecLit(ds *Datasec, depth int) error {
  219. gf.w.WriteString("struct { ")
  220. prevOffset := uint32(0)
  221. for i, vsi := range ds.Vars {
  222. v := vsi.Type.(*Var)
  223. if v.Linkage != GlobalVar {
  224. // Ignore static, extern, etc. for now.
  225. continue
  226. }
  227. if v.Name == "" {
  228. return fmt.Errorf("variable %d: empty name", i)
  229. }
  230. gf.writePadding(vsi.Offset - prevOffset)
  231. prevOffset = vsi.Offset + vsi.Size
  232. fmt.Fprintf(&gf.w, "%s ", gf.identifier(v.Name))
  233. if err := gf.writeType(v.Type, depth); err != nil {
  234. return fmt.Errorf("variable %d: %w", i, err)
  235. }
  236. gf.w.WriteString("; ")
  237. }
  238. gf.writePadding(ds.Size - prevOffset)
  239. gf.w.WriteString("}")
  240. return nil
  241. }
  242. func (gf *GoFormatter) writePadding(bytes uint32) {
  243. if bytes > 0 {
  244. fmt.Fprintf(&gf.w, "_ [%d]byte; ", bytes)
  245. }
  246. }
  247. func skipQualifiers(typ Type) Type {
  248. result := typ
  249. for depth := 0; depth <= maxTypeDepth; depth++ {
  250. switch v := (result).(type) {
  251. case qualifier:
  252. result = v.qualify()
  253. default:
  254. return result
  255. }
  256. }
  257. return &cycle{typ}
  258. }