From c8361ccd1ab6fafcc69847a9ed482b857dfabfc9 Mon Sep 17 00:00:00 2001 From: Simon Nattress Date: Fri, 10 Jul 2020 01:37:27 -0700 Subject: [PATCH 1/7] [Crossgen2] Add DelayLoadMethodCallThunks table, fix stack walks containing thunks GC stress runs with Crossgen2 binaries frequently see AVs with stack-walk failures. This occurs when a delay load thunk is being executed as a stack-walk is performed. The runtime resolves any thunk address to the code info for the last managed method in the runtime functions table. Fix the binary search algorithm in `NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod` which doesn't correctly return -1 if the code address being searched for is larger than any present. This old bug was not hit because Crossgen emits stubs earlier in the image than managed code, whereas the two are reversed with Crossgen2. Fix generation of the RuntimeFunctionsTable so that the terminating sentinel node is not treated as part of the table in the R2R header entry for the table. This was causing the sentinel node to be treated as its own runtime function by the runtime and could lead to reading beyond the table bounds in `NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod`. The bug in the binary search of the table hid this bug until now. Add the `DelayLoadMethodCallThunks` header entry. `DelayLoadMethodCallThunkNodeRange` is a placeholder node (not an `ObjectNode`) to provide a symbol to relocate against from the header. It represents the range of import thunks. Add support to the object writer for defining a range between two symbols in the same section. The relocation phase can then resolve the difference between the two symbols to determine the range size. Fixes https://github.com/dotnet/runtime/issues/38482 --- .../CodeGen/ReadyToRunObjectWriter.cs | 13 +++++++ .../DelayLoadMethodCallThunkNodeRange.cs | 36 +++++++++++++++++++ .../ReadyToRun/HeaderNode.cs | 15 +++++--- .../ReadyToRun/RuntimeFunctionsTableNode.cs | 9 +++-- .../ReadyToRunCodegenNodeFactory.cs | 4 +++ .../ILCompiler.ReadyToRun.csproj | 1 + .../ObjectWriter/R2RPEBuilder.cs | 12 ++++++- .../ObjectWriter/SectionBuilder.cs | 14 ++++++++ src/coreclr/src/vm/codeman.cpp | 2 +- 9 files changed, 97 insertions(+), 9 deletions(-) create mode 100644 src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadMethodCallThunkNodeRange.cs diff --git a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs index 18f7ffbb900357..d77bd67bf03241 100644 --- a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs +++ b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs @@ -138,6 +138,8 @@ public void EmitPortableExecutable() _customPESectionAlignment); NativeDebugDirectoryEntryNode nativeDebugDirectoryEntryNode = null; + ISymbolDefinitionNode firstImportThunk = null; + ISymbolDefinitionNode lastImportThunk = null; int nodeIndex = -1; foreach (var depNode in _nodes) @@ -162,6 +164,16 @@ public void EmitPortableExecutable() nativeDebugDirectoryEntryNode = nddeNode; } + if (node is ImportThunk importThunkNode) + { + // All the import thunks are in a single contiguous run + if (firstImportThunk == null) + { + firstImportThunk = importThunkNode; + } + lastImportThunk = importThunkNode; + } + string name = null; if (_mapFileBuilder != null) @@ -184,6 +196,7 @@ public void EmitPortableExecutable() r2rPeBuilder.SetCorHeader(_nodeFactory.CopiedCorHeaderNode, _nodeFactory.CopiedCorHeaderNode.Size); r2rPeBuilder.SetDebugDirectory(_nodeFactory.DebugDirectoryNode, _nodeFactory.DebugDirectoryNode.Size); + r2rPeBuilder.AddSymbolForRange(_nodeFactory.DelayLoadMethodCallThunks, firstImportThunk, lastImportThunk); if (_nodeFactory.Win32ResourcesNode != null) { diff --git a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadMethodCallThunkNodeRange.cs b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadMethodCallThunkNodeRange.cs new file mode 100644 index 00000000000000..b0463ee3de8bf8 --- /dev/null +++ b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadMethodCallThunkNodeRange.cs @@ -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 +{ + /// + /// 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. + /// + public class DelayLoadMethodCallThunkNodeRange : DependencyNodeCore, 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 GetConditionalStaticDependencies(NodeFactory context) => null; + public override IEnumerable GetStaticDependencies(NodeFactory context) => null; + public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory context) => null; + protected override string GetName(NodeFactory context) => "DelayLoadMethodCallThunkNodeRange"; + + public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) + { + sb.Append(GetName(null)); + } + } +} diff --git a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/HeaderNode.cs b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/HeaderNode.cs index fe33cebfbe5804..218fbcf2f5be9d 100644 --- a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/HeaderNode.cs +++ b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/HeaderNode.cs @@ -7,6 +7,7 @@ using Internal.Text; using Internal.TypeSystem; using Internal.ReadyToRunConstants; +using ILCompiler.DependencyAnalysisFramework; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -45,7 +46,7 @@ public abstract class HeaderNode : ObjectNode, ISymbolDefinitionNode { struct HeaderItem { - public HeaderItem(ReadyToRunSectionType id, ObjectNode node, ISymbolNode startSymbol) + public HeaderItem(ReadyToRunSectionType id, DependencyNodeCore node, ISymbolNode startSymbol) { Id = id; Node = node; @@ -53,7 +54,7 @@ public HeaderItem(ReadyToRunSectionType id, ObjectNode node, ISymbolNode startSy } public readonly ReadyToRunSectionType Id; - public readonly ObjectNode Node; + public readonly DependencyNodeCore Node; public readonly ISymbolNode StartSymbol; } @@ -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 node, ISymbolNode startSymbol) { _items.Add(new HeaderItem(id, node, startSymbol)); } @@ -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 ? -4 : 0; + builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_SYMBOL_SIZE, delta); count++; } diff --git a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsTableNode.cs b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsTableNode.cs index 24dd8d91c5a17d..b31000aa94418a 100644 --- a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsTableNode.cs +++ b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsTableNode.cs @@ -103,12 +103,17 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) return runtimeFunctionsBuilder.ToObjectData(); } - public int TableSize + /// + /// 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. + /// + public int TableSizeExcludingSentinel { get { Debug.Assert(_tableSize >= 0); - return _tableSize; + return _tableSize - 4; } } diff --git a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs index 0a29f3ff689b53..9f9ebf9366280c 100644 --- a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs +++ b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs @@ -305,6 +305,7 @@ private void CreateNodeCaches() public RuntimeFunctionsGCInfoNode RuntimeFunctionsGCInfo; public ProfileDataSectionNode ProfileDataSection; + public DelayLoadMethodCallThunkNodeRange DelayLoadMethodCallThunks; public InstanceEntryPointTableNode InstanceEntryPointTable; @@ -502,6 +503,9 @@ public void AttachToDependencyGraph(DependencyAnalyzerBase 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"); diff --git a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index 099820c53e54f4..483973871a90b5 100644 --- a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -94,6 +94,7 @@ + diff --git a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs index 95b4035178d3da..839b1f21d11067 100644 --- a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs +++ b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs @@ -268,6 +268,16 @@ public void AddObjectData(ObjectNode.ObjectData objectData, ObjectNodeSection se _sectionBuilder.AddObjectData(objectData, targetSectionIndex, name, mapFileBuilder); } + /// + /// 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. + /// + public void AddSymbolForRange(ISymbolNode symbol, ISymbolNode firstNode, ISymbolNode secondNode) + { + _sectionBuilder.AddSymbolForRange(symbol, firstNode, secondNode); + } + public int GetSymbolFilePosition(ISymbolNode symbol) { return _sectionBuilder.GetSymbolFilePosition(symbol); @@ -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; diff --git a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs index 3d31687cccf7b6..dd82ab79c76e2f 100644 --- a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs +++ b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs @@ -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 + )); + } + /// /// 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 diff --git a/src/coreclr/src/vm/codeman.cpp b/src/coreclr/src/vm/codeman.cpp index 7af2850b83d491..12c0363b9559cf 100644 --- a/src/coreclr/src/vm/codeman.cpp +++ b/src/coreclr/src/vm/codeman.cpp @@ -6175,7 +6175,7 @@ int NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(DWORD RelativePc, if (RelativePc < pNextFunctionEntry->BeginAddress) { PTR_RUNTIME_FUNCTION pFunctionEntry = pRuntimeFunctionTable + i; - if (RelativePc >= pFunctionEntry->BeginAddress) + if (RelativePc >= pFunctionEntry->BeginAddress && RelativePc <= pFunctionEntry->EndAddress) { return i; } From 71dec66f3881ec47be872b75cd8b9cd6cc70e091 Mon Sep 17 00:00:00 2001 From: Simon Nattress Date: Fri, 10 Jul 2020 15:27:19 -0700 Subject: [PATCH 2/7] Code review feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Pass image base address to `LookupUnwindInfoForMethod` and correct the runtime function EndAddress lookup to use the standard macro. The image base is needed on non-x64 platforms where end address isn't just part of the `RuntimeFunction` struct. Fortunately, all the callsites of `LookupUnwindInfoForMethod` had the image base easily available 🙌 * Assert if the ImportThunks are not emitted in a single run * Replace the RuntimeFunctionsTable sentinel adjustment with a const --- src/coreclr/src/debug/daccess/nidump.cpp | 6 +++--- .../CodeGen/ReadyToRunObjectWriter.cs | 6 +++++- .../DependencyAnalysis/ReadyToRun/HeaderNode.cs | 2 +- .../ReadyToRun/RuntimeFunctionsTableNode.cs | 4 +++- src/coreclr/src/vm/codeman.cpp | 15 ++++++++++----- src/coreclr/src/vm/codeman.h | 3 ++- src/coreclr/src/vm/jitinterface.cpp | 2 +- 7 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/coreclr/src/debug/daccess/nidump.cpp b/src/coreclr/src/debug/daccess/nidump.cpp index 5a0bbfd81006f4..c3ca2ff978dea9 100644 --- a/src/coreclr/src/debug/daccess/nidump.cpp +++ b/src/coreclr/src/debug/daccess/nidump.cpp @@ -3412,7 +3412,7 @@ size_t NativeImageDumper::TranslateSymbol(IXCLRDisassemblySupport *dis, { if (pNgenLayout->m_CodeSections[iRange].IsInRange((TADDR)addr)) { - int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1); + int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(PTR_TO_TADDR(m_decoder.GetBase()), rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1); if (MethodIndex >= 0) { #ifdef FEATURE_EH_FUNCLETS @@ -3434,7 +3434,7 @@ size_t NativeImageDumper::TranslateSymbol(IXCLRDisassemblySupport *dis, if (pNgenLayout->m_CodeSections[2].IsInRange((TADDR)addr)) { - int ColdMethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[2], 0, pNgenLayout->m_nRuntimeFunctions[2] - 1); + int ColdMethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(PTR_TO_TADDR(m_decoder.GetBase()), rva, pNgenLayout->m_pRuntimeFunctions[2], 0, pNgenLayout->m_nRuntimeFunctions[2] - 1); if (ColdMethodIndex >= 0) { PTR_RUNTIME_FUNCTION pRuntimeFunction; @@ -6394,7 +6394,7 @@ void NativeImageDumper::EntryPointToString( TADDR pEntryPoint, { if (pNgenLayout->m_CodeSections[iRange].IsInRange(pEntryPoint)) { - int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1); + int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(PTR_TO_TADDR(m_decoder.GetBase()), rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1); if (MethodIndex >= 0) { #ifdef FEATURE_EH_FUNCLETS diff --git a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs index d77bd67bf03241..a8b0beb944690a 100644 --- a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs +++ b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs @@ -140,6 +140,7 @@ public void EmitPortableExecutable() NativeDebugDirectoryEntryNode nativeDebugDirectoryEntryNode = null; ISymbolDefinitionNode firstImportThunk = null; ISymbolDefinitionNode lastImportThunk = null; + ObjectNode lastWrittenObjectNode = null; int nodeIndex = -1; foreach (var depNode in _nodes) @@ -166,7 +167,9 @@ public void EmitPortableExecutable() if (node is ImportThunk importThunkNode) { - // All the import thunks are in a single contiguous run + Debug.Assert(firstImportThunk == null || lastWrittenObjectNode is ImportThunk, + "All the import thunks must be in single contiguous run"); + if (firstImportThunk == null) { firstImportThunk = importThunkNode; @@ -192,6 +195,7 @@ public void EmitPortableExecutable() } EmitObjectData(r2rPeBuilder, nodeContents, nodeIndex, name, node.Section, _mapFileBuilder); + lastWrittenObjectNode = node; } r2rPeBuilder.SetCorHeader(_nodeFactory.CopiedCorHeaderNode, _nodeFactory.CopiedCorHeaderNode.Size); diff --git a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/HeaderNode.cs b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/HeaderNode.cs index 218fbcf2f5be9d..5ff1eeccad72c0 100644 --- a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/HeaderNode.cs +++ b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/HeaderNode.cs @@ -126,7 +126,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) // 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 ? -4 : 0; + int delta = item.Id == ReadyToRunSectionType.RuntimeFunctions ? RuntimeFunctionsTableNode.SentinelSizeAdjustment : 0; builder.EmitReloc(item.StartSymbol, RelocType.IMAGE_REL_SYMBOL_SIZE, delta); count++; diff --git a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsTableNode.cs b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsTableNode.cs index b31000aa94418a..c2ab705ef5c2f6 100644 --- a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsTableNode.cs +++ b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsTableNode.cs @@ -113,10 +113,12 @@ public int TableSizeExcludingSentinel get { Debug.Assert(_tableSize >= 0); - return _tableSize - 4; + return _tableSize + SentinelSizeAdjustment; } } public override int ClassCode => -855231428; + + internal const int SentinelSizeAdjustment = -4; } } diff --git a/src/coreclr/src/vm/codeman.cpp b/src/coreclr/src/vm/codeman.cpp index 12c0363b9559cf..b114cd855cd75e 100644 --- a/src/coreclr/src/vm/codeman.cpp +++ b/src/coreclr/src/vm/codeman.cpp @@ -5591,7 +5591,7 @@ BOOL NativeImageJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection, if (iRange == 2) { - int ColdMethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(RelativePc, + int ColdMethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(ImageBase, RelativePc, pLayoutInfo->m_pRuntimeFunctions[2], 0, pLayoutInfo->m_nRuntimeFunctions[2] - 1); @@ -5680,7 +5680,8 @@ BOOL NativeImageJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection, PTR_RUNTIME_FUNCTION FunctionTable = pLayoutInfo->m_pRuntimeFunctions[iRange]; PTR_DWORD pMethodDescs = pLayoutInfo->m_MethodDescs[iRange]; - int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(RelativePc, + int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(ImageBase, + RelativePc, FunctionTable, Low, High); @@ -5808,6 +5809,7 @@ DWORD NativeImageJitManager::GetFuncletStartOffsets(const METHODTOKEN& MethodTok NGenLayoutInfo * pLayoutInfo = JitTokenToZapModule(MethodToken)->GetNGenLayoutInfo(); int iColdMethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod( + moduleBase, (DWORD)(regionInfo.coldStartAddress - moduleBase), pLayoutInfo->m_pRuntimeFunctions[2], 0, @@ -6131,7 +6133,8 @@ DWORD NativeExceptionInfoLookupTable::LookupExceptionInfoRVAForMethod(PTR_CORCOM return 0; } -int NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(DWORD RelativePc, +int NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(TADDR ImageBase, + DWORD RelativePc, PTR_RUNTIME_FUNCTION pRuntimeFunctionTable, int Low, int High) @@ -6175,7 +6178,8 @@ int NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(DWORD RelativePc, if (RelativePc < pNextFunctionEntry->BeginAddress) { PTR_RUNTIME_FUNCTION pFunctionEntry = pRuntimeFunctionTable + i; - if (RelativePc >= pFunctionEntry->BeginAddress && RelativePc <= pFunctionEntry->EndAddress) + + if (RelativePc >= pFunctionEntry->BeginAddress && RelativePc < RUNTIME_FUNCTION__EndAddress(pFunctionEntry, ImageBase)) { return i; } @@ -6790,7 +6794,8 @@ BOOL ReadyToRunJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection, COUNT_T nRuntimeFunctions = pInfo->m_nRuntimeFunctions; PTR_RUNTIME_FUNCTION pRuntimeFunctions = pInfo->m_pRuntimeFunctions; - int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(RelativePc, + int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(ImageBase, + RelativePc, pRuntimeFunctions, 0, nRuntimeFunctions - 1); diff --git a/src/coreclr/src/vm/codeman.h b/src/coreclr/src/vm/codeman.h index ae76b6939da0c6..3b6381f468294c 100644 --- a/src/coreclr/src/vm/codeman.h +++ b/src/coreclr/src/vm/codeman.h @@ -1601,7 +1601,8 @@ class NativeExceptionInfoLookupTable class NativeUnwindInfoLookupTable { public: - static int LookupUnwindInfoForMethod(DWORD codeOffset, + static int LookupUnwindInfoForMethod(TADDR ImageBase, + DWORD codeOffset, PTR_RUNTIME_FUNCTION pRuntimeFunctionTable, int StartIndex, int EndIndex); diff --git a/src/coreclr/src/vm/jitinterface.cpp b/src/coreclr/src/vm/jitinterface.cpp index 99073bec81fa3f..385c3735c05d18 100644 --- a/src/coreclr/src/vm/jitinterface.cpp +++ b/src/coreclr/src/vm/jitinterface.cpp @@ -14596,7 +14596,7 @@ LPVOID EECodeInfo::findNextFunclet (LPVOID pvFuncletStart, SIZE_T Module * pZapModule = ExecutionManager::FindZapModule((TADDR)pvFuncletStart); NGenLayoutInfo * pLayoutInfo = pZapModule->GetNGenLayoutInfo(); - int ColdFunctionIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod((DWORD)((TADDR)pvFuncletStart - uImageBase), + int ColdFunctionIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod((TADDR)uImageBase, (DWORD)((TADDR)pvFuncletStart - uImageBase), pLayoutInfo->m_pRuntimeFunctions[2], 0, pLayoutInfo->m_nRuntimeFunctions[2] - 1); From 6514ee58ec1250f7d0833a117b8571b142171324 Mon Sep 17 00:00:00 2001 From: Simon Nattress Date: Fri, 10 Jul 2020 16:45:12 -0700 Subject: [PATCH 3/7] Sometimes there are no thunks.. --- .../ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs index a8b0beb944690a..20d6dac16b8a93 100644 --- a/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs +++ b/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs @@ -200,7 +200,11 @@ public void EmitPortableExecutable() r2rPeBuilder.SetCorHeader(_nodeFactory.CopiedCorHeaderNode, _nodeFactory.CopiedCorHeaderNode.Size); r2rPeBuilder.SetDebugDirectory(_nodeFactory.DebugDirectoryNode, _nodeFactory.DebugDirectoryNode.Size); - r2rPeBuilder.AddSymbolForRange(_nodeFactory.DelayLoadMethodCallThunks, firstImportThunk, lastImportThunk); + if (firstImportThunk != null) + { + r2rPeBuilder.AddSymbolForRange(_nodeFactory.DelayLoadMethodCallThunks, firstImportThunk, lastImportThunk); + } + if (_nodeFactory.Win32ResourcesNode != null) { From c2ea1ada9b6c2c3cb33fc75a732e54a8e37f3a9d Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Mon, 13 Jul 2020 19:17:56 -0700 Subject: [PATCH 4/7] Handle Windows X86 by using GCInfo to detect function size --- src/coreclr/src/vm/codeman.cpp | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/coreclr/src/vm/codeman.cpp b/src/coreclr/src/vm/codeman.cpp index b114cd855cd75e..ea2cba864dcb35 100644 --- a/src/coreclr/src/vm/codeman.cpp +++ b/src/coreclr/src/vm/codeman.cpp @@ -6179,11 +6179,19 @@ int NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(TADDR ImageBase, { PTR_RUNTIME_FUNCTION pFunctionEntry = pRuntimeFunctionTable + i; - if (RelativePc >= pFunctionEntry->BeginAddress && RelativePc < RUNTIME_FUNCTION__EndAddress(pFunctionEntry, ImageBase)) + if (RelativePc >= pFunctionEntry->BeginAddress) { - return i; +#if defined(TARGET_X86) && !defined(UNIX_X86_ABI) && !defined(FEATURE_EH_FUNCLETS) + // On Windows X86, the end offset is handled by the method region code (for ngen), and + // the GCInfo for ReadyToRun +#else + if (RelativePc < RUNTIME_FUNCTION__EndAddress(pFunctionEntry, ImageBase)) +#endif + { + return i; + break; + } } - break; } } @@ -6803,6 +6811,20 @@ BOOL ReadyToRunJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection, if (MethodIndex < 0) return FALSE; +#if defined(TARGET_X86) && !defined(UNIX_X86_ABI) && !defined(FEATURE_EH_FUNCLETS) + { + // On Windows X86, the RUNTIME_FUNCTION structure does not encode the end of the function + // Use the GCInfo to find the end of the function and verify that currentPC is in the + // bounds of the function + PTR_RUNTIME_FUNCTION FunctionEntryEarly = pRuntimeFunctions + MethodIndex; + METHODTOKEN methodToken = METHODTOKEN(pRangeSection, dac_cast(FunctionEntryEarly)); + DWORD offsetFromStartOfFunction = RelativePc - RUNTIME_FUNCTION__BeginAddress(FunctionEntryEarly); + DWORD functionSize = GetCodeManager()->GetFunctionSize(GetGCInfoToken(methodToken)); + if (functionSize < offsetFromStartOfFunction) + return FALSE; + } +#endif + if (ppMethodDesc == NULL && pCodeInfo == NULL) { // Bail early if caller doesn't care about the MethodDesc or EECodeInfo. From b68afecf7f94eee1beb3ad582adf4e77956e95ca Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Tue, 14 Jul 2020 12:24:13 -0700 Subject: [PATCH 5/7] Check to see if IP is stub before querying runtime function structure --- src/coreclr/src/vm/codeman.cpp | 44 ++++++++--------------------- src/coreclr/src/vm/codeman.h | 3 +- src/coreclr/src/vm/jitinterface.cpp | 2 +- 3 files changed, 14 insertions(+), 35 deletions(-) diff --git a/src/coreclr/src/vm/codeman.cpp b/src/coreclr/src/vm/codeman.cpp index ea2cba864dcb35..a075ea4767e6ee 100644 --- a/src/coreclr/src/vm/codeman.cpp +++ b/src/coreclr/src/vm/codeman.cpp @@ -5591,7 +5591,7 @@ BOOL NativeImageJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection, if (iRange == 2) { - int ColdMethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(ImageBase, RelativePc, + int ColdMethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(RelativePc, pLayoutInfo->m_pRuntimeFunctions[2], 0, pLayoutInfo->m_nRuntimeFunctions[2] - 1); @@ -5680,8 +5680,7 @@ BOOL NativeImageJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection, PTR_RUNTIME_FUNCTION FunctionTable = pLayoutInfo->m_pRuntimeFunctions[iRange]; PTR_DWORD pMethodDescs = pLayoutInfo->m_MethodDescs[iRange]; - int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(ImageBase, - RelativePc, + int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(RelativePc, FunctionTable, Low, High); @@ -5809,7 +5808,6 @@ DWORD NativeImageJitManager::GetFuncletStartOffsets(const METHODTOKEN& MethodTok NGenLayoutInfo * pLayoutInfo = JitTokenToZapModule(MethodToken)->GetNGenLayoutInfo(); int iColdMethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod( - moduleBase, (DWORD)(regionInfo.coldStartAddress - moduleBase), pLayoutInfo->m_pRuntimeFunctions[2], 0, @@ -6133,8 +6131,7 @@ DWORD NativeExceptionInfoLookupTable::LookupExceptionInfoRVAForMethod(PTR_CORCOM return 0; } -int NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(TADDR ImageBase, - DWORD RelativePc, +int NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(DWORD RelativePc, PTR_RUNTIME_FUNCTION pRuntimeFunctionTable, int Low, int High) @@ -6181,16 +6178,8 @@ int NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(TADDR ImageBase, if (RelativePc >= pFunctionEntry->BeginAddress) { -#if defined(TARGET_X86) && !defined(UNIX_X86_ABI) && !defined(FEATURE_EH_FUNCLETS) - // On Windows X86, the end offset is handled by the method region code (for ngen), and - // the GCInfo for ReadyToRun -#else - if (RelativePc < RUNTIME_FUNCTION__EndAddress(pFunctionEntry, ImageBase)) -#endif - { - return i; - break; - } + return i; + break; } } } @@ -6790,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; @@ -6802,8 +6797,7 @@ BOOL ReadyToRunJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection, COUNT_T nRuntimeFunctions = pInfo->m_nRuntimeFunctions; PTR_RUNTIME_FUNCTION pRuntimeFunctions = pInfo->m_pRuntimeFunctions; - int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(ImageBase, - RelativePc, + int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(RelativePc, pRuntimeFunctions, 0, nRuntimeFunctions - 1); @@ -6811,20 +6805,6 @@ BOOL ReadyToRunJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection, if (MethodIndex < 0) return FALSE; -#if defined(TARGET_X86) && !defined(UNIX_X86_ABI) && !defined(FEATURE_EH_FUNCLETS) - { - // On Windows X86, the RUNTIME_FUNCTION structure does not encode the end of the function - // Use the GCInfo to find the end of the function and verify that currentPC is in the - // bounds of the function - PTR_RUNTIME_FUNCTION FunctionEntryEarly = pRuntimeFunctions + MethodIndex; - METHODTOKEN methodToken = METHODTOKEN(pRangeSection, dac_cast(FunctionEntryEarly)); - DWORD offsetFromStartOfFunction = RelativePc - RUNTIME_FUNCTION__BeginAddress(FunctionEntryEarly); - DWORD functionSize = GetCodeManager()->GetFunctionSize(GetGCInfoToken(methodToken)); - if (functionSize < offsetFromStartOfFunction) - return FALSE; - } -#endif - if (ppMethodDesc == NULL && pCodeInfo == NULL) { // Bail early if caller doesn't care about the MethodDesc or EECodeInfo. diff --git a/src/coreclr/src/vm/codeman.h b/src/coreclr/src/vm/codeman.h index 3b6381f468294c..ae76b6939da0c6 100644 --- a/src/coreclr/src/vm/codeman.h +++ b/src/coreclr/src/vm/codeman.h @@ -1601,8 +1601,7 @@ class NativeExceptionInfoLookupTable class NativeUnwindInfoLookupTable { public: - static int LookupUnwindInfoForMethod(TADDR ImageBase, - DWORD codeOffset, + static int LookupUnwindInfoForMethod(DWORD codeOffset, PTR_RUNTIME_FUNCTION pRuntimeFunctionTable, int StartIndex, int EndIndex); diff --git a/src/coreclr/src/vm/jitinterface.cpp b/src/coreclr/src/vm/jitinterface.cpp index 385c3735c05d18..99073bec81fa3f 100644 --- a/src/coreclr/src/vm/jitinterface.cpp +++ b/src/coreclr/src/vm/jitinterface.cpp @@ -14596,7 +14596,7 @@ LPVOID EECodeInfo::findNextFunclet (LPVOID pvFuncletStart, SIZE_T Module * pZapModule = ExecutionManager::FindZapModule((TADDR)pvFuncletStart); NGenLayoutInfo * pLayoutInfo = pZapModule->GetNGenLayoutInfo(); - int ColdFunctionIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod((TADDR)uImageBase, (DWORD)((TADDR)pvFuncletStart - uImageBase), + int ColdFunctionIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod((DWORD)((TADDR)pvFuncletStart - uImageBase), pLayoutInfo->m_pRuntimeFunctions[2], 0, pLayoutInfo->m_nRuntimeFunctions[2] - 1); From 3def4ea4a40f86090f4f6c03112f7b1baaf84c5d Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Tue, 14 Jul 2020 12:44:59 -0700 Subject: [PATCH 6/7] Fix location of break statement --- src/coreclr/src/vm/codeman.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/coreclr/src/vm/codeman.cpp b/src/coreclr/src/vm/codeman.cpp index a075ea4767e6ee..ac385b88792410 100644 --- a/src/coreclr/src/vm/codeman.cpp +++ b/src/coreclr/src/vm/codeman.cpp @@ -6175,12 +6175,11 @@ int NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(DWORD RelativePc, if (RelativePc < pNextFunctionEntry->BeginAddress) { PTR_RUNTIME_FUNCTION pFunctionEntry = pRuntimeFunctionTable + i; - if (RelativePc >= pFunctionEntry->BeginAddress) { return i; - break; } + break; } } From f39d18ac422f4266a89293acb1a901663dd714b5 Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Tue, 14 Jul 2020 21:32:30 -0700 Subject: [PATCH 7/7] Address code review feedback --- src/coreclr/src/debug/daccess/nidump.cpp | 6 +++--- src/coreclr/src/vm/codeman.cpp | 5 +++-- src/coreclr/src/vm/codeman.h | 2 +- src/coreclr/src/vm/readytoruninfo.cpp | 2 ++ src/coreclr/src/vm/readytoruninfo.h | 4 ++++ 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/coreclr/src/debug/daccess/nidump.cpp b/src/coreclr/src/debug/daccess/nidump.cpp index c3ca2ff978dea9..5a0bbfd81006f4 100644 --- a/src/coreclr/src/debug/daccess/nidump.cpp +++ b/src/coreclr/src/debug/daccess/nidump.cpp @@ -3412,7 +3412,7 @@ size_t NativeImageDumper::TranslateSymbol(IXCLRDisassemblySupport *dis, { if (pNgenLayout->m_CodeSections[iRange].IsInRange((TADDR)addr)) { - int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(PTR_TO_TADDR(m_decoder.GetBase()), rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1); + int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1); if (MethodIndex >= 0) { #ifdef FEATURE_EH_FUNCLETS @@ -3434,7 +3434,7 @@ size_t NativeImageDumper::TranslateSymbol(IXCLRDisassemblySupport *dis, if (pNgenLayout->m_CodeSections[2].IsInRange((TADDR)addr)) { - int ColdMethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(PTR_TO_TADDR(m_decoder.GetBase()), rva, pNgenLayout->m_pRuntimeFunctions[2], 0, pNgenLayout->m_nRuntimeFunctions[2] - 1); + int ColdMethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[2], 0, pNgenLayout->m_nRuntimeFunctions[2] - 1); if (ColdMethodIndex >= 0) { PTR_RUNTIME_FUNCTION pRuntimeFunction; @@ -6394,7 +6394,7 @@ void NativeImageDumper::EntryPointToString( TADDR pEntryPoint, { if (pNgenLayout->m_CodeSections[iRange].IsInRange(pEntryPoint)) { - int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(PTR_TO_TADDR(m_decoder.GetBase()), rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1); + int MethodIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod(rva, pNgenLayout->m_pRuntimeFunctions[iRange], 0, pNgenLayout->m_nRuntimeFunctions[iRange] - 1); if (MethodIndex >= 0) { #ifdef FEATURE_EH_FUNCLETS diff --git a/src/coreclr/src/vm/codeman.cpp b/src/coreclr/src/vm/codeman.cpp index ac385b88792410..a04894fa77edfa 100644 --- a/src/coreclr/src/vm/codeman.cpp +++ b/src/coreclr/src/vm/codeman.cpp @@ -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(pRangeSection->pHeapListOrZapModule)->GetReadyToRunInfo(); + PTR_ReadyToRunInfo pReadyToRunInfo = dac_cast(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 diff --git a/src/coreclr/src/vm/codeman.h b/src/coreclr/src/vm/codeman.h index ae76b6939da0c6..d90f54df7cd5ac 100644 --- a/src/coreclr/src/vm/codeman.h +++ b/src/coreclr/src/vm/codeman.h @@ -1619,7 +1619,7 @@ class NativeUnwindInfoLookupTable #ifdef FEATURE_READYTORUN -class ReadyToRunJitManager : public IJitManager +class ReadyToRunJitManager final: public IJitManager { VPTR_VTABLE_CLASS(ReadyToRunJitManager, IJitManager) diff --git a/src/coreclr/src/vm/readytoruninfo.cpp b/src/coreclr/src/vm/readytoruninfo.cpp index b5b69edaac27e5..06d238b44b6c58 100644 --- a/src/coreclr/src/vm/readytoruninfo.cpp +++ b/src/coreclr/src/vm/readytoruninfo.cpp @@ -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) { diff --git a/src/coreclr/src/vm/readytoruninfo.h b/src/coreclr/src/vm/readytoruninfo.h index b7ec74769bd954..7a1919aa04b9c9 100644 --- a/src/coreclr/src/vm/readytoruninfo.h +++ b/src/coreclr/src/vm/readytoruninfo.h @@ -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; @@ -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(); }