Skip to content

Commit 82562bb

Browse files
jkoritzinskyjkotas
andauthored
Resolve dllimport.cpp runtimeasync todos (#122466)
Don't allow P/Invokes, FCalls or delegate methods to be marked as "async". Fix async thunks for such methods to be correctly considered as IL methods. Block "async" with UnmanagedCallersOnly. Fixes #121758 --------- Co-authored-by: Jan Kotas <[email protected]>
1 parent 84d9854 commit 82562bb

File tree

16 files changed

+159
-63
lines changed

16 files changed

+159
-63
lines changed

src/coreclr/dlls/mscorrc/mscorrc.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ BEGIN
593593
BFA_MISSING_DELEGATE_METHOD "Missing definition for required runtime implemented delegate method."
594594
BFA_MULT_TYPE_SAME_NAME "Duplicate type with name '%1' in assembly '%2'."
595595
BFA_INVALID_METHOD_TOKEN "Bad method token."
596+
BFA_BAD_ASYNC_METHOD "Bad use of RuntimeAsync flag."
596597
BFA_ECALLS_MUST_BE_IN_SYS_MOD "ECall methods must be packaged into a system module."
597598
BFA_CANT_GET_CLASSLAYOUT "Could not get classlayout."
598599
BFA_CALLCONV_NOT_LOCAL_SIG "Signature is not IMAGE_CEE_CS_CALLCONV_LOCAL_SIG."

src/coreclr/dlls/mscorrc/resource.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@
366366
#define BFA_MISSING_DELEGATE_METHOD 0x2030
367367
#define BFA_MULT_TYPE_SAME_NAME 0x2031
368368
#define BFA_INVALID_METHOD_TOKEN 0x2032
369+
#define BFA_BAD_ASYNC_METHOD 0x2033
369370
#define BFA_ECALLS_MUST_BE_IN_SYS_MOD 0x2034
370371
#define BFA_CANT_GET_CLASSLAYOUT 0x2035
371372
#define BFA_CALLCONV_NOT_LOCAL_SIG 0x2036

src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4284,6 +4284,11 @@ private uint getJitFlags(ref CORJIT_FLAGS flags, uint sizeInBytes)
42844284
ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramGenericMethod, this.MethodBeingCompiled);
42854285
}
42864286

4287+
if (this.MethodBeingCompiled.IsAsync)
4288+
{
4289+
ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramAsync, this.MethodBeingCompiled);
4290+
}
4291+
42874292
#if READYTORUN
42884293
// TODO: enable this check in full AOT
42894294
if (Marshaller.IsMarshallingRequired(this.MethodBeingCompiled.Signature, ((MetadataType)this.MethodBeingCompiled.OwningType).Module, this.MethodBeingCompiled.GetUnmanagedCallersOnlyMethodCallingConventions())) // Only blittable arguments

src/coreclr/tools/Common/TypeSystem/Common/ExceptionStringID.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public enum ExceptionStringID
3939
InvalidProgramGenericMethod,
4040
InvalidProgramNonBlittableTypes,
4141
InvalidProgramMultipleCallConv,
42+
InvalidProgramAsync,
4243

4344
// BadImageFormatException
4445
BadImageFormatGeneric,

src/coreclr/tools/Common/TypeSystem/Common/Properties/Resources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@
156156
<data name="FileLoadErrorGeneric" xml:space="preserve">
157157
<value>Failed to load assembly '{0}'</value>
158158
</data>
159+
<data name="InvalidProgramAsync" xml:space="preserve">
160+
<value>UnmanagedCallersOnly attribute specified on async method '{0}'</value>
161+
</data>
159162
<data name="InvalidProgramDefault" xml:space="preserve">
160163
<value>Invalid IL or CLR metadata</value>
161164
</data>

src/coreclr/tools/Common/TypeSystem/IL/NativeAotILProvider.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ private static MethodIL TryGetRuntimeImplementedMethodIL(MethodDesc method)
2323

2424
Debug.Assert(method.IsRuntimeImplemented);
2525

26+
if (method.IsAsync)
27+
{
28+
ThrowHelper.ThrowBadImageFormatException();
29+
}
30+
2631
TypeDesc owningType = method.OwningType;
2732

2833
if (owningType.IsDelegate)

src/coreclr/tools/Common/TypeSystem/Interop/UnmanagedCallingConventions.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public static UnmanagedCallingConventions GetPInvokeMethodCallingConventions(thi
103103
{
104104
Debug.Assert(method.IsPInvoke);
105105

106-
UnmanagedCallingConventions result;
106+
UnmanagedCallingConventions result = 0;
107107

108108
if (method is Internal.IL.Stubs.PInvokeTargetNativeMethod pinvokeTarget)
109109
method = pinvokeTarget.Target;
@@ -116,9 +116,9 @@ public static UnmanagedCallingConventions GetPInvokeMethodCallingConventions(thi
116116
&& (int)MethodSignatureFlags.UnmanagedCallingConventionThisCall == (int)UnmanagedCallingConventions.Thiscall);
117117
result = (UnmanagedCallingConventions)unmanagedCallConv;
118118
}
119-
else
119+
else if (method is EcmaMethod ecmaMethod)
120120
{
121-
CustomAttributeValue<TypeDesc>? unmanagedCallConvAttribute = ((EcmaMethod)method).GetDecodedCustomAttribute("System.Runtime.InteropServices", "UnmanagedCallConvAttribute");
121+
CustomAttributeValue<TypeDesc>? unmanagedCallConvAttribute = ecmaMethod.GetDecodedCustomAttribute("System.Runtime.InteropServices", "UnmanagedCallConvAttribute");
122122
if (unmanagedCallConvAttribute != null)
123123
{
124124
result = GetUnmanagedCallingConventionFromAttribute(unmanagedCallConvAttribute.Value, method.Context);
@@ -127,10 +127,10 @@ public static UnmanagedCallingConventions GetPInvokeMethodCallingConventions(thi
127127
{
128128
result = GetPlatformDefaultUnmanagedCallingConvention(method.Context);
129129
}
130-
}
131130

132-
if (method.HasCustomAttribute("System.Runtime.InteropServices", "SuppressGCTransitionAttribute"))
133-
result |= UnmanagedCallingConventions.IsSuppressGcTransition;
131+
if (method.HasCustomAttribute("System.Runtime.InteropServices", "SuppressGCTransitionAttribute"))
132+
result |= UnmanagedCallingConventions.IsSuppressGcTransition;
133+
}
134134

135135
return result;
136136
}

src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/PInvokeILProvider.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ public PInvokeILProvider(PInvokeILEmitterConfiguration pInvokeILEmitterConfigura
2525

2626
public override MethodIL GetMethodIL(MethodDesc method)
2727
{
28+
if (method.IsAsync)
29+
{
30+
ThrowHelper.ThrowBadImageFormatException();
31+
}
2832
return PInvokeILEmitter.EmitIL(method, _pInvokeILEmitterConfiguration, _interopStateManager);
2933
}
3034

src/coreclr/vm/comdelegate.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,6 +2045,10 @@ void COMDelegate::ThrowIfInvalidUnmanagedCallersOnlyUsage(MethodDesc* pMD)
20452045
if (pMD->HasClassOrMethodInstantiation())
20462046
EX_THROW(EEResourceException, (kInvalidProgramException, W("InvalidProgram_GenericMethod")));
20472047

2048+
// No async methods
2049+
if (pMD->IsAsyncMethod())
2050+
EX_THROW(EEResourceException, (kInvalidProgramException, W("InvalidProgram_AsyncMethod")));
2051+
20482052
// Arguments - Scenarios involving UnmanagedCallersOnly are handled during the jit.
20492053
bool unmanagedCallersOnlyRequiresMarshalling = false;
20502054
if (PInvoke::MarshalingRequired(pMD, NULL, NULL, NULL, unmanagedCallersOnlyRequiresMarshalling))

src/coreclr/vm/dllimport.cpp

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ StubSigDesc::StubSigDesc(MethodDesc *pMD)
100100
GC_NOTRIGGER;
101101
SUPPORTS_DAC;
102102
PRECONDITION(pMD != NULL);
103+
PRECONDITION(!pMD->IsAsyncMethod());
103104
}
104105
CONTRACTL_END;
105106

@@ -108,9 +109,6 @@ StubSigDesc::StubSigDesc(MethodDesc *pMD)
108109
m_sig = pMD->GetSignature();
109110
m_pModule = pMD->GetModule(); // Used for token resolution.
110111

111-
// TODO: (async) revisit and examine if this needs to be supported somehow
112-
_ASSERTE(!pMD->IsAsyncMethod());
113-
114112
m_tkMethodDef = pMD->GetMemberDef();
115113
SigTypeContext::InitTypeContext(pMD, &m_typeContext);
116114
m_pMetadataModule = pMD->GetModule();
@@ -1131,7 +1129,6 @@ class ILStubState : public StubState
11311129
DWORD dwToken = 0;
11321130
if (pTargetMD)
11331131
{
1134-
// TODO: (async) revisit and examine if this needs to be supported somehow
11351132
_ASSERTE(!pTargetMD->IsAsyncVariantMethod());
11361133
dwToken = pTargetMD->GetMemberDef();
11371134
}
@@ -2764,6 +2761,10 @@ void PInvokeStaticSigInfo::DllImportInit(
27642761

27652762
PRECONDITION(CheckPointer(pMD));
27662763

2764+
// P/Invoke methods should never be marked as async.
2765+
// This should be blocked in the class loader.
2766+
PRECONDITION(!pMD->IsAsyncMethod());
2767+
27672768
// These preconditions to prevent multithreaded regression
27682769
// where pMD->m_szLibName was passed in directly, cleared
27692770
// by this API, then accessed on another thread before being reset here.
@@ -2779,9 +2780,6 @@ void PInvokeStaticSigInfo::DllImportInit(
27792780
IMDInternalImport *pInternalImport = pMD->GetMDImport();
27802781
CorPinvokeMap mappingFlags = pmMaxValue;
27812782
mdModuleRef modref = mdModuleRefNil;
2782-
// TODO: (async) revisit and examine if this needs to be supported somehow
2783-
if (pMD->IsAsyncMethod())
2784-
ThrowHR(COR_E_NOTSUPPORTED);
27852783

27862784
if (FAILED(pInternalImport->GetPinvokeMap(pMD->GetMemberDef(), (DWORD*)&mappingFlags, ppEntryPointName, &modref)))
27872785
{
@@ -3053,16 +3051,15 @@ namespace
30533051
STANDARD_VM_CHECK;
30543052
PRECONDITION(pMD != NULL);
30553053
PRECONDITION(pMD->IsPInvoke());
3054+
PRECONDITION(!pMD->IsAsyncMethod());
30563055
PRECONDITION(callConv != NULL);
30573056
}
30583057
CONTRACTL_END;
30593058

30603059
CorInfoCallConvExtension callConvLocal;
30613060
IMDInternalImport* pInternalImport = pMD->GetMDImport();
30623061
CorPinvokeMap mappingFlags = pmMaxValue;
3063-
// TODO: (async) revisit and examine if this needs to be supported somehow
3064-
if (pMD->IsAsyncMethod())
3065-
ThrowHR(COR_E_NOTSUPPORTED);
3062+
30663063

30673064
HRESULT hr = pInternalImport->GetPinvokeMap(pMD->GetMemberDef(), (DWORD*)&mappingFlags, NULL /*pszImportName*/, NULL /*pmrImportDLL*/);
30683065
if (FAILED(hr))
@@ -3249,6 +3246,12 @@ BOOL PInvoke::MarshalingRequired(
32493246
{
32503247
STANDARD_VM_CHECK;
32513248
PRECONDITION(pMD != NULL || (!sigPointer.IsNull() && pModule != NULL));
3249+
3250+
// We should never see an async method here.
3251+
// Delegate Invoke methods should never be async.
3252+
// Async P/Invokes are not supported.
3253+
// Async UnmanagedCallersOnly methods are not supported.
3254+
PRECONDITION(pMD == NULL || !pMD->IsAsyncMethod());
32523255
}
32533256
CONTRACTL_END;
32543257

@@ -3324,10 +3327,6 @@ BOOL PInvoke::MarshalingRequired(
33243327
mdMethodDef methodToken = mdMethodDefNil;
33253328
if (pMD != NULL)
33263329
{
3327-
// TODO: (async) revisit and examine if this needs to be supported somehow
3328-
if (pMD->IsAsyncMethod())
3329-
ThrowHR(COR_E_NOTSUPPORTED);
3330-
33313330
methodToken = pMD->GetMemberDef();
33323331
}
33333332
CollateParamTokens(pMDImport, methodToken, numArgs - 1, pParamTokenArray);
@@ -6080,12 +6079,10 @@ static void GetILStubForCalli(VASigCookie* pVASigCookie, MethodDesc* pMD)
60806079

60816080
if (pMD != NULL)
60826081
{
6082+
_ASSERTE(pMD->IsPInvoke());
6083+
_ASSERTE(!pMD->IsAsyncMethod());
60836084
PInvokeStaticSigInfo sigInfo(pMD);
60846085

6085-
// TODO: (async) revisit and examine if this needs to be supported somehow
6086-
if (pMD->IsAsyncMethod())
6087-
ThrowHR(COR_E_NOTSUPPORTED);
6088-
60896086
md = pMD->GetMemberDef();
60906087
nlFlags = sigInfo.GetLinkFlags();
60916088
nlType = sigInfo.GetCharSet();

0 commit comments

Comments
 (0)