mirror of
https://github.com/reactos/reactos.git
synced 2025-05-18 00:31:27 +00:00
- 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:
parent
0fbf1539ac
commit
746299a0da
3 changed files with 125 additions and 104 deletions
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue