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