Create a branch for network fixes.
[reactos.git] / 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 CacheEntry->FileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
344 FileName->Length,
345 TAG_KDBS);
346 RtlInitUnicodeString(&CacheEntry->FileName, FileName->Buffer);
347 ASSERT(CacheEntry->FileName.Buffer);
348 CacheEntry->RefCount = 1;
349 CacheEntry->RosSymInfo = RosSymInfo;
350 InsertTailList(&SymbolFileListHead, &CacheEntry->ListEntry); /* FIXME: Lock list? */
351 }
352
353 /*! \brief Remove a symbol file (reference) from the cache.
354 *
355 * Tries to find a cache entry matching the given symbol info and decreases
356 * it's reference count. If the refcount is 0 after decreasing it the cache
357 * entry will be removed from the list and freed.
358 *
359 * \param RosSymInfo Pointer to the symbol info.
360 *
361 * \sa KdbpSymAddCachedFile
362 */
363 STATIC VOID
364 KdbpSymRemoveCachedFile(IN PROSSYM_INFO RosSymInfo)
365 {
366 PIMAGE_SYMBOL_INFO_CACHE Current;
367 PLIST_ENTRY CurrentEntry;
368 KIRQL Irql;
369
370 KeAcquireSpinLock(&SymbolFileListLock, &Irql);
371
372 CurrentEntry = SymbolFileListHead.Flink;
373 while (CurrentEntry != (&SymbolFileListHead))
374 {
375 Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
376
377 if (Current->RosSymInfo == RosSymInfo) /* found */
378 {
379 ASSERT(Current->RefCount > 0);
380 Current->RefCount--;
381 if (Current->RefCount < 1)
382 {
383 RemoveEntryList(&Current->ListEntry);
384 RosSymDelete(Current->RosSymInfo);
385 ExFreePool(Current);
386 }
387 KeReleaseSpinLock(&SymbolFileListLock, Irql);
388 return;
389 }
390
391 CurrentEntry = CurrentEntry->Flink;
392 }
393
394 KeReleaseSpinLock(&SymbolFileListLock, Irql);
395 DPRINT1("Warning: Removing unknown symbol file: RosSymInfo = %p\n", RosSymInfo);
396 }
397
398 /*! \brief Loads a symbol file.
399 *
400 * \param FileName Filename of the symbol file to load.
401 * \param RosSymInfo Pointer to a ROSSYM_INFO which gets filled.
402 *
403 * \sa KdbpSymUnloadModuleSymbols
404 */
405 STATIC VOID
406 KdbpSymLoadModuleSymbols(IN PUNICODE_STRING FileName,
407 OUT PROSSYM_INFO *RosSymInfo)
408 {
409 OBJECT_ATTRIBUTES ObjectAttributes;
410 HANDLE FileHandle;
411 NTSTATUS Status;
412 IO_STATUS_BLOCK IoStatusBlock;
413
414 /* Allow KDB to break on module load */
415 KdbModuleLoaded(FileName);
416
417 if (! LoadSymbols)
418 {
419 *RosSymInfo = NULL;
420 return;
421 }
422
423 /* Try to find cached (already loaded) symbol file */
424 *RosSymInfo = KdbpSymFindCachedFile(FileName);
425 if (*RosSymInfo != NULL)
426 {
427 DPRINT("Found cached symbol file %wZ\n", FileName);
428 return;
429 }
430
431 /* Open the file */
432 InitializeObjectAttributes(&ObjectAttributes,
433 FileName,
434 0,
435 NULL,
436 NULL);
437
438 DPRINT("Attempting to open image: %wZ\n", FileName);
439
440 Status = ZwOpenFile(&FileHandle,
441 FILE_READ_ACCESS,
442 &ObjectAttributes,
443 &IoStatusBlock,
444 FILE_SHARE_READ|FILE_SHARE_WRITE,
445 FILE_SYNCHRONOUS_IO_NONALERT);
446 if (!NT_SUCCESS(Status))
447 {
448 DPRINT("Could not open image file: %wZ\n", FileName);
449 return;
450 }
451
452 DPRINT("Loading symbols from %wZ...\n", FileName);
453
454 if (! RosSymCreateFromFile(&FileHandle, RosSymInfo))
455 {
456 DPRINT("Failed to load symbols from %wZ\n", FileName);
457 return;
458 }
459
460 ZwClose(FileHandle);
461
462 DPRINT("Symbols loaded.\n");
463
464 /* add file to cache */
465 KdbpSymAddCachedFile(FileName, *RosSymInfo);
466
467 DPRINT("Installed symbols: %wZ %p\n", FileName, *RosSymInfo);
468 }
469
470 /*! \brief Unloads symbol info.
471 *
472 * \param RosSymInfo Pointer to the symbol info to unload.
473 *
474 * \sa KdbpSymLoadModuleSymbols
475 */
476 STATIC VOID
477 KdbpSymUnloadModuleSymbols(IN PROSSYM_INFO RosSymInfo)
478 {
479 DPRINT("Unloading symbols\n");
480
481 if (RosSymInfo != NULL)
482 {
483 KdbpSymRemoveCachedFile(RosSymInfo);
484 }
485 }
486
487 /*! \brief Load symbol info for a user module.
488 *
489 * \param LdrModule Pointer to the module to load symbols for.
490 */
491 VOID
492 KdbSymLoadUserModuleSymbols(IN PLDR_DATA_TABLE_ENTRY LdrModule)
493 {
494 static WCHAR Prefix[] = L"\\??\\";
495 UNICODE_STRING KernelName;
496 DPRINT("LdrModule %p\n", LdrModule);
497
498 LdrModule->PatchInformation = NULL;
499
500 KernelName.MaximumLength = sizeof(Prefix) + LdrModule->FullDllName.Length;
501 KernelName.Length = KernelName.MaximumLength - sizeof(WCHAR);
502 KernelName.Buffer = ExAllocatePoolWithTag(PagedPool, KernelName.MaximumLength, TAG_KDBS);
503 if (NULL == KernelName.Buffer)
504 {
505 return;
506 }
507 memcpy(KernelName.Buffer, Prefix, sizeof(Prefix) - sizeof(WCHAR));
508 memcpy(KernelName.Buffer + sizeof(Prefix) / sizeof(WCHAR) - 1, LdrModule->FullDllName.Buffer,
509 LdrModule->FullDllName.Length);
510 KernelName.Buffer[KernelName.Length / sizeof(WCHAR)] = L'\0';
511
512 KdbpSymLoadModuleSymbols(&KernelName, (PROSSYM_INFO*)&LdrModule->PatchInformation);
513
514 ExFreePool(KernelName.Buffer);
515 }
516
517 /*! \brief Frees all symbols loaded for a process.
518 *
519 * \param Process Pointer to a process.
520 */
521 VOID
522 KdbSymFreeProcessSymbols(IN PEPROCESS Process)
523 {
524 PLIST_ENTRY CurrentEntry;
525 PLDR_DATA_TABLE_ENTRY Current;
526 PEPROCESS CurrentProcess;
527 PPEB Peb;
528
529 CurrentProcess = PsGetCurrentProcess();
530 if (CurrentProcess != Process)
531 {
532 KeAttachProcess(&Process->Pcb);
533 }
534 Peb = Process->Peb;
535 ASSERT(Peb);
536 ASSERT(Peb->Ldr);
537
538 CurrentEntry = Peb->Ldr->InLoadOrderModuleList.Flink;
539 while (CurrentEntry != &Peb->Ldr->InLoadOrderModuleList &&
540 CurrentEntry != NULL)
541 {
542 Current = CONTAINING_RECORD(CurrentEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
543
544 KdbpSymUnloadModuleSymbols(Current->PatchInformation);
545
546 CurrentEntry = CurrentEntry->Flink;
547 }
548 if (CurrentProcess != Process)
549 {
550 KeDetachProcess();
551 }
552 }
553
554 /*! \brief Load symbol info for a driver.
555 *
556 * \param Filename Filename of the driver.
557 * \param Module Pointer to the driver LDR_DATA_TABLE_ENTRY.
558 */
559 VOID
560 KdbSymLoadDriverSymbols(IN PUNICODE_STRING Filename,
561 IN PLDR_DATA_TABLE_ENTRY Module)
562 {
563 /* Load symbols for the image if available */
564 DPRINT("Loading driver %wZ symbols (driver @ %08x)\n", Filename, Module->DllBase);
565
566 Module->PatchInformation = NULL;
567
568 KdbpSymLoadModuleSymbols(Filename, (PROSSYM_INFO*)&Module->PatchInformation);
569 }
570
571 /*! \brief Unloads symbol info for a driver.
572 *
573 * \param ModuleObject Pointer to the driver LDR_DATA_TABLE_ENTRY.
574 */
575 VOID
576 KdbSymUnloadDriverSymbols(IN PLDR_DATA_TABLE_ENTRY ModuleObject)
577 {
578 /* Unload symbols for module if available */
579 KdbpSymUnloadModuleSymbols(ModuleObject->PatchInformation);
580 ModuleObject->PatchInformation = NULL;
581 }
582
583 VOID
584 KdbSymProcessSymbols(IN PANSI_STRING AnsiFileName, IN PKD_SYMBOLS_INFO SymbolInfo)
585 {
586 BOOLEAN Found = FALSE;
587 PLIST_ENTRY ListHead, NextEntry;
588 PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
589
590 //DPRINT("KdbSymProcessSymbols(%Z)\n", AnsiFileName);
591
592 /* We use PsLoadedModuleList here, otherwise (in case of
593 using KeLoaderBlock) all our data will be just lost */
594 ListHead = &PsLoadedModuleList;
595
596 /* Found module we are interested in */
597 NextEntry = ListHead->Flink;
598 while (ListHead != NextEntry)
599 {
600 /* Get the entry */
601 LdrEntry = CONTAINING_RECORD(NextEntry,
602 LDR_DATA_TABLE_ENTRY,
603 InLoadOrderLinks);
604
605 if (SymbolInfo->BaseOfDll == LdrEntry->DllBase)
606 {
607 Found = TRUE;
608 break;
609 }
610
611 /* Go to the next one */
612 NextEntry = NextEntry->Flink;
613 }
614
615 /* Exit if we didn't find the module requested */
616 if (!Found)
617 return;
618
619 DPRINT("Found LdrEntry=%p\n", LdrEntry);
620 if (!LoadSymbols)
621 {
622 LdrEntry->PatchInformation = NULL;
623 return;
624 }
625
626 /* Remove symbol info if it already exists */
627 if (LdrEntry->PatchInformation != NULL)
628 {
629 KdbpSymRemoveCachedFile(LdrEntry->PatchInformation);
630 }
631
632 /* Load new symbol information */
633 if (! RosSymCreateFromMem(LdrEntry->DllBase,
634 LdrEntry->SizeOfImage,
635 (PROSSYM_INFO*)&LdrEntry->PatchInformation))
636 {
637 /* Error loading symbol info, try to load it from file */
638 KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName,
639 (PROSSYM_INFO*)&LdrEntry->PatchInformation);
640
641 /* It already added symbols to cache */
642 }
643 else
644 {
645 /* Add file to cache */
646 KdbpSymAddCachedFile(&LdrEntry->FullDllName, LdrEntry->PatchInformation);
647 }
648
649 DPRINT("Installed symbols: %wZ@%08x-%08x %p\n",
650 &LdrEntry->BaseDllName,
651 LdrEntry->DllBase,
652 LdrEntry->SizeOfImage + (ULONG)LdrEntry->DllBase,
653 LdrEntry->PatchInformation);
654
655 }
656
657 VOID
658 NTAPI
659 KdbDebugPrint(PCH Message, ULONG Length)
660 {
661 /* Nothing here */
662 }
663
664
665 /*! \brief Initializes the KDB symbols implementation.
666 *
667 * \param DispatchTable Pointer to the KD dispatch table
668 * \param BootPhase Phase of initialization
669 */
670 VOID
671 NTAPI
672 KdbInitialize(PKD_DISPATCH_TABLE DispatchTable,
673 ULONG BootPhase)
674 {
675 PCHAR p1, p2;
676 SHORT Found;
677 CHAR YesNo;
678 LIST_ENTRY *ModuleEntry;
679 PLDR_DATA_TABLE_ENTRY DataTableEntry;
680 KD_SYMBOLS_INFO SymbolsInfo;
681
682 DPRINT("KdbSymInit() BootPhase=%d\n", BootPhase);
683
684 if (BootPhase == 0)
685 {
686 /* Write out the functions that we support for now */
687 DispatchTable->KdpInitRoutine = KdpKdbgInit;
688 DispatchTable->KdpPrintRoutine = KdbDebugPrint;
689
690 /* Register as a Provider */
691 InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
692
693 /* Perform actual initialization of symbol module */
694 //NtoskrnlModuleObject->PatchInformation = NULL;
695 //LdrHalModuleObject->PatchInformation = NULL;
696
697 InitializeListHead(&SymbolFileListHead);
698 KeInitializeSpinLock(&SymbolFileListLock);
699
700 #ifdef DBG
701 LoadSymbols = TRUE;
702 #else
703 LoadSymbols = FALSE;
704 #endif
705
706 /* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS,
707 * /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */
708 ASSERT(KeLoaderBlock);
709 p1 = KeLoaderBlock->LoadOptions;
710 while('\0' != *p1 && NULL != (p2 = strchr(p1, '/')))
711 {
712 p2++;
713 Found = 0;
714 if (0 == _strnicmp(p2, "LOADSYMBOLS", 11))
715 {
716 Found = +1;
717 p2 += 11;
718 }
719 else if (0 == _strnicmp(p2, "NOLOADSYMBOLS", 13))
720 {
721 Found = -1;
722 p2 += 13;
723 }
724 if (0 != Found)
725 {
726 while (isspace(*p2))
727 {
728 p2++;
729 }
730 if ('=' == *p2)
731 {
732 p2++;
733 while (isspace(*p2))
734 {
735 p2++;
736 }
737 YesNo = toupper(*p2);
738 if ('N' == YesNo || 'F' == YesNo || '0' == YesNo)
739 {
740 Found = -1 * Found;
741 }
742 }
743 LoadSymbols = (0 < Found);
744 }
745 p1 = p2;
746 }
747
748 RosSymInitKernelMode();
749 }
750 else if (BootPhase == 1)
751 {
752 /* Load symbols for NTOSKRNL.EXE */
753 ModuleEntry = &KeLoaderBlock->LoadOrderListHead;
754 DataTableEntry = CONTAINING_RECORD(ModuleEntry,
755 LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
756
757 SymbolsInfo.BaseOfDll = DataTableEntry->DllBase;
758 SymbolsInfo.CheckSum = DataTableEntry->CheckSum;
759 SymbolsInfo.ProcessId = 0;
760 SymbolsInfo.SizeOfImage = DataTableEntry->SizeOfImage;
761
762 KdbSymProcessSymbols(NULL, &SymbolsInfo);
763
764 /* and HAL.DLL */
765 ModuleEntry = ModuleEntry->Flink;
766 DataTableEntry = CONTAINING_RECORD(ModuleEntry,
767 LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
768
769 SymbolsInfo.BaseOfDll = DataTableEntry->DllBase;
770 SymbolsInfo.CheckSum = DataTableEntry->CheckSum;
771 SymbolsInfo.ProcessId = 0;
772 SymbolsInfo.SizeOfImage = DataTableEntry->SizeOfImage;
773
774 KdbSymProcessSymbols(NULL, &SymbolsInfo);
775 }
776 }
777
778 /* EOF */