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