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