|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 Microsoft Corporation
4:
5: Module Name:
6:
7: module.c
8:
9: Abstract:
10:
11: This file implements the module load debug events.
12:
13: Author:
14:
15: Wesley Witt (wesw) 1-May-1993
16:
17: Environment:
18:
19: User Mode
20:
21: --*/
22:
23: #include <windows.h>
24: #include <stdlib.h>
25: #include <stdio.h>
26: #include <string.h>
27:
28: #include "drwatson.h"
29: #include "proto.h"
30: #include "messages.h"
31:
32: //
33: // defines for symbol (.dbg) file searching
34: //
35: #define SYMBOL_PATH "_NT_SYMBOL_PATH"
36: #define ALTERNATE_SYMBOL_PATH "_NT_ALT_SYMBOL_PATH"
37:
38: //
39: // local prototypes
40: //
41: void ExtractDebugInfoFromImage( PMODULEINFO mi );
42: LPSTR GetSymbolSearchPath( void );
43: BOOL NormalizeFilename( char *szName );
44: HANDLE FindDebugInfoFile( LPSTR FileName, LPSTR SymbolPath, LPSTR DebugFilePath );
45: BOOL SearchTreeForFile(LPSTR RootPath,PCHAR InputPathName,PCHAR OutputPathBuffer);
46: BOOL GetDebugInfoFromDbg( PMODULEINFO mi, PUCHAR fptr );
47: BOOL GetDebugInfoFromExe( PMODULEINFO mi, PUCHAR fptr );
48: PMODULEINFO AllocMi( PDEBUGPACKET dp );
49:
50:
51:
52: BOOL
53: ProcessModuleLoad ( PDEBUGPACKET dp, LPDEBUG_EVENT de )
54:
55: /*++
56:
57: Routine Description:
58:
59: Process all module load debug events, create process & dll load.
60: The purpose is to allocate a MODULEINFO structure, fill in the
61: necessary values, and load the symbol table.
62:
63: Arguments:
64:
65: dp - pointer to a debug packet
66: de - pointer to a debug event structure
67:
68: Return Value:
69:
70: TRUE - everything worked
71: FALSE - we're hosed
72:
73: --*/
74:
75: {
76: HANDLE hFile = NULL;
77: DWORD len = 0;
78: DWORD li = 0;
79: LPSTR lpSymbolPath = NULL;
80: LPSTR DebugFilePath = NULL;
81: PIMAGE_DOS_HEADER dosHdr = NULL;
82: PIMAGE_NT_HEADERS ntHdr = NULL;
83: PIMAGE_FILE_HEADER fileHdr = NULL;
84: PIMAGE_OPTIONAL_HEADER optHdr = NULL;
85: HANDLE hMap = NULL;
86: PUCHAR fptr = NULL;
87: DWORD rva = 0;
88: DWORD i = 0;
89: DWORD numDebugDirs = 0;
90: PIMAGE_DEBUG_DIRECTORY debugDir = NULL;
91: PIMAGE_SECTION_HEADER sh = NULL;
92: PMODULEINFO mi = NULL;
93: DWORD dwSize = 0;
94: PIMAGE_DEBUG_MISC miscData = NULL;
95: LPSTR pExeName = NULL;
96: PIMAGE_DEBUG_DIRECTORY miscDir = NULL;
97: char buf [MAX_PATH];
98:
99:
100: //
101: // allocate a moduleinfo structure
102: //
103: mi = AllocMi( dp );
104: if (mi == NULL) {
105: return FALSE;
106: }
107:
108: //
109: // setup the debug event specific values
110: //
111: if (de->dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) {
112: hFile = de->u.CreateProcessInfo.hFile;
113: dp->hProcess = de->u.CreateProcessInfo.hProcess;
114: dp->dwProcessId = de->dwProcessId;
115: mi->dwLoadAddress = (DWORD)de->u.CreateProcessInfo.lpBaseOfImage;
116: }
117: else
118: if (de->dwDebugEventCode == LOAD_DLL_DEBUG_EVENT) {
119: hFile = de->u.LoadDll.hFile;
120: mi->dwLoadAddress = (DWORD)de->u.LoadDll.lpBaseOfDll;
121: }
122:
123: //
124: // map the input file (exe or dll)
125: //
126: hMap = CreateFileMapping( hFile,
127: NULL,
128: PAGE_READONLY,
129: 0,
130: 0,
131: NULL
132: );
133:
134: if (hMap == INVALID_HANDLE_VALUE) {
135: return FALSE;
136: }
137:
138: fptr = MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, 0 );
139:
140: if (fptr == NULL) {
141: return FALSE;
142: }
143:
144: //
145: // next, setup the pointers to the necessary header for access to the
146: // miscellaneous debug directory
147: //
148: dosHdr = (PIMAGE_DOS_HEADER) fptr;
149: if (dosHdr->e_magic != IMAGE_DOS_SIGNATURE) {
150: return FALSE;
151: }
152: ntHdr = (PIMAGE_NT_HEADERS) ((DWORD)dosHdr->e_lfanew + (DWORD)fptr);
153: fileHdr = &ntHdr->FileHeader;
154: optHdr = &ntHdr->OptionalHeader;
155:
156: mi->dwImageSize = optHdr->SizeOfImage;
157:
158: if (optHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size > 0) {
159:
160: //
161: // find the section header that contains the debug directories
162: //
163: rva = optHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
164:
165: numDebugDirs = optHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size /
166: sizeof(IMAGE_DEBUG_DIRECTORY);
167:
168: sh = IMAGE_FIRST_SECTION( ntHdr );
169:
170: for (li=0; li<ntHdr->FileHeader.NumberOfSections; li++, sh++) {
171: if (rva >= sh->VirtualAddress &&
172: rva < sh->VirtualAddress+sh->SizeOfRawData) {
173: break;
174: }
175: }
176:
177: //
178: // set the debugdir pointer to the first debug directory
179: //
180: debugDir = (PIMAGE_DEBUG_DIRECTORY) ( rva - sh->VirtualAddress +
181: sh->PointerToRawData +
182: fptr
183: );
184:
185: //
186: // cruise thru all of the debug directories looking for the
187: // miscellaneous debug directory
188: //
189: for (li=0; li<numDebugDirs; li++, debugDir++) {
190: switch(debugDir->Type) {
191: case IMAGE_DEBUG_TYPE_FPO:
192: LoadFpoData( mi,
193: (PFPO_DATA)(debugDir->PointerToRawData + fptr),
194: debugDir->SizeOfData
195: );
196: break;
197:
198: case IMAGE_DEBUG_TYPE_MISC:
199: //
200: // now, look for the data type containing the image name
201: //
202: miscData = (PIMAGE_DEBUG_MISC) (debugDir->PointerToRawData +
203: (DWORD)fptr);
204: li = debugDir->SizeOfData;
205: do {
206: if (miscData->DataType == IMAGE_DEBUG_MISC_EXENAME) {
207: strcpy( mi->szName, (LPSTR)miscData->Data );
208: break;
209: }
210: li -= miscData->Length;
211: miscData = (PIMAGE_DEBUG_MISC) ( (DWORD)miscData +
212: miscData->Length);
213: } while (li > 0);
214: break;
215:
216: default:
217: break;
218: }
219: }
220: }
221:
222: //
223: // now find the pdata table, if there is one
224: // this is mips only, but it's ok to do it in this function
225: // because there won't be a pdata section on x86.
226: //
227: sh = IMAGE_FIRST_SECTION( ntHdr );
228:
229: for (i=0; i<fileHdr->NumberOfSections; i++, sh++) {
230: if (strcmp(".pdata", sh->Name) == 0){
231: LoadExceptionData( mi,
232: (PRUNTIME_FUNCTION)(sh->PointerToRawData+fptr),
233: sh->SizeOfRawData
234: );
235: break;
236: }
237: }
238:
239: if (ntHdr->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) {
240:
241: //
242: // the characteristics are marked as having the symbols stripped
243: // so we must close the file handles and locate the .dbg file
244: //
245: CloseHandle( hMap );
246: CloseHandle( hFile );
247:
248: //
249: // get the path to use for searching for the .dbg file
250: //
251: lpSymbolPath = GetSymbolSearchPath();
252:
253: //
254: // find the .dbg file and open it
255: //
256: buf[0] = '\0';
257: hFile = FindDebugInfoFile( mi->szName, lpSymbolPath, buf );
258:
259: if (hFile == NULL) {
260: lprintf( MSG_CANT_ACCESS_IMAGE, mi->szName );
261: return FALSE;
262: }
263:
264: //
265: // map the .dbg file
266: //
267: hMap = CreateFileMapping( hFile,
268: NULL,
269: PAGE_READONLY,
270: 0,
271: 0,
272: NULL
273: );
274:
275: if (hMap == INVALID_HANDLE_VALUE) {
276: return FALSE;
277: }
278:
279: fptr = MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, 0 );
280:
281: if (fptr == NULL) {
282: return FALSE;
283: }
284:
285: //
286: // get the debug information from the exe file
287: //
288: if (!GetDebugInfoFromDbg( mi, fptr )) {
289: return FALSE;
290: }
291: }
292: else {
293: //
294: // get the debug information from the dbg file
295: //
296: if (!GetDebugInfoFromExe( mi, fptr )) {
297: return FALSE;
298: }
299: }
300:
301: //
302: // close all file handles
303: //
304: CloseHandle( hMap );
305: CloseHandle( hFile );
306:
307: if (mi->szName[0] == 0) {
308: //
309: // we could not the image name so use the default
310: //
311: if (de->dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) {
312: dwSize = sizeof(mi->szName);
313: GetTaskName( de->dwProcessId, mi->szName, &dwSize );
314: }
315: else
316: if (de->dwDebugEventCode == LOAD_DLL_DEBUG_EVENT) {
317: strcpy( mi->szName, "app.dll" );
318: }
319: }
320: else {
321: //
322: // put the path name & drive in the file name
323: //
324: NormalizeFilename( mi->szName );
325: }
326:
327: return TRUE;
328: }
329:
330: BOOL
331: GetDebugInfoFromExe( PMODULEINFO mi, PUCHAR fptr )
332:
333: /*++
334:
335: Routine Description:
336:
337: Loads all of the appropriate debug information from an EXE/DLL file.
338:
339: Arguments:
340:
341: mi - pointer to a module information structure
342: fptr - base address of the EXE/DLL file
343:
344: Return Value:
345:
346: TRUE - everything worked
347: FALSE - we're hosed
348:
349: --*/
350:
351: {
352: DWORD i = 0;
353: DWORD li = 0;
354: DWORD rva = 0;
355: DWORD numDebugDirs = 0;
356: PIMAGE_DEBUG_DIRECTORY debugDir = NULL;
357: PIMAGE_SECTION_HEADER sh = NULL;
358: PIMAGE_DOS_HEADER dosHdr = NULL;
359: PIMAGE_NT_HEADERS ntHdr = NULL;
360: PIMAGE_FILE_HEADER fileHdr = NULL;
361: PIMAGE_OPTIONAL_HEADER optHdr = NULL;
362: PUCHAR stringTable = NULL;
363: PIMAGE_SYMBOL allSymbols = NULL;
364: PIMAGE_DEBUG_DIRECTORY coffDir = NULL;
365: PIMAGE_DEBUG_DIRECTORY cvDir = NULL;
366: PIMAGE_EXPORT_DIRECTORY exportDir = NULL;
367: PUCHAR exportName = NULL;
368:
369:
370: //
371: // setup the image header pointers
372: //
373: dosHdr = (PIMAGE_DOS_HEADER) fptr;
374: if (dosHdr->e_magic != IMAGE_DOS_SIGNATURE) {
375: return FALSE;
376: }
377:
378: ntHdr = (PIMAGE_NT_HEADERS) ((DWORD)dosHdr->e_lfanew + (DWORD)fptr);
379: fileHdr = &ntHdr->FileHeader;
380: optHdr = &ntHdr->OptionalHeader;
381:
382: mi->dwImageSize = optHdr->SizeOfImage;
383:
384: if (!(fileHdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) {
385: return FALSE;
386: }
387:
388: //
389: // establish the COFF symbol table pointers
390: //
391: if (fileHdr->PointerToSymbolTable > 0 || fileHdr->NumberOfSymbols > 0) {
392: stringTable = fileHdr->PointerToSymbolTable + fptr +
393: (IMAGE_SIZEOF_SYMBOL * fileHdr->NumberOfSymbols);
394: allSymbols = (PIMAGE_SYMBOL) (fileHdr->PointerToSymbolTable + fptr);
395: }
396:
397: if (optHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size > 0) {
398:
399: //
400: // find the section header that the debug directories are in
401: //
402: rva = optHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
403:
404: numDebugDirs = optHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size /
405: sizeof(IMAGE_DEBUG_DIRECTORY);
406: if (numDebugDirs == 0) {
407: return FALSE;
408: }
409:
410: sh = IMAGE_FIRST_SECTION( ntHdr );
411:
412: for (i=0; i<fileHdr->NumberOfSections; i++, sh++) {
413: if (rva >= sh->VirtualAddress &&
414: rva < sh->VirtualAddress+sh->SizeOfRawData) {
415: break;
416: }
417: }
418:
419: debugDir = (PIMAGE_DEBUG_DIRECTORY) ( rva - sh->VirtualAddress +
420: sh->PointerToRawData +
421: fptr
422: );
423:
424: //
425: // process each debug directory
426: //
427: for (li=0; li<numDebugDirs; li++, debugDir++) {
428: switch(debugDir->Type) {
429: case IMAGE_DEBUG_TYPE_COFF:
430: coffDir = debugDir;
431: break;
432:
433: case IMAGE_DEBUG_TYPE_CODEVIEW:
434: cvDir = debugDir;
435: break;
436:
437: case IMAGE_DEBUG_TYPE_FPO:
438: LoadFpoData( mi,
439: (PFPO_DATA)(debugDir->PointerToRawData + fptr),
440: debugDir->SizeOfData
441: );
442: break;
443:
444: default:
445: break;
446: }
447: }
448:
449: if (cvDir != NULL) {
450: LoadCodeViewSymbols( mi,
451: cvDir->PointerToRawData + fptr,
452: IMAGE_FIRST_SECTION( ntHdr ),
453: fileHdr->NumberOfSections
454: );
455: }
456: else
457: if (coffDir != NULL) {
458: LoadCoffSymbols( mi,
459: stringTable,
460: allSymbols,
461: fileHdr->NumberOfSymbols
462: );
463: }
464: }
465:
466: //
467: // now find the exports table, if there is one
468: //
469: rva = optHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
470:
471: sh = IMAGE_FIRST_SECTION( ntHdr );
472:
473: //
474: // Find the section the where the export table is located in
475: //
476: for (i=0; i<fileHdr->NumberOfSections; i++, sh++) {
477: if (rva >= sh->VirtualAddress &&
478: rva < sh->VirtualAddress+sh->SizeOfRawData) {
479: break;
480: }
481: }
482:
483: //
484: // is there an export table ?
485: //
486: if (i != fileHdr->NumberOfSections) {
487: exportDir = (PIMAGE_EXPORT_DIRECTORY) ( rva -
488: (DWORD)sh->VirtualAddress +
489: sh->PointerToRawData +
490: (DWORD)fptr );
491:
492: exportName = (PUCHAR) ( exportDir->Name -
493: (DWORD)sh->VirtualAddress +
494: sh->PointerToRawData +
495: (DWORD)fptr );
496:
497: if (mi->szName[0] == '\0') {
498: strcpy( mi->szName, exportName );
499: }
500: }
501:
502: return TRUE;
503: }
504:
505: BOOL
506: GetDebugInfoFromDbg( PMODULEINFO mi, PUCHAR fptr )
507:
508: /*++
509:
510: Routine Description:
511:
512: Loads all of the appropriate debug information from a DBG file.
513:
514: Arguments:
515:
516: mi - pointer to a module information structure
517: fptr - base address of the EXE/DLL file
518:
519: Return Value:
520:
521: TRUE - everything worked
522: FALSE - we're hosed
523:
524: --*/
525:
526: {
527: DWORD li = 0;
528: DWORD numDebugDirs = 0;
529: PIMAGE_DEBUG_DIRECTORY debugDir = NULL;
530: PIMAGE_SECTION_HEADER sh = NULL;
531: PIMAGE_SEPARATE_DEBUG_HEADER sdh = NULL;
532: PIMAGE_COFF_SYMBOLS_HEADER coffSymHead = NULL;
533: PUCHAR stringTable = NULL;
534: PIMAGE_SYMBOL allSymbols = NULL;
535: PIMAGE_DEBUG_DIRECTORY coffDir = NULL;
536: PIMAGE_DEBUG_DIRECTORY cvDir = NULL;
537:
538:
539: //
540: // setup the basic image pointers
541: //
542: sdh = (PIMAGE_SEPARATE_DEBUG_HEADER) fptr;
543: sh = (PIMAGE_SECTION_HEADER) (sdh + 1);
544: debugDir = (PIMAGE_DEBUG_DIRECTORY)((DWORD)((DWORD)sh + (sdh->NumberOfSections*IMAGE_SIZEOF_SECTION_HEADER)) + sdh->ExportedNamesSize);
545:
546: mi->dwImageSize = sdh->SizeOfImage;
547:
548: if (sdh->DebugDirectorySize > 0) {
549:
550: //
551: // process each debug directory
552: //
553: numDebugDirs = sdh->DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY);
554: if (numDebugDirs == 0) {
555: return FALSE;
556: }
557:
558: for (li=0; li<numDebugDirs; li++, debugDir++) {
559: switch(debugDir->Type) {
560: case IMAGE_DEBUG_TYPE_COFF:
561: coffDir = debugDir;
562: break;
563:
564: case IMAGE_DEBUG_TYPE_CODEVIEW:
565: cvDir = debugDir;
566: break;
567:
568: case IMAGE_DEBUG_TYPE_FPO:
569: LoadFpoData( mi,
570: (PFPO_DATA)(debugDir->PointerToRawData + fptr),
571: debugDir->SizeOfData
572: );
573: break;
574:
575: case IMAGE_DEBUG_TYPE_EXCEPTION:
576: if (debugDir->SizeOfData > 0) {
577: LoadExceptionData( mi,
578: (PRUNTIME_FUNCTION)(debugDir->PointerToRawData+fptr),
579: debugDir->SizeOfData );
580: }
581: break;
582:
583: default:
584: break;
585: }
586: }
587: }
588:
589: if (cvDir != NULL) {
590: LoadCodeViewSymbols( mi,
591: cvDir->PointerToRawData + fptr,
592: sh,
593: sdh->NumberOfSections
594: );
595: }
596: else
597: if (coffDir != NULL) {
598: //
599: // setup the COFF symbol table pointers & load the COFF symbol table
600: //
601: coffSymHead = (PIMAGE_COFF_SYMBOLS_HEADER)(coffDir->PointerToRawData + fptr);
602: allSymbols = (PIMAGE_SYMBOL) ( (DWORD)coffSymHead +
603: coffSymHead->LvaToFirstSymbol
604: );
605: stringTable = (PUCHAR)((DWORD)allSymbols +
606: (IMAGE_SIZEOF_SYMBOL * coffSymHead->NumberOfSymbols));
607: LoadCoffSymbols( mi,
608: stringTable,
609: allSymbols,
610: coffSymHead->NumberOfSymbols
611: );
612: }
613:
614: return TRUE;
615: }
616:
617: LPSTR
618: GetSymbolSearchPath( void )
619:
620: /*++
621:
622: Routine Description:
623:
624: Gets the search path to be used for locating a .DBG file.
625:
626: Arguments:
627:
628: None.
629:
630: Return Value:
631:
632: pointer to the path string
633:
634: --*/
635:
636: {
637: LPSTR lpSymPathEnv = NULL;
638: LPSTR lpAltSymPathEnv = NULL;
639: LPSTR lpSystemRootEnv = NULL;
640: LPSTR SymbolSearchPath = NULL;
641: DWORD cbSymPath = 0;
642:
643: cbSymPath = 16;
644: if (lpSymPathEnv = getenv(SYMBOL_PATH)) {
645: cbSymPath += strlen(lpSymPathEnv) + 1;
646: }
647: if (lpAltSymPathEnv = getenv(ALTERNATE_SYMBOL_PATH)) {
648: cbSymPath += strlen(lpAltSymPathEnv) + 1;
649: }
650: if (lpSystemRootEnv = getenv("SystemRoot")) {
651: cbSymPath += strlen(lpSystemRootEnv) + 1;
652: }
653:
654: SymbolSearchPath = calloc(cbSymPath,1);
655:
656: if (lpAltSymPathEnv) {
657: strcat(SymbolSearchPath,lpAltSymPathEnv);
658: strcat(SymbolSearchPath,";");
659: }
660: if (lpSymPathEnv) {
661: strcat(SymbolSearchPath,lpSymPathEnv);
662: strcat(SymbolSearchPath,";");
663: }
664: if (lpSystemRootEnv) {
665: strcat(SymbolSearchPath,lpSystemRootEnv);
666: strcat(SymbolSearchPath,";");
667: }
668: return SymbolSearchPath;
669: }
670:
671: BOOL
672: NormalizeFilename( char *szName )
673:
674: /*++
675:
676: Routine Description:
677:
678: Prefixes the base name passed in by szName with the fully qualified
679: path name of the file.
680:
681: Arguments:
682:
683: szName - buffer for the file name
684:
685: Return Value:
686:
687: TRUE - file name contains the path & base name
688: FALSE - file name contains the base name only
689:
690: --*/
691:
692: {
693: DWORD rc = 0;
694: LPSTR lpszFilePart = NULL;
695: char szDrive [_MAX_DRIVE];
696: char szDir [_MAX_DIR];
697: char szFname [_MAX_FNAME];
698: char szExt [_MAX_EXT];
699: char buf [4096];
700: char szFullPath [4096];
701:
702:
703: //
704: // split the filename apart
705: //
706: _splitpath( szName, szDrive, szDir, szFname, szExt );
707:
708: //
709: // create a base file name excluding any possible path
710: //
711: wsprintf( buf, "%s%s", szFname, szExt );
712:
713: //
714: // create a full path name to the file based on our current
715: // working directory. this is done so that we can check the
716: // current directory before looking along the path env variable.
717: //
718: _fullpath( szFullPath, buf, sizeof(szFullPath) );
719:
720: //
721: // split the path apart so the constituent parts can be used
722: // by the next call to searchpath
723: //
724: _splitpath( szFullPath, szDrive, szDir, szFname, szExt );
725:
726: //
727: // look in the current working directory for the file
728: //
729: rc = SearchPath( szDir, szFname, szExt, sizeof(buf), buf, &lpszFilePart );
730: if (rc > 0) {
731: //
732: // found it so copy the filename and exit
733: //
734: strcpy( szName, buf );
735: return TRUE;
736: }
737:
738: //
739: // now look along the path environment variable for the filename
740: //
741: rc = SearchPath( NULL, szFname, szExt, sizeof(buf), buf, &lpszFilePart );
742: if (rc > 0) {
743: //
744: // found it so copy the filename and exit
745: //
746: strcpy( szName, buf );
747: return TRUE;
748: }
749:
750: //
751: // could not file the file anywhere so create a base filename
752: // and return
753: //
754: wsprintf( szName, "%s%s", szFname, szExt );
755: return FALSE;
756: }
757:
758: HANDLE
759: FindDebugInfoFile( LPSTR FileName, LPSTR SymbolPath, LPSTR DebugFilePath )
760:
761: /*++
762:
763: Routine Description:
764:
765: Locates a .DBG file based on the FileName and the SymbolPath.
766:
767: Arguments:
768:
769: FileName - base EXE/DLL file name
770: SymbolPath - path to search for the .DBG file
771: DebugFilePath - buffer for .DBG file name
772:
773: Return Value:
774:
775: not NULL - a valid handle to a .DBG file
776: NULL - could not find the .DBG file
777:
778: --*/
779:
780: {
781: HANDLE FileHandle;
782: LPSTR s, BaseName, Extension;
783: LPSTR Start, End;
784: UCHAR DirectoryPath[ MAX_PATH ];
785:
786: BaseName = strcpy( DebugFilePath, FileName );
787: BaseName += strlen( BaseName );
788: while (BaseName > DebugFilePath) {
789: if (*--BaseName == '\\' || *BaseName == '/' || *BaseName == ':') {
790: BaseName += 1;
791: break;
792: }
793: }
794: if (!(Extension = strrchr( BaseName, '.' ))) {
795: Extension = strchr( BaseName, '\0' );
796: }
797: strcpy( Extension, ".DBG" );
798: s = BaseName;
799: if (s > DebugFilePath) {
800: s -= 1;
801: }
802:
803: while (TRUE) {
804: FileHandle = CreateFile( DebugFilePath,
805: GENERIC_READ,
806: FILE_SHARE_READ | FILE_SHARE_WRITE,
807: NULL,
808: OPEN_EXISTING,
809: 0,
810: NULL
811: );
812: if (FileHandle != INVALID_HANDLE_VALUE) {
813: return FileHandle;
814: }
815:
816: while (s > DebugFilePath) {
817: if (*--s == '\\' || *s == '/' || *s == ':') {
818: break;
819: }
820: }
821:
822: if (s == DebugFilePath) {
823: break;
824: }
825:
826: strcpy( s, "\\Symbols\\" );
827: strcat( s, BaseName );
828: }
829:
830: Start = SymbolPath;
831: while (Start && *Start != '\0') {
832: if (End = strchr( Start, ';' )) {
833: strncpy( DirectoryPath, Start, End - Start );
834: DirectoryPath[ End - Start ] = '\0';
835: End += 1;
836: }
837: else {
838: strcpy( DirectoryPath, Start );
839: }
840:
841: if (SearchTreeForFile( DirectoryPath, BaseName, DebugFilePath )) {
842: FileHandle = CreateFile( DebugFilePath,
843: GENERIC_READ,
844: FILE_SHARE_READ | FILE_SHARE_WRITE,
845: NULL,
846: OPEN_EXISTING,
847: 0,
848: NULL
849: );
850: if (FileHandle != INVALID_HANDLE_VALUE) {
851: return FileHandle;
852: }
853: }
854:
855: Start = End;
856: }
857:
858: return NULL;
859: }
860:
861: #define MAX_DEPTH 32
862:
863: BOOL
864: SearchTreeForFile(
865: LPSTR RootPath,
866: PCHAR InputPathName,
867: PCHAR OutputPathBuffer
868: )
869:
870: /*++
871:
872: Routine Description:
873:
874: Searches down the path(RootPath) for a file(InputPathName).
875:
876: Arguments:
877:
878: RootPath - path to search down
879: InputPathName - file name to look for
880: OutputPathBuffer - buffer for .DBG file name
881:
882: Return Value:
883:
884: TRUE - file found
885: FALSE - could not find the .DBG file
886:
887: --*/
888:
889: {
890: PCHAR FileName;
891: PUCHAR Prefix = "";
892: CHAR PathBuffer[ MAX_PATH ];
893: ULONG Depth;
894: PCHAR PathTail[ MAX_DEPTH ];
895: PCHAR FindHandle[ MAX_DEPTH ];
896: LPWIN32_FIND_DATA FindFileData;
897: UCHAR FindFileBuffer[ MAX_PATH + sizeof( WIN32_FIND_DATA ) ];
898: BOOL Result;
899:
900: strcpy( PathBuffer, RootPath );
901: FileName = InputPathName;
902: while (*InputPathName) {
903: if (*InputPathName == ':' || *InputPathName == '\\' || *InputPathName == '/') {
904: FileName = ++InputPathName;
905: }
906: else {
907: InputPathName++;
908: }
909: }
910: FindFileData = (LPWIN32_FIND_DATA)FindFileBuffer;
911: Depth = 0;
912: Result = FALSE;
913: while (TRUE) {
914: startDirectorySearch:
915: PathTail[ Depth ] = strchr( PathBuffer, '\0' );
916: if (PathTail[ Depth ] > PathBuffer && PathTail[ Depth ][ -1 ] != '\\') {
917: *(PathTail[ Depth ])++ = '\\';
918: }
919:
920: strcpy( PathTail[ Depth ], "*.*" );
921: FindHandle[ Depth ] = FindFirstFile( PathBuffer, FindFileData );
922: if (FindHandle[ Depth ] != INVALID_HANDLE_VALUE) {
923: do {
924: if (FindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
925: if (strcmp( FindFileData->cFileName, "." ) &&
926: strcmp( FindFileData->cFileName, ".." ) &&
927: Depth < MAX_DEPTH
928: ) {
929: sprintf( PathTail[ Depth ], "%s\\", FindFileData->cFileName );
930: Depth++;
931: goto startDirectorySearch;
932: }
933: }
934: else
935: if (!stricmp( FindFileData->cFileName, FileName )) {
936: strcpy( PathTail[ Depth ], FindFileData->cFileName );
937: strcpy( OutputPathBuffer, PathBuffer );
938: Result = TRUE;
939: }
940:
941: restartDirectorySearch:
942: if (Result) {
943: break;
944: }
945: }
946: while (FindNextFile( FindHandle[ Depth ], FindFileData ));
947: FindClose( FindHandle[ Depth ] );
948:
949: if (Depth == 0) {
950: break;
951: }
952:
953: Depth--;
954: goto restartDirectorySearch;
955: }
956: }
957:
958: return Result;
959: }
960:
961: PMODULEINFO
962: AllocMi( PDEBUGPACKET dp )
963:
964: /*++
965:
966: Routine Description:
967:
968: Allocate a module information structure and link it in the
969: list of modules for this debugee.
970:
971: Arguments:
972:
973: dp - debug packet
974:
975: Return Value:
976:
977: pointer to module information structure
978:
979: --*/
980:
981: {
982: PMODULEINFO mi;
983:
984: mi = (PMODULEINFO) malloc( sizeof(MODULEINFO) );
985: if (mi == NULL) {
986: return NULL;
987: }
988: memset( mi, 0, sizeof(MODULEINFO) );
989:
990: if (dp->miHead == NULL) {
991: dp->miHead = dp->miTail = mi;
992: }
993: else {
994: dp->miTail->next = mi;
995: dp->miTail = mi;
996: }
997:
998: return mi;
999: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.