[MMIXER] Fix additional data size initialization for different audio formats (#6753)
[reactos.git] / ntoskrnl / kdbg / kdb_symbols.c
index feb0fb1..11ccd57 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/dbg/kdb_symbols.c
+ * FILE:            ntoskrnl/kdbg/kdb_symbols.c
  * PURPOSE:         Getting symbol information...
  *
  * PROGRAMMERS:     David Welch (welch@cwcom.net)
 /* INCLUDES *****************************************************************/
 
 #include <ntoskrnl.h>
+#include "kdb.h"
 
 #define NDEBUG
-#include <debug.h>
+#include "debug.h"
 
 /* GLOBALS ******************************************************************/
 
@@ -26,20 +27,20 @@ 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 BOOLEAN LoadSymbols = FALSE;
+static LIST_ENTRY SymbolsToLoad;
+static KSPIN_LOCK SymbolsToLoadLock;
+static KEVENT SymbolsToLoadEvent;
 
 /* FUNCTIONS ****************************************************************/
 
-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)
 {
@@ -48,7 +49,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;
@@ -75,7 +75,6 @@ KdbpSymSearchModuleList(
 BOOLEAN
 KdbpSymFindModule(
     IN PVOID Address  OPTIONAL,
-    IN LPCWSTR Name  OPTIONAL,
     IN INT Index  OPTIONAL,
     OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry)
 {
@@ -83,16 +82,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();
@@ -104,11 +105,11 @@ KdbpSymFindModule(
                                    &CurrentProcess->Peb->Ldr->InLoadOrderModuleList,
                                    &Count,
                                    Address,
-                                   Name,
                                    Index,
                                    pLdrEntry);
 }
 
+static
 PCHAR
 NTAPI
 KdbpSymUnicodeToAnsi(IN PUNICODE_STRING Unicode,
@@ -147,427 +148,322 @@ KdbpSymUnicodeToAnsi(IN PUNICODE_STRING Unicode,
 BOOLEAN
 KdbSymPrintAddress(
     IN PVOID Address,
-    IN PKTRAP_FRAME Context)
+    IN PCONTEXT Context)
 {
     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;
-        
-    KdbpSymUnicodeToAnsi(&LdrEntry->BaseDllName,
-                         ModuleNameAnsi,
-                         sizeof(ModuleNameAnsi));
 
     RelativeAddress = (ULONG_PTR)Address - (ULONG_PTR)LdrEntry->DllBase;
-    Status = KdbSymGetAddressInformation(LdrEntry->PatchInformation,
-                                         RelativeAddress,
-                                         &LineNumber,
-                                         FileName,
-                                         FunctionName);
-    if (NT_SUCCESS(Status))
-    {
-        DbgPrint("<%s:%x (%s:%d (%s))>",
-            ModuleNameAnsi, RelativeAddress, FileName, LineNumber, FunctionName);
-    }
-    else
-    {
-        DbgPrint("<%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.
- */
-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.
- *
- * \returns A pointer to the cached symbol info.
- * \retval NULL  No cached info found.
- *
- * \sa KdbpSymAddCachedFile
- */
-static PROSSYM_INFO
-KdbpSymFindCachedFile(
-    IN PUNICODE_STRING FileName)
-{
-    PIMAGE_SYMBOL_INFO_CACHE Current;
-    PLIST_ENTRY CurrentEntry;
-    KIRQL Irql;
-
-    DPRINT("Looking for cached symbol file %wZ\n", FileName);
-
-    KeAcquireSpinLock(&SymbolFileListLock, &Irql);
+    KdbpSymUnicodeToAnsi(&LdrEntry->BaseDllName,
+                        ModuleNameAnsi,
+                        sizeof(ModuleNameAnsi));
 
-    CurrentEntry = SymbolFileListHead.Flink;
-    while (CurrentEntry != (&SymbolFileListHead))
+    if (LdrEntry->PatchInformation)
     {
-        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))
+        ULONG LineNumber;
+        CHAR FileName[256];
+        CHAR FunctionName[256];
+
+        if (RosSymGetAddressInformation(LdrEntry->PatchInformation,
+                                        RelativeAddress,
+                                        &LineNumber,
+                                        FileName,
+                                        FunctionName))
         {
-            Current->RefCount++;
-            KeReleaseSpinLock(&SymbolFileListLock, Irql);
-            DPRINT("Found cached file!\n");
-            return Current->RosSymInfo;
+            KdbPrintf("<%s:%x (%s:%d (%s))>",
+                      ModuleNameAnsi, RelativeAddress,
+                      FileName, LineNumber, FunctionName);
+            Printed = TRUE;
         }
-
-        CurrentEntry = CurrentEntry->Flink;
     }
 
-    KeReleaseSpinLock(&SymbolFileListLock, Irql);
-
-    DPRINT("Cached file not found!\n");
-    return NULL;
-}
+    if (!Printed)
+    {
+        /* Just print module & address */
+        KdbPrintf("<%s:%x>", ModuleNameAnsi, RelativeAddress);
+    }
 
-/*! \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);
+    return TRUE;
 }
 
-/*! \brief Remove a symbol file (reference) from the cache.
- *
- * 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.
+static KSTART_ROUTINE LoadSymbolsRoutine;
+/*! \brief          The symbol loader thread routine.
+ *                  This opens the image file for reading and loads the symbols
+ *                  section from there.
  *
- * \param RosSymInfo  Pointer to the symbol info.
+ * \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 VOID
-KdbpSymRemoveCachedFile(
-    IN PROSSYM_INFO RosSymInfo)
+_Use_decl_annotations_
+VOID
+NTAPI
+LoadSymbolsRoutine(
+    _In_ PVOID Context)
 {
-    PIMAGE_SYMBOL_INFO_CACHE Current;
-    PLIST_ENTRY CurrentEntry;
-    KIRQL Irql;
+    UNREFERENCED_PARAMETER(Context);
 
-    KeAcquireSpinLock(&SymbolFileListLock, &Irql);
-
-    CurrentEntry = SymbolFileListHead.Flink;
-    while (CurrentEntry != (&SymbolFileListHead))
+    while (TRUE)
     {
-        Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
+        PLIST_ENTRY ListEntry;
+        NTSTATUS Status = KeWaitForSingleObject(&SymbolsToLoadEvent, WrKernel, KernelMode, FALSE, NULL);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("KeWaitForSingleObject failed?! 0x%08x\n", Status);
+            LoadSymbols = FALSE;
+            return;
+        }
 
-        if (Current->RosSymInfo == RosSymInfo) /* found */
+        while ((ListEntry = ExInterlockedRemoveHeadList(&SymbolsToLoad, &SymbolsToLoadLock)))
         {
-            ASSERT(Current->RefCount > 0);
-            Current->RefCount--;
-            if (Current->RefCount < 1)
+            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);
+                }
+            }
+
+            if (!NT_SUCCESS(Status))
             {
-                RemoveEntryList(&Current->ListEntry);
-                RosSymDelete(Current->RosSymInfo);
-                ExFreePool(Current);
+                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;
             }
 
-            KeReleaseSpinLock(&SymbolFileListLock, Irql);
-            return;
-        }
+            /* Hand it to Rossym */
+            if (!RosSymCreateFromFile(&FileHandle, (PROSSYM_INFO*)&LdrEntry->PatchInformation))
+                LdrEntry->PatchInformation = NULL;
 
-        CurrentEntry = CurrentEntry->Flink;
+            /* We're done for this one. */
+            NtClose(FileHandle);
+            MmUnloadSystemImage(LdrEntry);
+        }
     }
-
-    KeReleaseSpinLock(&SymbolFileListLock, Irql);
-    DPRINT1("Warning: Removing unknown symbol file: RosSymInfo = %p\n", RosSymInfo);
 }
 
-/*! \brief Loads a symbol file.
- *
- * \param FileName    Filename of the symbol file to load.
- * \param RosSymInfo  Pointer to a ROSSYM_INFO which gets filled.
+/*! \brief          Load symbols from image mapping. If this fails,
  *
- * \sa KdbpSymUnloadModuleSymbols
+ * \param LdrEntry  The entry to load symbols from
  */
-static VOID
-KdbpSymLoadModuleSymbols(
-    IN PUNICODE_STRING FileName,
-    OUT PROSSYM_INFO *RosSymInfo)
+VOID
+KdbSymProcessSymbols(
+    _Inout_ PLDR_DATA_TABLE_ENTRY LdrEntry,
+    _In_ BOOLEAN Load)
 {
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    HANDLE FileHandle;
-    NTSTATUS Status;
-    IO_STATUS_BLOCK IoStatusBlock;
-
-    /* Allow KDB to break on module load */
-    KdbModuleLoaded(FileName);
-
     if (!LoadSymbols)
-    {
-        *RosSymInfo = NULL;
         return;
-    }
 
-    /*  Try to find cached (already loaded) symbol file  */
-    *RosSymInfo = KdbpSymFindCachedFile(FileName);
-    if (*RosSymInfo)
+    /* Check if this is unload */
+    if (!Load)
     {
-        DPRINT("Found cached symbol file %wZ\n", FileName);
-        return;
-    }
-
-    /*  Open the file  */
-    InitializeObjectAttributes(&ObjectAttributes,
-                               FileName,
-                               0,
-                               NULL,
-                               NULL);
-
-    DPRINT("Attempting to open image: %wZ\n", FileName);
-
-    Status = ZwOpenFile(&FileHandle,
-                        FILE_READ_ACCESS | SYNCHRONIZE,
-                        &ObjectAttributes,
-                        &IoStatusBlock,
-                        FILE_SHARE_READ | FILE_SHARE_WRITE,
-                        FILE_SYNCHRONOUS_IO_NONALERT);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT("Could not open image file: %wZ\n", FileName);
-        return;
-    }
-
-    DPRINT("Loading symbols from %wZ...\n", FileName);
-
-    if (!RosSymCreateFromFile(&FileHandle, RosSymInfo))
-    {
-        DPRINT("Failed to load symbols from %wZ\n", FileName);
+        /* Did we process it */
+        if (LdrEntry->PatchInformation)
+        {
+            RosSymDelete(LdrEntry->PatchInformation);
+            LdrEntry->PatchInformation = NULL;
+        }
         return;
     }
 
-    ZwClose(FileHandle);
-
-    DPRINT("Symbols loaded.\n");
-
-    /* add file to cache */
-    KdbpSymAddCachedFile(FileName, *RosSymInfo);
-
-    DPRINT("Installed symbols: %wZ %p\n", FileName, *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);
-
-    /* Load new symbol information */
-    if (! RosSymCreateFromMem(LdrEntry->DllBase,
-        LdrEntry->SizeOfImage,
-        (PROSSYM_INFO*)&LdrEntry->PatchInformation))
-    {
-        /* Error loading symbol info, try to load it from file */
-        KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName,
-            (PROSSYM_INFO*)&LdrEntry->PatchInformation);
-
-        /* It already added symbols to cache */
-    }
-    else
-    {
-        /* Add file to cache */
-        KdbpSymAddCachedFile(&LdrEntry->FullDllName, LdrEntry->PatchInformation);
-    }
-
-    DPRINT("Installed symbols: %wZ@%p-%p %p\n",
-           &LdrEntry->BaseDllName,
-           LdrEntry->DllBase,
-           (PVOID)(LdrEntry->SizeOfImage + (ULONG_PTR)LdrEntry->DllBase),
-           LdrEntry->PatchInformation);
+    /* Add a ref until we really process it */
+    LdrEntry->LoadCount++;
 
-}
+    /* Tell our worker thread to read from it */
+    KeAcquireSpinLockAtDpcLevel(&SymbolsToLoadLock);
+    InsertTailList(&SymbolsToLoad, &LdrEntry->InInitializationOrderLinks);
+    KeReleaseSpinLockFromDpcLevel(&SymbolsToLoadLock);
 
-VOID
-NTAPI
-KdbDebugPrint(
-    PCH Message,
-    ULONG Length)
-{
-    /* Nothing here */
+    KeSetEvent(&SymbolsToLoadEvent, IO_NO_INCREMENT, FALSE);
 }
 
 
-/*! \brief Initializes the KDB symbols implementation.
+/**
+ * @brief   Initializes the KDB symbols implementation.
  *
- * \param DispatchTable         Pointer to the KD dispatch table
- * \param BootPhase             Phase of initialization
- */
-VOID
-NTAPI
-KdbInitialize(
-    PKD_DISPATCH_TABLE DispatchTable,
-    ULONG BootPhase)
+ * @param[in]   BootPhase
+ * Phase of initialization.
+ *
+ * @return
+ * TRUE if symbols are to be loaded at this given BootPhase; FALSE if not.
+ **/
+BOOLEAN
+KdbSymInit(
+    _In_ ULONG BootPhase)
 {
-    PCHAR p1, p2;
-    SHORT Found = FALSE;
-    CHAR YesNo;
-    PLDR_DATA_TABLE_ENTRY LdrEntry;
+#if 1 // FIXME: This is a workaround HACK!!
+    static BOOLEAN OrigLoadSymbols = FALSE;
+#endif
 
     DPRINT("KdbSymInit() BootPhase=%d\n", BootPhase);
 
-    LoadSymbols = FALSE;
-
-#if DBG
-    /* Load symbols only if we have 96Mb of RAM or more */
-    if (MmNumberOfPhysicalPages >= 0x6000)
-        LoadSymbols = TRUE;
-#endif
-
     if (BootPhase == 0)
     {
-        /* Write out the functions that we support for now */
-        DispatchTable->KdpInitRoutine = KdpKdbgInit;
-        DispatchTable->KdpPrintRoutine = KdbDebugPrint;
-
-        /* Register as a Provider */
-        InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
-
-        /* Perform actual initialization of symbol module */
-        //NtoskrnlModuleObject->PatchInformation = NULL;
-        //LdrHalModuleObject->PatchInformation = NULL;
-
-        InitializeListHead(&SymbolFileListHead);
-        KeInitializeSpinLock(&SymbolFileListLock);
+        PSTR CommandLine;
+        SHORT Found = FALSE;
+        CHAR YesNo;
+
+        /* By default, load symbols in DBG builds, but not in REL builds
+           or anything other than x86, because they only work on x86
+           and can cause the system to hang on x64. */
+#if DBG && defined(_M_IX86)
+        LoadSymbols = TRUE;
+#else
+        LoadSymbols = FALSE;
+#endif
 
-        /* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS,
-        * /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */
+        /* Check the command line for LOADSYMBOLS, NOLOADSYMBOLS,
+         * LOADSYMBOLS={YES|NO}, NOLOADSYMBOLS={YES|NO} */
         ASSERT(KeLoaderBlock);
-        p1 = KeLoaderBlock->LoadOptions;
-        while('\0' != *p1 && NULL != (p2 = strchr(p1, '/')))
+        CommandLine = KeLoaderBlock->LoadOptions;
+        while (*CommandLine)
         {
-            p2++;
+            /* Skip any whitespace */
+            while (isspace(*CommandLine))
+                ++CommandLine;
+
             Found = 0;
-            if (0 == _strnicmp(p2, "LOADSYMBOLS", 11))
+            if (_strnicmp(CommandLine, "LOADSYMBOLS", 11) == 0)
             {
                 Found = +1;
-                p2 += 11;
+                CommandLine += 11;
             }
-            else if (0 == _strnicmp(p2, "NOLOADSYMBOLS", 13))
+            else if (_strnicmp(CommandLine, "NOLOADSYMBOLS", 13) == 0)
             {
                 Found = -1;
-                p2 += 13;
+                CommandLine += 13;
             }
-            if (0 != Found)
+            if (Found != 0)
             {
-                while (isspace(*p2))
-                {
-                    p2++;
-                }
-                if ('=' == *p2)
+                if (*CommandLine == '=')
                 {
-                    p2++;
-                    while (isspace(*p2))
-                    {
-                        p2++;
-                    }
-                    YesNo = toupper(*p2);
-                    if ('N' == YesNo || 'F' == YesNo || '0' == YesNo)
+                    ++CommandLine;
+                    YesNo = toupper(*CommandLine);
+                    if (YesNo == 'N' || YesNo == '0')
                     {
                         Found = -1 * Found;
                     }
                 }
                 LoadSymbols = (0 < Found);
             }
-            p1 = p2;
+
+            /* Move on to the next option */
+            while (*CommandLine && !isspace(*CommandLine))
+                ++CommandLine;
         }
 
-        RosSymInitKernelMode();
+#if 1 // FIXME: This is a workaround HACK!!
+// Save the actual value of LoadSymbols but disable it for BootPhase 0.
+        OrigLoadSymbols = LoadSymbols;
+        LoadSymbols = FALSE;
+        return OrigLoadSymbols;
+#endif
     }
     else if (BootPhase == 1)
     {
-        /* 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. */
-        LdrEntry = CONTAINING_RECORD(PsLoadedModuleList.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-        KdbSymProcessSymbols(LdrEntry);
+        HANDLE Thread;
+        NTSTATUS Status;
+        KIRQL OldIrql;
+        PLIST_ENTRY ListEntry;
+
+#if 1 // FIXME: This is a workaround HACK!!
+// Now, restore the actual value of LoadSymbols.
+        LoadSymbols = OrigLoadSymbols;
+#endif
+
+        /* Do not continue loading symbols if we have less than 96MB of RAM */
+        if (MmNumberOfPhysicalPages < (96 * 1024 * 1024 / PAGE_SIZE))
+            LoadSymbols = FALSE;
+
+        /* Continue this phase only if we need to load symbols */
+        if (!LoadSymbols)
+            return LoadSymbols;
+
+        /* 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 LoadSymbols;
+        }
+
+        RosSymInitKernelMode();
 
-        /* Also load them for HAL.DLL. */
-        LdrEntry = CONTAINING_RECORD(PsLoadedModuleList.Flink->Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
-        KdbSymProcessSymbols(LdrEntry);
+        KeAcquireSpinLock(&PsLoadedModuleSpinLock, &OldIrql);
 
-        KdbpSymbolsInitialized = TRUE;
+        for (ListEntry = PsLoadedModuleList.Flink;
+             ListEntry != &PsLoadedModuleList;
+             ListEntry = ListEntry->Flink)
+        {
+            PLDR_DATA_TABLE_ENTRY LdrEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
+            KdbSymProcessSymbols(LdrEntry, TRUE);
+        }
+
+        KeReleaseSpinLock(&PsLoadedModuleSpinLock, OldIrql);
     }
+
+    return LoadSymbols;
 }
 
 /* EOF */