// dnlib: See LICENSE.txt for more info
using System;
using dnlib.IO;
using dnlib.PE;
namespace dnlib.DotNet.Writer {
///
/// Stores the instruction that jumps to _CorExeMain/_CorDllMain
///
public sealed class StartupStub : IChunk {
const StubType stubType = StubType.EntryPoint;
readonly RelocDirectory relocDirectory;
readonly Machine machine;
readonly CpuArch cpuArch;
readonly Action logError;
FileOffset offset;
RVA rva;
///
/// Gets/sets the
///
public ImportDirectory ImportDirectory { get; set; }
///
/// Gets/sets the
///
public PEHeaders PEHeaders { get; set; }
///
public FileOffset FileOffset => offset;
///
public RVA RVA => rva;
///
/// Gets the address of the JMP instruction
///
public RVA EntryPointRVA => rva + (cpuArch is null ? 0 : cpuArch.GetStubCodeOffset(stubType));
internal bool Enable { get; set; }
internal uint Alignment => cpuArch is null ? 1 : cpuArch.GetStubAlignment(stubType);
///
/// Constructor
///
/// Reloc directory
/// Machine
/// Error logger
internal StartupStub(RelocDirectory relocDirectory, Machine machine, Action logError) {
this.relocDirectory = relocDirectory;
this.machine = machine;
this.logError = logError;
CpuArch.TryGetCpuArch(machine, out cpuArch);
}
///
public void SetOffset(FileOffset offset, RVA rva) {
this.offset = offset;
this.rva = rva;
if (!Enable)
return;
if (cpuArch is null) {
logError("The module needs an unmanaged entry point but the CPU architecture isn't supported: {0} (0x{1:X4})", new object[] { machine, (ushort)machine });
return;
}
cpuArch.WriteStubRelocs(stubType, relocDirectory, this, 0);
}
///
public uint GetFileLength() {
if (!Enable)
return 0;
if (cpuArch is null)
return 0;
return cpuArch.GetStubSize(stubType);
}
///
public uint GetVirtualSize() => GetFileLength();
///
public uint CalculateAlignment() => 0;
///
public void WriteTo(DataWriter writer) {
if (!Enable)
return;
if (cpuArch is null)
return;
cpuArch.WriteStub(stubType, writer, PEHeaders.ImageBase, (uint)rva, (uint)ImportDirectory.IatCorXxxMainRVA);
}
}
}