Skip to content

Commit a2f46fc

Browse files
[clr-interp] Fix interop calls when PInvokePrecodeImport thunks are involved (#120227)
- Handle the case where the dispatch may get upgraded from a PInvokeImportThunk to a direct function pointer
1 parent 691e950 commit a2f46fc

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

src/coreclr/vm/callstubgenerator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,14 @@ struct CallStubHeader
4242
LIMITED_METHOD_CONTRACT;
4343

4444
_ASSERTE(target != 0);
45-
Routines[NumRoutines - 1] = target;
45+
VolatileStore(&Routines[NumRoutines - 1], target);
4646
}
4747

4848
PCODE GetTarget()
4949
{
5050
LIMITED_METHOD_CONTRACT;
5151

52-
return Routines[NumRoutines - 1];
52+
return VolatileLoadWithoutBarrier(&Routines[NumRoutines - 1]);
5353
}
5454

5555
size_t GetSize()

src/coreclr/vm/interpexec.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,33 @@ static CallStubHeader *UpdateCallStubForMethod(MethodDesc *pMD, PCODE target)
104104
return header;
105105
}
106106

107+
MethodDesc* GetTargetPInvokeMethodDesc(PCODE target)
108+
{
109+
CONTRACTL
110+
{
111+
THROWS;
112+
MODE_ANY;
113+
PRECONDITION(CheckPointer((void*)target));
114+
}
115+
CONTRACTL_END
116+
117+
GCX_PREEMP();
118+
119+
RangeSection * pRS = ExecutionManager::FindCodeRange(target, ExecutionManager::GetScanFlags());
120+
if (pRS != NULL && pRS->_flags & RangeSection::RANGE_SECTION_RANGELIST)
121+
{
122+
if (pRS->_pRangeList->GetCodeBlockKind() == STUB_CODE_BLOCK_STUBPRECODE)
123+
{
124+
if (((StubPrecode*)target)->GetType() == PRECODE_PINVOKE_IMPORT)
125+
{
126+
return dac_cast<PTR_MethodDesc>(((PInvokeImportPrecode*)target)->GetMethodDesc());
127+
}
128+
}
129+
}
130+
131+
return NULL;
132+
}
133+
107134
void InvokeManagedMethod(MethodDesc *pMD, int8_t *pArgs, int8_t *pRet, PCODE target)
108135
{
109136
CONTRACTL
@@ -124,7 +151,22 @@ void InvokeManagedMethod(MethodDesc *pMD, int8_t *pArgs, int8_t *pRet, PCODE tar
124151

125152
if (target != (PCODE)NULL)
126153
{
127-
_ASSERTE(pHeader->GetTarget() == target);
154+
PCODE headerTarget = pHeader->GetTarget();
155+
if (target != headerTarget)
156+
{
157+
#ifdef DEBUG
158+
// For pinvokes we may have a PInvokeImportPrecode as a pointer, and need to use passed in target preferentially
159+
// Since on multiple threads we may be racing to use this method, it is possible that the current target could be
160+
// the PInvokeImportPrecode or the actual target method, so we should allow either of them to match.
161+
MethodDesc *pMDTarget = GetTargetPInvokeMethodDesc(target);
162+
MethodDesc *pMDHeaderTarget = GetTargetPInvokeMethodDesc(headerTarget);
163+
164+
_ASSERTE(pMDTarget == NULL || pMDHeaderTarget == NULL);
165+
_ASSERTE(pMDTarget == NULL || pMDTarget == pMD);
166+
_ASSERTE(pMDHeaderTarget == NULL || pMDHeaderTarget == pMD);
167+
#endif // DEBUG
168+
pHeader->SetTarget(target);
169+
}
128170
}
129171

130172
pHeader->Invoke(pHeader->Routines, pArgs, pRet, pHeader->TotalStackSize);

0 commit comments

Comments
 (0)