update for HEAD-2003021201
[reactos.git] / ntoskrnl / dbg / kdb_stabs.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /*
20  * PROJECT:              ReactOS kernel
21  * FILE:                 ntoskrnl/ke/i386/exp.c
22  * PURPOSE:              Handling exceptions
23  * PROGRAMMER:           David Welch (welch@cwcom.net)
24  * REVISION HISTORY:
25  *              ??/??/??: Created
26  */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include <roscfg.h>
32 #include <internal/ntoskrnl.h>
33 #include <internal/ke.h>
34 #include <internal/i386/segment.h>
35 #include <internal/i386/mm.h>
36 #include <internal/module.h>
37 #include <internal/mm.h>
38 #include <internal/ps.h>
39 #include <internal/trap.h>
40 #include <ntdll/ldr.h>
41 #include <internal/safe.h>
42 #include <internal/kd.h>
43
44 #define NDEBUG
45 #include <internal/debug.h>
46
47 /* GLOBALS ******************************************************************/
48
49 typedef struct _SYMBOLFILE_HEADER {
50   unsigned long StabsOffset;
51   unsigned long StabsLength;
52   unsigned long StabstrOffset;
53   unsigned long StabstrLength;
54 } SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER;
55
56 typedef struct _IMAGE_SYMBOL_INFO_CACHE {
57   LIST_ENTRY ListEntry;
58   UNICODE_STRING FullName;
59   PVOID FileBuffer;
60   PVOID SymbolsBase;
61   ULONG SymbolsLength;
62   PVOID SymbolStringsBase;
63   ULONG SymbolStringsLength;
64 } IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE;
65
66
67 typedef struct _STAB_ENTRY {
68   unsigned long n_strx;         /* index into string table of name */
69   unsigned char n_type;         /* type of symbol */
70   unsigned char n_other;        /* misc info (usually empty) */
71   unsigned short n_desc;        /* description field */
72   unsigned long n_value;        /* value of symbol */
73 } _STAB_ENTRY, *PSTAB_ENTRY;
74
75 /*
76  * Desc - Line number
77  * Value - Relative virtual address
78  */
79 #define N_FUN 0x24
80
81 /*
82  * Desc - Line number
83  * Value - Relative virtual address
84  */
85 #define N_SLINE 0x44
86
87 /*
88  * String - First containing a '/' is the compillation directory (CD)
89  *          Not containing a '/' is a source file relative to CD
90  */
91 #define N_SO 0x64
92
93 static LIST_ENTRY SymbolListHead;
94 static KSPIN_LOCK SymbolListLock;
95
96 NTSTATUS
97 LdrGetAddressInformation(IN PIMAGE_SYMBOL_INFO  SymbolInfo,
98   IN ULONG_PTR  RelativeAddress,
99   OUT PULONG LineNumber,
100   OUT PCH FileName  OPTIONAL,
101   OUT PCH FunctionName  OPTIONAL);
102
103 VOID
104 KdbLdrUnloadModuleSymbols(PIMAGE_SYMBOL_INFO SymbolInfo);
105
106 /* FUNCTIONS ****************************************************************/
107
108 BOOLEAN 
109 KdbPrintUserAddress(PVOID address)
110 {
111    PLIST_ENTRY current_entry;
112    PLDR_MODULE current;
113    PEPROCESS CurrentProcess;
114    PPEB Peb = NULL;
115    ULONG_PTR RelativeAddress;
116    NTSTATUS Status;
117    ULONG LineNumber;
118    CHAR FileName[256];
119    CHAR FunctionName[256];
120
121    CurrentProcess = PsGetCurrentProcess();
122    if (NULL != CurrentProcess)
123     {
124       Peb = CurrentProcess->Peb;
125     }
126
127    if (NULL == Peb)
128            {
129        DbgPrint("<%x>", address);
130        return(TRUE);
131      }
132
133    current_entry = Peb->Ldr->InLoadOrderModuleList.Flink;
134    
135    while (current_entry != &Peb->Ldr->InLoadOrderModuleList &&
136           current_entry != NULL)
137      {
138         current = 
139           CONTAINING_RECORD(current_entry, LDR_MODULE, InLoadOrderModuleList);
140         
141         if (address >= (PVOID)current->BaseAddress &&
142             address < (PVOID)(current->BaseAddress + current->SizeOfImage))
143           {
144             RelativeAddress = (ULONG_PTR) address - (ULONG_PTR)current->BaseAddress;
145             Status = LdrGetAddressInformation(&current->SymbolInfo,
146               RelativeAddress,
147               &LineNumber,
148               FileName,
149               FunctionName);
150             if (NT_SUCCESS(Status))
151               {
152                 DbgPrint("<%wZ: %x (%s:%d (%s))>",
153                   &current->BaseDllName, RelativeAddress, FileName, LineNumber, FunctionName);
154               }
155             else
156              {
157                DbgPrint("<%wZ: %x>", &current->BaseDllName, RelativeAddress);
158              }
159              return(TRUE);
160           }
161
162         current_entry = current_entry->Flink;
163      }
164    return(FALSE);
165 }
166
167 BOOLEAN 
168 KdbPrintAddress(PVOID address)
169 {
170    PLIST_ENTRY current_entry;
171    MODULE_TEXT_SECTION* current;
172    extern LIST_ENTRY ModuleTextListHead;
173    ULONG_PTR RelativeAddress;
174    NTSTATUS Status;
175    ULONG LineNumber;
176    CHAR FileName[256];
177    CHAR FunctionName[256];
178
179    current_entry = ModuleTextListHead.Flink;
180    
181    while (current_entry != &ModuleTextListHead &&
182           current_entry != NULL)
183      {
184         current = 
185           CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
186
187         if (address >= (PVOID)current->Base &&
188             address < (PVOID)(current->Base + current->Length))
189           {
190             RelativeAddress = (ULONG_PTR) address - current->Base;
191             Status = LdrGetAddressInformation(&current->SymbolInfo,
192               RelativeAddress,
193               &LineNumber,
194               FileName,
195               FunctionName);
196             if (NT_SUCCESS(Status))
197               {
198                 DbgPrint("<%ws: %x (%s:%d (%s))>",
199                   current->Name, RelativeAddress, FileName, LineNumber, FunctionName);
200               }
201             else
202              {
203                DbgPrint("<%ws: %x>", current->Name, RelativeAddress);
204              }
205              return(TRUE);
206           }
207         current_entry = current_entry->Flink;
208      }
209    return(FALSE);
210 }
211
212 VOID
213 KdbFreeSymbolsProcess(PEPROCESS Process)
214 {
215   PLIST_ENTRY CurrentEntry;
216   PLDR_MODULE Current;
217   PIMAGE_SYMBOL_INFO SymbolInfo;
218   PEPROCESS CurrentProcess;
219   PPEB Peb;
220
221   CurrentProcess = PsGetCurrentProcess();
222   if (CurrentProcess != Process)
223   {
224     KeAttachProcess(Process);
225   }
226   Peb = Process->Peb;
227   assert (Peb);
228   assert (Peb->Ldr);
229
230   CurrentEntry = Peb->Ldr->InLoadOrderModuleList.Flink;
231   while (CurrentEntry != &Peb->Ldr->InLoadOrderModuleList && 
232          CurrentEntry != NULL)
233     {
234       Current = CONTAINING_RECORD(CurrentEntry, LDR_MODULE, 
235                                   InLoadOrderModuleList);
236
237       SymbolInfo = &Current->SymbolInfo;
238       KdbLdrUnloadModuleSymbols(SymbolInfo);
239
240       CurrentEntry = CurrentEntry->Flink;
241     }
242   if (CurrentProcess != Process)
243   {
244     KeDetachProcess();
245   }
246 }
247
248 VOID
249 KdbLdrInit(MODULE_TEXT_SECTION* NtoskrnlTextSection,
250            MODULE_TEXT_SECTION* LdrHalTextSection)
251 {
252   RtlZeroMemory(&NtoskrnlTextSection->SymbolInfo, 
253                 sizeof(NtoskrnlTextSection->SymbolInfo));
254   NtoskrnlTextSection->SymbolInfo.ImageBase = 
255     NtoskrnlTextSection->OptionalHeader->ImageBase;
256   NtoskrnlTextSection->SymbolInfo.ImageSize = NtoskrnlTextSection->Length;
257
258   RtlZeroMemory(&LdrHalTextSection->SymbolInfo, 
259                 sizeof(LdrHalTextSection->SymbolInfo));
260   LdrHalTextSection->SymbolInfo.ImageBase = 
261     LdrHalTextSection->OptionalHeader->ImageBase;
262   LdrHalTextSection->SymbolInfo.ImageSize = LdrHalTextSection->Length;
263
264   InitializeListHead(&SymbolListHead);
265   KeInitializeSpinLock(&SymbolListLock);
266 }
267
268 VOID
269 LdrpParseImageSymbols(PIMAGE_SYMBOL_INFO SymbolInfo)
270 /* Note: It is important that the symbol strings buffer not be released after
271    this function is called because the strings are still referenced */
272 {
273   PSYMBOL CurrentFileNameSymbol;
274   PSYMBOL CurrentFunctionSymbol;
275   PSYMBOL CurrentLineNumberSymbol;
276   PSYMBOL Symbol;
277   PSTAB_ENTRY StabEntry;
278   PVOID StabsEnd;
279   PCHAR String;
280   ULONG_PTR FunRelativeAddress;
281   ULONG FunLineNumber;
282   ULONG_PTR ImageBase;
283
284   assert(SymbolInfo);
285
286   DPRINT("Parsing symbols.\n");
287
288   SymbolInfo->FileNameSymbols.SymbolCount = 0;
289   SymbolInfo->FileNameSymbols.Symbols = NULL;
290   SymbolInfo->FunctionSymbols.SymbolCount = 0;
291   SymbolInfo->FunctionSymbols.Symbols = NULL;
292   SymbolInfo->LineNumberSymbols.SymbolCount = 0;
293   SymbolInfo->LineNumberSymbols.Symbols = NULL;
294   StabsEnd = SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength;
295   StabEntry = (PSTAB_ENTRY) SymbolInfo->SymbolsBase;
296   ImageBase = SymbolInfo->ImageBase;
297   FunRelativeAddress = 0;
298   FunLineNumber = 0;
299   CurrentFileNameSymbol = NULL;
300   CurrentFunctionSymbol = NULL;
301   CurrentLineNumberSymbol = NULL;
302   while ((ULONG_PTR) StabEntry < (ULONG_PTR) StabsEnd)
303     {
304       Symbol = NULL;
305
306       if (StabEntry->n_type == N_FUN)
307         {
308           if (StabEntry->n_desc > 0)
309             {
310               assert(StabEntry->n_value >= ImageBase);
311
312               FunRelativeAddress = StabEntry->n_value - ImageBase;
313               FunLineNumber = StabEntry->n_desc;
314
315               Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
316               assert(Symbol);
317               Symbol->Next = NULL;
318               Symbol->SymbolType = ST_FUNCTION;
319               Symbol->RelativeAddress = FunRelativeAddress;
320               Symbol->LineNumber = FunLineNumber;
321               String = (PCHAR)SymbolInfo->SymbolStringsBase + StabEntry->n_strx;
322               RtlInitAnsiString(&Symbol->Name, String);
323
324               DPRINT("FUN found. '%s' %d @ %x\n",
325                 Symbol->Name.Buffer, FunLineNumber, FunRelativeAddress);
326             }
327         }
328       else if (StabEntry->n_type == N_SLINE)
329         {
330           Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
331           assert(Symbol);
332           Symbol->Next = NULL;
333           Symbol->SymbolType = ST_LINENUMBER;
334           Symbol->RelativeAddress = FunRelativeAddress + StabEntry->n_value;
335           Symbol->LineNumber = StabEntry->n_desc;
336
337           DPRINT("SLINE found. %d @ %x\n",
338             Symbol->LineNumber, Symbol->RelativeAddress);
339         }
340       else if (StabEntry->n_type == N_SO)
341         {
342           Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
343           assert(Symbol);
344           Symbol->Next = NULL;
345           Symbol->SymbolType = ST_FILENAME;
346           Symbol->RelativeAddress = StabEntry->n_value - ImageBase;
347           Symbol->LineNumber = 0;
348           String = (PCHAR)SymbolInfo->SymbolStringsBase + StabEntry->n_strx;
349           RtlInitAnsiString(&Symbol->Name, String);
350
351           DPRINT("SO found. '%s' @ %x\n",
352             Symbol->Name.Buffer, Symbol->RelativeAddress);
353         }
354
355       if (Symbol != NULL)
356         {
357           switch (Symbol->SymbolType)
358           {
359             case ST_FILENAME:
360               if (SymbolInfo->FileNameSymbols.Symbols == NULL)
361                 SymbolInfo->FileNameSymbols.Symbols = Symbol;
362               else
363                 CurrentFileNameSymbol->Next = Symbol;
364
365               CurrentFileNameSymbol = Symbol;
366
367               SymbolInfo->FileNameSymbols.SymbolCount++;
368               break;
369             case ST_FUNCTION:
370               if (SymbolInfo->FunctionSymbols.Symbols == NULL)
371                 SymbolInfo->FunctionSymbols.Symbols = Symbol;
372               else
373                 CurrentFunctionSymbol->Next = Symbol;
374
375               CurrentFunctionSymbol = Symbol;
376
377               SymbolInfo->FunctionSymbols.SymbolCount++;
378               break;
379             case ST_LINENUMBER:
380               if (SymbolInfo->LineNumberSymbols.Symbols == NULL)
381                 SymbolInfo->LineNumberSymbols.Symbols = Symbol;
382               else
383                 CurrentLineNumberSymbol->Next = Symbol;
384
385               CurrentLineNumberSymbol = Symbol;
386
387               SymbolInfo->LineNumberSymbols.SymbolCount++;
388               break;
389           }
390         }
391
392       StabEntry++;
393     }
394 }
395
396 static NTSTATUS
397 LdrpGetFileName(IN PIMAGE_SYMBOL_INFO  SymbolInfo,
398   IN ULONG_PTR  RelativeAddress,
399   OUT PCH  FileName)
400 {
401   PSYMBOL NextSymbol;
402   ULONG_PTR NextAddress;
403   PSYMBOL Symbol;
404
405   Symbol = SymbolInfo->FileNameSymbols.Symbols;
406   while (Symbol != NULL)
407     {
408       NextSymbol = Symbol->Next;
409       if (NextSymbol != NULL)
410         NextAddress = NextSymbol->RelativeAddress;
411       else
412         NextAddress = SymbolInfo->ImageSize;
413
414       DPRINT("FN SEARCH: Type %d  RelativeAddress %x >= Symbol->RelativeAddress %x  < NextAddress %x\n",
415         Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress);
416
417       if ((Symbol->SymbolType == ST_FILENAME) &&
418         (RelativeAddress >= Symbol->RelativeAddress) &&
419         (RelativeAddress < NextAddress))
420         {
421           DPRINT("FN found\n");
422           strcpy(FileName, Symbol->Name.Buffer);
423           return STATUS_SUCCESS;
424         }
425       Symbol = NextSymbol;
426     }
427
428   DPRINT("FN not found\n");
429
430   return STATUS_UNSUCCESSFUL;
431 }
432
433 static NTSTATUS
434 LdrpGetFunctionName(IN PIMAGE_SYMBOL_INFO  SymbolInfo,
435   IN ULONG_PTR  RelativeAddress,
436   OUT PCH  FunctionName)
437 {
438   PSYMBOL NextSymbol;
439   ULONG_PTR NextAddress;
440   PSYMBOL Symbol;
441
442   Symbol = SymbolInfo->FunctionSymbols.Symbols;
443   while (Symbol != NULL)
444     {
445       NextSymbol = Symbol->Next;
446       if (NextSymbol != NULL)
447         NextAddress = NextSymbol->RelativeAddress;
448       else
449         NextAddress = SymbolInfo->ImageSize;
450
451       DPRINT("FUN SEARCH: Type %d  RelativeAddress %x >= Symbol->RelativeAddress %x  < NextAddress %x\n",
452         Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress);
453
454       if ((Symbol->SymbolType == ST_FUNCTION) &&
455         (RelativeAddress >= Symbol->RelativeAddress) &&
456         (RelativeAddress < NextAddress))
457         {
458           PCHAR ExtraInfo;
459           ULONG Length;
460
461           DPRINT("FUN found\n");
462
463           /* Remove the extra information from the function name */
464           ExtraInfo = strchr(Symbol->Name.Buffer, ':');
465           if (ExtraInfo != NULL)
466             Length = ExtraInfo - Symbol->Name.Buffer;
467           else
468             Length = strlen(Symbol->Name.Buffer);
469
470           strncpy(FunctionName, Symbol->Name.Buffer, Length);
471           FunctionName[Length]=0;
472           return STATUS_SUCCESS;
473         }
474       Symbol = NextSymbol;
475     }
476
477   DPRINT("FUN not found\n");
478
479   return STATUS_UNSUCCESSFUL;
480 }
481
482 static NTSTATUS
483 LdrpGetLineNumber(IN PIMAGE_SYMBOL_INFO  SymbolInfo,
484   IN ULONG_PTR  RelativeAddress,
485   OUT PULONG  LineNumber)
486 {
487   PSYMBOL NextSymbol;
488   ULONG_PTR NextAddress;
489   PSYMBOL Symbol;
490
491   Symbol = SymbolInfo->LineNumberSymbols.Symbols;
492   while (Symbol != NULL)
493     {
494       NextSymbol = Symbol->Next;
495       if (NextSymbol != NULL)
496         NextAddress = NextSymbol->RelativeAddress;
497       else
498         NextAddress = SymbolInfo->ImageSize;
499
500       DPRINT("LN SEARCH: Type %d  RelativeAddress %x >= Symbol->RelativeAddress %x  < NextAddress %x\n",
501         Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress);
502
503       if ((Symbol->SymbolType == ST_LINENUMBER) &&
504         (RelativeAddress >= Symbol->RelativeAddress) &&
505         (RelativeAddress < NextAddress))
506         {
507           DPRINT("LN found\n");
508           *LineNumber = Symbol->LineNumber;
509           return STATUS_SUCCESS;
510         }
511       Symbol = NextSymbol;
512     }
513
514   DPRINT("LN not found\n");
515
516   return STATUS_UNSUCCESSFUL;
517 }
518
519 NTSTATUS
520 LdrGetAddressInformation(IN PIMAGE_SYMBOL_INFO  SymbolInfo,
521   IN ULONG_PTR  RelativeAddress,
522   OUT PULONG LineNumber,
523   OUT PCH FileName  OPTIONAL,
524   OUT PCH FunctionName  OPTIONAL)
525 {
526   NTSTATUS Status;
527
528   *LineNumber = 0;
529
530   DPRINT("RelativeAddress %p\n", RelativeAddress);
531
532   if (RelativeAddress >= SymbolInfo->ImageSize)
533     {
534       DPRINT("Address is not within .text section. RelativeAddress %p  Length 0x%x\n",
535         RelativeAddress, SymbolInfo->ImageSize);
536       return STATUS_UNSUCCESSFUL;
537     }
538
539   if (!AreSymbolsParsed(SymbolInfo))
540     {
541       LdrpParseImageSymbols(SymbolInfo);
542     }
543
544   Status = LdrpGetLineNumber(SymbolInfo, RelativeAddress, LineNumber);
545   if (!NT_SUCCESS(Status))
546     {
547       return Status;
548     }
549
550   if (FileName)
551    {
552      Status = LdrpGetFileName(SymbolInfo, RelativeAddress, FileName);
553      if (!NT_SUCCESS(Status))
554        {
555          strcpy(FileName, "");
556        }
557    }
558
559   if (FunctionName)
560    {
561      Status = LdrpGetFunctionName(SymbolInfo, RelativeAddress, FunctionName);
562      if (!NT_SUCCESS(Status))
563        {
564          strcpy(FunctionName, "");
565        }
566    }
567
568   return STATUS_SUCCESS;
569 }
570
571 VOID
572 LdrpLoadModuleSymbols(PUNICODE_STRING FileName,
573                       PIMAGE_SYMBOL_INFO SymbolInfo)
574 {
575   FILE_STANDARD_INFORMATION FileStdInfo;
576   OBJECT_ATTRIBUTES ObjectAttributes;
577   WCHAR TmpFileName[MAX_PATH];
578   UNICODE_STRING SymFileName;
579   LPWSTR Start, Ext;
580   HANDLE FileHandle;
581   PVOID FileBuffer;
582   NTSTATUS Status;
583   ULONG Length;
584   IO_STATUS_BLOCK IoStatusBlock;
585   PSYMBOLFILE_HEADER SymbolFileHeader;
586
587   /*  Get the path to the symbol store  */
588   wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\");
589
590   /*  Get the symbol filename from the module name  */
591   Start = wcsrchr(FileName->Buffer, L'\\');
592   if (Start == NULL)
593     Start = FileName->Buffer;
594   else
595     Start++;
596
597   Ext = wcsrchr(FileName->Buffer, L'.');
598   if (Ext != NULL)
599     Length = Ext - Start;
600   else
601     Length = wcslen(Start);
602
603   wcsncat(TmpFileName, Start, Length);
604   wcscat(TmpFileName, L".sym");
605   RtlInitUnicodeString(&SymFileName, TmpFileName);
606
607   /*  Open the file  */
608   InitializeObjectAttributes(&ObjectAttributes,
609                              &SymFileName,
610                              0,
611                              NULL,
612                              NULL);
613
614   Status = ZwOpenFile(&FileHandle,
615                       FILE_ALL_ACCESS,
616                       &ObjectAttributes,
617                       &IoStatusBlock,
618                       0,
619                       FILE_SYNCHRONOUS_IO_NONALERT);
620   if (!NT_SUCCESS(Status))
621     {
622       DPRINT("Could not open symbol file: %wZ\n", &SymFileName);
623       return;
624     }
625
626   CPRINT("Loading symbols from %wZ...\n", &SymFileName);
627
628   /*  Get the size of the file  */
629   Status = ZwQueryInformationFile(FileHandle,
630                                   &IoStatusBlock,
631                                   &FileStdInfo,
632                                   sizeof(FileStdInfo),
633                                   FileStandardInformation);
634   if (!NT_SUCCESS(Status))
635     {
636       DPRINT("Could not get file size\n");
637       ZwClose(FileHandle);
638       return;
639     }
640
641   /*  Allocate nonpageable memory for symbol file  */
642   FileBuffer = ExAllocatePool(NonPagedPool,
643                               FileStdInfo.EndOfFile.u.LowPart);
644
645   if (FileBuffer == NULL)
646     {
647       DPRINT("Could not allocate memory for symbol file\n");
648       ZwClose(FileHandle);
649       return;
650     }
651    
652   /*  Load file into memory chunk  */
653   Status = ZwReadFile(FileHandle,
654                       0, 0, 0,
655                       &IoStatusBlock,
656                       FileBuffer,
657                       FileStdInfo.EndOfFile.u.LowPart,
658                       0, 0);
659   if (!NT_SUCCESS(Status))
660     {
661       DPRINT("Could not read symbol file into memory (Status 0x%x)\n", Status);
662       ExFreePool(FileBuffer);
663       ZwClose(FileHandle);
664       return;
665     }
666
667   ZwClose(FileHandle);
668
669   SymbolFileHeader = (PSYMBOLFILE_HEADER) FileBuffer;
670   SymbolInfo->FileBuffer = FileBuffer;
671   SymbolInfo->SymbolsBase = FileBuffer + SymbolFileHeader->StabsOffset;
672   SymbolInfo->SymbolsLength = SymbolFileHeader->StabsLength;
673   SymbolInfo->SymbolStringsBase = FileBuffer + SymbolFileHeader->StabstrOffset;
674   SymbolInfo->SymbolStringsLength = SymbolFileHeader->StabstrLength;
675 }
676
677 VOID
678 KdbLdrUnloadModuleSymbols(PIMAGE_SYMBOL_INFO SymbolInfo)
679 {
680   PSYMBOL NextSymbol;
681   PSYMBOL Symbol;
682
683   DPRINT("Unloading symbols\n");
684
685   if (SymbolInfo != NULL)
686     {
687       Symbol = SymbolInfo->FileNameSymbols.Symbols;
688       while (Symbol != NULL)
689         {
690           NextSymbol = Symbol->Next;
691           RtlFreeAnsiString(&Symbol->Name);
692           ExFreePool(Symbol);
693           Symbol = NextSymbol;
694         }
695
696       SymbolInfo->FileNameSymbols.SymbolCount = 0;
697       SymbolInfo->FileNameSymbols.Symbols = NULL;
698
699       Symbol = SymbolInfo->FunctionSymbols.Symbols;
700       while (Symbol != NULL)
701         {
702           NextSymbol = Symbol->Next;
703           RtlFreeAnsiString(&Symbol->Name);
704           ExFreePool(Symbol);
705           Symbol = NextSymbol;
706         }
707
708       SymbolInfo->FunctionSymbols.SymbolCount = 0;
709       SymbolInfo->FunctionSymbols.Symbols = NULL;
710
711       Symbol = SymbolInfo->LineNumberSymbols.Symbols;
712       while (Symbol != NULL)
713         {
714           NextSymbol = Symbol->Next;
715           RtlFreeAnsiString(&Symbol->Name);
716           ExFreePool(Symbol);
717           Symbol = NextSymbol;
718         }
719
720       SymbolInfo->LineNumberSymbols.SymbolCount = 0;
721       SymbolInfo->LineNumberSymbols.Symbols = NULL;
722 #if 0
723       /* Don't free buffers because we cache symbol buffers
724          (eg. they are shared across processes) */
725       /* FIXME: We can free them if we do reference counting */
726       if (SymbolInfo->FileBuffer != NULL)
727         {
728           ExFreePool(SymbolInfo->FileBuffer);
729           SymbolInfo->FileBuffer = NULL;
730           SymbolInfo->SymbolsBase = NULL;
731           SymbolInfo->SymbolsLength = 0;
732         }
733 #endif
734     }
735 }
736
737
738 PIMAGE_SYMBOL_INFO_CACHE
739 LdrpLookupUserSymbolInfo(PLDR_MODULE LdrModule)
740 {
741   PIMAGE_SYMBOL_INFO_CACHE Current;
742   PLIST_ENTRY CurrentEntry;
743   KIRQL Irql;
744
745   DPRINT("Searching symbols for %S\n", LdrModule->FullDllName.Buffer);
746
747   KeAcquireSpinLock(&SymbolListLock, &Irql);
748
749   CurrentEntry = SymbolListHead.Flink;
750   while (CurrentEntry != (&SymbolListHead))
751     {
752       Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
753
754       if (RtlEqualUnicodeString(&Current->FullName, &LdrModule->FullDllName, TRUE))
755         {
756           KeReleaseSpinLock(&SymbolListLock, Irql);
757           return Current;
758         }
759
760       CurrentEntry = CurrentEntry->Flink;
761     }
762
763   KeReleaseSpinLock(&SymbolListLock, Irql);
764
765   return(NULL);
766 }
767
768 VOID
769 KdbLdrLoadUserModuleSymbols(PLDR_MODULE LdrModule)
770 {
771   PIMAGE_SYMBOL_INFO_CACHE CacheEntry;
772
773   DPRINT("LdrModule %p\n", LdrModule);
774
775   RtlZeroMemory(&LdrModule->SymbolInfo, sizeof(LdrModule->SymbolInfo));
776   LdrModule->SymbolInfo.ImageBase = (ULONG_PTR) LdrModule->BaseAddress;
777   LdrModule->SymbolInfo.ImageSize = LdrModule->SizeOfImage;
778
779   CacheEntry = LdrpLookupUserSymbolInfo(LdrModule);
780   if (CacheEntry != NULL)
781     {
782       DPRINT("Symbol cache hit for %S\n", CacheEntry->FullName.Buffer);
783    
784       LdrModule->SymbolInfo.FileBuffer = CacheEntry->FileBuffer;
785       LdrModule->SymbolInfo.SymbolsBase = CacheEntry->SymbolsBase;
786       LdrModule->SymbolInfo.SymbolsLength = CacheEntry->SymbolsLength;
787       LdrModule->SymbolInfo.SymbolStringsBase = CacheEntry->SymbolStringsBase;
788       LdrModule->SymbolInfo.SymbolStringsLength = CacheEntry->SymbolStringsLength;
789     }
790   else
791     {
792       CacheEntry = ExAllocatePool(NonPagedPool, sizeof(IMAGE_SYMBOL_INFO_CACHE));
793       assert(CacheEntry);
794       RtlZeroMemory(CacheEntry, sizeof(IMAGE_SYMBOL_INFO_CACHE));
795
796       RtlCreateUnicodeString(&CacheEntry->FullName, LdrModule->FullDllName.Buffer);
797       assert(CacheEntry->FullName.Buffer);
798       LdrpLoadModuleSymbols(&LdrModule->FullDllName, &LdrModule->SymbolInfo);
799       CacheEntry->FileBuffer = LdrModule->SymbolInfo.FileBuffer;
800       CacheEntry->SymbolsBase = LdrModule->SymbolInfo.SymbolsBase;
801       CacheEntry->SymbolsLength = LdrModule->SymbolInfo.SymbolsLength;
802       CacheEntry->SymbolStringsBase = LdrModule->SymbolInfo.SymbolStringsBase;
803       CacheEntry->SymbolStringsLength = LdrModule->SymbolInfo.SymbolStringsLength;
804       InsertTailList(&SymbolListHead, &CacheEntry->ListEntry);
805     }
806 }
807
808 VOID
809 KdbLoadDriver(PUNICODE_STRING Filename, PMODULE_OBJECT Module)
810 {
811   /* Load symbols for the image if available */
812   LdrpLoadModuleSymbols(Filename, &Module->TextSection->SymbolInfo);
813 }
814
815 VOID
816 KdbUnloadDriver(PMODULE_OBJECT ModuleObject)
817 {
818   /* Unload symbols for module if available */
819   KdbLdrUnloadModuleSymbols(&ModuleObject->TextSection->SymbolInfo);
820 }
821
822 VOID
823 KdbProcessSymbolFile(PVOID ModuleLoadBase, PCHAR FileName, ULONG Length)
824 {
825   PMODULE_OBJECT ModuleObject;
826   UNICODE_STRING ModuleName;
827   CHAR TmpBaseName[MAX_PATH];
828   CHAR TmpFileName[MAX_PATH];
829   PSYMBOLFILE_HEADER SymbolFileHeader;
830   PIMAGE_SYMBOL_INFO SymbolInfo;
831   ANSI_STRING AnsiString;
832
833   DPRINT("Module %s is a symbol file\n", FileName);
834
835   strncpy(TmpBaseName, FileName, Length);
836   TmpBaseName[Length] = '\0';
837   
838   DPRINT("base: %s (Length %d)\n", TmpBaseName, Length);
839   
840   strcpy(TmpFileName, TmpBaseName);
841   strcat(TmpFileName, ".sys");
842   RtlInitAnsiString(&AnsiString, TmpFileName);
843   
844   RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
845   ModuleObject = LdrGetModuleObject(&ModuleName);
846   RtlFreeUnicodeString(&ModuleName);
847   if (ModuleObject == NULL)
848     {
849       strcpy(TmpFileName, TmpBaseName);
850       strcat(TmpFileName, ".exe");
851       RtlInitAnsiString(&AnsiString, TmpFileName);
852       RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
853       ModuleObject = LdrGetModuleObject(&ModuleName);
854       RtlFreeUnicodeString(&ModuleName);
855     }
856   if (ModuleObject != NULL)
857     {
858       SymbolInfo = (PIMAGE_SYMBOL_INFO) &ModuleObject->TextSection->SymbolInfo;
859       SymbolFileHeader = (PSYMBOLFILE_HEADER) ModuleLoadBase;
860       SymbolInfo->FileBuffer = ModuleLoadBase;
861       SymbolInfo->SymbolsBase = ModuleLoadBase + SymbolFileHeader->StabsOffset;
862       SymbolInfo->SymbolsLength = SymbolFileHeader->StabsLength;
863       SymbolInfo->SymbolStringsBase = ModuleLoadBase + SymbolFileHeader->StabstrOffset;
864       SymbolInfo->SymbolStringsLength = SymbolFileHeader->StabstrLength;
865     } 
866 }
867
868 VOID
869 KdbInitializeDriver(PMODULE_TEXT_SECTION ModuleTextSection)
870 {
871   RtlZeroMemory(&ModuleTextSection->SymbolInfo, sizeof(ModuleTextSection->SymbolInfo));
872   ModuleTextSection->SymbolInfo.ImageBase = 
873     ModuleTextSection->OptionalHeader->ImageBase;
874   ModuleTextSection->SymbolInfo.ImageSize = ModuleTextSection->Length;
875 }
876
877 VOID
878 KdbLdrLoadAutoConfigDrivers(VOID)
879 {
880   UNICODE_STRING ModuleName;
881   PMODULE_OBJECT ModuleObject;
882
883   /*
884    * Load symbols for ntoskrnl.exe and hal.dll because \SystemRoot
885    * is created after their module entries
886    */
887
888   RtlInitUnicodeStringFromLiteral(&ModuleName, KERNEL_MODULE_NAME);
889   ModuleObject = LdrGetModuleObject(&ModuleName);
890   if (ModuleObject != NULL)
891     {
892       LdrpLoadModuleSymbols(&ModuleName, 
893                             &ModuleObject->TextSection->SymbolInfo);
894     }
895
896   RtlInitUnicodeStringFromLiteral(&ModuleName, HAL_MODULE_NAME);
897   ModuleObject = LdrGetModuleObject(&ModuleName);
898   if (ModuleObject != NULL)
899     {
900       LdrpLoadModuleSymbols(&ModuleName,
901                             &ModuleObject->TextSection->SymbolInfo);
902     }
903 }