Implement and use LdrProcessRelocationBlock().

svn path=/trunk/; revision=9905
This commit is contained in:
Eric Kohl 2004-06-27 12:21:14 +00:00
parent 3bd4ef3363
commit fbe9f7f64f
4 changed files with 84 additions and 44 deletions

View file

@ -126,6 +126,12 @@ LdrLoadDll(IN PWSTR SearchPath OPTIONAL,
IN PUNICODE_STRING Name, IN PUNICODE_STRING Name,
OUT PVOID *BaseAddress OPTIONAL); OUT PVOID *BaseAddress OPTIONAL);
PIMAGE_BASE_RELOCATION STDCALL
LdrProcessRelocationBlock(IN PVOID Address,
IN USHORT Count,
IN PUSHORT TypeOffset,
IN ULONG_PTR Delta);
NTSTATUS STDCALL NTSTATUS STDCALL
LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey, LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey,
IN PCWSTR ValueName, IN PCWSTR ValueName,

View file

@ -1,4 +1,4 @@
; $Id: ntdll.def,v 1.121 2004/06/13 10:35:52 navaraf Exp $ ; $Id: ntdll.def,v 1.122 2004/06/27 12:21:14 ekohl Exp $
; ;
; ReactOS Operating System ; ReactOS Operating System
; ;
@ -51,7 +51,7 @@ LdrGetDllHandle@16
LdrGetProcedureAddress@16 LdrGetProcedureAddress@16
LdrInitializeThunk@16 LdrInitializeThunk@16
LdrLoadDll@16 LdrLoadDll@16
;LdrProcessRelocationBlock@16 LdrProcessRelocationBlock@16
LdrQueryImageFileExecutionOptions@24 LdrQueryImageFileExecutionOptions@24
LdrQueryProcessModuleInformation@12 LdrQueryProcessModuleInformation@12
LdrShutdownProcess@0 LdrShutdownProcess@0

View file

@ -1,4 +1,4 @@
; $Id: ntdll.edf,v 1.111 2004/06/13 10:35:52 navaraf Exp $ ; $Id: ntdll.edf,v 1.112 2004/06/27 12:21:14 ekohl Exp $
; ;
; ReactOS Operating System ; ReactOS Operating System
; ;
@ -51,7 +51,7 @@ LdrGetDllHandle=LdrGetDllHandle@16
LdrGetProcedureAddress=LdrGetProcedureAddress@16 LdrGetProcedureAddress=LdrGetProcedureAddress@16
LdrInitializeThunk=LdrInitializeThunk@16 LdrInitializeThunk=LdrInitializeThunk@16
LdrLoadDll=LdrLoadDll@16 LdrLoadDll=LdrLoadDll@16
;LdrProcessRelocationBlock LdrProcessRelocationBlock=LdrProcessRelocationBlock@16
LdrQueryImageFileExecutionOptions=LdrQueryImageFileExecutionOptions@24 LdrQueryImageFileExecutionOptions=LdrQueryImageFileExecutionOptions@24
LdrQueryProcessModuleInformation=LdrQueryProcessModuleInformation@12 LdrQueryProcessModuleInformation=LdrQueryProcessModuleInformation@12
LdrShutdownProcess=LdrShutdownProcess@0 LdrShutdownProcess=LdrShutdownProcess@0

View file

@ -1,4 +1,4 @@
/* $Id: utils.c,v 1.95 2004/06/26 15:11:14 navaraf Exp $ /* $Id: utils.c,v 1.96 2004/06/27 12:20:33 ekohl Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -1226,10 +1226,10 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
{ {
PIMAGE_DATA_DIRECTORY RelocationDDir; PIMAGE_DATA_DIRECTORY RelocationDDir;
PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd; PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
ULONG Count, ProtectSize, OldProtect, OldProtect2, i; ULONG Count, ProtectSize, OldProtect, OldProtect2;
PVOID Page, ProtectPage, ProtectPage2; PVOID Page, ProtectPage, ProtectPage2;
PWORD TypeOffset; PUSHORT TypeOffset;
ULONG Delta = (ULONG_PTR)ImageBase - NTHeaders->OptionalHeader.ImageBase; ULONG_PTR Delta;
NTSTATUS Status; NTSTATUS Status;
if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
@ -1244,19 +1244,21 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
{ {
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
ProtectSize = PAGE_SIZE; ProtectSize = PAGE_SIZE;
RelocationDir = (IMAGE_BASE_RELOCATION*)((ULONG_PTR)ImageBase + Delta = (ULONG_PTR)ImageBase - NTHeaders->OptionalHeader.ImageBase;
RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase +
RelocationDDir->VirtualAddress); RelocationDDir->VirtualAddress);
RelocationEnd = (IMAGE_BASE_RELOCATION*)((ULONG_PTR)ImageBase + RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase +
RelocationDDir->VirtualAddress + RelocationDDir->Size); RelocationDDir->VirtualAddress + RelocationDDir->Size);
while (RelocationDir < RelocationEnd && while (RelocationDir < RelocationEnd &&
RelocationDir->SizeOfBlock > 0) RelocationDir->SizeOfBlock > 0)
{ {
Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) /
sizeof(WORD); sizeof(USHORT);
Page = ImageBase + RelocationDir->VirtualAddress; Page = ImageBase + RelocationDir->VirtualAddress;
TypeOffset = (PWORD)(RelocationDir + 1); TypeOffset = (PUSHORT)(RelocationDir + 1);
/* Unprotect the page(s) we're about to relocate. */ /* Unprotect the page(s) we're about to relocate. */
ProtectPage = Page; ProtectPage = Page;
@ -1268,7 +1270,7 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Failed to unprotect relocation target.\n"); DPRINT1("Failed to unprotect relocation target.\n");
return(Status); return Status;
} }
if (RelocationDir->VirtualAddress + PAGE_SIZE < if (RelocationDir->VirtualAddress + PAGE_SIZE <
@ -1288,36 +1290,21 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
&ProtectSize, &ProtectSize,
OldProtect, OldProtect,
&OldProtect); &OldProtect);
return(Status); return Status;
} }
} }
else
/* Patch the page. */
for (i = 0; i < Count; i++)
{ {
SHORT Offset = TypeOffset[i] & 0xFFF; ProtectPage2 = NULL;
USHORT Type = TypeOffset[i] >> 12;
switch (Type)
{
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGH:
*(PUSHORT)(Page + Offset) += HIWORD(Delta);
break;
case IMAGE_REL_BASED_LOW:
*(PUSHORT)(Page + Offset) += LOWORD(Delta);
break;
case IMAGE_REL_BASED_HIGHLOW:
*(PULONG)(Page + Offset) += Delta;
break;
case IMAGE_REL_BASED_HIGHADJ:
default:
DPRINT("Unknown/unsupported fixup type %d.\n", type);
return STATUS_UNSUCCESSFUL;
}
} }
RelocationDir = LdrProcessRelocationBlock(Page,
Count,
TypeOffset,
Delta);
if (RelocationDir == NULL)
return STATUS_UNSUCCESSFUL;
/* Restore old page protection. */ /* Restore old page protection. */
NtProtectVirtualMemory(NtCurrentProcess(), NtProtectVirtualMemory(NtCurrentProcess(),
&ProtectPage, &ProtectPage,
@ -1325,8 +1312,7 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
OldProtect, OldProtect,
&OldProtect); &OldProtect);
if (RelocationDir->VirtualAddress + PAGE_SIZE < if (ProtectPage2 != NULL)
NTHeaders->OptionalHeader.SizeOfImage)
{ {
NtProtectVirtualMemory(NtCurrentProcess(), NtProtectVirtualMemory(NtCurrentProcess(),
&ProtectPage2, &ProtectPage2,
@ -1334,9 +1320,6 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
OldProtect2, OldProtect2,
&OldProtect2); &OldProtect2);
} }
RelocationDir = (IMAGE_BASE_RELOCATION*)((ULONG_PTR)RelocationDir +
RelocationDir->SizeOfBlock);
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -3030,4 +3013,55 @@ LdrQueryImageFileExecutionOptions (IN PUNICODE_STRING SubKey,
return Status; return Status;
} }
PIMAGE_BASE_RELOCATION STDCALL
LdrProcessRelocationBlock(IN PVOID Address,
IN USHORT Count,
IN PUSHORT TypeOffset,
IN ULONG_PTR Delta)
{
SHORT Offset;
USHORT Type;
USHORT i;
PUSHORT ShortPtr;
PULONG LongPtr;
for (i = 0; i < Count; i++)
{
Offset = *TypeOffset & 0xFFF;
Type = *TypeOffset >> 12;
switch (Type)
{
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGH:
ShortPtr = (PUSHORT)(Address + Offset);
*ShortPtr += HIWORD(Delta);
break;
case IMAGE_REL_BASED_LOW:
ShortPtr = (PUSHORT)(Address + Offset);
*ShortPtr += LOWORD(Delta);
break;
case IMAGE_REL_BASED_HIGHLOW:
LongPtr = (PULONG)(Address + Offset);
*LongPtr += Delta;
break;
case IMAGE_REL_BASED_HIGHADJ:
case IMAGE_REL_BASED_MIPS_JMPADDR:
default:
DPRINT1("Unknown/unsupported fixup type %hu.\n", Type);
return NULL;
}
TypeOffset++;
}
return (PIMAGE_BASE_RELOCATION)TypeOffset;
}
/* EOF */ /* EOF */