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 }