https://git.reactos.org/?p=reactos.git;a=commitdiff;h=835c30232e42acd7143d59...
commit 835c30232e42acd7143d597bedf07e430232535d Author: Jérôme Gardou jerome.gardou@reactos.org AuthorDate: Tue Jun 22 19:46:27 2021 +0200 Commit: Jérôme Gardou zefklop@users.noreply.github.com CommitDate: Tue Jun 29 11:49:20 2021 +0200
[NTOS:KD][NTOS:KD64][NTOS:KDBG] Fix IRQL & spinlock use
KD64: Raise to HIGH_LEVEL when entering trap KDBG: lower to DISPATCH_LEVEL when applying IRQL hack & use a worker thread to load symbols KD&KDBG: Actually unload symbols when required --- ntoskrnl/include/internal/kd64.h | 5 + ntoskrnl/kd/kdio.c | 9 +- ntoskrnl/kd64/kdprint.c | 2 +- ntoskrnl/kd64/kdtrap.c | 10 +- ntoskrnl/kdbg/kdb.c | 9 +- ntoskrnl/kdbg/kdb.h | 4 +- ntoskrnl/kdbg/kdb_cli.c | 6 +- ntoskrnl/kdbg/kdb_symbols.c | 391 +++++++++++++++++---------------------- sdk/include/reactos/rossym.h | 7 +- sdk/lib/rossym/rossympriv.h | 7 - 10 files changed, 203 insertions(+), 247 deletions(-)
diff --git a/ntoskrnl/include/internal/kd64.h b/ntoskrnl/include/internal/kd64.h index 4802c9c9f60..7e992e0b4ec 100644 --- a/ntoskrnl/include/internal/kd64.h +++ b/ntoskrnl/include/internal/kd64.h @@ -514,6 +514,11 @@ KdpDprintf( ... );
+BOOLEAN +NTAPI +KdpPrintString( + _In_ PSTRING Output); + // // Global KD Data // diff --git a/ntoskrnl/kd/kdio.c b/ntoskrnl/kd/kdio.c index 3dabd050d26..275971acd92 100644 --- a/ntoskrnl/kd/kdio.c +++ b/ntoskrnl/kd/kdio.c @@ -580,13 +580,10 @@ KdSendPacket( { #ifdef KDBG PLDR_DATA_TABLE_ENTRY LdrEntry; - if (!WaitStateChange->u.LoadSymbols.UnloadSymbols) + /* Load symbols. Currently implemented only for KDBG! */ + if (KdbpSymFindModule((PVOID)(ULONG_PTR)WaitStateChange->u.LoadSymbols.BaseOfDll, -1, &LdrEntry)) { - /* Load symbols. Currently implemented only for KDBG! */ - if (KdbpSymFindModule((PVOID)(ULONG_PTR)WaitStateChange->u.LoadSymbols.BaseOfDll, NULL, -1, &LdrEntry)) - { - KdbSymProcessSymbols(LdrEntry); - } + KdbSymProcessSymbols(LdrEntry, !WaitStateChange->u.LoadSymbols.UnloadSymbols); } #endif return; diff --git a/ntoskrnl/kd64/kdprint.c b/ntoskrnl/kd64/kdprint.c index a086652ddb3..83e2e2f3840 100644 --- a/ntoskrnl/kd64/kdprint.c +++ b/ntoskrnl/kd64/kdprint.c @@ -445,7 +445,7 @@ KdpDprintf( STRING String; USHORT Length; va_list ap; - CHAR Buffer[100]; + CHAR Buffer[512];
/* Format the string */ va_start(ap, Format); diff --git a/ntoskrnl/kd64/kdtrap.c b/ntoskrnl/kd64/kdtrap.c index b8314a94685..ed13f3f1971 100644 --- a/ntoskrnl/kd64/kdtrap.c +++ b/ntoskrnl/kd64/kdtrap.c @@ -144,10 +144,11 @@ KdpTrap(IN PKTRAP_FRAME TrapFrame, BOOLEAN Handled; NTSTATUS ReturnStatus; USHORT ReturnLength; - KIRQL OldIrql; + KIRQL OldIrql = DISPATCH_LEVEL;
- /* Raise as high as we can. */ - KeRaiseIrql(HIGH_LEVEL, &OldIrql); + /* Raise if we have to. */ + if (KeGetCurrentIrql() < DISPATCH_LEVEL) + OldIrql = KeRaiseIrqlToDpcLevel();
/* * Check if we got a STATUS_BREAKPOINT with a SubID for Print, Prompt or @@ -261,7 +262,8 @@ KdpTrap(IN PKTRAP_FRAME TrapFrame, SecondChanceException); }
- KeLowerIrql(OldIrql); + if (OldIrql < DISPATCH_LEVEL) + KeLowerIrql(OldIrql);
/* Return TRUE or FALSE to caller */ return Handled; diff --git a/ntoskrnl/kdbg/kdb.c b/ntoskrnl/kdbg/kdb.c index 8ec2e3bef1d..df1da7da3d2 100644 --- a/ntoskrnl/kdbg/kdb.c +++ b/ntoskrnl/kdbg/kdb.c @@ -1531,10 +1531,10 @@ KdbEnterDebuggerException( OldEflags = __readeflags(); _disable();
- /* HACK: Save the current IRQL and pretend we are at passive level, - * although interrupts are off. Needed because KDBG calls pageable code. */ + /* HACK: Save the current IRQL and pretend we are at dispatch level */ OldIrql = KeGetCurrentIrql(); - KeLowerIrql(PASSIVE_LEVEL); + if (OldIrql > DISPATCH_LEVEL) + KeLowerIrql(DISPATCH_LEVEL);
/* Exception inside the debugger? Game over. */ if (InterlockedIncrement(&KdbEntryCount) > 1) @@ -1579,7 +1579,8 @@ KdbEnterDebuggerException( InterlockedDecrement(&KdbEntryCount);
/* HACK: Raise back to old IRQL */ - KeRaiseIrql(OldIrql, &OldIrql); + if (OldIrql > DISPATCH_LEVEL) + KeRaiseIrql(OldIrql, &OldIrql);
/* Leave critical section */ __writeeflags(OldEflags); diff --git a/ntoskrnl/kdbg/kdb.h b/ntoskrnl/kdbg/kdb.h index a496cc4a7b5..3ccd6fc49e0 100644 --- a/ntoskrnl/kdbg/kdb.h +++ b/ntoskrnl/kdbg/kdb.h @@ -148,7 +148,6 @@ KdbpRpnEvaluateParsedExpression( BOOLEAN KdbpSymFindModule( IN PVOID Address OPTIONAL, - IN LPCWSTR Name OPTIONAL, IN INT Index OPTIONAL, OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry);
@@ -160,7 +159,8 @@ KdbSymPrintAddress(
VOID KdbSymProcessSymbols( - IN PLDR_DATA_TABLE_ENTRY LdrEntry); + _Inout_ PLDR_DATA_TABLE_ENTRY LdrEntry, + _In_ BOOLEAN Load);
/* from kdb.c */
diff --git a/ntoskrnl/kdbg/kdb_cli.c b/ntoskrnl/kdbg/kdb_cli.c index 228bebffd4d..6c903f93695 100644 --- a/ntoskrnl/kdbg/kdb_cli.c +++ b/ntoskrnl/kdbg/kdb_cli.c @@ -1977,7 +1977,7 @@ KdbpCmdMod(
Address = (ULONG_PTR)Result;
- if (!KdbpSymFindModule((PVOID)Address, NULL, -1, &LdrEntry)) + if (!KdbpSymFindModule((PVOID)Address, -1, &LdrEntry)) { KdbpPrint("No module containing address 0x%p found!\n", Address); return TRUE; @@ -1987,7 +1987,7 @@ KdbpCmdMod( } else { - if (!KdbpSymFindModule(NULL, NULL, 0, &LdrEntry)) + if (!KdbpSymFindModule(NULL, 0, &LdrEntry)) { ULONG_PTR ntoskrnlBase = ((ULONG_PTR)KdbpCmdMod) & 0xfff00000; KdbpPrint(" Base Size Name\n"); @@ -2003,7 +2003,7 @@ KdbpCmdMod( { KdbpPrint(" %08x %08x %wZ\n", LdrEntry->DllBase, LdrEntry->SizeOfImage, &LdrEntry->BaseDllName);
- if(DisplayOnlyOneModule || !KdbpSymFindModule(NULL, NULL, i++, &LdrEntry)) + if(DisplayOnlyOneModule || !KdbpSymFindModule(NULL, i++, &LdrEntry)) break; }
diff --git a/ntoskrnl/kdbg/kdb_symbols.c b/ntoskrnl/kdbg/kdb_symbols.c index a066e39d8b7..997b55e5516 100644 --- a/ntoskrnl/kdbg/kdb_symbols.c +++ b/ntoskrnl/kdbg/kdb_symbols.c @@ -27,27 +27,19 @@ typedef struct _IMAGE_SYMBOL_INFO_CACHE IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE;
static BOOLEAN LoadSymbols; -static LIST_ENTRY SymbolFileListHead; -static KSPIN_LOCK SymbolFileListLock; -BOOLEAN KdbpSymbolsInitialized = FALSE; +static LIST_ENTRY SymbolsToLoad; +static KSPIN_LOCK SymbolsToLoadLock; +static KEVENT SymbolsToLoadEvent;
/* FUNCTIONS ****************************************************************/
-static NTSTATUS -KdbSymGetAddressInformation( - IN PROSSYM_INFO RosSymInfo, - IN ULONG_PTR RelativeAddress, - OUT PULONG LineNumber OPTIONAL, - OUT PCH FileName OPTIONAL, - OUT PCH FunctionName OPTIONAL); - -static BOOLEAN +static +BOOLEAN KdbpSymSearchModuleList( IN PLIST_ENTRY current_entry, IN PLIST_ENTRY end_entry, IN PLONG Count, IN PVOID Address, - IN LPCWSTR Name, IN INT Index, OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry) { @@ -56,7 +48,6 @@ KdbpSymSearchModuleList( *pLdrEntry = CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
if ((Address && Address >= (PVOID)(*pLdrEntry)->DllBase && Address < (PVOID)((ULONG_PTR)(*pLdrEntry)->DllBase + (*pLdrEntry)->SizeOfImage)) || - (Name && !_wcsnicmp((*pLdrEntry)->BaseDllName.Buffer, Name, (*pLdrEntry)->BaseDllName.Length / sizeof(WCHAR))) || (Index >= 0 && (*Count)++ == Index)) { return TRUE; @@ -83,7 +74,6 @@ KdbpSymSearchModuleList( BOOLEAN KdbpSymFindModule( IN PVOID Address OPTIONAL, - IN LPCWSTR Name OPTIONAL, IN INT Index OPTIONAL, OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry) { @@ -91,16 +81,18 @@ KdbpSymFindModule( PEPROCESS CurrentProcess;
/* First try to look up the module in the kernel module list. */ + KeAcquireSpinLockAtDpcLevel(&PsLoadedModuleSpinLock); if(KdbpSymSearchModuleList(PsLoadedModuleList.Flink, &PsLoadedModuleList, &Count, Address, - Name, Index, pLdrEntry)) { + KeReleaseSpinLockFromDpcLevel(&PsLoadedModuleSpinLock); return TRUE; } + KeReleaseSpinLockFromDpcLevel(&PsLoadedModuleSpinLock);
/* That didn't succeed. Try the module list of the current process now. */ CurrentProcess = PsGetCurrentProcess(); @@ -112,11 +104,11 @@ KdbpSymFindModule( &CurrentProcess->Peb->Ldr->InLoadOrderModuleList, &Count, Address, - Name, Index, pLdrEntry); }
+static PCHAR NTAPI KdbpSymUnicodeToAnsi(IN PUNICODE_STRING Unicode, @@ -159,233 +151,183 @@ KdbSymPrintAddress( { PLDR_DATA_TABLE_ENTRY LdrEntry; ULONG_PTR RelativeAddress; - NTSTATUS Status; - ULONG LineNumber; - CHAR FileName[256]; - CHAR FunctionName[256]; + BOOLEAN Printed = FALSE; CHAR ModuleNameAnsi[64];
- if (!KdbpSymbolsInitialized || !KdbpSymFindModule(Address, NULL, -1, &LdrEntry)) + if (!KdbpSymFindModule(Address, -1, &LdrEntry)) return FALSE;
+ RelativeAddress = (ULONG_PTR)Address - (ULONG_PTR)LdrEntry->DllBase; + KdbpSymUnicodeToAnsi(&LdrEntry->BaseDllName, - ModuleNameAnsi, - sizeof(ModuleNameAnsi)); + ModuleNameAnsi, + sizeof(ModuleNameAnsi));
- RelativeAddress = (ULONG_PTR)Address - (ULONG_PTR)LdrEntry->DllBase; - Status = KdbSymGetAddressInformation(LdrEntry->PatchInformation, - RelativeAddress, - &LineNumber, - FileName, - FunctionName); - if (NT_SUCCESS(Status)) + if (LdrEntry->PatchInformation) { - KdpDprintf("<%s:%x (%s:%d (%s))>", - ModuleNameAnsi, RelativeAddress, FileName, LineNumber, FunctionName); + ULONG LineNumber; + CHAR FileName[256]; + CHAR FunctionName[256]; + + if (RosSymGetAddressInformation(LdrEntry->PatchInformation, RelativeAddress, &LineNumber, FileName, FunctionName)) + { + STRING str; + /* Use KdpPrintString because KdpDprintf is limited wrt string size */ + KdpDprintf("<%s:%x (", ModuleNameAnsi, RelativeAddress); + str.Buffer = FileName; + str.Length = strnlen(FileName, sizeof(FileName)); + str.MaximumLength = sizeof(FileName); + KdpPrintString(&str); + KdpDprintf(":%d (%s))>", LineNumber, FunctionName); + + Printed = TRUE; + } } - else + + if (!Printed) { + /* Just print module & address */ KdpDprintf("<%s:%x>", ModuleNameAnsi, RelativeAddress); }
return TRUE; }
- -/*! \brief Get information for an address (source file, line number, - * function name) - * - * \param SymbolInfo Pointer to ROSSYM_INFO. - * \param RelativeAddress Relative address to look up. - * \param LineNumber Pointer to an ULONG which is filled with the line - * number (can be NULL) - * \param FileName Pointer to an array of CHARs which gets filled with - * the filename (can be NULL) - * \param FunctionName Pointer to an array of CHARs which gets filled with - * the function name (can be NULL) - * - * \returns NTSTATUS error code. - * \retval STATUS_SUCCESS At least one of the requested informations was found. - * \retval STATUS_UNSUCCESSFUL None of the requested information was found. - */ -static NTSTATUS -KdbSymGetAddressInformation( - IN PROSSYM_INFO RosSymInfo, - IN ULONG_PTR RelativeAddress, - OUT PULONG LineNumber OPTIONAL, - OUT PCH FileName OPTIONAL, - OUT PCH FunctionName OPTIONAL) -{ - if (!KdbpSymbolsInitialized || - !RosSymInfo || - !RosSymGetAddressInformation(RosSymInfo, RelativeAddress, LineNumber, FileName, FunctionName)) - { - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - -/*! \brief Find cached symbol file. - * - * Looks through the list of cached symbol files and tries to find an already - * loaded one. - * - * \param FileName FileName of the symbol file to look for. +static KSTART_ROUTINE LoadSymbolsRoutine; +/*! \brief The symbol loader thread routine. + * This opens the image file for reading and loads the symbols + * section from there. * - * \returns A pointer to the cached symbol info. - * \retval NULL No cached info found. + * \note We must do this because KdbSymProcessSymbols is + * called at high IRQL and we can't set the event from here * - * \sa KdbpSymAddCachedFile + * \param Context Unused */ -static PROSSYM_INFO -KdbpSymFindCachedFile( - IN PUNICODE_STRING FileName) +_Use_decl_annotations_ +VOID +NTAPI +LoadSymbolsRoutine( + _In_ PVOID Context) { - PIMAGE_SYMBOL_INFO_CACHE Current; - PLIST_ENTRY CurrentEntry; - - DPRINT("Looking for cached symbol file %wZ\n", FileName); + UNREFERENCED_PARAMETER(Context);
- KeAcquireSpinLockAtDpcLevel(&SymbolFileListLock); - - CurrentEntry = SymbolFileListHead.Flink; - while (CurrentEntry != (&SymbolFileListHead)) + while (TRUE) { - Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry); - - DPRINT("Current->FileName %wZ FileName %wZ\n", &Current->FileName, FileName); - if (RtlEqualUnicodeString(&Current->FileName, FileName, TRUE)) + PLIST_ENTRY ListEntry; + NTSTATUS Status = KeWaitForSingleObject(&SymbolsToLoadEvent, WrKernel, KernelMode, FALSE, NULL); + if (!NT_SUCCESS(Status)) { - Current->RefCount++; - KeReleaseSpinLockFromDpcLevel(&SymbolFileListLock); - DPRINT("Found cached file!\n"); - return Current->RosSymInfo; + DPRINT1("KeWaitForSingleObject failed?! 0x%08x\n", Status); + LoadSymbols = FALSE; + return; }
- CurrentEntry = CurrentEntry->Flink; - } + while ((ListEntry = ExInterlockedRemoveHeadList(&SymbolsToLoad, &SymbolsToLoadLock))) + { + PLDR_DATA_TABLE_ENTRY LdrEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks); + HANDLE FileHandle; + OBJECT_ATTRIBUTES Attrib; + IO_STATUS_BLOCK Iosb; + InitializeObjectAttributes(&Attrib, &LdrEntry->FullDllName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); + DPRINT1("Trying %wZ\n", &LdrEntry->FullDllName); + Status = ZwOpenFile(&FileHandle, + FILE_READ_ACCESS | SYNCHRONIZE, + &Attrib, + &Iosb, + FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + /* Try system paths */ + static const UNICODE_STRING System32Dir = RTL_CONSTANT_STRING(L"\SystemRoot\system32\"); + UNICODE_STRING ImagePath; + WCHAR ImagePathBuffer[256]; + RtlInitEmptyUnicodeString(&ImagePath, ImagePathBuffer, sizeof(ImagePathBuffer)); + RtlCopyUnicodeString(&ImagePath, &System32Dir); + RtlAppendUnicodeStringToString(&ImagePath, &LdrEntry->BaseDllName); + InitializeObjectAttributes(&Attrib, &ImagePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); + DPRINT1("Trying %wZ\n", &ImagePath); + Status = ZwOpenFile(&FileHandle, + FILE_READ_ACCESS | SYNCHRONIZE, + &Attrib, + &Iosb, + FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + static const UNICODE_STRING DriversDir= RTL_CONSTANT_STRING(L"\SystemRoot\system32\drivers\"); + + RtlInitEmptyUnicodeString(&ImagePath, ImagePathBuffer, sizeof(ImagePathBuffer)); + RtlCopyUnicodeString(&ImagePath, &DriversDir); + RtlAppendUnicodeStringToString(&ImagePath, &LdrEntry->BaseDllName); + InitializeObjectAttributes(&Attrib, &ImagePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); + DPRINT1("Trying %wZ\n", &ImagePath); + Status = ZwOpenFile(&FileHandle, + FILE_READ_ACCESS | SYNCHRONIZE, + &Attrib, + &Iosb, + FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + } + }
- KeReleaseSpinLockFromDpcLevel(&SymbolFileListLock); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed opening file %wZ (%wZ) for reading symbols (0x%08x)\n", &LdrEntry->FullDllName, &LdrEntry->BaseDllName, Status); + /* We took a ref previously */ + MmUnloadSystemImage(LdrEntry); + continue; + }
- DPRINT("Cached file not found!\n"); - return NULL; -} + /* Hand it to Rossym */ + if (!RosSymCreateFromFile(&FileHandle, (PROSSYM_INFO*)&LdrEntry->PatchInformation)) + LdrEntry->PatchInformation = NULL;
-/*! \brief Add a symbol file to the cache. - * - * \param FileName Filename of the symbol file. - * \param RosSymInfo Pointer to the symbol info. - * - * \sa KdbpSymRemoveCachedFile - */ -static VOID -KdbpSymAddCachedFile( - IN PUNICODE_STRING FileName, - IN PROSSYM_INFO RosSymInfo) -{ - PIMAGE_SYMBOL_INFO_CACHE CacheEntry; - KIRQL Irql; - - DPRINT("Adding symbol file: RosSymInfo = %p\n", RosSymInfo); - - /* allocate entry */ - CacheEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE), TAG_KDBS); - ASSERT(CacheEntry); - RtlZeroMemory(CacheEntry, sizeof (IMAGE_SYMBOL_INFO_CACHE)); - - /* fill entry */ - CacheEntry->FileName.Buffer = ExAllocatePoolWithTag(NonPagedPool, - FileName->Length, - TAG_KDBS); - RtlCopyUnicodeString(&CacheEntry->FileName, FileName); - ASSERT(CacheEntry->FileName.Buffer); - CacheEntry->RefCount = 1; - CacheEntry->RosSymInfo = RosSymInfo; - KeAcquireSpinLock(&SymbolFileListLock, &Irql); - InsertTailList(&SymbolFileListHead, &CacheEntry->ListEntry); - KeReleaseSpinLock(&SymbolFileListLock, Irql); + /* We're done for this one. */ + NtClose(FileHandle); + MmUnloadSystemImage(LdrEntry); + } + } }
-/*! \brief Remove a symbol file (reference) from the cache. +/*! \brief Load symbols from image mapping. If this fails, * - * Tries to find a cache entry matching the given symbol info and decreases - * it's reference count. If the refcount is 0 after decreasing it the cache - * entry will be removed from the list and freed. - * - * \param RosSymInfo Pointer to the symbol info. - * - * \sa KdbpSymAddCachedFile + * \param LdrEntry The entry to load symbols from */ -static VOID -KdbpSymRemoveCachedFile( - IN PROSSYM_INFO RosSymInfo) +VOID +KdbSymProcessSymbols( + _Inout_ PLDR_DATA_TABLE_ENTRY LdrEntry, + _In_ BOOLEAN Load) { - PIMAGE_SYMBOL_INFO_CACHE Current; - PLIST_ENTRY CurrentEntry; - KIRQL Irql; - - KeAcquireSpinLock(&SymbolFileListLock, &Irql); + if (!LoadSymbols) + return;
- CurrentEntry = SymbolFileListHead.Flink; - while (CurrentEntry != (&SymbolFileListHead)) + /* Check if this is unload */ + if (!Load) { - Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry); - - if (Current->RosSymInfo == RosSymInfo) /* found */ + /* Did we process it */ + if (LdrEntry->PatchInformation) { - ASSERT(Current->RefCount > 0); - Current->RefCount--; - if (Current->RefCount < 1) - { - RemoveEntryList(&Current->ListEntry); - RosSymDelete(Current->RosSymInfo); - ExFreePool(Current); - } - - KeReleaseSpinLock(&SymbolFileListLock, Irql); - return; + RosSymDelete(LdrEntry->PatchInformation); + LdrEntry->PatchInformation = NULL; } - - CurrentEntry = CurrentEntry->Flink; + return; }
- KeReleaseSpinLock(&SymbolFileListLock, Irql); - DPRINT1("Warning: Removing unknown symbol file: RosSymInfo = %p\n", RosSymInfo); -} - -VOID -KdbSymProcessSymbols( - IN PLDR_DATA_TABLE_ENTRY LdrEntry) -{ - if (!LoadSymbols) + if (RosSymCreateFromMem(LdrEntry->DllBase, LdrEntry->SizeOfImage, (PROSSYM_INFO*)&LdrEntry->PatchInformation)) { - LdrEntry->PatchInformation = NULL; return; }
- /* Remove symbol info if it already exists */ - if (LdrEntry->PatchInformation) - KdbpSymRemoveCachedFile(LdrEntry->PatchInformation); - - /* Check cache */ - LdrEntry->PatchInformation = KdbpSymFindCachedFile(&LdrEntry->FullDllName); + /* Add a ref until we really process it */ + LdrEntry->LoadCount++;
- if (!LdrEntry->PatchInformation) - { - /* Load new symbol information */ - if (RosSymCreateFromMem(LdrEntry->DllBase, LdrEntry->SizeOfImage, (PROSSYM_INFO*)&LdrEntry->PatchInformation)) - { - /* Add file to cache */ - KdbpSymAddCachedFile(&LdrEntry->FullDllName, LdrEntry->PatchInformation); - } - } + /* Tell our worker thread to read from it */ + KeAcquireSpinLockAtDpcLevel(&SymbolsToLoadLock); + InsertTailList(&SymbolsToLoad, &LdrEntry->InInitializationOrderLinks); + KeReleaseSpinLockFromDpcLevel(&SymbolsToLoadLock);
- DPRINT("Installed symbols: %wZ@%p-%p %p\n", - &LdrEntry->BaseDllName, - LdrEntry->DllBase, - (PVOID)(LdrEntry->SizeOfImage + (ULONG_PTR)LdrEntry->DllBase), - LdrEntry->PatchInformation); + KeSetEvent(&SymbolsToLoadEvent, IO_NO_INCREMENT, FALSE); }
VOID @@ -412,7 +354,6 @@ KdbInitialize( PCHAR p1, p2; SHORT Found = FALSE; CHAR YesNo; - PLDR_DATA_TABLE_ENTRY LdrEntry;
DPRINT("KdbSymInit() BootPhase=%d\n", BootPhase);
@@ -437,9 +378,6 @@ KdbInitialize( //NtoskrnlModuleObject->PatchInformation = NULL; //LdrHalModuleObject->PatchInformation = NULL;
- InitializeListHead(&SymbolFileListHead); - KeInitializeSpinLock(&SymbolFileListLock); - /* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS, * /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */ ASSERT(KeLoaderBlock); @@ -481,24 +419,39 @@ KdbInitialize( } p1 = p2; } - - RosSymInitKernelMode(); } - else if (BootPhase == 1) + else if ((BootPhase == 1) && LoadSymbols) { + HANDLE Thread; + NTSTATUS Status; KIRQL OldIrql; - /* Load symbols for NTOSKRNL.EXE. - It is always the first module in PsLoadedModuleList. KeLoaderBlock can't be used here as its content is just temporary. */ - OldIrql = KeRaiseIrqlToDpcLevel(); - LdrEntry = CONTAINING_RECORD(PsLoadedModuleList.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - KdbSymProcessSymbols(LdrEntry); - - /* Also load them for HAL.DLL. */ - LdrEntry = CONTAINING_RECORD(PsLoadedModuleList.Flink->Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - KdbSymProcessSymbols(LdrEntry); - KeLowerIrql(OldIrql); - - KdbpSymbolsInitialized = TRUE; + + /* Launch our worker thread */ + InitializeListHead(&SymbolsToLoad); + KeInitializeSpinLock(&SymbolsToLoadLock); + KeInitializeEvent(&SymbolsToLoadEvent, SynchronizationEvent, FALSE); + + Status = PsCreateSystemThread(&Thread, THREAD_ALL_ACCESS, NULL, NULL, NULL, LoadSymbolsRoutine, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed starting symbols loader thread: 0x%08x\n", Status); + LoadSymbols = FALSE; + return; + } + + RosSymInitKernelMode(); + + KeAcquireSpinLock(&PsLoadedModuleSpinLock, &OldIrql); + + PLIST_ENTRY ListEntry = PsLoadedModuleList.Flink; + while (ListEntry != &PsLoadedModuleList) + { + PLDR_DATA_TABLE_ENTRY LdrEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + KdbSymProcessSymbols(LdrEntry, TRUE); + ListEntry = ListEntry->Flink; + } + + KeReleaseSpinLock(&PsLoadedModuleSpinLock, OldIrql); } }
diff --git a/sdk/include/reactos/rossym.h b/sdk/include/reactos/rossym.h index 91a7b9b0f02..e5e9e124a11 100644 --- a/sdk/include/reactos/rossym.h +++ b/sdk/include/reactos/rossym.h @@ -119,7 +119,12 @@ typedef struct _ROSSYM_OWN_FILECONTEXT { struct Dwarf; typedef struct Dwarf *PROSSYM_INFO; #else -typedef struct _ROSSYM_INFO *PROSSYM_INFO; +typedef struct _ROSSYM_INFO { + PROSSYM_ENTRY Symbols; + ULONG SymbolsCount; + PCHAR Strings; + ULONG StringsLength; +} ROSSYM_INFO, *PROSSYM_INFO; #endif
VOID RosSymInit(PROSSYM_CALLBACKS Callbacks); diff --git a/sdk/lib/rossym/rossympriv.h b/sdk/lib/rossym/rossympriv.h index cc3f8ff2ff9..fb97019710a 100644 --- a/sdk/lib/rossym/rossympriv.h +++ b/sdk/lib/rossym/rossympriv.h @@ -9,13 +9,6 @@
#pragma once
-typedef struct _ROSSYM_INFO { - PROSSYM_ENTRY Symbols; - ULONG SymbolsCount; - PCHAR Strings; - ULONG StringsLength; -} ROSSYM_INFO; - extern ROSSYM_CALLBACKS RosSymCallbacks;
#define RosSymAllocMem(Size) (*RosSymCallbacks.AllocMemProc)(Size)