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...
7 * PROGRAMMERS: David Welch (welch@cwcom.net)
8 * Colin Finck (colin@reactos.org)
11 /* INCLUDES *****************************************************************/
16 #include "../cache/section/newmm.h"
19 /* GLOBALS ******************************************************************/
21 #define CURRENT_PROCESS ((HANDLE)~0)
23 typedef struct _IMAGE_SYMBOL_INFO_CACHE
27 UNICODE_STRING FileName
;
28 PROSSYM_INFO RosSymInfo
;
30 IMAGE_SYMBOL_INFO_CACHE
, *PIMAGE_SYMBOL_INFO_CACHE
;
32 typedef struct _ROSSYM_KM_OWN_CONTEXT
{
33 LARGE_INTEGER FileOffset
;
34 PFILE_OBJECT FileObject
;
35 } ROSSYM_KM_OWN_CONTEXT
, *PROSSYM_KM_OWN_CONTEXT
;
37 static BOOLEAN LoadSymbols
;
38 static LIST_ENTRY SymbolFileListHead
;
39 static KSPIN_LOCK SymbolFileListLock
;
40 static PROSSYM_INFO KdbpRosSymInfo
;
41 static ULONG_PTR KdbpImageBase
;
42 BOOLEAN KdbpSymbolsInitialized
= FALSE
;
44 /* FUNCTIONS ****************************************************************/
47 KdbpSeekSymFile(PVOID FileContext
, ULONG_PTR Target
)
49 PROSSYM_KM_OWN_CONTEXT Context
= (PROSSYM_KM_OWN_CONTEXT
)FileContext
;
50 Context
->FileOffset
.QuadPart
= Target
;
55 KdbpReadSymFile(PVOID FileContext
, PVOID Buffer
, ULONG Length
)
57 PROSSYM_KM_OWN_CONTEXT Context
= (PROSSYM_KM_OWN_CONTEXT
)FileContext
;
59 NTSTATUS Status
= MiSimpleRead
66 return NT_SUCCESS(Status
);
69 static PROSSYM_KM_OWN_CONTEXT
70 KdbpCaptureFileForSymbols(PFILE_OBJECT FileObject
)
72 PROSSYM_KM_OWN_CONTEXT Context
= ExAllocatePool(NonPagedPool
, sizeof(*Context
));
73 if (!Context
) return NULL
;
74 ObReferenceObject(FileObject
);
75 Context
->FileOffset
.QuadPart
= 0;
76 Context
->FileObject
= FileObject
;
81 KdbpReleaseFileForSymbols(PROSSYM_KM_OWN_CONTEXT Context
)
83 ObDereferenceObject(Context
->FileObject
);
88 KdbpSymSearchModuleList(
89 IN PLIST_ENTRY current_entry
,
90 IN PLIST_ENTRY end_entry
,
95 OUT PLDR_DATA_TABLE_ENTRY
* pLdrEntry
)
97 while (current_entry
&& current_entry
!= end_entry
)
99 *pLdrEntry
= CONTAINING_RECORD(current_entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
101 if ((Address
&& Address
>= (PVOID
)(*pLdrEntry
)->DllBase
&& Address
< (PVOID
)((ULONG_PTR
)(*pLdrEntry
)->DllBase
+ (*pLdrEntry
)->SizeOfImage
)) ||
102 (Name
&& !_wcsnicmp((*pLdrEntry
)->BaseDllName
.Buffer
, Name
, (*pLdrEntry
)->BaseDllName
.Length
/ sizeof(WCHAR
))) ||
103 (Index
>= 0 && (*Count
)++ == Index
))
108 current_entry
= current_entry
->Flink
;
114 /*! \brief Find a module...
116 * \param Address If \a Address is not NULL the module containing \a Address
118 * \param Name If \a Name is not NULL the module named \a Name will be
120 * \param Index If \a Index is >= 0 the Index'th module will be returned.
121 * \param pLdrEntry Pointer to a PLDR_DATA_TABLE_ENTRY which is filled.
123 * \retval TRUE Module was found, \a pLdrEntry was filled.
124 * \retval FALSE No module was found.
128 IN PVOID Address OPTIONAL
,
129 IN LPCWSTR Name OPTIONAL
,
130 IN INT Index OPTIONAL
,
131 OUT PLDR_DATA_TABLE_ENTRY
* pLdrEntry
)
134 PEPROCESS CurrentProcess
;
136 /* First try to look up the module in the kernel module list. */
137 if(KdbpSymSearchModuleList(PsLoadedModuleList
.Flink
,
148 /* That didn't succeed. Try the module list of the current process now. */
149 CurrentProcess
= PsGetCurrentProcess();
151 if(!CurrentProcess
|| !CurrentProcess
->Peb
|| !CurrentProcess
->Peb
->Ldr
)
154 return KdbpSymSearchModuleList(CurrentProcess
->Peb
->Ldr
->InLoadOrderModuleList
.Flink
,
155 &CurrentProcess
->Peb
->Ldr
->InLoadOrderModuleList
,
163 /*! \brief Print address...
165 * Tries to lookup line number, file name and function name for the given
166 * address and prints it.
167 * If no such information is found the address is printed in the format
168 * <module: offset>, otherwise the format will be
169 * <module: offset (filename:linenumber (functionname))>
171 * \retval TRUE Module containing \a Address was found, \a Address was printed.
172 * \retval FALSE No module containing \a Address was found, nothing was printed.
177 IN PKTRAP_FRAME Context
)
180 PMEMORY_AREA MemoryArea
= NULL
;
181 PROS_SECTION_OBJECT SectionObject
;
182 PLDR_DATA_TABLE_ENTRY LdrEntry
;
183 PROSSYM_KM_OWN_CONTEXT FileContext
;
184 ULONG_PTR RelativeAddress
;
186 ROSSYM_LINEINFO LineInfo
= {0};
189 enum _ROSSYM_REGNAME regname
;
192 { ROSSYM_X86_EDX
, FIELD_OFFSET(KTRAP_FRAME
, Edx
) },
193 { ROSSYM_X86_EAX
, FIELD_OFFSET(KTRAP_FRAME
, Eax
) },
194 { ROSSYM_X86_ECX
, FIELD_OFFSET(KTRAP_FRAME
, Ecx
) },
195 { ROSSYM_X86_EBX
, FIELD_OFFSET(KTRAP_FRAME
, Ebx
) },
196 { ROSSYM_X86_ESI
, FIELD_OFFSET(KTRAP_FRAME
, Esi
) },
197 { ROSSYM_X86_EDI
, FIELD_OFFSET(KTRAP_FRAME
, Edi
) },
198 { ROSSYM_X86_EBP
, FIELD_OFFSET(KTRAP_FRAME
, Ebp
) },
199 { ROSSYM_X86_ESP
, FIELD_OFFSET(KTRAP_FRAME
, HardwareEsp
) }
204 DPRINT("Has Context %x (EBP %x)\n", Context
, Context
->Ebp
);
205 LineInfo
.Flags
= ROSSYM_LINEINFO_HAS_REGISTERS
;
207 for (i
= 0; i
< sizeof(regmap
) / sizeof(regmap
[0]); i
++) {
209 (&LineInfo
.Registers
.Registers
[regmap
[i
].regname
],
210 ((PCHAR
)Context
)+regmap
[i
].ctx_offset
,
212 DPRINT("DWARF REG[%d] -> %x\n", regmap
[i
].regname
, LineInfo
.Registers
.Registers
[regmap
[i
].regname
]);
216 if (!KdbpSymbolsInitialized
|| !KdbpSymFindModule(Address
, NULL
, -1, &LdrEntry
))
219 RelativeAddress
= (ULONG_PTR
)Address
- (ULONG_PTR
)LdrEntry
->DllBase
;
220 Status
= KdbSymGetAddressInformation
221 (LdrEntry
->PatchInformation
,
225 if (NT_SUCCESS(Status
))
227 DbgPrint("<%wZ:%x (%s:%d (%s))>",
228 &LdrEntry
->BaseDllName
, RelativeAddress
, LineInfo
.FileName
, LineInfo
.LineNumber
, LineInfo
.FunctionName
);
234 for (i
= 0; i
< LineInfo
.NumParams
; i
++) {
238 LineInfo
.Parameters
[i
].ValueName
,
239 LineInfo
.Parameters
[i
].Value
);
247 else if (Address
< MmSystemRangeStart
)
249 MemoryArea
= MmLocateMemoryAreaByAddress(&PsGetCurrentProcess()->Vm
, Address
);
250 if (!MemoryArea
|| MemoryArea
->Type
!= MEMORY_AREA_SECTION_VIEW
)
254 SectionObject
= MemoryArea
->Data
.SectionData
.Section
;
255 if (!(SectionObject
->AllocationAttributes
& SEC_IMAGE
)) goto end
;
256 if (MemoryArea
->StartingAddress
!= (PVOID
)KdbpImageBase
)
260 RosSymDelete(KdbpRosSymInfo
);
261 KdbpRosSymInfo
= NULL
;
265 if ((FileContext
= KdbpCaptureFileForSymbols(SectionObject
->FileObject
)))
267 if (RosSymCreateFromFile(FileContext
, &KdbpRosSymInfo
))
268 KdbpImageBase
= (ULONG_PTR
)MemoryArea
->StartingAddress
;
270 KdbpReleaseFileForSymbols(FileContext
);
276 RelativeAddress
= (ULONG_PTR
)Address
- KdbpImageBase
;
277 RosSymFreeInfo(&LineInfo
);
278 Status
= KdbSymGetAddressInformation
282 if (NT_SUCCESS(Status
))
285 ("<%wZ:%x (%s:%d (%s))>",
286 &SectionObject
->FileObject
->FileName
,
290 LineInfo
.FunctionName
);
297 for (i
= 0; i
< LineInfo
.NumParams
; i
++) {
301 LineInfo
.Parameters
[i
].ValueName
,
302 LineInfo
.Parameters
[i
].Value
);
314 DbgPrint("<%wZ:%x>", &LdrEntry
->BaseDllName
, RelativeAddress
);
320 /*! \brief Get information for an address (source file, line number,
323 * \param SymbolInfo Pointer to ROSSYM_INFO.
324 * \param RelativeAddress Relative address to look up.
325 * \param LineNumber Pointer to an ULONG which is filled with the line
326 * number (can be NULL)
327 * \param FileName Pointer to an array of CHARs which gets filled with
328 * the filename (can be NULL)
329 * \param FunctionName Pointer to an array of CHARs which gets filled with
330 * the function name (can be NULL)
332 * \returns NTSTATUS error code.
333 * \retval STATUS_SUCCESS At least one of the requested informations was found.
334 * \retval STATUS_UNSUCCESSFUL None of the requested information was found.
337 KdbSymGetAddressInformation(
338 IN PROSSYM_INFO RosSymInfo
,
339 IN ULONG_PTR RelativeAddress
,
340 IN PROSSYM_LINEINFO LineInfo
)
342 if (!KdbpSymbolsInitialized
||
344 !RosSymGetAddressInformation(RosSymInfo
, RelativeAddress
, LineInfo
))
346 return STATUS_UNSUCCESSFUL
;
349 return STATUS_SUCCESS
;
352 /*! \brief Find cached symbol file.
354 * Looks through the list of cached symbol files and tries to find an already
357 * \param FileName FileName of the symbol file to look for.
359 * \returns A pointer to the cached symbol info.
360 * \retval NULL No cached info found.
362 * \sa KdbpSymAddCachedFile
365 KdbpSymFindCachedFile(
366 IN PUNICODE_STRING FileName
)
368 PIMAGE_SYMBOL_INFO_CACHE Current
;
369 PLIST_ENTRY CurrentEntry
;
372 KeAcquireSpinLock(&SymbolFileListLock
, &Irql
);
374 CurrentEntry
= SymbolFileListHead
.Flink
;
375 while (CurrentEntry
!= (&SymbolFileListHead
))
377 Current
= CONTAINING_RECORD(CurrentEntry
, IMAGE_SYMBOL_INFO_CACHE
, ListEntry
);
379 if (RtlEqualUnicodeString(&Current
->FileName
, FileName
, TRUE
))
382 KeReleaseSpinLock(&SymbolFileListLock
, Irql
);
383 DPRINT("Found cached file!\n");
384 return Current
->RosSymInfo
;
387 CurrentEntry
= CurrentEntry
->Flink
;
390 KeReleaseSpinLock(&SymbolFileListLock
, Irql
);
392 DPRINT("Cached file not found!\n");
396 /*! \brief Add a symbol file to the cache.
398 * \param FileName Filename of the symbol file.
399 * \param RosSymInfo Pointer to the symbol info.
401 * \sa KdbpSymRemoveCachedFile
404 KdbpSymAddCachedFile(
405 IN PUNICODE_STRING FileName
,
406 IN PROSSYM_INFO RosSymInfo
)
408 PIMAGE_SYMBOL_INFO_CACHE CacheEntry
;
410 DPRINT("Adding symbol file: %wZ RosSymInfo = %p\n", FileName
, RosSymInfo
);
413 CacheEntry
= ExAllocatePoolWithTag(NonPagedPool
, sizeof (IMAGE_SYMBOL_INFO_CACHE
), TAG_KDBS
);
415 RtlZeroMemory(CacheEntry
, sizeof (IMAGE_SYMBOL_INFO_CACHE
));
418 CacheEntry
->FileName
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
421 CacheEntry
->FileName
.MaximumLength
= FileName
->Length
;
422 RtlCopyUnicodeString(&CacheEntry
->FileName
, FileName
);
423 ASSERT(CacheEntry
->FileName
.Buffer
);
424 CacheEntry
->RefCount
= 1;
425 CacheEntry
->RosSymInfo
= RosSymInfo
;
426 InsertTailList(&SymbolFileListHead
, &CacheEntry
->ListEntry
); /* FIXME: Lock list? */
429 /*! \brief Remove a symbol file (reference) from the cache.
431 * Tries to find a cache entry matching the given symbol info and decreases
432 * it's reference count. If the refcount is 0 after decreasing it the cache
433 * entry will be removed from the list and freed.
435 * \param RosSymInfo Pointer to the symbol info.
437 * \sa KdbpSymAddCachedFile
440 KdbpSymRemoveCachedFile(
441 IN PROSSYM_INFO RosSymInfo
)
443 PIMAGE_SYMBOL_INFO_CACHE Current
;
444 PLIST_ENTRY CurrentEntry
;
447 KeAcquireSpinLock(&SymbolFileListLock
, &Irql
);
449 CurrentEntry
= SymbolFileListHead
.Flink
;
450 while (CurrentEntry
!= (&SymbolFileListHead
))
452 Current
= CONTAINING_RECORD(CurrentEntry
, IMAGE_SYMBOL_INFO_CACHE
, ListEntry
);
454 if (Current
->RosSymInfo
== RosSymInfo
) /* found */
456 ASSERT(Current
->RefCount
> 0);
458 if (Current
->RefCount
< 1)
460 RemoveEntryList(&Current
->ListEntry
);
461 RosSymDelete(Current
->RosSymInfo
);
465 KeReleaseSpinLock(&SymbolFileListLock
, Irql
);
469 CurrentEntry
= CurrentEntry
->Flink
;
472 KeReleaseSpinLock(&SymbolFileListLock
, Irql
);
475 /*! \brief Loads a symbol file.
477 * \param FileName Filename of the symbol file to load.
478 * \param RosSymInfo Pointer to a ROSSYM_INFO which gets filled.
480 * \sa KdbpSymUnloadModuleSymbols
483 KdbpSymLoadModuleSymbols(
484 IN PUNICODE_STRING FileName
,
485 OUT PROSSYM_INFO
*RosSymInfo
)
487 OBJECT_ATTRIBUTES ObjectAttributes
;
490 IO_STATUS_BLOCK IoStatusBlock
;
491 PFILE_OBJECT FileObject
;
492 PROSSYM_KM_OWN_CONTEXT FileContext
;
494 /* Allow KDB to break on module load */
495 KdbModuleLoaded(FileName
);
503 /* Try to find cached (already loaded) symbol file */
504 *RosSymInfo
= KdbpSymFindCachedFile(FileName
);
507 DPRINT("Found cached symbol file %wZ\n", FileName
);
512 InitializeObjectAttributes(&ObjectAttributes
,
514 OBJ_CASE_INSENSITIVE
|OBJ_KERNEL_HANDLE
,
518 DPRINT("Attempting to open image: %wZ\n", FileName
);
520 Status
= ZwOpenFile(&FileHandle
,
524 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
525 FILE_NON_DIRECTORY_FILE
|FILE_SYNCHRONOUS_IO_NONALERT
);
526 if (!NT_SUCCESS(Status
))
528 DPRINT("Could not open image file(%x): %wZ\n", Status
, FileName
);
532 DPRINT("Loading symbols from %wZ...\n", FileName
);
534 Status
= ObReferenceObjectByHandle
536 FILE_READ_DATA
|SYNCHRONIZE
,
542 if (!NT_SUCCESS(Status
))
544 DPRINT("Could not get the file object\n");
549 if ((FileContext
= KdbpCaptureFileForSymbols(FileObject
)))
551 if (RosSymCreateFromFile(FileContext
, RosSymInfo
))
553 /* add file to cache */
555 UNICODE_STRING TruncatedName
= *FileName
;
556 for (i
= (TruncatedName
.Length
/ sizeof(WCHAR
)) - 1; i
>= 0; i
--)
557 if (TruncatedName
.Buffer
[i
] == '\\') {
558 TruncatedName
.Buffer
+= i
+1;
559 TruncatedName
.Length
-= (i
+1)*sizeof(WCHAR
);
560 TruncatedName
.MaximumLength
-= (i
+1)*sizeof(WCHAR
);
563 KdbpSymAddCachedFile(&TruncatedName
, *RosSymInfo
);
564 DPRINT("Installed symbols: %wZ %p\n", &TruncatedName
, *RosSymInfo
);
566 KdbpReleaseFileForSymbols(FileContext
);
569 ObDereferenceObject(FileObject
);
574 KdbSymProcessSymbols(
575 IN PLDR_DATA_TABLE_ENTRY LdrEntry
)
579 LdrEntry
->PatchInformation
= NULL
;
583 /* Remove symbol info if it already exists */
584 if (LdrEntry
->PatchInformation
) {
585 KdbpSymRemoveCachedFile(LdrEntry
->PatchInformation
);
588 /* Error loading symbol info, try to load it from file */
589 KdbpSymLoadModuleSymbols(&LdrEntry
->FullDllName
,
590 (PROSSYM_INFO
*)&LdrEntry
->PatchInformation
);
592 if (!LdrEntry
->PatchInformation
) {
593 // HACK: module dll names don't identify the real files
594 UNICODE_STRING SystemRoot
;
595 UNICODE_STRING ModuleNameCopy
;
596 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot\\system32\\Drivers\\");
597 ModuleNameCopy
.Length
= 0;
598 ModuleNameCopy
.MaximumLength
=
599 LdrEntry
->BaseDllName
.MaximumLength
+ SystemRoot
.MaximumLength
;
600 ModuleNameCopy
.Buffer
= ExAllocatePool(NonPagedPool
, SystemRoot
.MaximumLength
+ LdrEntry
->BaseDllName
.MaximumLength
);
601 RtlCopyUnicodeString(&ModuleNameCopy
, &SystemRoot
);
603 (ModuleNameCopy
.Buffer
+ ModuleNameCopy
.Length
/ sizeof(WCHAR
),
604 LdrEntry
->BaseDllName
.Buffer
,
605 LdrEntry
->BaseDllName
.Length
);
606 ModuleNameCopy
.Length
+= LdrEntry
->BaseDllName
.Length
;
607 KdbpSymLoadModuleSymbols(&ModuleNameCopy
,
608 (PROSSYM_INFO
*)&LdrEntry
->PatchInformation
);
609 if (!LdrEntry
->PatchInformation
) {
610 SystemRoot
.Length
-= strlen("Drivers\\") * sizeof(WCHAR
);
611 RtlCopyUnicodeString(&ModuleNameCopy
, &SystemRoot
);
613 (ModuleNameCopy
.Buffer
+ ModuleNameCopy
.Length
/ sizeof(WCHAR
),
614 LdrEntry
->BaseDllName
.Buffer
,
615 LdrEntry
->BaseDllName
.Length
);
616 ModuleNameCopy
.Length
+= LdrEntry
->BaseDllName
.Length
;
617 KdbpSymLoadModuleSymbols(&ModuleNameCopy
,
618 (PROSSYM_INFO
*)&LdrEntry
->PatchInformation
);
620 RtlFreeUnicodeString(&ModuleNameCopy
);
623 /* It already added symbols to cache */
624 DPRINT("Installed symbols: %wZ@%p-%p %p\n",
625 &LdrEntry
->BaseDllName
,
627 (PVOID
)(LdrEntry
->SizeOfImage
+ (ULONG_PTR
)LdrEntry
->DllBase
),
628 LdrEntry
->PatchInformation
);
643 PVOID OriginalMapping
;
646 static PVOID
KdbpSymAllocMem(ULONG_PTR Size
)
648 KdbpMallocHeader
*Hdr
;
649 if (Size
< PAGE_SIZE
)
651 PVOID Result
= ExAllocatePoolWithTag(NonPagedPool
, Size
+ sizeof(KdbpMallocHeader
), 'RSYM');
652 if (!Result
) return NULL
;
653 Hdr
= (KdbpMallocHeader
*)Result
;
661 SIZE_T RegionSize
= Size
+ sizeof(KdbpMallocHeader
);
662 NTSTATUS Status
= NtAllocateVirtualMemory
663 (CURRENT_PROCESS
, &Base
, 0, &RegionSize
, MEM_COMMIT
, PAGE_READWRITE
);
664 if (!NT_SUCCESS(Status
)) return NULL
;
665 Hdr
= (KdbpMallocHeader
*)Base
;
666 Hdr
->Mdl
= IoAllocateMdl(Base
, RegionSize
, FALSE
, FALSE
, NULL
);
668 NtFreeVirtualMemory(CURRENT_PROCESS
, &Base
, &RegionSize
, MEM_RELEASE
);
671 Hdr
->Size
= RegionSize
;
672 Hdr
->OriginalMapping
= Base
;
673 MmProbeAndLockPages(Hdr
->Mdl
, KernelMode
, IoModifyAccess
);
674 KdbpMallocHeader
*MappedHdr
= (KdbpMallocHeader
*)MmMapLockedPages(Hdr
->Mdl
, KernelMode
);
676 MmUnlockPages(Hdr
->Mdl
);
678 NtFreeVirtualMemory(CURRENT_PROCESS
, &Base
, &RegionSize
, MEM_RELEASE
);
681 return &MappedHdr
[1];
685 static VOID
KdbpSymFreeMem(PVOID Area
)
687 PCHAR HdrPtr
= ((PCHAR
)Area
) - sizeof(KdbpMallocHeader
);
688 KdbpMallocHeader
*Hdr
= (KdbpMallocHeader
*)HdrPtr
;
689 if (Hdr
->Size
< PAGE_SIZE
)
696 PVOID BaseAddress
= Hdr
->OriginalMapping
;
697 SIZE_T RegionSize
= Hdr
->Size
;
698 MmUnmapLockedPages(Hdr
, Mdl
);
700 NtFreeVirtualMemory(CURRENT_PROCESS
, &BaseAddress
, &RegionSize
, MEM_RELEASE
);
705 static BOOLEAN
KdbpSymReadMem(PVOID FileContext
, PVOID TargetDebug
, PVOID SourceMem
, ULONG Size
)
707 return NT_SUCCESS(KdbpSafeReadMemory(TargetDebug
, SourceMem
, Size
));
710 static ROSSYM_CALLBACKS KdbpRosSymCallbacks
= {
711 KdbpSymAllocMem
, KdbpSymFreeMem
,
712 KdbpReadSymFile
, KdbpSeekSymFile
,
716 /*! \brief Initializes the KDB symbols implementation.
718 * \param DispatchTable Pointer to the KD dispatch table
719 * \param BootPhase Phase of initialization
724 PKD_DISPATCH_TABLE DispatchTable
,
730 PLDR_DATA_TABLE_ENTRY LdrEntry
;
732 DPRINT("KdbSymInit() BootPhase=%d\n", BootPhase
);
737 /* Load symbols only if we have 96Mb of RAM or more */
738 if (MmNumberOfPhysicalPages
>= 0x6000)
744 /* Write out the functions that we support for now */
745 DispatchTable
->KdpInitRoutine
= KdpKdbgInit
;
746 DispatchTable
->KdpPrintRoutine
= KdbDebugPrint
;
748 /* Register as a Provider */
749 InsertTailList(&KdProviders
, &DispatchTable
->KdProvidersList
);
751 /* Perform actual initialization of symbol module */
752 //NtoskrnlModuleObject->PatchInformation = NULL;
753 //LdrHalModuleObject->PatchInformation = NULL;
755 InitializeListHead(&SymbolFileListHead
);
756 KeInitializeSpinLock(&SymbolFileListLock
);
758 /* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS,
759 * /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */
760 ASSERT(KeLoaderBlock
);
761 p1
= KeLoaderBlock
->LoadOptions
;
762 while('\0' != *p1
&& NULL
!= (p2
= strchr(p1
, '/')))
766 if (0 == _strnicmp(p2
, "LOADSYMBOLS", 11))
771 else if (0 == _strnicmp(p2
, "NOLOADSYMBOLS", 13))
789 YesNo
= toupper(*p2
);
790 if ('N' == YesNo
|| 'F' == YesNo
|| '0' == YesNo
)
795 LoadSymbols
= (0 < Found
);
800 RosSymInit(&KdbpRosSymCallbacks
);
802 else if (BootPhase
== 3)
804 /* Load symbols for NTOSKRNL.EXE.
805 It is always the first module in PsLoadedModuleList. KeLoaderBlock can't be used here as its content is just temporary. */
806 LdrEntry
= CONTAINING_RECORD(PsLoadedModuleList
.Flink
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
807 KdbSymProcessSymbols(LdrEntry
);
809 /* Also load them for HAL.DLL. */
810 LdrEntry
= CONTAINING_RECORD(PsLoadedModuleList
.Flink
->Flink
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
811 KdbSymProcessSymbols(LdrEntry
);
813 KdbpSymbolsInitialized
= TRUE
;