98890094139df2d8d2ca1f1a16834e15ec85c468
[reactos.git] / reactos / ntoskrnl / kdbg / kdb_symbols.cmake.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 * Colin Finck (colin@reactos.org)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14
15 #define NDEBUG
16 #include "../cache/section/newmm.h"
17 #include <debug.h>
18
19 /* GLOBALS ******************************************************************/
20
21 typedef struct _IMAGE_SYMBOL_INFO_CACHE
22 {
23 LIST_ENTRY ListEntry;
24 ULONG RefCount;
25 UNICODE_STRING FileName;
26 PROSSYM_INFO RosSymInfo;
27 }
28 IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE;
29
30 typedef struct _ROSSYM_KM_OWN_CONTEXT {
31 LARGE_INTEGER FileOffset;
32 PFILE_OBJECT FileObject;
33 } ROSSYM_KM_OWN_CONTEXT, *PROSSYM_KM_OWN_CONTEXT;
34
35 static BOOLEAN LoadSymbols;
36 static LIST_ENTRY SymbolFileListHead;
37 static KSPIN_LOCK SymbolFileListLock;
38 static PROSSYM_INFO KdbpRosSymInfo;
39 static ULONG_PTR KdbpImageBase;
40 BOOLEAN KdbpSymbolsInitialized = FALSE;
41
42 /* FUNCTIONS ****************************************************************/
43
44 static BOOLEAN
45 KdbpSeekSymFile(PVOID FileContext, ULONG_PTR Target)
46 {
47 PROSSYM_KM_OWN_CONTEXT Context = (PROSSYM_KM_OWN_CONTEXT)FileContext;
48 Context->FileOffset.QuadPart = Target;
49 return TRUE;
50 }
51
52 static BOOLEAN
53 KdbpReadSymFile(PVOID FileContext, PVOID Buffer, ULONG Length)
54 {
55 PROSSYM_KM_OWN_CONTEXT Context = (PROSSYM_KM_OWN_CONTEXT)FileContext;
56 IO_STATUS_BLOCK Iosb;
57 NTSTATUS Status = MiSimpleRead
58 (Context->FileObject,
59 &Context->FileOffset,
60 Buffer,
61 Length,
62 FALSE,
63 &Iosb);
64 return NT_SUCCESS(Status);
65 }
66
67 static PROSSYM_KM_OWN_CONTEXT
68 KdbpCaptureFileForSymbols(PFILE_OBJECT FileObject)
69 {
70 PROSSYM_KM_OWN_CONTEXT Context = ExAllocatePool(NonPagedPool, sizeof(*Context));
71 if (!Context) return NULL;
72 ObReferenceObject(FileObject);
73 Context->FileOffset.QuadPart = 0;
74 Context->FileObject = FileObject;
75 return Context;
76 }
77
78 static VOID
79 KdbpReleaseFileForSymbols(PROSSYM_KM_OWN_CONTEXT Context)
80 {
81 ObDereferenceObject(Context->FileObject);
82 ExFreePool(Context);
83 }
84
85 static BOOLEAN
86 KdbpSymSearchModuleList(
87 IN PLIST_ENTRY current_entry,
88 IN PLIST_ENTRY end_entry,
89 IN PLONG Count,
90 IN PVOID Address,
91 IN LPCWSTR Name,
92 IN INT Index,
93 OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry)
94 {
95 while (current_entry && current_entry != end_entry)
96 {
97 *pLdrEntry = CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
98
99 if ((Address && Address >= (PVOID)(*pLdrEntry)->DllBase && Address < (PVOID)((ULONG_PTR)(*pLdrEntry)->DllBase + (*pLdrEntry)->SizeOfImage)) ||
100 (Name && !_wcsnicmp((*pLdrEntry)->BaseDllName.Buffer, Name, (*pLdrEntry)->BaseDllName.Length / sizeof(WCHAR))) ||
101 (Index >= 0 && (*Count)++ == Index))
102 {
103 return TRUE;
104 }
105
106 current_entry = current_entry->Flink;
107 }
108
109 return FALSE;
110 }
111
112 /*! \brief Find a module...
113 *
114 * \param Address If \a Address is not NULL the module containing \a Address
115 * is searched.
116 * \param Name If \a Name is not NULL the module named \a Name will be
117 * searched.
118 * \param Index If \a Index is >= 0 the Index'th module will be returned.
119 * \param pLdrEntry Pointer to a PLDR_DATA_TABLE_ENTRY which is filled.
120 *
121 * \retval TRUE Module was found, \a pLdrEntry was filled.
122 * \retval FALSE No module was found.
123 */
124 BOOLEAN
125 KdbpSymFindModule(
126 IN PVOID Address OPTIONAL,
127 IN LPCWSTR Name OPTIONAL,
128 IN INT Index OPTIONAL,
129 OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry)
130 {
131 LONG Count = 0;
132 PEPROCESS CurrentProcess;
133
134 /* First try to look up the module in the kernel module list. */
135 if(KdbpSymSearchModuleList(PsLoadedModuleList.Flink,
136 &PsLoadedModuleList,
137 &Count,
138 Address,
139 Name,
140 Index,
141 pLdrEntry))
142 {
143 return TRUE;
144 }
145
146 /* That didn't succeed. Try the module list of the current process now. */
147 CurrentProcess = PsGetCurrentProcess();
148
149 if(!CurrentProcess || !CurrentProcess->Peb || !CurrentProcess->Peb->Ldr)
150 return FALSE;
151
152 return KdbpSymSearchModuleList(CurrentProcess->Peb->Ldr->InLoadOrderModuleList.Flink,
153 &CurrentProcess->Peb->Ldr->InLoadOrderModuleList,
154 &Count,
155 Address,
156 Name,
157 Index,
158 pLdrEntry);
159 }
160
161 /*! \brief Print address...
162 *
163 * Tries to lookup line number, file name and function name for the given
164 * address and prints it.
165 * If no such information is found the address is printed in the format
166 * <module: offset>, otherwise the format will be
167 * <module: offset (filename:linenumber (functionname))>
168 *
169 * \retval TRUE Module containing \a Address was found, \a Address was printed.
170 * \retval FALSE No module containing \a Address was found, nothing was printed.
171 */
172 BOOLEAN
173 KdbSymPrintAddress(
174 IN PVOID Address,
175 IN PKTRAP_FRAME Context)
176 {
177 int i;
178 PMEMORY_AREA MemoryArea = NULL;
179 PROS_SECTION_OBJECT SectionObject;
180 PLDR_DATA_TABLE_ENTRY LdrEntry;
181 PROSSYM_KM_OWN_CONTEXT FileContext;
182 ULONG_PTR RelativeAddress;
183 NTSTATUS Status;
184 ROSSYM_LINEINFO LineInfo = {0};
185
186 struct {
187 enum _ROSSYM_REGNAME regname;
188 size_t ctx_offset;
189 } regmap[] = {
190 { ROSSYM_X86_EDX, FIELD_OFFSET(KTRAP_FRAME, Edx) },
191 { ROSSYM_X86_EAX, FIELD_OFFSET(KTRAP_FRAME, Eax) },
192 { ROSSYM_X86_ECX, FIELD_OFFSET(KTRAP_FRAME, Ecx) },
193 { ROSSYM_X86_EBX, FIELD_OFFSET(KTRAP_FRAME, Ebx) },
194 { ROSSYM_X86_ESI, FIELD_OFFSET(KTRAP_FRAME, Esi) },
195 { ROSSYM_X86_EDI, FIELD_OFFSET(KTRAP_FRAME, Edi) },
196 { ROSSYM_X86_EBP, FIELD_OFFSET(KTRAP_FRAME, Ebp) },
197 { ROSSYM_X86_ESP, FIELD_OFFSET(KTRAP_FRAME, HardwareEsp) }
198 };
199
200 if (Context)
201 {
202 DPRINT("Has Context %x (EBP %x)\n", Context, Context->Ebp);
203 LineInfo.Flags = ROSSYM_LINEINFO_HAS_REGISTERS;
204
205 for (i = 0; i < sizeof(regmap) / sizeof(regmap[0]); i++) {
206 memcpy
207 (&LineInfo.Registers.Registers[regmap[i].regname],
208 ((PCHAR)Context)+regmap[i].ctx_offset,
209 sizeof(ULONG_PTR));
210 DPRINT("DWARF REG[%d] -> %x\n", regmap[i].regname, LineInfo.Registers.Registers[regmap[i].regname]);
211 }
212 }
213
214 if (!KdbpSymbolsInitialized || !KdbpSymFindModule(Address, NULL, -1, &LdrEntry))
215 return FALSE;
216
217 RelativeAddress = (ULONG_PTR)Address - (ULONG_PTR)LdrEntry->DllBase;
218 Status = KdbSymGetAddressInformation
219 (LdrEntry->PatchInformation,
220 RelativeAddress,
221 &LineInfo);
222
223 if (NT_SUCCESS(Status))
224 {
225 DbgPrint("<%wZ:%x (%s:%d (%s))>",
226 &LdrEntry->BaseDllName, RelativeAddress, LineInfo.FileName, LineInfo.LineNumber, LineInfo.FunctionName);
227 if (Context)
228 {
229 int i;
230 char *comma = "";
231 DbgPrint("(");
232 for (i = 0; i < LineInfo.NumParams; i++) {
233 DbgPrint
234 ("%s%s=%llx",
235 comma,
236 LineInfo.Parameters[i].ValueName,
237 LineInfo.Parameters[i].Value);
238 comma = ",";
239 }
240 DbgPrint(")");
241 }
242
243 return TRUE;
244 }
245 else if (Address < MmSystemRangeStart)
246 {
247 MemoryArea = MmLocateMemoryAreaByAddress(&PsGetCurrentProcess()->Vm, Address);
248 if (!MemoryArea || MemoryArea->Type != MEMORY_AREA_SECTION_VIEW)
249 {
250 goto end;
251 }
252 SectionObject = MemoryArea->Data.SectionData.Section;
253 if (!(SectionObject->AllocationAttributes & SEC_IMAGE)) goto end;
254 if (MemoryArea->StartingAddress != (PVOID)KdbpImageBase)
255 {
256 if (KdbpRosSymInfo)
257 {
258 RosSymDelete(KdbpRosSymInfo);
259 KdbpRosSymInfo = NULL;
260 KdbpImageBase = 0;
261 }
262
263 if ((FileContext = KdbpCaptureFileForSymbols(SectionObject->FileObject)))
264 {
265 if (RosSymCreateFromFile(FileContext, &KdbpRosSymInfo))
266 KdbpImageBase = (ULONG_PTR)MemoryArea->StartingAddress;
267
268 KdbpReleaseFileForSymbols(FileContext);
269 }
270 }
271
272 if (KdbpRosSymInfo)
273 {
274 RelativeAddress = (ULONG_PTR)Address - KdbpImageBase;
275 RosSymFreeInfo(&LineInfo);
276 Status = KdbSymGetAddressInformation
277 (KdbpRosSymInfo,
278 RelativeAddress,
279 &LineInfo);
280 if (NT_SUCCESS(Status))
281 {
282 DbgPrint
283 ("<%wZ:%x (%s:%d (%s))>",
284 &SectionObject->FileObject->FileName,
285 RelativeAddress,
286 LineInfo.FileName,
287 LineInfo.LineNumber,
288 LineInfo.FunctionName);
289
290 if (Context)
291 {
292 int i;
293 char *comma = "";
294 DbgPrint("(");
295 for (i = 0; i < LineInfo.NumParams; i++) {
296 DbgPrint
297 ("%s%s=%llx",
298 comma,
299 LineInfo.Parameters[i].ValueName,
300 LineInfo.Parameters[i].Value);
301 comma = ",";
302 }
303 DbgPrint(")");
304 }
305
306 return TRUE;
307 }
308 }
309 }
310
311 end:
312 DbgPrint("<%wZ:%x>", &LdrEntry->BaseDllName, RelativeAddress);
313
314 return TRUE;
315 }
316
317
318 /*! \brief Get information for an address (source file, line number,
319 * function name)
320 *
321 * \param SymbolInfo Pointer to ROSSYM_INFO.
322 * \param RelativeAddress Relative address to look up.
323 * \param LineNumber Pointer to an ULONG which is filled with the line
324 * number (can be NULL)
325 * \param FileName Pointer to an array of CHARs which gets filled with
326 * the filename (can be NULL)
327 * \param FunctionName Pointer to an array of CHARs which gets filled with
328 * the function name (can be NULL)
329 *
330 * \returns NTSTATUS error code.
331 * \retval STATUS_SUCCESS At least one of the requested informations was found.
332 * \retval STATUS_UNSUCCESSFUL None of the requested information was found.
333 */
334 NTSTATUS
335 KdbSymGetAddressInformation(
336 IN PROSSYM_INFO RosSymInfo,
337 IN ULONG_PTR RelativeAddress,
338 IN PROSSYM_LINEINFO LineInfo)
339 {
340 if (!KdbpSymbolsInitialized ||
341 !RosSymInfo ||
342 !RosSymGetAddressInformation(RosSymInfo, RelativeAddress, LineInfo))
343 {
344 return STATUS_UNSUCCESSFUL;
345 }
346
347 return STATUS_SUCCESS;
348 }
349
350 /*! \brief Find cached symbol file.
351 *
352 * Looks through the list of cached symbol files and tries to find an already
353 * loaded one.
354 *
355 * \param FileName FileName of the symbol file to look for.
356 *
357 * \returns A pointer to the cached symbol info.
358 * \retval NULL No cached info found.
359 *
360 * \sa KdbpSymAddCachedFile
361 */
362 PROSSYM_INFO
363 KdbpSymFindCachedFile(
364 IN PUNICODE_STRING FileName)
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 (RtlEqualUnicodeString(&Current->FileName, FileName, TRUE))
378 {
379 Current->RefCount++;
380 KeReleaseSpinLock(&SymbolFileListLock, Irql);
381 DPRINT("Found cached file!\n");
382 return Current->RosSymInfo;
383 }
384
385 CurrentEntry = CurrentEntry->Flink;
386 }
387
388 KeReleaseSpinLock(&SymbolFileListLock, Irql);
389
390 DPRINT("Cached file not found!\n");
391 return NULL;
392 }
393
394 /*! \brief Add a symbol file to the cache.
395 *
396 * \param FileName Filename of the symbol file.
397 * \param RosSymInfo Pointer to the symbol info.
398 *
399 * \sa KdbpSymRemoveCachedFile
400 */
401 static VOID
402 KdbpSymAddCachedFile(
403 IN PUNICODE_STRING FileName,
404 IN PROSSYM_INFO RosSymInfo)
405 {
406 PIMAGE_SYMBOL_INFO_CACHE CacheEntry;
407
408 DPRINT("Adding symbol file: %wZ RosSymInfo = %p\n", FileName, RosSymInfo);
409
410 /* allocate entry */
411 CacheEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE), TAG_KDBS);
412 ASSERT(CacheEntry);
413 RtlZeroMemory(CacheEntry, sizeof (IMAGE_SYMBOL_INFO_CACHE));
414
415 /* fill entry */
416 CacheEntry->FileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
417 FileName->Length,
418 TAG_KDBS);
419 CacheEntry->FileName.MaximumLength = FileName->Length;
420 RtlCopyUnicodeString(&CacheEntry->FileName, FileName);
421 ASSERT(CacheEntry->FileName.Buffer);
422 CacheEntry->RefCount = 1;
423 CacheEntry->RosSymInfo = RosSymInfo;
424 InsertTailList(&SymbolFileListHead, &CacheEntry->ListEntry); /* FIXME: Lock list? */
425 }
426
427 /*! \brief Remove a symbol file (reference) from the cache.
428 *
429 * Tries to find a cache entry matching the given symbol info and decreases
430 * it's reference count. If the refcount is 0 after decreasing it the cache
431 * entry will be removed from the list and freed.
432 *
433 * \param RosSymInfo Pointer to the symbol info.
434 *
435 * \sa KdbpSymAddCachedFile
436 */
437 static VOID
438 KdbpSymRemoveCachedFile(
439 IN PROSSYM_INFO RosSymInfo)
440 {
441 PIMAGE_SYMBOL_INFO_CACHE Current;
442 PLIST_ENTRY CurrentEntry;
443 KIRQL Irql;
444
445 KeAcquireSpinLock(&SymbolFileListLock, &Irql);
446
447 CurrentEntry = SymbolFileListHead.Flink;
448 while (CurrentEntry != (&SymbolFileListHead))
449 {
450 Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
451
452 if (Current->RosSymInfo == RosSymInfo) /* found */
453 {
454 ASSERT(Current->RefCount > 0);
455 Current->RefCount--;
456 if (Current->RefCount < 1)
457 {
458 RemoveEntryList(&Current->ListEntry);
459 RosSymDelete(Current->RosSymInfo);
460 ExFreePool(Current);
461 }
462
463 KeReleaseSpinLock(&SymbolFileListLock, Irql);
464 return;
465 }
466
467 CurrentEntry = CurrentEntry->Flink;
468 }
469
470 KeReleaseSpinLock(&SymbolFileListLock, Irql);
471 }
472
473 /*! \brief Loads a symbol file.
474 *
475 * \param FileName Filename of the symbol file to load.
476 * \param RosSymInfo Pointer to a ROSSYM_INFO which gets filled.
477 *
478 * \sa KdbpSymUnloadModuleSymbols
479 */
480 VOID
481 KdbpSymLoadModuleSymbols(
482 IN PUNICODE_STRING FileName,
483 OUT PROSSYM_INFO *RosSymInfo)
484 {
485 OBJECT_ATTRIBUTES ObjectAttributes;
486 HANDLE FileHandle;
487 NTSTATUS Status;
488 IO_STATUS_BLOCK IoStatusBlock;
489 PFILE_OBJECT FileObject;
490 PROSSYM_KM_OWN_CONTEXT FileContext;
491
492 /* Allow KDB to break on module load */
493 KdbModuleLoaded(FileName);
494
495 if (!LoadSymbols)
496 {
497 *RosSymInfo = NULL;
498 return;
499 }
500
501 /* Try to find cached (already loaded) symbol file */
502 *RosSymInfo = KdbpSymFindCachedFile(FileName);
503 if (*RosSymInfo)
504 {
505 DPRINT("Found cached symbol file %wZ\n", FileName);
506 return;
507 }
508
509 /* Open the file */
510 InitializeObjectAttributes(&ObjectAttributes,
511 FileName,
512 OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
513 NULL,
514 NULL);
515
516 DPRINT("Attempting to open image: %wZ\n", FileName);
517
518 Status = ZwOpenFile(&FileHandle,
519 FILE_READ_ACCESS,
520 &ObjectAttributes,
521 &IoStatusBlock,
522 FILE_SHARE_READ|FILE_SHARE_WRITE,
523 FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT);
524 if (!NT_SUCCESS(Status))
525 {
526 DPRINT("Could not open image file(%x): %wZ\n", Status, FileName);
527 return;
528 }
529
530 DPRINT("Loading symbols from %wZ...\n", FileName);
531
532 Status = ObReferenceObjectByHandle
533 (FileHandle,
534 FILE_READ_DATA|SYNCHRONIZE,
535 NULL,
536 KernelMode,
537 (PVOID*)&FileObject,
538 NULL);
539
540 if (!NT_SUCCESS(Status))
541 {
542 DPRINT("Could not get the file object\n");
543 ZwClose(FileHandle);
544 return;
545 }
546
547 if ((FileContext = KdbpCaptureFileForSymbols(FileObject)))
548 {
549 if (RosSymCreateFromFile(FileContext, RosSymInfo))
550 {
551 /* add file to cache */
552 int i;
553 UNICODE_STRING TruncatedName = *FileName;
554 for (i = (TruncatedName.Length / sizeof(WCHAR)) - 1; i >= 0; i--)
555 if (TruncatedName.Buffer[i] == '\\') {
556 TruncatedName.Buffer += i+1;
557 TruncatedName.Length -= (i+1)*sizeof(WCHAR);
558 TruncatedName.MaximumLength -= (i+1)*sizeof(WCHAR);
559 break;
560 }
561 KdbpSymAddCachedFile(&TruncatedName, *RosSymInfo);
562 DPRINT("Installed symbols: %wZ %p\n", &TruncatedName, *RosSymInfo);
563 }
564 KdbpReleaseFileForSymbols(FileContext);
565 }
566
567 ObDereferenceObject(FileObject);
568 ZwClose(FileHandle);
569 }
570
571 VOID
572 KdbSymProcessSymbols(
573 IN PLDR_DATA_TABLE_ENTRY LdrEntry)
574 {
575 if (!LoadSymbols)
576 {
577 LdrEntry->PatchInformation = NULL;
578 return;
579 }
580
581 /* Remove symbol info if it already exists */
582 if (LdrEntry->PatchInformation) {
583 KdbpSymRemoveCachedFile(LdrEntry->PatchInformation);
584 }
585
586 /* Error loading symbol info, try to load it from file */
587 KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName,
588 (PROSSYM_INFO*)&LdrEntry->PatchInformation);
589
590 if (!LdrEntry->PatchInformation) {
591 // HACK: module dll names don't identify the real files
592 UNICODE_STRING SystemRoot;
593 UNICODE_STRING ModuleNameCopy;
594 RtlInitUnicodeString(&SystemRoot, L"\\SystemRoot\\system32\\Drivers\\");
595 ModuleNameCopy.Length = 0;
596 ModuleNameCopy.MaximumLength =
597 LdrEntry->BaseDllName.MaximumLength + SystemRoot.MaximumLength;
598 ModuleNameCopy.Buffer = ExAllocatePool(NonPagedPool, SystemRoot.MaximumLength + LdrEntry->BaseDllName.MaximumLength);
599 RtlCopyUnicodeString(&ModuleNameCopy, &SystemRoot);
600 RtlCopyMemory
601 (ModuleNameCopy.Buffer + ModuleNameCopy.Length / sizeof(WCHAR),
602 LdrEntry->BaseDllName.Buffer,
603 LdrEntry->BaseDllName.Length);
604 ModuleNameCopy.Length += LdrEntry->BaseDllName.Length;
605 KdbpSymLoadModuleSymbols(&ModuleNameCopy,
606 (PROSSYM_INFO*)&LdrEntry->PatchInformation);
607 if (!LdrEntry->PatchInformation) {
608 SystemRoot.Length -= strlen("Drivers\\") * sizeof(WCHAR);
609 RtlCopyUnicodeString(&ModuleNameCopy, &SystemRoot);
610 RtlCopyMemory
611 (ModuleNameCopy.Buffer + ModuleNameCopy.Length / sizeof(WCHAR),
612 LdrEntry->BaseDllName.Buffer,
613 LdrEntry->BaseDllName.Length);
614 ModuleNameCopy.Length += LdrEntry->BaseDllName.Length;
615 KdbpSymLoadModuleSymbols(&ModuleNameCopy,
616 (PROSSYM_INFO*)&LdrEntry->PatchInformation);
617 }
618 RtlFreeUnicodeString(&ModuleNameCopy);
619 }
620
621 /* It already added symbols to cache */
622 DPRINT("Installed symbols: %wZ@%p-%p %p\n",
623 &LdrEntry->BaseDllName,
624 LdrEntry->DllBase,
625 (PVOID)(LdrEntry->SizeOfImage + (ULONG_PTR)LdrEntry->DllBase),
626 LdrEntry->PatchInformation);
627 }
628
629 VOID
630 NTAPI
631 KdbDebugPrint(
632 PCH Message,
633 ULONG Length)
634 {
635 /* Nothing here */
636 }
637
638 static PVOID KdbpSymAllocMem(ULONG_PTR size)
639 {
640 return ExAllocatePoolWithTag(NonPagedPool, size, 'RSYM');
641 }
642
643 static VOID KdbpSymFreeMem(PVOID Area)
644 {
645 return ExFreePool(Area);
646 }
647
648 static BOOLEAN KdbpSymReadMem(PVOID FileContext, PVOID TargetDebug, PVOID SourceMem, ULONG Size)
649 {
650 return NT_SUCCESS(KdbpSafeReadMemory(TargetDebug, SourceMem, Size));
651 }
652
653 static ROSSYM_CALLBACKS KdbpRosSymCallbacks = {
654 KdbpSymAllocMem, KdbpSymFreeMem,
655 KdbpReadSymFile, KdbpSeekSymFile,
656 KdbpSymReadMem
657 };
658
659 /*! \brief Initializes the KDB symbols implementation.
660 *
661 * \param DispatchTable Pointer to the KD dispatch table
662 * \param BootPhase Phase of initialization
663 */
664 VOID
665 NTAPI
666 KdbInitialize(
667 PKD_DISPATCH_TABLE DispatchTable,
668 ULONG BootPhase)
669 {
670 PCHAR p1, p2;
671 SHORT Found = FALSE;
672 CHAR YesNo;
673 PLDR_DATA_TABLE_ENTRY LdrEntry;
674
675 DPRINT("KdbSymInit() BootPhase=%d\n", BootPhase);
676
677 LoadSymbols = FALSE;
678
679 #if DBG
680 /* Load symbols only if we have 96Mb of RAM or more */
681 if (MmNumberOfPhysicalPages >= 0x6000)
682 LoadSymbols = TRUE;
683 #endif
684
685 if (BootPhase == 0)
686 {
687 /* Write out the functions that we support for now */
688 DispatchTable->KdpInitRoutine = KdpKdbgInit;
689 DispatchTable->KdpPrintRoutine = KdbDebugPrint;
690
691 /* Register as a Provider */
692 InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
693
694 /* Perform actual initialization of symbol module */
695 //NtoskrnlModuleObject->PatchInformation = NULL;
696 //LdrHalModuleObject->PatchInformation = NULL;
697
698 InitializeListHead(&SymbolFileListHead);
699 KeInitializeSpinLock(&SymbolFileListLock);
700
701 /* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS,
702 * /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */
703 ASSERT(KeLoaderBlock);
704 p1 = KeLoaderBlock->LoadOptions;
705 while('\0' != *p1 && NULL != (p2 = strchr(p1, '/')))
706 {
707 p2++;
708 Found = 0;
709 if (0 == _strnicmp(p2, "LOADSYMBOLS", 11))
710 {
711 Found = +1;
712 p2 += 11;
713 }
714 else if (0 == _strnicmp(p2, "NOLOADSYMBOLS", 13))
715 {
716 Found = -1;
717 p2 += 13;
718 }
719 if (0 != Found)
720 {
721 while (isspace(*p2))
722 {
723 p2++;
724 }
725 if ('=' == *p2)
726 {
727 p2++;
728 while (isspace(*p2))
729 {
730 p2++;
731 }
732 YesNo = toupper(*p2);
733 if ('N' == YesNo || 'F' == YesNo || '0' == YesNo)
734 {
735 Found = -1 * Found;
736 }
737 }
738 LoadSymbols = (0 < Found);
739 }
740 p1 = p2;
741 }
742
743 RosSymInit(&KdbpRosSymCallbacks);
744 }
745 else if (BootPhase == 3)
746 {
747 /* Load symbols for NTOSKRNL.EXE.
748 It is always the first module in PsLoadedModuleList. KeLoaderBlock can't be used here as its content is just temporary. */
749 LdrEntry = CONTAINING_RECORD(PsLoadedModuleList.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
750 KdbSymProcessSymbols(LdrEntry);
751
752 /* Also load them for HAL.DLL. */
753 LdrEntry = CONTAINING_RECORD(PsLoadedModuleList.Flink->Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
754 KdbSymProcessSymbols(LdrEntry);
755
756 KdbpSymbolsInitialized = TRUE;
757 }
758 }
759
760 /* EOF */