https://git.reactos.org/?p=reactos.git;a=commitdiff;h=835c30232e42acd7143d5…
commit 835c30232e42acd7143d597bedf07e430232535d
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Tue Jun 22 19:46:27 2021 +0200
Commit: Jérôme Gardou <zefklop(a)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)