1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//
5// File: ILStubResolver.cpp
6//
7
8//
9
10
11#include "common.h"
12
13#include "field.h"
14
15// returns pointer to IL code
16BYTE* ILStubResolver::GetCodeInfo(unsigned* pCodeSize, unsigned* pStackSize, CorInfoOptions* pOptions, unsigned* pEHSize)
17{
18 CONTRACT(BYTE*)
19 {
20 STANDARD_VM_CHECK;
21 PRECONDITION(CheckPointer(pCodeSize));
22 PRECONDITION(CheckPointer(pStackSize));
23 PRECONDITION(CheckPointer(pOptions));
24 PRECONDITION(CheckPointer(pEHSize));
25 PRECONDITION(CheckPointer(m_pCompileTimeState));
26 POSTCONDITION(CheckPointer(RETVAL));
27 }
28 CONTRACT_END;
29
30#ifndef DACCESS_COMPILE
31 CORINFO_METHOD_INFO methodInfo;
32 getMethodInfoILMethodHeaderHelper(&m_pCompileTimeState->m_ILHeader, &methodInfo);
33
34 *pCodeSize = methodInfo.ILCodeSize;
35 *pStackSize = methodInfo.maxStack;
36 *pOptions = methodInfo.options;
37 *pEHSize = methodInfo.EHcount;
38
39 RETURN methodInfo.ILCode;
40#else // DACCESS_COMPILE
41 DacNotImpl();
42 RETURN NULL;
43#endif // DACCESS_COMPILE
44}
45
46// static
47LPCUTF8 ILStubResolver::GetStubClassName(MethodDesc* pMD)
48{
49 CONTRACTL
50 {
51 MODE_ANY;
52 GC_NOTRIGGER;
53 NOTHROW;
54 SUPPORTS_DAC;
55 PRECONDITION(pMD->IsILStub());
56 }
57 CONTRACTL_END;
58
59 return "ILStubClass";
60}
61
62LPCUTF8 ILStubResolver::GetStubMethodName()
63{
64 CONTRACTL
65 {
66 MODE_ANY;
67 GC_NOTRIGGER;
68 NOTHROW;
69 }
70 CONTRACTL_END;
71
72 switch (m_type)
73 {
74 case CLRToNativeInteropStub: return "IL_STUB_PInvoke";
75 case CLRToCOMInteropStub: return "IL_STUB_CLRtoCOM";
76 case CLRToWinRTInteropStub: return "IL_STUB_CLRtoWinRT";
77 case NativeToCLRInteropStub: return "IL_STUB_ReversePInvoke";
78 case COMToCLRInteropStub: return "IL_STUB_COMtoCLR";
79 case WinRTToCLRInteropStub: return "IL_STUB_WinRTtoCLR";
80#ifdef FEATURE_ARRAYSTUB_AS_IL
81 case ArrayOpStub: return "IL_STUB_Array";
82#endif
83#ifdef FEATURE_MULTICASTSTUB_AS_IL
84 case MulticastDelegateStub: return "IL_STUB_MulticastDelegate_Invoke";
85#endif
86#ifdef FEATURE_STUBS_AS_IL
87 case UnboxingILStub: return "IL_STUB_UnboxingStub";
88 case InstantiatingStub: return "IL_STUB_InstantiatingStub";
89 case SecureDelegateStub: return "IL_STUB_SecureDelegate_Invoke";
90#endif
91 default:
92 UNREACHABLE_MSG("Unknown stub type");
93 }
94}
95
96void ILStubResolver::GetJitContext(SecurityControlFlags* pSecurityControlFlags,
97 TypeHandle* pTypeOwner)
98{
99 CONTRACTL
100 {
101 STANDARD_VM_CHECK;
102 PRECONDITION(CheckPointer(pSecurityControlFlags));
103 PRECONDITION(CheckPointer(pTypeOwner));
104 }
105 CONTRACTL_END;
106
107 *pSecurityControlFlags = DynamicResolver::SkipVisibilityChecks;
108 *pTypeOwner = TypeHandle();
109}
110
111ChunkAllocator* ILStubResolver::GetJitMetaHeap()
112{
113 LIMITED_METHOD_CONTRACT;
114 _ASSERTE(FALSE);
115 return NULL;
116}
117
118SigPointer
119ILStubResolver::GetLocalSig()
120{
121 STANDARD_VM_CONTRACT;
122
123 return SigPointer(
124 m_pCompileTimeState->m_ILHeader.LocalVarSig,
125 m_pCompileTimeState->m_ILHeader.cbLocalVarSig);
126}
127
128OBJECTHANDLE ILStubResolver::ConstructStringLiteral(mdToken token)
129{
130 STANDARD_VM_CONTRACT;
131 _ASSERTE(FALSE);
132 return NULL;
133}
134
135BOOL ILStubResolver::IsValidStringRef(mdToken metaTok)
136{
137 STANDARD_VM_CONTRACT;
138 _ASSERTE(FALSE);
139 return FALSE;
140}
141
142void ILStubResolver::ResolveToken(mdToken token, TypeHandle * pTH, MethodDesc ** ppMD, FieldDesc ** ppFD)
143{
144 STANDARD_VM_CONTRACT;
145
146 *pTH = NULL;
147 *ppMD = NULL;
148 *ppFD = NULL;
149
150 switch (TypeFromToken(token))
151 {
152 case mdtMethodDef:
153 {
154 MethodDesc* pMD = m_pCompileTimeState->m_tokenLookupMap.LookupMethodDef(token);
155 _ASSERTE(pMD);
156 *ppMD = pMD;
157 *pTH = TypeHandle(pMD->GetMethodTable());
158 }
159 break;
160
161 case mdtTypeDef:
162 {
163 TypeHandle typeHnd = m_pCompileTimeState->m_tokenLookupMap.LookupTypeDef(token);
164 _ASSERTE(!typeHnd.IsNull());
165 *pTH = typeHnd;
166 }
167 break;
168
169 case mdtFieldDef:
170 {
171 FieldDesc* pFD = m_pCompileTimeState->m_tokenLookupMap.LookupFieldDef(token);
172 _ASSERTE(pFD);
173 *ppFD = pFD;
174 *pTH = TypeHandle(pFD->GetEnclosingMethodTable());
175 }
176 break;
177
178 default:
179 UNREACHABLE_MSG("unexpected metadata token type");
180 }
181}
182
183//---------------------------------------------------------------------------------------
184//
185SigPointer
186ILStubResolver::ResolveSignature(
187 mdToken token)
188{
189 STANDARD_VM_CONTRACT;
190 CONSISTENCY_CHECK_MSG(token == TOKEN_ILSTUB_TARGET_SIG, "IL stubs do not support any other signature tokens!");
191
192 return m_pCompileTimeState->m_StubTargetMethodSig;
193}
194
195//---------------------------------------------------------------------------------------
196//
197SigPointer
198ILStubResolver::ResolveSignatureForVarArg(
199 mdToken token)
200{
201 STANDARD_VM_CONTRACT;
202 _ASSERTE(FALSE);
203 return SigPointer();
204}
205
206//---------------------------------------------------------------------------------------
207//
208void ILStubResolver::GetEHInfo(unsigned EHnumber, CORINFO_EH_CLAUSE* clause)
209{
210 CONTRACTL
211 {
212 STANDARD_VM_CHECK;
213 PRECONDITION(CheckPointer(m_pCompileTimeState));
214 PRECONDITION(CheckPointer(m_pCompileTimeState->m_ILHeader.EH));
215 PRECONDITION(EHnumber < m_pCompileTimeState->m_ILHeader.EH->EHCount());
216 }
217 CONTRACTL_END;
218
219 COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehClause;
220 const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo;
221 ehInfo = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)m_pCompileTimeState->m_ILHeader.EH->EHClause(EHnumber, &ehClause);
222 clause->Flags = (CORINFO_EH_CLAUSE_FLAGS)ehInfo->GetFlags();
223 clause->TryOffset = ehInfo->GetTryOffset();
224 clause->TryLength = ehInfo->GetTryLength();
225 clause->HandlerOffset = ehInfo->GetHandlerOffset();
226 clause->HandlerLength = ehInfo->GetHandlerLength();
227 clause->ClassToken = ehInfo->GetClassToken();
228 clause->FilterOffset = ehInfo->GetFilterOffset();
229}
230
231bool ILStubResolver::IsNativeToCLRInteropStub()
232{
233 return (m_type == NativeToCLRInteropStub);
234}
235
236void ILStubResolver::SetStubType(ILStubType stubType)
237{
238 LIMITED_METHOD_CONTRACT;
239 m_type = stubType;
240}
241
242void ILStubResolver::SetStubMethodDesc(MethodDesc* pStubMD)
243{
244 LIMITED_METHOD_CONTRACT;
245 m_pStubMD = PTR_MethodDesc(pStubMD);
246}
247
248void ILStubResolver::SetStubTargetMethodDesc(MethodDesc* pStubTargetMD)
249{
250 LIMITED_METHOD_CONTRACT;
251 m_pStubTargetMD = PTR_MethodDesc(pStubTargetMD);
252}
253
254
255//---------------------------------------------------------------------------------------
256//
257void
258ILStubResolver::SetStubTargetMethodSig(
259 PCCOR_SIGNATURE pStubTargetMethodSig,
260 DWORD cbStubTargetSigLength)
261{
262 CONTRACTL
263 {
264 STANDARD_VM_CHECK;
265 PRECONDITION(CheckPointer(m_pCompileTimeState));
266 }
267 CONTRACTL_END;
268
269 NewHolder<BYTE> pNewSig = new BYTE[cbStubTargetSigLength];
270
271 memcpyNoGCRefs((void *)pNewSig, pStubTargetMethodSig, cbStubTargetSigLength);
272
273 m_pCompileTimeState->m_StubTargetMethodSig = SigPointer(pNewSig, cbStubTargetSigLength);
274 pNewSig.SuppressRelease();
275}
276
277//---------------------------------------------------------------------------------------
278//
279MethodDesc *
280ILStubResolver::GetStubTargetMethodDesc()
281{
282 LIMITED_METHOD_CONTRACT;
283 return m_pStubTargetMD;
284}
285
286MethodDesc* ILStubResolver::GetStubMethodDesc()
287{
288 LIMITED_METHOD_CONTRACT;
289 return m_pStubMD;
290}
291
292ILStubResolver::ILStubResolver() :
293 m_pCompileTimeState(dac_cast<PTR_CompileTimeState>(ILNotYetGenerated)),
294 m_pStubMD(dac_cast<PTR_MethodDesc>(nullptr)),
295 m_pStubTargetMD(dac_cast<PTR_MethodDesc>(nullptr)),
296 m_type(Unassigned),
297 m_jitFlags()
298{
299 LIMITED_METHOD_CONTRACT;
300
301}
302
303//---------------------------------------------------------------------------------------
304//
305COR_ILMETHOD_DECODER *
306ILStubResolver::AllocGeneratedIL(
307 size_t cbCode,
308 DWORD cbLocalSig,
309 UINT maxStack)
310{
311 STANDARD_VM_CONTRACT;
312
313#if !defined(DACCESS_COMPILE)
314 _ASSERTE(0 != cbCode);
315
316 NewHolder<BYTE> pNewILCodeBuffer = NULL;
317 NewHolder<BYTE> pNewLocalSig = NULL;
318 NewHolder<CompileTimeState> pNewCompileTimeState = NULL;
319
320 pNewCompileTimeState = (CompileTimeState *)new BYTE[sizeof(CompileTimeState)];
321 memset(pNewCompileTimeState, 0, sizeof(CompileTimeState));
322
323 pNewILCodeBuffer = new BYTE[cbCode];
324
325 if (0 != cbLocalSig)
326 {
327 pNewLocalSig = new BYTE[cbLocalSig];
328 }
329
330 COR_ILMETHOD_DECODER* pILHeader = &pNewCompileTimeState->m_ILHeader;
331
332 pILHeader->Flags = 0;
333 pILHeader->CodeSize = (DWORD)cbCode;
334 pILHeader->MaxStack = maxStack;
335 pILHeader->EH = 0;
336 pILHeader->Sect = 0;
337 pILHeader->Code = pNewILCodeBuffer;
338 pILHeader->LocalVarSig = pNewLocalSig;
339 pILHeader->cbLocalVarSig = cbLocalSig;
340
341#ifdef _DEBUG
342 LPVOID pPrevCompileTimeState =
343#endif // _DEBUG
344 FastInterlockExchangePointer(&m_pCompileTimeState, pNewCompileTimeState.GetValue());
345 CONSISTENCY_CHECK(ILNotYetGenerated == (UINT_PTR)pPrevCompileTimeState);
346
347 pNewLocalSig.SuppressRelease();
348 pNewILCodeBuffer.SuppressRelease();
349 pNewCompileTimeState.SuppressRelease();
350
351 return pILHeader;
352
353#else // DACCESS_COMPILE
354 DacNotImpl();
355 return NULL;
356
357#endif // DACCESS_COMPILE
358} // ILStubResolver::AllocGeneratedIL
359
360//---------------------------------------------------------------------------------------
361//
362COR_ILMETHOD_DECODER* ILStubResolver::GetILHeader()
363{
364 CONTRACTL
365 {
366 MODE_ANY;
367 THROWS;
368 GC_NOTRIGGER;
369 PRECONDITION(CheckPointer(m_pCompileTimeState));
370 }
371 CONTRACTL_END;
372
373 return &m_pCompileTimeState->m_ILHeader;
374}
375
376COR_ILMETHOD_SECT_EH* ILStubResolver::AllocEHSect(size_t nClauses)
377{
378 STANDARD_VM_CONTRACT;
379
380 if (nClauses >= 1)
381 {
382 size_t cbSize = sizeof(COR_ILMETHOD_SECT_EH)
383 - sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT)
384 + (nClauses * sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT));
385 m_pCompileTimeState->m_pEHSect = (COR_ILMETHOD_SECT_EH*) new BYTE[cbSize];
386 CONSISTENCY_CHECK(NULL == m_pCompileTimeState->m_ILHeader.EH);
387 m_pCompileTimeState->m_ILHeader.EH = m_pCompileTimeState->m_pEHSect;
388 return m_pCompileTimeState->m_pEHSect;
389 }
390 else
391 {
392 return NULL;
393 }
394}
395
396
397void ILStubResolver::FreeCompileTimeState()
398{
399 CONTRACTL
400 {
401 NOTHROW;
402 GC_NOTRIGGER;
403 MODE_ANY;
404 }
405 CONTRACTL_END;
406
407 if ((ILNotYetGenerated == dac_cast<TADDR>(m_pCompileTimeState)) ||
408 (ILGeneratedAndFreed == dac_cast<TADDR>(m_pCompileTimeState)))
409 {
410 return;
411 }
412
413 ClearCompileTimeState(ILGeneratedAndFreed);
414}
415
416//---------------------------------------------------------------------------------------
417//
418void
419ILStubResolver::ClearCompileTimeState(CompileTimeStatePtrSpecialValues newState)
420{
421 CONTRACTL
422 {
423 NOTHROW;
424 GC_NOTRIGGER;
425 MODE_ANY;
426 }
427 CONTRACTL_END;
428
429 //
430 // See allocations in AllocGeneratedIL and SetStubTargetMethodSig
431 //
432
433 COR_ILMETHOD_DECODER * pILHeader = &m_pCompileTimeState->m_ILHeader;
434
435 CONSISTENCY_CHECK(NULL != pILHeader->Code);
436 delete[] pILHeader->Code;
437
438 if (NULL != pILHeader->LocalVarSig)
439 {
440 delete[] pILHeader->LocalVarSig;
441 }
442
443 if (!m_pCompileTimeState->m_StubTargetMethodSig.IsNull())
444 {
445 delete[] m_pCompileTimeState->m_StubTargetMethodSig.GetPtr();
446 }
447
448 if (NULL != m_pCompileTimeState->m_pEHSect)
449 {
450 delete[] m_pCompileTimeState->m_pEHSect;
451 }
452
453 delete m_pCompileTimeState;
454
455 FastInterlockExchangePointer(&m_pCompileTimeState, dac_cast<PTR_CompileTimeState>((TADDR)newState));
456} // ILStubResolver::ClearCompileTimeState
457
458//---------------------------------------------------------------------------------------
459//
460void
461ILStubResolver::SetTokenLookupMap(
462 TokenLookupMap * pMap)
463{
464 CONTRACTL
465 {
466 STANDARD_VM_CHECK;
467 PRECONDITION(CheckPointer(m_pCompileTimeState));
468 }
469 CONTRACTL_END;
470
471 // run copy ctor
472 new (&m_pCompileTimeState->m_tokenLookupMap) TokenLookupMap(pMap);
473}
474
475bool ILStubResolver::IsCompiled()
476{
477 LIMITED_METHOD_CONTRACT;
478 return (dac_cast<TADDR>(m_pCompileTimeState) == ILGeneratedAndFreed);
479}
480
481bool ILStubResolver::IsILGenerated()
482{
483 return (dac_cast<TADDR>(m_pCompileTimeState) != ILNotYetGenerated);
484}
485
486void ILStubResolver::SetJitFlags(CORJIT_FLAGS jitFlags)
487{
488 LIMITED_METHOD_CONTRACT;
489 m_jitFlags = jitFlags;
490}
491
492CORJIT_FLAGS ILStubResolver::GetJitFlags()
493{
494 LIMITED_METHOD_CONTRACT;
495 return m_jitFlags;
496}
497
498// static
499void ILStubResolver::StubGenFailed(ILStubResolver* pResolver)
500{
501 CONTRACTL
502 {
503 NOTHROW;
504 GC_NOTRIGGER;
505 MODE_ANY;
506 }
507 CONTRACTL_END;
508
509 if ((ILNotYetGenerated == dac_cast<TADDR>(pResolver->m_pCompileTimeState)) ||
510 (ILGeneratedAndFreed == dac_cast<TADDR>(pResolver->m_pCompileTimeState)))
511 {
512 return;
513 }
514
515 pResolver->ClearCompileTimeState(ILNotYetGenerated);
516}
517