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