|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: debug.c ! 8: ! 9: Abstract: ! 10: ! 11: This module implements functions for splitting debugging information ! 12: out of an image file and into a separate .DBG file. ! 13: ! 14: Author: ! 15: ! 16: Steven R. Wood 4-May-1993 ! 17: ! 18: Revision History: ! 19: ! 20: --*/ ! 21: ! 22: #include <windows.h> ! 23: #include <imagehlp.h> ! 24: #include <stdio.h> ! 25: ! 26: // Helper routines ! 27: ! 28: PIMAGE_NT_HEADERS ! 29: ImageNtHeader ( ! 30: IN PVOID Base ! 31: ); ! 32: ! 33: PVOID ! 34: ImageDirectoryEntryToData ( ! 35: IN PVOID Base, ! 36: IN BOOLEAN MappedAsImage, ! 37: IN USHORT DirectoryEntry, ! 38: OUT PULONG Size ! 39: ); ! 40: ! 41: BOOL ! 42: SplitSymbols( ! 43: LPSTR ImageName, ! 44: LPSTR SymbolsPath, ! 45: LPSTR SymbolFilePath ! 46: ) ! 47: { ! 48: HANDLE FileHandle, SymbolFileHandle; ! 49: HANDLE hMappedFile; ! 50: LPVOID ImageBase; ! 51: PIMAGE_NT_HEADERS NtHeaders; ! 52: LPSTR ImageFileName; ! 53: LPVOID Symbols, SymbolsToFree; ! 54: DWORD SizeOfSymbols, Unused, ImageNameOffset, cb; ! 55: PIMAGE_SECTION_HEADER Sections; ! 56: DWORD SectionNumber, BytesWritten, BytesRead, NewFileSize, HeaderSum, CheckSum; ! 57: PIMAGE_DEBUG_DIRECTORY DebugDirectories; ! 58: PIMAGE_DEBUG_DIRECTORY DebugDirectory; ! 59: PIMAGE_DEBUG_DIRECTORY MiscDebugDirectory; ! 60: PIMAGE_DEBUG_DIRECTORY FpoDebugDirectory; ! 61: DWORD DebugDirectorySize, DbgFileHeaderSize, NumberOfDebugDirectories; ! 62: IMAGE_SEPARATE_DEBUG_HEADER DbgFileHeader; ! 63: PIMAGE_EXPORT_DIRECTORY ExportDirectory; ! 64: DWORD ExportedNamesSize; ! 65: LPDWORD pp; ! 66: LPSTR ExportedNames, Src, Dst; ! 67: DWORD i, RvaOffset, ExportDirectorySize; ! 68: PFPO_DATA FpoTable; ! 69: DWORD FpoTableSize; ! 70: PIMAGE_RUNTIME_FUNCTION_ENTRY RuntimeFunctionTable, pSrc; ! 71: DWORD RuntimeFunctionTableSize; ! 72: PIMAGE_FUNCTION_ENTRY FunctionTable, pDst; ! 73: DWORD FunctionTableSize; ! 74: ULONG NumberOfFunctionTableEntries; ! 75: IMAGE_DEBUG_DIRECTORY PhonyFPODbgDir; ! 76: DWORD SavedErrorCode; ! 77: BOOL InsertExtensionSubDir; ! 78: LPSTR ImageFilePathToSaveInImage; ! 79: ! 80: ImageFileName = ImageName + strlen( ImageName ); ! 81: while (ImageFileName > ImageName) { ! 82: if (ImageFileName[ -1 ] == '\\' || ! 83: ImageFileName[ -1 ] == '/' || ! 84: ImageFileName[ -1 ] == ':' ! 85: ) { ! 86: break; ! 87: } ! 88: else { ! 89: ImageFileName -= 1; ! 90: } ! 91: } ! 92: ! 93: if (SymbolsPath == NULL || ! 94: SymbolsPath[ 0 ] == '\0' || ! 95: SymbolsPath[ 0 ] == '.' ! 96: ) { ! 97: strncpy( SymbolFilePath, ImageName, ImageFileName - ImageName ); ! 98: SymbolFilePath[ ImageFileName - ImageName ] = '\0'; ! 99: InsertExtensionSubDir = FALSE; ! 100: } ! 101: else { ! 102: strcpy( SymbolFilePath, SymbolsPath ); ! 103: InsertExtensionSubDir = TRUE; ! 104: } ! 105: ! 106: Dst = SymbolFilePath + strlen( SymbolFilePath ); ! 107: if (Dst > SymbolFilePath && Dst[-1] != '\\' && Dst[-1] != '/' && Dst[-1] != ':') { ! 108: *Dst++ = '\\'; ! 109: } ! 110: ImageFilePathToSaveInImage = Dst; ! 111: Src = strrchr( ImageFileName, '.' ); ! 112: if (Src != NULL && InsertExtensionSubDir) { ! 113: while (*Dst = *++Src) { ! 114: Dst += 1; ! 115: } ! 116: *Dst++ = '\\'; ! 117: } ! 118: strcpy( Dst, ImageFileName ); ! 119: Dst = strrchr( Dst, '.' ); ! 120: if (Dst == NULL) { ! 121: Dst = SymbolFilePath + strlen( SymbolFilePath ); ! 122: } ! 123: strcpy( Dst, ".DBG" ); ! 124: ! 125: // ! 126: // open and map the file. ! 127: // ! 128: FileHandle = CreateFile( ImageName, ! 129: GENERIC_READ | GENERIC_WRITE, ! 130: FILE_SHARE_READ, ! 131: NULL, ! 132: OPEN_EXISTING, ! 133: 0, ! 134: NULL ! 135: ); ! 136: ! 137: ! 138: if (FileHandle == INVALID_HANDLE_VALUE) { ! 139: return FALSE; ! 140: } ! 141: ! 142: hMappedFile = CreateFileMapping( FileHandle, ! 143: NULL, ! 144: PAGE_READWRITE, ! 145: 0, ! 146: 0, ! 147: NULL ! 148: ); ! 149: if (!hMappedFile) { ! 150: CloseHandle( FileHandle ); ! 151: return FALSE; ! 152: } ! 153: ! 154: ImageBase = MapViewOfFile( hMappedFile, ! 155: FILE_MAP_WRITE, ! 156: 0, ! 157: 0, ! 158: 0 ! 159: ); ! 160: if (!ImageBase) { ! 161: CloseHandle( hMappedFile ); ! 162: CloseHandle( FileHandle ); ! 163: return FALSE; ! 164: } ! 165: ! 166: // ! 167: // Everything is mapped. Now check the image and find nt image headers ! 168: // ! 169: ! 170: NtHeaders = ImageNtHeader( ImageBase ); ! 171: if (NtHeaders == NULL) { ! 172: UnmapViewOfFile( ImageBase ); ! 173: CloseHandle( hMappedFile ); ! 174: CloseHandle( FileHandle ); ! 175: SetLastError( ERROR_BAD_EXE_FORMAT ); ! 176: return FALSE; ! 177: } ! 178: ! 179: if (NtHeaders->OptionalHeader.MajorLinkerVersion < 2 || ! 180: NtHeaders->OptionalHeader.MinorLinkerVersion < 5 ! 181: ) { ! 182: UnmapViewOfFile( ImageBase ); ! 183: CloseHandle( hMappedFile ); ! 184: CloseHandle( FileHandle ); ! 185: SetLastError( ERROR_BAD_EXE_FORMAT ); ! 186: return FALSE; ! 187: } ! 188: ! 189: if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) { ! 190: UnmapViewOfFile( ImageBase ); ! 191: CloseHandle( hMappedFile ); ! 192: CloseHandle( FileHandle ); ! 193: SetLastError( ERROR_ALREADY_ASSIGNED ); ! 194: return FALSE; ! 195: } ! 196: ! 197: DebugDirectories = ImageDirectoryEntryToData( ImageBase, ! 198: FALSE, ! 199: IMAGE_DIRECTORY_ENTRY_DEBUG, ! 200: &DebugDirectorySize ! 201: ); ! 202: if (DebugDirectories == NULL || DebugDirectorySize == 0) { ! 203: UnmapViewOfFile( ImageBase ); ! 204: CloseHandle( hMappedFile ); ! 205: CloseHandle( FileHandle ); ! 206: SetLastError( ERROR_BAD_EXE_FORMAT ); ! 207: return FALSE; ! 208: } ! 209: NumberOfDebugDirectories = DebugDirectorySize / sizeof( IMAGE_DEBUG_DIRECTORY ); ! 210: ! 211: Sections = IMAGE_FIRST_SECTION( NtHeaders ); ! 212: for (SectionNumber = 0; ! 213: SectionNumber < NtHeaders->FileHeader.NumberOfSections; ! 214: SectionNumber++ ! 215: ) { ! 216: if (Sections[ SectionNumber ].PointerToRawData != 0 && ! 217: !stricmp( Sections[ SectionNumber ].Name, ".debug" ) ! 218: ) { ! 219: break; ! 220: } ! 221: } ! 222: ! 223: FpoTable = NULL; ! 224: SymbolsToFree = NULL; ! 225: ExportedNames = NULL; ! 226: MiscDebugDirectory = NULL; ! 227: FpoDebugDirectory = NULL; ! 228: if (SectionNumber >= NtHeaders->FileHeader.NumberOfSections) { ! 229: if (NtHeaders->FileHeader.PointerToSymbolTable == 0 || ! 230: NtHeaders->FileHeader.NumberOfSymbols == 0 ! 231: ) { ! 232: goto nosyms; ! 233: } ! 234: ! 235: NewFileSize = NtHeaders->FileHeader.PointerToSymbolTable; ! 236: DebugDirectory = DebugDirectories; ! 237: for (i=0; i<NumberOfDebugDirectories; i++) { ! 238: if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_MISC) { ! 239: NewFileSize = DebugDirectory->PointerToRawData + ! 240: DebugDirectory->SizeOfData; ! 241: MiscDebugDirectory = DebugDirectory; ! 242: } ! 243: else ! 244: if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO) { ! 245: FpoTableSize = DebugDirectory->SizeOfData; ! 246: FpoTable = VirtualAlloc( NULL, ! 247: FpoTableSize, ! 248: MEM_COMMIT, ! 249: PAGE_READWRITE ! 250: ); ! 251: if ( FpoTable == NULL) { ! 252: goto nosyms; ! 253: } ! 254: if (SetFilePointer( FileHandle, ! 255: DebugDirectory->PointerToRawData, ! 256: NULL, ! 257: FILE_BEGIN ! 258: ) != DebugDirectory->PointerToRawData ! 259: ) { ! 260: goto nosyms; ! 261: } ! 262: ! 263: if (!ReadFile( FileHandle, FpoTable, FpoTableSize, &BytesRead, NULL ) || ! 264: FpoTableSize != BytesRead ! 265: ) { ! 266: goto nosyms; ! 267: } ! 268: } ! 269: ! 270: DebugDirectory += 1; ! 271: } ! 272: ! 273: SizeOfSymbols = GetFileSize( FileHandle, &Unused ) - NewFileSize; ! 274: Symbols = VirtualAlloc( NULL, ! 275: SizeOfSymbols, ! 276: MEM_COMMIT, ! 277: PAGE_READWRITE ! 278: ); ! 279: if (Symbols == NULL) { ! 280: goto nosyms; ! 281: } ! 282: SymbolsToFree = Symbols; ! 283: ! 284: if (SetFilePointer( FileHandle, ! 285: NewFileSize, ! 286: NULL, ! 287: FILE_BEGIN ! 288: ) != NewFileSize ! 289: ) { ! 290: goto nosyms; ! 291: } ! 292: ! 293: if (!ReadFile( FileHandle, Symbols, SizeOfSymbols, &BytesRead, NULL ) || ! 294: SizeOfSymbols != BytesRead ! 295: ) { ! 296: goto nosyms; ! 297: } ! 298: Sections = NULL; ! 299: } ! 300: else { ! 301: NewFileSize = Sections[ SectionNumber ].PointerToRawData; ! 302: DebugDirectory = DebugDirectories; ! 303: for (i=0; i<NumberOfDebugDirectories; i++) { ! 304: if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_MISC) { ! 305: NewFileSize = DebugDirectory->PointerToRawData + ! 306: DebugDirectory->SizeOfData; ! 307: MiscDebugDirectory = DebugDirectory; ! 308: } ! 309: else ! 310: if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO) { ! 311: FpoTableSize = DebugDirectory->SizeOfData; ! 312: FpoTable = VirtualAlloc( NULL, ! 313: FpoTableSize, ! 314: MEM_COMMIT, ! 315: PAGE_READWRITE ! 316: ); ! 317: if ( FpoTable == NULL) { ! 318: goto nosyms; ! 319: } ! 320: ! 321: memmove( FpoTable, ! 322: ((PCHAR)ImageBase + DebugDirectory->PointerToRawData), ! 323: FpoTableSize ! 324: ); ! 325: } ! 326: ! 327: DebugDirectory += 1; ! 328: } ! 329: ! 330: Symbols = (PCHAR)ImageBase + NewFileSize; ! 331: SizeOfSymbols = GetFileSize( FileHandle, &Unused ) - NewFileSize; ! 332: } ! 333: ! 334: ExportDirectory = (PIMAGE_EXPORT_DIRECTORY) ! 335: ImageDirectoryEntryToData( ImageBase, ! 336: FALSE, ! 337: IMAGE_DIRECTORY_ENTRY_EXPORT, ! 338: &ExportDirectorySize ! 339: ); ! 340: if (ExportDirectory) { ! 341: // ! 342: // This particular piece of magic gets us the RVA of the ! 343: // EXPORT section. Dont ask. ! 344: // ! 345: ! 346: RvaOffset = (DWORD) ! 347: ImageDirectoryEntryToData( ImageBase, ! 348: TRUE, ! 349: IMAGE_DIRECTORY_ENTRY_EXPORT, ! 350: &ExportDirectorySize ! 351: ) - (DWORD)ImageBase; ! 352: ! 353: pp = (LPDWORD)((DWORD)ExportDirectory + ! 354: (DWORD)ExportDirectory->AddressOfNames - RvaOffset ! 355: ); ! 356: ! 357: ExportedNamesSize = 1; ! 358: for (i=0; i<ExportDirectory->NumberOfNames; i++) { ! 359: Src = (LPSTR)((DWORD)ExportDirectory + *pp++ - RvaOffset); ! 360: ExportedNamesSize += strlen( Src ) + 1; ! 361: } ! 362: ExportedNamesSize = (ExportedNamesSize + 16) & ~15; ! 363: ! 364: Dst = (LPSTR)LocalAlloc( LPTR, ExportedNamesSize ); ! 365: if (Dst != NULL) { ! 366: ExportedNames = Dst; ! 367: pp = (LPDWORD)((DWORD)ExportDirectory + ! 368: (DWORD)ExportDirectory->AddressOfNames - RvaOffset ! 369: ); ! 370: for (i=0; i<ExportDirectory->NumberOfNames; i++) { ! 371: Src = (LPSTR)((DWORD)ExportDirectory + *pp++ - RvaOffset); ! 372: while (*Dst++ = *Src++) { ! 373: } ! 374: } ! 375: } ! 376: } ! 377: else { ! 378: ExportedNamesSize = 0; ! 379: } ! 380: ! 381: RuntimeFunctionTable = (PIMAGE_RUNTIME_FUNCTION_ENTRY) ! 382: ImageDirectoryEntryToData( ImageBase, ! 383: FALSE, ! 384: IMAGE_DIRECTORY_ENTRY_EXCEPTION, ! 385: &RuntimeFunctionTableSize ! 386: ); ! 387: if (RuntimeFunctionTable == NULL) { ! 388: RuntimeFunctionTableSize = 0; ! 389: FunctionTableSize = 0; ! 390: FunctionTable = NULL; ! 391: } ! 392: else { ! 393: NumberOfFunctionTableEntries = RuntimeFunctionTableSize / sizeof( IMAGE_RUNTIME_FUNCTION_ENTRY ); ! 394: FunctionTableSize = NumberOfFunctionTableEntries * sizeof( IMAGE_FUNCTION_ENTRY ); ! 395: FunctionTable = (PIMAGE_FUNCTION_ENTRY)VirtualAlloc( NULL, ! 396: FunctionTableSize, ! 397: MEM_COMMIT, ! 398: PAGE_READWRITE ! 399: ); ! 400: if (FunctionTable == NULL) { ! 401: goto nosyms; ! 402: } ! 403: ! 404: pSrc = RuntimeFunctionTable; ! 405: pDst = FunctionTable; ! 406: for (i=0; i<NumberOfFunctionTableEntries; i++) { ! 407: // ! 408: // Make .pdata entries in .DBG file relative. ! 409: // ! 410: pDst->StartingAddress = pSrc->BeginAddress - NtHeaders->OptionalHeader.ImageBase; ! 411: pDst->EndingAddress = pSrc->EndAddress - NtHeaders->OptionalHeader.ImageBase; ! 412: pDst->EndOfPrologue = pSrc->PrologEndAddress - NtHeaders->OptionalHeader.ImageBase; ! 413: pSrc += 1; ! 414: pDst += 1; ! 415: } ! 416: } ! 417: ! 418: if (!MakeSureDirectoryPathExists( SymbolFilePath )) { ! 419: return FALSE; ! 420: } ! 421: ! 422: SymbolFileHandle = CreateFile( SymbolFilePath, ! 423: GENERIC_WRITE, ! 424: 0, ! 425: NULL, ! 426: CREATE_ALWAYS, ! 427: 0, ! 428: NULL ! 429: ); ! 430: if (SymbolFileHandle == INVALID_HANDLE_VALUE) { ! 431: goto nosyms; ! 432: } ! 433: ! 434: DbgFileHeaderSize = sizeof( DbgFileHeader ) + ! 435: (NtHeaders->FileHeader.NumberOfSections * sizeof( IMAGE_SECTION_HEADER )) + ! 436: ExportedNamesSize + ! 437: FunctionTableSize + ! 438: DebugDirectorySize; ! 439: if (FunctionTable != NULL) { ! 440: DbgFileHeaderSize += sizeof( PhonyFPODbgDir ); ! 441: memset( &PhonyFPODbgDir, 0, sizeof( PhonyFPODbgDir ) ); ! 442: PhonyFPODbgDir.Type = IMAGE_DEBUG_TYPE_EXCEPTION; ! 443: PhonyFPODbgDir.SizeOfData = FunctionTableSize; ! 444: PhonyFPODbgDir.PointerToRawData = DbgFileHeaderSize - ! 445: FunctionTableSize; ! 446: if (Sections != NULL) { ! 447: PhonyFPODbgDir.PointerToRawData -= sizeof( IMAGE_SECTION_HEADER ); ! 448: } ! 449: } ! 450: DbgFileHeaderSize = ((DbgFileHeaderSize + 15) & ~15); ! 451: ! 452: if (SetFilePointer( SymbolFileHandle, ! 453: DbgFileHeaderSize, ! 454: NULL, ! 455: FILE_BEGIN ! 456: ) != DbgFileHeaderSize ! 457: ) { ! 458: BytesWritten = 0; ! 459: } ! 460: else { ! 461: if (!WriteFile( SymbolFileHandle, ! 462: Symbols, ! 463: SizeOfSymbols, ! 464: &BytesWritten, ! 465: NULL ! 466: ) ! 467: ) { ! 468: BytesWritten = 0; ! 469: } ! 470: } ! 471: ! 472: if (BytesWritten == SizeOfSymbols) { ! 473: cb = DebugDirectorySize; ! 474: DebugDirectory = DebugDirectories; ! 475: while (cb >= sizeof( *DebugDirectory )) { ! 476: if (DebugDirectory->AddressOfRawData) { ! 477: DebugDirectory->AddressOfRawData = 0; ! 478: } ! 479: ! 480: if (NewFileSize <= DebugDirectory->PointerToRawData) { ! 481: DebugDirectory->PointerToRawData -= NewFileSize; ! 482: DebugDirectory->PointerToRawData += DbgFileHeaderSize; ! 483: } ! 484: ! 485: if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO) { ! 486: PhonyFPODbgDir = *DebugDirectory; ! 487: DebugDirectory->PointerToRawData = NewFileSize; ! 488: } ! 489: ! 490: DebugDirectory += 1; ! 491: cb -= sizeof( *DebugDirectory ); ! 492: } ! 493: ! 494: NtHeaders->FileHeader.PointerToSymbolTable = 0; ! 495: NtHeaders->FileHeader.Characteristics |= IMAGE_FILE_DEBUG_STRIPPED; ! 496: ! 497: if (Sections != NULL) { ! 498: NtHeaders->OptionalHeader.SizeOfImage = Sections[ SectionNumber ].VirtualAddress; ! 499: NtHeaders->OptionalHeader.SizeOfInitializedData -= Sections[ SectionNumber ].SizeOfRawData; ! 500: NtHeaders->FileHeader.NumberOfSections -= 1; ! 501: } ! 502: ! 503: if (MiscDebugDirectory != NULL && MiscDebugDirectory->Type == IMAGE_DEBUG_TYPE_MISC) { ! 504: ImageNameOffset = MiscDebugDirectory->PointerToRawData + ! 505: FIELD_OFFSET( IMAGE_DEBUG_MISC, Data ); ! 506: if (SetFilePointer( FileHandle, ImageNameOffset, NULL, FILE_BEGIN ) == ImageNameOffset) { ! 507: WriteFile( FileHandle, ImageFilePathToSaveInImage, strlen( ImageFilePathToSaveInImage ) + 1, &Unused, NULL ); ! 508: } ! 509: } ! 510: ! 511: if (FpoTable) { ! 512: memcpy( (PCHAR)ImageBase + NewFileSize, ! 513: FpoTable, ! 514: FpoTableSize ! 515: ); ! 516: ! 517: NewFileSize += PhonyFPODbgDir.SizeOfData; ! 518: } ! 519: ! 520: CheckSumMappedFile( ImageBase, ! 521: NewFileSize, ! 522: &HeaderSum, ! 523: &CheckSum ! 524: ); ! 525: NtHeaders->OptionalHeader.CheckSum = CheckSum; ! 526: ! 527: DbgFileHeader.Signature = IMAGE_SEPARATE_DEBUG_SIGNATURE; ! 528: DbgFileHeader.Flags = 0; ! 529: DbgFileHeader.Machine = NtHeaders->FileHeader.Machine; ! 530: DbgFileHeader.Characteristics = NtHeaders->FileHeader.Characteristics; ! 531: DbgFileHeader.TimeDateStamp = NtHeaders->FileHeader.TimeDateStamp; ! 532: DbgFileHeader.CheckSum = CheckSum; ! 533: DbgFileHeader.ImageBase = NtHeaders->OptionalHeader.ImageBase; ! 534: DbgFileHeader.SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage; ! 535: DbgFileHeader.ExportedNamesSize = ExportedNamesSize; ! 536: DbgFileHeader.DebugDirectorySize = DebugDirectorySize; ! 537: DbgFileHeader.NumberOfSections = NtHeaders->FileHeader.NumberOfSections; ! 538: memset( DbgFileHeader.Reserved, 0, sizeof( DbgFileHeader.Reserved ) ); ! 539: DebugDirectory = DebugDirectories; ! 540: ! 541: SetFilePointer( SymbolFileHandle, 0, NULL, FILE_BEGIN ); ! 542: WriteFile( SymbolFileHandle, ! 543: &DbgFileHeader, ! 544: sizeof( DbgFileHeader ), ! 545: &BytesWritten, ! 546: NULL ! 547: ); ! 548: WriteFile( SymbolFileHandle, ! 549: IMAGE_FIRST_SECTION( NtHeaders ), ! 550: sizeof( IMAGE_SECTION_HEADER ) * NtHeaders->FileHeader.NumberOfSections, ! 551: &BytesWritten, ! 552: NULL ! 553: ); ! 554: ! 555: if (ExportedNamesSize) { ! 556: WriteFile( SymbolFileHandle, ! 557: ExportedNames, ! 558: ExportedNamesSize, ! 559: &BytesWritten, ! 560: NULL ! 561: ); ! 562: } ! 563: ! 564: if (FunctionTable) { ! 565: WriteFile( SymbolFileHandle, ! 566: &PhonyFPODbgDir, ! 567: sizeof( PhonyFPODbgDir ), ! 568: &BytesWritten, ! 569: NULL ! 570: ); ! 571: } ! 572: else ! 573: if (FpoTable) { ! 574: WriteFile( SymbolFileHandle, ! 575: &PhonyFPODbgDir, ! 576: sizeof( PhonyFPODbgDir ), ! 577: &BytesWritten, ! 578: NULL ! 579: ); ! 580: DebugDirectory += 1; ! 581: DebugDirectorySize -= sizeof( PhonyFPODbgDir ); ! 582: } ! 583: ! 584: WriteFile( SymbolFileHandle, ! 585: DebugDirectory, ! 586: DebugDirectorySize, ! 587: &BytesWritten, ! 588: NULL ! 589: ); ! 590: ! 591: if (FunctionTable) { ! 592: WriteFile( SymbolFileHandle, ! 593: FunctionTable, ! 594: FunctionTableSize, ! 595: &BytesWritten, ! 596: NULL ! 597: ); ! 598: } ! 599: ! 600: SetFilePointer( SymbolFileHandle, 0, NULL, FILE_END ); ! 601: CloseHandle( SymbolFileHandle ); ! 602: ! 603: FlushViewOfFile( ImageBase, NewFileSize ); ! 604: UnmapViewOfFile( ImageBase ); ! 605: CloseHandle( hMappedFile ); ! 606: if (SetFilePointer( FileHandle, NewFileSize, NULL, FILE_BEGIN ) != NewFileSize || ! 607: !SetEndOfFile( FileHandle ) ! 608: ) { ! 609: } ! 610: ! 611: TouchFileTimes( FileHandle, NULL ); ! 612: CloseHandle( FileHandle ); ! 613: ! 614: if (ExportedNames != NULL) { ! 615: LocalFree( ExportedNames ); ! 616: } ! 617: ! 618: if (FpoTable != NULL) { ! 619: VirtualFree( FpoTable, 0, MEM_RELEASE ); ! 620: } ! 621: ! 622: if (SymbolsToFree != NULL) { ! 623: VirtualFree( SymbolsToFree, 0, MEM_RELEASE ); ! 624: } ! 625: ! 626: if (FunctionTable != NULL) { ! 627: VirtualFree( FunctionTable, 0, MEM_RELEASE ); ! 628: } ! 629: return TRUE; ! 630: } ! 631: else { ! 632: CloseHandle( SymbolFileHandle ); ! 633: DeleteFile( SymbolFilePath ); ! 634: } ! 635: ! 636: nosyms: ! 637: SavedErrorCode = GetLastError(); ! 638: if (ExportedNames != NULL) { ! 639: LocalFree( ExportedNames ); ! 640: } ! 641: ! 642: if (FpoTable != NULL) { ! 643: VirtualFree( FpoTable, 0, MEM_RELEASE ); ! 644: } ! 645: ! 646: if (SymbolsToFree != NULL) { ! 647: VirtualFree( SymbolsToFree, 0, MEM_RELEASE ); ! 648: } ! 649: ! 650: if (FunctionTable != NULL) { ! 651: VirtualFree( FunctionTable, 0, MEM_RELEASE ); ! 652: } ! 653: ! 654: UnmapViewOfFile( ImageBase ); ! 655: CloseHandle( hMappedFile ); ! 656: CloseHandle( FileHandle ); ! 657: SetLastError( SavedErrorCode ); ! 658: return FALSE; ! 659: } ! 660: ! 661: BOOL ! 662: SearchTreeForFile( ! 663: LPSTR RootPath, ! 664: PCHAR InputPathName, ! 665: PCHAR OutputPathBuffer ! 666: ); ! 667: ! 668: HANDLE ! 669: FindExecutableImage( ! 670: LPSTR FileName, ! 671: LPSTR SymbolPath, ! 672: LPSTR ImageFilePath ! 673: ); ! 674: ! 675: BOOL ! 676: GetImageNameFromMiscDebugData( ! 677: HANDLE FileHandle, ! 678: PVOID MappedBase, ! 679: PIMAGE_NT_HEADERS NtHeaders, ! 680: PIMAGE_DEBUG_DIRECTORY DebugDirectories, ! 681: ULONG NumberOfDebugDirectories, ! 682: LPSTR ImageFilePath ! 683: ); ! 684: ! 685: PIMAGE_DEBUG_INFORMATION ! 686: MapDebugInformation( ! 687: HANDLE FileHandle, ! 688: LPSTR FileName, ! 689: LPSTR SymbolPath, ! 690: ULONG ImageBase ! 691: ) ! 692: { ! 693: ULONG NumberOfHandlesToClose; ! 694: HANDLE HandlesToClose[ 4 ]; ! 695: HANDLE MappingHandle; ! 696: PVOID MappedBase, Next; ! 697: BOOL SeparateSymbols; ! 698: UCHAR ImageFilePath[ MAX_PATH ]; ! 699: UCHAR DebugFilePath[ MAX_PATH ]; ! 700: PIMAGE_DEBUG_INFORMATION DebugInfo; ! 701: PIMAGE_NT_HEADERS NtHeaders; ! 702: PIMAGE_DEBUG_DIRECTORY DebugDirectories; ! 703: PIMAGE_DEBUG_DIRECTORY DebugDirectory; ! 704: PIMAGE_SEPARATE_DEBUG_HEADER DebugFileHeader; ! 705: PIMAGE_EXPORT_DIRECTORY ExportDirectory; ! 706: PIMAGE_RUNTIME_FUNCTION_ENTRY RuntimeFunctionTable; ! 707: PIMAGE_FUNCTION_ENTRY FunctionTable; ! 708: ULONG NumberOfFunctionTableEntries, FunctionTableSize; ! 709: PVOID DebugData; ! 710: LPSTR Src, Dst; ! 711: PULONG pp; ! 712: ULONG RvaOffset; ! 713: ULONG i, j; ! 714: ULONG ExportedNamesSize; ! 715: ULONG DebugInfoHeaderSize; ! 716: ULONG DebugInfoSize; ! 717: ULONG Size; ! 718: ULONG NumberOfDebugDirectories; ! 719: LONG BaseOffset; ! 720: HANDLE SavedImageFileHandle; ! 721: ! 722: if (FileHandle == NULL && (FileName == NULL || FileName[ 0 ] == '\0')) { ! 723: return NULL; ! 724: } ! 725: ! 726: DebugInfo = NULL; ! 727: NumberOfHandlesToClose = 0; ! 728: MappedBase = NULL; ! 729: SeparateSymbols = FALSE; ! 730: SavedImageFileHandle = NULL; ! 731: ImageFilePath[ 0 ] = '\0'; ! 732: NumberOfFunctionTableEntries = 0; ! 733: FunctionTableSize = 0; ! 734: FunctionTable = NULL; ! 735: try { ! 736: try { ! 737: if (FileHandle == NULL) { ! 738: FileHandle = FindExecutableImage( FileName, SymbolPath, ImageFilePath ); ! 739: if (FileHandle == NULL) { ! 740: strcpy( ImageFilePath, FileName ); ! 741: getDebugFile: ! 742: FileHandle = FindDebugInfoFile( FileName, SymbolPath, DebugFilePath ); ! 743: if (FileHandle == NULL) { ! 744: if (SavedImageFileHandle != NULL) { ! 745: FileHandle = SavedImageFileHandle; ! 746: goto noDebugFile; ! 747: } ! 748: else { ! 749: leave; ! 750: } ! 751: } ! 752: else { ! 753: SeparateSymbols = TRUE; ! 754: } ! 755: } ! 756: else { ! 757: SavedImageFileHandle = FileHandle; ! 758: } ! 759: ! 760: HandlesToClose[ NumberOfHandlesToClose++ ] = FileHandle; ! 761: } ! 762: else { ! 763: SavedImageFileHandle = FileHandle; ! 764: } ! 765: ! 766: // ! 767: // map image file and process enough to get the image name and capture ! 768: // stuff from header. ! 769: // ! 770: ! 771: MappingHandle = CreateFileMapping( FileHandle, ! 772: NULL, ! 773: PAGE_READONLY, ! 774: 0, ! 775: 0, ! 776: NULL ! 777: ); ! 778: if (MappingHandle == NULL) { ! 779: leave; ! 780: } ! 781: HandlesToClose[ NumberOfHandlesToClose++ ] = MappingHandle; ! 782: ! 783: MappedBase = MapViewOfFile( MappingHandle, ! 784: FILE_MAP_READ, ! 785: 0, ! 786: 0, ! 787: 0 ! 788: ); ! 789: if (MappedBase == NULL) { ! 790: leave; ! 791: } ! 792: ! 793: DebugInfoSize = sizeof( *DebugInfo ) + strlen( ImageFilePath ) + 1; ! 794: if (SeparateSymbols) { ! 795: DebugInfoSize += strlen( DebugFilePath ) + 1; ! 796: } ! 797: ! 798: if (!SeparateSymbols) { ! 799: NtHeaders = ImageNtHeader( MappedBase ); ! 800: if (NtHeaders == NULL) { ! 801: leave; ! 802: } ! 803: ! 804: DebugDirectories = (PIMAGE_DEBUG_DIRECTORY) ! 805: ImageDirectoryEntryToData( MappedBase, ! 806: FALSE, ! 807: IMAGE_DIRECTORY_ENTRY_DEBUG, ! 808: &Size ! 809: ); ! 810: if (DebugDirectories != NULL) { ! 811: NumberOfDebugDirectories = Size / sizeof( IMAGE_DEBUG_DIRECTORY ); ! 812: } ! 813: else { ! 814: NumberOfDebugDirectories = 0; ! 815: } ! 816: ! 817: if (FileName == NULL && ! 818: GetImageNameFromMiscDebugData( FileHandle, ! 819: MappedBase, ! 820: NtHeaders, ! 821: DebugDirectories, ! 822: NumberOfDebugDirectories, ! 823: ImageFilePath ! 824: ) ! 825: ) { ! 826: FileName = ImageFilePath; ! 827: DebugInfoSize += strlen( ImageFilePath ); ! 828: } ! 829: ! 830: DebugInfoSize = (DebugInfoSize + 16) & ~15; ! 831: DebugInfoHeaderSize = DebugInfoSize; ! 832: ! 833: if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) { ! 834: goto getDebugFile; ! 835: } ! 836: ! 837: noDebugFile: ! 838: ExportDirectory = (PIMAGE_EXPORT_DIRECTORY) ! 839: ImageDirectoryEntryToData( MappedBase, ! 840: FALSE, ! 841: IMAGE_DIRECTORY_ENTRY_EXPORT, ! 842: &Size ! 843: ); ! 844: if (ExportDirectory) { ! 845: // ! 846: // This particular piece of magic gets us the RVA of the ! 847: // EXPORT section. Dont ask. ! 848: // ! 849: ! 850: RvaOffset = (ULONG) ! 851: ImageDirectoryEntryToData( MappedBase, ! 852: TRUE, ! 853: IMAGE_DIRECTORY_ENTRY_EXPORT, ! 854: &Size ! 855: ) - (DWORD)MappedBase; ! 856: ! 857: pp = (PULONG)((ULONG)ExportDirectory + ! 858: (ULONG)ExportDirectory->AddressOfNames - RvaOffset ! 859: ); ! 860: ! 861: ExportedNamesSize = 1; ! 862: for (i=0; i<ExportDirectory->NumberOfNames; i++) { ! 863: Src = (LPSTR)((ULONG)ExportDirectory + *pp++ - RvaOffset); ! 864: ExportedNamesSize += strlen( Src ) + 1; ! 865: } ! 866: ExportedNamesSize = (ExportedNamesSize + 16) & ~15; ! 867: DebugInfoSize += ExportedNamesSize; ! 868: } ! 869: else { ! 870: ExportedNamesSize = 0; ! 871: } ! 872: ! 873: RuntimeFunctionTable = (PIMAGE_RUNTIME_FUNCTION_ENTRY) ! 874: ImageDirectoryEntryToData( MappedBase, ! 875: FALSE, ! 876: IMAGE_DIRECTORY_ENTRY_EXCEPTION, ! 877: &Size ! 878: ); ! 879: if (RuntimeFunctionTable != NULL) { ! 880: NumberOfFunctionTableEntries = Size / sizeof( IMAGE_RUNTIME_FUNCTION_ENTRY ); ! 881: FunctionTableSize = NumberOfFunctionTableEntries * ! 882: sizeof( IMAGE_FUNCTION_ENTRY ); ! 883: ! 884: DebugInfoSize += FunctionTableSize; ! 885: } ! 886: ! 887: if (NumberOfDebugDirectories != 0) { ! 888: DebugDirectory = DebugDirectories; ! 889: for (i=0; i<NumberOfDebugDirectories; i++) { ! 890: if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO || ! 891: DebugDirectory->Type == IMAGE_DEBUG_TYPE_COFF ! 892: ) { ! 893: if (DebugDirectory->AddressOfRawData == 0) { ! 894: DebugInfoSize += DebugDirectory->SizeOfData; ! 895: } ! 896: } ! 897: ! 898: DebugDirectory += 1; ! 899: } ! 900: } ! 901: } ! 902: else { ! 903: DebugFileHeader = (PIMAGE_SEPARATE_DEBUG_HEADER)MappedBase; ! 904: Next = (PVOID)((PIMAGE_SECTION_HEADER)(DebugFileHeader + 1) + DebugFileHeader->NumberOfSections); ! 905: if (DebugFileHeader->ExportedNamesSize != 0) { ! 906: Next = (PVOID)((PCHAR)Next + DebugFileHeader->ExportedNamesSize); ! 907: } ! 908: DebugDirectories = (PIMAGE_DEBUG_DIRECTORY)Next; ! 909: DebugDirectory = DebugDirectories; ! 910: NumberOfDebugDirectories = DebugFileHeader->DebugDirectorySize / sizeof( IMAGE_DEBUG_DIRECTORY ); ! 911: ! 912: for (i=0; i<NumberOfDebugDirectories; i++) { ! 913: if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_EXCEPTION) { ! 914: FunctionTableSize = DebugDirectory->SizeOfData; ! 915: NumberOfFunctionTableEntries = FunctionTableSize / sizeof( IMAGE_FUNCTION_ENTRY ); ! 916: break; ! 917: } ! 918: ! 919: DebugDirectory += 1; ! 920: } ! 921: ! 922: DebugInfoSize = (DebugInfoSize + 16) & ~15; ! 923: DebugInfoHeaderSize = DebugInfoSize; ! 924: DebugInfoSize += FunctionTableSize; ! 925: } ! 926: ! 927: DebugInfo = VirtualAlloc( NULL, DebugInfoSize, MEM_COMMIT, PAGE_READWRITE ); ! 928: if (DebugInfo == NULL) { ! 929: leave; ! 930: } ! 931: ! 932: DebugInfo->Size = DebugInfoSize; ! 933: DebugInfo->ImageFilePath = (LPSTR)(DebugInfo + 1); ! 934: strcpy( DebugInfo->ImageFilePath, ImageFilePath ); ! 935: Src = strchr( DebugInfo->ImageFilePath, '\0' ); ! 936: while (Src > DebugInfo->ImageFilePath) { ! 937: if (Src[ -1 ] == '\\' || Src[ -1 ] == '/' || Src[ -1 ] == ':') { ! 938: break; ! 939: } ! 940: else { ! 941: Src -= 1; ! 942: } ! 943: } ! 944: DebugInfo->ImageFileName = Src; ! 945: DebugInfo->DebugFilePath = DebugInfo->ImageFilePath; ! 946: if (SeparateSymbols) { ! 947: DebugInfo->DebugFilePath += strlen( DebugInfo->ImageFilePath ) + 1; ! 948: strcpy( DebugInfo->DebugFilePath, DebugFilePath ); ! 949: } ! 950: ! 951: DebugInfo->MappedBase = MappedBase; ! 952: if (SeparateSymbols) { ! 953: DebugInfo->Machine = DebugFileHeader->Machine; ! 954: DebugInfo->Characteristics = DebugFileHeader->Characteristics; ! 955: DebugInfo->TimeDateStamp = DebugFileHeader->TimeDateStamp; ! 956: DebugInfo->CheckSum = DebugFileHeader->CheckSum; ! 957: DebugInfo->ImageBase = DebugFileHeader->ImageBase; ! 958: DebugInfo->SizeOfImage = DebugFileHeader->SizeOfImage; ! 959: DebugInfo->NumberOfSections = DebugFileHeader->NumberOfSections; ! 960: DebugInfo->Sections = (PIMAGE_SECTION_HEADER)(DebugFileHeader + 1); ! 961: Next = (PVOID)(DebugInfo->Sections + DebugInfo->NumberOfSections); ! 962: ! 963: DebugInfo->ExportedNamesSize = DebugFileHeader->ExportedNamesSize; ! 964: if (DebugInfo->ExportedNamesSize) { ! 965: DebugInfo->ExportedNames = (LPSTR)Next; ! 966: Next = (PVOID)((PCHAR)Next + DebugInfo->ExportedNamesSize); ! 967: } ! 968: DebugDirectory = DebugDirectories; ! 969: NumberOfDebugDirectories = DebugFileHeader->DebugDirectorySize / sizeof( IMAGE_DEBUG_DIRECTORY ); ! 970: Next = (PVOID)((PCHAR)Next + DebugFileHeader->DebugDirectorySize); ! 971: for (i=0; i<NumberOfDebugDirectories; i++) { ! 972: if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_EXCEPTION) { ! 973: DebugInfo->NumberOfFunctionTableEntries = NumberOfFunctionTableEntries; ! 974: DebugInfo->FunctionTableEntries = (PIMAGE_FUNCTION_ENTRY) ! 975: ((PCHAR)MappedBase + DebugDirectory->PointerToRawData); ! 976: ! 977: BaseOffset = ImageBase; ! 978: FunctionTable = (PIMAGE_FUNCTION_ENTRY)((ULONG)DebugInfo + DebugInfoHeaderSize); ! 979: memmove( FunctionTable, DebugInfo->FunctionTableEntries, FunctionTableSize ); ! 980: DebugInfo->FunctionTableEntries = FunctionTable; ! 981: DebugInfo->LowestFunctionStartingAddress = (ULONG)0xFFFFFFFF; ! 982: DebugInfo->HighestFunctionEndingAddress = 0; ! 983: for (j=0; j<DebugInfo->NumberOfFunctionTableEntries; j++) { ! 984: FunctionTable->StartingAddress += BaseOffset; ! 985: if (FunctionTable->StartingAddress < DebugInfo->LowestFunctionStartingAddress) { ! 986: DebugInfo->LowestFunctionStartingAddress = FunctionTable->StartingAddress; ! 987: } ! 988: ! 989: FunctionTable->EndingAddress += BaseOffset; ! 990: if (FunctionTable->EndingAddress > DebugInfo->HighestFunctionEndingAddress) { ! 991: DebugInfo->HighestFunctionEndingAddress = FunctionTable->EndingAddress; ! 992: } ! 993: ! 994: FunctionTable->EndOfPrologue += BaseOffset; ! 995: FunctionTable += 1; ! 996: } ! 997: } ! 998: else ! 999: if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO) { ! 1000: DebugInfo->NumberOfFpoTableEntries = ! 1001: DebugDirectory->SizeOfData / sizeof( FPO_DATA ); ! 1002: DebugInfo->FpoTableEntries = (PFPO_DATA) ! 1003: ((PCHAR)MappedBase + DebugDirectory->PointerToRawData); ! 1004: } ! 1005: else ! 1006: if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_COFF) { ! 1007: DebugInfo->SizeOfCoffSymbols = DebugDirectory->SizeOfData; ! 1008: DebugInfo->CoffSymbols = (PIMAGE_COFF_SYMBOLS_HEADER) ! 1009: ((PCHAR)MappedBase + DebugDirectory->PointerToRawData); ! 1010: } ! 1011: ! 1012: DebugDirectory += 1; ! 1013: } ! 1014: } ! 1015: else { ! 1016: DebugInfo->Machine = NtHeaders->FileHeader.Machine; ! 1017: DebugInfo->Characteristics = NtHeaders->FileHeader.Characteristics; ! 1018: DebugInfo->TimeDateStamp = NtHeaders->FileHeader.TimeDateStamp; ! 1019: DebugInfo->CheckSum = NtHeaders->OptionalHeader.CheckSum; ! 1020: DebugInfo->ImageBase = NtHeaders->OptionalHeader.ImageBase; ! 1021: DebugInfo->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage; ! 1022: DebugInfo->NumberOfSections = NtHeaders->FileHeader.NumberOfSections; ! 1023: DebugInfo->Sections = IMAGE_FIRST_SECTION( NtHeaders ); ! 1024: Next = (PVOID)((ULONG)DebugInfo + DebugInfoHeaderSize); ! 1025: ! 1026: DebugInfo->ExportedNamesSize = ExportedNamesSize; ! 1027: if (DebugInfo->ExportedNamesSize) { ! 1028: DebugInfo->ExportedNames = (LPSTR)Next; ! 1029: Next = (PVOID)((LPSTR)Next + ExportedNamesSize); ! 1030: ! 1031: pp = (PULONG)((ULONG)ExportDirectory + ! 1032: (ULONG)ExportDirectory->AddressOfNames - RvaOffset ! 1033: ); ! 1034: ! 1035: Dst = DebugInfo->ExportedNames; ! 1036: for (i=0; i<ExportDirectory->NumberOfNames; i++) { ! 1037: Src = (LPSTR)((ULONG)ExportDirectory + *pp++ - RvaOffset); ! 1038: while (*Dst++ = *Src++) { ! 1039: } ! 1040: } ! 1041: } ! 1042: ! 1043: if (RuntimeFunctionTable != NULL) { ! 1044: BaseOffset = ImageBase - DebugInfo->ImageBase; ! 1045: DebugInfo->FunctionTableEntries = (PIMAGE_FUNCTION_ENTRY)Next; ! 1046: DebugInfo->NumberOfFunctionTableEntries = NumberOfFunctionTableEntries; ! 1047: Next = (PVOID)((LPSTR)Next + FunctionTableSize); ! 1048: ! 1049: DebugInfo->LowestFunctionStartingAddress = (ULONG)0xFFFFFFFF; ! 1050: DebugInfo->HighestFunctionEndingAddress = 0; ! 1051: FunctionTable = DebugInfo->FunctionTableEntries; ! 1052: for (i=0; i<NumberOfFunctionTableEntries; i++) { ! 1053: FunctionTable->StartingAddress = RuntimeFunctionTable->BeginAddress + BaseOffset; ! 1054: if (FunctionTable->StartingAddress < DebugInfo->LowestFunctionStartingAddress) { ! 1055: DebugInfo->LowestFunctionStartingAddress = FunctionTable->StartingAddress; ! 1056: } ! 1057: ! 1058: FunctionTable->EndingAddress = RuntimeFunctionTable->EndAddress + BaseOffset; ! 1059: if (FunctionTable->EndingAddress > DebugInfo->HighestFunctionEndingAddress) { ! 1060: DebugInfo->HighestFunctionEndingAddress = FunctionTable->EndingAddress; ! 1061: } ! 1062: ! 1063: FunctionTable->EndOfPrologue = RuntimeFunctionTable->PrologEndAddress + BaseOffset; ! 1064: RuntimeFunctionTable += 1; ! 1065: FunctionTable += 1; ! 1066: } ! 1067: } ! 1068: ! 1069: DebugDirectory = DebugDirectories; ! 1070: for (i=0; i<NumberOfDebugDirectories; i++) { ! 1071: if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO || ! 1072: ((DebugDirectory->Type == IMAGE_DEBUG_TYPE_COFF) && ! 1073: !(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) ! 1074: ) ! 1075: ) { ! 1076: DebugData = NULL; ! 1077: if (DebugDirectory->AddressOfRawData == 0) { ! 1078: if (SetFilePointer( FileHandle, ! 1079: DebugDirectory->PointerToRawData, ! 1080: NULL, ! 1081: FILE_BEGIN ! 1082: ) == DebugDirectory->PointerToRawData ! 1083: ) { ! 1084: if (ReadFile( FileHandle, ! 1085: Next, ! 1086: DebugDirectory->SizeOfData, ! 1087: &Size, ! 1088: NULL ! 1089: ) && ! 1090: DebugDirectory->SizeOfData == Size ! 1091: ) { ! 1092: DebugData = Next; ! 1093: Next = (PVOID)((LPSTR)Next + Size); ! 1094: } ! 1095: } ! 1096: } ! 1097: else { ! 1098: DebugData = (LPSTR)MappedBase + DebugDirectory->PointerToRawData; ! 1099: Size = DebugDirectory->SizeOfData; ! 1100: } ! 1101: ! 1102: if (DebugData != NULL) { ! 1103: if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FPO) { ! 1104: DebugInfo->FpoTableEntries = DebugData; ! 1105: DebugInfo->NumberOfFpoTableEntries = Size / sizeof( FPO_DATA ); ! 1106: } ! 1107: else { ! 1108: DebugInfo->CoffSymbols = DebugData; ! 1109: DebugInfo->SizeOfCoffSymbols = Size; ! 1110: } ! 1111: } ! 1112: } ! 1113: ! 1114: DebugDirectory += 1; ! 1115: } ! 1116: } ! 1117: } ! 1118: except( EXCEPTION_EXECUTE_HANDLER ) { ! 1119: if (DebugInfo != NULL) { ! 1120: VirtualFree( DebugInfo, 0, MEM_RELEASE ); ! 1121: DebugInfo = NULL; ! 1122: } ! 1123: } ! 1124: } ! 1125: finally { ! 1126: if (DebugInfo == NULL) { ! 1127: if (MappedBase != NULL) { ! 1128: UnmapViewOfFile( MappedBase ); ! 1129: } ! 1130: } ! 1131: ! 1132: while (NumberOfHandlesToClose--) { ! 1133: CloseHandle( HandlesToClose[ NumberOfHandlesToClose ] ); ! 1134: } ! 1135: } ! 1136: ! 1137: return DebugInfo; ! 1138: } ! 1139: ! 1140: ! 1141: BOOL ! 1142: UnmapDebugInformation( ! 1143: PIMAGE_DEBUG_INFORMATION DebugInfo ! 1144: ) ! 1145: { ! 1146: if (DebugInfo != NULL) { ! 1147: try { ! 1148: UnmapViewOfFile( DebugInfo->MappedBase ); ! 1149: memset( DebugInfo, 0, sizeof( *DebugInfo ) ); ! 1150: VirtualFree( DebugInfo, 0, MEM_RELEASE ); ! 1151: } ! 1152: except( EXCEPTION_EXECUTE_HANDLER ) { ! 1153: return FALSE; ! 1154: } ! 1155: } ! 1156: ! 1157: return TRUE; ! 1158: } ! 1159: ! 1160: HANDLE ! 1161: FindExecutableImage( ! 1162: LPSTR FileName, ! 1163: LPSTR SymbolPath, ! 1164: LPSTR ImageFilePath ! 1165: ) ! 1166: { ! 1167: LPSTR Start, End; ! 1168: HANDLE FileHandle; ! 1169: UCHAR DirectoryPath[ MAX_PATH ]; ! 1170: ! 1171: Start = SymbolPath; ! 1172: while (Start && *Start != '\0') { ! 1173: if (End = strchr( Start, ';' )) { ! 1174: strncpy( DirectoryPath, Start, End - Start ); ! 1175: DirectoryPath[ End - Start ] = '\0'; ! 1176: End += 1; ! 1177: } ! 1178: else { ! 1179: strcpy( DirectoryPath, Start ); ! 1180: } ! 1181: ! 1182: if (SearchTreeForFile( DirectoryPath, FileName, ImageFilePath )) { ! 1183: FileHandle = CreateFile( ImageFilePath, ! 1184: GENERIC_READ, ! 1185: FILE_SHARE_READ | FILE_SHARE_WRITE, ! 1186: NULL, ! 1187: OPEN_EXISTING, ! 1188: 0, ! 1189: NULL ! 1190: ); ! 1191: if (FileHandle != INVALID_HANDLE_VALUE) { ! 1192: return FileHandle; ! 1193: } ! 1194: } ! 1195: ! 1196: Start = End; ! 1197: } ! 1198: ! 1199: return NULL; ! 1200: } ! 1201: ! 1202: ! 1203: HANDLE ! 1204: FindDebugInfoFile( ! 1205: LPSTR FileName, ! 1206: LPSTR SymbolPath, ! 1207: LPSTR DebugFilePath ! 1208: ) ! 1209: { ! 1210: HANDLE FileHandle; ! 1211: LPSTR s; ! 1212: LPSTR Start, End; ! 1213: UCHAR BaseName[ MAX_PATH ]; ! 1214: DWORD n; ! 1215: ! 1216: if (!(s = strrchr( FileName, '.' )) || stricmp( s, ".DBG" )) { ! 1217: if (s != NULL) { ! 1218: strcpy( BaseName, s+1 ); ! 1219: strcat( BaseName, "\\" ); ! 1220: } ! 1221: else { ! 1222: BaseName[ 0 ] = '\0'; ! 1223: } ! 1224: ! 1225: s = FileName + strlen( FileName ); ! 1226: while (s > FileName) { ! 1227: if (*--s == '\\' || *s == '/' || *s == ':') { ! 1228: s += 1; ! 1229: break; ! 1230: } ! 1231: } ! 1232: strcat( BaseName, s ); ! 1233: if (!(s = strrchr( BaseName, '.' ))) { ! 1234: s = strchr( BaseName, '\0' ); ! 1235: } ! 1236: strcpy( s, ".DBG" ); ! 1237: } ! 1238: else { ! 1239: strcpy( BaseName, FileName ); ! 1240: } ! 1241: ! 1242: Start = SymbolPath; ! 1243: while (Start && *Start != '\0') { ! 1244: if (End = strchr( Start, ';' )) { ! 1245: *End = '\0'; ! 1246: } ! 1247: ! 1248: n = GetFullPathName( Start, MAX_PATH, DebugFilePath, &s ); ! 1249: if (End) { ! 1250: *End++ = ';'; ! 1251: } ! 1252: Start = End; ! 1253: if (n == 0) { ! 1254: continue; ! 1255: } ! 1256: ! 1257: if (s != NULL && !stricmp( s, "Symbols" )) { ! 1258: strcat( DebugFilePath, "\\" ); ! 1259: } ! 1260: else { ! 1261: strcat( DebugFilePath, "\\Symbols\\" ); ! 1262: } ! 1263: strcat( DebugFilePath, BaseName ); ! 1264: ! 1265: FileHandle = CreateFile( DebugFilePath, ! 1266: GENERIC_READ, ! 1267: FILE_SHARE_READ | FILE_SHARE_WRITE, ! 1268: NULL, ! 1269: OPEN_EXISTING, ! 1270: 0, ! 1271: NULL ! 1272: ); ! 1273: if (FileHandle != INVALID_HANDLE_VALUE) { ! 1274: return FileHandle; ! 1275: } ! 1276: } ! 1277: ! 1278: return NULL; ! 1279: } ! 1280: ! 1281: BOOL ! 1282: GetImageNameFromMiscDebugData( ! 1283: HANDLE FileHandle, ! 1284: PVOID MappedBase, ! 1285: PIMAGE_NT_HEADERS NtHeaders, ! 1286: PIMAGE_DEBUG_DIRECTORY DebugDirectories, ! 1287: ULONG NumberOfDebugDirectories, ! 1288: LPSTR ImageFilePath ! 1289: ) ! 1290: { ! 1291: IMAGE_DEBUG_MISC TempMiscData; ! 1292: PIMAGE_DEBUG_MISC DebugMiscData; ! 1293: ULONG BytesToRead, BytesRead; ! 1294: BOOLEAN FoundImageName; ! 1295: LPSTR ImageName; ! 1296: ! 1297: while (NumberOfDebugDirectories) { ! 1298: if (DebugDirectories->Type == IMAGE_DEBUG_TYPE_MISC) { ! 1299: break; ! 1300: } ! 1301: else { ! 1302: DebugDirectories += 1; ! 1303: NumberOfDebugDirectories -= 1; ! 1304: } ! 1305: } ! 1306: ! 1307: if (NumberOfDebugDirectories == 0) { ! 1308: return FALSE; ! 1309: } ! 1310: ! 1311: if (NtHeaders->OptionalHeader.MinorLinkerVersion < 36) { ! 1312: BytesToRead = FIELD_OFFSET( IMAGE_DEBUG_MISC, Reserved ); ! 1313: } ! 1314: else { ! 1315: BytesToRead = FIELD_OFFSET( IMAGE_DEBUG_MISC, Data ); ! 1316: } ! 1317: ! 1318: DebugMiscData = NULL; ! 1319: if (DebugDirectories->AddressOfRawData == 0) { ! 1320: if (SetFilePointer( FileHandle, ! 1321: DebugDirectories->PointerToRawData, ! 1322: NULL, ! 1323: FILE_BEGIN ! 1324: ) == DebugDirectories->PointerToRawData ! 1325: ) { ! 1326: if (ReadFile( FileHandle, ! 1327: &TempMiscData, ! 1328: BytesToRead, ! 1329: &BytesRead, ! 1330: NULL ! 1331: ) && ! 1332: BytesRead == BytesToRead ! 1333: ) { ! 1334: DebugMiscData = &TempMiscData; ! 1335: } ! 1336: } ! 1337: } ! 1338: else { ! 1339: DebugMiscData = (PIMAGE_DEBUG_MISC)((PCHAR)MappedBase + ! 1340: DebugDirectories->PointerToRawData ! 1341: ); ! 1342: } ! 1343: ! 1344: FoundImageName = FALSE; ! 1345: if (DebugMiscData != NULL && DebugMiscData->DataType == IMAGE_DEBUG_MISC_EXENAME) { ! 1346: if (DebugMiscData == &TempMiscData) { ! 1347: BytesToRead = DebugMiscData->Length - BytesToRead; ! 1348: if (ReadFile( FileHandle, ! 1349: ImageFilePath, ! 1350: BytesToRead, ! 1351: &BytesRead, ! 1352: NULL ! 1353: ) && ! 1354: BytesRead == BytesToRead ! 1355: ) { ! 1356: FoundImageName = TRUE; ! 1357: } ! 1358: } ! 1359: else { ! 1360: ImageName = (PCHAR)DebugMiscData + BytesToRead; ! 1361: BytesToRead = DebugMiscData->Length - BytesToRead; ! 1362: if (*ImageName != '\0' ) { ! 1363: memcpy( ImageFilePath, ImageName, BytesToRead ); ! 1364: FoundImageName = TRUE; ! 1365: } ! 1366: } ! 1367: } ! 1368: ! 1369: return FoundImageName; ! 1370: } ! 1371: ! 1372: ! 1373: ! 1374: #define MAX_DEPTH 32 ! 1375: ! 1376: BOOL ! 1377: SearchTreeForFile( ! 1378: LPSTR RootPath, ! 1379: LPSTR InputPathName, ! 1380: LPSTR OutputPathBuffer ! 1381: ) ! 1382: { ! 1383: PCHAR FileName; ! 1384: PUCHAR Prefix = ""; ! 1385: CHAR PathBuffer[ MAX_PATH ]; ! 1386: ULONG Depth; ! 1387: PCHAR PathTail[ MAX_DEPTH ]; ! 1388: PCHAR FindHandle[ MAX_DEPTH ]; ! 1389: LPWIN32_FIND_DATA FindFileData; ! 1390: UCHAR FindFileBuffer[ MAX_PATH + sizeof( WIN32_FIND_DATA ) ]; ! 1391: BOOL Result; ! 1392: ! 1393: strcpy( PathBuffer, RootPath ); ! 1394: FileName = InputPathName; ! 1395: while (*InputPathName) { ! 1396: if (*InputPathName == ':' || *InputPathName == '\\' || *InputPathName == '/') { ! 1397: FileName = ++InputPathName; ! 1398: } ! 1399: else { ! 1400: InputPathName++; ! 1401: } ! 1402: } ! 1403: FindFileData = (LPWIN32_FIND_DATA)FindFileBuffer; ! 1404: Depth = 0; ! 1405: Result = FALSE; ! 1406: while (TRUE) { ! 1407: startDirectorySearch: ! 1408: PathTail[ Depth ] = strchr( PathBuffer, '\0' ); ! 1409: if (PathTail[ Depth ] > PathBuffer && PathTail[ Depth ][ -1 ] != '\\') { ! 1410: *(PathTail[ Depth ])++ = '\\'; ! 1411: } ! 1412: ! 1413: strcpy( PathTail[ Depth ], "*.*" ); ! 1414: FindHandle[ Depth ] = FindFirstFile( PathBuffer, FindFileData ); ! 1415: if (FindHandle[ Depth ] != INVALID_HANDLE_VALUE) { ! 1416: do { ! 1417: if (FindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { ! 1418: if (strcmp( FindFileData->cFileName, "." ) && ! 1419: strcmp( FindFileData->cFileName, ".." ) && ! 1420: Depth < MAX_DEPTH ! 1421: ) { ! 1422: sprintf( PathTail[ Depth ], "%s\\", FindFileData->cFileName ); ! 1423: Depth++; ! 1424: goto startDirectorySearch; ! 1425: } ! 1426: } ! 1427: else ! 1428: if (!stricmp( FindFileData->cFileName, FileName )) { ! 1429: strcpy( PathTail[ Depth ], FindFileData->cFileName ); ! 1430: strcpy( OutputPathBuffer, PathBuffer ); ! 1431: Result = TRUE; ! 1432: } ! 1433: ! 1434: restartDirectorySearch: ! 1435: if (Result) { ! 1436: break; ! 1437: } ! 1438: } ! 1439: while (FindNextFile( FindHandle[ Depth ], FindFileData )); ! 1440: FindClose( FindHandle[ Depth ] ); ! 1441: ! 1442: if (Depth == 0) { ! 1443: break; ! 1444: } ! 1445: ! 1446: Depth--; ! 1447: goto restartDirectorySearch; ! 1448: } ! 1449: } ! 1450: ! 1451: return Result; ! 1452: } ! 1453: ! 1454: ! 1455: BOOL ! 1456: MakeSureDirectoryPathExists( ! 1457: LPSTR DirPath ! 1458: ) ! 1459: { ! 1460: LPSTR Dir,p; ! 1461: DWORD dw; ! 1462: ! 1463: Dir = DirPath; ! 1464: p = Dir+1; ! 1465: ! 1466: // ! 1467: // If the second character in the path is "\", then this is a UNC ! 1468: // path, and we should skip forward until we reach the 2nd \ in the ! 1469: // path. ! 1470: // ! 1471: if (*p == '\\') { ! 1472: p++; // Skip over the second \ in the name. ! 1473: ! 1474: // ! 1475: // Skip until we hit the first "\" (\\Server\). ! 1476: // ! 1477: ! 1478: while (*p && *p != '\\') { ! 1479: p++; ! 1480: } ! 1481: ! 1482: if (*p) { ! 1483: *p++; ! 1484: } ! 1485: ! 1486: // ! 1487: // Skip until we hit the second "\" (\\Server\Share\). ! 1488: // ! 1489: ! 1490: while (*p && *p != '\\') { ! 1491: p++; ! 1492: } ! 1493: ! 1494: // ! 1495: // The directory to check is the "path" part of \\Server\Share\path ! 1496: // ! 1497: ! 1498: if (*p) { ! 1499: Dir = p-1; ! 1500: } ! 1501: } ! 1502: else if (*p == ':' ) { ! 1503: p++; ! 1504: p++; ! 1505: } ! 1506: ! 1507: while( *p ) { ! 1508: if ( *p == '\\' ) { ! 1509: *p = '\0'; ! 1510: dw = GetFileAttributes(DirPath); ! 1511: if ( dw == 0xffffffff || dw & FILE_ATTRIBUTE_DIRECTORY != FILE_ATTRIBUTE_DIRECTORY ) { ! 1512: if ( dw == 0xffffffff ) { ! 1513: if ( !CreateDirectory(DirPath,NULL) ) { ! 1514: return FALSE; ! 1515: } ! 1516: } ! 1517: } ! 1518: ! 1519: *p = '\\'; ! 1520: } ! 1521: p++; ! 1522: } ! 1523: ! 1524: return TRUE; ! 1525: } ! 1526: ! 1527: ! 1528: BOOL ! 1529: UpdateDebugInfoFile( ! 1530: LPSTR ImageFileName, ! 1531: LPSTR SymbolPath, ! 1532: LPSTR DebugFilePath, ! 1533: PIMAGE_NT_HEADERS NtHeaders ! 1534: ) ! 1535: { ! 1536: HANDLE hDebugFile, hMappedFile; ! 1537: PVOID MappedAddress; ! 1538: PIMAGE_SEPARATE_DEBUG_HEADER DbgFileHeader; ! 1539: ! 1540: hDebugFile = FindDebugInfoFile( ! 1541: ImageFileName, ! 1542: SymbolPath, ! 1543: DebugFilePath ! 1544: ); ! 1545: if ( hDebugFile == NULL ) { ! 1546: return FALSE; ! 1547: } ! 1548: CloseHandle(hDebugFile); ! 1549: ! 1550: hDebugFile = CreateFile( DebugFilePath, ! 1551: GENERIC_READ | GENERIC_WRITE, ! 1552: FILE_SHARE_READ | FILE_SHARE_WRITE, ! 1553: NULL, ! 1554: OPEN_EXISTING, ! 1555: 0, ! 1556: NULL ! 1557: ); ! 1558: if ( hDebugFile == INVALID_HANDLE_VALUE ) { ! 1559: return FALSE; ! 1560: } ! 1561: ! 1562: hMappedFile = CreateFileMapping( ! 1563: hDebugFile, ! 1564: NULL, ! 1565: PAGE_READWRITE, ! 1566: 0, ! 1567: 0, ! 1568: NULL ! 1569: ); ! 1570: if ( !hMappedFile ) { ! 1571: CloseHandle(hDebugFile); ! 1572: return FALSE; ! 1573: } ! 1574: ! 1575: MappedAddress = MapViewOfFile(hMappedFile, ! 1576: FILE_MAP_WRITE, ! 1577: 0, ! 1578: 0, ! 1579: 0 ! 1580: ); ! 1581: CloseHandle(hMappedFile); ! 1582: if ( !MappedAddress ) { ! 1583: CloseHandle(hDebugFile); ! 1584: return FALSE; ! 1585: } ! 1586: ! 1587: DbgFileHeader = (PIMAGE_SEPARATE_DEBUG_HEADER)MappedAddress; ! 1588: if (DbgFileHeader->ImageBase != NtHeaders->OptionalHeader.ImageBase || ! 1589: DbgFileHeader->CheckSum != NtHeaders->OptionalHeader.CheckSum ! 1590: ) { ! 1591: DbgFileHeader->ImageBase = NtHeaders->OptionalHeader.ImageBase; ! 1592: DbgFileHeader->CheckSum = NtHeaders->OptionalHeader.CheckSum; ! 1593: UnmapViewOfFile(MappedAddress); ! 1594: FlushViewOfFile(MappedAddress,0); ! 1595: TouchFileTimes(hDebugFile,NULL); ! 1596: CloseHandle(hDebugFile); ! 1597: return TRUE; ! 1598: } ! 1599: else { ! 1600: UnmapViewOfFile(MappedAddress); ! 1601: FlushViewOfFile(MappedAddress,0); ! 1602: CloseHandle(hDebugFile); ! 1603: return FALSE; ! 1604: } ! 1605: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.