change a few #ifdefs to allow loading of SYM files for user modules in DBG builds
[reactos.git] / reactos / lib / ntdll / ldr / utils.c
index 1200f1c..c6dcf4a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: utils.c,v 1.92 2004/06/25 19:05:20 ekohl Exp $
+/* $Id: utils.c,v 1.102 2004/12/15 03:00:33 royce Exp $
  * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -68,7 +68,7 @@ static VOID LdrpDetachProcess(BOOL UnloadAll);
 
 /* FUNCTIONS *****************************************************************/
 
-#ifdef KDBG
+#if defined(DBG) || defined(KDBG)
 
 VOID
 LdrpLoadUserModuleSymbols(PLDR_MODULE LdrModule)
@@ -82,7 +82,7 @@ LdrpLoadUserModuleSymbols(PLDR_MODULE LdrModule)
     NULL);
 }
 
-#endif /* DBG */
+#endif /* DBG || KDBG */
 
 static inline LONG LdrpDecrementLoadCount(PLDR_MODULE Module, BOOL Locked)
 {
@@ -252,7 +252,10 @@ LdrpInitializeTlsForProccess(VOID)
                TlsData->StartAddressOfRawData = (PVOID)TlsDirectory->StartAddressOfRawData;
                TlsData->TlsDataSize = TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData;
                TlsData->TlsZeroSize = TlsDirectory->SizeOfZeroFill;
-               TlsData->TlsAddressOfCallBacks = *TlsDirectory->AddressOfCallBacks;
+               if (TlsDirectory->AddressOfCallBacks)
+                 TlsData->TlsAddressOfCallBacks = *TlsDirectory->AddressOfCallBacks;
+               else
+                 TlsData->TlsAddressOfCallBacks = NULL;
                TlsData->Module = Module;
 #if 0
                DbgPrint("TLS directory for %wZ\n", &Module->BaseDllName);
@@ -1224,184 +1227,101 @@ static NTSTATUS
 LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
                       PVOID ImageBase)
 {
-  USHORT NumberOfEntries;
-  PUSHORT pValue16;
-  ULONG RelocationRVA;
-  ULONG Delta32;
-  ULONG Offset;
-  PULONG pValue32;
-  PRELOCATION_DIRECTORY RelocationDir;
-  PRELOCATION_ENTRY RelocationBlock;
-  int i;
   PIMAGE_DATA_DIRECTORY RelocationDDir;
-  ULONG OldProtect;
-  PVOID ProtectBase;
-  ULONG ProtectSize;
-  ULONG OldProtect2;
-  PVOID ProtectBase2;
-  ULONG ProtectSize2;
+  PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
+  ULONG Count, ProtectSize, OldProtect, OldProtect2;
+  PVOID Page, ProtectPage, ProtectPage2;
+  PUSHORT TypeOffset;
+  ULONG_PTR Delta;
   NTSTATUS Status;
-  PIMAGE_SECTION_HEADER Sections;
-  ULONG MaxExtend;
-  ULONG RelocationBlockOffset;
-  ULONG RelocationSectionSize;
 
   if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
     {
       return STATUS_UNSUCCESSFUL;
     }
 
-  Sections =
-    (PIMAGE_SECTION_HEADER)((PVOID)NTHeaders + sizeof(IMAGE_NT_HEADERS));
-  MaxExtend = 0;
-  RelocationSectionSize = 0;
-  for (i = 0; i < NTHeaders->FileHeader.NumberOfSections; i++)
-    {
-      if (!(Sections[i].Characteristics & IMAGE_SECTION_NOLOAD))
-        {
-          ULONG Extend;
-          Extend =
-            (ULONG)(Sections[i].VirtualAddress + Sections[i].Misc.VirtualSize);
-          MaxExtend = max(MaxExtend, Extend);
-        }
-
-      if (!memcmp(Sections[i].Name,".reloc", 6))
-       {
-         RelocationSectionSize = Sections[i].Misc.VirtualSize;
-         DPRINT("Relocation section size: %lx\n", RelocationSectionSize);
-       }
-    }
-
   RelocationDDir =
     &NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
-  RelocationRVA = RelocationDDir->VirtualAddress;
 
-  if (RelocationRVA)
+  if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0)
     {
-      RelocationDir =
-        (PRELOCATION_DIRECTORY)((PCHAR)ImageBase + RelocationRVA);
+      return STATUS_SUCCESS;
+    }
 
-      RelocationBlockOffset = 0;
-      while (RelocationBlockOffset < RelocationSectionSize)
-        {
-          if (RelocationDir->VirtualAddress > MaxExtend)
-            {
-              RelocationRVA += RelocationDir->SizeOfBlock;
-              RelocationDir =
-                (PRELOCATION_DIRECTORY) (ImageBase + RelocationRVA);
-              continue;
-            }
+  ProtectSize = PAGE_SIZE;
+  Delta = (ULONG_PTR)ImageBase - NTHeaders->OptionalHeader.ImageBase;
+  RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase +
+                  RelocationDDir->VirtualAddress);
+  RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase +
+                  RelocationDDir->VirtualAddress + RelocationDDir->Size);
 
-          Delta32 = (ULONG)(ImageBase - NTHeaders->OptionalHeader.ImageBase);
-          RelocationBlock =
-            (PRELOCATION_ENTRY) (RelocationRVA + ImageBase +
-                                 sizeof (RELOCATION_DIRECTORY));
-          NumberOfEntries =
-            RelocationDir->SizeOfBlock - sizeof (RELOCATION_DIRECTORY);
-          NumberOfEntries = NumberOfEntries / sizeof (RELOCATION_ENTRY);
+  while (RelocationDir < RelocationEnd &&
+         RelocationDir->SizeOfBlock > 0)
+    {
+      Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) /
+              sizeof(USHORT);
+      Page = ImageBase + RelocationDir->VirtualAddress;
+      TypeOffset = (PUSHORT)(RelocationDir + 1);
+
+      /* Unprotect the page(s) we're about to relocate. */
+      ProtectPage = Page;
+      Status = NtProtectVirtualMemory(NtCurrentProcess(),
+                                      &ProtectPage,
+                                      &ProtectSize,
+                                      PAGE_READWRITE,
+                                      &OldProtect);
+      if (!NT_SUCCESS(Status))
+        {
+          DPRINT1("Failed to unprotect relocation target.\n");
+          return Status;
+        }
 
-          ProtectBase = ImageBase + RelocationDir->VirtualAddress;
-          ProtectSize = PAGE_SIZE;
+      if (RelocationDir->VirtualAddress + PAGE_SIZE <
+          NTHeaders->OptionalHeader.SizeOfImage)
+        {
+          ProtectPage2 = ProtectPage + PAGE_SIZE;
           Status = NtProtectVirtualMemory(NtCurrentProcess(),
-                                          &ProtectBase,
+                                          &ProtectPage2,
                                           &ProtectSize,
                                           PAGE_READWRITE,
-                                          &OldProtect);
-          if (!NT_SUCCESS(Status))
-            {
-              DPRINT1("Failed to unprotect relocation target.\n");
-              return(Status);
-            }
-
-          if (RelocationDir->VirtualAddress + PAGE_SIZE < MaxExtend)
-            {
-                  ProtectBase2 = ImageBase + RelocationDir->VirtualAddress + PAGE_SIZE;
-                  ProtectSize2 = PAGE_SIZE;
-                  Status = NtProtectVirtualMemory(NtCurrentProcess(),
-                                                  &ProtectBase2,
-                                                  &ProtectSize2,
-                                                  PAGE_READWRITE,
-                                                  &OldProtect2);
-                  if (!NT_SUCCESS(Status))
-                    {
-                      DPRINT1("Failed to unprotect relocation target (2).\n");
-                      NtProtectVirtualMemory(NtCurrentProcess(),
-                                             &ProtectBase,
-                                             &ProtectSize,
-                                             OldProtect,
-                                             &OldProtect);
-                      return(Status);
-                    }
-              }
-          for (i = 0; i < NumberOfEntries; i++)
-            {
-              Offset = (RelocationBlock[i].TypeOffset & 0xfff);
-              Offset += (ULONG)(RelocationDir->VirtualAddress + ImageBase);
-
-              /*
-               * What kind of relocations should we perform
-               * for the current entry?
-               */
-              switch (RelocationBlock[i].TypeOffset >> 12)
-                {
-                case TYPE_RELOC_ABSOLUTE:
-                  break;
-
-                case TYPE_RELOC_HIGH:
-                  pValue16 = (PUSHORT)Offset;
-                  *pValue16 += Delta32 >> 16;
-                  break;
-
-                case TYPE_RELOC_LOW:
-                  pValue16 = (PUSHORT)Offset;
-                  *pValue16 += Delta32 & 0xffff;
-                  break;
-
-                case TYPE_RELOC_HIGHLOW:
-                  pValue32 = (PULONG)Offset;
-                  *pValue32 += Delta32;
-                  break;
-
-                case TYPE_RELOC_HIGHADJ:
-                  /* FIXME: do the highadjust fixup  */
-                  DPRINT("TYPE_RELOC_HIGHADJ fixup not implemented, sorry\n");
-                  return STATUS_UNSUCCESSFUL;
-
-                default:
-                  DPRINT("unexpected fixup type\n");
-                  return STATUS_UNSUCCESSFUL;
-                }
-            }
-
-          Status = NtProtectVirtualMemory(NtCurrentProcess(),
-                                          &ProtectBase,
-                                          &ProtectSize,
-                                          OldProtect,
-                                          &OldProtect);
+                                          &OldProtect2);
           if (!NT_SUCCESS(Status))
             {
-              DPRINT1("Failed to protect relocation target.\n");
-              return(Status);
-            }
-
-          if (RelocationDir->VirtualAddress + PAGE_SIZE < MaxExtend)
-            {
-                  Status = NtProtectVirtualMemory(NtCurrentProcess(),
-                                                  &ProtectBase2,
-                                                  &ProtectSize2,
-                                                  OldProtect2,
-                                                  &OldProtect2);
-                  if (!NT_SUCCESS(Status))
-                    {
-                      DPRINT1("Failed to protect relocation target2.\n");
-                      return(Status);
-                    }
+              DPRINT1("Failed to unprotect relocation target (2).\n");
+              NtProtectVirtualMemory(NtCurrentProcess(),
+                                     &ProtectPage,
+                                     &ProtectSize,
+                                     OldProtect,
+                                     &OldProtect);
+              return Status;
             }
+        }
+      else
+        {
+          ProtectPage2 = NULL;
+        }
 
-          RelocationRVA += RelocationDir->SizeOfBlock;
-          RelocationDir =
-            (PRELOCATION_DIRECTORY) (ImageBase + RelocationRVA);
-          RelocationBlockOffset += RelocationDir->SizeOfBlock;
+      RelocationDir = LdrProcessRelocationBlock(Page,
+                                                Count,
+                                                TypeOffset,
+                                                Delta);
+      if (RelocationDir == NULL)
+        return STATUS_UNSUCCESSFUL;
+
+      /* Restore old page protection. */
+      NtProtectVirtualMemory(NtCurrentProcess(),
+                             &ProtectPage,
+                             &ProtectSize,
+                             OldProtect,
+                             &OldProtect);
+
+      if (ProtectPage2 != NULL)
+        {
+          NtProtectVirtualMemory(NtCurrentProcess(),
+                                 &ProtectPage2,
+                                 &ProtectSize,
+                                 OldProtect2,
+                                 &OldProtect2);
         }
     }
 
@@ -1712,7 +1632,7 @@ LdrFixupImports(IN PWSTR SearchPath OPTIONAL,
    PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptor;
    PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundImportDescriptorCurrent;
    PIMAGE_TLS_DIRECTORY TlsDirectory;
-   ULONG TlsSize;
+   ULONG TlsSize = 0;
    NTSTATUS Status;
    PLDR_MODULE ImportedModule;
    PCHAR ImportedName;
@@ -2165,9 +2085,9 @@ LdrpLoadModule(IN PWSTR SearchPath OPTIONAL,
             DPRINT1("LdrFixupImports failed for %wZ, status=%x\n", &(*Module)->BaseDllName, Status);
             return Status;
           }
-#ifdef KDBG
+#if defined(DBG) || defined(KDBG)
         LdrpLoadUserModuleSymbols(*Module);
-#endif
+#endif /* DBG || KDBG */
         RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
         InsertTailList(&NtCurrentPeb()->Ldr->InInitializationOrderModuleList,
                        &(*Module)->InInitializationOrderModuleList);
@@ -2495,7 +2415,7 @@ LdrpDetachProcess(BOOL UnloadAll)
                ((UnloadAll && Module->LoadCount >= 0) || Module->LoadCount == 0))
              {
                /* remove the module entry from the list */
-               RemoveEntryList (&Module->InLoadOrderModuleList)
+               RemoveEntryList (&Module->InLoadOrderModuleList);
                RemoveEntryList (&Module->InInitializationOrderModuleList);
 
                NtUnmapViewOfSection (NtCurrentProcess (), Module->BaseAddress);
@@ -2709,7 +2629,7 @@ LdrQueryProcessModuleInformation(IN PMODULE_INFORMATION ModuleInformation OPTION
   PLIST_ENTRY ModuleListHead;
   PLIST_ENTRY Entry;
   PLDR_MODULE Module;
-  PMODULE_ENTRY ModulePtr = NULL;
+  PDEBUG_MODULE_INFORMATION ModulePtr = NULL;
   NTSTATUS Status = STATUS_SUCCESS;
   ULONG UsedSize = sizeof(ULONG);
   ANSI_STRING AnsiString;
@@ -2746,31 +2666,30 @@ LdrQueryProcessModuleInformation(IN PMODULE_INFORMATION ModuleInformation OPTION
         }
       else if (ModuleInformation != NULL)
         {
-          ModulePtr->Unknown0 = 0;      // FIXME: ??
-          ModulePtr->Unknown1 = 0;      // FIXME: ??
-          ModulePtr->BaseAddress = Module->BaseAddress;
-          ModulePtr->SizeOfImage = Module->SizeOfImage;
+          ModulePtr->Reserved[0] = ModulePtr->Reserved[1] = 0;      // FIXME: ??
+          ModulePtr->Base = Module->BaseAddress;
+          ModulePtr->Size = Module->SizeOfImage;
           ModulePtr->Flags = Module->Flags;
-          ModulePtr->Unknown2 = 0;      // FIXME: load order index ??
-          ModulePtr->Unknown3 = 0;      // FIXME: ??
+          ModulePtr->Index = 0;      // FIXME: index ??
+          ModulePtr->Unknown = 0;      // FIXME: ??
           ModulePtr->LoadCount = Module->LoadCount;
 
           AnsiString.Length = 0;
           AnsiString.MaximumLength = 256;
-          AnsiString.Buffer = ModulePtr->ModuleName;
+          AnsiString.Buffer = ModulePtr->ImageName;
           RtlUnicodeStringToAnsiString(&AnsiString,
                                        &Module->FullDllName,
                                        FALSE);
-          p = strrchr(ModulePtr->ModuleName, '\\');
+          p = strrchr(ModulePtr->ImageName, '\\');
           if (p != NULL)
-            ModulePtr->PathLength = p - ModulePtr->ModuleName + 1;
+            ModulePtr->ModuleNameOffset = p - ModulePtr->ImageName + 1;
           else
-            ModulePtr->PathLength = 0;
+            ModulePtr->ModuleNameOffset = 0;
 
           ModulePtr++;
           ModuleInformation->ModuleCount++;
         }
-      UsedSize += sizeof(MODULE_ENTRY);
+      UsedSize += sizeof(DEBUG_MODULE_INFORMATION);
 
       Entry = Entry->Flink;
     }
@@ -3096,4 +3015,55 @@ LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey,
   return Status;
 }
 
+
+PIMAGE_BASE_RELOCATION STDCALL
+LdrProcessRelocationBlock(IN PVOID Address,
+                         IN USHORT Count,
+                         IN PUSHORT TypeOffset,
+                         IN ULONG_PTR Delta)
+{
+  SHORT Offset;
+  USHORT Type;
+  USHORT i;
+  PUSHORT ShortPtr;
+  PULONG LongPtr;
+
+  for (i = 0; i < Count; i++)
+    {
+      Offset = *TypeOffset & 0xFFF;
+      Type = *TypeOffset >> 12;
+
+      switch (Type)
+        {
+          case IMAGE_REL_BASED_ABSOLUTE:
+            break;
+
+          case IMAGE_REL_BASED_HIGH:
+            ShortPtr = (PUSHORT)(Address + Offset);
+            *ShortPtr += HIWORD(Delta);
+            break;
+
+          case IMAGE_REL_BASED_LOW:
+            ShortPtr = (PUSHORT)(Address + Offset);
+            *ShortPtr += LOWORD(Delta);
+            break;
+
+          case IMAGE_REL_BASED_HIGHLOW:
+            LongPtr = (PULONG)(Address + Offset);
+            *LongPtr += Delta;
+            break;
+
+          case IMAGE_REL_BASED_HIGHADJ:
+          case IMAGE_REL_BASED_MIPS_JMPADDR:
+          default:
+            DPRINT1("Unknown/unsupported fixup type %hu.\n", Type);
+            return NULL;
+        }
+
+      TypeOffset++;
+    }
+
+  return (PIMAGE_BASE_RELOCATION)TypeOffset;
+}
+
 /* EOF */