github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/declextract/entity.go (about)

     1  // Copyright 2024 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package declextract
     5  
     6  import (
     7  	"strings"
     8  
     9  	"github.com/google/syzkaller/pkg/clangtool"
    10  )
    11  
    12  type Output struct {
    13  	Functions       []*Function      `json:"functions,omitempty"`
    14  	Consts          []*ConstInfo     `json:"consts,omitempty"`
    15  	Enums           []*Enum          `json:"enums,omitempty"`
    16  	Structs         []*Struct        `json:"structs,omitempty"`
    17  	Syscalls        []*Syscall       `json:"syscalls,omitempty"`
    18  	FileOps         []*FileOps       `json:"file_ops,omitempty"`
    19  	Ioctls          []*Ioctl         `json:"ioctls,omitempty"`
    20  	IouringOps      []*IouringOp     `json:"iouring_ops,omitempty"`
    21  	NetlinkFamilies []*NetlinkFamily `json:"netlink_families,omitempty"`
    22  	NetlinkPolicies []*NetlinkPolicy `json:"netlink_policies,omitempty"`
    23  }
    24  
    25  type Function struct {
    26  	Name      string `json:"name,omitempty"`
    27  	File      string `json:"file,omitempty"`
    28  	StartLine int    `json:"start_line,omitempty"`
    29  	EndLine   int    `json:"end_line,omitempty"`
    30  	IsStatic  bool   `json:"is_static,omitempty"`
    31  	// Information about function scopes. There is a global scope (with Arg=-1),
    32  	// and scope for each switch case on the function argument.
    33  	Scopes []*FunctionScope `json:"scopes,omitempty"`
    34  
    35  	callers int
    36  	facts   map[string]*typingNode
    37  }
    38  
    39  type FunctionScope struct {
    40  	// The function argument index that is switched on (-1 for the global scope).
    41  	Arg int `json:"arg"`
    42  	// The set of case values for this scope.
    43  	// It's empt for the global scope for the default case scope.
    44  	Values    []string      `json:"values,omitempty"`
    45  	StartLine int           `json:"start_line,omitempty"`
    46  	EndLine   int           `json:"end_line,omitempty"`
    47  	Calls     []string      `json:"calls,omitempty"`
    48  	Facts     []*TypingFact `json:"facts,omitempty"`
    49  
    50  	fn            *Function
    51  	calls         []*Function
    52  	coveredBlocks int
    53  	totalBlocks   int
    54  }
    55  
    56  type ConstInfo struct {
    57  	Name     string `json:"name"`
    58  	Filename string `json:"filename"`
    59  	Value    int64  `json:"value"`
    60  }
    61  
    62  type Field struct {
    63  	Name        string `json:"name,omitempty"`
    64  	IsAnonymous bool   `json:"is_anonymous,omitempty"`
    65  	BitWidth    int    `json:"bit_width,omitempty"`
    66  	CountedBy   int    `json:"counted_by,omitempty"`
    67  	Type        *Type  `json:"type,omitempty"`
    68  
    69  	syzType string
    70  }
    71  
    72  type Syscall struct {
    73  	Func       string   `json:"func,omitempty"`
    74  	Args       []*Field `json:"args,omitempty"`
    75  	SourceFile string   `json:"source_file,omitempty"`
    76  
    77  	returnType string
    78  }
    79  
    80  // FileOps describes one file_operations variable.
    81  type FileOps struct {
    82  	Name string `json:"name,omitempty"`
    83  	// Names of callback functions.
    84  	Open       string `json:"open,omitempty"`
    85  	Read       string `json:"read,omitempty"`
    86  	Write      string `json:"write,omitempty"`
    87  	Mmap       string `json:"mmap,omitempty"`
    88  	Ioctl      string `json:"ioctl,omitempty"`
    89  	SourceFile string `json:"source_file,omitempty"`
    90  
    91  	*fileOps
    92  }
    93  
    94  type fileOps struct {
    95  	open  *Function
    96  	read  *Function
    97  	write *Function
    98  	mmap  *Function
    99  	ioctl *Function
   100  	ops   []*Function // all non-nil callbacks
   101  }
   102  
   103  type Ioctl struct {
   104  	// Literal name of the command (e.g. KCOV_REMOTE_ENABLE).
   105  	Name string `json:"name,omitempty"`
   106  	Type *Type  `json:"type,omitempty"`
   107  }
   108  
   109  type IouringOp struct {
   110  	Name       string `json:"name,omitempty"`
   111  	Func       string `json:"func,omitempty"`
   112  	SourceFile string `json:"source_file,omitempty"`
   113  }
   114  
   115  type NetlinkFamily struct {
   116  	Name       string       `json:"name,omitempty"`
   117  	Ops        []*NetlinkOp `json:"ops,omitempty"`
   118  	SourceFile string       `json:"source_file,omitempty"`
   119  }
   120  
   121  type NetlinkPolicy struct {
   122  	Name  string         `json:"name,omitempty"`
   123  	Attrs []*NetlinkAttr `json:"attrs,omitempty"`
   124  }
   125  
   126  type NetlinkOp struct {
   127  	Name   string `json:"name,omitempty"`
   128  	Func   string `json:"func,omitempty"`
   129  	Access string `json:"access,omitempty"`
   130  	Policy string `json:"policy,omitempty"`
   131  }
   132  
   133  type NetlinkAttr struct {
   134  	Name         string `json:"name,omitempty"`
   135  	Kind         string `json:"kind,omitempty"`
   136  	MaxSize      int    `json:"max_size,omitempty"`
   137  	NestedPolicy string `json:"nested_policy,omitempty"`
   138  	Elem         *Type  `json:"elem,omitempty"`
   139  }
   140  
   141  type Struct struct {
   142  	Name      string   `json:"name,omitempty"`
   143  	ByteSize  int      `json:"byte_size,omitempty"`
   144  	Align     int      `json:"align,omitempty"`
   145  	IsUnion   bool     `json:"is_union,omitempty"`
   146  	IsPacked  bool     `json:"is_packed,omitempty"`
   147  	AlignAttr int      `json:"align_attr,omitempty"`
   148  	Fields    []*Field `json:"fields,omitempty"`
   149  }
   150  
   151  type Enum struct {
   152  	Name   string   `json:"name,omitempty"`
   153  	Values []string `json:"values,omitempty"`
   154  }
   155  
   156  type Type struct {
   157  	Int    *IntType    `json:"int,omitempty"`
   158  	Ptr    *PtrType    `json:"ptr,omitempty"`
   159  	Array  *ArrayType  `json:"array,omitempty"`
   160  	Buffer *BufferType `json:"buffer,omitempty"`
   161  	Struct string      `json:"struct,omitempty"`
   162  }
   163  
   164  type IntType struct {
   165  	ByteSize int    `json:"byte_size,omitempty"`
   166  	MinValue int    `json:"min_value,omitempty"`
   167  	MaxValue int    `json:"max_value,omitempty"`
   168  	IsConst  bool   `json:"is_const,omitempty"`
   169  	Name     string `json:"name,omitempty"`
   170  	Base     string `json:"base,omitempty"`
   171  	Enum     string `json:"enum,omitempty"`
   172  
   173  	isBigEndian bool
   174  }
   175  
   176  type PtrType struct {
   177  	Elem    *Type `json:"elem,omitempty"`
   178  	IsConst bool  `json:"is_const,omitempty"`
   179  }
   180  
   181  type ArrayType struct {
   182  	Elem        *Type `json:"elem,omitempty"`
   183  	MinSize     int   `json:"min_size,omitempty"`
   184  	MaxSize     int   `json:"max_size,omitempty"`
   185  	Align       int   `json:"align,omitempty"`
   186  	IsConstSize bool  `json:"is_const_size,omitempty"`
   187  }
   188  
   189  type BufferType struct {
   190  	MinSize         int  `json:"min_size,omitempty"`
   191  	MaxSize         int  `json:"max_size,omitempty"`
   192  	IsString        bool `json:"is_string,omitempty"`
   193  	IsNonTerminated bool `json:"is_non_terminated,omitempty"`
   194  }
   195  
   196  type TypingFact struct {
   197  	Src *TypingEntity `json:"src,omitempty"`
   198  	Dst *TypingEntity `json:"dst,omitempty"`
   199  }
   200  
   201  type TypingEntity struct {
   202  	Return     *EntityReturn     `json:"return,omitempty"`
   203  	Argument   *EntityArgument   `json:"argument,omitempty"`
   204  	Field      *EntityField      `json:"field,omitempty"`
   205  	Local      *EntityLocal      `json:"local,omitempty"`
   206  	GlobalAddr *EntityGlobalAddr `json:"global_addr,omitempty"`
   207  }
   208  
   209  type EntityReturn struct {
   210  	Func string `json:"func,omitempty"`
   211  }
   212  
   213  type EntityArgument struct {
   214  	Func string `json:"func,omitempty"`
   215  	Arg  int    `json:"arg"`
   216  }
   217  
   218  type EntityField struct {
   219  	Struct string `json:"struct"`
   220  	Field  string `json:"field"`
   221  }
   222  
   223  type EntityLocal struct {
   224  	Name string `json:"name"`
   225  }
   226  
   227  type EntityGlobalAddr struct {
   228  	Name string
   229  }
   230  
   231  func (out *Output) Merge(other *Output) {
   232  	out.Functions = append(out.Functions, other.Functions...)
   233  	out.Consts = append(out.Consts, other.Consts...)
   234  	out.Enums = append(out.Enums, other.Enums...)
   235  	out.Structs = append(out.Structs, other.Structs...)
   236  	out.Syscalls = append(out.Syscalls, other.Syscalls...)
   237  	out.FileOps = append(out.FileOps, other.FileOps...)
   238  	out.Ioctls = append(out.Ioctls, other.Ioctls...)
   239  	out.IouringOps = append(out.IouringOps, other.IouringOps...)
   240  	out.NetlinkFamilies = append(out.NetlinkFamilies, other.NetlinkFamilies...)
   241  	out.NetlinkPolicies = append(out.NetlinkPolicies, other.NetlinkPolicies...)
   242  }
   243  
   244  func (out *Output) Finalize(v *clangtool.Verifier) {
   245  	out.Functions = clangtool.SortAndDedupSlice(out.Functions)
   246  	out.Consts = clangtool.SortAndDedupSlice(out.Consts)
   247  	out.Enums = clangtool.SortAndDedupSlice(out.Enums)
   248  	out.Structs = clangtool.SortAndDedupSlice(out.Structs)
   249  	out.Syscalls = clangtool.SortAndDedupSlice(out.Syscalls)
   250  	out.FileOps = clangtool.SortAndDedupSlice(out.FileOps)
   251  	out.Ioctls = clangtool.SortAndDedupSlice(out.Ioctls)
   252  	out.IouringOps = clangtool.SortAndDedupSlice(out.IouringOps)
   253  	out.NetlinkFamilies = clangtool.SortAndDedupSlice(out.NetlinkFamilies)
   254  	out.NetlinkPolicies = clangtool.SortAndDedupSlice(out.NetlinkPolicies)
   255  }
   256  
   257  // SetSoureFile attaches the source file to the entities that need it.
   258  // The clang tool could do it, but it looks easier to do it here.
   259  func (out *Output) SetSourceFile(file string, updatePath func(string) string) {
   260  	for _, fn := range out.Functions {
   261  		fn.File = updatePath(fn.File)
   262  		// To optimize build time kernel/sched compiles a number of source files together
   263  		// by including them into another source file. As the result static functions
   264  		// declared in one source file effectively referenced from another source file.
   265  		// In order to be able to resolve them, we pretend such functions are not static.
   266  		if strings.HasSuffix(fn.File, ".c") && fn.File != file {
   267  			fn.IsStatic = false
   268  		}
   269  	}
   270  	for _, ci := range out.Consts {
   271  		ci.Filename = updatePath(ci.Filename)
   272  	}
   273  	for _, call := range out.Syscalls {
   274  		call.SourceFile = file
   275  	}
   276  	for _, fops := range out.FileOps {
   277  		fops.SourceFile = file
   278  	}
   279  	for _, fam := range out.NetlinkFamilies {
   280  		fam.SourceFile = file
   281  	}
   282  	for _, op := range out.IouringOps {
   283  		op.SourceFile = file
   284  	}
   285  }