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