mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 01:55:39 +00:00
- Rewritten relocation code to not make invalid assumptions (".reloc" section name) and to not unprotect second page (not needed really).
svn path=/trunk/; revision=9884
This commit is contained in:
parent
e4c1673f80
commit
399da20296
1 changed files with 68 additions and 167 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: utils.c,v 1.93 2004/06/26 11:23:32 ekohl Exp $
|
/* $Id: utils.c,v 1.94 2004/06/26 14:37:05 navaraf Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -1224,87 +1224,44 @@ static NTSTATUS
|
||||||
LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
|
LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
|
||||||
PVOID ImageBase)
|
PVOID ImageBase)
|
||||||
{
|
{
|
||||||
USHORT NumberOfEntries;
|
|
||||||
PUSHORT pValue16;
|
|
||||||
ULONG RelocationRVA;
|
|
||||||
ULONG Delta32;
|
|
||||||
ULONG Offset;
|
|
||||||
PULONG pValue32;
|
|
||||||
PRELOCATION_DIRECTORY RelocationDir;
|
|
||||||
PRELOCATION_ENTRY RelocationBlock;
|
|
||||||
int i;
|
|
||||||
PIMAGE_DATA_DIRECTORY RelocationDDir;
|
PIMAGE_DATA_DIRECTORY RelocationDDir;
|
||||||
ULONG OldProtect;
|
PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
|
||||||
PVOID ProtectBase;
|
ULONG Count, ProtectSize, OldProtect, i;
|
||||||
ULONG ProtectSize;
|
PVOID Page, ProtectPage;
|
||||||
ULONG OldProtect2;
|
PWORD TypeOffset;
|
||||||
PVOID ProtectBase2;
|
ULONG Delta = (ULONG_PTR)ImageBase - NTHeaders->OptionalHeader.ImageBase;
|
||||||
ULONG ProtectSize2;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PIMAGE_SECTION_HEADER Sections;
|
|
||||||
ULONG MaxExtend;
|
|
||||||
ULONG RelocationBlockOffset;
|
|
||||||
ULONG RelocationSectionSize;
|
|
||||||
|
|
||||||
if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
|
if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
|
||||||
{
|
{
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sections =
|
|
||||||
(PIMAGE_SECTION_HEADER)((PVOID)NTHeaders + sizeof(IMAGE_NT_HEADERS));
|
|
||||||
MaxExtend = 0;
|
|
||||||
RelocationSectionSize = 0;
|
|
||||||
for (i = 0; i < NTHeaders->FileHeader.NumberOfSections; i++)
|
|
||||||
{
|
|
||||||
if (!(Sections[i].Characteristics & IMAGE_SECTION_NOLOAD))
|
|
||||||
{
|
|
||||||
ULONG Extend;
|
|
||||||
Extend =
|
|
||||||
(ULONG)(Sections[i].VirtualAddress + Sections[i].Misc.VirtualSize);
|
|
||||||
MaxExtend = max(MaxExtend, Extend);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!memcmp(Sections[i].Name,".reloc", 6))
|
|
||||||
{
|
|
||||||
RelocationSectionSize = Sections[i].Misc.VirtualSize;
|
|
||||||
DPRINT("Relocation section size: %lx\n", RelocationSectionSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RelocationDDir =
|
RelocationDDir =
|
||||||
&NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
&NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
||||||
RelocationRVA = RelocationDDir->VirtualAddress;
|
|
||||||
|
|
||||||
if (RelocationRVA)
|
if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0)
|
||||||
{
|
{
|
||||||
RelocationDir =
|
return STATUS_SUCCESS;
|
||||||
(PRELOCATION_DIRECTORY)((PCHAR)ImageBase + RelocationRVA);
|
|
||||||
|
|
||||||
RelocationBlockOffset = 0;
|
|
||||||
while (RelocationBlockOffset < RelocationSectionSize)
|
|
||||||
{
|
|
||||||
if (RelocationDir->VirtualAddress > MaxExtend)
|
|
||||||
{
|
|
||||||
RelocationRVA += RelocationDir->SizeOfBlock;
|
|
||||||
RelocationDir =
|
|
||||||
(PRELOCATION_DIRECTORY) (ImageBase + RelocationRVA);
|
|
||||||
RelocationBlockOffset += RelocationDir->SizeOfBlock;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Delta32 = (ULONG)(ImageBase - NTHeaders->OptionalHeader.ImageBase);
|
|
||||||
RelocationBlock =
|
|
||||||
(PRELOCATION_ENTRY) (RelocationRVA + ImageBase +
|
|
||||||
sizeof (RELOCATION_DIRECTORY));
|
|
||||||
NumberOfEntries =
|
|
||||||
RelocationDir->SizeOfBlock - sizeof (RELOCATION_DIRECTORY);
|
|
||||||
NumberOfEntries = NumberOfEntries / sizeof (RELOCATION_ENTRY);
|
|
||||||
|
|
||||||
ProtectBase = ImageBase + RelocationDir->VirtualAddress;
|
|
||||||
ProtectSize = PAGE_SIZE;
|
ProtectSize = PAGE_SIZE;
|
||||||
|
RelocationDir = (IMAGE_BASE_RELOCATION*)((ULONG_PTR)ImageBase +
|
||||||
|
RelocationDDir->VirtualAddress);
|
||||||
|
RelocationEnd = (IMAGE_BASE_RELOCATION*)((ULONG_PTR)ImageBase +
|
||||||
|
RelocationDDir->VirtualAddress + RelocationDDir->Size);
|
||||||
|
while (RelocationDir < RelocationEnd &&
|
||||||
|
RelocationDir->SizeOfBlock > 0)
|
||||||
|
{
|
||||||
|
Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) /
|
||||||
|
sizeof(WORD);
|
||||||
|
Page = ImageBase + RelocationDir->VirtualAddress;
|
||||||
|
TypeOffset = (PWORD)(RelocationDir + 1);
|
||||||
|
|
||||||
|
/* Unprotect the page we're about to relocate. */
|
||||||
|
ProtectPage = Page;
|
||||||
Status = NtProtectVirtualMemory(NtCurrentProcess(),
|
Status = NtProtectVirtualMemory(NtCurrentProcess(),
|
||||||
&ProtectBase,
|
&ProtectPage,
|
||||||
&ProtectSize,
|
&ProtectSize,
|
||||||
PAGE_READWRITE,
|
PAGE_READWRITE,
|
||||||
&OldProtect);
|
&OldProtect);
|
||||||
|
@ -1314,97 +1271,41 @@ LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RelocationDir->VirtualAddress + PAGE_SIZE < MaxExtend)
|
/* Patch the page. */
|
||||||
|
for (i = 0; i < Count; i++)
|
||||||
{
|
{
|
||||||
ProtectBase2 = ImageBase + RelocationDir->VirtualAddress + PAGE_SIZE;
|
SHORT Offset = TypeOffset[i] & 0xFFF;
|
||||||
ProtectSize2 = PAGE_SIZE;
|
USHORT Type = TypeOffset[i] >> 12;
|
||||||
Status = NtProtectVirtualMemory(NtCurrentProcess(),
|
|
||||||
&ProtectBase2,
|
switch (Type)
|
||||||
&ProtectSize2,
|
|
||||||
PAGE_READWRITE,
|
|
||||||
&OldProtect2);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
DPRINT1("Failed to unprotect relocation target (2).\n");
|
case IMAGE_REL_BASED_ABSOLUTE:
|
||||||
NtProtectVirtualMemory(NtCurrentProcess(),
|
|
||||||
&ProtectBase,
|
|
||||||
&ProtectSize,
|
|
||||||
OldProtect,
|
|
||||||
&OldProtect);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < NumberOfEntries; i++)
|
|
||||||
{
|
|
||||||
Offset = (RelocationBlock[i].TypeOffset & 0xfff);
|
|
||||||
Offset += (ULONG)(RelocationDir->VirtualAddress + ImageBase);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* What kind of relocations should we perform
|
|
||||||
* for the current entry?
|
|
||||||
*/
|
|
||||||
switch (RelocationBlock[i].TypeOffset >> 12)
|
|
||||||
{
|
|
||||||
case TYPE_RELOC_ABSOLUTE:
|
|
||||||
break;
|
break;
|
||||||
|
case IMAGE_REL_BASED_HIGH:
|
||||||
case TYPE_RELOC_HIGH:
|
*(PUSHORT)(Page + Offset) += HIWORD(Delta);
|
||||||
pValue16 = (PUSHORT)Offset;
|
|
||||||
*pValue16 += Delta32 >> 16;
|
|
||||||
break;
|
break;
|
||||||
|
case IMAGE_REL_BASED_LOW:
|
||||||
case TYPE_RELOC_LOW:
|
*(PUSHORT)(Page + Offset) += LOWORD(Delta);
|
||||||
pValue16 = (PUSHORT)Offset;
|
|
||||||
*pValue16 += Delta32 & 0xffff;
|
|
||||||
break;
|
break;
|
||||||
|
case IMAGE_REL_BASED_HIGHLOW:
|
||||||
case TYPE_RELOC_HIGHLOW:
|
*(PULONG)(Page + Offset) += Delta;
|
||||||
pValue32 = (PULONG)Offset;
|
|
||||||
*pValue32 += Delta32;
|
|
||||||
break;
|
break;
|
||||||
|
case IMAGE_REL_BASED_HIGHADJ:
|
||||||
case TYPE_RELOC_HIGHADJ:
|
|
||||||
/* FIXME: do the highadjust fixup */
|
|
||||||
DPRINT("TYPE_RELOC_HIGHADJ fixup not implemented, sorry\n");
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DPRINT("unexpected fixup type\n");
|
DPRINT("Unknown/unsupported fixup type %d.\n", type);
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = NtProtectVirtualMemory(NtCurrentProcess(),
|
/* Restore old page protection. */
|
||||||
&ProtectBase,
|
NtProtectVirtualMemory(NtCurrentProcess(),
|
||||||
|
&ProtectPage,
|
||||||
&ProtectSize,
|
&ProtectSize,
|
||||||
OldProtect,
|
OldProtect,
|
||||||
&OldProtect);
|
&OldProtect);
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to protect relocation target.\n");
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RelocationDir->VirtualAddress + PAGE_SIZE < MaxExtend)
|
RelocationDir = (IMAGE_BASE_RELOCATION*)((ULONG_PTR)RelocationDir +
|
||||||
{
|
RelocationDir->SizeOfBlock);
|
||||||
Status = NtProtectVirtualMemory(NtCurrentProcess(),
|
|
||||||
&ProtectBase2,
|
|
||||||
&ProtectSize2,
|
|
||||||
OldProtect2,
|
|
||||||
&OldProtect2);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to protect relocation target2.\n");
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RelocationRVA += RelocationDir->SizeOfBlock;
|
|
||||||
RelocationDir =
|
|
||||||
(PRELOCATION_DIRECTORY) (ImageBase + RelocationRVA);
|
|
||||||
RelocationBlockOffset += RelocationDir->SizeOfBlock;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue