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