|
|
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.