Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / 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 #if 0
182 PROSSYM_KM_OWN_CONTEXT FileContext;
183 #endif
184 ULONG_PTR RelativeAddress;
185 NTSTATUS Status;
186 ROSSYM_LINEINFO LineInfo = {0};
187
188 struct {
189 enum _ROSSYM_REGNAME regname;
190 size_t ctx_offset;
191 } regmap[] = {
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) }
200 };
201
202 if (Context)
203 {
204 #if 0
205 // Disable arguments for now
206 DPRINT("Has Context %x (EBP %x)\n", Context, Context->Ebp);
207 LineInfo.Flags = ROSSYM_LINEINFO_HAS_REGISTERS;
208 #endif
209
210 for (i = 0; i < sizeof(regmap) / sizeof(regmap[0]); i++) {
211 memcpy
212 (&LineInfo.Registers.Registers[regmap[i].regname],
213 ((PCHAR)Context)+regmap[i].ctx_offset,
214 sizeof(ULONG_PTR));
215 DPRINT("DWARF REG[%d] -> %x\n", regmap[i].regname, LineInfo.Registers.Registers[regmap[i].regname]);
216 }
217 }
218
219 if (!KdbpSymbolsInitialized || !KdbpSymFindModule(Address, NULL, -1, &LdrEntry))
220 return FALSE;
221
222 RelativeAddress = (ULONG_PTR)Address - (ULONG_PTR)LdrEntry->DllBase;
223 Status = KdbSymGetAddressInformation
224 (LdrEntry->PatchInformation,
225 RelativeAddress,
226 &LineInfo);
227
228 if (NT_SUCCESS(Status))
229 {
230 DbgPrint("<%wZ:%x (%s:%d (%s))>",
231 &LdrEntry->BaseDllName, RelativeAddress, LineInfo.FileName, LineInfo.LineNumber, LineInfo.FunctionName);
232 if (Context && LineInfo.NumParams)
233 {
234 int i;
235 char *comma = "";
236 DbgPrint("(");
237 for (i = 0; i < LineInfo.NumParams; i++) {
238 DbgPrint
239 ("%s%s=%llx",
240 comma,
241 LineInfo.Parameters[i].ValueName,
242 LineInfo.Parameters[i].Value);
243 comma = ",";
244 }
245 DbgPrint(")");
246 }
247
248 return TRUE;
249 }
250 else if (Address < MmSystemRangeStart)
251 {
252 MemoryArea = MmLocateMemoryAreaByAddress(&PsGetCurrentProcess()->Vm, Address);
253 if (!MemoryArea || MemoryArea->Type != MEMORY_AREA_SECTION_VIEW)
254 {
255 goto end;
256 }
257
258 SectionObject = MemoryArea->Data.SectionData.Section;
259 if (!(SectionObject->AllocationAttributes & SEC_IMAGE)) goto end;
260 #if 0
261 if (MemoryArea->StartingAddress != (PVOID)KdbpImageBase)
262 {
263 if (KdbpRosSymInfo)
264 {
265 RosSymDelete(KdbpRosSymInfo);
266 KdbpRosSymInfo = NULL;
267 KdbpImageBase = 0;
268 }
269
270 if ((FileContext = KdbpCaptureFileForSymbols(SectionObject->FileObject)))
271 {
272 if (RosSymCreateFromFile(FileContext, &KdbpRosSymInfo))
273 KdbpImageBase = (ULONG_PTR)MemoryArea->StartingAddress;
274
275 KdbpReleaseFileForSymbols(FileContext);
276 }
277 }
278
279 if (KdbpRosSymInfo)
280 {
281 RelativeAddress = (ULONG_PTR)Address - KdbpImageBase;
282 RosSymFreeInfo(&LineInfo);
283 Status = KdbSymGetAddressInformation
284 (KdbpRosSymInfo,
285 RelativeAddress,
286 &LineInfo);
287 if (NT_SUCCESS(Status))
288 {
289 DbgPrint
290 ("<%wZ:%x (%s:%d (%s))>",
291 &SectionObject->FileObject->FileName,
292 RelativeAddress,
293 LineInfo.FileName,
294 LineInfo.LineNumber,
295 LineInfo.FunctionName);
296
297 if (Context && LineInfo.NumParams)
298 {
299 int i;
300 char *comma = "";
301 DbgPrint("(");
302 for (i = 0; i < LineInfo.NumParams; i++) {
303 DbgPrint
304 ("%s%s=%llx",
305 comma,
306 LineInfo.Parameters[i].ValueName,
307 LineInfo.Parameters[i].Value);
308 comma = ",";
309 }
310 DbgPrint(")");
311 }
312
313 return TRUE;
314 }
315 }
316 #endif
317 }
318
319 end:
320 DbgPrint("<%wZ:%x>", &LdrEntry->BaseDllName, RelativeAddress);
321
322 return TRUE;
323 }
324
325
326 /*! \brief Get information for an address (source file, line number,
327 * function name)
328 *
329 * \param SymbolInfo Pointer to ROSSYM_INFO.
330 * \param RelativeAddress Relative address to look up.
331 * \param LineNumber Pointer to an ULONG which is filled with the line
332 * number (can be NULL)
333 * \param FileName Pointer to an array of CHARs which gets filled with
334 * the filename (can be NULL)
335 * \param FunctionName Pointer to an array of CHARs which gets filled with
336 * the function name (can be NULL)
337 *
338 * \returns NTSTATUS error code.
339 * \retval STATUS_SUCCESS At least one of the requested informations was found.
340 * \retval STATUS_UNSUCCESSFUL None of the requested information was found.
341 */
342 NTSTATUS
343 KdbSymGetAddressInformation(
344 IN PROSSYM_INFO RosSymInfo,
345 IN ULONG_PTR RelativeAddress,
346 IN PROSSYM_LINEINFO LineInfo)
347 {
348 if (!KdbpSymbolsInitialized ||
349 !RosSymInfo ||
350 !RosSymGetAddressInformation(RosSymInfo, RelativeAddress, LineInfo))
351 {
352 return STATUS_UNSUCCESSFUL;
353 }
354
355 return STATUS_SUCCESS;
356 }
357
358 /*! \brief Find cached symbol file.
359 *
360 * Looks through the list of cached symbol files and tries to find an already
361 * loaded one.
362 *
363 * \param FileName FileName of the symbol file to look for.
364 *
365 * \returns A pointer to the cached symbol info.
366 * \retval NULL No cached info found.
367 *
368 * \sa KdbpSymAddCachedFile
369 */
370 PROSSYM_INFO
371 KdbpSymFindCachedFile(
372 IN PUNICODE_STRING FileName)
373 {
374 PIMAGE_SYMBOL_INFO_CACHE Current;
375 PLIST_ENTRY CurrentEntry;
376 KIRQL Irql;
377
378 KeAcquireSpinLock(&SymbolFileListLock, &Irql);
379
380 CurrentEntry = SymbolFileListHead.Flink;
381 while (CurrentEntry != (&SymbolFileListHead))
382 {
383 Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
384
385 if (RtlEqualUnicodeString(&Current->FileName, FileName, TRUE))
386 {
387 Current->RefCount++;
388 KeReleaseSpinLock(&SymbolFileListLock, Irql);
389 DPRINT("Found cached file!\n");
390 return Current->RosSymInfo;
391 }
392
393 CurrentEntry = CurrentEntry->Flink;
394 }
395
396 KeReleaseSpinLock(&SymbolFileListLock, Irql);
397
398 DPRINT("Cached file not found!\n");
399 return NULL;
400 }
401
402 /*! \brief Add a symbol file to the cache.
403 *
404 * \param FileName Filename of the symbol file.
405 * \param RosSymInfo Pointer to the symbol info.
406 *
407 * \sa KdbpSymRemoveCachedFile
408 */
409 static VOID
410 KdbpSymAddCachedFile(
411 IN PUNICODE_STRING FileName,
412 IN PROSSYM_INFO RosSymInfo)
413 {
414 PIMAGE_SYMBOL_INFO_CACHE CacheEntry;
415
416 DPRINT("Adding symbol file: %wZ RosSymInfo = %p\n", FileName, RosSymInfo);
417
418 /* allocate entry */
419 CacheEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE), TAG_KDBS);
420 ASSERT(CacheEntry);
421 RtlZeroMemory(CacheEntry, sizeof (IMAGE_SYMBOL_INFO_CACHE));
422
423 /* fill entry */
424 CacheEntry->FileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
425 FileName->Length,
426 TAG_KDBS);
427 CacheEntry->FileName.MaximumLength = FileName->Length;
428 RtlCopyUnicodeString(&CacheEntry->FileName, FileName);
429 ASSERT(CacheEntry->FileName.Buffer);
430 CacheEntry->RefCount = 1;
431 CacheEntry->RosSymInfo = RosSymInfo;
432 InsertTailList(&SymbolFileListHead, &CacheEntry->ListEntry); /* FIXME: Lock list? */
433 }
434
435 /*! \brief Remove a symbol file (reference) from the cache.
436 *
437 * Tries to find a cache entry matching the given symbol info and decreases
438 * it's reference count. If the refcount is 0 after decreasing it the cache
439 * entry will be removed from the list and freed.
440 *
441 * \param RosSymInfo Pointer to the symbol info.
442 *
443 * \sa KdbpSymAddCachedFile
444 */
445 static VOID
446 KdbpSymRemoveCachedFile(
447 IN PROSSYM_INFO RosSymInfo)
448 {
449 PIMAGE_SYMBOL_INFO_CACHE Current;
450 PLIST_ENTRY CurrentEntry;
451 KIRQL Irql;
452
453 KeAcquireSpinLock(&SymbolFileListLock, &Irql);
454
455 CurrentEntry = SymbolFileListHead.Flink;
456 while (CurrentEntry != (&SymbolFileListHead))
457 {
458 Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
459
460 if (Current->RosSymInfo == RosSymInfo) /* found */
461 {
462 ASSERT(Current->RefCount > 0);
463 Current->RefCount--;
464 if (Current->RefCount < 1)
465 {
466 RemoveEntryList(&Current->ListEntry);
467 RosSymDelete(Current->RosSymInfo);
468 ExFreePool(Current);
469 }
470
471 KeReleaseSpinLock(&SymbolFileListLock, Irql);
472 return;
473 }
474
475 CurrentEntry = CurrentEntry->Flink;
476 }
477
478 KeReleaseSpinLock(&SymbolFileListLock, Irql);
479 }
480
481 /*! \brief Loads a symbol file.
482 *
483 * \param FileName Filename of the symbol file to load.
484 * \param RosSymInfo Pointer to a ROSSYM_INFO which gets filled.
485 *
486 * \sa KdbpSymUnloadModuleSymbols
487 */
488 VOID
489 KdbpSymLoadModuleSymbols(
490 IN PUNICODE_STRING FileName,
491 OUT PROSSYM_INFO *RosSymInfo)
492 {
493 OBJECT_ATTRIBUTES ObjectAttributes;
494 HANDLE FileHandle;
495 NTSTATUS Status;
496 IO_STATUS_BLOCK IoStatusBlock;
497 PFILE_OBJECT FileObject;
498 PROSSYM_KM_OWN_CONTEXT FileContext;
499
500 /* Allow KDB to break on module load */
501 KdbModuleLoaded(FileName);
502
503 if (!LoadSymbols)
504 {
505 *RosSymInfo = NULL;
506 return;
507 }
508
509 /* Try to find cached (already loaded) symbol file */
510 *RosSymInfo = KdbpSymFindCachedFile(FileName);
511 if (*RosSymInfo)
512 {
513 DPRINT("Found cached symbol file %wZ\n", FileName);
514 return;
515 }
516
517 /* Open the file */
518 InitializeObjectAttributes(&ObjectAttributes,
519 FileName,
520 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
521 NULL,
522 NULL);
523
524 DPRINT("Attempting to open image: %wZ\n", FileName);
525
526 Status = ZwOpenFile(&FileHandle,
527 FILE_READ_ACCESS | SYNCHRONIZE,
528 &ObjectAttributes,
529 &IoStatusBlock,
530 FILE_SHARE_READ | FILE_SHARE_WRITE,
531 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
532 if (!NT_SUCCESS(Status))
533 {
534 DPRINT("Could not open image file(%x): %wZ\n", Status, FileName);
535 return;
536 }
537
538 DPRINT("Loading symbols from %wZ...\n", FileName);
539
540 Status = ObReferenceObjectByHandle
541 (FileHandle,
542 FILE_READ_DATA | SYNCHRONIZE,
543 NULL,
544 KernelMode,
545 (PVOID*)&FileObject,
546 NULL);
547
548 if (!NT_SUCCESS(Status))
549 {
550 DPRINT("Could not get the file object\n");
551 ZwClose(FileHandle);
552 return;
553 }
554
555 if ((FileContext = KdbpCaptureFileForSymbols(FileObject)))
556 {
557 if (RosSymCreateFromFile(FileContext, RosSymInfo))
558 {
559 /* add file to cache */
560 int i;
561 UNICODE_STRING TruncatedName = *FileName;
562 for (i = (TruncatedName.Length / sizeof(WCHAR)) - 1; i >= 0; i--)
563 if (TruncatedName.Buffer[i] == '\\') {
564 TruncatedName.Buffer += i+1;
565 TruncatedName.Length -= (i+1)*sizeof(WCHAR);
566 TruncatedName.MaximumLength -= (i+1)*sizeof(WCHAR);
567 break;
568 }
569 KdbpSymAddCachedFile(&TruncatedName, *RosSymInfo);
570 DPRINT("Installed symbols: %wZ %p\n", &TruncatedName, *RosSymInfo);
571 }
572 KdbpReleaseFileForSymbols(FileContext);
573 }
574
575 ObDereferenceObject(FileObject);
576 ZwClose(FileHandle);
577 }
578
579 VOID
580 KdbSymProcessSymbols(
581 IN PLDR_DATA_TABLE_ENTRY LdrEntry)
582 {
583 if (!LoadSymbols)
584 {
585 LdrEntry->PatchInformation = NULL;
586 return;
587 }
588
589 /* Remove symbol info if it already exists */
590 if (LdrEntry->PatchInformation) {
591 KdbpSymRemoveCachedFile(LdrEntry->PatchInformation);
592 }
593
594 /* Error loading symbol info, try to load it from file */
595 KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName,
596 (PROSSYM_INFO*)&LdrEntry->PatchInformation);
597
598 if (!LdrEntry->PatchInformation) {
599 // HACK: module dll names don't identify the real files
600 UNICODE_STRING SystemRoot;
601 UNICODE_STRING ModuleNameCopy;
602 RtlInitUnicodeString(&SystemRoot, L"\\SystemRoot\\system32\\Drivers\\");
603 ModuleNameCopy.Length = 0;
604 ModuleNameCopy.MaximumLength =
605 LdrEntry->BaseDllName.MaximumLength + SystemRoot.MaximumLength;
606 ModuleNameCopy.Buffer = ExAllocatePool(NonPagedPool, SystemRoot.MaximumLength + LdrEntry->BaseDllName.MaximumLength);
607 RtlCopyUnicodeString(&ModuleNameCopy, &SystemRoot);
608 RtlCopyMemory
609 (ModuleNameCopy.Buffer + ModuleNameCopy.Length / sizeof(WCHAR),
610 LdrEntry->BaseDllName.Buffer,
611 LdrEntry->BaseDllName.Length);
612 ModuleNameCopy.Length += LdrEntry->BaseDllName.Length;
613 KdbpSymLoadModuleSymbols(&ModuleNameCopy,
614 (PROSSYM_INFO*)&LdrEntry->PatchInformation);
615 if (!LdrEntry->PatchInformation) {
616 SystemRoot.Length -= strlen("Drivers\\") * sizeof(WCHAR);
617 RtlCopyUnicodeString(&ModuleNameCopy, &SystemRoot);
618 RtlCopyMemory
619 (ModuleNameCopy.Buffer + ModuleNameCopy.Length / sizeof(WCHAR),
620 LdrEntry->BaseDllName.Buffer,
621 LdrEntry->BaseDllName.Length);
622 ModuleNameCopy.Length += LdrEntry->BaseDllName.Length;
623 KdbpSymLoadModuleSymbols(&ModuleNameCopy,
624 (PROSSYM_INFO*)&LdrEntry->PatchInformation);
625 }
626 RtlFreeUnicodeString(&ModuleNameCopy);
627 }
628
629 /* It already added symbols to cache */
630 DPRINT("Installed symbols: %wZ@%p-%p %p\n",
631 &LdrEntry->BaseDllName,
632 LdrEntry->DllBase,
633 (PVOID)(LdrEntry->SizeOfImage + (ULONG_PTR)LdrEntry->DllBase),
634 LdrEntry->PatchInformation);
635 }
636
637 VOID
638 NTAPI
639 KdbDebugPrint(
640 PCH Message,
641 ULONG Length)
642 {
643 /* Nothing here */
644 }
645
646 static PVOID KdbpSymAllocMem(ULONG_PTR size)
647 {
648 return ExAllocatePoolWithTag(NonPagedPool, size, 'RSYM');
649 }
650
651 static VOID KdbpSymFreeMem(PVOID Area)
652 {
653 return ExFreePool(Area);
654 }
655
656 static BOOLEAN KdbpSymReadMem(PVOID FileContext, ULONG_PTR* TargetDebug, PVOID SourceMem, ULONG Size)
657 {
658 return NT_SUCCESS(KdbpSafeReadMemory(TargetDebug, SourceMem, Size));
659 }
660
661 static ROSSYM_CALLBACKS KdbpRosSymCallbacks = {
662 KdbpSymAllocMem, KdbpSymFreeMem,
663 KdbpReadSymFile, KdbpSeekSymFile,
664 KdbpSymReadMem
665 };
666
667 /*! \brief Initializes the KDB symbols implementation.
668 *
669 * \param DispatchTable Pointer to the KD dispatch table
670 * \param BootPhase Phase of initialization
671 */
672 VOID
673 NTAPI
674 KdbInitialize(
675 PKD_DISPATCH_TABLE DispatchTable,
676 ULONG BootPhase)
677 {
678 PCHAR p1, p2;
679 SHORT Found = FALSE;
680 CHAR YesNo;
681 PLDR_DATA_TABLE_ENTRY LdrEntry;
682
683 DPRINT("KdbSymInit() BootPhase=%d\n", BootPhase);
684
685 LoadSymbols = FALSE;
686
687 #if DBG
688 /* Load symbols only if we have 96Mb of RAM or more */
689 if (MmNumberOfPhysicalPages >= 0x6000)
690 LoadSymbols = TRUE;
691 #endif
692
693 if (BootPhase == 0)
694 {
695 /* Write out the functions that we support for now */
696 DispatchTable->KdpInitRoutine = KdpKdbgInit;
697 DispatchTable->KdpPrintRoutine = KdbDebugPrint;
698
699 /* Register as a Provider */
700 InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
701
702 /* Perform actual initialization of symbol module */
703 //NtoskrnlModuleObject->PatchInformation = NULL;
704 //LdrHalModuleObject->PatchInformation = NULL;
705
706 InitializeListHead(&SymbolFileListHead);
707 KeInitializeSpinLock(&SymbolFileListLock);
708
709 /* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS,
710 * /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */
711 ASSERT(KeLoaderBlock);
712 p1 = KeLoaderBlock->LoadOptions;
713 while('\0' != *p1 && NULL != (p2 = strchr(p1, '/')))
714 {
715 p2++;
716 Found = 0;
717 if (0 == _strnicmp(p2, "LOADSYMBOLS", 11))
718 {
719 Found = +1;
720 p2 += 11;
721 }
722 else if (0 == _strnicmp(p2, "NOLOADSYMBOLS", 13))
723 {
724 Found = -1;
725 p2 += 13;
726 }
727 if (0 != Found)
728 {
729 while (isspace(*p2))
730 {
731 p2++;
732 }
733 if ('=' == *p2)
734 {
735 p2++;
736 while (isspace(*p2))
737 {
738 p2++;
739 }
740 YesNo = toupper(*p2);
741 if ('N' == YesNo || 'F' == YesNo || '0' == YesNo)
742 {
743 Found = -1 * Found;
744 }
745 }
746 LoadSymbols = (0 < Found);
747 }
748 p1 = p2;
749 }
750
751 RosSymInit(&KdbpRosSymCallbacks);
752 }
753 else if (BootPhase == 3)
754 {
755 /* Load symbols for NTOSKRNL.EXE.
756 It is always the first module in PsLoadedModuleList. KeLoaderBlock can't be used here as its content is just temporary. */
757 LdrEntry = CONTAINING_RECORD(PsLoadedModuleList.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
758 KdbSymProcessSymbols(LdrEntry);
759
760 /* Also load them for HAL.DLL. */
761 LdrEntry = CONTAINING_RECORD(PsLoadedModuleList.Flink->Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
762 KdbSymProcessSymbols(LdrEntry);
763
764 KdbpSymbolsInitialized = TRUE;
765 }
766 }
767
768 /* EOF */