Reverted latest 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
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(PPEB Peb)
214 {
215 PLIST_ENTRY CurrentEntry;
216 PLDR_MODULE Current;
217 PIMAGE_SYMBOL_INFO SymbolInfo;
218
219 assert (Peb);
220 assert (Peb->Ldr);
221
222 CurrentEntry = Peb->Ldr->InLoadOrderModuleList.Flink;
223 while (CurrentEntry != &Peb->Ldr->InLoadOrderModuleList &&
224 CurrentEntry != NULL)
225 {
226 Current = CONTAINING_RECORD(CurrentEntry, LDR_MODULE,
227 InLoadOrderModuleList);
228
229 SymbolInfo = &Current->SymbolInfo;
230 KdbLdrUnloadModuleSymbols(SymbolInfo);
231
232 CurrentEntry = CurrentEntry->Flink;
233 }
234 }
235
236 VOID
237 KdbLdrInit(MODULE_TEXT_SECTION* NtoskrnlTextSection,
238 MODULE_TEXT_SECTION* LdrHalTextSection)
239 {
240 RtlZeroMemory(&NtoskrnlTextSection->SymbolInfo,
241 sizeof(NtoskrnlTextSection->SymbolInfo));
242 NtoskrnlTextSection->SymbolInfo.ImageBase =
243 NtoskrnlTextSection->OptionalHeader->ImageBase;
244 NtoskrnlTextSection->SymbolInfo.ImageSize = NtoskrnlTextSection->Length;
245
246 RtlZeroMemory(&LdrHalTextSection->SymbolInfo,
247 sizeof(LdrHalTextSection->SymbolInfo));
248 LdrHalTextSection->SymbolInfo.ImageBase =
249 LdrHalTextSection->OptionalHeader->ImageBase;
250 LdrHalTextSection->SymbolInfo.ImageSize = LdrHalTextSection->Length;
251
252 InitializeListHead(&SymbolListHead);
253 KeInitializeSpinLock(&SymbolListLock);
254 }
255
256 VOID
257 LdrpParseImageSymbols(PIMAGE_SYMBOL_INFO SymbolInfo)
258 /* Note: It is important that the symbol strings buffer not be released after
259 this function is called because the strings are still referenced */
260 {
261 PSYMBOL CurrentFileNameSymbol;
262 PSYMBOL CurrentFunctionSymbol;
263 PSYMBOL CurrentLineNumberSymbol;
264 PSYMBOL Symbol;
265 PSTAB_ENTRY StabEntry;
266 PVOID StabsEnd;
267 PCHAR String;
268 ULONG_PTR FunRelativeAddress;
269 ULONG FunLineNumber;
270 ULONG_PTR ImageBase;
271
272 assert(SymbolInfo);
273
274 DPRINT("Parsing symbols.\n");
275
276 SymbolInfo->FileNameSymbols.SymbolCount = 0;
277 SymbolInfo->FileNameSymbols.Symbols = NULL;
278 SymbolInfo->FunctionSymbols.SymbolCount = 0;
279 SymbolInfo->FunctionSymbols.Symbols = NULL;
280 SymbolInfo->LineNumberSymbols.SymbolCount = 0;
281 SymbolInfo->LineNumberSymbols.Symbols = NULL;
282 StabsEnd = SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength;
283 StabEntry = (PSTAB_ENTRY) SymbolInfo->SymbolsBase;
284 ImageBase = SymbolInfo->ImageBase;
285 FunRelativeAddress = 0;
286 FunLineNumber = 0;
287 CurrentFileNameSymbol = NULL;
288 CurrentFunctionSymbol = NULL;
289 CurrentLineNumberSymbol = NULL;
290 while ((ULONG_PTR) StabEntry < (ULONG_PTR) StabsEnd)
291 {
292 Symbol = NULL;
293
294 if (StabEntry->n_type == N_FUN)
295 {
296 if (StabEntry->n_desc > 0)
297 {
298 assert(StabEntry->n_value >= ImageBase);
299
300 FunRelativeAddress = StabEntry->n_value - ImageBase;
301 FunLineNumber = StabEntry->n_desc;
302
303 Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
304 assert(Symbol);
305 Symbol->Next = NULL;
306 Symbol->SymbolType = ST_FUNCTION;
307 Symbol->RelativeAddress = FunRelativeAddress;
308 Symbol->LineNumber = FunLineNumber;
309 String = (PCHAR)SymbolInfo->SymbolStringsBase + StabEntry->n_strx;
310 RtlInitAnsiString(&Symbol->Name, String);
311
312 DPRINT("FUN found. '%s' %d @ %x\n",
313 Symbol->Name.Buffer, FunLineNumber, FunRelativeAddress);
314 }
315 }
316 else if (StabEntry->n_type == N_SLINE)
317 {
318 Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
319 assert(Symbol);
320 Symbol->Next = NULL;
321 Symbol->SymbolType = ST_LINENUMBER;
322 Symbol->RelativeAddress = FunRelativeAddress + StabEntry->n_value;
323 Symbol->LineNumber = StabEntry->n_desc;
324
325 DPRINT("SLINE found. %d @ %x\n",
326 Symbol->LineNumber, Symbol->RelativeAddress);
327 }
328 else if (StabEntry->n_type == N_SO)
329 {
330 Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL));
331 assert(Symbol);
332 Symbol->Next = NULL;
333 Symbol->SymbolType = ST_FILENAME;
334 Symbol->RelativeAddress = StabEntry->n_value - ImageBase;
335 Symbol->LineNumber = 0;
336 String = (PCHAR)SymbolInfo->SymbolStringsBase + StabEntry->n_strx;
337 RtlInitAnsiString(&Symbol->Name, String);
338
339 DPRINT("SO found. '%s' @ %x\n",
340 Symbol->Name.Buffer, Symbol->RelativeAddress);
341 }
342
343 if (Symbol != NULL)
344 {
345 switch (Symbol->SymbolType)
346 {
347 case ST_FILENAME:
348 if (SymbolInfo->FileNameSymbols.Symbols == NULL)
349 SymbolInfo->FileNameSymbols.Symbols = Symbol;
350 else
351 CurrentFileNameSymbol->Next = Symbol;
352
353 CurrentFileNameSymbol = Symbol;
354
355 SymbolInfo->FileNameSymbols.SymbolCount++;
356 break;
357 case ST_FUNCTION:
358 if (SymbolInfo->FunctionSymbols.Symbols == NULL)
359 SymbolInfo->FunctionSymbols.Symbols = Symbol;
360 else
361 CurrentFunctionSymbol->Next = Symbol;
362
363 CurrentFunctionSymbol = Symbol;
364
365 SymbolInfo->FunctionSymbols.SymbolCount++;
366 break;
367 case ST_LINENUMBER:
368 if (SymbolInfo->LineNumberSymbols.Symbols == NULL)
369 SymbolInfo->LineNumberSymbols.Symbols = Symbol;
370 else
371 CurrentLineNumberSymbol->Next = Symbol;
372
373 CurrentLineNumberSymbol = Symbol;
374
375 SymbolInfo->LineNumberSymbols.SymbolCount++;
376 break;
377 }
378 }
379
380 StabEntry++;
381 }
382 }
383
384 static NTSTATUS
385 LdrpGetFileName(IN PIMAGE_SYMBOL_INFO SymbolInfo,
386 IN ULONG_PTR RelativeAddress,
387 OUT PCH FileName)
388 {
389 PSYMBOL NextSymbol;
390 ULONG_PTR NextAddress;
391 PSYMBOL Symbol;
392
393 Symbol = SymbolInfo->FileNameSymbols.Symbols;
394 while (Symbol != NULL)
395 {
396 NextSymbol = Symbol->Next;
397 if (NextSymbol != NULL)
398 NextAddress = NextSymbol->RelativeAddress;
399 else
400 NextAddress = SymbolInfo->ImageSize;
401
402 DPRINT("FN SEARCH: Type %d RelativeAddress %x >= Symbol->RelativeAddress %x < NextAddress %x\n",
403 Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress);
404
405 if ((Symbol->SymbolType == ST_FILENAME) &&
406 (RelativeAddress >= Symbol->RelativeAddress) &&
407 (RelativeAddress < NextAddress))
408 {
409 DPRINT("FN found\n");
410 strcpy(FileName, Symbol->Name.Buffer);
411 return STATUS_SUCCESS;
412 }
413 Symbol = NextSymbol;
414 }
415
416 DPRINT("FN not found\n");
417
418 return STATUS_UNSUCCESSFUL;
419 }
420
421 static NTSTATUS
422 LdrpGetFunctionName(IN PIMAGE_SYMBOL_INFO SymbolInfo,
423 IN ULONG_PTR RelativeAddress,
424 OUT PCH FunctionName)
425 {
426 PSYMBOL NextSymbol;
427 ULONG_PTR NextAddress;
428 PSYMBOL Symbol;
429
430 Symbol = SymbolInfo->FunctionSymbols.Symbols;
431 while (Symbol != NULL)
432 {
433 NextSymbol = Symbol->Next;
434 if (NextSymbol != NULL)
435 NextAddress = NextSymbol->RelativeAddress;
436 else
437 NextAddress = SymbolInfo->ImageSize;
438
439 DPRINT("FUN SEARCH: Type %d RelativeAddress %x >= Symbol->RelativeAddress %x < NextAddress %x\n",
440 Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress);
441
442 if ((Symbol->SymbolType == ST_FUNCTION) &&
443 (RelativeAddress >= Symbol->RelativeAddress) &&
444 (RelativeAddress < NextAddress))
445 {
446 PCHAR ExtraInfo;
447 ULONG Length;
448
449 DPRINT("FUN found\n");
450
451 /* Remove the extra information from the function name */
452 ExtraInfo = strchr(Symbol->Name.Buffer, ':');
453 if (ExtraInfo != NULL)
454 Length = ExtraInfo - Symbol->Name.Buffer;
455 else
456 Length = strlen(Symbol->Name.Buffer);
457
458 strncpy(FunctionName, Symbol->Name.Buffer, Length);
459 return STATUS_SUCCESS;
460 }
461 Symbol = NextSymbol;
462 }
463
464 DPRINT("FUN not found\n");
465
466 return STATUS_UNSUCCESSFUL;
467 }
468
469 static NTSTATUS
470 LdrpGetLineNumber(IN PIMAGE_SYMBOL_INFO SymbolInfo,
471 IN ULONG_PTR RelativeAddress,
472 OUT PULONG LineNumber)
473 {
474 PSYMBOL NextSymbol;
475 ULONG_PTR NextAddress;
476 PSYMBOL Symbol;
477
478 Symbol = SymbolInfo->LineNumberSymbols.Symbols;
479 while (Symbol != NULL)
480 {
481 NextSymbol = Symbol->Next;
482 if (NextSymbol != NULL)
483 NextAddress = NextSymbol->RelativeAddress;
484 else
485 NextAddress = SymbolInfo->ImageSize;
486
487 DPRINT("LN SEARCH: Type %d RelativeAddress %x >= Symbol->RelativeAddress %x < NextAddress %x\n",
488 Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress);
489
490 if ((Symbol->SymbolType == ST_LINENUMBER) &&
491 (RelativeAddress >= Symbol->RelativeAddress) &&
492 (RelativeAddress < NextAddress))
493 {
494 DPRINT("LN found\n");
495 *LineNumber = Symbol->LineNumber;
496 return STATUS_SUCCESS;
497 }
498 Symbol = NextSymbol;
499 }
500
501 DPRINT("LN not found\n");
502
503 return STATUS_UNSUCCESSFUL;
504 }
505
506 NTSTATUS
507 LdrGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo,
508 IN ULONG_PTR RelativeAddress,
509 OUT PULONG LineNumber,
510 OUT PCH FileName OPTIONAL,
511 OUT PCH FunctionName OPTIONAL)
512 {
513 NTSTATUS Status;
514
515 *LineNumber = 0;
516
517 DPRINT("RelativeAddress %p\n", RelativeAddress);
518
519 if (RelativeAddress >= SymbolInfo->ImageSize)
520 {
521 DPRINT("Address is not within .text section. RelativeAddress %p Length 0x%x\n",
522 RelativeAddress, SymbolInfo->ImageSize);
523 return STATUS_UNSUCCESSFUL;
524 }
525
526 if (!AreSymbolsParsed(SymbolInfo))
527 {
528 LdrpParseImageSymbols(SymbolInfo);
529 }
530
531 Status = LdrpGetLineNumber(SymbolInfo, RelativeAddress, LineNumber);
532 if (!NT_SUCCESS(Status))
533 {
534 return Status;
535 }
536
537 if (FileName)
538 {
539 Status = LdrpGetFileName(SymbolInfo, RelativeAddress, FileName);
540 if (!NT_SUCCESS(Status))
541 {
542 strcpy(FileName, "");
543 }
544 }
545
546 if (FunctionName)
547 {
548 Status = LdrpGetFunctionName(SymbolInfo, RelativeAddress, FunctionName);
549 if (!NT_SUCCESS(Status))
550 {
551 strcpy(FunctionName, "");
552 }
553 }
554
555 return STATUS_SUCCESS;
556 }
557
558 VOID
559 LdrpLoadModuleSymbols(PUNICODE_STRING FileName,
560 PIMAGE_SYMBOL_INFO SymbolInfo)
561 {
562 FILE_STANDARD_INFORMATION FileStdInfo;
563 OBJECT_ATTRIBUTES ObjectAttributes;
564 WCHAR TmpFileName[MAX_PATH];
565 UNICODE_STRING SymFileName;
566 LPWSTR Start, Ext;
567 HANDLE FileHandle;
568 PVOID FileBuffer;
569 NTSTATUS Status;
570 ULONG Length;
571 IO_STATUS_BLOCK IoStatusBlock;
572 PSYMBOLFILE_HEADER SymbolFileHeader;
573
574 /* Get the path to the symbol store */
575 wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\");
576
577 /* Get the symbol filename from the module name */
578 Start = wcsrchr(FileName->Buffer, L'\\');
579 if (Start == NULL)
580 Start = FileName->Buffer;
581 else
582 Start++;
583
584 Ext = wcsrchr(FileName->Buffer, L'.');
585 if (Ext != NULL)
586 Length = Ext - Start;
587 else
588 Length = wcslen(Start);
589
590 wcsncat(TmpFileName, Start, Length);
591 wcscat(TmpFileName, L".sym");
592 RtlInitUnicodeString(&SymFileName, TmpFileName);
593
594 /* Open the file */
595 InitializeObjectAttributes(&ObjectAttributes,
596 &SymFileName,
597 0,
598 NULL,
599 NULL);
600
601 Status = ZwOpenFile(&FileHandle,
602 FILE_ALL_ACCESS,
603 &ObjectAttributes,
604 &IoStatusBlock,
605 0,
606 FILE_SYNCHRONOUS_IO_NONALERT);
607 if (!NT_SUCCESS(Status))
608 {
609 DPRINT("Could not open symbol file: %wZ\n", &SymFileName);
610 return;
611 }
612
613 CPRINT("Loading symbols from %wZ...\n", &SymFileName);
614
615 /* Get the size of the file */
616 Status = ZwQueryInformationFile(FileHandle,
617 &IoStatusBlock,
618 &FileStdInfo,
619 sizeof(FileStdInfo),
620 FileStandardInformation);
621 if (!NT_SUCCESS(Status))
622 {
623 DPRINT("Could not get file size\n");
624 ZwClose(FileHandle);
625 return;
626 }
627
628 /* Allocate nonpageable memory for symbol file */
629 FileBuffer = ExAllocatePool(NonPagedPool,
630 FileStdInfo.EndOfFile.u.LowPart);
631
632 if (FileBuffer == NULL)
633 {
634 DPRINT("Could not allocate memory for symbol file\n");
635 ZwClose(FileHandle);
636 return;
637 }
638
639 /* Load file into memory chunk */
640 Status = ZwReadFile(FileHandle,
641 0, 0, 0,
642 &IoStatusBlock,
643 FileBuffer,
644 FileStdInfo.EndOfFile.u.LowPart,
645 0, 0);
646 if (!NT_SUCCESS(Status))
647 {
648 DPRINT("Could not read symbol file into memory (Status 0x%x)\n", Status);
649 ExFreePool(FileBuffer);
650 ZwClose(FileHandle);
651 return;
652 }
653
654 ZwClose(FileHandle);
655
656 SymbolFileHeader = (PSYMBOLFILE_HEADER) FileBuffer;
657 SymbolInfo->FileBuffer = FileBuffer;
658 SymbolInfo->SymbolsBase = FileBuffer + SymbolFileHeader->StabsOffset;
659 SymbolInfo->SymbolsLength = SymbolFileHeader->StabsLength;
660 SymbolInfo->SymbolStringsBase = FileBuffer + SymbolFileHeader->StabstrOffset;
661 SymbolInfo->SymbolStringsLength = SymbolFileHeader->StabstrLength;
662 }
663
664 VOID
665 KdbLdrUnloadModuleSymbols(PIMAGE_SYMBOL_INFO SymbolInfo)
666 {
667 PSYMBOL NextSymbol;
668 PSYMBOL Symbol;
669
670 DPRINT("Unloading symbols\n");
671
672 if (SymbolInfo != NULL)
673 {
674 Symbol = SymbolInfo->FileNameSymbols.Symbols;
675 while (Symbol != NULL)
676 {
677 NextSymbol = Symbol->Next;
678 RtlFreeAnsiString(&Symbol->Name);
679 ExFreePool(Symbol);
680 Symbol = NextSymbol;
681 }
682
683 SymbolInfo->FileNameSymbols.SymbolCount = 0;
684 SymbolInfo->FileNameSymbols.Symbols = NULL;
685
686 Symbol = SymbolInfo->FunctionSymbols.Symbols;
687 while (Symbol != NULL)
688 {
689 NextSymbol = Symbol->Next;
690 RtlFreeAnsiString(&Symbol->Name);
691 ExFreePool(Symbol);
692 Symbol = NextSymbol;
693 }
694
695 SymbolInfo->FunctionSymbols.SymbolCount = 0;
696 SymbolInfo->FunctionSymbols.Symbols = NULL;
697
698 Symbol = SymbolInfo->LineNumberSymbols.Symbols;
699 while (Symbol != NULL)
700 {
701 NextSymbol = Symbol->Next;
702 RtlFreeAnsiString(&Symbol->Name);
703 ExFreePool(Symbol);
704 Symbol = NextSymbol;
705 }
706
707 SymbolInfo->LineNumberSymbols.SymbolCount = 0;
708 SymbolInfo->LineNumberSymbols.Symbols = NULL;
709 #if 0
710 /* Don't free buffers because we cache symbol buffers
711 (eg. they are shared across processes) */
712 /* FIXME: We can free them if we do reference counting */
713 if (SymbolInfo->FileBuffer != NULL)
714 {
715 ExFreePool(SymbolInfo->FileBuffer);
716 SymbolInfo->FileBuffer = NULL;
717 SymbolInfo->SymbolsBase = NULL;
718 SymbolInfo->SymbolsLength = 0;
719 }
720 #endif
721 }
722 }
723
724
725 PIMAGE_SYMBOL_INFO_CACHE
726 LdrpLookupUserSymbolInfo(PLDR_MODULE LdrModule)
727 {
728 PIMAGE_SYMBOL_INFO_CACHE Current;
729 PLIST_ENTRY CurrentEntry;
730 KIRQL Irql;
731
732 DPRINT("Searching symbols for %S\n", LdrModule->FullDllName.Buffer);
733
734 KeAcquireSpinLock(&SymbolListLock, &Irql);
735
736 CurrentEntry = SymbolListHead.Flink;
737 while (CurrentEntry != (&SymbolListHead))
738 {
739 Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
740
741 if (RtlEqualUnicodeString(&Current->FullName, &LdrModule->FullDllName, TRUE))
742 {
743 KeReleaseSpinLock(&SymbolListLock, Irql);
744 return Current;
745 }
746
747 CurrentEntry = CurrentEntry->Flink;
748 }
749
750 KeReleaseSpinLock(&SymbolListLock, Irql);
751
752 return(NULL);
753 }
754
755 VOID
756 KdbLdrLoadUserModuleSymbols(PLDR_MODULE LdrModule)
757 {
758 PIMAGE_SYMBOL_INFO_CACHE CacheEntry;
759
760 DPRINT("LdrModule %p\n", LdrModule);
761
762 RtlZeroMemory(&LdrModule->SymbolInfo, sizeof(LdrModule->SymbolInfo));
763 LdrModule->SymbolInfo.ImageBase = (ULONG_PTR) LdrModule->BaseAddress;
764 LdrModule->SymbolInfo.ImageSize = LdrModule->SizeOfImage;
765
766 CacheEntry = LdrpLookupUserSymbolInfo(LdrModule);
767 if (CacheEntry != NULL)
768 {
769 DPRINT("Symbol cache hit for %S\n", CacheEntry->FullName.Buffer);
770
771 LdrModule->SymbolInfo.FileBuffer = CacheEntry->FileBuffer;
772 LdrModule->SymbolInfo.SymbolsBase = CacheEntry->SymbolsBase;
773 LdrModule->SymbolInfo.SymbolsLength = CacheEntry->SymbolsLength;
774 LdrModule->SymbolInfo.SymbolStringsBase = CacheEntry->SymbolStringsBase;
775 LdrModule->SymbolInfo.SymbolStringsLength = CacheEntry->SymbolStringsLength;
776 }
777 else
778 {
779 CacheEntry = ExAllocatePool(NonPagedPool, sizeof(IMAGE_SYMBOL_INFO_CACHE));
780 assert(CacheEntry);
781 RtlZeroMemory(CacheEntry, sizeof(IMAGE_SYMBOL_INFO_CACHE));
782
783 RtlCreateUnicodeString(&CacheEntry->FullName, LdrModule->FullDllName.Buffer);
784 assert(CacheEntry->FullName.Buffer);
785 LdrpLoadModuleSymbols(&LdrModule->FullDllName, &LdrModule->SymbolInfo);
786 InsertTailList(&SymbolListHead, &CacheEntry->ListEntry);
787 }
788 }
789
790 VOID
791 KdbLoadDriver(PUNICODE_STRING Filename, PMODULE_OBJECT Module)
792 {
793 /* Load symbols for the image if available */
794 LdrpLoadModuleSymbols(Filename, &Module->TextSection->SymbolInfo);
795 }
796
797 VOID
798 KdbUnloadDriver(PMODULE_OBJECT ModuleObject)
799 {
800 /* Unload symbols for module if available */
801 KdbLdrUnloadModuleSymbols(&ModuleObject->TextSection->SymbolInfo);
802 }
803
804 VOID
805 KdbProcessSymbolFile(PVOID ModuleLoadBase, PCHAR FileName, ULONG Length)
806 {
807 PMODULE_OBJECT ModuleObject;
808 UNICODE_STRING ModuleName;
809 CHAR TmpBaseName[MAX_PATH];
810 CHAR TmpFileName[MAX_PATH];
811 PSYMBOLFILE_HEADER SymbolFileHeader;
812 PIMAGE_SYMBOL_INFO SymbolInfo;
813 ANSI_STRING AnsiString;
814
815 DPRINT("Module %s is a symbol file\n", FileName);
816
817 strncpy(TmpBaseName, FileName, Length);
818 TmpBaseName[Length] = '\0';
819
820 DPRINT("base: %s (Length %d)\n", TmpBaseName, Length);
821
822 strcpy(TmpFileName, TmpBaseName);
823 strcat(TmpFileName, ".sys");
824 RtlInitAnsiString(&AnsiString, TmpFileName);
825
826 RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
827 ModuleObject = LdrGetModuleObject(&ModuleName);
828 RtlFreeUnicodeString(&ModuleName);
829 if (ModuleObject == NULL)
830 {
831 strcpy(TmpFileName, TmpBaseName);
832 strcat(TmpFileName, ".exe");
833 RtlInitAnsiString(&AnsiString, TmpFileName);
834 RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE);
835 ModuleObject = LdrGetModuleObject(&ModuleName);
836 RtlFreeUnicodeString(&ModuleName);
837 }
838 if (ModuleObject != NULL)
839 {
840 SymbolInfo = (PIMAGE_SYMBOL_INFO) &ModuleObject->TextSection->SymbolInfo;
841 SymbolFileHeader = (PSYMBOLFILE_HEADER) ModuleLoadBase;
842 SymbolInfo->FileBuffer = ModuleLoadBase;
843 SymbolInfo->SymbolsBase = ModuleLoadBase + SymbolFileHeader->StabsOffset;
844 SymbolInfo->SymbolsLength = SymbolFileHeader->StabsLength;
845 SymbolInfo->SymbolStringsBase = ModuleLoadBase + SymbolFileHeader->StabstrOffset;
846 SymbolInfo->SymbolStringsLength = SymbolFileHeader->StabstrLength;
847 }
848 }
849
850 VOID
851 KdbInitializeDriver(PMODULE_TEXT_SECTION ModuleTextSection)
852 {
853 RtlZeroMemory(&ModuleTextSection->SymbolInfo, sizeof(ModuleTextSection->SymbolInfo));
854 ModuleTextSection->SymbolInfo.ImageBase =
855 ModuleTextSection->OptionalHeader->ImageBase;
856 ModuleTextSection->SymbolInfo.ImageSize = ModuleTextSection->Length;
857 }
858
859 VOID
860 KdbLdrLoadAutoConfigDrivers(VOID)
861 {
862 UNICODE_STRING ModuleName;
863 PMODULE_OBJECT ModuleObject;
864
865 /*
866 * Load symbols for ntoskrnl.exe and hal.dll because \SystemRoot
867 * is created after their module entries
868 */
869
870 RtlInitUnicodeStringFromLiteral(&ModuleName, KERNEL_MODULE_NAME);
871 ModuleObject = LdrGetModuleObject(&ModuleName);
872 if (ModuleObject != NULL)
873 {
874 LdrpLoadModuleSymbols(&ModuleName,
875 &ModuleObject->TextSection->SymbolInfo);
876 }
877
878 RtlInitUnicodeStringFromLiteral(&ModuleName, HAL_MODULE_NAME);
879 ModuleObject = LdrGetModuleObject(&ModuleName);
880 if (ModuleObject != NULL)
881 {
882 LdrpLoadModuleSymbols(&ModuleName,
883 &ModuleObject->TextSection->SymbolInfo);
884 }
885 }