Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ public void EmitPortableExecutable()
_customPESectionAlignment);

NativeDebugDirectoryEntryNode nativeDebugDirectoryEntryNode = null;
ISymbolDefinitionNode firstImportThunk = null;
ISymbolDefinitionNode lastImportThunk = null;
ObjectNode lastWrittenObjectNode = null;

int nodeIndex = -1;
foreach (var depNode in _nodes)
Expand All @@ -162,6 +165,18 @@ public void EmitPortableExecutable()
nativeDebugDirectoryEntryNode = nddeNode;
}

if (node is ImportThunk importThunkNode)
{
Debug.Assert(firstImportThunk == null || lastWrittenObjectNode is ImportThunk,
"All the import thunks must be in single contiguous run");

if (firstImportThunk == null)
{
firstImportThunk = importThunkNode;
}
lastImportThunk = importThunkNode;
}

string name = null;

if (_mapFileBuilder != null)
Expand All @@ -180,10 +195,16 @@ public void EmitPortableExecutable()
}

EmitObjectData(r2rPeBuilder, nodeContents, nodeIndex, name, node.Section, _mapFileBuilder);
lastWrittenObjectNode = node;
}

r2rPeBuilder.SetCorHeader(_nodeFactory.CopiedCorHeaderNode, _nodeFactory.CopiedCorHeaderNode.Size);
r2rPeBuilder.SetDebugDirectory(_nodeFactory.DebugDirectoryNode, _nodeFactory.DebugDirectoryNode.Size);
if (firstImportThunk != null)
{
r2rPeBuilder.AddSymbolForRange(_nodeFactory.DelayLoadMethodCallThunks, firstImportThunk, lastImportThunk);
}


if (_nodeFactory.Win32ResourcesNode != null)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;

using ILCompiler.DependencyAnalysisFramework;

using Internal.Text;

namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
/// <summary>
/// Provides an ISymbolNode for the R2R header table to relocate against when looking up the delay load method call thunks.
/// They are emitted in a contiguous run of object nodes. This symbol is used in the object writer to represent the range
/// of bytes containing all the thunks.
/// </summary>
public class DelayLoadMethodCallThunkNodeRange : DependencyNodeCore<NodeFactory>, ISymbolDefinitionNode
{
public override bool InterestingForDynamicDependencyAnalysis => false;
public override bool HasDynamicDependencies => false;
public override bool HasConditionalStaticDependencies => false;
public override bool StaticDependenciesAreComputed => true;
public int Offset => 0;
public bool RepresentsIndirectionCell => false;
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context) => null;
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context) => null;
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;
protected override string GetName(NodeFactory context) => "DelayLoadMethodCallThunkNodeRange";

public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(GetName(null));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Internal.Text;
using Internal.TypeSystem;
using Internal.ReadyToRunConstants;
using ILCompiler.DependencyAnalysisFramework;

namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
Expand Down Expand Up @@ -45,15 +46,15 @@ public abstract class HeaderNode : ObjectNode, ISymbolDefinitionNode
{
struct HeaderItem
{
public HeaderItem(ReadyToRunSectionType id, ObjectNode node, ISymbolNode startSymbol)
public HeaderItem(ReadyToRunSectionType id, DependencyNodeCore<NodeFactory> node, ISymbolNode startSymbol)
{
Id = id;
Node = node;
StartSymbol = startSymbol;
}

public readonly ReadyToRunSectionType Id;
public readonly ObjectNode Node;
public readonly DependencyNodeCore<NodeFactory> Node;
public readonly ISymbolNode StartSymbol;
}

Expand All @@ -67,7 +68,7 @@ public HeaderNode(TargetDetails target, ReadyToRunFlags flags)
_flags = flags;
}

public void Add(ReadyToRunSectionType id, ObjectNode node, ISymbolNode startSymbol)
public void Add(ReadyToRunSectionType id, DependencyNodeCore<NodeFactory> node, ISymbolNode startSymbol)
{
_items.Add(new HeaderItem(id, node, startSymbol));
}
Expand Down Expand Up @@ -116,13 +117,17 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
foreach (var item in _items)
{
// Skip empty entries
if (!relocsOnly && item.Node.ShouldSkipEmittingObjectNode(factory))
if (!relocsOnly && item.Node is ObjectNode on && on.ShouldSkipEmittingObjectNode(factory))
continue;

builder.EmitInt((int)item.Id);

builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB);
builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_SYMBOL_SIZE);

// The header entry for the runtime functions table should not include the 4 byte 0xffffffff sentinel
// value in the covered range.
int delta = item.Id == ReadyToRunSectionType.RuntimeFunctions ? RuntimeFunctionsTableNode.SentinelSizeAdjustment : 0;
builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_SYMBOL_SIZE, delta);

count++;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,22 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
return runtimeFunctionsBuilder.ToObjectData();
}

public int TableSize
/// <summary>
/// Returns the runtime functions table size and excludes the 4 byte sentinel entry at the end (used by
/// the runtime in NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod) so that it's not treated as
/// part of the table itself.
/// </summary>
public int TableSizeExcludingSentinel
{
get
{
Debug.Assert(_tableSize >= 0);
return _tableSize;
return _tableSize + SentinelSizeAdjustment;
}
}

public override int ClassCode => -855231428;

internal const int SentinelSizeAdjustment = -4;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ private void CreateNodeCaches()
public RuntimeFunctionsGCInfoNode RuntimeFunctionsGCInfo;

public ProfileDataSectionNode ProfileDataSection;
public DelayLoadMethodCallThunkNodeRange DelayLoadMethodCallThunks;

public InstanceEntryPointTableNode InstanceEntryPointTable;

Expand Down Expand Up @@ -502,6 +503,9 @@ public void AttachToDependencyGraph(DependencyAnalyzerBase<NodeFactory> graph)
ProfileDataSection = new ProfileDataSectionNode();
Header.Add(Internal.Runtime.ReadyToRunSectionType.ProfileDataInfo, ProfileDataSection, ProfileDataSection.StartSymbol);

DelayLoadMethodCallThunks = new DelayLoadMethodCallThunkNodeRange();
Header.Add(Internal.Runtime.ReadyToRunSectionType.DelayLoadMethodCallThunks, DelayLoadMethodCallThunks, DelayLoadMethodCallThunks);

ExceptionInfoLookupTableNode exceptionInfoLookupTableNode = new ExceptionInfoLookupTableNode(this);
Header.Add(Internal.Runtime.ReadyToRunSectionType.ExceptionInfo, exceptionInfoLookupTableNode, exceptionInfoLookupTableNode);
graph.AddRoot(exceptionInfoLookupTableNode, "ExceptionInfoLookupTable is always generated");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
<Compile Include="..\..\Common\JitInterface\CorInfoTypes.VarInfo.cs" Link="JitInterface\CorInfoTypes.VarInfo.cs" />
<Compile Include="..\..\Common\JitInterface\SystemVStructClassificator.cs" Link="JitInterface\SystemVStructClassificator.cs" />
<Compile Include="..\..\Common\TypeSystem\Interop\InteropTypes.cs" Link="Interop\InteropTypes.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\DelayLoadMethodCallThunkNodeRange.cs" />
<Compile Include="ObjectWriter\MapFileBuilder.cs" />
<Compile Include="CodeGen\ReadyToRunObjectWriter.cs" />
<Compile Include="Compiler\CompilationModuleGroup.ReadyToRun.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,16 @@ public void AddObjectData(ObjectNode.ObjectData objectData, ObjectNodeSection se
_sectionBuilder.AddObjectData(objectData, targetSectionIndex, name, mapFileBuilder);
}

/// <summary>
/// Add a symbol to the symbol map which defines the area of the binary between the two emitted symbols.
/// This allows relocations (both position and size) to regions of the image. Both nodes must be in the
/// same section and firstNode must be emitted before secondNode.
/// </summary>
public void AddSymbolForRange(ISymbolNode symbol, ISymbolNode firstNode, ISymbolNode secondNode)
{
_sectionBuilder.AddSymbolForRange(symbol, firstNode, secondNode);
}

public int GetSymbolFilePosition(ISymbolNode symbol)
{
return _sectionBuilder.GetSymbolFilePosition(symbol);
Expand Down Expand Up @@ -497,7 +507,7 @@ protected override PEDirectoriesBuilder GetDirectories()
RuntimeFunctionsTableNode runtimeFunctionsTable = _getRuntimeFunctionsTable();
builder.ExceptionTable = new DirectoryEntry(
relativeVirtualAddress: _sectionBuilder.GetSymbolRVA(runtimeFunctionsTable),
size: runtimeFunctionsTable.TableSize);
size: runtimeFunctionsTable.TableSizeExcludingSentinel);
}

return builder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,20 @@ public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, st
}
}

public void AddSymbolForRange(ISymbolNode symbol, ISymbolNode firstNode, ISymbolNode secondNode)
{
SymbolTarget firstSymbolTarget = _symbolMap[firstNode];
SymbolTarget secondSymbolTarget = _symbolMap[secondNode];
Debug.Assert(firstSymbolTarget.SectionIndex == secondSymbolTarget.SectionIndex);
Debug.Assert(firstSymbolTarget.Offset <= secondSymbolTarget.Offset);

_symbolMap.Add(symbol, new SymbolTarget(
sectionIndex: firstSymbolTarget.SectionIndex,
offset: firstSymbolTarget.Offset,
size: secondSymbolTarget.Offset - firstSymbolTarget.Offset + secondSymbolTarget.Size
));
}

/// <summary>
/// Get the list of sections that need to be emitted to the output PE file.
/// We filter out name duplicates as we'll end up merging builder sections with the same name
Expand Down
11 changes: 9 additions & 2 deletions src/coreclr/src/vm/codeman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6610,14 +6610,15 @@ StubCodeBlockKind ReadyToRunJitManager::GetStubCodeBlockKind(RangeSection * pRan
NOTHROW;
GC_NOTRIGGER;
MODE_ANY;
SUPPORTS_DAC;
}
CONTRACTL_END;

DWORD rva = (DWORD)(currentPC - pRangeSection->LowAddress);

ReadyToRunInfo * pReadyToRunInfo = dac_cast<PTR_Module>(pRangeSection->pHeapListOrZapModule)->GetReadyToRunInfo();
PTR_ReadyToRunInfo pReadyToRunInfo = dac_cast<PTR_Module>(pRangeSection->pHeapListOrZapModule)->GetReadyToRunInfo();

IMAGE_DATA_DIRECTORY * pDelayLoadMethodCallThunksDir = pReadyToRunInfo->FindSection(ReadyToRunSectionType::DelayLoadMethodCallThunks);
PTR_IMAGE_DATA_DIRECTORY pDelayLoadMethodCallThunksDir = pReadyToRunInfo->GetDelayMethodCallThunksSection();
if (pDelayLoadMethodCallThunksDir != NULL)
{
if (pDelayLoadMethodCallThunksDir->VirtualAddress <= rva
Expand Down Expand Up @@ -6778,6 +6779,12 @@ BOOL ReadyToRunJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection,

// READYTORUN: FUTURE: Hot-cold spliting

// If the address is in a thunk, return NULL.
if (GetStubCodeBlockKind(pRangeSection, currentPC) != STUB_CODE_BLOCK_UNKNOWN)
{
return FALSE;
}

TADDR currentInstr = PCODEToPINSTR(currentPC);

TADDR ImageBase = pRangeSection->LowAddress;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/src/vm/codeman.h
Original file line number Diff line number Diff line change
Expand Up @@ -1619,7 +1619,7 @@ class NativeUnwindInfoLookupTable

#ifdef FEATURE_READYTORUN

class ReadyToRunJitManager : public IJitManager
class ReadyToRunJitManager final: public IJitManager
{
VPTR_VTABLE_CLASS(ReadyToRunJitManager, IJitManager)

Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/src/vm/readytoruninfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,8 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYT
m_methodDefEntryPoints = NativeArray(&m_nativeReader, pEntryPointsDir->VirtualAddress);
}

m_pSectionDelayLoadMethodCallThunks = m_component.FindSection(ReadyToRunSectionType::DelayLoadMethodCallThunks);

IMAGE_DATA_DIRECTORY * pinstMethodsDir = m_pComposite->FindSection(ReadyToRunSectionType::InstanceMethodEntryPoints);
if (pinstMethodsDir != NULL)
{
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/src/vm/readytoruninfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class ReadyToRunInfo
PTR_RUNTIME_FUNCTION m_pRuntimeFunctions;
DWORD m_nRuntimeFunctions;

PTR_IMAGE_DATA_DIRECTORY m_pSectionDelayLoadMethodCallThunks;

PTR_CORCOMPILE_IMPORT_SECTION m_pImportSections;
DWORD m_nImportSections;

Expand Down Expand Up @@ -92,6 +94,8 @@ class ReadyToRunInfo

PTR_READYTORUN_HEADER GetReadyToRunHeader() const { return m_pHeader; }

PTR_IMAGE_DATA_DIRECTORY GetDelayMethodCallThunksSection() const { return m_pSectionDelayLoadMethodCallThunks; }

PTR_NativeImage GetNativeImage() const { return m_pNativeImage; }

PTR_PEImageLayout GetImage() const { return m_pComposite->GetImage(); }
Expand Down