From c9029a200df89f5598c5f8e77963b6f901e264fe Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Mon, 14 Jul 2025 22:05:04 +0200 Subject: [PATCH 1/2] Fix ExecutionManager::GetCodeMethodDesc for interpreter The ExecutionManager::GetCodeMethodDesc expects that the address passed to it is an address of actual JIT/AOT or interpreter generated code. However, it is sometimes passed an address of the interpreter precode, e.g. in the case when called by the MethodTable::GetMethodDescForSlotAddress. The VTable slots need to point to the interpreter stub so that these methods can be called by virtual calls from native code. This change adds a check for the interpreter precode to the ExecutionManager::GetCodeMethodDesc and extracts the MethodDesc from the interpreter data in case it is passed the precode address. --- src/coreclr/vm/codeman.cpp | 13 ++++++++++++- src/coreclr/vm/precode.cpp | 13 ++++++++++++- src/coreclr/vm/precode.h | 15 +++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index cdb8a2ddbef47f..03e14e90796e80 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -5088,6 +5088,17 @@ MethodDesc * ExecutionManager::GetCodeMethodDesc(PCODE currentPC) } CONTRACTL_END +#ifdef FEATURE_INTERPRETER + // For interpreted methods, the currentPC can point to the InterpreterPrecode. So we need to get the MethodDesc from it, + // the EECodeInfo works only for the actual IR bytecode. + PTR_Precode pPrecode = Precode::GetPrecodeFromEntryPoint(currentPC); + if (pPrecode != NULL && pPrecode->GetType() == InterpreterPrecode::Type) + { + // If we are in an interpreter precode, we get the MethodDesc from the precode + return pPrecode->GetMethodDesc(); + } +#endif // FEATURE_INTERPRETER + EECodeInfo codeInfo(currentPC); if (!codeInfo.IsValid()) return NULL; @@ -6396,7 +6407,7 @@ size_t ReadyToRunJitManager::WalkILOffsets( BoundsType boundsType, void* pContext, size_t (* pfnWalkILOffsets)(ICorDebugInfo::OffsetMapping *pOffsetMapping, void *pContext)) -{ +{ CONTRACTL { THROWS; // on OOM. GC_NOTRIGGER; // getting vars shouldn't trigger diff --git a/src/coreclr/vm/precode.cpp b/src/coreclr/vm/precode.cpp index bafa39a9a9104a..12de5e49105349 100644 --- a/src/coreclr/vm/precode.cpp +++ b/src/coreclr/vm/precode.cpp @@ -10,6 +10,7 @@ #include "common.h" #include "dllimportcallback.h" +#include "../interpreter/interpretershared.h" #ifdef FEATURE_PERFMAP #include "perfmap.h" @@ -158,7 +159,7 @@ MethodDesc* Precode::GetMethodDesc(BOOL fSpeculative /*= FALSE*/) break; #ifdef FEATURE_INTERPRETER case PRECODE_INTERPRETER: - return NULL; + pMD = AsInterpreterPrecode()->GetMethodDesc(); break; #endif // FEATURE_INTERPRETER @@ -180,6 +181,16 @@ MethodDesc* Precode::GetMethodDesc(BOOL fSpeculative /*= FALSE*/) return (PTR_MethodDesc)pMD; } +#ifdef FEATURE_INTERPRETER +TADDR InterpreterPrecode::GetMethodDesc() +{ + LIMITED_METHOD_DAC_CONTRACT; + + InterpByteCodeStart* pInterpreterCode = dac_cast(GetData()->ByteCodeAddr); + return (TADDR)pInterpreterCode->Method->methodHnd; +} +#endif // FEATURE_INTERPRETER + BOOL Precode::IsPointingToPrestub(PCODE target) { CONTRACTL diff --git a/src/coreclr/vm/precode.h b/src/coreclr/vm/precode.h index 6a5abf0e099de6..8e96b3064c4ecc 100644 --- a/src/coreclr/vm/precode.h +++ b/src/coreclr/vm/precode.h @@ -335,7 +335,12 @@ struct InterpreterPrecode LIMITED_METHOD_CONTRACT; return (InterpreterPrecode*)PCODEToPINSTR(entryPoint); } + + TADDR GetMethodDesc(); }; + +typedef DPTR(InterpreterPrecode) PTR_InterpreterPrecode; + #endif // FEATURE_INTERPRETER #ifdef HAS_FIXUP_PRECODE @@ -593,6 +598,16 @@ class Precode { } #endif // HAS_THISPTR_RETBUF_PRECODE +#ifdef FEATURE_INTERPRETER + InterpreterPrecode* AsInterpreterPrecode() + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return dac_cast(this); + } +#endif // FEATURE_INTERPRETER + TADDR GetStart() { SUPPORTS_DAC; From 54168216ed1dc3df3e16e15868dda8ad65e92893 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Tue, 15 Jul 2025 00:00:32 +0200 Subject: [PATCH 2/2] Revert changes in codeman.cpp --- src/coreclr/vm/codeman.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index 03e14e90796e80..cdb8a2ddbef47f 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -5088,17 +5088,6 @@ MethodDesc * ExecutionManager::GetCodeMethodDesc(PCODE currentPC) } CONTRACTL_END -#ifdef FEATURE_INTERPRETER - // For interpreted methods, the currentPC can point to the InterpreterPrecode. So we need to get the MethodDesc from it, - // the EECodeInfo works only for the actual IR bytecode. - PTR_Precode pPrecode = Precode::GetPrecodeFromEntryPoint(currentPC); - if (pPrecode != NULL && pPrecode->GetType() == InterpreterPrecode::Type) - { - // If we are in an interpreter precode, we get the MethodDesc from the precode - return pPrecode->GetMethodDesc(); - } -#endif // FEATURE_INTERPRETER - EECodeInfo codeInfo(currentPC); if (!codeInfo.IsValid()) return NULL; @@ -6407,7 +6396,7 @@ size_t ReadyToRunJitManager::WalkILOffsets( BoundsType boundsType, void* pContext, size_t (* pfnWalkILOffsets)(ICorDebugInfo::OffsetMapping *pOffsetMapping, void *pContext)) -{ +{ CONTRACTL { THROWS; // on OOM. GC_NOTRIGGER; // getting vars shouldn't trigger