HRESULT CeeFileGenWriter::MapTokens( CeeGenTokenMapper *pMapper, IMetaDataImport *pImport) { mdTypeDef td; mdMethodDef md; ULONG count; ULONG MethodRVA; ULONG codeOffset; ULONG BaseRVA; DWORD dwFlags; DWORD iFlags; HCORENUM hTypeDefs = 0, hEnum = 0; WCHAR rcwName[MAX_CLASSNAME_LENGTH]; HRESULT hr; CeeSection TextSection = getTextSection(); // Ask for the base RVA of the first method in the stream. All other // method RVA's are >= that value, and will give us the raw offset required. hr = getMethodRVA(0, &BaseRVA); _ASSERTE(SUCCEEDED(hr)); // do globals first while ((hr = pImport->EnumMethods(&hEnum, mdTokenNil, &md, 1, &count)) == S_OK) { hr = pImport->GetMethodProps(md, NULL, rcwName, lengthof(rcwName), NULL, &dwFlags, NULL, NULL, &MethodRVA, &iFlags); _ASSERTE(SUCCEEDED(hr)); if (MethodRVA == 0 || ((IsMdAbstract(dwFlags) || IsMiInternalCall(iFlags)) || (! IsMiIL(iFlags) && ! IsMiOPTIL(iFlags)))) continue; // The raw offset of the method is the RVA in the image minus // the first method in the text section. codeOffset = MethodRVA - BaseRVA; hr = MapTokensForMethod(pMapper, (BYTE *) TextSection.computePointer(codeOffset), rcwName); if (FAILED(hr)) goto ErrExit; } if (hEnum) pImport->CloseEnum(hEnum); hEnum = 0; while ((hr = pImport->EnumTypeDefs(&hTypeDefs, &td, 1, &count)) == S_OK) { while ((hr = pImport->EnumMethods(&hEnum, td, &md, 1, &count)) == S_OK) { hr = pImport->GetMethodProps(md, NULL, rcwName, lengthof(rcwName), NULL, &dwFlags, NULL, NULL, &MethodRVA, &iFlags); _ASSERTE(SUCCEEDED(hr)); if (MethodRVA == 0 || ((IsMdAbstract(dwFlags) || IsMiInternalCall(iFlags)) || (! IsMiIL(iFlags) && ! IsMiOPTIL(iFlags)))) continue; // The raw offset of the method is the RVA in the image minus // the first method in the text section. codeOffset = MethodRVA - BaseRVA; hr = MapTokensForMethod(pMapper, (BYTE *) TextSection.computePointer(codeOffset), rcwName); if (FAILED(hr)) goto ErrExit; } if (hEnum) pImport->CloseEnum(hEnum); hEnum = 0; } ErrExit: if (hTypeDefs) pImport->CloseEnum(hTypeDefs); if (hEnum) pImport->CloseEnum(hEnum); return (hr); }
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)); }