void Binder::CheckMscorlib() { const FieldOffsetCheck *pOffsets = MscorlibFieldOffsets; while (pOffsets->fieldID != FIELD__NIL) { FieldDesc *pFD = g_Mscorlib.FetchField(pOffsets->fieldID); DWORD offset = pFD->GetOffset(); if (!pFD->GetMethodTableOfEnclosingClass()->IsValueClass()) offset += sizeof(ObjHeader); _ASSERTE(offset == pOffsets->expectedOffset && "Managed class field offset does not match unmanaged class field offset"); pOffsets++; } const ClassSizeCheck *pSizes = MscorlibClassSizes; while (pSizes->classID != CLASS__NIL) { MethodTable *pMT = g_Mscorlib.FetchClass(pSizes->classID); DWORD size = pMT->GetClass()->GetNumInstanceFieldBytes(); DWORD expected = pSizes->expectedSize - sizeof(void*); _ASSERTE(size == expected && "Managed object size does not match unmanaged object size"); pSizes++; } // check the consistency of BCL and VM // note: it is not enabled by default because of it is time consuming and // changes the bootstrap sequence of the EE if (!g_pConfig->GetConfigDWORD(L"ConsistencyCheck", 0)) return; // // VM referencing BCL (mscorlib.h) // for (BinderClassID cID = (BinderClassID) 1; cID <= g_Mscorlib.m_cClassRIDs; cID = (BinderClassID) (cID + 1)) { if (g_Mscorlib.GetClassName(cID) != NULL) // Allow for CorSigElement entries with no classes g_Mscorlib.FetchClass(cID); } for (BinderMethodID mID = (BinderMethodID) 1; mID <= g_Mscorlib.m_cMethodRIDs; mID = (BinderMethodID) (mID + 1)) g_Mscorlib.FetchMethod(mID); for (BinderFieldID fID = (BinderFieldID) 1; fID <= g_Mscorlib.m_cFieldRIDs; fID = (BinderFieldID) (fID + 1)) g_Mscorlib.FetchField(fID); // // BCL referencing VM (ecall.cpp) // HRESULT hr = S_OK; Module *pModule = g_Mscorlib.m_pModule; IMDInternalImport *pInternalImport = pModule->GetMDImport(); HENUMInternal hEnum; // for all methods... IfFailGo(pInternalImport->EnumAllInit(mdtMethodDef, &hEnum)); for (;;) { mdTypeDef td; mdTypeDef tdClass; DWORD dwImplFlags; if (!pInternalImport->EnumNext(&hEnum, &td)) break; pInternalImport->GetMethodImplProps(td, NULL, &dwImplFlags); // ... that are internal calls ... if (!IsMiInternalCall(dwImplFlags)) continue; IfFailGo(pInternalImport->GetParentToken(td, &tdClass)); NameHandle className(pModule, tdClass); TypeHandle type; type = pModule->GetClassLoader()->LoadTypeHandle(&className, RETURN_ON_ERROR, FALSE); if (type.IsNull()) { LPCUTF8 pszName = pInternalImport->GetNameOfMethodDef(tdClass); OutputDebugStringA(pszName); OutputDebugStringA("\n"); _ASSERTE(false); } MethodDesc *pMD = type.AsMethodTable()->GetClass()->FindMethod(td);; _ASSERTE(pMD); // ... check that the method is in the fcall table. if (GetIDForMethod(pMD) == 0xffff) { LPCUTF8 pszName = pInternalImport->GetNameOfMethodDef(td); OutputDebugStringA(pszName); OutputDebugStringA("\n"); _ASSERTE(false); } } pInternalImport->EnumClose(&hEnum); ErrExit: _ASSERTE(SUCCEEDED(hr)); }