From 746299a0dafd37bf2679522f89e40d2513b6e64e Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Sun, 10 Sep 2006 08:00:57 +0000 Subject: [PATCH] - Move and slightly modify the relocation code to RTL, change its prototype so that it can be used in future in freeldr, ntdll and in kernel (right now there is code duplication, which is removed from kernel by this commit). svn path=/trunk/; revision=24016 --- reactos/include/ndk/rtlfuncs.h | 12 ++++ reactos/lib/rtl/image.c | 109 ++++++++++++++++++++++++++++++++- reactos/ntoskrnl/ldr/loader.c | 108 ++------------------------------ 3 files changed, 125 insertions(+), 104 deletions(-) diff --git a/reactos/include/ndk/rtlfuncs.h b/reactos/include/ndk/rtlfuncs.h index ec76c604720..b7d3f1e4d21 100644 --- a/reactos/include/ndk/rtlfuncs.h +++ b/reactos/include/ndk/rtlfuncs.h @@ -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 // diff --git a/reactos/lib/rtl/image.c b/reactos/lib/rtl/image.c index 09435070b75..8b87b39672b 100644 --- a/reactos/lib/rtl/image.c +++ b/reactos/lib/rtl/image.c @@ -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 */ diff --git a/reactos/ntoskrnl/ldr/loader.c b/reactos/ntoskrnl/ldr/loader.c index 4e2cc3a9b8b..0c320666754 100644 --- a/reactos/ntoskrnl/ldr/loader.c +++ b/reactos/ntoskrnl/ldr/loader.c @@ -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