singrdk/base/Kernel/Singularity/Loader/Relocations.cs

124 lines
4.9 KiB
C#
Raw Normal View History

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();
}
}
}