- Move and slightly modify the relocation code to RTL, change its prototype so that...
authorAleksey Bragin <aleksey@reactos.org>
Sun, 10 Sep 2006 08:00:57 +0000 (08:00 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Sun, 10 Sep 2006 08:00:57 +0000 (08:00 +0000)
svn path=/trunk/; revision=24016

reactos/include/ndk/rtlfuncs.h
reactos/lib/rtl/image.c
reactos/ntoskrnl/ldr/loader.c

index ec76c60..b7d3f1e 100644 (file)
@@ -2593,6 +2593,18 @@ RtlImageRvaToSection(
     ULONG Rva
 );
 
+NTSYSAPI
+ULONG
+NTAPI
+LdrRelocateImageWithBias(
+    IN PVOID NewAddress,
+    IN LONGLONG AdditionalBias,
+    IN PUCHAR LoaderName,
+    IN ULONG Success,
+    IN ULONG Conflict,
+    IN ULONG Invalid
+);
+
 //
 // Activation Context Functions
 //
index 0943507..8b87b39 100644 (file)
@@ -2,7 +2,9 @@
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/rtl/image.c
  * PURPOSE:         Image handling functions
- * PROGRAMMER:      Eric Kohl
+ *                  Relocate functions were previously located in
+ *                  ntoskrnl/ldr/loader.c
+ * PROGRAMMER:      Eric Kohl + original authors from loader.c file
  */
 
 /* INCLUDES *****************************************************************/
@@ -147,4 +149,109 @@ RtlImageRvaToVa (
                       (ULONG_PTR)Section->VirtualAddress);
 }
 
+ULONG
+NTAPI
+LdrRelocateImageWithBias(
+    IN PVOID BaseAddress,
+    IN LONGLONG AdditionalBias,
+    IN PUCHAR LoaderName,
+    IN ULONG Success,
+    IN ULONG Conflict,
+    IN ULONG Invalid
+    )
+{
+    PIMAGE_NT_HEADERS NtHeaders;
+    PIMAGE_DATA_DIRECTORY RelocationDDir;
+    PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
+    ULONG Count, i;
+    PVOID Address;//, MaxAddress;
+    PUSHORT TypeOffset;
+    ULONG_PTR Delta;
+    SHORT Offset;
+    USHORT Type;
+    PUSHORT ShortPtr;
+    PULONG LongPtr;
+
+    NtHeaders = RtlImageNtHeader(BaseAddress);
+
+    if (NtHeaders == NULL)
+        return Invalid;
+
+    if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
+    {
+        return Conflict;
+    }
+
+    RelocationDDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+
+    if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0)
+    {
+        return Success;
+    }
+
+    Delta = (ULONG_PTR)BaseAddress - NtHeaders->OptionalHeader.ImageBase + AdditionalBias;
+    RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)BaseAddress + RelocationDDir->VirtualAddress);
+    RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDDir->Size);
+    //MaxAddress = RVA(BaseAddress, DriverSize);
+
+    while (RelocationDir < RelocationEnd &&
+        RelocationDir->SizeOfBlock > 0)
+    {
+        Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
+        Address = RVA(BaseAddress, RelocationDir->VirtualAddress);
+        TypeOffset = (PUSHORT)(RelocationDir + 1);
+
+        for (i = 0; i < Count; i++)
+        {
+            Offset = *TypeOffset & 0xFFF;
+            Type = *TypeOffset >> 12;
+            ShortPtr = (PUSHORT)(RVA(Address, Offset));
+
+            /* Don't relocate after the end of the loaded driver */
+            /*if ((PVOID)ShortPtr >= MaxAddress)
+            {
+                break;
+            }*/
+
+            /*
+            * Don't relocate within the relocation section itself.
+            * GCC/LD generates sometimes relocation records for the relocation section.
+            * This is a bug in GCC/LD.
+            */
+            if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
+                (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
+            {
+                switch (Type)
+                {
+                case IMAGE_REL_BASED_ABSOLUTE:
+                    break;
+
+                case IMAGE_REL_BASED_HIGH:
+                    *ShortPtr += HIWORD(Delta);
+                    break;
+
+                case IMAGE_REL_BASED_LOW:
+                    *ShortPtr += LOWORD(Delta);
+                    break;
+
+                case IMAGE_REL_BASED_HIGHLOW:
+                    LongPtr = (PULONG)ShortPtr;
+                    *LongPtr += Delta;
+                    break;
+
+                case IMAGE_REL_BASED_HIGHADJ:
+                case IMAGE_REL_BASED_MIPS_JMPADDR:
+                default:
+                    DPRINT1("Unknown/unsupported fixup type %hu.\n", Type);
+                    DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, *TypeOffset);
+                    return Invalid;
+                }
+            }
+            TypeOffset++;
+        }
+        RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDir->SizeOfBlock);
+    }
+
+    return Success;
+}
 /* EOF */
index 4e2cc3a..0c32066 100644 (file)
@@ -84,11 +84,6 @@ LdrPEGetExportByName (
 static PVOID
 LdrPEFixupForward ( PCHAR ForwardName );
 
-static NTSTATUS
-LdrPEPerformRelocations (
-    PVOID DriverBase,
-    ULONG DriverSize );
-
 static NTSTATUS
 LdrPEFixupImports ( PLDR_DATA_TABLE_ENTRY Module );
 
@@ -782,7 +777,8 @@ LdrPEProcessModule(
     }
 
     /*  Perform relocation fixups  */
-    Status = LdrPEPerformRelocations(DriverBase, DriverSize);
+    Status = LdrRelocateImageWithBias(DriverBase, 0, "", STATUS_SUCCESS,
+        STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
     if (!NT_SUCCESS(Status))
     {
         //   MmFreeSection(DriverBase);
@@ -1009,7 +1005,9 @@ LdrSafePEProcessModule (
         }
 
         /*  Perform relocation fixups  */
-        Status = LdrPEPerformRelocations(DriverBase, *DriverSize);
+        Status = LdrRelocateImageWithBias(DriverBase, 0, "", STATUS_SUCCESS,
+            STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
+
         if (!NT_SUCCESS(Status))
         {
             return NULL;
@@ -1108,102 +1106,6 @@ LdrPEFixupForward ( PCHAR ForwardName )
     return LdrPEGetExportByName(ModuleObject->DllBase, (PUCHAR)(p+1), 0xffff);
 }
 
-static NTSTATUS
-LdrPEPerformRelocations (
-    PVOID DriverBase,
-    ULONG DriverSize)
-{
-    PIMAGE_NT_HEADERS NtHeaders;
-    PIMAGE_DATA_DIRECTORY RelocationDDir;
-    PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
-    ULONG Count, i;
-    PVOID Address, MaxAddress;
-    PUSHORT TypeOffset;
-    ULONG_PTR Delta;
-    SHORT Offset;
-    USHORT Type;
-    PUSHORT ShortPtr;
-    PULONG LongPtr;
-
-    NtHeaders = RtlImageNtHeader(DriverBase);
-
-    if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
-    {
-        return STATUS_UNSUCCESSFUL;
-    }
-
-    RelocationDDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
-
-    if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0)
-    {
-        return STATUS_SUCCESS;
-    }
-
-    Delta = (ULONG_PTR)DriverBase - NtHeaders->OptionalHeader.ImageBase;
-    RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)DriverBase + RelocationDDir->VirtualAddress);
-    RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDDir->Size);
-    MaxAddress = RVA(DriverBase, DriverSize);
-
-    while (RelocationDir < RelocationEnd &&
-        RelocationDir->SizeOfBlock > 0)
-    {
-        Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
-        Address = RVA(DriverBase, RelocationDir->VirtualAddress);
-        TypeOffset = (PUSHORT)(RelocationDir + 1);
-
-        for (i = 0; i < Count; i++)
-        {
-            Offset = *TypeOffset & 0xFFF;
-            Type = *TypeOffset >> 12;
-            ShortPtr = (PUSHORT)(RVA(Address, Offset));
-
-            /* Don't relocate after the end of the loaded driver */
-            if ((PVOID)ShortPtr >= MaxAddress)
-            {
-                break;
-            }
-
-            /*
-            * Don't relocate within the relocation section itself.
-            * GCC/LD generates sometimes relocation records for the relocation section.
-            * This is a bug in GCC/LD.
-            */
-            if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
-                (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
-            {
-                switch (Type)
-                {
-                case IMAGE_REL_BASED_ABSOLUTE:
-                    break;
-
-                case IMAGE_REL_BASED_HIGH:
-                    *ShortPtr += HIWORD(Delta);
-                    break;
-
-                case IMAGE_REL_BASED_LOW:
-                    *ShortPtr += LOWORD(Delta);
-                    break;
-
-                case IMAGE_REL_BASED_HIGHLOW:
-                    LongPtr = (PULONG)ShortPtr;
-                    *LongPtr += Delta;
-                    break;
-
-                case IMAGE_REL_BASED_HIGHADJ:
-                case IMAGE_REL_BASED_MIPS_JMPADDR:
-                default:
-                    DPRINT1("Unknown/unsupported fixup type %hu.\n", Type);
-                    DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address, i, Count, *TypeOffset);
-                    return STATUS_UNSUCCESSFUL;
-                }
-            }
-            TypeOffset++;
-        }
-        RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDir->SizeOfBlock);
-    }
-
-    return STATUS_SUCCESS;
-}
 #ifndef PATH_MAX
 #define PATH_MAX 260
 #endif