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