https://git.reactos.org/?p=reactos.git;a=commitdiff;h=835c30232e42acd7143d597bedf07e430232535d

commit 835c30232e42acd7143d597bedf07e430232535d
Author:     Jérôme Gardou <[email protected]>
AuthorDate: Tue Jun 22 19:46:27 2021 +0200
Commit:     Jérôme Gardou <[email protected]>
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)

Reply via email to