116 lines
4.4 KiB
C#
116 lines
4.4 KiB
C#
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
//
|
||
|
// Simple PE Loader for Singularity
|
||
|
//
|
||
|
// Currently does not support:
|
||
|
// x64
|
||
|
// sections loaded at separate addresses
|
||
|
// loading at preferred address
|
||
|
|
||
|
// #define verbose
|
||
|
|
||
|
// haryadi
|
||
|
//#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;
|
||
|
|
||
|
internal static void FixupBlocks(IoMemory relocationMemory, int relocOffset,
|
||
|
IoMemory codeMemory, uint diff)
|
||
|
{
|
||
|
uint va = relocationMemory.Read32Unchecked(relocOffset);
|
||
|
uint size = relocationMemory.Read32Unchecked(relocOffset+4);
|
||
|
while (0 != va)
|
||
|
{
|
||
|
#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,
|
||
|
IoMemory codeMemory, uint diff, uint va, int size)
|
||
|
{
|
||
|
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
|
||
|
for (int i = 0; i < numberOfEntries; i++)
|
||
|
{
|
||
|
fixupEntry = relocationMemory.Read16(relocOffset);
|
||
|
relocOffset += 2;
|
||
|
currentSize -= 2;
|
||
|
ushort type = (ushort) (fixupEntry >>12);
|
||
|
//clear out the upper bits
|
||
|
uint rVA = (uint)(fixupEntry & 0xfff)+ va;
|
||
|
if (IMAGE_REL_BASED_ABSOLUTE == type)
|
||
|
{
|
||
|
//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;
|
||
|
}
|
||
|
else if (IMAGE_REL_BASED_HIGHLOW == type)
|
||
|
{
|
||
|
// get 32-bit word pointed by rVA
|
||
|
// mem object representing loaded image is 0 based rVA is sufficient
|
||
|
uint fixupItem = codeMemory.Read32Unchecked((int)rVA);
|
||
|
uint newValue = unchecked(diff + (uint) fixupItem);
|
||
|
#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);
|
||
|
}
|
||
|
}
|
||
|
//DebugStub.WriteLine();
|
||
|
}
|
||
|
}
|
||
|
}
|