|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using Internal.Text;
using Internal.TypeSystem.Ecma;
using Debug = System.Diagnostics.Debug;
namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
public class CopiedCorHeaderNode : ObjectNode, ISymbolDefinitionNode
{
private static readonly int s_corHeaderSize = 0x48;
private EcmaModule _module;
public CopiedCorHeaderNode(EcmaModule sourceModule)
{
_module = sourceModule;
}
public override ObjectNodeSection GetSection(NodeFactory factory)
{
return ObjectNodeSection.ReadOnlyDataSection;
}
public override bool IsShareable => false;
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
public override int ClassCode => (int)ObjectNodeOrder.CorHeaderNode;
public override bool StaticDependenciesAreComputed => true;
public int Offset => 0;
public int Size => s_corHeaderSize;
/// <summary>
/// Deserialize a directory entry from a blob reader.
/// </summary>
/// <param name="reader">Reader to deserialize directory entry from</param>
private static DirectoryEntry ReadDirectoryEntry(ref BlobReader reader)
{
int rva = reader.ReadInt32();
int size = reader.ReadInt32();
return new DirectoryEntry(rva, size);
}
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix);
if (_module != null)
sb.Append($"__CorHeader_{_module.Assembly.GetName().Name}");
else
sb.Append("__CompositeCorHeader_"u8);
}
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);
builder.RequireInitialPointerAlignment();
builder.AddSymbol(this);
if (_module != null)
{
BlobReader reader = _module.PEReader.GetEntireImage().GetReader();
reader.Offset = _module.PEReader.PEHeaders.CorHeaderStartOffset;
// Header Size
int headerSize = reader.ReadInt32();
builder.EmitInt(headerSize);
// Runtime major, minor version
builder.EmitUShort(reader.ReadUInt16());
builder.EmitUShort(reader.ReadUInt16());
// Metadata Directory
ReadDirectoryEntry(ref reader);
var metadataBlob = factory.CopiedMetadataBlob(_module);
builder.EmitReloc(metadataBlob, RelocType.IMAGE_REL_BASED_ADDR32NB);
builder.EmitInt(metadataBlob.Size);
// Flags
builder.EmitUInt((uint)(((CorFlags)reader.ReadUInt32() & ~CorFlags.ILOnly) | CorFlags.ILLibrary));
// Entrypoint
builder.EmitInt(reader.ReadInt32());
// Resources Directory
if (ReadDirectoryEntry(ref reader).Size > 0)
{
var managedResources = factory.CopiedManagedResources(_module);
builder.EmitReloc(managedResources, RelocType.IMAGE_REL_BASED_ADDR32NB);
builder.EmitInt(managedResources.Size);
}
else
{
WriteEmptyDirectoryEntry(ref builder);
}
// Strong Name Signature Directory
if (ReadDirectoryEntry(ref reader).Size > 0)
{
var strongNameSignature = factory.CopiedStrongNameSignature(_module);
builder.EmitReloc(strongNameSignature, RelocType.IMAGE_REL_BASED_ADDR32NB);
builder.EmitInt(strongNameSignature.Size);
}
else
{
WriteEmptyDirectoryEntry(ref builder);
}
// Code Manager Table Directory
ReadDirectoryEntry(ref reader);
WriteEmptyDirectoryEntry(ref builder);
// VTable Fixups Directory
ReadDirectoryEntry(ref reader);
WriteEmptyDirectoryEntry(ref builder);
// Export Address Table Jumps Directory
ReadDirectoryEntry(ref reader);
WriteEmptyDirectoryEntry(ref builder);
// Managed Native (ReadyToRun) Header Directory
ReadDirectoryEntry(ref reader);
builder.EmitReloc(factory.Header, RelocType.IMAGE_REL_BASED_ADDR32NB);
builder.EmitReloc(factory.Header, RelocType.IMAGE_REL_SYMBOL_SIZE);
// Did we fully read the header?
Debug.Assert(reader.Offset - headerSize == _module.PEReader.PEHeaders.CorHeaderStartOffset);
Debug.Assert(builder.CountBytes == headerSize);
Debug.Assert(headerSize == Size);
}
else
{
// Generating CORHeader for composite image
// Header Size
builder.EmitInt(Size);
// Runtime major, minor version
builder.EmitUShort(0);
builder.EmitUShort(0);
// Metadata Directory
builder.EmitReloc(factory.ManifestMetadataTable, RelocType.IMAGE_REL_BASED_ADDR32NB);
builder.EmitReloc(factory.ManifestMetadataTable, RelocType.IMAGE_REL_SYMBOL_SIZE);
// Flags
if (factory.CompositeImageSettings.PublicKey != null)
{
const uint COMIMAGE_FLAGS_STRONGNAMESIGNED = 8;
builder.EmitUInt(COMIMAGE_FLAGS_STRONGNAMESIGNED);
}
else
{
builder.EmitUInt(0);
}
// Entrypoint
builder.EmitInt(0);
// Resources Directory
WriteEmptyDirectoryEntry(ref builder);
// Strong Name Signature Directory
WriteEmptyDirectoryEntry(ref builder);
// Code Manager Table Directory
WriteEmptyDirectoryEntry(ref builder);
// VTable Fixups Directory
WriteEmptyDirectoryEntry(ref builder);
// Export Address Table Jumps Directory
WriteEmptyDirectoryEntry(ref builder);
// Managed Native (ReadyToRun) Header Directory
builder.EmitReloc(factory.Header, RelocType.IMAGE_REL_BASED_ADDR32NB);
builder.EmitReloc(factory.Header, RelocType.IMAGE_REL_SYMBOL_SIZE);
}
return builder.ToObjectData();
}
private void WriteEmptyDirectoryEntry(ref ObjectDataBuilder builder)
{
builder.EmitInt(0);
builder.EmitInt(0);
}
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
if (_module == null)
{
if (((CopiedCorHeaderNode)other)._module == null)
return 0;
return -1;
}
else if (((CopiedCorHeaderNode)other)._module == null)
{
return 1;
}
return _module.CompareTo(((CopiedCorHeaderNode)other)._module);
}
}
}
|