Reapply fixed half of 24020 (relocation update in rtl). Tested on vmware and real hardware.

svn path=/trunk/; revision=24112
This commit is contained in:
Aleksey Bragin 2006-09-14 16:37:05 +00:00
parent 63ae604355
commit efcc4447c1

View file

@ -3,8 +3,10 @@
* FILE: lib/rtl/image.c
* PURPOSE: Image handling functions
* Relocate functions were previously located in
* ntoskrnl/ldr/loader.c
* PROGRAMMER: Eric Kohl + original authors from loader.c file
* ntoskrnl/ldr/loader.c and
* dll/ntdll/ldr/utils.c files
* PROGRAMMER: Eric Kohl + original authors from loader.c and utils.c file
* Aleksey Bragin
*/
/* INCLUDES *****************************************************************/
@ -149,6 +151,70 @@ RtlImageRvaToVa (
(ULONG_PTR)Section->VirtualAddress);
}
PIMAGE_BASE_RELOCATION
LdrProcessRelocationBlockLongLong(
IN ULONG_PTR Address,
IN ULONG Count,
IN PUSHORT TypeOffset,
IN LONGLONG Delta
)
{
SHORT Offset;
USHORT Type;
USHORT i;
PUSHORT ShortPtr;
PULONG LongPtr;
for (i = 0; i < Count; i++)
{
Offset = *TypeOffset & 0xFFF;
Type = *TypeOffset >> 12;
ShortPtr = (PUSHORT)(RVA(Address, Offset));
/*
* 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.
* Fix for it disabled, since it was only in ntoskrnl and not in ntdll
*/
/*
if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
(ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
{*/
switch (Type)
{
/* case IMAGE_REL_BASED_SECTION : */
/* case IMAGE_REL_BASED_REL32 : */
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGH:
*ShortPtr = HIWORD(MAKELONG(0, *ShortPtr) + (LONG)Delta);
break;
case IMAGE_REL_BASED_LOW:
*ShortPtr += LOWORD(Delta);
break;
case IMAGE_REL_BASED_HIGHLOW:
LongPtr = (PULONG)RVA(Address, Offset);
*LongPtr += (ULONG)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 (PIMAGE_BASE_RELOCATION)NULL;
}
TypeOffset++;
}
return (PIMAGE_BASE_RELOCATION)TypeOffset;
}
ULONG
NTAPI
LdrRelocateImageWithBias(
@ -163,14 +229,10 @@ LdrRelocateImageWithBias(
PIMAGE_NT_HEADERS NtHeaders;
PIMAGE_DATA_DIRECTORY RelocationDDir;
PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
ULONG Count, i;
PVOID Address;//, MaxAddress;
ULONG Count;
ULONG_PTR Address;
PUSHORT TypeOffset;
ULONG_PTR Delta;
SHORT Offset;
USHORT Type;
PUSHORT ShortPtr;
PULONG LongPtr;
LONGLONG Delta;
NtHeaders = RtlImageNtHeader(BaseAddress);
@ -192,64 +254,24 @@ LdrRelocateImageWithBias(
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);
Address = (ULONG_PTR)RVA(BaseAddress, RelocationDir->VirtualAddress);
TypeOffset = (PUSHORT)(RelocationDir + 1);
for (i = 0; i < Count; i++)
RelocationDir = LdrProcessRelocationBlockLongLong(Address,
Count,
TypeOffset,
Delta);
if (RelocationDir == NULL)
{
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++;
DPRINT1("Error during call to LdrProcessRelocationBlockLongLong()!\n");
return Invalid;
}
RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDir->SizeOfBlock);
}
return Success;