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