aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/declextract/entity.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/declextract/entity.go')
-rw-r--r--pkg/declextract/entity.go175
1 files changed, 175 insertions, 0 deletions
diff --git a/pkg/declextract/entity.go b/pkg/declextract/entity.go
new file mode 100644
index 000000000..57e589e40
--- /dev/null
+++ b/pkg/declextract/entity.go
@@ -0,0 +1,175 @@
+// Copyright 2024 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+package declextract
+
+import (
+ "bytes"
+ "encoding/json"
+ "slices"
+)
+
+type Output struct {
+ Includes []string `json:"includes,omitempty"`
+ Defines []*Define `json:"defines,omitempty"`
+ Enums []*Enum `json:"enums,omitempty"`
+ Structs []*Struct `json:"structs,omitempty"`
+ Syscalls []*Syscall `json:"syscalls,omitempty"`
+ IouringOps []*IouringOp `json:"iouring_ops,omitempty"`
+ NetlinkFamilies []*NetlinkFamily `json:"netlink_families,omitempty"`
+ NetlinkPolicies []*NetlinkPolicy `json:"netlink_policies,omitempty"`
+}
+
+type Define struct {
+ Name string `json:"name,omitempty"`
+ Value string `json:"value,omitempty"`
+}
+
+type Field struct {
+ Name string `json:"name,omitempty"`
+ IsAnonymous bool `json:"is_anonymous,omitempty"`
+ BitWidth int `json:"bit_width,omitempty"`
+ CountedBy int `json:"counted_by,omitempty"`
+ Type *Type `json:"type,omitempty"`
+
+ syzType string
+}
+
+type Syscall struct {
+ Func string `json:"func,omitempty"`
+ Args []*Field `json:"args,omitempty"`
+ SourceFile string `json:"source_file,omitempty"`
+}
+
+type IouringOp struct {
+ Name string `json:"name,omitempty"`
+ Func string `json:"func,omitempty"`
+ SourceFile string `json:"source_file,omitempty"`
+}
+
+type NetlinkFamily struct {
+ Name string `json:"name,omitempty"`
+ Ops []*NetlinkOp `json:"ops,omitempty"`
+ SourceFile string `json:"source_file,omitempty"`
+}
+
+type NetlinkPolicy struct {
+ Name string `json:"name,omitempty"`
+ Attrs []*NetlinkAttr `json:"attrs,omitempty"`
+}
+
+type NetlinkOp struct {
+ Name string `json:"name,omitempty"`
+ Func string `json:"func,omitempty"`
+ Access string `json:"access,omitempty"`
+ Policy string `json:"policy,omitempty"`
+}
+
+type NetlinkAttr struct {
+ Name string `json:"name,omitempty"`
+ Kind string `json:"kind,omitempty"`
+ MaxSize int `json:"max_size,omitempty"`
+ NestedPolicy string `json:"nested_policy,omitempty"`
+ Elem *Type `json:"elem,omitempty"`
+}
+
+type Struct struct {
+ Name string `json:"name,omitempty"`
+ ByteSize int `json:"byte_size,omitempty"`
+ IsUnion bool `json:"is_union,omitempty"`
+ IsPacked bool `json:"is_packed,omitempty"`
+ Align int `json:"align,omitempty"`
+ Fields []*Field `json:"fields,omitempty"`
+
+ // TODO: remove me.
+ isVarlen bool
+}
+
+type Enum struct {
+ Name string `json:"name,omitempty"`
+ Values []string `json:"values,omitempty"`
+}
+
+type Type struct {
+ Int *IntType `json:"int,omitempty"`
+ Ptr *PtrType `json:"ptr,omitempty"`
+ Array *ArrayType `json:"array,omitempty"`
+ Buffer *BufferType `json:"buffer,omitempty"`
+ Struct string `json:"struct,omitempty"`
+}
+
+type IntType struct {
+ ByteSize int `json:"byte_size,omitempty"`
+ Name string `json:"name,omitempty"`
+ Base string `json:"base,omitempty"`
+ Enum string `json:"enum,omitempty"`
+
+ isBigEndian bool
+}
+
+type PtrType struct {
+ Elem *Type `json:"elem,omitempty"`
+ IsConst bool `json:"is_const,omitempty"`
+}
+
+type ArrayType struct {
+ Elem *Type `json:"elem,omitempty"`
+ MinSize int `json:"min_size,omitempty"`
+ MaxSize int `json:"max_size,omitempty"`
+}
+
+type BufferType struct {
+ MinSize int `json:"min_size,omitempty"`
+ MaxSize int `json:"max_size,omitempty"`
+ IsString bool `json:"is_string,omitempty"`
+ IsNonTerminated bool `json:"is_non_terminated,omitempty"`
+}
+
+func (out *Output) Merge(other *Output) {
+ out.Includes = append(out.Includes, other.Includes...)
+ out.Defines = append(out.Defines, other.Defines...)
+ out.Enums = append(out.Enums, other.Enums...)
+ out.Structs = append(out.Structs, other.Structs...)
+ out.Syscalls = append(out.Syscalls, other.Syscalls...)
+ out.IouringOps = append(out.IouringOps, other.IouringOps...)
+ out.NetlinkFamilies = append(out.NetlinkFamilies, other.NetlinkFamilies...)
+ out.NetlinkPolicies = append(out.NetlinkPolicies, other.NetlinkPolicies...)
+}
+
+func (out *Output) SortAndDedup() {
+ out.Includes = sortAndDedupSlice(out.Includes)
+ out.Defines = sortAndDedupSlice(out.Defines)
+ out.Enums = sortAndDedupSlice(out.Enums)
+ out.Structs = sortAndDedupSlice(out.Structs)
+ out.Syscalls = sortAndDedupSlice(out.Syscalls)
+ out.IouringOps = sortAndDedupSlice(out.IouringOps)
+ out.NetlinkFamilies = sortAndDedupSlice(out.NetlinkFamilies)
+ out.NetlinkPolicies = sortAndDedupSlice(out.NetlinkPolicies)
+}
+
+// SetSoureFile attaches the source file to the entities that need it.
+// The clang tool could do it, but it looks easier to do it here.
+func (out *Output) SetSourceFile(file string) {
+ for _, call := range out.Syscalls {
+ call.SourceFile = file
+ }
+ for _, fam := range out.NetlinkFamilies {
+ fam.SourceFile = file
+ }
+ for _, op := range out.IouringOps {
+ op.SourceFile = file
+ }
+}
+
+func sortAndDedupSlice[Slice ~[]E, E any](s Slice) Slice {
+ slices.SortFunc(s, func(a, b E) int {
+ aa, _ := json.Marshal(a)
+ bb, _ := json.Marshal(b)
+ return bytes.Compare(aa, bb)
+ })
+ return slices.CompactFunc(s, func(a, b E) bool {
+ aa, _ := json.Marshal(a)
+ bb, _ := json.Marshal(b)
+ return bytes.Equal(aa, bb)
+ })
+}