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)
10 /* INCLUDES *****************************************************************/
17 /* GLOBALS ******************************************************************/
19 typedef struct _IMAGE_SYMBOL_INFO_CACHE
{
22 UNICODE_STRING FileName
;
23 PROSSYM_INFO RosSymInfo
;
24 } IMAGE_SYMBOL_INFO_CACHE
, *PIMAGE_SYMBOL_INFO_CACHE
;
26 static BOOLEAN LoadSymbols
;
27 static LIST_ENTRY SymbolFileListHead
;
28 static KSPIN_LOCK SymbolFileListLock
;
29 BOOLEAN KdbpSymbolsInitialized
= FALSE
;
31 /* FUNCTIONS ****************************************************************/
33 /*! \brief Find a user-mode module...
35 * \param Address If \a Address is not NULL the module containing \a Address
37 * \param Name If \a Name is not NULL the module named \a Name will be
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.
42 * \retval TRUE Module was found, \a pInfo was filled.
43 * \retval FALSE No module was found.
45 * \sa KdbpSymFindModule
48 KdbpSymFindUserModule(IN PVOID Address OPTIONAL
,
49 IN LPCWSTR Name OPTIONAL
,
50 IN INT Index OPTIONAL
,
51 OUT PKDB_MODULE_INFO pInfo
)
53 PLIST_ENTRY current_entry
;
54 PLDR_DATA_TABLE_ENTRY current
;
55 PEPROCESS CurrentProcess
;
60 if (!KdbpSymbolsInitialized
)
63 CurrentProcess
= PsGetCurrentProcess();
64 if (CurrentProcess
!= NULL
)
66 Peb
= CurrentProcess
->Peb
;
69 if (Peb
== NULL
|| Peb
->Ldr
== NULL
)
74 current_entry
= Peb
->Ldr
->InLoadOrderModuleList
.Flink
;
76 while (current_entry
!= &Peb
->Ldr
->InLoadOrderModuleList
&&
77 current_entry
!= NULL
)
79 current
= CONTAINING_RECORD(current_entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
80 Length
= min(current
->BaseDllName
.Length
/ sizeof(WCHAR
), 255);
81 if ((Address
!= NULL
&& (Address
>= (PVOID
)current
->DllBase
&&
82 Address
< (PVOID
)((char *)current
->DllBase
+ current
->SizeOfImage
))) ||
83 (Name
!= NULL
&& _wcsnicmp(current
->BaseDllName
.Buffer
, Name
, Length
) == 0) ||
84 (Index
>= 0 && Count
++ == Index
))
86 wcsncpy(pInfo
->Name
, current
->BaseDllName
.Buffer
, Length
);
87 pInfo
->Name
[Length
] = L
'\0';
88 pInfo
->Base
= (ULONG_PTR
)current
->DllBase
;
89 pInfo
->Size
= current
->SizeOfImage
;
90 pInfo
->RosSymInfo
= current
->PatchInformation
;
93 current_entry
= current_entry
->Flink
;
99 /*! \brief Find a kernel-mode module...
101 * Works like \a KdbpSymFindUserModule.
103 * \sa KdbpSymFindUserModule
106 KdbpSymFindModule(IN PVOID Address OPTIONAL
,
107 IN LPCWSTR Name OPTIONAL
,
108 IN INT Index OPTIONAL
,
109 OUT PKDB_MODULE_INFO pInfo
)
111 PLIST_ENTRY current_entry
;
112 PLDR_DATA_TABLE_ENTRY current
;
116 if (!KdbpSymbolsInitialized
)
119 current_entry
= PsLoadedModuleList
.Flink
;
121 while (current_entry
!= &PsLoadedModuleList
)
123 current
= CONTAINING_RECORD(current_entry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
125 Length
= min(current
->BaseDllName
.Length
/ sizeof(WCHAR
), 255);
126 if ((Address
!= NULL
&& (Address
>= (PVOID
)current
->DllBase
&&
127 Address
< (PVOID
)((ULONG_PTR
)current
->DllBase
+ current
->SizeOfImage
))) ||
128 (Name
!= NULL
&& _wcsnicmp(current
->BaseDllName
.Buffer
, Name
, Length
) == 0) ||
129 (Index
>= 0 && Count
++ == Index
))
131 wcsncpy(pInfo
->Name
, current
->BaseDllName
.Buffer
, Length
);
132 pInfo
->Name
[Length
] = L
'\0';
133 pInfo
->Base
= (ULONG_PTR
)current
->DllBase
;
134 pInfo
->Size
= current
->SizeOfImage
;
135 pInfo
->RosSymInfo
= current
->PatchInformation
;
138 current_entry
= current_entry
->Flink
;
141 return KdbpSymFindUserModule(Address
, Name
, Index
-Count
, pInfo
);
144 /*! \brief Find module by address...
146 * \param Address Any address inside the module to look for.
147 * \param pInfo Pointer to a KDB_MODULE_INFO struct which is filled on
150 * \retval TRUE Success - module found.
151 * \retval FALSE Failure - module not found.
153 * \sa KdbpSymFindModuleByName
154 * \sa KdbpSymFindModuleByIndex
157 KdbpSymFindModuleByAddress(IN PVOID Address
,
158 OUT PKDB_MODULE_INFO pInfo
)
160 return KdbpSymFindModule(Address
, NULL
, -1, pInfo
);
163 /*! \brief Find module by name...
165 * \param Name Name of the module to look for.
166 * \param pInfo Pointer to a KDB_MODULE_INFO struct which is filled on
169 * \retval TRUE Success - module found.
170 * \retval FALSE Failure - module not found.
172 * \sa KdbpSymFindModuleByAddress
173 * \sa KdbpSymFindModuleByIndex
176 KdbpSymFindModuleByName(IN LPCWSTR Name
,
177 OUT PKDB_MODULE_INFO pInfo
)
179 return KdbpSymFindModule(NULL
, Name
, -1, pInfo
);
182 /*! \brief Find module by index...
184 * \param Index Index of the module to return.
185 * \param pInfo Pointer to a KDB_MODULE_INFO struct which is filled on
188 * \retval TRUE Success - module found.
189 * \retval FALSE Failure - module not found.
191 * \sa KdbpSymFindModuleByName
192 * \sa KdbpSymFindModuleByAddress
195 KdbpSymFindModuleByIndex(IN INT Index
,
196 OUT PKDB_MODULE_INFO pInfo
)
198 return KdbpSymFindModule(NULL
, NULL
, Index
, pInfo
);
201 /*! \brief Print address...
203 * Tries to lookup line number, file name and function name for the given
204 * address and prints it.
205 * If no such information is found the address is printed in the format
206 * <module: offset>, otherwise the format will be
207 * <module: offset (filename:linenumber (functionname))>
209 * \retval TRUE Module containing \a Address was found, \a Address was printed.
210 * \retval FALSE No module containing \a Address was found, nothing was printed.
213 KdbSymPrintAddress(IN PVOID Address
)
215 KDB_MODULE_INFO Info
;
216 ULONG_PTR RelativeAddress
;
220 CHAR FunctionName
[256];
222 if (!KdbpSymbolsInitialized
|| !KdbpSymFindModuleByAddress(Address
, &Info
))
225 RelativeAddress
= (ULONG_PTR
) Address
- Info
.Base
;
226 Status
= KdbSymGetAddressInformation(Info
.RosSymInfo
,
231 if (NT_SUCCESS(Status
))
233 DbgPrint("<%ws:%x (%s:%d (%s))>",
234 Info
.Name
, RelativeAddress
, FileName
, LineNumber
, FunctionName
);
238 DbgPrint("<%ws:%x>", Info
.Name
, RelativeAddress
);
245 /*! \brief Get information for an address (source file, line number,
248 * \param SymbolInfo Pointer to ROSSYM_INFO.
249 * \param RelativeAddress Relative address to look up.
250 * \param LineNumber Pointer to an ULONG which is filled with the line
251 * number (can be NULL)
252 * \param FileName Pointer to an array of CHARs which gets filled with
253 * the filename (can be NULL)
254 * \param FunctionName Pointer to an array of CHARs which gets filled with
255 * the function name (can be NULL)
257 * \returns NTSTATUS error code.
258 * \retval STATUS_SUCCESS At least one of the requested informations was found.
259 * \retval STATUS_UNSUCCESSFUL None of the requested information was found.
262 KdbSymGetAddressInformation(IN PROSSYM_INFO RosSymInfo
,
263 IN ULONG_PTR RelativeAddress
,
264 OUT PULONG LineNumber OPTIONAL
,
265 OUT PCH FileName OPTIONAL
,
266 OUT PCH FunctionName OPTIONAL
)
268 if (!KdbpSymbolsInitialized
)
270 return STATUS_UNSUCCESSFUL
;
273 if (NULL
== RosSymInfo
)
275 return STATUS_UNSUCCESSFUL
;
278 if (! RosSymGetAddressInformation(RosSymInfo
, RelativeAddress
, LineNumber
,
279 FileName
, FunctionName
))
281 return STATUS_UNSUCCESSFUL
;
284 return STATUS_SUCCESS
;
287 /*! \brief Find cached symbol file.
289 * Looks through the list of cached symbol files and tries to find an already
292 * \param FileName FileName of the symbol file to look for.
294 * \returns A pointer to the cached symbol info.
295 * \retval NULL No cached info found.
297 * \sa KdbpSymAddCachedFile
300 KdbpSymFindCachedFile(IN PUNICODE_STRING FileName
)
302 PIMAGE_SYMBOL_INFO_CACHE Current
;
303 PLIST_ENTRY CurrentEntry
;
306 DPRINT("Looking for cached symbol file %wZ\n", FileName
);
308 KeAcquireSpinLock(&SymbolFileListLock
, &Irql
);
310 CurrentEntry
= SymbolFileListHead
.Flink
;
311 while (CurrentEntry
!= (&SymbolFileListHead
))
313 Current
= CONTAINING_RECORD(CurrentEntry
, IMAGE_SYMBOL_INFO_CACHE
, ListEntry
);
315 DPRINT("Current->FileName %wZ FileName %wZ\n", &Current
->FileName
, FileName
);
316 if (RtlEqualUnicodeString(&Current
->FileName
, FileName
, TRUE
))
319 KeReleaseSpinLock(&SymbolFileListLock
, Irql
);
320 DPRINT("Found cached file!\n");
321 return Current
->RosSymInfo
;
324 CurrentEntry
= CurrentEntry
->Flink
;
327 KeReleaseSpinLock(&SymbolFileListLock
, Irql
);
329 DPRINT("Cached file not found!\n");
333 /*! \brief Add a symbol file to the cache.
335 * \param FileName Filename of the symbol file.
336 * \param RosSymInfo Pointer to the symbol info.
338 * \sa KdbpSymRemoveCachedFile
341 KdbpSymAddCachedFile(IN PUNICODE_STRING FileName
,
342 IN PROSSYM_INFO RosSymInfo
)
344 PIMAGE_SYMBOL_INFO_CACHE CacheEntry
;
346 DPRINT("Adding symbol file: RosSymInfo = %p\n", RosSymInfo
);
349 CacheEntry
= ExAllocatePoolWithTag(NonPagedPool
, sizeof (IMAGE_SYMBOL_INFO_CACHE
), TAG_KDBS
);
351 RtlZeroMemory(CacheEntry
, sizeof (IMAGE_SYMBOL_INFO_CACHE
));
354 CacheEntry
->FileName
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
357 RtlCopyUnicodeString(&CacheEntry
->FileName
, FileName
);
358 ASSERT(CacheEntry
->FileName
.Buffer
);
359 CacheEntry
->RefCount
= 1;
360 CacheEntry
->RosSymInfo
= RosSymInfo
;
361 InsertTailList(&SymbolFileListHead
, &CacheEntry
->ListEntry
); /* FIXME: Lock list? */
364 /*! \brief Remove a symbol file (reference) from the cache.
366 * Tries to find a cache entry matching the given symbol info and decreases
367 * it's reference count. If the refcount is 0 after decreasing it the cache
368 * entry will be removed from the list and freed.
370 * \param RosSymInfo Pointer to the symbol info.
372 * \sa KdbpSymAddCachedFile
375 KdbpSymRemoveCachedFile(IN PROSSYM_INFO RosSymInfo
)
377 PIMAGE_SYMBOL_INFO_CACHE Current
;
378 PLIST_ENTRY CurrentEntry
;
381 KeAcquireSpinLock(&SymbolFileListLock
, &Irql
);
383 CurrentEntry
= SymbolFileListHead
.Flink
;
384 while (CurrentEntry
!= (&SymbolFileListHead
))
386 Current
= CONTAINING_RECORD(CurrentEntry
, IMAGE_SYMBOL_INFO_CACHE
, ListEntry
);
388 if (Current
->RosSymInfo
== RosSymInfo
) /* found */
390 ASSERT(Current
->RefCount
> 0);
392 if (Current
->RefCount
< 1)
394 RemoveEntryList(&Current
->ListEntry
);
395 RosSymDelete(Current
->RosSymInfo
);
398 KeReleaseSpinLock(&SymbolFileListLock
, Irql
);
402 CurrentEntry
= CurrentEntry
->Flink
;
405 KeReleaseSpinLock(&SymbolFileListLock
, Irql
);
406 DPRINT1("Warning: Removing unknown symbol file: RosSymInfo = %p\n", RosSymInfo
);
409 /*! \brief Loads a symbol file.
411 * \param FileName Filename of the symbol file to load.
412 * \param RosSymInfo Pointer to a ROSSYM_INFO which gets filled.
414 * \sa KdbpSymUnloadModuleSymbols
417 KdbpSymLoadModuleSymbols(IN PUNICODE_STRING FileName
,
418 OUT PROSSYM_INFO
*RosSymInfo
)
420 OBJECT_ATTRIBUTES ObjectAttributes
;
423 IO_STATUS_BLOCK IoStatusBlock
;
425 /* Allow KDB to break on module load */
426 KdbModuleLoaded(FileName
);
434 /* Try to find cached (already loaded) symbol file */
435 *RosSymInfo
= KdbpSymFindCachedFile(FileName
);
436 if (*RosSymInfo
!= NULL
)
438 DPRINT("Found cached symbol file %wZ\n", FileName
);
443 InitializeObjectAttributes(&ObjectAttributes
,
449 DPRINT("Attempting to open image: %wZ\n", FileName
);
451 Status
= ZwOpenFile(&FileHandle
,
455 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
456 FILE_SYNCHRONOUS_IO_NONALERT
);
457 if (!NT_SUCCESS(Status
))
459 DPRINT("Could not open image file: %wZ\n", FileName
);
463 DPRINT("Loading symbols from %wZ...\n", FileName
);
465 if (! RosSymCreateFromFile(&FileHandle
, RosSymInfo
))
467 DPRINT("Failed to load symbols from %wZ\n", FileName
);
473 DPRINT("Symbols loaded.\n");
475 /* add file to cache */
476 KdbpSymAddCachedFile(FileName
, *RosSymInfo
);
478 DPRINT("Installed symbols: %wZ %p\n", FileName
, *RosSymInfo
);
481 /*! \brief Unloads symbol info.
483 * \param RosSymInfo Pointer to the symbol info to unload.
485 * \sa KdbpSymLoadModuleSymbols
488 KdbpSymUnloadModuleSymbols(IN PROSSYM_INFO RosSymInfo
)
490 DPRINT("Unloading symbols\n");
492 if (RosSymInfo
!= NULL
)
494 KdbpSymRemoveCachedFile(RosSymInfo
);
498 /*! \brief Load symbol info for a user module.
500 * \param LdrModule Pointer to the module to load symbols for.
503 KdbSymLoadUserModuleSymbols(IN PLDR_DATA_TABLE_ENTRY LdrModule
)
505 static WCHAR Prefix
[] = L
"\\??\\";
506 UNICODE_STRING KernelName
;
507 DPRINT("LdrModule %p\n", LdrModule
);
509 LdrModule
->PatchInformation
= NULL
;
511 KernelName
.MaximumLength
= sizeof(Prefix
) + LdrModule
->FullDllName
.Length
;
512 KernelName
.Length
= KernelName
.MaximumLength
- sizeof(WCHAR
);
513 KernelName
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
, KernelName
.MaximumLength
, TAG_KDBS
);
514 if (NULL
== KernelName
.Buffer
)
518 memcpy(KernelName
.Buffer
, Prefix
, sizeof(Prefix
) - sizeof(WCHAR
));
519 memcpy(KernelName
.Buffer
+ sizeof(Prefix
) / sizeof(WCHAR
) - 1, LdrModule
->FullDllName
.Buffer
,
520 LdrModule
->FullDllName
.Length
);
521 KernelName
.Buffer
[KernelName
.Length
/ sizeof(WCHAR
)] = L
'\0';
523 KdbpSymLoadModuleSymbols(&KernelName
, (PROSSYM_INFO
*)&LdrModule
->PatchInformation
);
525 ExFreePool(KernelName
.Buffer
);
528 /*! \brief Frees all symbols loaded for a process.
530 * \param Process Pointer to a process.
533 KdbSymFreeProcessSymbols(IN PEPROCESS Process
)
535 PLIST_ENTRY CurrentEntry
;
536 PLDR_DATA_TABLE_ENTRY Current
;
537 PEPROCESS CurrentProcess
;
540 CurrentProcess
= PsGetCurrentProcess();
541 if (CurrentProcess
!= Process
)
543 KeAttachProcess(&Process
->Pcb
);
549 CurrentEntry
= Peb
->Ldr
->InLoadOrderModuleList
.Flink
;
550 while (CurrentEntry
!= &Peb
->Ldr
->InLoadOrderModuleList
&&
551 CurrentEntry
!= NULL
)
553 Current
= CONTAINING_RECORD(CurrentEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
555 KdbpSymUnloadModuleSymbols(Current
->PatchInformation
);
557 CurrentEntry
= CurrentEntry
->Flink
;
559 if (CurrentProcess
!= Process
)
565 /*! \brief Load symbol info for a driver.
567 * \param Filename Filename of the driver.
568 * \param Module Pointer to the driver LDR_DATA_TABLE_ENTRY.
571 KdbSymLoadDriverSymbols(IN PUNICODE_STRING Filename
,
572 IN PLDR_DATA_TABLE_ENTRY Module
)
574 /* Load symbols for the image if available */
575 DPRINT("Loading driver %wZ symbols (driver @ %08x)\n", Filename
, Module
->DllBase
);
577 Module
->PatchInformation
= NULL
;
579 KdbpSymLoadModuleSymbols(Filename
, (PROSSYM_INFO
*)&Module
->PatchInformation
);
582 /*! \brief Unloads symbol info for a driver.
584 * \param ModuleObject Pointer to the driver LDR_DATA_TABLE_ENTRY.
587 KdbSymUnloadDriverSymbols(IN PLDR_DATA_TABLE_ENTRY ModuleObject
)
589 /* Unload symbols for module if available */
590 KdbpSymUnloadModuleSymbols(ModuleObject
->PatchInformation
);
591 ModuleObject
->PatchInformation
= NULL
;
595 KdbSymProcessSymbols(IN PANSI_STRING AnsiFileName
, IN PKD_SYMBOLS_INFO SymbolInfo
)
597 BOOLEAN Found
= FALSE
;
598 PLIST_ENTRY ListHead
, NextEntry
;
599 PLDR_DATA_TABLE_ENTRY LdrEntry
= NULL
;
601 //DPRINT("KdbSymProcessSymbols(%Z)\n", AnsiFileName);
603 /* We use PsLoadedModuleList here, otherwise (in case of
604 using KeLoaderBlock) all our data will be just lost */
605 ListHead
= &PsLoadedModuleList
;
607 /* Found module we are interested in */
608 NextEntry
= ListHead
->Flink
;
609 while (ListHead
!= NextEntry
)
612 LdrEntry
= CONTAINING_RECORD(NextEntry
,
613 LDR_DATA_TABLE_ENTRY
,
616 if (SymbolInfo
->BaseOfDll
== LdrEntry
->DllBase
)
622 /* Go to the next one */
623 NextEntry
= NextEntry
->Flink
;
626 /* Exit if we didn't find the module requested */
630 DPRINT("Found LdrEntry=%p\n", LdrEntry
);
633 LdrEntry
->PatchInformation
= NULL
;
637 /* Remove symbol info if it already exists */
638 if (LdrEntry
->PatchInformation
!= NULL
)
640 KdbpSymRemoveCachedFile(LdrEntry
->PatchInformation
);
643 /* Load new symbol information */
644 if (! RosSymCreateFromMem(LdrEntry
->DllBase
,
645 LdrEntry
->SizeOfImage
,
646 (PROSSYM_INFO
*)&LdrEntry
->PatchInformation
))
648 /* Error loading symbol info, try to load it from file */
649 KdbpSymLoadModuleSymbols(&LdrEntry
->FullDllName
,
650 (PROSSYM_INFO
*)&LdrEntry
->PatchInformation
);
652 /* It already added symbols to cache */
656 /* Add file to cache */
657 KdbpSymAddCachedFile(&LdrEntry
->FullDllName
, LdrEntry
->PatchInformation
);
660 DPRINT("Installed symbols: %wZ@%p-%p %p\n",
661 &LdrEntry
->BaseDllName
,
663 (PVOID
)(LdrEntry
->SizeOfImage
+ (ULONG_PTR
)LdrEntry
->DllBase
),
664 LdrEntry
->PatchInformation
);
670 KdbDebugPrint(PCH Message
, ULONG Length
)
676 /*! \brief Initializes the KDB symbols implementation.
678 * \param DispatchTable Pointer to the KD dispatch table
679 * \param BootPhase Phase of initialization
683 KdbInitialize(PKD_DISPATCH_TABLE DispatchTable
,
689 LIST_ENTRY
*ModuleEntry
;
690 PLDR_DATA_TABLE_ENTRY DataTableEntry
;
691 KD_SYMBOLS_INFO SymbolsInfo
;
693 DPRINT("KdbSymInit() BootPhase=%d\n", BootPhase
);
697 /* Write out the functions that we support for now */
698 DispatchTable
->KdpInitRoutine
= KdpKdbgInit
;
699 DispatchTable
->KdpPrintRoutine
= KdbDebugPrint
;
701 /* Register as a Provider */
702 InsertTailList(&KdProviders
, &DispatchTable
->KdProvidersList
);
704 /* Perform actual initialization of symbol module */
705 //NtoskrnlModuleObject->PatchInformation = NULL;
706 //LdrHalModuleObject->PatchInformation = NULL;
708 InitializeListHead(&SymbolFileListHead
);
709 KeInitializeSpinLock(&SymbolFileListLock
);
717 /* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS,
718 * /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */
719 ASSERT(KeLoaderBlock
);
720 p1
= KeLoaderBlock
->LoadOptions
;
721 while('\0' != *p1
&& NULL
!= (p2
= strchr(p1
, '/')))
725 if (0 == _strnicmp(p2
, "LOADSYMBOLS", 11))
730 else if (0 == _strnicmp(p2
, "NOLOADSYMBOLS", 13))
748 YesNo
= toupper(*p2
);
749 if ('N' == YesNo
|| 'F' == YesNo
|| '0' == YesNo
)
754 LoadSymbols
= (0 < Found
);
759 RosSymInitKernelMode();
761 else if (BootPhase
== 1)
763 /* Load symbols for NTOSKRNL.EXE */
764 ModuleEntry
= &KeLoaderBlock
->LoadOrderListHead
;
765 DataTableEntry
= CONTAINING_RECORD(ModuleEntry
,
766 LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
768 SymbolsInfo
.BaseOfDll
= DataTableEntry
->DllBase
;
769 SymbolsInfo
.CheckSum
= DataTableEntry
->CheckSum
;
770 SymbolsInfo
.ProcessId
= 0;
771 SymbolsInfo
.SizeOfImage
= DataTableEntry
->SizeOfImage
;
773 KdbSymProcessSymbols(NULL
, &SymbolsInfo
);
776 ModuleEntry
= ModuleEntry
->Flink
;
777 DataTableEntry
= CONTAINING_RECORD(ModuleEntry
,
778 LDR_DATA_TABLE_ENTRY
, InLoadOrderLinks
);
780 SymbolsInfo
.BaseOfDll
= DataTableEntry
->DllBase
;
781 SymbolsInfo
.CheckSum
= DataTableEntry
->CheckSum
;
782 SymbolsInfo
.ProcessId
= 0;
783 SymbolsInfo
.SizeOfImage
= DataTableEntry
->SizeOfImage
;
785 KdbSymProcessSymbols(NULL
, &SymbolsInfo
);
786 KdbpSymbolsInitialized
= TRUE
;