github.com/saferwall/pe@v1.5.2/debug.go (about) 1 // Copyright 2018 Saferwall. All rights reserved. 2 // Use of this source code is governed by Apache v2 license 3 // license that can be found in the LICENSE file. 4 5 package pe 6 7 import ( 8 "encoding/binary" 9 "errors" 10 "fmt" 11 ) 12 13 // The following values are defined for the Type field of the debug directory entry: 14 const ( 15 // An unknown value that is ignored by all tools. 16 ImageDebugTypeUnknown = 0 17 18 // The COFF debug information (line numbers, symbol table, and string table). 19 // This type of debug information is also pointed to by fields in the file headers. 20 ImageDebugTypeCOFF = 1 21 22 // The Visual C++ debug information. 23 ImageDebugTypeCodeView = 2 24 25 // The frame pointer omission (FPO) information. This information tells the 26 // debugger how to interpret nonstandard stack frames, which use the EBP 27 // register for a purpose other than as a frame pointer. 28 ImageDebugTypeFPO = 3 29 30 // The location of DBG file. 31 ImageDebugTypeMisc = 4 32 33 // A copy of .pdata section. 34 ImageDebugTypeException = 5 35 36 // Reserved. 37 ImageDebugTypeFixup = 6 38 39 // The mapping from an RVA in image to an RVA in source image. 40 ImageDebugTypeOMAPToSrc = 7 41 42 // The mapping from an RVA in source image to an RVA in image. 43 ImageDebugTypeOMAPFromSrc = 8 44 45 // Reserved for Borland. 46 ImageDebugTypeBorland = 9 47 48 // Reserved. 49 ImageDebugTypeReserved = 10 50 51 // Reserved. 52 ImageDebugTypeCLSID = 11 53 54 // Visual C++ features (/GS counts /sdl counts and guardN counts). 55 ImageDebugTypeVCFeature = 12 56 57 // Pogo aka PGO aka Profile Guided Optimization. 58 ImageDebugTypePOGO = 13 59 60 // Incremental Link Time Code Generation (iLTCG). 61 ImageDebugTypeILTCG = 14 62 63 // Intel MPX. 64 ImageDebugTypeMPX = 15 65 66 // PE determinism or reproducibility. 67 ImageDebugTypeRepro = 16 68 69 // Extended DLL characteristics bits. 70 ImageDebugTypeExDllCharacteristics = 20 71 ) 72 73 const ( 74 // CVSignatureRSDS represents the CodeView signature 'SDSR'. 75 CVSignatureRSDS = 0x53445352 76 77 // CVSignatureNB10 represents the CodeView signature 'NB10'. 78 CVSignatureNB10 = 0x3031424e 79 ) 80 81 const ( 82 // FrameFPO indicates a frame of type FPO. 83 FrameFPO = 0x0 84 85 // FrameTrap indicates a frame of type Trap. 86 FrameTrap = 0x1 87 88 // FrameTSS indicates a frame of type TSS. 89 FrameTSS = 0x2 90 91 // FrameNonFPO indicates a frame of type Non-FPO. 92 FrameNonFPO = 0x3 93 ) 94 95 // DllCharacteristicsExType represents a DLL Characteristics type. 96 type DllCharacteristicsExType uint32 97 98 const ( 99 // ImageDllCharacteristicsExCETCompat indicates that the image is CET 100 // compatible. 101 ImageDllCharacteristicsExCETCompat = 0x0001 102 ) 103 104 const ( 105 // POGOTypePGU represents a signature for an undocumented PGO sub type. 106 POGOTypePGU = 0x50475500 107 // POGOTypePGI represents a signature for an undocumented PGO sub type. 108 POGOTypePGI = 0x50474900 109 // POGOTypePGO represents a signature for an undocumented PGO sub type. 110 POGOTypePGO = 0x50474F00 111 // POGOTypeLTCG represents a signature for an undocumented PGO sub type. 112 POGOTypeLTCG = 0x4c544347 113 ) 114 115 // ImageDebugDirectoryType represents the type of a debug directory. 116 type ImageDebugDirectoryType uint32 117 118 // ImageDebugDirectory represents the IMAGE_DEBUG_DIRECTORY structure. 119 // This directory indicates what form of debug information is present 120 // and where it is. This directory consists of an array of debug directory 121 // entries whose location and size are indicated in the image optional header. 122 type ImageDebugDirectory struct { 123 // Reserved, must be 0. 124 Characteristics uint32 `json:"characteristics"` 125 126 // The time and date that the debug data was created. 127 TimeDateStamp uint32 `json:"time_date_stamp"` 128 129 // The major version number of the debug data format. 130 MajorVersion uint16 `json:"major_version"` 131 132 // The minor version number of the debug data format. 133 MinorVersion uint16 `json:"minor_version"` 134 135 // The format of debugging information. This field enables support of 136 // multiple debuggers. 137 Type ImageDebugDirectoryType `json:"type"` 138 139 // The size of the debug data (not including the debug directory itself). 140 SizeOfData uint32 `json:"size_of_data"` 141 142 //The address of the debug data when loaded, relative to the image base. 143 AddressOfRawData uint32 `json:"address_of_raw_data"` 144 145 // The file pointer to the debug data. 146 PointerToRawData uint32 `json:"pointer_to_raw_data"` 147 } 148 149 // DebugEntry wraps ImageDebugDirectory to include debug directory type. 150 type DebugEntry struct { 151 // Points to the image debug entry structure. 152 Struct ImageDebugDirectory `json:"struct"` 153 154 // Holds specific information about the debug type entry. 155 Info interface{} `json:"info"` 156 157 // Type of the debug entry. 158 Type string `json:"type"` 159 } 160 161 // GUID is a 128-bit value consisting of one group of 8 hexadecimal digits, 162 // followed by three groups of 4 hexadecimal digits each, followed by one 163 // group of 12 hexadecimal digits. 164 type GUID struct { 165 Data1 uint32 166 Data2 uint16 167 Data3 uint16 168 Data4 [8]byte 169 } 170 171 // CVSignature represents a CodeView signature. 172 type CVSignature uint32 173 174 // CVInfoPDB70 represents the the CodeView data block of a PDB 7.0 file. 175 type CVInfoPDB70 struct { 176 // CodeView signature, equal to `RSDS`. 177 CVSignature CVSignature `json:"cv_signature"` 178 179 // A unique identifier, which changes with every rebuild of the executable and PDB file. 180 Signature GUID `json:"signature"` 181 182 // Ever-incrementing value, which is initially set to 1 and incremented every 183 // time when a part of the PDB file is updated without rewriting the whole file. 184 Age uint32 `json:"age"` 185 186 // Null-terminated name of the PDB file. It can also contain full or partial 187 // path to the file. 188 PDBFileName string `json:"pdb_file_name"` 189 } 190 191 // CVHeader represents the the CodeView header struct to the PDB 2.0 file. 192 type CVHeader struct { 193 // CodeView signature, equal to `NB10`. 194 Signature CVSignature `json:"signature"` 195 196 // CodeView offset. Set to 0, because debug information is stored in a 197 // separate file. 198 Offset uint32 `json:"offset"` 199 } 200 201 // CVInfoPDB20 represents the the CodeView data block of a PDB 2.0 file. 202 type CVInfoPDB20 struct { 203 // Points to the CodeView header structure. 204 CVHeader CVHeader `json:"cv_header"` 205 206 // The time when debug information was created (in seconds since 01.01.1970). 207 Signature uint32 `json:"signature"` 208 209 // Ever-incrementing value, which is initially set to 1 and incremented every 210 // time when a part of the PDB file is updated without rewriting the whole file. 211 Age uint32 `json:"age"` 212 213 // Null-terminated name of the PDB file. It can also contain full or partial 214 // path to the file. 215 PDBFileName string `json:"pdb_file_name"` 216 } 217 218 // FPOFrameType represents the type of a FPO frame. 219 type FPOFrameType uint8 220 221 // FPOData represents the stack frame layout for a function on an x86 computer when 222 // frame pointer omission (FPO) optimization is used. The structure is used to locate 223 // the base of the call frame. 224 type FPOData struct { 225 // The offset of the first byte of the function code. 226 OffsetStart uint32 `json:"offset_start"` 227 228 // The number of bytes in the function. 229 ProcSize uint32 `json:"proc_size"` 230 231 // The number of local variables. 232 NumLocals uint32 `json:"num_locals"` 233 234 // The size of the parameters, in DWORDs. 235 ParamsSize uint16 `json:"params_size"` 236 237 // The number of bytes in the function prolog code. 238 PrologLength uint8 `json:"prolog_length"` 239 240 // The number of registers saved. 241 SavedRegsCount uint8 `json:"saved_regs_count"` 242 243 // A variable that indicates whether the function uses structured exception handling. 244 HasSEH uint8 `json:"has_seh"` 245 246 // A variable that indicates whether the EBP register has been allocated. 247 UseBP uint8 `json:"use_bp"` 248 249 // Reserved for future use. 250 Reserved uint8 `json:"reserved"` 251 252 // A variable that indicates the frame type. 253 FrameType FPOFrameType `json:"frame_type"` 254 } 255 256 // ImagePGOItem represents the _IMAGE_POGO_INFO structure. 257 type ImagePGOItem struct { 258 RVA uint32 `json:"rva"` 259 Size uint32 `json:"size"` 260 Name string `json:"name"` 261 } 262 263 // POGOType represents a POGO type. 264 type POGOType uint32 265 266 // POGO structure contains information related to the Profile Guided Optimization. 267 // PGO is an approach to optimization where the compiler uses profile information 268 // to make better optimization decisions for the program. 269 type POGO struct { 270 // Signature represents the PGO sub type. 271 Signature POGOType `json:"signature"` 272 Entries []ImagePGOItem `json:"entries"` 273 } 274 275 type VCFeature struct { 276 PreVC11 uint32 `json:"pre_vc11"` 277 CCpp uint32 `json:"C/C++"` 278 Gs uint32 `json:"/GS"` 279 Sdl uint32 `json:"/sdl"` 280 GuardN uint32 `json:"guardN"` 281 } 282 283 type REPRO struct { 284 Size uint32 `json:"size"` 285 Hash []byte `json:"hash"` 286 } 287 288 // ImageDebugMisc represents the IMAGE_DEBUG_MISC structure. 289 type ImageDebugMisc struct { 290 // The type of data carried in the `Data` field. 291 DataType uint32 `json:"data_type"` 292 293 // The length of this structure in bytes, including the entire Data field 294 // and its NUL terminator (rounded to four byte multiple.) 295 Length uint32 `json:"length"` 296 297 // The encoding of the Data field. True if data is unicode string. 298 Unicode bool `json:"unicode"` 299 300 // Reserved. 301 Reserved [3]byte `json:"reserved"` 302 303 // Actual data. 304 Data string `json:"data"` 305 } 306 307 // Image files contain an optional debug directory that indicates what form of 308 // debug information is present and where it is. This directory consists of an 309 // array of debug directory entries whose location and size are indicated in the 310 // image optional header. The debug directory can be in a discardable .debug 311 // section (if one exists), or it can be included in any other section in the 312 // image file, or not be in a section at all. 313 func (pe *File) parseDebugDirectory(rva, size uint32) error { 314 315 debugEntry := DebugEntry{} 316 debugDir := ImageDebugDirectory{} 317 errorMsg := fmt.Sprintf("Invalid debug information. Can't read data at RVA: 0x%x", rva) 318 debugDirSize := uint32(binary.Size(debugDir)) 319 debugDirsCount := size / debugDirSize 320 321 for i := uint32(0); i < debugDirsCount; i++ { 322 offset := pe.GetOffsetFromRva(rva + debugDirSize*i) 323 err := pe.structUnpack(&debugDir, offset, debugDirSize) 324 if err != nil { 325 return errors.New(errorMsg) 326 } 327 328 switch debugDir.Type { 329 case ImageDebugTypeCodeView: 330 debugSignature, err := pe.ReadUint32(debugDir.PointerToRawData) 331 if err != nil { 332 continue 333 } 334 335 if debugSignature == CVSignatureRSDS { 336 // PDB 7.0 337 pdb := CVInfoPDB70{CVSignature: CVSignatureRSDS} 338 339 // Extract the GUID. 340 offset := debugDir.PointerToRawData + 4 341 guidSize := uint32(binary.Size(pdb.Signature)) 342 err = pe.structUnpack(&pdb.Signature, offset, guidSize) 343 if err != nil { 344 continue 345 } 346 347 // Extract the age. 348 offset += guidSize 349 pdb.Age, err = pe.ReadUint32(offset) 350 if err != nil { 351 continue 352 } 353 offset += 4 354 355 // PDB file name. 356 pdbFilenameSize := debugDir.SizeOfData - 24 - 1 357 358 // pdbFileName_size can be negative here, as seen in the malware 359 // sample with MD5 hash: 7c297600870d026c014d42596bb9b5fd 360 // Checking for positive size here to ensure proper parsing. 361 if pdbFilenameSize > 0 { 362 pdbFilename := make([]byte, pdbFilenameSize) 363 err = pe.structUnpack(&pdbFilename, offset, pdbFilenameSize) 364 if err != nil { 365 continue 366 } 367 pdb.PDBFileName = string(pdbFilename) 368 } 369 370 // Include these extra information. 371 debugEntry.Info = pdb 372 373 } else if debugSignature == CVSignatureNB10 { 374 // PDB 2.0. 375 cvHeader := CVHeader{} 376 offset := debugDir.PointerToRawData 377 err = pe.structUnpack(&cvHeader, offset, size) 378 if err != nil { 379 continue 380 } 381 382 pdb := CVInfoPDB20{CVHeader: cvHeader} 383 384 // Extract the signature. 385 pdb.Signature, err = pe.ReadUint32(offset + 8) 386 if err != nil { 387 continue 388 } 389 390 // Extract the age. 391 pdb.Age, err = pe.ReadUint32(offset + 12) 392 if err != nil { 393 continue 394 } 395 offset += 16 396 397 pdbFilenameSize := debugDir.SizeOfData - 16 - 1 398 if pdbFilenameSize > 0 { 399 pdbFilename := make([]byte, pdbFilenameSize) 400 err = pe.structUnpack(&pdbFilename, offset, pdbFilenameSize) 401 if err != nil { 402 continue 403 } 404 pdb.PDBFileName = string(pdbFilename) 405 } 406 407 // Include these extra information. 408 debugEntry.Info = pdb 409 } 410 case ImageDebugTypePOGO: 411 pogoSignature, err := pe.ReadUint32(debugDir.PointerToRawData) 412 if err != nil { 413 continue 414 } 415 416 pogo := POGO{} 417 418 switch pogoSignature { 419 case 0x0, POGOTypePGU, POGOTypePGI, POGOTypePGO, POGOTypeLTCG: 420 // TODO: Some files like 00da1a2a9d9ebf447508bf6550f05f466f8eabb4ed6c4f2a524c0769b2d75bc1 421 // have a POGO signature of 0x0. To be reverse engineered. 422 pogo.Signature = POGOType(pogoSignature) 423 offset = debugDir.PointerToRawData + 4 424 c := uint32(0) 425 for c < debugDir.SizeOfData-4 { 426 427 pogoEntry := ImagePGOItem{} 428 pogoEntry.RVA, err = pe.ReadUint32(offset) 429 if err != nil { 430 break 431 } 432 offset += 4 433 434 pogoEntry.Size, err = pe.ReadUint32(offset) 435 if err != nil { 436 break 437 } 438 offset += 4 439 440 pogoEntry.Name = string(pe.GetStringFromData(0, pe.data[offset:offset+64])) 441 442 pogo.Entries = append(pogo.Entries, pogoEntry) 443 offset += uint32(len(pogoEntry.Name)) 444 445 // Make sure offset is aligned to 4 bytes. 446 padding := 4 - (offset % 4) 447 c += 4 + 4 + uint32(len(pogoEntry.Name)) + padding 448 offset += padding 449 } 450 451 debugEntry.Info = pogo 452 } 453 case ImageDebugTypeVCFeature: 454 vcf := VCFeature{} 455 size := uint32(binary.Size(vcf)) 456 err := pe.structUnpack(&vcf, debugDir.PointerToRawData, size) 457 if err != nil { 458 continue 459 } 460 debugEntry.Info = vcf 461 case ImageDebugTypeRepro: 462 repro := REPRO{} 463 offset := debugDir.PointerToRawData 464 465 // Extract the size. 466 repro.Size, err = pe.ReadUint32(offset) 467 if err != nil { 468 continue 469 } 470 471 // Extract the hash. 472 repro.Hash, err = pe.ReadBytesAtOffset(offset+4, repro.Size) 473 if err != nil { 474 continue 475 } 476 debugEntry.Info = repro 477 case ImageDebugTypeFPO: 478 offset := debugDir.PointerToRawData 479 size := uint32(16) 480 fpoEntries := []FPOData{} 481 c := uint32(0) 482 for c < debugDir.SizeOfData { 483 fpo := FPOData{} 484 fpo.OffsetStart, err = pe.ReadUint32(offset) 485 if err != nil { 486 break 487 } 488 489 fpo.ProcSize, err = pe.ReadUint32(offset + 4) 490 if err != nil { 491 break 492 } 493 494 fpo.NumLocals, err = pe.ReadUint32(offset + 8) 495 if err != nil { 496 break 497 } 498 499 fpo.ParamsSize, err = pe.ReadUint16(offset + 12) 500 if err != nil { 501 break 502 } 503 504 fpo.PrologLength, err = pe.ReadUint8(offset + 14) 505 if err != nil { 506 break 507 } 508 509 attributes, err := pe.ReadUint16(offset + 15) 510 if err != nil { 511 break 512 } 513 514 // 515 // UChar cbRegs :3; /* # regs saved */ 516 // UChar fHasSEH:1; /* Structured Exception Handling */ 517 // UChar fUseBP :1; /* EBP has been used */ 518 // UChar reserved:1; 519 // UChar cbFrame:2; /* frame type */ 520 // 521 522 // The lowest 3 bits 523 fpo.SavedRegsCount = uint8(attributes & 0x7) 524 525 // The next bit. 526 fpo.HasSEH = uint8(attributes & 0x8 >> 3) 527 528 // The next bit. 529 fpo.UseBP = uint8(attributes & 0x10 >> 4) 530 531 // The next bit. 532 fpo.Reserved = uint8(attributes & 0x20 >> 5) 533 534 // The next 2 bits. 535 fpo.FrameType = FPOFrameType(attributes & 0xC0 >> 6) 536 537 fpoEntries = append(fpoEntries, fpo) 538 c += size 539 offset += 16 540 } 541 debugEntry.Info = fpoEntries 542 case ImageDebugTypeExDllCharacteristics: 543 exDllChar, err := pe.ReadUint32(debugDir.PointerToRawData) 544 if err != nil { 545 continue 546 } 547 548 debugEntry.Info = DllCharacteristicsExType(exDllChar) 549 } 550 551 debugEntry.Struct = debugDir 552 debugEntry.Type = debugDir.Type.String() 553 pe.Debugs = append(pe.Debugs, debugEntry) 554 } 555 556 if len(pe.Debugs) > 0 { 557 pe.HasDebug = true 558 } 559 560 return nil 561 } 562 563 // SectionAttributeDescription maps a section attribute to a friendly name. 564 func SectionAttributeDescription(section string) string { 565 sectionNameMap := map[string]string{ 566 ".00cfg": "CFG Check Functions Pointers", 567 ".bss$00": "Uninit.data in phaseN of Pri7", 568 ".bss$dk00": "PGI: Uninit.data may be not const", 569 ".bss$dk01": "PGI: Uninit.data may be not const", 570 ".bss$pr00": "PGI: Uninit.data only for read", 571 ".bss$pr03": "PGI: Uninit.data only for read", 572 ".bss$zz": "PGO: Dead uninit.data", 573 ".CRT$XCA": "First C++ Initializer", 574 ".CRT$XCZ": "Last C++ Initializer", 575 ".xdata$x": "EH data", 576 ".gfids$y": "CFG Functions table", 577 ".CRT$XCAA": "Startup C++ Initializer", 578 ".CRT$XCC": "Global initializer: init_seg(compiler)", 579 ".CRT$XCL": "Global initializer: init_seg(lib)", 580 ".CRT$XCU": "Global initializer: init_seg(user)", 581 ".CRT$XDA": "First Dynamic TLS Initializer", 582 ".CRT$XDZ": "Last Dynamic TLS Initializer", 583 ".CRT$XIA": "First C Initializer", 584 ".CRT$XIAA": "Startup C Initializer", 585 ".CRT$XIAB": "PGO C Initializer", 586 ".CRT$XIAC": "Post-PGO C Initializer", 587 ".CRT$XIC": "CRT C Initializers", 588 ".CRT$XIYA": "VCCorLib Threading Model Initializer", 589 ".CRT$XIYAA": "XAML Designer Threading Model Override Initializer", 590 ".CRT$XIYB": "VCCorLib Main Initializer", 591 ".CRT$XIZ": "Last C Initializer", 592 ".CRT$XLA": "First Loader TLS Callback", 593 ".CRT$XLC": "CRT TLS Constructor", 594 ".CRT$XLD": "CRT TLS Terminator", 595 ".CRT$XLZ": "Last Loader TLS Callback", 596 ".CRT$XPA": "First Pre-Terminator", 597 ".CRT$XPB": "CRT ConcRT Pre-Terminator", 598 ".CRT$XPX": "CRT Pre-Terminators", 599 ".CRT$XPXA": "CRT stdio Pre-Terminator", 600 ".CRT$XPZ": "Last Pre-Terminator", 601 ".CRT$XTA": "First Terminator", 602 ".CRT$XTZ": "Last Terminator", 603 ".CRTMA$XCA": "First Managed C++ Initializer", 604 ".CRTMA$XCZ": "Last Managed C++ Initializer", 605 ".CRTVT$XCA": "First Managed VTable Initializer", 606 ".CRTVT$XCZ": "Last Managed VTable Initializer", 607 ".data$00": "Init.data in phaseN of Pri7", 608 ".data$dk00": "PGI: Init.data may be not const", 609 ".data$dk00$brc": "PGI: Init.data may be not const", 610 ".data$pr00": "PGI: Init.data only for read", 611 ".data$r": "RTTI Type Descriptors", 612 ".data$zz": "PGO: Dead init.data", 613 ".data$zz$brc": "PGO: Dead init.data", 614 ".didat$2": "Delay Import Descriptors", 615 ".didat$3": "Delay Import Final NULL Entry", 616 ".didat$4": "Delay Import INT", 617 ".didat$5": "Delay Import IAT", 618 ".didat$6": "Delay Import Symbol Names", 619 ".didat$7": "Delay Import Bound IAT", 620 ".edata": "Export Table", 621 ".gehcont": "CFG EHCont Table", 622 ".gfids": "CFG Functions Table", 623 ".giats": "CFG IAT Table", 624 ".idata$2": "Import Descriptors", 625 ".idata$3": "Import Final NULL Entry", 626 ".idata$4": "Import Names Table", 627 ".idata$5": "Import Addresses Table", 628 ".idata$6": "Import Symbol and DLL Names", 629 ".pdata": "Procedure data", 630 ".rdata$00": "Readonly data in phaseN of Pri7", 631 ".rdata$00$brc": "Readonly data in phaseN of Pri7", 632 ".rdata$09": "Readonly data in phaseN of Pri7", 633 ".rdata$brc": "BaseRelocation Clustering", 634 ".rdata$r": "RTTI Data", 635 ".rdata$sxdata": "Safe SEH", 636 ".rdata$T": "TLS Header", 637 ".rdata$zETW0": "ETW Metadata Header", 638 ".rdata$zETW1": "ETW Events Metadata", 639 ".rdata$zETW2": "ETW Providers Metadata", 640 ".rdata$zETW9": "ETW Metadata Footer", 641 ".rdata$zz": "PGO: Dead Readonly Data", 642 ".rdata$zz$brc": "PGO: Dead Readonly Data", 643 ".rdata$zzzdbg": "Debug directory data", 644 ".rsrc$01": "Resources Header", 645 ".rsrc$02": "Resources Data", 646 ".rtc$IAA": "First RTC Initializer", 647 ".rtc$IZZ": "Last RTC Initializer", 648 ".rtc$TAA": "First RTC Terminator", 649 ".rtc$TZZ": "Last RTC Terminator", 650 ".text$di": "MSVC Dynamic Initializers", 651 ".text$lp00kernel32.dll!20_pri7": "PGO: LoaderPhaseN warm-to-hot code", 652 ".text$lp01kernel32.dll!20_pri7": "PGO: LoaderPhaseN warm-to-hot code", 653 ".text$lp03kernel32.dll!30_clientonly": "PGO: LoaderPhaseN warm-to-hot code", 654 ".text$lp04kernel32.dll!30_clientonly": "PGO: LoaderPhaseN warm-to-hot code", 655 ".text$lp08kernel32.dll!40_serveronly": "PGO: LoaderPhaseN warm-to-hot code", 656 ".text$lp09kernel32.dll!40_serveronly": "PGO: LoaderPhaseN warm-to-hot code", 657 ".text$lp10kernel32.dll!40_serveronly": "PGO: LoaderPhaseN warm-to-hot code", 658 ".text$mn": "Contains EP", 659 ".text$mn$00": "CFG Dispatching", 660 ".text$np": "PGO: __asm or disabled via pragma", 661 ".text$x": "EH Filters", 662 ".text$yd": "MSVC Destructors", 663 ".text$zy": "PGO: Dead Code Blocks", 664 ".text$zz": "PGO: Dead Whole Functions", 665 ".xdata": "Unwind data", 666 } 667 668 if val, ok := sectionNameMap[section]; ok { 669 return val 670 } 671 672 return "" 673 } 674 675 // String returns a string interpretation of the FPO frame type. 676 func (ft FPOFrameType) String() string { 677 frameTypeMap := map[FPOFrameType]string{ 678 FrameFPO: "FPO", 679 FrameTrap: "Trap", 680 FrameTSS: "TSS", 681 FrameNonFPO: "Non FPO", 682 } 683 684 v, ok := frameTypeMap[ft] 685 if ok { 686 return v 687 } 688 689 return "?" 690 } 691 692 // String returns the string representation of a GUID. 693 func (g GUID) String() string { 694 return fmt.Sprintf("{%06X-%04X-%04X-%04X-%X}", g.Data1, g.Data2, g.Data3, g.Data4[0:2], g.Data4[2:]) 695 } 696 697 // String returns the string representation of a debug entry type. 698 func (t ImageDebugDirectoryType) String() string { 699 700 debugTypeMap := map[ImageDebugDirectoryType]string{ 701 ImageDebugTypeUnknown: "Unknown", 702 ImageDebugTypeCOFF: "COFF", 703 ImageDebugTypeCodeView: "CodeView", 704 ImageDebugTypeFPO: "FPO", 705 ImageDebugTypeMisc: "Misc", 706 ImageDebugTypeException: "Exception", 707 ImageDebugTypeFixup: "Fixup", 708 ImageDebugTypeOMAPToSrc: "OMAP To Src", 709 ImageDebugTypeOMAPFromSrc: "OMAP From Src", 710 ImageDebugTypeBorland: "Borland", 711 ImageDebugTypeReserved: "Reserved", 712 ImageDebugTypeVCFeature: "VC Feature", 713 ImageDebugTypePOGO: "POGO", 714 ImageDebugTypeILTCG: "iLTCG", 715 ImageDebugTypeMPX: "MPX", 716 ImageDebugTypeRepro: "REPRO", 717 ImageDebugTypeExDllCharacteristics: "Ex.DLL Characteristics", 718 } 719 720 v, ok := debugTypeMap[t] 721 if ok { 722 return v 723 } 724 725 return "?" 726 } 727 728 // String returns a string interpretation of a POGO type. 729 func (p POGOType) String() string { 730 pogoTypeMap := map[POGOType]string{ 731 POGOTypePGU: "PGU", 732 POGOTypePGI: "PGI", 733 POGOTypePGO: "PGO", 734 POGOTypeLTCG: "LTCG", 735 } 736 737 v, ok := pogoTypeMap[p] 738 if ok { 739 return v 740 } 741 742 return "?" 743 } 744 745 // String returns a string interpretation of a CodeView signature. 746 func (s CVSignature) String() string { 747 cvSignatureMap := map[CVSignature]string{ 748 CVSignatureRSDS: "RSDS", 749 CVSignatureNB10: "NB10", 750 } 751 752 v, ok := cvSignatureMap[s] 753 if ok { 754 return v 755 } 756 757 return "?" 758 } 759 760 // String returns a string interpretation of Dll Characteristics Ex. 761 func (flag DllCharacteristicsExType) String() string { 762 dllCharacteristicsExTypeMap := map[DllCharacteristicsExType]string{ 763 ImageDllCharacteristicsExCETCompat: "CET Compatible", 764 } 765 766 v, ok := dllCharacteristicsExTypeMap[flag] 767 if ok { 768 return v 769 } 770 771 return "?" 772 }