Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

217 lines
5.4 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
ldrreloc.c
Abstract:
This module contains the code to relocate an image when
the preferred base isn't available. This is called by the
boot loader, device driver loader, and system loader.
Author:
Mike O'Leary (mikeol) 03-Feb-1992
Revision History:
--*/
#include "ntrtlp.h"
#if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
#pragma alloc_text(PAGE,LdrRelocateImage)
#pragma alloc_text(PAGE,LdrProcessRelocationBlock)
#endif
ULONG
LdrRelocateImage (
IN PVOID NewBase,
IN PUCHAR LoaderName,
IN ULONG Success,
IN ULONG Conflict,
IN ULONG Invalid
)
/*++
Routine Description:
This routine relocates an image file that was not loaded into memory
at the prefered address.
Arguments:
NewBase - Supplies a pointer to the image base.
LoaderName - Indicates which loader routine is being called from.
Success - Value to return if relocation successful.
Conflict - Value to return if can't relocate.
Invalid - Value to return if relocations are invalid.
Return Value:
Success if image is relocated.
Conflict if image can't be relocated.
Invalid if image contains invalid fixups.
--*/
{
LONG Temp, Diff;
ULONG TotalCountBytes, VA, OldBase, SizeOfBlock;
PUCHAR FixupVA;
USHORT Offset;
PUSHORT NextOffset;
PIMAGE_NT_HEADERS NtHeaders;
PIMAGE_BASE_RELOCATION NextBlock;
RTL_PAGED_CODE();
NtHeaders = RtlImageNtHeader( NewBase );
OldBase = NtHeaders->OptionalHeader.ImageBase;
//
// Locate the relocation section.
//
NextBlock = (PIMAGE_BASE_RELOCATION)RtlImageDirectoryEntryToData(
NewBase, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &TotalCountBytes);
if (!NextBlock || !TotalCountBytes) {
//
// The image does not contain a relocation table, and therefore
// cannot be relocated.
//
#if DBG
DbgPrint("%s: Image can't be relocated, no fixup information.\n", LoaderName);
#endif // DBG
return Conflict;
}
//
// If the image has a relocation table, then apply the specified fixup
// information to the image.
//
while (TotalCountBytes) {
SizeOfBlock = NextBlock->SizeOfBlock;
TotalCountBytes -= SizeOfBlock;
SizeOfBlock -= sizeof(IMAGE_BASE_RELOCATION);
SizeOfBlock /= sizeof(USHORT);
NextOffset = (PUSHORT)((ULONG)NextBlock + sizeof(IMAGE_BASE_RELOCATION));
VA = (ULONG)NewBase + NextBlock->VirtualAddress;
Diff = (LONG)NewBase - (LONG)OldBase;
if ( !(NextBlock = LdrProcessRelocationBlock(VA,SizeOfBlock,NextOffset,Diff)) ) {
#if DBG
DbgPrint("%s: Unknown base relocation type\n", LoaderName);
#endif
return Invalid;
}
}
return Success;
}
PIMAGE_BASE_RELOCATION
LdrProcessRelocationBlock(
IN ULONG VA,
IN ULONG SizeOfBlock,
IN PUSHORT NextOffset,
IN LONG Diff
)
{
PUCHAR FixupVA;
USHORT Offset;
LONG Temp;
RTL_PAGED_CODE();
while (SizeOfBlock--) {
Offset = *NextOffset & (USHORT)0xfff;
FixupVA = (PUCHAR)(VA + Offset);
//
// Apply the fixups.
//
switch ((*NextOffset) >> 12) {
case IMAGE_REL_BASED_HIGHLOW :
//
// HighLow - (32-bits) relocate the high and low half
// of an address.
//
*(LONG UNALIGNED *)FixupVA += Diff;
break;
case IMAGE_REL_BASED_HIGH :
//
// High - (16-bits) relocate the high half of an address.
//
Temp = *(PUSHORT)FixupVA << 16;
Temp += Diff;
*(PUSHORT)FixupVA = (USHORT)(Temp >> 16);
break;
case IMAGE_REL_BASED_HIGHADJ :
//
// Adjust high - (16-bits) relocate the high half of an
// address and adjust for sign extension of low half.
//
Temp = *(PUSHORT)FixupVA << 16;
++NextOffset;
--SizeOfBlock;
Temp += (LONG)(*(PSHORT)NextOffset);
Temp += Diff;
Temp += 0x8000;
*(PUSHORT)FixupVA = (USHORT)(Temp >> 16);
break;
case IMAGE_REL_BASED_LOW :
//
// Low - (16-bit) relocate the low half of an address.
//
Temp = *(PSHORT)FixupVA;
Temp += Diff;
*(PUSHORT)FixupVA = (USHORT)Temp;
break;
case IMAGE_REL_BASED_MIPS_JMPADDR :
//
// JumpAddress - (32-bits) relocate a MIPS jump address.
//
Temp = (*(PULONG)FixupVA & 0x3ffffff) << 2;
Temp += Diff;
*(PULONG)FixupVA = (*(PULONG)FixupVA & ~0x3ffffff) |
((Temp >> 2) & 0x3ffffff);
break;
case IMAGE_REL_BASED_ABSOLUTE :
//
// Absolute - no fixup required.
//
break;
default :
//
// Illegal - illegal relocation type.
//
return (PIMAGE_BASE_RELOCATION)NULL;
}
++NextOffset;
}
return (PIMAGE_BASE_RELOCATION)NextOffset;
}