github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/tools/clang/declextract/output.h (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 #ifndef SYZ_DECLEXTRACT_OUTPUT_H 5 #define SYZ_DECLEXTRACT_OUTPUT_H 6 7 #include <memory> 8 #include <string> 9 #include <unordered_set> 10 #include <vector> 11 12 const char* const AccessUnknown = ""; 13 const char* const AccessUser = "user"; 14 const char* const AccessNsAdmin = "ns_admin"; 15 const char* const AccessAdmin = "admin"; 16 17 struct IntType; 18 struct PtrType; 19 struct ArrType; 20 struct BufferType; 21 22 struct FieldType { 23 std::unique_ptr<IntType> Int; 24 std::unique_ptr<PtrType> Ptr; 25 std::unique_ptr<ArrType> Array; 26 std::unique_ptr<BufferType> Buffer; 27 std::unique_ptr<std::string> Struct; 28 29 FieldType() = default; 30 FieldType(IntType&& Typ) : Int(std::make_unique<IntType>(std::move(Typ))) {} 31 FieldType(PtrType&& Typ) : Ptr(std::make_unique<PtrType>(std::move(Typ))) {} 32 FieldType(ArrType&& Typ) : Array(std::make_unique<ArrType>(std::move(Typ))) {} 33 FieldType(BufferType&& Typ) : Buffer(std::make_unique<BufferType>(std::move(Typ))) {} 34 FieldType(const std::string& Typ) : Struct(std::make_unique<std::string>(std::move(Typ))) {} 35 }; 36 37 struct IntType { 38 int ByteSize = 0; 39 int64_t MinValue = 0; 40 int64_t MaxValue = 0; 41 bool IsConst = false; 42 std::string Name; 43 std::string Base; 44 std::string Enum; 45 }; 46 47 struct PtrType { 48 FieldType Elem; 49 bool IsConst = false; 50 }; 51 52 struct ArrType { 53 FieldType Elem; 54 int MinSize = 0; 55 int MaxSize = 0; 56 int Align = 0; 57 bool IsConstSize = false; 58 }; 59 60 struct BufferType { 61 int MinSize = 0; 62 int MaxSize = 0; 63 bool IsString = false; 64 bool IsNonTerminated = false; 65 }; 66 67 struct ConstInfo { 68 std::string Name; 69 std::string Filename; 70 int64_t Value; 71 }; 72 73 struct Field { 74 std::string Name; 75 bool IsAnonymous = false; 76 int BitWidth = 0; 77 int CountedBy = -1; 78 FieldType Type; 79 }; 80 81 struct Struct { 82 std::string Name; 83 int ByteSize = 0; 84 int Align = 0; 85 bool IsUnion = false; 86 bool IsPacked = false; 87 int AlignAttr = 0; 88 std::vector<Field> Fields; 89 }; 90 91 struct Enum { 92 std::string Name; 93 std::vector<std::string> Values; 94 }; 95 96 struct Ioctl { 97 std::string Name; 98 FieldType Type; 99 }; 100 101 struct FileOps { 102 std::string Name; 103 std::string Open; 104 std::string Read; 105 std::string Write; 106 std::string Mmap; 107 std::string Ioctl; 108 }; 109 110 struct EntityReturn { 111 std::string Func; 112 }; 113 114 struct EntityArgument { 115 std::string Func; 116 unsigned Arg; 117 }; 118 119 struct EntityField { 120 std::string Struct; 121 std::string Field; 122 }; 123 124 struct EntityLocal { 125 std::string Name; 126 }; 127 128 struct EntityGlobalAddr { 129 std::string Name; 130 }; 131 132 struct EntityResource { 133 std::string Type; 134 std::string SubType; 135 }; 136 137 struct TypingEntity { 138 std::unique_ptr<EntityReturn> Return; 139 std::unique_ptr<EntityArgument> Argument; 140 std::unique_ptr<EntityField> Field; 141 std::unique_ptr<EntityLocal> Local; 142 std::unique_ptr<EntityGlobalAddr> GlobalAddr; 143 std::unique_ptr<EntityResource> Resource; 144 145 TypingEntity() = default; 146 TypingEntity(EntityReturn&& E) : Return(std::make_unique<EntityReturn>(std::move(E))) {} 147 TypingEntity(EntityArgument&& E) : Argument(std::make_unique<EntityArgument>(std::move(E))) {} 148 TypingEntity(EntityField&& E) : Field(std::make_unique<EntityField>(std::move(E))) {} 149 TypingEntity(EntityLocal&& E) : Local(std::make_unique<EntityLocal>(std::move(E))) {} 150 TypingEntity(EntityGlobalAddr&& E) : GlobalAddr(std::make_unique<EntityGlobalAddr>(std::move(E))) {} 151 TypingEntity(EntityResource&& E) : Resource(std::make_unique<EntityResource>(std::move(E))) {} 152 }; 153 154 struct TypingFact { 155 TypingEntity Src; 156 TypingEntity Dst; 157 }; 158 159 struct FunctionScope { 160 int Arg = 0; 161 int StartLine = 0; 162 int EndLine = 0; 163 std::vector<std::string> Values; 164 std::vector<std::string> Calls; 165 std::vector<TypingFact> Facts; 166 }; 167 168 struct Function { 169 std::string Name; 170 std::string File; 171 int StartLine = 0; 172 int EndLine = 0; 173 bool IsStatic = false; 174 std::vector<FunctionScope> Scopes; 175 }; 176 177 struct Syscall { 178 std::string Func; 179 std::vector<Field> Args; 180 }; 181 182 struct IouringOp { 183 std::string Name; 184 std::string Func; 185 }; 186 187 struct NetlinkOp { 188 std::string Name; 189 std::string Func; 190 const char* Access = nullptr; 191 std::string Policy; 192 }; 193 194 struct NetlinkFamily { 195 std::string Name; 196 std::vector<NetlinkOp> Ops; 197 }; 198 199 struct NetlinkAttr { 200 std::string Name; 201 std::string Kind; 202 int MaxSize = 0; 203 std::string NestedPolicy; 204 std::unique_ptr<FieldType> Elem; 205 }; 206 207 struct NetlinkPolicy { 208 std::string Name; 209 std::vector<NetlinkAttr> Attrs; 210 }; 211 212 inline void print(JSONPrinter& Printer, const ConstInfo& V) { 213 JSONPrinter::Scope Scope(Printer); 214 Printer.Field("name", V.Name); 215 Printer.Field("filename", V.Filename); 216 Printer.Field("value", V.Value, true); 217 } 218 219 inline void print(JSONPrinter& Printer, const Field& V) { 220 JSONPrinter::Scope Scope(Printer); 221 Printer.Field("name", V.Name); 222 Printer.Field("is_anonymous", V.IsAnonymous); 223 Printer.Field("bit_width", V.BitWidth); 224 Printer.Field("counted_by", V.CountedBy); 225 Printer.Field("type", V.Type, true); 226 } 227 228 inline void print(JSONPrinter& Printer, const Struct& V) { 229 JSONPrinter::Scope Scope(Printer); 230 Printer.Field("name", V.Name); 231 Printer.Field("align", V.Align); 232 Printer.Field("byte_size", V.ByteSize); 233 Printer.Field("is_union", V.IsUnion); 234 Printer.Field("is_packed", V.IsPacked); 235 Printer.Field("align_attr", V.AlignAttr); 236 Printer.Field("fields", V.Fields, true); 237 } 238 239 inline void print(JSONPrinter& Printer, const Enum& V) { 240 JSONPrinter::Scope Scope(Printer); 241 Printer.Field("name", V.Name); 242 Printer.Field("values", V.Values, true); 243 } 244 245 inline void print(JSONPrinter& Printer, const FieldType& V) { 246 JSONPrinter::Scope Scope(Printer); 247 if (V.Int) 248 Printer.Field("int", *V.Int, true); 249 else if (V.Ptr) 250 Printer.Field("ptr", *V.Ptr, true); 251 else if (V.Array) 252 Printer.Field("array", *V.Array, true); 253 else if (V.Buffer) 254 Printer.Field("buffer", *V.Buffer, true); 255 else 256 Printer.Field("struct", *V.Struct, true); 257 } 258 259 inline void print(JSONPrinter& Printer, const IntType& V) { 260 JSONPrinter::Scope Scope(Printer); 261 Printer.Field("byte_size", V.ByteSize); 262 Printer.Field("min_value", V.MinValue); 263 Printer.Field("max_value", V.MaxValue); 264 Printer.Field("is_const", V.IsConst); 265 Printer.Field("name", V.Name); 266 Printer.Field("base", V.Base); 267 Printer.Field("enum", V.Enum, true); 268 } 269 270 inline void print(JSONPrinter& Printer, const PtrType& V) { 271 JSONPrinter::Scope Scope(Printer); 272 Printer.Field("elem", V.Elem); 273 Printer.Field("is_const", V.IsConst, true); 274 } 275 276 inline void print(JSONPrinter& Printer, const ArrType& V) { 277 JSONPrinter::Scope Scope(Printer); 278 Printer.Field("elem", V.Elem); 279 Printer.Field("min_size", V.MinSize); 280 Printer.Field("max_size", V.MaxSize); 281 Printer.Field("align", V.Align); 282 Printer.Field("is_const_size", V.IsConstSize, true); 283 } 284 285 inline void print(JSONPrinter& Printer, const BufferType& V) { 286 JSONPrinter::Scope Scope(Printer); 287 Printer.Field("min_size", V.MinSize); 288 Printer.Field("max_size", V.MaxSize); 289 Printer.Field("is_string", V.IsString); 290 Printer.Field("is_non_terminated", V.IsNonTerminated, true); 291 } 292 293 inline void print(JSONPrinter& Printer, const Ioctl& V) { 294 JSONPrinter::Scope Scope(Printer); 295 Printer.Field("name", V.Name); 296 Printer.Field("type", V.Type, true); 297 } 298 299 inline void print(JSONPrinter& Printer, const FileOps& V) { 300 JSONPrinter::Scope Scope(Printer); 301 Printer.Field("name", V.Name); 302 Printer.Field("open", V.Open); 303 Printer.Field("read", V.Read); 304 Printer.Field("write", V.Write); 305 Printer.Field("mmap", V.Mmap); 306 Printer.Field("ioctl", V.Ioctl, true); 307 } 308 309 inline void print(JSONPrinter& Printer, const EntityReturn& V) { 310 JSONPrinter::Scope Scope(Printer); 311 Printer.Field("func", V.Func, true); 312 } 313 314 inline void print(JSONPrinter& Printer, const EntityArgument& V) { 315 JSONPrinter::Scope Scope(Printer); 316 Printer.Field("func", V.Func); 317 Printer.Field("arg", V.Arg, true); 318 } 319 320 inline void print(JSONPrinter& Printer, const EntityField& V) { 321 JSONPrinter::Scope Scope(Printer); 322 Printer.Field("struct", V.Struct); 323 Printer.Field("field", V.Field, true); 324 } 325 326 inline void print(JSONPrinter& Printer, const EntityLocal& V) { 327 JSONPrinter::Scope Scope(Printer); 328 Printer.Field("name", V.Name, true); 329 } 330 331 inline void print(JSONPrinter& Printer, const EntityGlobalAddr& V) { 332 JSONPrinter::Scope Scope(Printer); 333 Printer.Field("name", V.Name, true); 334 } 335 336 inline void print(JSONPrinter& Printer, const EntityResource& V) { 337 JSONPrinter::Scope Scope(Printer); 338 Printer.Field("type", V.Type); 339 Printer.Field("subtype", V.SubType, true); 340 } 341 342 inline void print(JSONPrinter& Printer, const TypingEntity& V) { 343 JSONPrinter::Scope Scope(Printer); 344 if (V.Return) 345 Printer.Field("return", *V.Return, true); 346 else if (V.Argument) 347 Printer.Field("argument", *V.Argument, true); 348 else if (V.Field) 349 Printer.Field("field", *V.Field, true); 350 else if (V.Local) 351 Printer.Field("local", *V.Local, true); 352 else if (V.GlobalAddr) 353 Printer.Field("global_addr", *V.GlobalAddr, true); 354 else 355 Printer.Field("resource", *V.Resource, true); 356 } 357 358 inline void print(JSONPrinter& Printer, const TypingFact& V) { 359 JSONPrinter::Scope Scope(Printer); 360 Printer.Field("src", V.Src); 361 Printer.Field("dst", V.Dst, true); 362 } 363 364 inline void print(JSONPrinter& Printer, const FunctionScope& V) { 365 JSONPrinter::Scope Scope(Printer); 366 Printer.Field("arg", V.Arg); 367 Printer.Field("values", V.Values); 368 Printer.Field("start_line", V.StartLine); 369 Printer.Field("end_line", V.EndLine); 370 Printer.Field("calls", V.Calls); 371 Printer.Field("facts", V.Facts, true); 372 } 373 374 inline void print(JSONPrinter& Printer, const Function& V) { 375 JSONPrinter::Scope Scope(Printer); 376 Printer.Field("name", V.Name); 377 Printer.Field("file", V.File); 378 Printer.Field("start_line", V.StartLine); 379 Printer.Field("end_line", V.EndLine); 380 Printer.Field("is_static", V.IsStatic); 381 Printer.Field("scopes", V.Scopes, true); 382 } 383 384 inline void print(JSONPrinter& Printer, const Syscall& V) { 385 JSONPrinter::Scope Scope(Printer); 386 Printer.Field("func", V.Func); 387 Printer.Field("args", V.Args, true); 388 } 389 390 inline void print(JSONPrinter& Printer, const IouringOp& V) { 391 JSONPrinter::Scope Scope(Printer); 392 Printer.Field("name", V.Name); 393 Printer.Field("func", V.Func, true); 394 } 395 396 inline void print(JSONPrinter& Printer, const NetlinkOp& V) { 397 JSONPrinter::Scope Scope(Printer); 398 Printer.Field("name", V.Name); 399 Printer.Field("func", V.Func); 400 Printer.Field("access", V.Access); 401 Printer.Field("policy", V.Policy, true); 402 } 403 404 inline void print(JSONPrinter& Printer, const NetlinkFamily& V) { 405 JSONPrinter::Scope Scope(Printer); 406 Printer.Field("name", V.Name); 407 Printer.Field("ops", V.Ops, true); 408 } 409 410 inline void print(JSONPrinter& Printer, const NetlinkAttr& V) { 411 JSONPrinter::Scope Scope(Printer); 412 Printer.Field("name", V.Name); 413 Printer.Field("kind", V.Kind); 414 Printer.Field("max_size", V.MaxSize); 415 Printer.Field("nested_policy", V.NestedPolicy); 416 Printer.Field("elem", V.Elem, true); 417 } 418 419 inline void print(JSONPrinter& Printer, const NetlinkPolicy& V) { 420 JSONPrinter::Scope Scope(Printer); 421 Printer.Field("name", V.Name); 422 Printer.Field("attrs", V.Attrs, true); 423 } 424 425 // This type is used when we can't figure out the right type, but need some type to use. 426 inline FieldType TodoType() { 427 return IntType{ 428 .ByteSize = 1, 429 .Name = "TODO", 430 .Base = "long", 431 }; 432 } 433 434 class Output { 435 public: 436 void emit(Function&& V) { Functions.push_back(std::move(V)); } 437 void emit(ConstInfo&& V) { Consts.push_back(std::move(V)); } 438 void emit(Struct&& V) { Structs.push_back(std::move(V)); } 439 void emit(Enum&& V) { Enums.push_back(std::move(V)); } 440 void emit(Syscall&& V) { Syscalls.push_back(std::move(V)); } 441 void emit(FileOps&& V) { FileOps.push_back(std::move(V)); } 442 void emit(Ioctl&& V) { Ioctls.push_back(std::move(V)); } 443 void emit(IouringOp&& V) { IouringOps.push_back(std::move(V)); } 444 void emit(NetlinkFamily&& V) { NetlinkFamilies.push_back(std::move(V)); } 445 void emit(NetlinkPolicy&& V) { NetlinkPolicies.push_back(std::move(V)); } 446 447 void print() const { 448 JSONPrinter Printer; 449 Printer.Field("functions", Functions); 450 Printer.Field("consts", Consts); 451 Printer.Field("enums", Enums); 452 Printer.Field("structs", Structs); 453 Printer.Field("syscalls", Syscalls); 454 Printer.Field("file_ops", FileOps); 455 Printer.Field("ioctls", Ioctls); 456 Printer.Field("iouring_ops", IouringOps); 457 Printer.Field("netlink_families", NetlinkFamilies); 458 Printer.Field("netlink_policies", NetlinkPolicies, true); 459 } 460 461 private: 462 std::vector<Function> Functions; 463 std::vector<ConstInfo> Consts; 464 std::vector<Enum> Enums; 465 std::vector<Struct> Structs; 466 std::vector<Syscall> Syscalls; 467 std::vector<FileOps> FileOps; 468 std::vector<Ioctl> Ioctls; 469 std::vector<IouringOp> IouringOps; 470 std::vector<NetlinkFamily> NetlinkFamilies; 471 std::vector<NetlinkPolicy> NetlinkPolicies; 472 }; 473 474 #endif