1 /// Copyright: Copyright (c) 2017-2019 Andrey Penechko. 2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 3 /// Authors: Andrey Penechko. 4 5 /// Code View format symbols 6 module vox.be.debug_info.pdb.symbol; 7 8 import std.bitmanip : bitfields; 9 import std.format : formattedWrite; 10 import vox.be.debug_info.pdb; 11 12 // SYM_ENUM_e 13 enum SymbolKind : ushort 14 { 15 S_COMPILE = 0x0001, // Compile flags symbol 16 S_END = 0x0006, // Block, procedure, "with" or thunk end 17 S_ENDARG = 0x000A, // end of argument/return list 18 19 // 16 bit symbols omitted 20 21 // sym records with 32-bit types embedded instead of 16-bit 22 // all have 0x1000 bit set for easy identification 23 // only do the 32-bit target versions since we don't really 24 // care about 16-bit ones anymore. 25 S_TI16_MAX = 0x1000, 26 27 S_REGISTER_ST = 0x1001, // Register variable 28 S_CONSTANT_ST = 0x1002, // constant symbol 29 S_UDT_ST = 0x1003, // User defined type 30 S_COBOLUDT_ST = 0x1004, // special UDT for cobol that does not symbol pack 31 S_MANYREG_ST = 0x1005, // multiple register variable 32 S_BPREL32_ST = 0x1006, // BP-relative 33 S_LDATA32_ST = 0x1007, // Module-local symbol 34 S_GDATA32_ST = 0x1008, // Global data symbol 35 S_PUB32_ST = 0x1009, // a public symbol (CV internal reserved) 36 S_LPROC32_ST = 0x100a, // Local procedure start 37 S_GPROC32_ST = 0x100b, // Global procedure start 38 S_VFTABLE32 = 0x100c, // address of virtual function table 39 S_REGREL32_ST = 0x100d, // register relative address 40 S_LTHREAD32_ST = 0x100e, // local thread storage 41 S_GTHREAD32_ST = 0x100f, // global thread storage 42 43 S_LPROCMIPS_ST = 0x1010, // Local procedure start 44 S_GPROCMIPS_ST = 0x1011, // Global procedure start 45 46 S_FRAMEPROC = 0x1012, // extra frame and proc information 47 S_COMPILE2_ST = 0x1013, // extended compile flags and info 48 49 // new symbols necessary for 16-bit enumerates of IA64 registers 50 // and IA64 specific symbols 51 52 S_MANYREG2_ST = 0x1014, // multiple register variable 53 S_LPROCIA64_ST = 0x1015, // Local procedure start (IA64) 54 S_GPROCIA64_ST = 0x1016, // Global procedure start (IA64) 55 56 // Local symbols for IL 57 S_LOCALSLOT_ST = 0x1017, // local IL sym with field for local slot index 58 S_PARAMSLOT_ST = 0x1018, // local IL sym with field for parameter slot index 59 60 S_ANNOTATION = 0x1019, // Annotation string literals 61 62 // symbols to support managed code debugging 63 S_GMANPROC_ST = 0x101a, // Global proc 64 S_LMANPROC_ST = 0x101b, // Local proc 65 S_RESERVED1 = 0x101c, // reserved 66 S_RESERVED2 = 0x101d, // reserved 67 S_RESERVED3 = 0x101e, // reserved 68 S_RESERVED4 = 0x101f, // reserved 69 S_LMANDATA_ST = 0x1020, 70 S_GMANDATA_ST = 0x1021, 71 S_MANFRAMEREL_ST= 0x1022, 72 S_MANREGISTER_ST= 0x1023, 73 S_MANSLOT_ST = 0x1024, 74 S_MANMANYREG_ST = 0x1025, 75 S_MANREGREL_ST = 0x1026, 76 S_MANMANYREG2_ST= 0x1027, 77 S_MANTYPREF = 0x1028, // Index for type referenced by name from metadata 78 S_UNAMESPACE_ST = 0x1029, // Using namespace 79 80 // Symbols w/ SZ name fields. All name fields contain utf8 encoded strings. 81 S_ST_MAX = 0x1100, // starting point for SZ name symbols 82 83 S_OBJNAME = 0x1101, // path to object file name 84 S_THUNK32 = 0x1102, // Thunk Start 85 S_BLOCK32 = 0x1103, // block start 86 S_WITH32 = 0x1104, // with start 87 S_LABEL32 = 0x1105, // code label 88 S_REGISTER = 0x1106, // Register variable 89 S_CONSTANT = 0x1107, // constant symbol 90 S_UDT = 0x1108, // User defined type 91 S_COBOLUDT = 0x1109, // special UDT for cobol that does not symbol pack 92 S_MANYREG = 0x110a, // multiple register variable 93 S_BPREL32 = 0x110b, // BP-relative 94 S_LDATA32 = 0x110c, // Module-local symbol 95 S_GDATA32 = 0x110d, // Global data symbol 96 S_PUB32 = 0x110e, // a public symbol (CV internal reserved) 97 S_LPROC32 = 0x110f, // Local procedure start 98 S_GPROC32 = 0x1110, // Global procedure start 99 S_REGREL32 = 0x1111, // register relative address 100 S_LTHREAD32 = 0x1112, // local thread storage 101 S_GTHREAD32 = 0x1113, // global thread storage 102 103 S_LPROCMIPS = 0x1114, // Local procedure start 104 S_GPROCMIPS = 0x1115, // Global procedure start 105 S_COMPILE2 = 0x1116, // extended compile flags and info 106 S_MANYREG2 = 0x1117, // multiple register variable 107 S_LPROCIA64 = 0x1118, // Local procedure start (IA64) 108 S_GPROCIA64 = 0x1119, // Global procedure start (IA64) 109 S_LOCALSLOT = 0x111a, // local IL sym with field for local slot index 110 S_SLOT = S_LOCALSLOT, // alias for LOCALSLOT 111 S_PARAMSLOT = 0x111b, // local IL sym with field for parameter slot index 112 113 // symbols to support managed code debugging 114 S_LMANDATA = 0x111c, 115 S_GMANDATA = 0x111d, 116 S_MANFRAMEREL = 0x111e, 117 S_MANREGISTER = 0x111f, 118 S_MANSLOT = 0x1120, 119 S_MANMANYREG = 0x1121, 120 S_MANREGREL = 0x1122, 121 S_MANMANYREG2 = 0x1123, 122 S_UNAMESPACE = 0x1124, // Using namespace 123 124 // ref symbols with name fields 125 S_PROCREF = 0x1125, // Reference to a procedure 126 S_DATAREF = 0x1126, // Reference to data 127 S_LPROCREF = 0x1127, // Local Reference to a procedure 128 S_ANNOTATIONREF = 0x1128, // Reference to an S_ANNOTATION symbol 129 S_TOKENREF = 0x1129, // Reference to one of the many MANPROCSYM's 130 131 // continuation of managed symbols 132 S_GMANPROC = 0x112a, // Global proc 133 S_LMANPROC = 0x112b, // Local proc 134 135 // short, light-weight thunks 136 S_TRAMPOLINE = 0x112c, // trampoline thunks 137 S_MANCONSTANT = 0x112d, // constants with metadata type info 138 139 // native attributed local/parms 140 S_ATTR_FRAMEREL = 0x112e, // relative to virtual frame ptr 141 S_ATTR_REGISTER = 0x112f, // stored in a register 142 S_ATTR_REGREL = 0x1130, // relative to register (alternate frame ptr) 143 S_ATTR_MANYREG = 0x1131, // stored in >1 register 144 145 // Separated code (from the compiler) support 146 S_SEPCODE = 0x1132, 147 148 S_LOCAL_2005 = 0x1133, // defines a local symbol in optimized code 149 S_DEFRANGE_2005 = 0x1134, // defines a single range of addresses in which symbol can be evaluated 150 S_DEFRANGE2_2005 = 0x1135, // defines ranges of addresses in which symbol can be evaluated 151 152 S_SECTION = 0x1136, // A COFF section in a PE executable 153 S_COFFGROUP = 0x1137, // A COFF group 154 S_EXPORT = 0x1138, // A export 155 156 S_CALLSITEINFO = 0x1139, // Indirect call site information 157 S_FRAMECOOKIE = 0x113a, // Security cookie information 158 159 S_DISCARDED = 0x113b, // Discarded by LINK /OPT:REF (experimental, see richards) 160 161 S_COMPILE3 = 0x113c, // Replacement for S_COMPILE2 162 S_ENVBLOCK = 0x113d, // Environment block split off from S_COMPILE2 163 164 S_LOCAL = 0x113e, // defines a local symbol in optimized code 165 S_DEFRANGE = 0x113f, // defines a single range of addresses in which symbol can be evaluated 166 S_DEFRANGE_SUBFIELD = 0x1140, // ranges for a subfield 167 168 S_DEFRANGE_REGISTER = 0x1141, // ranges for en-registered symbol 169 S_DEFRANGE_FRAMEPOINTER_REL = 0x1142, // range for stack symbol. 170 S_DEFRANGE_SUBFIELD_REGISTER = 0x1143, // ranges for en-registered field of symbol 171 S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE = 0x1144, // range for stack symbol span valid full scope of function body, gap might apply. 172 S_DEFRANGE_REGISTER_REL = 0x1145, // range for symbol address as register + offset. 173 174 // S_PROC symbols that reference ID instead of type 175 S_LPROC32_ID = 0x1146, 176 S_GPROC32_ID = 0x1147, 177 S_LPROCMIPS_ID = 0x1148, 178 S_GPROCMIPS_ID = 0x1149, 179 S_LPROCIA64_ID = 0x114a, 180 S_GPROCIA64_ID = 0x114b, 181 182 S_BUILDINFO = 0x114c, // build information. 183 S_INLINESITE = 0x114d, // inlined function callsite. 184 S_INLINESITE_END = 0x114e, 185 S_PROC_ID_END = 0x114f, 186 187 S_DEFRANGE_HLSL = 0x1150, 188 S_GDATA_HLSL = 0x1151, 189 S_LDATA_HLSL = 0x1152, 190 191 S_FILESTATIC = 0x1153, 192 193 S_LOCAL_DPC_GROUPSHARED = 0x1154, // DPC groupshared variable 194 S_LPROC32_DPC = 0x1155, // DPC local procedure start 195 S_LPROC32_DPC_ID = 0x1156, 196 S_DEFRANGE_DPC_PTR_TAG = 0x1157, // DPC pointer tag definition range 197 S_DPC_SYM_TAG_MAP = 0x1158, // DPC pointer tag value to symbol record map 198 199 S_ARMSWITCHTABLE = 0x1159, 200 S_CALLEES = 0x115a, 201 S_CALLERS = 0x115b, 202 S_POGODATA = 0x115c, 203 S_INLINESITE2 = 0x115d, // extended inline site information 204 205 S_HEAPALLOCSITE = 0x115e, // heap allocation site 206 207 S_MOD_TYPEREF = 0x115f, // only generated at link time 208 209 S_REF_MINIPDB = 0x1160, // only generated at link time for mini PDB 210 S_PDBMAP = 0x1161, // only generated at link time for mini PDB 211 212 S_GDATA_HLSL32 = 0x1162, 213 S_LDATA_HLSL32 = 0x1163, 214 215 S_GDATA_HLSL32_EX = 0x1164, 216 S_LDATA_HLSL32_EX = 0x1165, 217 218 S_INLINEES = 0x1168, 219 220 S_RECTYPE_MAX, // one greater than last 221 S_RECTYPE_LAST = S_RECTYPE_MAX - 1, 222 S_RECTYPE_PAD = S_RECTYPE_MAX + 0x100 // Used *only* to verify symbol record types so that current PDB code can potentially read 223 // future PDBs (assuming no format change, etc). 224 } 225 226 // struct UDTSYM 227 // S_UDT, S_COBOLUDT 228 align(1) struct UdtSym { 229 TypeIndex type; 230 // next follows zero-terminated string (name) 231 } 232 233 // struct INLINESITESYM 234 // S_INLINESITE 235 align(1) struct InlineSiteSym { 236 uint parent; // pointer to the inliner 237 uint end; // pointer to this block's end of S_INLINESITE_END kind 238 TypeIndex inlinee; 239 // next follows an array of compressed binary annotations 240 } 241 242 // S_PUB32 243 align(2) struct PublicSym32 244 { 245 PublicSymFlags flags; 246 uint offset; 247 ushort segment; 248 // next follows zero-terminated string (name) 249 } 250 static assert(PublicSym32.sizeof == 10); 251 252 // CV_PUBSYMFLAGS 253 enum PublicSymFlags : uint { 254 none = 0, 255 code = 1 << 0, 256 func = 1 << 1, 257 managed = 1 << 2, 258 MSIL = 1 << 3, 259 } 260 261 // S_PROCREF, S_LPROCREF 262 align(2) struct ProcRefSym 263 { 264 uint sumName; // SUC of the name 265 uint symOffset; // Offset of actual symbol in $$Symbols 266 ushort mod; // Module containing the actual symbol 267 // next follows zero-terminated string 268 } 269 static assert(ProcRefSym.sizeof == 10); 270 271 // struct PROCSYM32 272 // S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC, S_LPROC32_DPC_ID 273 align(1) struct ProcSym { 274 uint parent; // pointer to the parent 275 uint end; // pointer to this blocks end (S_END) 276 uint next; // pointer to next symbol 277 uint length; // Proc length 278 uint dbgStart; // Debug start offset 279 uint dbgEnd; // Debug end offset 280 TypeIndex typeIndex; // Type index or ID 281 uint offset; 282 ushort segment; 283 ubyte flags; // set of ProcSymFlags 284 // next follows zero-terminated string 285 } 286 287 enum ProcSymFlags : ubyte { 288 none = 0, 289 hasFP = 1 << 0, 290 hasIRET = 1 << 1, 291 hasFRET = 1 << 2, 292 isNoReturn = 1 << 3, 293 isUnreachable = 1 << 4, 294 hasCustomCallingConv = 1 << 5, 295 isNoInline = 1 << 6, 296 hasOptimizedDebugInfo = 1 << 7, 297 } 298 299 void printProcSymFlags(ubyte set) 300 { 301 import std.stdio : write; 302 if (set == 0) { 303 write(" none"); 304 return; 305 } 306 if (set & ProcSymFlags.hasFP) write(" hasFP"); 307 if (set & ProcSymFlags.hasIRET) write(" hasIRET"); 308 if (set & ProcSymFlags.hasFRET) write(" hasFRET"); 309 if (set & ProcSymFlags.isNoReturn) write(" isNoReturn"); 310 if (set & ProcSymFlags.isUnreachable) write(" isUnreachable"); 311 if (set & ProcSymFlags.hasCustomCallingConv) write(" hasCustomCallingConv"); 312 if (set & ProcSymFlags.isNoInline) write(" isNoInline"); 313 if (set & ProcSymFlags.hasOptimizedDebugInfo) write(" hasOptimizedDebugInfo"); 314 } 315 316 // S_REGREL32 317 align(1) struct RegRelativeSym { 318 uint offset; // offset of symbol 319 TypeIndex type; // Type index or metadata token 320 RegisterId register; // register index for symbol 321 // next follows zero-terminated string (name) 322 } 323 324 // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA 325 align(1) struct DataSym { 326 TypeIndex type; 327 uint dataOffset; 328 ushort segment; 329 // next follows zero-terminated string (name) 330 } 331 332 // S_LTHREAD32, S_GTHREAD32 333 align(1) struct ThreadDataSym { 334 TypeIndex type; 335 uint dataOffset; 336 ushort segment; 337 // next follows zero-terminated string (name) 338 } 339 340 // struct FRAMEPROCSYM 341 // S_FRAMEPROC 342 align(1) struct FrameProcSym { 343 uint totalFrameBytes; 344 uint paddingFrameBytes; 345 uint offsetToPadding; 346 uint bytesOfCalleeSavedRegisters; 347 uint offsetOfExceptionHandler; 348 ushort sectionIdOfExceptionHandler; 349 350 mixin(bitfields!( 351 bool, "hasAlloca", 1, // function uses _alloca() 352 bool, "hasSetJmp", 1, // function uses setjmp() 353 bool, "hasLongJmp", 1, // function uses longjmp() 354 bool, "hasInlineAssembly", 1, // function uses inline asm 355 bool, "hasExceptionHandling", 1, // function has EH states 356 bool, "markedInline", 1, // function was speced as inline 357 bool, "hasStructuredExceptionHandling", 1, // function has SEH 358 bool, "naked", 1, // function is __declspec(naked) 359 bool, "securityChecks", 1, // function has buffer security check introduced by /GS. 360 bool, "asynchronousExceptionHandling", 1, // function compiled with /EHa 361 bool, "noStackOrderingForSecurityChecks", 1, // function has /GS buffer checks, but stack ordering couldn't be done 362 bool, "inlined", 1, // function was inlined within another function 363 bool, "strictSecurityChecks", 1, // function is __declspec(strict_gs_check) 364 bool, "safeBuffers", 1, // function is __declspec(safebuffers) 365 uint, "encodedLocalBasePointer", 2, // record function's local pointer explicitly. 366 uint, "encodedParamBasePointer", 2, // record function's parameter pointer explicitly. 367 bool, "profileGuidedOptimization", 1, // function was compiled with PGO/PGU 368 bool, "validProfileCounts", 1, // Do we have valid Pogo counts? 369 bool, "optimizedForSpeed", 1, // Did we optimize for speed? 370 bool, "guardCfg", 1, // function contains CFG checks (and no write checks) 371 bool, "guardCfw", 1, // function contains CFW checks and/or instrumentation 372 373 uint, "pad", 9, 374 )); 375 }; 376 377 // struct THUNKSYM32 378 // S_THUNK32 379 struct ThunkSym { 380 uint parent; // pointer to the parent 381 uint end; // pointer to this blocks end 382 uint next; // pointer to next symbol 383 uint offset; 384 ushort segment; 385 ushort length; 386 ThunkOrdinal type; 387 // next follows zero-terminated string (name) 388 // next follows variant portion of thunk (ubyte[]) 389 } 390 391 // struct TRAMPOLINESYM 392 // S_TRAMPOLINE 393 align(1) struct TrampolineSym { 394 TrampolineType type; // trampoline sym subtype 395 ushort size; // size of the thunk 396 uint thunkOffset; // offset of the thunk 397 uint targetOffset; // offset of the target of the thunk 398 ushort thunkSection; // section index of the thunk 399 ushort targetSection; // section index of the target of the thunk 400 } 401 402 // struct CFLAGSYM 403 // S_COMPILE 404 align(1) struct CompileSym { 405 align(1): 406 ubyte machine; // target processor CV_CPUType 407 mixin(bitfields!( 408 CV_SourceLanguage, "sourceLanguage", 8, // language index 409 bool, "pcode", 1, // true if pcode present 410 ubyte, "floatprec", 2, // floating precision 411 ubyte, "floatpkg", 2, // float package 412 ubyte, "ambdata", 3, // ambient data model 413 ubyte, "ambcode", 3, // ambient code model 414 bool, "mode32", 1, // true if compiled 32 bit mode 415 uint, "pad", 12, // reserved 416 )); 417 // next follows compiler version string 418 } 419 static assert(CompileSym.sizeof == 5); 420 421 // struct COMPILESYM 422 // S_COMPILE2 423 struct CompileSym2 { 424 mixin(bitfields!( 425 CV_SourceLanguage, "sourceLanguage", 8, // Language index 426 bool, "EC", 1, // Compiled for edit and continue 427 bool, "NoDbgInfo", 1, // Compiled without debugging info 428 bool, "LTCG", 1, // Compiled with LTCG 429 bool, "NoDataAlign", 1, // Compiled with /bzalign 430 bool, "ManagedPresent", 1, // Managed code/data present 431 bool, "SecurityChecks", 1, // Compiled with /GS 432 bool, "HotPatch", 1, // Compiled with /hotpatch 433 bool, "CVTCIL", 1, // Converted with CVTCIL 434 bool, "MSILModule", 1, // MSIL module 435 uint, "padding", 15, // padding 436 )); 437 CV_CPUType machine; // Target processor 438 ushort verFEMajor; // Front end major version # 439 ushort verFEMinor; // Front end minor version # 440 ushort verFEBuild; // Front end build version # 441 ushort verMajor; // Back end major version # 442 ushort verMinor; // Back end minor version # 443 ushort verBuild; // Back end build version # 444 // next follows sequence of pairs of zero-terminated strings, terminated by empty string 445 } 446 447 // struct COMPILESYM3 448 // S_COMPILE3 449 align(1) struct CompileSym3 { 450 mixin(bitfields!( 451 CV_SourceLanguage, "sourceLanguage", 8, // Language index 452 bool, "EC", 1, // Compiled for edit and continue 453 bool, "NoDbgInfo", 1, // Compiled without debugging info 454 bool, "LTCG", 1, // Compiled with LTCG 455 bool, "NoDataAlign", 1, // Compiled with /bzalign 456 bool, "ManagedPresent", 1, // Managed code/data present 457 bool, "SecurityChecks", 1, // Compiled with /GS 458 bool, "HotPatch", 1, // Compiled with /hotpatch 459 bool, "CVTCIL", 1, // Converted with CVTCIL 460 bool, "MSILModule", 1, // MSIL module 461 bool, "Sdl", 1, // Compiled with /sdl 462 bool, "PGO", 1, // Compiled with /ltcg:pgo or pgu 463 bool, "Exp", 1, // .exp module 464 uint, "padding", 12, // padding 465 )); 466 CV_CPUType machine; // Target processor 467 ushort verFEMajor; // Front end major version # 468 ushort verFEMinor; // Front end minor version # 469 ushort verFEBuild; // Front end build version # 470 ushort verFEQFE; // Front end QFE version # 471 ushort verMajor; // Back end major version # 472 ushort verMinor; // Back end minor version # 473 ushort verBuild; // Back end build version # 474 ushort verQFE; // Back end QFE version # 475 // next follows Version string 476 } 477 478 // struct ENVBLOCKSYM 479 // S_ENVBLOCK 480 align(1) struct EnvBlockSym { 481 mixin(bitfields!( 482 bool, "EC", 1, // Compiled for edit and continue 483 uint, "pad", 7, // padding 484 )); 485 // next follows sequence of pairs of zero-terminated strings, terminated by empty string 486 } 487 488 // struct BUILDINFOSYM 489 // S_BUILDINFO 490 align(1) struct BuildInfoSym { 491 TypeIndex buildId; // CV_ItemId of Build Info. 492 } 493 494 // struct LOCALSYM 495 // S_LOCAL 496 align(1) struct LocalSym 497 { 498 TypeIndex typeIndex; // type index 499 ushort flags; // set of LocalSymFlags 500 // next follows zero-terminated string 501 } 502 503 enum LocalSymFlags : ushort { 504 none = 0, 505 isParameter = 1 << 0, 506 isAddressTaken = 1 << 1, 507 isCompilerGenerated = 1 << 2, 508 isAggregate = 1 << 3, 509 isAggregated = 1 << 4, 510 isAliased = 1 << 5, 511 isAlias = 1 << 6, 512 isReturnValue = 1 << 7, 513 isOptimizedOut = 1 << 8, 514 isEnregisteredGlobal = 1 << 9, 515 isEnregisteredStatic = 1 << 10, 516 } 517 518 void printLocalSymFlags(ushort set) 519 { 520 import std.stdio : write; 521 if (set == 0) { 522 write(" none"); 523 return; 524 } 525 if (set & LocalSymFlags.isParameter) write(" isParameter"); 526 if (set & LocalSymFlags.isAddressTaken) write(" isAddressTaken"); 527 if (set & LocalSymFlags.isCompilerGenerated) write(" isCompilerGenerated"); 528 if (set & LocalSymFlags.isAggregate) write(" isAggregate"); 529 if (set & LocalSymFlags.isAggregated) write(" isAggregated"); 530 if (set & LocalSymFlags.isAliased) write(" isAliased"); 531 if (set & LocalSymFlags.isAlias) write(" isAlias"); 532 if (set & LocalSymFlags.isReturnValue) write(" isReturnValue"); 533 if (set & LocalSymFlags.isOptimizedOut) write(" isOptimizedOut"); 534 if (set & LocalSymFlags.isEnregisteredGlobal) write(" isEnregisteredGlobal"); 535 if (set & LocalSymFlags.isEnregisteredStatic) write(" isEnregisteredStatic"); 536 } 537 538 // struct LABELSYM32 539 // S_LABEL32 540 struct LabelSym { 541 uint offset; 542 ushort segment; 543 ubyte flags; // set of ProcSymFlags 544 // next follows zero-terminated string 545 } 546 547 // struct BLOCKSYM32 548 // S_BLOCK32 549 align(1) struct BlockSym { 550 uint parent; // pointer to the parent 551 uint end; // pointer to this blocks end (S_END) 552 uint codeSize; // Block length 553 uint codeOffset; // Offset in code segment 554 ushort codeSegment; // segment of block 555 // next follows string (name) 556 } 557 558 // struct OBJNAMESYM 559 // S_OBJNAME 560 align(1) struct ObjNameSym { 561 uint signature; 562 // next follows zero-terminated string (name) 563 } 564 565 // struct SECTIONSYM 566 // S_SECTION 567 align(1) struct SectionSym 568 { 569 ushort section; // Section number 570 ubyte alignmentPower; // Alignment of this section == (1 << alignmentPower) 571 ubyte reserved; // Reserved. Must be zero. 572 uint rva; 573 uint length; 574 uint characteristics; 575 // next follows zero-terminated string (name) 576 } 577 578 // struct COFFGROUPSYM 579 // S_COFFGROUP 580 align(1) struct CoffGroupSym { 581 uint length; 582 uint characteristics; 583 uint symbolOffset; 584 ushort symbolSegment; 585 // next follows zero-terminated string (name) 586 } 587 588 // Comes from .exp files 589 // struct EXPORTSYM 590 // S_EXPORT 591 struct ExportSym { 592 ushort ordinal; 593 mixin(bitfields!( 594 bool, "isConstant", 1, // CONSTANT 595 bool, "isData", 1, // DATA 596 bool, "isPrivate", 1, // PRIVATE 597 bool, "hasNoName", 1, // NONAME 598 bool, "hasExplicitOrdinal", 1, // Ordinal was explicitly assigned 599 bool, "isForwarder", 1, // This is a forwarder 600 uint, "pad", 10, 601 )); 602 // next follows zero-terminated string (name) 603 } 604 605 // struct CV_LVAR_ADDR_RANGE 606 // represents an address range, used for optimized code debug info 607 struct LocalVariableAddrRange { 608 uint offsetStart; 609 ushort iSectStart; 610 ushort range; 611 612 void toString(scope void delegate(const(char)[]) sink) { 613 sink.formattedWrite("[%04X:%08X] - [%04X:%08X]", 614 iSectStart, offsetStart, iSectStart, offsetStart+range); 615 } 616 } 617 618 // struct CV_LVAR_ADDR_GAP 619 struct LocalVariableAddrGap { 620 ushort startOffset; // relative offset from the beginning of the live range. 621 ushort length; // length of this gap. 622 } 623 624 // struct DEFRANGESYMREGISTER 625 // S_DEFRANGE_REGISTER 626 struct DefRangeRegisterSym { 627 RegisterId register; // Register to hold the value of the symbol 628 ushort mayHaveNoName; // May have no user name on one of control flow path. 629 LocalVariableAddrRange range; // Range of addresses where this program is valid 630 // The value is not available in following gaps. 631 // LocalVariableAddrGap[] gaps; follows 632 } 633 634 // struct DEFRANGESYMSUBFIELDREGISTER 635 // S_DEFRANGE_SUBFIELD_REGISTER 636 struct DefRangeSubfieldRegisterSym { 637 RegisterId register; 638 ushort mayHaveNoName; // May have no user name on one of control flow path. 639 uint offsetInParent; 640 LocalVariableAddrRange range; 641 // LocalVariableAddrGap[] gaps; follows 642 } 643 644 // struct DEFRANGESYMREGISTERREL 645 // S_DEFRANGE_REGISTER_REL 646 align(1) struct DefRangeRegisterRelSym { 647 RegisterId baseReg; // Register to hold the base pointer of the symbol 648 mixin(bitfields!( 649 bool, "spilledUdtMember", 1, // Spilled member for s.i. 650 ubyte, "", 3, 651 uint, "offsetInParent", 12, // Offset in parent variable. 652 )); 653 int basePointerOffset; // offset to register 654 655 LocalVariableAddrRange range; // Range of addresses where this program is valid 656 } 657 658 // struct DEFRANGESYM 659 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE 660 struct DefRangeFramePointerRelFullScopeSym { // A frame variable valid in all function scope 661 int offFramePointer; // offset to frame pointer 662 } 663 664 // struct DEFRANGESYM 665 // S_DEFRANGE_FRAMEPOINTER_REL 666 struct DefRangeFramePointerRelSym { // A live range of frame variable 667 int offFramePointer; // offset to frame pointer 668 LocalVariableAddrRange range; // Range of addresses where this program is valid 669 // The value is not available in following gaps. 670 // LocalVariableAddrGap[] follows 671 } 672 673 674 // struct FUNCTIONLIST 675 // S_CALLERS, S_CALLEES, S_INLINEES 676 struct FunctionListSym { 677 uint numFuncs; // Number of functions 678 // TypeIndex[numFuncs] funcs; 679 // uint[] numInvocations; numInvocations.length may be < numFuncs. 680 // For all (i >= numInvocations.length && i < numFuncs), numInvocations[i] == 0 681 } 682 683 // S_CONSTANT, S_MANCONSTANT 684 align(2) struct ConstSym { 685 TypeIndex type; // Type index (containing enum if enumerate) or metadata token 686 ushort value; // numeric leaf containing value (if less than LF_NUMERIC) or CV_TYPE otherwise 687 // followed by payload, depending on `value` content 688 // followed by zero-terminated string (name) 689 } 690 static assert(ConstSym.sizeof == 6); 691 692 // struct FRAMECOOKIE 693 // S_FRAMECOOKIE 694 struct FrameCookieSym { 695 uint offset; // Frame relative offset 696 RegisterId reg; // Register index 697 FrameCookieType type; // Type of the cookie 698 ubyte flags; // Flags describing this cookie 699 } 700 701 // struct HEAPALLOCSITE 702 // S_HEAPALLOCSITE 703 struct HeapAllocationSiteSym { 704 uint offset; // offset of call site 705 ushort section; // section index of call site 706 ushort instrBytes; // length of heap allocation call instruction 707 TypeIndex type; // type index describing function signature 708 } 709 710 // 711 // Symbol for describing indirect calls when they are using 712 // a function pointer cast on some other type or temporary. 713 // Typical content will be an LF_POINTER to an LF_PROCEDURE 714 // type record that should mimic an actual variable with the 715 // function pointer type in question. 716 // 717 // Since the compiler can sometimes tail-merge a function call 718 // through a function pointer, there may be more than one 719 // S_CALLSITEINFO record at an address. This is similar to what 720 // you could do in your own code by: 721 // 722 // if (expr) 723 // pfn = &function1; 724 // else 725 // pfn = &function2; 726 // 727 // (*pfn)(arg list); 728 // 729 // struct CALLSITEINFO 730 // S_CALLSITEINFO 731 struct CallSiteInfoSym { 732 uint offset; // offset of call site 733 ushort section; // section index of call site 734 ushort reserved0; // alignment padding field, must be zero 735 TypeIndex type; // type index describing function signature 736 } 737 738 // struct UNAMESPACE 739 // S_UNAMESPACE 740 struct UNamespaceSym { // using namespace 741 // followed by zero-terminated string (name) 742 } 743 744 // struct FILESTATICSYM 745 // S_FILESTATIC 746 struct FileStaticSym { 747 align(2): 748 TypeIndex type; // type index 749 uint modOffset; // index of mod filename in stringtable 750 ushort flags; // set of LocalSymFlags 751 // followed by zero-terminated string (name) 752 } 753 static assert(FileStaticSym.sizeof == 10);