- 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
This commit is contained in:
Aleksey Bragin 2006-09-10 08:00:57 +00:00
parent 0fbf1539ac
commit 746299a0da
3 changed files with 125 additions and 104 deletions

View 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
//

View 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 */

View 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