- Fix KiDispatchException to unmask KI_EXCEPTION_INTERNAL when setting the exception...
[reactos.git] / reactos / ntoskrnl / kdbg / kdb_symbols.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/dbg/kdb_symbols.c
5 * PURPOSE: Getting symbol information...
6 *
7 * PROGRAMMERS: David Welch (welch@cwcom.net)
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntoskrnl.h>
13
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS ******************************************************************/
18
19 typedef struct _IMAGE_SYMBOL_INFO_CACHE {
20 LIST_ENTRY ListEntry;
21 ULONG RefCount;
22 UNICODE_STRING FileName;
23 PROSSYM_INFO RosSymInfo;
24 } IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE;
25
26 static BOOLEAN LoadSymbols;
27 static LIST_ENTRY SymbolFileListHead;
28 static KSPIN_LOCK SymbolFileListLock;
29
30
31 /* FUNCTIONS ****************************************************************/
32
33 /*! \brief Find a user-mode module...
34 *
35 * \param Address If \a Address is not NULL the module containing \a Address
36 * is searched.
37 * \param Name If \a Name is not NULL the module named \a Name will be
38 * searched.
39 * \param Index If \a Index is >= 0 the Index'th module will be returned.
40 * \param pInfo Pointer to a KDB_MODULE_INFO which is filled.
41 *
42 * \retval TRUE Module was found, \a pInfo was filled.
43 * \retval FALSE No module was found.
44 *
45 * \sa KdbpSymFindModule
46 */
47 STATIC BOOLEAN
48 KdbpSymFindUserModule(IN PVOID Address OPTIONAL,
49 IN LPCWSTR Name OPTIONAL,
50 IN INT Index OPTIONAL,
51 OUT PKDB_MODULE_INFO pInfo)
52 {
53 PLIST_ENTRY current_entry;
54 PLDR_DATA_TABLE_ENTRY current;
55 PEPROCESS CurrentProcess;
56 PPEB Peb = NULL;
57 INT Count = 0;
58 INT Length;
59
60 CurrentProcess = PsGetCurrentProcess();
61 if (CurrentProcess != NULL)
62 {
63 Peb = CurrentProcess->Peb;
64 }
65
66 if (Peb == NULL || Peb->Ldr == NULL)
67 {
68 return FALSE;
69 }
70
71 current_entry = Peb->Ldr->InLoadOrderModuleList.Flink;
72
73 while (current_entry != &Peb->Ldr->InLoadOrderModuleList &&
74 current_entry != NULL)
75 {
76 current = CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
77 Length = min(current->BaseDllName.Length / sizeof(WCHAR), 255);
78 if ((Address != NULL && (Address >= (PVOID)current->DllBase &&
79 Address < (PVOID)((char *)current->DllBase + current->SizeOfImage))) ||
80 (Name != NULL && _wcsnicmp(current->BaseDllName.Buffer, Name, Length) == 0) ||
81 (Index >= 0 && Count++ == Index))
82 {
83 wcsncpy(pInfo->Name, current->BaseDllName.Buffer, Length);
84 pInfo->Name[Length] = L'\0';
85 pInfo->Base = (ULONG_PTR)current->DllBase;
86 pInfo->Size = current->SizeOfImage;
87 pInfo->RosSymInfo = current->PatchInformation;
88 return TRUE;
89 }
90 current_entry = current_entry->Flink;
91 }
92
93 return FALSE;
94 }
95
96 /*! \brief Find a kernel-mode module...
97 *
98 * Works like \a KdbpSymFindUserModule.
99 *
100 * \sa KdbpSymFindUserModule
101 */
102 STATIC BOOLEAN
103 KdbpSymFindModule(IN PVOID Address OPTIONAL,
104 IN LPCWSTR Name OPTIONAL,
105 IN INT Index OPTIONAL,
106 OUT PKDB_MODULE_INFO pInfo)
107 {
108 PLIST_ENTRY current_entry;
109 PLDR_DATA_TABLE_ENTRY current;
110 INT Count = 0;
111 INT Length;
112
113 current_entry = PsLoadedModuleList.Flink;
114
115 while (current_entry != &PsLoadedModuleList)
116 {
117 current = CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
118
119 Length = min(current->BaseDllName.Length / sizeof(WCHAR), 255);
120 if ((Address != NULL && (Address >= (PVOID)current->DllBase &&
121 Address < (PVOID)((ULONG_PTR)current->DllBase + current->SizeOfImage))) ||
122 (Name != NULL && _wcsnicmp(current->BaseDllName.Buffer, Name, Length) == 0) ||
123 (Index >= 0 && Count++ == Index))
124 {
125 wcsncpy(pInfo->Name, current->BaseDllName.Buffer, Length);
126 pInfo->Name[Length] = L'\0';
127 pInfo->Base = (ULONG_PTR)current->DllBase;
128 pInfo->Size = current->SizeOfImage;
129 pInfo->RosSymInfo = current->PatchInformation;
130 return TRUE;
131 }
132 current_entry = current_entry->Flink;
133 }
134
135 return KdbpSymFindUserModule(Address, Name, Index-Count, pInfo);
136 }
137
138 /*! \brief Find module by address...
139 *
140 * \param Address Any address inside the module to look for.
141 * \param pInfo Pointer to a KDB_MODULE_INFO struct which is filled on
142 * success.
143 *
144 * \retval TRUE Success - module found.
145 * \retval FALSE Failure - module not found.
146 *
147 * \sa KdbpSymFindModuleByName
148 * \sa KdbpSymFindModuleByIndex
149 */
150 BOOLEAN
151 KdbpSymFindModuleByAddress(IN PVOID Address,
152 OUT PKDB_MODULE_INFO pInfo)
153 {
154 return KdbpSymFindModule(Address, NULL, -1, pInfo);
155 }
156
157 /*! \brief Find module by name...
158 *
159 * \param Name Name of the module to look for.
160 * \param pInfo Pointer to a KDB_MODULE_INFO struct which is filled on
161 * success.
162 *
163 * \retval TRUE Success - module found.
164 * \retval FALSE Failure - module not found.
165 *
166 * \sa KdbpSymFindModuleByAddress
167 * \sa KdbpSymFindModuleByIndex
168 */
169 BOOLEAN
170 KdbpSymFindModuleByName(IN LPCWSTR Name,
171 OUT PKDB_MODULE_INFO pInfo)
172 {
173 return KdbpSymFindModule(NULL, Name, -1, pInfo);
174 }
175
176 /*! \brief Find module by index...
177 *
178 * \param Index Index of the module to return.
179 * \param pInfo Pointer to a KDB_MODULE_INFO struct which is filled on
180 * success.
181 *
182 * \retval TRUE Success - module found.
183 * \retval FALSE Failure - module not found.
184 *
185 * \sa KdbpSymFindModuleByName
186 * \sa KdbpSymFindModuleByAddress
187 */
188 BOOLEAN
189 KdbpSymFindModuleByIndex(IN INT Index,
190 OUT PKDB_MODULE_INFO pInfo)
191 {
192 return KdbpSymFindModule(NULL, NULL, Index, pInfo);
193 }
194
195 /*! \brief Print address...
196 *
197 * Tries to lookup line number, file name and function name for the given
198 * address and prints it.
199 * If no such information is found the address is printed in the format
200 * <module: offset>, otherwise the format will be
201 * <module: offset (filename:linenumber (functionname))>
202 *
203 * \retval TRUE Module containing \a Address was found, \a Address was printed.
204 * \retval FALSE No module containing \a Address was found, nothing was printed.
205 */
206 BOOLEAN
207 KdbSymPrintAddress(IN PVOID Address)
208 {
209 KDB_MODULE_INFO Info;
210 ULONG_PTR RelativeAddress;
211 NTSTATUS Status;
212 ULONG LineNumber;
213 CHAR FileName[256];
214 CHAR FunctionName[256];
215
216 if (!KdbpSymFindModuleByAddress(Address, &Info))
217 return FALSE;
218
219 RelativeAddress = (ULONG_PTR) Address - Info.Base;
220 Status = KdbSymGetAddressInformation(Info.RosSymInfo,
221 RelativeAddress,
222 &LineNumber,
223 FileName,
224 FunctionName);
225 if (NT_SUCCESS(Status))
226 {
227 DbgPrint("<%ws:%x (%s:%d (%s))>",
228 Info.Name, RelativeAddress, FileName, LineNumber, FunctionName);
229 }
230 else
231 {
232 DbgPrint("<%ws:%x>", Info.Name, RelativeAddress);
233 }
234
235 return TRUE;
236 }
237
238
239 /*! \brief Get information for an address (source file, line number,
240 * function name)
241 *
242 * \param SymbolInfo Pointer to ROSSYM_INFO.
243 * \param RelativeAddress Relative address to look up.
244 * \param LineNumber Pointer to an ULONG which is filled with the line
245 * number (can be NULL)
246 * \param FileName Pointer to an array of CHARs which gets filled with
247 * the filename (can be NULL)
248 * \param FunctionName Pointer to an array of CHARs which gets filled with
249 * the function name (can be NULL)
250 *
251 * \returns NTSTATUS error code.
252 * \retval STATUS_SUCCESS At least one of the requested informations was found.
253 * \retval STATUS_UNSUCCESSFUL None of the requested information was found.
254 */
255 NTSTATUS
256 KdbSymGetAddressInformation(IN PROSSYM_INFO RosSymInfo,
257 IN ULONG_PTR RelativeAddress,
258 OUT PULONG LineNumber OPTIONAL,
259 OUT PCH FileName OPTIONAL,
260 OUT PCH FunctionName OPTIONAL)
261 {
262 if (NULL == RosSymInfo)
263 {
264 return STATUS_UNSUCCESSFUL;
265 }
266
267 if (! RosSymGetAddressInformation(RosSymInfo, RelativeAddress, LineNumber,
268 FileName, FunctionName))
269 {
270 return STATUS_UNSUCCESSFUL;
271 }
272
273 return STATUS_SUCCESS;
274 }
275
276 /*! \brief Find cached symbol file.
277 *
278 * Looks through the list of cached symbol files and tries to find an already
279 * loaded one.
280 *
281 * \param FileName FileName of the symbol file to look for.
282 *
283 * \returns A pointer to the cached symbol info.
284 * \retval NULL No cached info found.
285 *
286 * \sa KdbpSymAddCachedFile
287 */
288 STATIC PROSSYM_INFO
289 KdbpSymFindCachedFile(IN PUNICODE_STRING FileName)
290 {
291 PIMAGE_SYMBOL_INFO_CACHE Current;
292 PLIST_ENTRY CurrentEntry;
293 KIRQL Irql;
294
295 DPRINT("Looking for cached symbol file %wZ\n", FileName);
296
297 KeAcquireSpinLock(&SymbolFileListLock, &Irql);
298
299 CurrentEntry = SymbolFileListHead.Flink;
300 while (CurrentEntry != (&SymbolFileListHead))
301 {
302 Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
303
304 DPRINT("Current->FileName %wZ FileName %wZ\n", &Current->FileName, FileName);
305 if (RtlEqualUnicodeString(&Current->FileName, FileName, TRUE))
306 {
307 Current->RefCount++;
308 KeReleaseSpinLock(&SymbolFileListLock, Irql);
309 DPRINT("Found cached file!\n");
310 return Current->RosSymInfo;
311 }
312
313 CurrentEntry = CurrentEntry->Flink;
314 }
315
316 KeReleaseSpinLock(&SymbolFileListLock, Irql);
317
318 DPRINT("Cached file not found!\n");
319 return NULL;
320 }
321
322 /*! \brief Add a symbol file to the cache.
323 *
324 * \param FileName Filename of the symbol file.
325 * \param RosSymInfo Pointer to the symbol info.
326 *
327 * \sa KdbpSymRemoveCachedFile
328 */
329 STATIC VOID
330 KdbpSymAddCachedFile(IN PUNICODE_STRING FileName,
331 IN PROSSYM_INFO RosSymInfo)
332 {
333 PIMAGE_SYMBOL_INFO_CACHE CacheEntry;
334
335 DPRINT("Adding symbol file: RosSymInfo = %p\n", RosSymInfo);
336
337 /* allocate entry */
338 CacheEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE), TAG_KDBS);
339 ASSERT(CacheEntry);
340 RtlZeroMemory(CacheEntry, sizeof (IMAGE_SYMBOL_INFO_CACHE));
341
342 /* fill entry */
343 RtlCreateUnicodeString(&CacheEntry->FileName, FileName->Buffer);
344 ASSERT(CacheEntry->FileName.Buffer);
345 CacheEntry->RefCount = 1;
346 CacheEntry->RosSymInfo = RosSymInfo;
347 InsertTailList(&SymbolFileListHead, &CacheEntry->ListEntry); /* FIXME: Lock list? */
348 }
349
350 /*! \brief Remove a symbol file (reference) from the cache.
351 *
352 * Tries to find a cache entry matching the given symbol info and decreases
353 * it's reference count. If the refcount is 0 after decreasing it the cache
354 * entry will be removed from the list and freed.
355 *
356 * \param RosSymInfo Pointer to the symbol info.
357 *
358 * \sa KdbpSymAddCachedFile
359 */
360 STATIC VOID
361 KdbpSymRemoveCachedFile(IN PROSSYM_INFO RosSymInfo)
362 {
363 PIMAGE_SYMBOL_INFO_CACHE Current;
364 PLIST_ENTRY CurrentEntry;
365 KIRQL Irql;
366
367 KeAcquireSpinLock(&SymbolFileListLock, &Irql);
368
369 CurrentEntry = SymbolFileListHead.Flink;
370 while (CurrentEntry != (&SymbolFileListHead))
371 {
372 Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
373
374 if (Current->RosSymInfo == RosSymInfo) /* found */
375 {
376 ASSERT(Current->RefCount > 0);
377 Current->RefCount--;
378 if (Current->RefCount < 1)
379 {
380 RemoveEntryList(&Current->ListEntry);
381 RosSymDelete(Current->RosSymInfo);
382 ExFreePool(Current);
383 }
384 KeReleaseSpinLock(&SymbolFileListLock, Irql);
385 return;
386 }
387
388 CurrentEntry = CurrentEntry->Flink;
389 }
390
391 KeReleaseSpinLock(&SymbolFileListLock, Irql);
392 DPRINT1("Warning: Removing unknown symbol file: RosSymInfo = %p\n", RosSymInfo);
393 }
394
395 /*! \brief Loads a symbol file.
396 *
397 * \param FileName Filename of the symbol file to load.
398 * \param RosSymInfo Pointer to a ROSSYM_INFO which gets filled.
399 *
400 * \sa KdbpSymUnloadModuleSymbols
401 */
402 STATIC VOID
403 KdbpSymLoadModuleSymbols(IN PUNICODE_STRING FileName,
404 OUT PROSSYM_INFO *RosSymInfo)
405 {
406 OBJECT_ATTRIBUTES ObjectAttributes;
407 HANDLE FileHandle;
408 NTSTATUS Status;
409 IO_STATUS_BLOCK IoStatusBlock;
410
411 /* Allow KDB to break on module load */
412 KdbModuleLoaded(FileName);
413
414 if (! LoadSymbols)
415 {
416 *RosSymInfo = NULL;
417 return;
418 }
419
420 /* Try to find cached (already loaded) symbol file */
421 *RosSymInfo = KdbpSymFindCachedFile(FileName);
422 if (*RosSymInfo != NULL)
423 {
424 DPRINT("Found cached symbol file %wZ\n", FileName);
425 return;
426 }
427
428 /* Open the file */
429 InitializeObjectAttributes(&ObjectAttributes,
430 FileName,
431 0,
432 NULL,
433 NULL);
434
435 DPRINT("Attempting to open image: %wZ\n", FileName);
436
437 Status = ZwOpenFile(&FileHandle,
438 FILE_READ_ACCESS,
439 &ObjectAttributes,
440 &IoStatusBlock,
441 FILE_SHARE_READ|FILE_SHARE_WRITE,
442 FILE_SYNCHRONOUS_IO_NONALERT);
443 if (!NT_SUCCESS(Status))
444 {
445 DPRINT("Could not open image file: %wZ\n", &FileName);
446 return;
447 }
448
449 DPRINT("Loading symbols from %wZ...\n", FileName);
450
451 if (! RosSymCreateFromFile(&FileHandle, RosSymInfo))
452 {
453 DPRINT("Failed to load symbols from %wZ\n", FileName);
454 return;
455 }
456
457 ZwClose(FileHandle);
458
459 DPRINT("Symbols loaded.\n");
460
461 /* add file to cache */
462 KdbpSymAddCachedFile(FileName, *RosSymInfo);
463
464 DPRINT("Installed symbols: %wZ %p\n", FileName, *RosSymInfo);
465 }
466
467 /*! \brief Unloads symbol info.
468 *
469 * \param RosSymInfo Pointer to the symbol info to unload.
470 *
471 * \sa KdbpSymLoadModuleSymbols
472 */
473 STATIC VOID
474 KdbpSymUnloadModuleSymbols(IN PROSSYM_INFO RosSymInfo)
475 {
476 DPRINT("Unloading symbols\n");
477
478 if (RosSymInfo != NULL)
479 {
480 KdbpSymRemoveCachedFile(RosSymInfo);
481 }
482 }
483
484 /*! \brief Load symbol info for a user module.
485 *
486 * \param LdrModule Pointer to the module to load symbols for.
487 */
488 VOID
489 KdbSymLoadUserModuleSymbols(IN PLDR_DATA_TABLE_ENTRY LdrModule)
490 {
491 static WCHAR Prefix[] = L"\\??\\";
492 UNICODE_STRING KernelName;
493 DPRINT("LdrModule %p\n", LdrModule);
494
495 LdrModule->PatchInformation = NULL;
496
497 KernelName.MaximumLength = sizeof(Prefix) + LdrModule->FullDllName.Length;
498 KernelName.Length = KernelName.MaximumLength - sizeof(WCHAR);
499 KernelName.Buffer = ExAllocatePoolWithTag(PagedPool, KernelName.MaximumLength, TAG_KDBS);
500 if (NULL == KernelName.Buffer)
501 {
502 return;
503 }
504 memcpy(KernelName.Buffer, Prefix, sizeof(Prefix) - sizeof(WCHAR));
505 memcpy(KernelName.Buffer + sizeof(Prefix) / sizeof(WCHAR) - 1, LdrModule->FullDllName.Buffer,
506 LdrModule->FullDllName.Length);
507 KernelName.Buffer[KernelName.Length / sizeof(WCHAR)] = L'\0';
508
509 KdbpSymLoadModuleSymbols(&KernelName, (PROSSYM_INFO*)&LdrModule->PatchInformation);
510
511 ExFreePool(KernelName.Buffer);
512 }
513
514 /*! \brief Frees all symbols loaded for a process.
515 *
516 * \param Process Pointer to a process.
517 */
518 VOID
519 KdbSymFreeProcessSymbols(IN PEPROCESS Process)
520 {
521 PLIST_ENTRY CurrentEntry;
522 PLDR_DATA_TABLE_ENTRY Current;
523 PEPROCESS CurrentProcess;
524 PPEB Peb;
525
526 CurrentProcess = PsGetCurrentProcess();
527 if (CurrentProcess != Process)
528 {
529 KeAttachProcess(&Process->Pcb);
530 }
531 Peb = Process->Peb;
532 ASSERT(Peb);
533 ASSERT(Peb->Ldr);
534
535 CurrentEntry = Peb->Ldr->InLoadOrderModuleList.Flink;
536 while (CurrentEntry != &Peb->Ldr->InLoadOrderModuleList &&
537 CurrentEntry != NULL)
538 {
539 Current = CONTAINING_RECORD(CurrentEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
540
541 KdbpSymUnloadModuleSymbols(Current->PatchInformation);
542
543 CurrentEntry = CurrentEntry->Flink;
544 }
545 if (CurrentProcess != Process)
546 {
547 KeDetachProcess();
548 }
549 }
550
551 /*! \brief Load symbol info for a driver.
552 *
553 * \param Filename Filename of the driver.
554 * \param Module Pointer to the driver LDR_DATA_TABLE_ENTRY.
555 */
556 VOID
557 KdbSymLoadDriverSymbols(IN PUNICODE_STRING Filename,
558 IN PLDR_DATA_TABLE_ENTRY Module)
559 {
560 /* Load symbols for the image if available */
561 DPRINT("Loading driver %wZ symbols (driver @ %08x)\n", Filename, Module->DllBase);
562
563 Module->PatchInformation = NULL;
564
565 KdbpSymLoadModuleSymbols(Filename, (PROSSYM_INFO*)&Module->PatchInformation);
566 }
567
568 /*! \brief Unloads symbol info for a driver.
569 *
570 * \param ModuleObject Pointer to the driver LDR_DATA_TABLE_ENTRY.
571 */
572 VOID
573 KdbSymUnloadDriverSymbols(IN PLDR_DATA_TABLE_ENTRY ModuleObject)
574 {
575 /* Unload symbols for module if available */
576 KdbpSymUnloadModuleSymbols(ModuleObject->PatchInformation);
577 ModuleObject->PatchInformation = NULL;
578 }
579
580 /*! \brief Called when a symbol file is loaded by the loader?
581 *
582 * Tries to find a driver (.sys) or executable (.exe) with the same base name
583 * as the symbol file and sets the drivers/exes symbol info to the loaded
584 * module.
585 * Used to load ntoskrnl and hal symbols before the SystemRoot is available to us.
586 *
587 * \param FileName Filename for which the symbols are loaded.
588 */
589 VOID
590 KdbSymProcessBootSymbols(IN PUNICODE_STRING FileName)
591 {
592 PLDR_DATA_TABLE_ENTRY ModuleObject;
593 BOOLEAN Found = FALSE;
594 BOOLEAN IsRaw;
595 PLIST_ENTRY ListHead, NextEntry;
596 PLDR_DATA_TABLE_ENTRY LdrEntry;
597 PUNICODE_STRING ModuleName = FileName;
598 UNICODE_STRING NtosSymName = RTL_CONSTANT_STRING(L"ntoskrnl.sym");
599 UNICODE_STRING NtosName = RTL_CONSTANT_STRING(L"ntoskrnl.exe");
600
601 if (RtlEqualUnicodeString(FileName, &NtosSymName, TRUE))
602 {
603 ModuleName = &NtosName;
604 IsRaw = TRUE;
605 }
606 else
607 {
608 IsRaw = FALSE;
609 }
610
611 ModuleObject = NULL;
612
613 if (ModuleObject != NULL)
614 {
615 if (! LoadSymbols)
616 {
617 ModuleObject->PatchInformation = NULL;
618 return;
619 }
620
621 ListHead = &KeLoaderBlock->LoadOrderListHead;
622 NextEntry = ListHead->Flink;
623 while (ListHead != NextEntry)
624 {
625 /* Get the entry */
626 LdrEntry = CONTAINING_RECORD(NextEntry,
627 LDR_DATA_TABLE_ENTRY,
628 InLoadOrderLinks);
629
630 if (RtlEqualUnicodeString(FileName, &LdrEntry->BaseDllName, TRUE))
631 {
632 Found = TRUE;
633 break;
634 }
635
636 /* Go to the next one */
637 NextEntry = NextEntry->Flink;
638 }
639
640 if (Found)
641 {
642 if (ModuleObject->PatchInformation != NULL)
643 {
644 KdbpSymRemoveCachedFile(ModuleObject->PatchInformation);
645 }
646
647 if (IsRaw)
648 {
649 DPRINT("Data: %p %p %wZ\n", LdrEntry->DllBase, LdrEntry->SizeOfImage, &LdrEntry->FullDllName);
650 if (! RosSymCreateFromRaw(LdrEntry->DllBase,
651 LdrEntry->SizeOfImage,
652 (PROSSYM_INFO*)&ModuleObject->PatchInformation))
653 {
654 return;
655 }
656 }
657 else
658 {
659 if (! RosSymCreateFromMem(LdrEntry->DllBase,
660 LdrEntry->SizeOfImage,
661 (PROSSYM_INFO*)&ModuleObject->PatchInformation))
662 {
663 return;
664 }
665 }
666
667 /* add file to cache */
668 KdbpSymAddCachedFile(FileName, ModuleObject->PatchInformation);
669
670 DPRINT("Installed symbols: %wZ@%08x-%08x %p\n",
671 FileName,
672 ModuleObject->DllBase,
673 ModuleObject->SizeOfImage + (ULONG)ModuleObject->DllBase,
674 ModuleObject->PatchInformation);
675 }
676 }
677 }
678
679 /*! \brief Initializes the KDB symbols implementation.
680 *
681 * \param NtoskrnlModuleObject LDR_DATA_TABLE_ENTRY of ntoskrnl.exe
682 * \param LdrHalModuleObject LDR_DATA_TABLE_ENTRY of hal.sys
683 */
684 VOID
685 KdbSymInit(IN PLDR_DATA_TABLE_ENTRY NtoskrnlModuleObject,
686 IN PLDR_DATA_TABLE_ENTRY LdrHalModuleObject)
687 {
688 PCHAR p1, p2;
689 int Found;
690 char YesNo;
691
692 NtoskrnlModuleObject->PatchInformation = NULL;
693 LdrHalModuleObject->PatchInformation = NULL;
694
695 InitializeListHead(&SymbolFileListHead);
696 KeInitializeSpinLock(&SymbolFileListLock);
697
698 #ifdef DBG
699 LoadSymbols = TRUE;
700 #else
701 LoadSymbols = FALSE;
702 #endif
703
704 /* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS,
705 * /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */
706 p1 = KeLoaderBlock->LoadOptions;
707 while('\0' != *p1 && NULL != (p2 = strchr(p1, '/')))
708 {
709 p2++;
710 Found = 0;
711 if (0 == _strnicmp(p2, "LOADSYMBOLS", 11))
712 {
713 Found = +1;
714 p2 += 11;
715 }
716 else if (0 == _strnicmp(p2, "NOLOADSYMBOLS", 13))
717 {
718 Found = -1;
719 p2 += 13;
720 }
721 if (0 != Found)
722 {
723 while (isspace(*p2))
724 {
725 p2++;
726 }
727 if ('=' == *p2)
728 {
729 p2++;
730 while (isspace(*p2))
731 {
732 p2++;
733 }
734 YesNo = toupper(*p2);
735 if ('N' == YesNo || 'F' == YesNo || '0' == YesNo)
736 {
737 Found = -1 * Found;
738 }
739 }
740 LoadSymbols = (0 < Found);
741 }
742 p1 = p2;
743 }
744
745 RosSymInitKernelMode();
746 }
747
748 /* EOF */