implemented sweeping of handle tables
[reactos.git] / reactos / ntoskrnl / kdbg / kdb_symbols.c
index 70d3990..bc37191 100644 (file)
@@ -9,10 +9,7 @@
 
 /* INCLUDES *****************************************************************/
 
-#include <ddk/ntddk.h>
-#include <roscfg.h>
 #include <ntoskrnl.h>
-#include <reactos/rossym.h>
 
 #define NDEBUG
 #include <internal/debug.h>
@@ -26,6 +23,7 @@ typedef struct _IMAGE_SYMBOL_INFO_CACHE {
   PROSSYM_INFO RosSymInfo;
 } IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE;
 
+static BOOLEAN LoadSymbols;
 static LIST_ENTRY SymbolFileListHead;
 static KSPIN_LOCK SymbolFileListLock;
 
@@ -53,10 +51,11 @@ KdbpSymFindUserModule(IN PVOID Address  OPTIONAL,
                       OUT PKDB_MODULE_INFO pInfo)
 {
   PLIST_ENTRY current_entry;
-  PLDR_MODULE current;
+  PLDR_DATA_TABLE_ENTRY current;
   PEPROCESS CurrentProcess;
   PPEB Peb = NULL;
   INT Count = 0;
+  INT Length;
 
   CurrentProcess = PsGetCurrentProcess();
   if (CurrentProcess != NULL)
@@ -64,7 +63,7 @@ KdbpSymFindUserModule(IN PVOID Address  OPTIONAL,
       Peb = CurrentProcess->Peb;
     }
 
-  if (Peb == NULL)
+  if (Peb == NULL || Peb->Ldr == NULL)
     {
       return FALSE;
     }
@@ -74,21 +73,18 @@ KdbpSymFindUserModule(IN PVOID Address  OPTIONAL,
   while (current_entry != &Peb->Ldr->InLoadOrderModuleList &&
          current_entry != NULL)
     {
-      current = CONTAINING_RECORD(current_entry, LDR_MODULE, InLoadOrderModuleList);
-
-      if ((Address != NULL && (Address >= (PVOID)current->BaseAddress &&
-                               Address < (PVOID)((char *)current->BaseAddress + current->ResidentSize))) ||
-          (Name != NULL && _wcsicmp(current->BaseDllName.Buffer, Name) == 0) ||
+      current = CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
+      Length = min(current->BaseDllName.Length / sizeof(WCHAR), 255);
+      if ((Address != NULL && (Address >= (PVOID)current->DllBase &&
+                               Address < (PVOID)((char *)current->DllBase + current->SizeOfImage))) ||
+          (Name != NULL && _wcsnicmp(current->BaseDllName.Buffer, Name, Length) == 0) ||
           (Index >= 0 && Count++ == Index))
         {
-         INT Length = current->BaseDllName.Length;
-         if (Length > 255)
-           Length = 255;
          wcsncpy(pInfo->Name, current->BaseDllName.Buffer, Length);
          pInfo->Name[Length] = L'\0';
-          pInfo->Base = (ULONG_PTR)current->BaseAddress;
-          pInfo->Size = current->ResidentSize;
-          pInfo->RosSymInfo = current->RosSymInfo;
+          pInfo->Base = (ULONG_PTR)current->DllBase;
+          pInfo->Size = current->SizeOfImage;
+          pInfo->RosSymInfo = current->PatchInformation;
           return TRUE;
         }
       current_entry = current_entry->Flink;
@@ -110,27 +106,28 @@ KdbpSymFindModule(IN PVOID Address  OPTIONAL,
                   OUT PKDB_MODULE_INFO pInfo)
 {
   PLIST_ENTRY current_entry;
-  MODULE_TEXT_SECTION* current;
-  extern LIST_ENTRY ModuleTextListHead;
+  PLDR_DATA_TABLE_ENTRY current;
+  extern LIST_ENTRY ModuleListHead;
   INT Count = 0;
+  INT Length;
 
-  current_entry = ModuleTextListHead.Flink;
+  current_entry = ModuleListHead.Flink;
 
-  while (current_entry != &ModuleTextListHead &&
-         current_entry != NULL)
+  while (current_entry != &ModuleListHead)
     {
-      current = CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
+      current = CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
 
-      if ((Address != NULL && (Address >= (PVOID)current->Base &&
-                               Address < (PVOID)(current->Base + current->Length))) ||
-          (Name != NULL && _wcsicmp(current->Name, Name) == 0) ||
+      Length = min(current->BaseDllName.Length / sizeof(WCHAR), 255);
+      if ((Address != NULL && (Address >= (PVOID)current->DllBase &&
+                               Address < (PVOID)((ULONG_PTR)current->DllBase + current->SizeOfImage))) ||
+          (Name != NULL && _wcsnicmp(current->BaseDllName.Buffer, Name, Length) == 0) ||
           (Index >= 0 && Count++ == Index))
         {
-         wcsncpy(pInfo->Name, current->Name, 255);
-         pInfo->Name[255] = L'\0';
-          pInfo->Base = (ULONG_PTR)current->Base;
-          pInfo->Size = current->Length;
-          pInfo->RosSymInfo = current->RosSymInfo;
+         wcsncpy(pInfo->Name, current->BaseDllName.Buffer, Length);
+         pInfo->Name[Length] = L'\0';
+          pInfo->Base = (ULONG_PTR)current->DllBase;
+          pInfo->Size = current->SizeOfImage;
+          pInfo->RosSymInfo = current->PatchInformation;
           return TRUE;
         }
       current_entry = current_entry->Flink;
@@ -344,7 +341,7 @@ KdbpSymAddCachedFile(IN PUNICODE_STRING FileName,
   RtlZeroMemory(CacheEntry, sizeof (IMAGE_SYMBOL_INFO_CACHE));
 
   /* fill entry */
-  RtlpCreateUnicodeString(&CacheEntry->FileName, FileName->Buffer, PagedPool);
+  RtlCreateUnicodeString(&CacheEntry->FileName, FileName->Buffer);
   ASSERT(CacheEntry->FileName.Buffer);
   CacheEntry->RefCount = 1;
   CacheEntry->RosSymInfo = RosSymInfo;
@@ -415,6 +412,12 @@ KdbpSymLoadModuleSymbols(IN PUNICODE_STRING FileName,
   /* 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 != NULL)
@@ -484,12 +487,14 @@ KdbpSymUnloadModuleSymbols(IN PROSSYM_INFO RosSymInfo)
  * \param LdrModule Pointer to the module to load symbols for.
  */
 VOID
-KdbSymLoadUserModuleSymbols(IN PLDR_MODULE LdrModule)
+KdbSymLoadUserModuleSymbols(IN PLDR_DATA_TABLE_ENTRY LdrModule)
 {
   static WCHAR Prefix[] = L"\\??\\";
   UNICODE_STRING KernelName;
   DPRINT("LdrModule %p\n", LdrModule);
 
+  LdrModule->PatchInformation = NULL;
+
   KernelName.MaximumLength = sizeof(Prefix) + LdrModule->FullDllName.Length;
   KernelName.Length = KernelName.MaximumLength - sizeof(WCHAR);
   KernelName.Buffer = ExAllocatePoolWithTag(PagedPool, KernelName.MaximumLength, TAG_KDBS);
@@ -502,9 +507,7 @@ KdbSymLoadUserModuleSymbols(IN PLDR_MODULE LdrModule)
          LdrModule->FullDllName.Length);
   KernelName.Buffer[KernelName.Length / sizeof(WCHAR)] = L'\0';
 
-  LdrModule->RosSymInfo = NULL;
-
-  KdbpSymLoadModuleSymbols(&KernelName, &LdrModule->RosSymInfo);
+  KdbpSymLoadModuleSymbols(&KernelName, (PROSSYM_INFO*)&LdrModule->PatchInformation);
 
   ExFreePool(KernelName.Buffer);
 }
@@ -517,14 +520,14 @@ VOID
 KdbSymFreeProcessSymbols(IN PEPROCESS Process)
 {
   PLIST_ENTRY CurrentEntry;
-  PLDR_MODULE Current;
+  PLDR_DATA_TABLE_ENTRY Current;
   PEPROCESS CurrentProcess;
   PPEB Peb;
 
   CurrentProcess = PsGetCurrentProcess();
   if (CurrentProcess != Process)
   {
-    KeAttachProcess(EPROCESS_TO_KPROCESS(Process));
+    KeAttachProcess(&Process->Pcb);
   }
   Peb = Process->Peb;
   ASSERT(Peb);
@@ -534,9 +537,9 @@ KdbSymFreeProcessSymbols(IN PEPROCESS Process)
   while (CurrentEntry != &Peb->Ldr->InLoadOrderModuleList &&
         CurrentEntry != NULL)
     {
-      Current = CONTAINING_RECORD(CurrentEntry, LDR_MODULE, InLoadOrderModuleList);
+      Current = CONTAINING_RECORD(CurrentEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
 
-      KdbpSymUnloadModuleSymbols(Current->RosSymInfo);
+      KdbpSymUnloadModuleSymbols(Current->PatchInformation);
 
       CurrentEntry = CurrentEntry->Flink;
     }
@@ -549,30 +552,30 @@ KdbSymFreeProcessSymbols(IN PEPROCESS Process)
 /*! \brief Load symbol info for a driver.
  *
  * \param Filename  Filename of the driver.
- * \param Module    Pointer to the driver MODULE_OBJECT.
+ * \param Module    Pointer to the driver LDR_DATA_TABLE_ENTRY.
  */
 VOID
 KdbSymLoadDriverSymbols(IN PUNICODE_STRING Filename,
-                        IN PMODULE_OBJECT Module)
+                        IN PLDR_DATA_TABLE_ENTRY Module)
 {
   /* Load symbols for the image if available */
-  DPRINT("Loading driver %wZ symbols (driver @ %08x)\n", Filename, Module->Base);
+  DPRINT("Loading driver %wZ symbols (driver @ %08x)\n", Filename, Module->DllBase);
 
-  Module->TextSection->RosSymInfo = NULL;
+  Module->PatchInformation = NULL;
 
-  KdbpSymLoadModuleSymbols(Filename, &Module->TextSection->RosSymInfo);
+  KdbpSymLoadModuleSymbols(Filename, (PROSSYM_INFO*)&Module->PatchInformation);
 }
 
 /*! \brief Unloads symbol info for a driver.
  *
- * \param ModuleObject  Pointer to the driver MODULE_OBJECT.
+ * \param ModuleObject  Pointer to the driver LDR_DATA_TABLE_ENTRY.
  */
 VOID
-KdbSymUnloadDriverSymbols(IN PMODULE_OBJECT ModuleObject)
+KdbSymUnloadDriverSymbols(IN PLDR_DATA_TABLE_ENTRY ModuleObject)
 {
   /* Unload symbols for module if available */
-  KdbpSymUnloadModuleSymbols(ModuleObject->TextSection->RosSymInfo);
-  ModuleObject->TextSection->RosSymInfo = NULL;
+  KdbpSymUnloadModuleSymbols(ModuleObject->PatchInformation);
+  ModuleObject->PatchInformation = NULL;
 }
 
 /*! \brief Called when a symbol file is loaded by the loader?
@@ -587,7 +590,7 @@ KdbSymUnloadDriverSymbols(IN PMODULE_OBJECT ModuleObject)
 VOID
 KdbSymProcessBootSymbols(IN PCHAR FileName)
 {
-  PMODULE_OBJECT ModuleObject;
+  PLDR_DATA_TABLE_ENTRY ModuleObject;
   UNICODE_STRING UnicodeString;
   PLOADER_MODULE KeLoaderModules = (PLOADER_MODULE)KeLoaderBlock.ModsAddr;
   ANSI_STRING AnsiString;
@@ -612,6 +615,12 @@ KdbSymProcessBootSymbols(IN PCHAR FileName)
 
   if (ModuleObject != NULL)
   {
+     if (! LoadSymbols)
+     {
+        ModuleObject->PatchInformation = NULL;
+        return;
+     }
+
      for (i = 0; i < KeLoaderBlock.ModsCount; i++)
      {
         if (0 == _stricmp(FileName, (PCHAR)KeLoaderModules[i].String))
@@ -622,16 +631,16 @@ KdbSymProcessBootSymbols(IN PCHAR FileName)
      if (i < KeLoaderBlock.ModsCount)
      {
         KeLoaderModules[i].Reserved = 1;
-        if (ModuleObject->TextSection->RosSymInfo != NULL)
+        if (ModuleObject->PatchInformation != NULL)
         {
-           KdbpSymRemoveCachedFile(ModuleObject->TextSection->RosSymInfo);
+           KdbpSymRemoveCachedFile(ModuleObject->PatchInformation);
         }
 
         if (IsRaw)
         {
            if (! RosSymCreateFromRaw((PVOID) KeLoaderModules[i].ModStart,
                                      KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart,
-                                     &ModuleObject->TextSection->RosSymInfo))
+                                     (PROSSYM_INFO*)&ModuleObject->PatchInformation))
            {
               return;
            }
@@ -640,7 +649,7 @@ KdbSymProcessBootSymbols(IN PCHAR FileName)
         {
            if (! RosSymCreateFromMem((PVOID) KeLoaderModules[i].ModStart,
                                      KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart,
-                                     &ModuleObject->TextSection->RosSymInfo))
+                                     (PROSSYM_INFO*)&ModuleObject->PatchInformation))
            {
               return;
            }
@@ -649,33 +658,84 @@ KdbSymProcessBootSymbols(IN PCHAR FileName)
         /* add file to cache */
         RtlInitAnsiString(&AnsiString, FileName);
        RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
-        KdbpSymAddCachedFile(&UnicodeString, ModuleObject->TextSection->RosSymInfo);
+        KdbpSymAddCachedFile(&UnicodeString, ModuleObject->PatchInformation);
         RtlFreeUnicodeString(&UnicodeString);
 
         DPRINT("Installed symbols: %s@%08x-%08x %p\n",
               FileName,
-              ModuleObject->Base,
-              ModuleObject->Length + ModuleObject->Base,
-              ModuleObject->TextSection->RosSymInfo);
+              ModuleObject->DllBase,
+              ModuleObject->SizeOfImage + (ULONG)ModuleObject->DllBase,
+              ModuleObject->PatchInformation);
      }
   }
 }
 
 /*! \brief Initializes the KDB symbols implementation.
  *
- * \param NtoskrnlTextSection  MODULE_TEXT_SECTION of ntoskrnl.exe
- * \param LdrHalTextSection    MODULE_TEXT_SECTION of hal.sys
+ * \param NtoskrnlModuleObject  LDR_DATA_TABLE_ENTRY of ntoskrnl.exe
+ * \param LdrHalModuleObject    LDR_DATA_TABLE_ENTRY of hal.sys
  */
 VOID
-KdbSymInit(IN PMODULE_TEXT_SECTION NtoskrnlTextSection,
-          IN PMODULE_TEXT_SECTION LdrHalTextSection)
+KdbSymInit(IN PLDR_DATA_TABLE_ENTRY NtoskrnlModuleObject,
+          IN PLDR_DATA_TABLE_ENTRY LdrHalModuleObject)
 {
-  NtoskrnlTextSection->RosSymInfo = NULL;
-  LdrHalTextSection->RosSymInfo = NULL;
+  PCHAR p1, p2;
+  int Found;
+  char YesNo;
+
+  NtoskrnlModuleObject->PatchInformation = NULL;
+  LdrHalModuleObject->PatchInformation = NULL;
 
   InitializeListHead(&SymbolFileListHead);
   KeInitializeSpinLock(&SymbolFileListLock);
 
+#ifdef DBG
+  LoadSymbols = TRUE;
+#else
+  LoadSymbols = FALSE;
+#endif
+
+  /* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS,
+   * /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */
+  p1 = (PCHAR) KeLoaderBlock.CommandLine;
+  while('\0' != *p1 && NULL != (p2 = strchr(p1, '/')))
+    {
+      p2++;
+      Found = 0;
+      if (0 == _strnicmp(p2, "LOADSYMBOLS", 11))
+        {
+          Found = +1;
+          p2 += 11;
+        }
+      else if (0 == _strnicmp(p2, "NOLOADSYMBOLS", 13))
+        {
+          Found = -1;
+          p2 += 13;
+        }
+      if (0 != Found)
+        {
+          while (isspace(*p2))
+            {
+              p2++;
+            }
+          if ('=' == *p2)
+            {
+              p2++;
+              while (isspace(*p2))
+                {
+                  p2++;
+                }
+              YesNo = toupper(*p2);
+              if ('N' == YesNo || 'F' == YesNo || '0' == YesNo)
+                {
+                  Found = -1 * Found;
+                }
+            }
+          LoadSymbols = (0 < Found);
+        }
+      p1 = p2;
+    }
+
   RosSymInitKernelMode();
 }