- Replace MODULE_OBJECT with LDR_DATA_TABLE_ENTRY.
[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 PLDR_DATA_TABLE_ENTRY current;
112 extern LIST_ENTRY ModuleListHead;
113 INT Count = 0;
114
115 current_entry = ModuleListHead.Flink;
116
117 while (current_entry != &ModuleListHead)
118 {
119 current = CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
120
121 if ((Address != NULL && (Address >= (PVOID)current->DllBase &&
122 Address < (PVOID)((ULONG_PTR)current->DllBase + current->SizeOfImage))) ||
123 (Name != NULL && _wcsnicmp(current->BaseDllName.Buffer, Name,
124 current->BaseDllName.Length / sizeof(WCHAR)) == 0) ||
125 (Index >= 0 && Count++ == Index))
126 {
127 wcsncpy(pInfo->Name, current->BaseDllName.Buffer,
128 min(255, current->BaseDllName.Length / sizeof(WCHAR)));
129 pInfo->Name[255] = L'\0';
130 pInfo->Base = (ULONG_PTR)current->DllBase;
131 pInfo->Size = current->SizeOfImage;
132 pInfo->RosSymInfo = current->RosSymInfo;
133 return TRUE;
134 }
135 current_entry = current_entry->Flink;
136 }
137
138 return KdbpSymFindUserModule(Address, Name, Index-Count, pInfo);
139 }
140
141 /*! \brief Find module by address...
142 *
143 * \param Address Any address inside the module to look for.
144 * \param pInfo Pointer to a KDB_MODULE_INFO struct which is filled on
145 * success.
146 *
147 * \retval TRUE Success - module found.
148 * \retval FALSE Failure - module not found.
149 *
150 * \sa KdbpSymFindModuleByName
151 * \sa KdbpSymFindModuleByIndex
152 */
153 BOOLEAN
154 KdbpSymFindModuleByAddress(IN PVOID Address,
155 OUT PKDB_MODULE_INFO pInfo)
156 {
157 return KdbpSymFindModule(Address, NULL, -1, pInfo);
158 }
159
160 /*! \brief Find module by name...
161 *
162 * \param Name Name of the module to look for.
163 * \param pInfo Pointer to a KDB_MODULE_INFO struct which is filled on
164 * success.
165 *
166 * \retval TRUE Success - module found.
167 * \retval FALSE Failure - module not found.
168 *
169 * \sa KdbpSymFindModuleByAddress
170 * \sa KdbpSymFindModuleByIndex
171 */
172 BOOLEAN
173 KdbpSymFindModuleByName(IN LPCWSTR Name,
174 OUT PKDB_MODULE_INFO pInfo)
175 {
176 return KdbpSymFindModule(NULL, Name, -1, pInfo);
177 }
178
179 /*! \brief Find module by index...
180 *
181 * \param Index Index of the module to return.
182 * \param pInfo Pointer to a KDB_MODULE_INFO struct which is filled on
183 * success.
184 *
185 * \retval TRUE Success - module found.
186 * \retval FALSE Failure - module not found.
187 *
188 * \sa KdbpSymFindModuleByName
189 * \sa KdbpSymFindModuleByAddress
190 */
191 BOOLEAN
192 KdbpSymFindModuleByIndex(IN INT Index,
193 OUT PKDB_MODULE_INFO pInfo)
194 {
195 return KdbpSymFindModule(NULL, NULL, Index, pInfo);
196 }
197
198 /*! \brief Print address...
199 *
200 * Tries to lookup line number, file name and function name for the given
201 * address and prints it.
202 * If no such information is found the address is printed in the format
203 * <module: offset>, otherwise the format will be
204 * <module: offset (filename:linenumber (functionname))>
205 *
206 * \retval TRUE Module containing \a Address was found, \a Address was printed.
207 * \retval FALSE No module containing \a Address was found, nothing was printed.
208 */
209 BOOLEAN
210 KdbSymPrintAddress(IN PVOID Address)
211 {
212 KDB_MODULE_INFO Info;
213 ULONG_PTR RelativeAddress;
214 NTSTATUS Status;
215 ULONG LineNumber;
216 CHAR FileName[256];
217 CHAR FunctionName[256];
218
219 if (!KdbpSymFindModuleByAddress(Address, &Info))
220 return FALSE;
221
222 RelativeAddress = (ULONG_PTR) Address - Info.Base;
223 Status = KdbSymGetAddressInformation(Info.RosSymInfo,
224 RelativeAddress,
225 &LineNumber,
226 FileName,
227 FunctionName);
228 if (NT_SUCCESS(Status))
229 {
230 DbgPrint("<%ws:%x (%s:%d (%s))>",
231 Info.Name, RelativeAddress, FileName, LineNumber, FunctionName);
232 }
233 else
234 {
235 DbgPrint("<%ws:%x>", Info.Name, RelativeAddress);
236 }
237
238 return TRUE;
239 }
240
241
242 /*! \brief Get information for an address (source file, line number,
243 * function name)
244 *
245 * \param SymbolInfo Pointer to ROSSYM_INFO.
246 * \param RelativeAddress Relative address to look up.
247 * \param LineNumber Pointer to an ULONG which is filled with the line
248 * number (can be NULL)
249 * \param FileName Pointer to an array of CHARs which gets filled with
250 * the filename (can be NULL)
251 * \param FunctionName Pointer to an array of CHARs which gets filled with
252 * the function name (can be NULL)
253 *
254 * \returns NTSTATUS error code.
255 * \retval STATUS_SUCCESS At least one of the requested informations was found.
256 * \retval STATUS_UNSUCCESSFUL None of the requested information was found.
257 */
258 NTSTATUS
259 KdbSymGetAddressInformation(IN PROSSYM_INFO RosSymInfo,
260 IN ULONG_PTR RelativeAddress,
261 OUT PULONG LineNumber OPTIONAL,
262 OUT PCH FileName OPTIONAL,
263 OUT PCH FunctionName OPTIONAL)
264 {
265 if (NULL == RosSymInfo)
266 {
267 return STATUS_UNSUCCESSFUL;
268 }
269
270 if (! RosSymGetAddressInformation(RosSymInfo, RelativeAddress, LineNumber,
271 FileName, FunctionName))
272 {
273 return STATUS_UNSUCCESSFUL;
274 }
275
276 return STATUS_SUCCESS;
277 }
278
279 /*! \brief Find cached symbol file.
280 *
281 * Looks through the list of cached symbol files and tries to find an already
282 * loaded one.
283 *
284 * \param FileName FileName of the symbol file to look for.
285 *
286 * \returns A pointer to the cached symbol info.
287 * \retval NULL No cached info found.
288 *
289 * \sa KdbpSymAddCachedFile
290 */
291 STATIC PROSSYM_INFO
292 KdbpSymFindCachedFile(IN PUNICODE_STRING FileName)
293 {
294 PIMAGE_SYMBOL_INFO_CACHE Current;
295 PLIST_ENTRY CurrentEntry;
296 KIRQL Irql;
297
298 DPRINT("Looking for cached symbol file %wZ\n", FileName);
299
300 KeAcquireSpinLock(&SymbolFileListLock, &Irql);
301
302 CurrentEntry = SymbolFileListHead.Flink;
303 while (CurrentEntry != (&SymbolFileListHead))
304 {
305 Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
306
307 DPRINT("Current->FileName %wZ FileName %wZ\n", &Current->FileName, FileName);
308 if (RtlEqualUnicodeString(&Current->FileName, FileName, TRUE))
309 {
310 Current->RefCount++;
311 KeReleaseSpinLock(&SymbolFileListLock, Irql);
312 DPRINT("Found cached file!\n");
313 return Current->RosSymInfo;
314 }
315
316 CurrentEntry = CurrentEntry->Flink;
317 }
318
319 KeReleaseSpinLock(&SymbolFileListLock, Irql);
320
321 DPRINT("Cached file not found!\n");
322 return NULL;
323 }
324
325 /*! \brief Add a symbol file to the cache.
326 *
327 * \param FileName Filename of the symbol file.
328 * \param RosSymInfo Pointer to the symbol info.
329 *
330 * \sa KdbpSymRemoveCachedFile
331 */
332 STATIC VOID
333 KdbpSymAddCachedFile(IN PUNICODE_STRING FileName,
334 IN PROSSYM_INFO RosSymInfo)
335 {
336 PIMAGE_SYMBOL_INFO_CACHE CacheEntry;
337
338 DPRINT("Adding symbol file: RosSymInfo = %p\n", RosSymInfo);
339
340 /* allocate entry */
341 CacheEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE), TAG_KDBS);
342 ASSERT(CacheEntry);
343 RtlZeroMemory(CacheEntry, sizeof (IMAGE_SYMBOL_INFO_CACHE));
344
345 /* fill entry */
346 RtlCreateUnicodeString(&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->RosSymInfo = 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->RosSymInfo);
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(EPROCESS_TO_KPROCESS(Process));
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, InLoadOrderModuleList);
543
544 KdbpSymUnloadModuleSymbols(Current->RosSymInfo);
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->Base);
565
566 Module->RosSymInfo = NULL;
567
568 KdbpSymLoadModuleSymbols(Filename, (PROSSYM_INFO*)&Module->RosSymInfo);
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->RosSymInfo);
580 ModuleObject->RosSymInfo = NULL;
581 }
582
583 /*! \brief Called when a symbol file is loaded by the loader?
584 *
585 * Tries to find a driver (.sys) or executable (.exe) with the same base name
586 * as the symbol file and sets the drivers/exes symbol info to the loaded
587 * module.
588 * Used to load ntoskrnl and hal symbols before the SystemRoot is available to us.
589 *
590 * \param FileName Filename for which the symbols are loaded.
591 */
592 VOID
593 KdbSymProcessBootSymbols(IN PCHAR FileName)
594 {
595 PLDR_DATA_TABLE_ENTRY ModuleObject;
596 UNICODE_STRING UnicodeString;
597 PLOADER_MODULE KeLoaderModules = (PLOADER_MODULE)KeLoaderBlock.ModsAddr;
598 ANSI_STRING AnsiString;
599 ULONG i;
600 BOOLEAN IsRaw;
601
602 DPRINT("KdbSymProcessBootSymbols(%s)\n", FileName);
603
604 if (0 == _stricmp(FileName, "ntoskrnl.sym"))
605 {
606 RtlInitAnsiString(&AnsiString, "ntoskrnl.exe");
607 IsRaw = TRUE;
608 }
609 else
610 {
611 RtlInitAnsiString(&AnsiString, FileName);
612 IsRaw = FALSE;
613 }
614 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
615 ModuleObject = LdrGetModuleObject(&UnicodeString);
616 RtlFreeUnicodeString(&UnicodeString);
617
618 if (ModuleObject != NULL)
619 {
620 if (! LoadSymbols)
621 {
622 ModuleObject->RosSymInfo = NULL;
623 return;
624 }
625
626 for (i = 0; i < KeLoaderBlock.ModsCount; i++)
627 {
628 if (0 == _stricmp(FileName, (PCHAR)KeLoaderModules[i].String))
629 {
630 break;
631 }
632 }
633 if (i < KeLoaderBlock.ModsCount)
634 {
635 KeLoaderModules[i].Reserved = 1;
636 if (ModuleObject->RosSymInfo != NULL)
637 {
638 KdbpSymRemoveCachedFile(ModuleObject->RosSymInfo);
639 }
640
641 if (IsRaw)
642 {
643 if (! RosSymCreateFromRaw((PVOID) KeLoaderModules[i].ModStart,
644 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart,
645 (PROSSYM_INFO*)&ModuleObject->RosSymInfo))
646 {
647 return;
648 }
649 }
650 else
651 {
652 if (! RosSymCreateFromMem((PVOID) KeLoaderModules[i].ModStart,
653 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart,
654 (PROSSYM_INFO*)&ModuleObject->RosSymInfo))
655 {
656 return;
657 }
658 }
659
660 /* add file to cache */
661 RtlInitAnsiString(&AnsiString, FileName);
662 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
663 KdbpSymAddCachedFile(&UnicodeString, ModuleObject->RosSymInfo);
664 RtlFreeUnicodeString(&UnicodeString);
665
666 DPRINT("Installed symbols: %s@%08x-%08x %p\n",
667 FileName,
668 ModuleObject->DllBase,
669 ModuleObject->SizeOfImage + ModuleObject->DllBase,
670 ModuleObject->RosSymInfo);
671 }
672 }
673 }
674
675 /*! \brief Initializes the KDB symbols implementation.
676 *
677 * \param NtoskrnlModuleObject LDR_DATA_TABLE_ENTRY of ntoskrnl.exe
678 * \param LdrHalModuleObject LDR_DATA_TABLE_ENTRY of hal.sys
679 */
680 VOID
681 KdbSymInit(IN PLDR_DATA_TABLE_ENTRY NtoskrnlModuleObject,
682 IN PLDR_DATA_TABLE_ENTRY LdrHalModuleObject)
683 {
684 PCHAR p1, p2;
685 int Found;
686 char YesNo;
687
688 NtoskrnlModuleObject->RosSymInfo = NULL;
689 LdrHalModuleObject->RosSymInfo = NULL;
690
691 InitializeListHead(&SymbolFileListHead);
692 KeInitializeSpinLock(&SymbolFileListLock);
693
694 #ifdef DBG
695 LoadSymbols = TRUE;
696 #else
697 LoadSymbols = FALSE;
698 #endif
699
700 /* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS,
701 * /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */
702 p1 = (PCHAR) KeLoaderBlock.CommandLine;
703 while('\0' != *p1 && NULL != (p2 = strchr(p1, '/')))
704 {
705 p2++;
706 Found = 0;
707 if (0 == _strnicmp(p2, "LOADSYMBOLS", 11))
708 {
709 Found = +1;
710 p2 += 11;
711 }
712 else if (0 == _strnicmp(p2, "NOLOADSYMBOLS", 13))
713 {
714 Found = -1;
715 p2 += 13;
716 }
717 if (0 != Found)
718 {
719 while (isspace(*p2))
720 {
721 p2++;
722 }
723 if ('=' == *p2)
724 {
725 p2++;
726 while (isspace(*p2))
727 {
728 p2++;
729 }
730 YesNo = toupper(*p2);
731 if ('N' == YesNo || 'F' == YesNo || '0' == YesNo)
732 {
733 Found = -1 * Found;
734 }
735 }
736 LoadSymbols = (0 < Found);
737 }
738 p1 = p2;
739 }
740
741 RosSymInitKernelMode();
742 }
743
744 /* EOF */