2008-11-17 18:29:00 -05:00
|
|
|
// ----------------------------------------------------------------------------
|
2008-03-05 09:52:00 -05:00
|
|
|
//
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
//
|
2008-11-17 18:29:00 -05:00
|
|
|
// ----------------------------------------------------------------------------
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
//
|
|
|
|
// Simple PE Loader for Singularity
|
|
|
|
//
|
|
|
|
// Currently does not support:
|
|
|
|
// x64
|
|
|
|
// sections loaded at separate addresses
|
|
|
|
// loading at preferred address
|
|
|
|
|
|
|
|
// #define verbose
|
|
|
|
|
|
|
|
//#define SINGULARITY_ASMP
|
|
|
|
|
|
|
|
namespace Microsoft.Singularity.Loader
|
|
|
|
{
|
|
|
|
using Microsoft.Singularity;
|
|
|
|
using Microsoft.Singularity.Io;
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
using System.Threading;
|
|
|
|
|
|
|
|
internal class Relocations
|
|
|
|
{
|
|
|
|
private const ushort sizeofBaseRelocation = 8;
|
|
|
|
|
|
|
|
//Based relocation types.
|
|
|
|
private const ushort IMAGE_REL_BASED_ABSOLUTE = 0;
|
|
|
|
private const ushort IMAGE_REL_BASED_HIGH = 1;
|
|
|
|
private const ushort IMAGE_REL_BASED_LOW = 2;
|
|
|
|
private const ushort IMAGE_REL_BASED_HIGHLOW = 3;
|
|
|
|
private const ushort IMAGE_REL_BASED_HIGHADJ = 4;
|
2008-11-17 18:29:00 -05:00
|
|
|
private const ushort IMAGE_REL_BASED_DIR64 = 10;
|
2008-03-05 09:52:00 -05:00
|
|
|
|
|
|
|
internal static void FixupBlocks(IoMemory relocationMemory, int relocOffset,
|
2008-11-17 18:29:00 -05:00
|
|
|
IoMemory codeMemory, UIntPtr diff)
|
2008-03-05 09:52:00 -05:00
|
|
|
{
|
|
|
|
uint va = relocationMemory.Read32Unchecked(relocOffset);
|
|
|
|
uint size = relocationMemory.Read32Unchecked(relocOffset+4);
|
2008-11-17 18:29:00 -05:00
|
|
|
while (0 != va) {
|
2008-03-05 09:52:00 -05:00
|
|
|
#if verbose
|
|
|
|
DebugStub.WriteLine(" FixUpBlocks: addr={0:x8}, size={1:x8}, roffset={2:x8} ",
|
|
|
|
__arglist(va, size,relocOffset));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SINGULARITY_ASMP
|
|
|
|
if (va == 0xffffffff || size == 0xffffffff
|
|
|
|
||
|
|
|
|
va >= 0xc0000000 || size >= 0xc0000000) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
FixupBlock(relocationMemory, relocOffset,
|
|
|
|
codeMemory, diff, va, (int)size);
|
|
|
|
relocOffset += (int)size;
|
|
|
|
va = relocationMemory.Read32Unchecked(relocOffset);
|
|
|
|
size = relocationMemory.Read32Unchecked(relocOffset+4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void FixupBlock(IoMemory relocationMemory, int relocOffset,
|
2008-11-17 18:29:00 -05:00
|
|
|
IoMemory codeMemory, UIntPtr diff, uint va, int size)
|
2008-03-05 09:52:00 -05:00
|
|
|
{
|
|
|
|
ushort fixupEntry;
|
|
|
|
|
|
|
|
// Compute number of entries
|
|
|
|
int numberOfEntries = (size - sizeofBaseRelocation) /2;
|
|
|
|
#if verbose
|
|
|
|
DebugStub.WriteLine(" FixUp: addr={0:x8}, size={1:x8}, count={2}",
|
|
|
|
__arglist(va, size, numberOfEntries));
|
|
|
|
#endif
|
|
|
|
int currentSize = size - sizeofBaseRelocation;
|
|
|
|
relocOffset += sizeofBaseRelocation; //skip block header
|
2008-11-17 18:29:00 -05:00
|
|
|
for (int i = 0; i < numberOfEntries; i++) {
|
2008-03-05 09:52:00 -05:00
|
|
|
fixupEntry = relocationMemory.Read16(relocOffset);
|
|
|
|
relocOffset += 2;
|
|
|
|
currentSize -= 2;
|
|
|
|
ushort type = (ushort) (fixupEntry >>12);
|
|
|
|
//clear out the upper bits
|
|
|
|
uint rVA = (uint)(fixupEntry & 0xfff)+ va;
|
2008-11-17 18:29:00 -05:00
|
|
|
if (IMAGE_REL_BASED_ABSOLUTE == type) {
|
2008-03-05 09:52:00 -05:00
|
|
|
//DebugStub.WriteLine(" type={0:x4} rVA={1:x8}",
|
|
|
|
//__arglist(type, rVA));
|
|
|
|
// hit an alignment type. there should be no more entries
|
|
|
|
//DebugStub.WriteLine(" fixup: count ={0}, loop count ={1} size={2}",
|
|
|
|
//__arglist(numberOfEntries, i, currentSize));
|
|
|
|
break;
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if (IMAGE_REL_BASED_HIGHLOW == type) {
|
2008-03-05 09:52:00 -05:00
|
|
|
// get 32-bit word pointed by rVA
|
|
|
|
// mem object representing loaded image is 0 based rVA is sufficient
|
|
|
|
uint fixupItem = codeMemory.Read32Unchecked((int)rVA);
|
2008-11-17 18:29:00 -05:00
|
|
|
uint newValue = unchecked((uint) diff + (uint) fixupItem);
|
2008-03-05 09:52:00 -05:00
|
|
|
#if verbose
|
|
|
|
DebugStub.WriteLine(" Fixup: rVA={0:x8} value={1:x8} diff={2:x8}, newValue={3:x8}",
|
|
|
|
__arglist(rVA, fixupItem, diff, newValue));
|
|
|
|
#endif
|
|
|
|
codeMemory.Write32Unchecked((int) rVA, newValue);
|
|
|
|
}
|
2008-11-17 18:29:00 -05:00
|
|
|
else if (IMAGE_REL_BASED_DIR64 == type) {
|
|
|
|
ulong OldValue;
|
|
|
|
ulong NewValue;
|
|
|
|
|
|
|
|
OldValue = codeMemory.Read64((int) rVA);
|
|
|
|
|
|
|
|
NewValue = unchecked(OldValue + (ulong) diff);
|
|
|
|
|
|
|
|
codeMemory.Write64((int) rVA, NewValue);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DebugStub.WriteLine("PE Bad fixup: %x", __arglist(type));
|
|
|
|
DebugStub.Break();
|
|
|
|
}
|
2008-03-05 09:52:00 -05:00
|
|
|
}
|
|
|
|
//DebugStub.WriteLine();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|