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
6
7
8#include "common.h"
9
10#include "binder.h"
11#include "ecall.h"
12
13#include "field.h"
14#include "excep.h"
15#include "eeconfig.h"
16#include "runtimehandles.h"
17#include "customattribute.h"
18#include "debugdebugger.h"
19#include "dllimport.h"
20#include "nativeoverlapped.h"
21#include "clrvarargs.h"
22#include "sigbuilder.h"
23
24#ifdef FEATURE_PREJIT
25#include "compile.h"
26#endif
27
28//
29// Retrieve structures from ID.
30//
31NOINLINE PTR_MethodTable MscorlibBinder::LookupClass(BinderClassID id)
32{
33 WRAPPER_NO_CONTRACT;
34 return (&g_Mscorlib)->LookupClassLocal(id);
35}
36
37PTR_MethodTable MscorlibBinder::GetClassLocal(BinderClassID id)
38{
39 WRAPPER_NO_CONTRACT;
40
41 PTR_MethodTable pMT = VolatileLoad(&(m_pClasses[id]));
42 if (pMT == NULL)
43 return LookupClassLocal(id);
44 return pMT;
45}
46
47PTR_MethodTable MscorlibBinder::LookupClassLocal(BinderClassID id)
48{
49 CONTRACTL
50 {
51 THROWS;
52 GC_TRIGGERS;
53 INJECT_FAULT(ThrowOutOfMemory());
54
55 PRECONDITION(id != CLASS__NIL);
56 PRECONDITION(id <= m_cClasses);
57 }
58 CONTRACTL_END;
59
60 PTR_MethodTable pMT = NULL;
61
62 // Binder methods are used for loading "known" types from mscorlib.dll. Thus they are unlikely to be part
63 // of a recursive cycle. This is used too broadly to force manual overrides at every callsite.
64 OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
65
66 const MscorlibClassDescription *d = m_classDescriptions + (int)id;
67
68 pMT = ClassLoader::LoadTypeByNameThrowing(GetModule()->GetAssembly(), d->nameSpace, d->name).AsMethodTable();
69
70 _ASSERTE(pMT->GetModule() == GetModule());
71
72#ifndef DACCESS_COMPILE
73 VolatileStore(&m_pClasses[id], pMT);
74#endif
75
76 return pMT;
77}
78
79NOINLINE MethodDesc * MscorlibBinder::LookupMethod(BinderMethodID id)
80{
81 WRAPPER_NO_CONTRACT;
82 return (&g_Mscorlib)->LookupMethodLocal(id);
83}
84
85MethodDesc * MscorlibBinder::GetMethodLocal(BinderMethodID id)
86{
87 WRAPPER_NO_CONTRACT;
88
89 MethodDesc * pMD = VolatileLoad(&(m_pMethods[id]));
90 if (pMD == NULL)
91 return LookupMethodLocal(id);
92 return pMD;
93}
94
95MethodDesc * MscorlibBinder::LookupMethodLocal(BinderMethodID id)
96{
97 CONTRACTL
98 {
99 THROWS;
100 GC_TRIGGERS;
101 INJECT_FAULT(ThrowOutOfMemory());
102
103 PRECONDITION(id != METHOD__NIL);
104 PRECONDITION(id <= m_cMethods);
105 }
106 CONTRACTL_END;
107
108#ifndef DACCESS_COMPILE
109 MethodDesc * pMD = NULL;
110
111 const MscorlibMethodDescription *d = m_methodDescriptions + (id - 1);
112
113 MethodTable * pMT = GetClassLocal(d->classID);
114 _ASSERTE(pMT != NULL && "Couldn't find a type in mscorlib!");
115
116 if (d->sig != NULL)
117 {
118 Signature sig = GetSignatureLocal(d->sig);
119
120 pMD = MemberLoader::FindMethod(pMT, d->name, sig.GetRawSig(), sig.GetRawSigLen(), GetModule());
121 }
122 else
123 {
124 pMD = MemberLoader::FindMethodByName(pMT, d->name);
125 }
126
127
128 PREFIX_ASSUME_MSGF(pMD != NULL, ("EE expects method to exist: %s:%s Sig pointer: %p\n", pMT->GetDebugClassName(), d->name, d->sig));
129
130 VolatileStore(&m_pMethods[id], pMD);
131
132 return pMD;
133#else
134 DacNotImpl();
135 return NULL;
136#endif
137}
138
139NOINLINE FieldDesc * MscorlibBinder::LookupField(BinderFieldID id)
140{
141 WRAPPER_NO_CONTRACT;
142 return (&g_Mscorlib)->LookupFieldLocal(id);
143}
144
145FieldDesc * MscorlibBinder::GetFieldLocal(BinderFieldID id)
146{
147 WRAPPER_NO_CONTRACT;
148
149 FieldDesc * pFD = VolatileLoad(&(m_pFields[id]));
150 if (pFD == NULL)
151 return LookupFieldLocal(id);
152 return pFD;
153}
154
155FieldDesc * MscorlibBinder::LookupFieldLocal(BinderFieldID id)
156{
157 CONTRACTL
158 {
159 THROWS;
160 GC_TRIGGERS;
161 INJECT_FAULT(ThrowOutOfMemory());
162
163 PRECONDITION(id != FIELD__NIL);
164 PRECONDITION(id <= m_cFields);
165 }
166 CONTRACTL_END;
167
168 FieldDesc * pFD = NULL;
169
170 const MscorlibFieldDescription *d = m_fieldDescriptions + (id - 1);
171
172 MethodTable * pMT = GetClassLocal(d->classID);
173
174 pFD = MemberLoader::FindField(pMT, d->name, NULL, 0, NULL);
175
176#ifndef DACCESS_COMPILE
177 PREFIX_ASSUME_MSGF(pFD != NULL, ("EE expects field to exist: %s:%s\n", pMT->GetDebugClassName(), d->name));
178
179 VolatileStore(&(m_pFields[id]), pFD);
180#endif
181
182 return pFD;
183}
184
185NOINLINE PTR_MethodTable MscorlibBinder::LookupClassIfExist(BinderClassID id)
186{
187 CONTRACTL
188 {
189 GC_NOTRIGGER;
190 NOTHROW;
191 FORBID_FAULT;
192 MODE_ANY;
193
194 PRECONDITION(id != CLASS__NIL);
195 PRECONDITION(id <= (&g_Mscorlib)->m_cClasses);
196 }
197 CONTRACTL_END;
198
199 // Run the class loader in non-load mode.
200 ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
201
202 // Binder methods are used for loading "known" types from mscorlib.dll. Thus they are unlikely to be part
203 // of a recursive cycle. This is used too broadly to force manual overrides at every callsite.
204 OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
205
206 const MscorlibClassDescription *d = (&g_Mscorlib)->m_classDescriptions + (int)id;
207
208 PTR_MethodTable pMT = ClassLoader::LoadTypeByNameThrowing(GetModule()->GetAssembly(), d->nameSpace, d->name,
209 ClassLoader::ReturnNullIfNotFound, ClassLoader::DontLoadTypes, CLASS_LOAD_UNRESTOREDTYPEKEY).AsMethodTable();
210
211 _ASSERTE((pMT == NULL) || (pMT->GetModule() == GetModule()));
212
213#ifndef DACCESS_COMPILE
214 if ((pMT != NULL) && pMT->IsFullyLoaded())
215 VolatileStore(&(g_Mscorlib.m_pClasses[id]), pMT);
216#endif
217
218 return pMT;
219}
220
221Signature MscorlibBinder::GetSignature(LPHARDCODEDMETASIG pHardcodedSig)
222{
223 CONTRACTL
224 {
225 THROWS;
226 GC_TRIGGERS;
227 INJECT_FAULT(COMPlusThrowOM());
228 MODE_ANY;
229 }
230 CONTRACTL_END
231
232// Make sure all HardCodedMetaSig's are global. Because there is no individual
233// cleanup of converted binary sigs, using allocated HardCodedMetaSig's
234// can lead to a quiet memory leak.
235#ifdef _DEBUG_IMPL
236
237// This #include workaround generates a monster boolean expression that compares
238// "this" against the address of every global defined in metasig.h
239 if (! (0
240#define METASIG_BODY(varname, types) || pHardcodedSig==&gsig_ ## varname
241#include "metasig.h"
242 ))
243 {
244 _ASSERTE(!"The HardCodedMetaSig struct can only be declared as a global in metasig.h.");
245 }
246#endif
247
248 return (&g_Mscorlib)->GetSignatureLocal(pHardcodedSig);
249}
250
251Signature MscorlibBinder::GetTargetSignature(LPHARDCODEDMETASIG pHardcodedSig)
252{
253 CONTRACTL
254 {
255 THROWS;
256 GC_TRIGGERS;
257 INJECT_FAULT(COMPlusThrowOM());
258 MODE_ANY;
259 }
260 CONTRACTL_END
261
262#ifdef CROSSGEN_COMPILE
263 return GetModule()->m_pBinder->GetSignatureLocal(pHardcodedSig);
264#else
265 return (&g_Mscorlib)->GetSignatureLocal(pHardcodedSig);
266#endif
267}
268
269// Get the metasig, do a one-time conversion if necessary
270Signature MscorlibBinder::GetSignatureLocal(LPHARDCODEDMETASIG pHardcodedSig)
271{
272 CONTRACTL
273 {
274 THROWS;
275 GC_TRIGGERS;
276 INJECT_FAULT(COMPlusThrowOM());
277 MODE_ANY;
278 }
279 CONTRACTL_END
280
281 PTR_CBYTE pMetaSig = PTR_CBYTE((TADDR)VolatileLoad(&pHardcodedSig->m_pMetaSig));
282
283 // To minimize code and data size, the hardcoded metasigs are baked as much as possible
284 // at compile time. Only the signatures with type references require one-time conversion at runtime.
285
286 // the negative size means signature with unresolved type references
287 if ((INT8)*pMetaSig < 0)
288 {
289#ifndef DACCESS_COMPILE
290 pMetaSig = ConvertSignature(pHardcodedSig, pMetaSig);
291#else
292 DacNotImpl();
293#endif
294 }
295
296 // The metasig has to be resolved at this point
297 INT8 cbSig = (INT8)*pMetaSig;
298 _ASSERTE(cbSig > 0);
299
300#ifdef DACCESS_COMPILE
301 PCCOR_SIGNATURE pSig = (PCCOR_SIGNATURE)
302 DacInstantiateTypeByAddress(dac_cast<TADDR>(pMetaSig + 1),
303 cbSig,
304 true);
305#else
306 PCCOR_SIGNATURE pSig = pMetaSig+1;
307#endif
308
309 return Signature(pSig, cbSig);
310}
311
312#ifndef DACCESS_COMPILE
313
314bool MscorlibBinder::ConvertType(const BYTE*& pSig, SigBuilder * pSigBuilder)
315{
316 bool bSomethingResolved = false;
317
318Again:
319 CorElementType type = (CorElementType)*pSig++;
320
321 switch (type)
322 {
323 case ELEMENT_TYPE_GENERICINST:
324 {
325 pSigBuilder->AppendElementType(type);
326 if (ConvertType(pSig, pSigBuilder))
327 bSomethingResolved = true;
328 int arity = *pSig++;
329 pSigBuilder->AppendData(arity);
330 for (int i = 0; i < arity; i++)
331 {
332 if (ConvertType(pSig, pSigBuilder))
333 bSomethingResolved = true;
334 }
335 }
336 break;
337
338 case ELEMENT_TYPE_BYREF:
339 case ELEMENT_TYPE_PTR:
340 case ELEMENT_TYPE_SZARRAY:
341 pSigBuilder->AppendElementType(type);
342 if (ConvertType(pSig, pSigBuilder))
343 bSomethingResolved = true;
344 break;
345
346 case ELEMENT_TYPE_CMOD_OPT:
347 case ELEMENT_TYPE_CMOD_REQD:
348 {
349 // The binder class id may overflow 1 byte. Use 2 bytes to encode it.
350 BinderClassID id = (BinderClassID)(*pSig + 0x100 * *(pSig + 1));
351 pSig += 2;
352
353 pSigBuilder->AppendElementType(type);
354 pSigBuilder->AppendToken(GetClassLocal(id)->GetCl());
355 bSomethingResolved = true;
356 }
357 goto Again;
358
359 case ELEMENT_TYPE_CLASS:
360 case ELEMENT_TYPE_VALUETYPE:
361 {
362 // The binder class id may overflow 1 byte. Use 2 bytes to encode it.
363 BinderClassID id = (BinderClassID)(*pSig + 0x100 * *(pSig + 1));
364 pSig += 2;
365
366 pSigBuilder->AppendElementType(type);
367 pSigBuilder->AppendToken(GetClassLocal(id)->GetCl());
368 bSomethingResolved = true;
369 }
370 break;
371
372 case ELEMENT_TYPE_VAR:
373 case ELEMENT_TYPE_MVAR:
374 {
375 pSigBuilder->AppendElementType(type);
376 pSigBuilder->AppendData(*pSig++);
377 }
378 break;
379
380 default:
381 pSigBuilder->AppendElementType(type);
382 break;
383 }
384
385 return bSomethingResolved;
386}
387
388//------------------------------------------------------------------
389// Resolve type references in the hardcoded metasig.
390// Returns a new signature with type refences resolved.
391//------------------------------------------------------------------
392void MscorlibBinder::BuildConvertedSignature(const BYTE* pSig, SigBuilder * pSigBuilder)
393{
394 CONTRACTL
395 {
396 STANDARD_VM_CHECK;
397 PRECONDITION(CheckPointer(pSig));
398 PRECONDITION(CheckPointer(pSigBuilder));
399 }
400 CONTRACTL_END
401
402 unsigned argCount;
403 unsigned callConv;
404 bool bSomethingResolved = false;
405
406 // calling convention
407 callConv = *pSig++;
408 pSigBuilder->AppendData(callConv);
409
410 if ((callConv & IMAGE_CEE_CS_CALLCONV_MASK) == IMAGE_CEE_CS_CALLCONV_DEFAULT) {
411 // arg count
412 argCount = *pSig++;
413 pSigBuilder->AppendData(argCount);
414 }
415 else {
416 if ((callConv & IMAGE_CEE_CS_CALLCONV_MASK) != IMAGE_CEE_CS_CALLCONV_FIELD)
417 THROW_BAD_FORMAT(BFA_BAD_SIGNATURE, (Module*)NULL);
418 argCount = 0;
419 }
420
421 // <= because we want to include the return value or the field
422 for (unsigned i = 0; i <= argCount; i++) {
423 if (ConvertType(pSig, pSigBuilder))
424 bSomethingResolved = true;
425 }
426
427 _ASSERTE(bSomethingResolved);
428}
429
430const BYTE* MscorlibBinder::ConvertSignature(LPHARDCODEDMETASIG pHardcodedSig, const BYTE* pSig)
431{
432 CONTRACTL
433 {
434 THROWS;
435 GC_TRIGGERS;
436 INJECT_FAULT(COMPlusThrowOM());
437 MODE_ANY;
438 }
439 CONTRACTL_END
440
441 GCX_PREEMP();
442
443 SigBuilder sigBuilder;
444
445 BuildConvertedSignature(pSig+1, &sigBuilder);
446
447 DWORD cbCount;
448 PVOID pSignature = sigBuilder.GetSignature(&cbCount);
449
450 {
451 CrstHolder ch(&s_SigConvertCrst);
452
453 if (*(INT8*)pHardcodedSig->m_pMetaSig < 0) {
454
455 BYTE* pResolved = (BYTE*)(void*)(SystemDomain::GetGlobalLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(1) + S_SIZE_T(cbCount)));
456
457 _ASSERTE(FitsIn<INT8>(cbCount));
458 *(INT8*)pResolved = static_cast<INT8>(cbCount);
459 CopyMemory(pResolved+1, pSignature, cbCount);
460
461 // this has to be last, overwrite the pointer to the metasig with the resolved one
462 VolatileStore<const BYTE *>(&const_cast<HardCodedMetaSig *>(pHardcodedSig)->m_pMetaSig, pResolved);
463 }
464 }
465
466 return pHardcodedSig->m_pMetaSig;
467}
468
469#endif // #ifndef DACCESS_COMPILE
470
471#ifdef _DEBUG
472void MscorlibBinder::TriggerGCUnderStress()
473{
474 CONTRACTL
475 {
476 THROWS;
477 GC_TRIGGERS;
478 SO_TOLERANT;
479 INJECT_FAULT(ThrowOutOfMemory());
480 }
481 CONTRACTL_END;
482
483#ifndef DACCESS_COMPILE
484 _ASSERTE (GetThread ());
485 TRIGGERSGC ();
486 // Force a GC here because GetClass could trigger GC nondeterminsticly
487 if (g_pConfig->GetGCStressLevel() != 0)
488 {
489 DEBUG_ONLY_REGION();
490 Thread * pThread = GetThread ();
491 BOOL bInCoopMode = pThread->PreemptiveGCDisabled ();
492 GCX_COOP ();
493 if (bInCoopMode)
494 {
495 pThread->PulseGCMode ();
496 }
497 }
498#endif //DACCESS_COMPILE
499}
500#endif // _DEBUG
501
502DWORD MscorlibBinder::GetFieldOffset(BinderFieldID id)
503{
504 WRAPPER_NO_CONTRACT;
505
506 return GetField(id)->GetOffset();
507}
508
509#ifndef DACCESS_COMPILE
510
511CrstStatic MscorlibBinder::s_SigConvertCrst;
512
513/*static*/
514void MscorlibBinder::Startup()
515{
516 WRAPPER_NO_CONTRACT
517 s_SigConvertCrst.Init(CrstSigConvert);
518}
519
520#if defined(_DEBUG) && !defined(CROSSGEN_COMPILE)
521
522// NoClass is used to suppress check for unmanaged and managed size match
523#define NoClass char[USHRT_MAX]
524
525const MscorlibBinder::OffsetAndSizeCheck MscorlibBinder::OffsetsAndSizes[] =
526{
527 #define DEFINE_CLASS_U(nameSpace, stringName, unmanagedType) \
528 { PTR_CSTR((TADDR) g_ ## nameSpace ## NS ), PTR_CUTF8((TADDR) # stringName), sizeof(unmanagedType), 0, 0, 0 },
529
530 #define DEFINE_FIELD_U(stringName, unmanagedContainingType, unmanagedOffset) \
531 { 0, 0, 0, PTR_CUTF8((TADDR) # stringName), offsetof(unmanagedContainingType, unmanagedOffset), sizeof(((unmanagedContainingType*)1)->unmanagedOffset) },
532 #include "mscorlib.h"
533};
534
535//
536// check the basic consistency between mscorlib and mscorwks
537//
538void MscorlibBinder::Check()
539{
540 STANDARD_VM_CONTRACT;
541
542 MethodTable * pMT = NULL;
543
544 for (unsigned i = 0; i < NumItems(OffsetsAndSizes); i++)
545 {
546 const OffsetAndSizeCheck * p = OffsetsAndSizes + i;
547
548 if (p->className != NULL)
549 {
550 pMT = ClassLoader::LoadTypeByNameThrowing(GetModule()->GetAssembly(), p->classNameSpace, p->className).AsMethodTable();
551
552 if (p->expectedClassSize == sizeof(NoClass))
553 continue;
554
555 // hidden size of the type that participates in the alignment calculation
556 DWORD hiddenSize = pMT->IsValueType() ? sizeof(MethodTable*) : 0;
557
558 DWORD size = pMT->GetBaseSize() - (sizeof(ObjHeader)+hiddenSize);
559
560 DWORD expectedsize = (DWORD)ALIGN_UP(p->expectedClassSize + (sizeof(ObjHeader) + hiddenSize),
561 DATA_ALIGNMENT) - (sizeof(ObjHeader) + hiddenSize);
562
563 CONSISTENCY_CHECK_MSGF(size == expectedsize,
564 ("Managed object size does not match unmanaged object size\n"
565 "man: 0x%x, unman: 0x%x, Name: %s\n", size, expectedsize, pMT->GetDebugClassName()));
566 }
567 else
568 if (p->fieldName != NULL)
569 {
570 // This assert will fire if there is DEFINE_FIELD_U macro without preceeding DEFINE_CLASS_U macro in mscorlib.h
571 _ASSERTE(pMT != NULL);
572
573 FieldDesc * pFD = MemberLoader::FindField(pMT, p->fieldName, NULL, 0, NULL);
574 _ASSERTE(pFD != NULL);
575
576 DWORD offset = pFD->GetOffset();
577
578 if (!pFD->IsFieldOfValueType())
579 {
580 offset += Object::GetOffsetOfFirstField();
581 }
582
583 CONSISTENCY_CHECK_MSGF(offset == p->expectedFieldOffset,
584 ("Managed class field offset does not match unmanaged class field offset\n"
585 "man: 0x%x, unman: 0x%x, Class: %s, Name: %s\n", offset, p->expectedFieldOffset, pFD->GetApproxEnclosingMethodTable()->GetDebugClassName(), pFD->GetName()));
586
587 DWORD size = pFD->LoadSize();
588
589 CONSISTENCY_CHECK_MSGF(size == p->expectedFieldSize,
590 ("Managed class field size does not match unmanaged class field size\n"
591 "man: 0x%x, unman: 0x%x, Class: %s, Name: %s\n", size, p->expectedFieldSize, pFD->GetApproxEnclosingMethodTable()->GetDebugClassName(), pFD->GetName()));
592 }
593 }
594}
595
596#ifdef CHECK_FCALL_SIGNATURE
597//
598// check consistency of the unmanaged and managed fcall signatures
599//
600/* static */ FCSigCheck* FCSigCheck::g_pFCSigCheck;
601const char * aType[] =
602{
603 "void",
604 "FC_BOOL_RET",
605 "CLR_BOOL",
606 "FC_CHAR_RET",
607 "CLR_CHAR",
608 "FC_INT8_RET",
609 "INT8",
610 "FC_UINT8_RET",
611 "UINT8",
612 "FC_INT16_RET",
613 "INT16",
614 "FC_UINT16_RET",
615 "UINT16",
616 "INT64",
617 "VINT64",
618 "UINT64",
619 "VUINT64",
620 "float",
621 "Vfloat",
622 "double",
623 "Vdouble"
624};
625
626const char * aInt32Type[] =
627{
628 "INT32",
629 "UINT32", // we might remove it to have a better check
630 "int",
631 "unsigned int", // we might remove it to have a better check
632 "DWORD", // we might remove it to have a better check
633 "HRESULT", // we might remove it to have a better check
634 "mdToken", // we might remove it to have a better check
635 "ULONG", // we might remove it to have a better check
636 "mdMemberRef", // we might remove it to have a better check
637 "mdCustomAttribute", // we might remove it to have a better check
638 "mdTypeDef", // we might remove it to have a better check
639 "mdFieldDef", // we might remove it to have a better check
640 "LONG",
641 "CLR_I4",
642 "LCID" // we might remove it to have a better check
643};
644
645const char * aUInt32Type[] =
646{
647 "UINT32",
648 "unsigned int",
649 "DWORD",
650 "INT32", // we might remove it to have a better check
651 "ULONG"
652};
653
654static BOOL IsStrInArray(const char* sStr, size_t len, const char* aStrArray[], int nSize)
655{
656 STANDARD_VM_CONTRACT;
657 for (int i = 0; i < nSize; i++)
658 {
659 if (SString::_strnicmp(aStrArray[i], sStr, (COUNT_T)len) == 0)
660 {
661 return TRUE;
662 }
663 }
664 return FALSE;
665}
666
667static void FCallCheckSignature(MethodDesc* pMD, PCODE pImpl)
668{
669 STANDARD_VM_CONTRACT;
670
671 const char* pUnmanagedSig = NULL;
672
673 FCSigCheck* pSigCheck = FCSigCheck::g_pFCSigCheck;
674 while (pSigCheck != NULL)
675 {
676 if (pImpl == (PCODE)pSigCheck->func) {
677 pUnmanagedSig = pSigCheck->signature;
678 break;
679 }
680 pSigCheck = pSigCheck->next;
681 }
682
683 MetaSig msig(pMD);
684 int argIndex = -2; // start with return value
685 int enregisteredArguments = 0;
686 const char* pUnmanagedArg = pUnmanagedSig;
687 for (;;)
688 {
689 CorElementType argType = ELEMENT_TYPE_END;
690 TypeHandle argTypeHandle;
691
692 if (argIndex == -2)
693 {
694 // return value
695 argType = msig.GetReturnType();
696 if (argType == ELEMENT_TYPE_VALUETYPE)
697 argTypeHandle = msig.GetRetTypeHandleThrowing();
698 }
699
700 if (argIndex == -1)
701 {
702 // this ptr
703 if (msig.HasThis())
704 argType = ELEMENT_TYPE_CLASS;
705 else
706 argIndex++; // move on to the first argument
707 }
708
709 if (argIndex >= 0)
710 {
711 argType = msig.NextArg();
712 if (argType == ELEMENT_TYPE_END)
713 break;
714 if (argType == ELEMENT_TYPE_VALUETYPE)
715 argTypeHandle = msig.GetLastTypeHandleThrowing();
716 }
717
718 const char* expectedType = NULL;
719
720 switch (argType)
721 {
722 case ELEMENT_TYPE_VOID:
723 expectedType = pMD->IsCtor() ? NULL : "void";
724 break;
725 case ELEMENT_TYPE_BOOLEAN:
726 expectedType = (argIndex == -2) ? "FC_BOOL_RET" : "CLR_BOOL";
727 break;
728 case ELEMENT_TYPE_CHAR:
729 expectedType = (argIndex == -2) ? "FC_CHAR_RET" : "CLR_CHAR";
730 break;
731 case ELEMENT_TYPE_I1:
732 expectedType = (argIndex == -2) ? "FC_INT8_RET" : "INT8";
733 break;
734 case ELEMENT_TYPE_U1:
735 expectedType = (argIndex == -2) ? "FC_UINT8_RET" : "UINT8";
736 break;
737 case ELEMENT_TYPE_I2:
738 expectedType = (argIndex == -2) ? "FC_INT16_RET" : "INT16";
739 break;
740 case ELEMENT_TYPE_U2:
741 expectedType = (argIndex == -2) ? "FC_UINT16_RET" : "UINT16";
742 break;
743 //case ELEMENT_TYPE_I4:
744 // expectedType = "INT32";
745 // break;
746 // case ELEMENT_TYPE_U4:
747 // expectedType = "UINT32";
748 // break;
749
750 // See the comments in fcall.h on what the "V" prefix means.
751 case ELEMENT_TYPE_I8:
752 expectedType = ((argIndex == -2) || (enregisteredArguments >= 2)) ? "INT64" : "VINT64";
753 break;
754 case ELEMENT_TYPE_U8:
755 expectedType = ((argIndex == -2) || (enregisteredArguments >= 2)) ? "UINT64" : "VUINT64";
756 break;
757 case ELEMENT_TYPE_R4:
758 expectedType = ((argIndex == -2) || (enregisteredArguments >= 2)) ? "float" : "Vfloat";
759 break;
760 case ELEMENT_TYPE_R8:
761 expectedType = ((argIndex == -2) || (enregisteredArguments >= 2)) ? "double" : "Vdouble";
762 break;
763 default:
764 // no checks for other types
765 break;
766 }
767
768 // Count number of enregistered arguments for x86
769 if ((argIndex != -2) && !((expectedType != NULL) && (*expectedType == 'V')))
770 {
771 enregisteredArguments++;
772 }
773
774 if (pUnmanagedSig != NULL)
775 {
776 CONSISTENCY_CHECK_MSGF(pUnmanagedArg != NULL,
777 ("Unexpected end of managed fcall signature\n"
778 "Method: %s:%s\n", pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName));
779
780 const char* pUnmanagedArgEnd = strchr(pUnmanagedArg, ',');
781
782 const char* pUnmanagedTypeEnd = (pUnmanagedArgEnd != NULL) ?
783 pUnmanagedArgEnd : (pUnmanagedArg + strlen(pUnmanagedArg));
784
785 if (argIndex != -2)
786 {
787 // skip argument name
788 while(pUnmanagedTypeEnd > pUnmanagedArg)
789 {
790 char c = *(pUnmanagedTypeEnd-1);
791 if ((c != '_')
792 && ((c < '0') || ('9' < c))
793 && ((c < 'a') || ('z' < c))
794 && ((c < 'A') || ('Z' < c)))
795 break;
796 pUnmanagedTypeEnd--;
797 }
798 }
799
800 // skip whitespaces
801 while(pUnmanagedTypeEnd > pUnmanagedArg)
802 {
803 char c = *(pUnmanagedTypeEnd-1);
804 if ((c != 0x20) && (c != '\t') && (c != '\n') && (c != '\r'))
805 break;
806 pUnmanagedTypeEnd--;
807 }
808
809 size_t len = pUnmanagedTypeEnd - pUnmanagedArg;
810 // generate the unmanaged argument signature to show them in the error message if possible
811 StackSString ssUnmanagedType(SString::Ascii, pUnmanagedArg, (COUNT_T)len);
812 StackScratchBuffer buffer;
813 const char * pUnManagedType = ssUnmanagedType.GetANSI(buffer);
814
815 if (expectedType != NULL)
816 {
817 // when managed type is well known
818 if (!(strlen(expectedType) == len && SString::_strnicmp(expectedType, pUnmanagedArg, (COUNT_T)len) == 0))
819 {
820 printf("CheckExtended: The managed and unmanaged fcall signatures do not match, Method: %s:%s. Argument: %d Expecting: %s Actual: %s\n", pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, argIndex, expectedType, pUnManagedType);
821 }
822 }
823 else
824 {
825 // when managed type is not wellknown, we still can find sig mismatch if native type is a well known type
826 BOOL bSigError = false;
827 if (argType == ELEMENT_TYPE_VOID && pMD->IsCtor())
828 {
829 bSigError = false;
830 }
831 else if (argType == ELEMENT_TYPE_I4)
832 {
833 bSigError = !IsStrInArray(pUnmanagedArg, len, aInt32Type, NumItems(aInt32Type));
834 }
835 else if (argType == ELEMENT_TYPE_U4)
836 {
837 bSigError = !IsStrInArray(pUnmanagedArg, len, aUInt32Type, NumItems(aUInt32Type));
838 }
839 else if (argType == ELEMENT_TYPE_VALUETYPE)
840 {
841 // we already did special check for value type
842 bSigError = false;
843 }
844 else
845 {
846 bSigError = IsStrInArray(pUnmanagedArg, len, aType, NumItems(aType));
847 }
848 if (bSigError)
849 {
850 printf("CheckExtended: The managed and unmanaged fcall signatures do not match, Method: %s:%s. Argument: %d Expecting: (CorElementType)%d actual: %s\n", pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName, argIndex, argType, pUnManagedType);
851 }
852 }
853 pUnmanagedArg = (pUnmanagedArgEnd != NULL) ? (pUnmanagedArgEnd+1) : NULL;
854 }
855
856 argIndex++;
857 }
858
859 if (pUnmanagedSig != NULL)
860 {
861 if (msig.IsVarArg())
862 {
863 if (!((pUnmanagedArg != NULL) && strcmp(pUnmanagedArg, "...") == 0))
864 {
865 printf("CheckExtended: Expecting varargs in unmanaged fcall signature, Method: %s:%s\n", pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName);
866 }
867 }
868 else
869 {
870 if (!(pUnmanagedArg == NULL))
871 {
872 printf("CheckExtended: Unexpected end of unmanaged fcall signature, Method: %s:%s\n", pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName);
873 }
874 }
875 }
876}
877#endif // CHECK_FCALL_SIGNATURE
878
879//
880// extended check of consistency between mscorlib and mscorwks:
881// - verifies that all references from mscorlib to mscorwks are present
882// - verifies that all references from mscorwks to mscorlib are present
883// - limited detection of mismatches between managed and unmanaged fcall signatures
884//
885void MscorlibBinder::CheckExtended()
886{
887 STANDARD_VM_CONTRACT;
888
889 // check the consistency of BCL and VM
890 // note: it is not enabled by default because of it is time consuming and
891 // changes the bootstrap sequence of the EE
892 if (!CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ConsistencyCheck))
893 return;
894
895 //
896 // VM referencing BCL (mscorlib.h)
897 //
898 for (BinderClassID cID = (BinderClassID) 1; (int)cID < m_cClasses; cID = (BinderClassID) (cID + 1))
899 {
900 bool fError = false;
901 EX_TRY
902 {
903 if (MscorlibBinder::GetClassName(cID) != NULL) // Allow for CorSigElement entries with no classes
904 {
905 if (NULL == MscorlibBinder::GetClass(cID))
906 {
907 fError = true;
908 }
909 }
910 }
911 EX_CATCH
912 {
913 fError = true;
914 }
915 EX_END_CATCH(SwallowAllExceptions)
916
917 if (fError)
918 {
919 printf("CheckExtended: VM expects type to exist: %s.%s\n", MscorlibBinder::GetClassNameSpace(cID), MscorlibBinder::GetClassName(cID));
920 }
921 }
922
923 for (BinderMethodID mID = (BinderMethodID) 1; mID < (BinderMethodID) MscorlibBinder::m_cMethods; mID = (BinderMethodID) (mID + 1))
924 {
925 bool fError = false;
926 BinderClassID cID = m_methodDescriptions[mID-1].classID;
927 EX_TRY
928 {
929 if (NULL == MscorlibBinder::GetMethod(mID))
930 {
931 fError = true;
932 }
933 }
934 EX_CATCH
935 {
936 fError = true;
937 }
938 EX_END_CATCH(SwallowAllExceptions)
939
940 if (fError)
941 {
942 printf("CheckExtended: VM expects method to exist: %s.%s::%s\n", MscorlibBinder::GetClassNameSpace(cID), MscorlibBinder::GetClassName(cID), MscorlibBinder::GetMethodName(mID));
943 }
944 }
945
946 for (BinderFieldID fID = (BinderFieldID) 1; fID < (BinderFieldID) MscorlibBinder::m_cFields; fID = (BinderFieldID) (fID + 1))
947 {
948 bool fError = false;
949 BinderClassID cID = m_fieldDescriptions[fID-1].classID;
950 EX_TRY
951 {
952 if (NULL == MscorlibBinder::GetField(fID))
953 {
954 fError = true;
955 }
956 }
957 EX_CATCH
958 {
959 fError = true;
960 }
961 EX_END_CATCH(SwallowAllExceptions)
962
963 if (fError)
964 {
965 printf("CheckExtended: VM expects field to exist: %s.%s::%s\n", MscorlibBinder::GetClassNameSpace(cID), MscorlibBinder::GetClassName(cID), MscorlibBinder::GetFieldName(fID));
966 }
967 }
968
969 //
970 // BCL referencing VM (ecall.cpp)
971 //
972 SetSHash<DWORD> usedECallIds;
973
974 HRESULT hr = S_OK;
975 Module *pModule = MscorlibBinder::m_pModule;
976 IMDInternalImport *pInternalImport = pModule->GetMDImport();
977
978 HENUMInternal hEnum;
979
980 // for all methods...
981 IfFailGo(pInternalImport->EnumAllInit(mdtMethodDef, &hEnum));
982
983 for (;;) {
984 mdTypeDef td;
985 mdTypeDef tdClass;
986 DWORD dwImplFlags;
987 DWORD dwMemberAttrs;
988
989 if (!pInternalImport->EnumNext(&hEnum, &td))
990 break;
991
992 pInternalImport->GetMethodImplProps(td, NULL, &dwImplFlags);
993
994 IfFailGo(pInternalImport->GetMethodDefProps(td, &dwMemberAttrs));
995
996 // ... that are internal calls ...
997 if (!IsMiInternalCall(dwImplFlags) && !IsMdPinvokeImpl(dwMemberAttrs))
998 continue;
999
1000 IfFailGo(pInternalImport->GetParentToken(td, &tdClass));
1001
1002 TypeHandle type;
1003
1004 EX_TRY
1005 {
1006 type = ClassLoader::LoadTypeDefOrRefThrowing(pModule, tdClass,
1007 ClassLoader::ThrowIfNotFound,
1008 ClassLoader::PermitUninstDefOrRef);
1009 }
1010 EX_CATCH
1011 {
1012 LPCUTF8 pszClassName;
1013 LPCUTF8 pszNameSpace;
1014 if (FAILED(pInternalImport->GetNameOfTypeDef(tdClass, &pszClassName, &pszNameSpace)))
1015 {
1016 pszClassName = pszNameSpace = "Invalid TypeDef record";
1017 }
1018 printf("CheckExtended: Unable to load class from mscorlib: %s.%s\n", pszNameSpace, pszClassName);
1019 }
1020 EX_END_CATCH(SwallowAllExceptions)
1021
1022 MethodDesc *pMD = MemberLoader::FindMethod(type.AsMethodTable(), td);
1023 _ASSERTE(pMD);
1024
1025 // Required to support generic FCalls (only instance methods on generic types constrained to "class" are allowed)
1026 if (type.IsGenericTypeDefinition()) {
1027 pMD = pMD->FindOrCreateTypicalSharedInstantiation();
1028 }
1029
1030 DWORD id = 0;
1031
1032 if (pMD->IsFCall())
1033 {
1034 id = ((FCallMethodDesc *)pMD)->GetECallID();
1035 if (id == 0) {
1036 id = ECall::GetIDForMethod(pMD);
1037 }
1038 }
1039 else
1040 if (pMD->IsNDirect())
1041 {
1042 PInvokeStaticSigInfo sigInfo;
1043 NDirect::PopulateNDirectMethodDesc((NDirectMethodDesc *)pMD, &sigInfo);
1044
1045 if (pMD->IsQCall())
1046 {
1047 id = ((NDirectMethodDesc *)pMD)->GetECallID();
1048 if (id == 0) {
1049 id = ECall::GetIDForMethod(pMD);
1050 }
1051 }
1052 else
1053 {
1054 continue;
1055 }
1056 }
1057 else
1058 {
1059 continue;
1060 }
1061
1062 // ... check that the method is in the fcall table.
1063 if (id == 0) {
1064 LPCUTF8 pszClassName;
1065 LPCUTF8 pszNameSpace;
1066 if (FAILED(pInternalImport->GetNameOfTypeDef(tdClass, &pszClassName, &pszNameSpace)))
1067 {
1068 pszClassName = pszNameSpace = "Invalid TypeDef record";
1069 }
1070 LPCUTF8 pszName;
1071 if (FAILED(pInternalImport->GetNameOfMethodDef(td, &pszName)))
1072 {
1073 pszName = "Invalid method name";
1074 }
1075 printf("CheckExtended: Unable to find internalcall implementation: %s.%s::%s\n", pszNameSpace, pszClassName, pszName);
1076 }
1077
1078 if (id != 0)
1079 {
1080 usedECallIds.Add(id);
1081 }
1082
1083#ifdef CHECK_FCALL_SIGNATURE
1084 if (pMD->IsFCall())
1085 {
1086 FCallCheckSignature(pMD, ECall::GetFCallImpl(pMD));
1087 }
1088#endif // CHECK_FCALL_SIGNATURE
1089 }
1090
1091 pInternalImport->EnumClose(&hEnum);
1092
1093 // Verify that there are no unused entries in the ecall table
1094 ECall::CheckUnusedECalls(usedECallIds);
1095
1096 //
1097 // Stub constants
1098 //
1099#define ASMCONSTANTS_C_ASSERT(cond)
1100#define ASMCONSTANTS_RUNTIME_ASSERT(cond) _ASSERTE(cond)
1101#include "asmconstants.h"
1102
1103 _ASSERTE(sizeof(VARIANT) == MscorlibBinder::GetClass(CLASS__NATIVEVARIANT)->GetNativeSize());
1104
1105 printf("CheckExtended: completed without exception.\n");
1106
1107ErrExit:
1108 _ASSERTE(SUCCEEDED(hr));
1109}
1110
1111#endif // _DEBUG && !CROSSGEN_COMPILE
1112
1113extern const MscorlibClassDescription c_rgMscorlibClassDescriptions[];
1114extern const USHORT c_nMscorlibClassDescriptions;
1115
1116extern const MscorlibMethodDescription c_rgMscorlibMethodDescriptions[];
1117extern const USHORT c_nMscorlibMethodDescriptions;
1118
1119extern const MscorlibFieldDescription c_rgMscorlibFieldDescriptions[];
1120extern const USHORT c_nMscorlibFieldDescriptions;
1121
1122#ifdef CROSSGEN_COMPILE
1123namespace CrossGenMscorlib
1124{
1125 extern const MscorlibClassDescription c_rgMscorlibClassDescriptions[];
1126 extern const USHORT c_nMscorlibClassDescriptions;
1127
1128 extern const MscorlibMethodDescription c_rgMscorlibMethodDescriptions[];
1129 extern const USHORT c_nMscorlibMethodDescriptions;
1130
1131 extern const MscorlibFieldDescription c_rgMscorlibFieldDescriptions[];
1132 extern const USHORT c_nMscorlibFieldDescriptions;
1133};
1134#endif
1135
1136void MscorlibBinder::AttachModule(Module * pModule)
1137{
1138 STANDARD_VM_CONTRACT;
1139
1140 MscorlibBinder * pGlobalBinder = &g_Mscorlib;
1141
1142 pGlobalBinder->SetDescriptions(pModule,
1143 c_rgMscorlibClassDescriptions, c_nMscorlibClassDescriptions,
1144 c_rgMscorlibMethodDescriptions, c_nMscorlibMethodDescriptions,
1145 c_rgMscorlibFieldDescriptions, c_nMscorlibFieldDescriptions);
1146
1147#if defined(FEATURE_PREJIT) && !defined(CROSSGEN_COMPILE)
1148 MscorlibBinder * pPersistedBinder = pModule->m_pBinder;
1149
1150 if (pPersistedBinder != NULL
1151 // Do not use persisted binder for profiling native images. See comment in code:MscorlibBinder::Fixup.
1152 && !(pModule->GetNativeImage()->GetNativeVersionInfo()->wConfigFlags & CORCOMPILE_CONFIG_PROFILING))
1153 {
1154 pGlobalBinder->m_pClasses = pPersistedBinder->m_pClasses;
1155 pGlobalBinder->m_pMethods = pPersistedBinder->m_pMethods;
1156 pGlobalBinder->m_pFields = pPersistedBinder->m_pFields;
1157
1158 pModule->m_pBinder = pGlobalBinder;
1159 return;
1160 }
1161#endif // FEATURE_PREJIT && CROSSGEN_COMPILE
1162
1163 pGlobalBinder->AllocateTables();
1164
1165#ifdef CROSSGEN_COMPILE
1166 MscorlibBinder * pTargetBinder = (MscorlibBinder *)(void *)
1167 pModule->GetAssembly()->GetLowFrequencyHeap()
1168 ->AllocMem(S_SIZE_T(sizeof(MscorlibBinder)));
1169
1170 pTargetBinder->SetDescriptions(pModule,
1171 CrossGenMscorlib::c_rgMscorlibClassDescriptions, CrossGenMscorlib::c_nMscorlibClassDescriptions,
1172 CrossGenMscorlib::c_rgMscorlibMethodDescriptions, CrossGenMscorlib::c_nMscorlibMethodDescriptions,
1173 CrossGenMscorlib::c_rgMscorlibFieldDescriptions, CrossGenMscorlib::c_nMscorlibFieldDescriptions);
1174
1175 pTargetBinder->AllocateTables();
1176
1177 pModule->m_pBinder = pTargetBinder;
1178#else
1179 pModule->m_pBinder = pGlobalBinder;
1180#endif
1181}
1182
1183void MscorlibBinder::SetDescriptions(Module * pModule,
1184 const MscorlibClassDescription * pClassDescriptions, USHORT nClasses,
1185 const MscorlibMethodDescription * pMethodDescriptions, USHORT nMethods,
1186 const MscorlibFieldDescription * pFieldDescriptions, USHORT nFields)
1187{
1188 LIMITED_METHOD_CONTRACT;
1189
1190 m_pModule = pModule;
1191
1192 m_classDescriptions = pClassDescriptions;
1193 m_cClasses = nClasses;
1194
1195 m_methodDescriptions = pMethodDescriptions;
1196 m_cMethods = nMethods;
1197
1198 m_fieldDescriptions = pFieldDescriptions;
1199 m_cFields = nFields;
1200}
1201
1202void MscorlibBinder::AllocateTables()
1203{
1204 STANDARD_VM_CONTRACT;
1205
1206 LoaderHeap * pHeap = m_pModule->GetAssembly()->GetLowFrequencyHeap();
1207
1208 m_pClasses = (MethodTable **)(void *)
1209 pHeap->AllocMem(S_SIZE_T(m_cClasses) * S_SIZE_T(sizeof(*m_pClasses)));
1210 // Note: Memory allocated on loader heap is zero filled
1211 // ZeroMemory(m_pClasses, m_cClasses * sizeof(*m_pClasses));
1212
1213 m_pMethods = (MethodDesc **)(void *)
1214 pHeap->AllocMem(S_SIZE_T(m_cMethods) * S_SIZE_T(sizeof(*m_pMethods)));
1215 // Note: Memory allocated on loader heap is zero filled
1216 // ZeroMemory(m_pMethods, m_cMethodMDs * sizeof(*m_pMethods));
1217
1218 m_pFields = (FieldDesc **)(void *)
1219 pHeap->AllocMem(S_SIZE_T(m_cFields) * S_SIZE_T(sizeof(*m_pFields)));
1220 // Note: Memory allocated on loader heap is zero filled
1221 // ZeroMemory(m_pFields, m_cFieldRIDs * sizeof(*m_pFields));
1222}
1223
1224PTR_MethodTable MscorlibBinder::LoadPrimitiveType(CorElementType et)
1225{
1226 STANDARD_VM_CONTRACT;
1227
1228 PTR_MethodTable pMT = g_Mscorlib.m_pClasses[et];
1229
1230 // Primitive types hit cyclic reference on binder during type loading so we have to load them in two steps
1231 if (pMT == NULL)
1232 {
1233 const MscorlibClassDescription *d = (&g_Mscorlib)->m_classDescriptions + (int)et;
1234
1235 pMT = ClassLoader::LoadTypeByNameThrowing(GetModule()->GetAssembly(), d->nameSpace, d->name,
1236 ClassLoader::ThrowIfNotFound, ClassLoader::LoadTypes, CLASS_LOAD_APPROXPARENTS).AsMethodTable();
1237 g_Mscorlib.m_pClasses[et] = pMT;
1238
1239 ClassLoader::EnsureLoaded(pMT);
1240 }
1241
1242 return pMT;
1243}
1244
1245#ifdef FEATURE_NATIVE_IMAGE_GENERATION
1246void MscorlibBinder::BindAll()
1247{
1248 STANDARD_VM_CONTRACT;
1249
1250 for (BinderClassID cID = (BinderClassID) 1; cID < m_cClasses; cID = (BinderClassID) (cID + 1))
1251 {
1252 if (m_classDescriptions[cID].name != NULL) // Allow for CorSigElement entries with no classes
1253 GetClassLocal(cID);
1254 }
1255
1256 for (BinderMethodID mID = (BinderMethodID) 1; mID < m_cMethods; mID = (BinderMethodID) (mID + 1))
1257 GetMethodLocal(mID);
1258
1259 for (BinderFieldID fID = (BinderFieldID) 1; fID < m_cFields; fID = (BinderFieldID) (fID + 1))
1260 GetFieldLocal(fID);
1261}
1262
1263void MscorlibBinder::Save(DataImage *image)
1264{
1265 STANDARD_VM_CONTRACT;
1266
1267 image->StoreStructure(this, sizeof(MscorlibBinder),
1268 DataImage::ITEM_BINDER);
1269
1270 image->StoreStructure(m_pClasses, m_cClasses * sizeof(*m_pClasses),
1271 DataImage::ITEM_BINDER_ITEMS);
1272
1273 image->StoreStructure(m_pMethods, m_cMethods * sizeof(*m_pMethods),
1274 DataImage::ITEM_BINDER_ITEMS);
1275
1276 image->StoreStructure(m_pFields, m_cFields * sizeof(*m_pFields),
1277 DataImage::ITEM_BINDER_ITEMS);
1278}
1279
1280void MscorlibBinder::Fixup(DataImage *image)
1281{
1282 STANDARD_VM_CONTRACT;
1283
1284 image->FixupPointerField(this, offsetof(MscorlibBinder, m_pModule));
1285
1286 int i;
1287
1288 image->FixupPointerField(this, offsetof(MscorlibBinder, m_pClasses));
1289 for (i = 1; i < m_cClasses; i++)
1290 {
1291#if _DEBUG
1292 //
1293 // We do not want to check for restore at runtime for performance reasons.
1294 // If there is ever a case that requires restore, it should be special
1295 // cased here and restored explicitly by GetClass/GetField/GetMethod caller.
1296 //
1297 // Profiling NGen images force restore for all types. We are still going to save
1298 // the binder for nidump, but we are not going to use it at runtime.
1299 //
1300 if (m_pClasses[i] != NULL && !GetAppDomain()->ToCompilationDomain()->m_fForceProfiling)
1301 {
1302 _ASSERTE(!m_pClasses[i]->NeedsRestore(image));
1303 }
1304#endif
1305 image->FixupPointerField(m_pClasses, i * sizeof(m_pClasses[0]));
1306 }
1307
1308 image->FixupPointerField(this, offsetof(MscorlibBinder, m_pMethods));
1309 for (i = 1; i < m_cMethods; i++)
1310 {
1311#if _DEBUG
1312 // See comment above.
1313 if (m_pMethods[i] != NULL && !GetAppDomain()->ToCompilationDomain()->m_fForceProfiling)
1314 {
1315 _ASSERTE(!m_pMethods[i]->NeedsRestore(image));
1316 }
1317#endif
1318
1319 image->FixupPointerField(m_pMethods, i * sizeof(m_pMethods[0]));
1320 }
1321
1322 image->FixupPointerField(this, offsetof(MscorlibBinder, m_pFields));
1323 for (i = 1; i < m_cFields; i++)
1324 {
1325 image->FixupPointerField(m_pFields, i * sizeof(m_pFields[0]));
1326 }
1327
1328 image->ZeroPointerField(this, offsetof(MscorlibBinder, m_classDescriptions));
1329 image->ZeroPointerField(this, offsetof(MscorlibBinder, m_methodDescriptions));
1330 image->ZeroPointerField(this, offsetof(MscorlibBinder, m_fieldDescriptions));
1331}
1332#endif // FEATURE_NATIVE_IMAGE_GENERATION
1333
1334#endif // #ifndef DACCESS_COMPILE
1335
1336#ifdef DACCESS_COMPILE
1337
1338void
1339MscorlibBinder::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
1340{
1341 SUPPORTS_DAC;
1342 DAC_ENUM_DTHIS();
1343
1344 DacEnumMemoryRegion(dac_cast<TADDR>(m_classDescriptions),
1345 m_cClasses * sizeof(MscorlibClassDescription));
1346 DacEnumMemoryRegion(dac_cast<TADDR>(m_methodDescriptions),
1347 (m_cMethods - 1) * sizeof(MscorlibMethodDescription));
1348 DacEnumMemoryRegion(dac_cast<TADDR>(m_fieldDescriptions),
1349 (m_cFields - 1) * sizeof(MscorlibFieldDescription));
1350
1351 if (m_pModule.IsValid())
1352 {
1353 m_pModule->EnumMemoryRegions(flags, true);
1354 }
1355
1356 DacEnumMemoryRegion(dac_cast<TADDR>(m_pClasses),
1357 m_cClasses * sizeof(PTR_MethodTable));
1358 DacEnumMemoryRegion(dac_cast<TADDR>(m_pMethods),
1359 m_cMethods * sizeof(PTR_MethodDesc));
1360 DacEnumMemoryRegion(dac_cast<TADDR>(m_pFields),
1361 m_cFields * sizeof(PTR_FieldDesc));
1362}
1363
1364#endif // #ifdef DACCESS_COMPILE
1365
1366GVAL_IMPL(MscorlibBinder, g_Mscorlib);
1367