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