FieldDesc *Binder::LookupField(BinderFieldID id) { _ASSERTE(m_pModule != NULL); _ASSERTE(id != FIELD__NIL); _ASSERTE(id <= m_cFieldRIDs); THROWSCOMPLUSEXCEPTION(); const FieldDescription *d = m_fieldDescriptions + id - 1; MethodTable *pMT = FetchClass(d->classID); FieldDesc *pFD; pFD = pMT->GetClass()->FindField(d->name, d->sig); _ASSERTE(pFD != NULL || !"EE expects field to exist"); _ASSERTE(pFD - pMT->GetClass()->GetFieldDescListRaw() >= 0); _ASSERTE(pFD - pMT->GetClass()->GetFieldDescListRaw() < (pMT->GetClass()->GetNumStaticFields() + pMT->GetClass()->GetNumIntroducedInstanceFields())); _ASSERTE(pFD - pMT->GetClass()->GetFieldDescListRaw() + 1 < USHRT_MAX); USHORT index = (USHORT)(pFD - pMT->GetClass()->GetFieldDescListRaw()); m_pFieldRIDs[id-1] = index+1; // Go ahead and fill in the rid map since we're here anyway m_pModule->StoreFieldDef(pFD->GetMemberDef(), pFD); return pFD; }
MethodTable *Binder::LookupClass(BinderClassID id, BOOL fLoad) { _ASSERTE(m_pModule != NULL); _ASSERTE(id != CLASS__NIL); _ASSERTE(id <= m_cClassRIDs); MethodTable *pMT; const ClassDescription *d = m_classDescriptions + id - 1; NameHandle nh(d->name); if (!fLoad) { nh.SetTokenNotToLoad(tdAllTypes); pMT = m_pModule->GetClassLoader()->FindTypeHandle(&nh).AsMethodTable(); if (pMT == NULL) return NULL; } else { THROWSCOMPLUSEXCEPTION(); BEGIN_ENSURE_COOPERATIVE_GC(); OBJECTREF pThrowable = NULL; GCPROTECT_BEGIN(pThrowable); pMT = m_pModule->GetClassLoader()->FindTypeHandle(&nh, &pThrowable).AsMethodTable(); if (pMT == NULL) { _ASSERTE(!"EE expects class to exist"); COMPlusThrow(pThrowable); } GCPROTECT_END(); END_ENSURE_COOPERATIVE_GC(); } _ASSERTE(pMT->GetModule() == m_pModule); mdTypeDef td = pMT->GetClass()->GetCl(); _ASSERTE(!IsNilToken(td)); _ASSERTE(RidFromToken(td) <= USHRT_MAX); m_pClassRIDs[id-1] = (USHORT) RidFromToken(td); m_pModule->StoreTypeDef(td, pMT); return pMT; }
FieldDesc *Binder::RawGetField(BinderFieldID id) { CANNOTTHROWCOMPLUSEXCEPTION(); _ASSERTE(m_pModule != NULL); _ASSERTE(id != FIELD__NIL); _ASSERTE(id <= m_cFieldRIDs); const FieldDescription *f = m_fieldDescriptions + id - 1; MethodTable *pMT = RawGetClass(f->classID); _ASSERTE(pMT != NULL); // Can't do this because the class may not be restored yet. // _ASSERTE(m_pFieldRIDs[id-1]-1 < (pMT->GetClass()->GetNumStaticFields() // + pMT->GetClass()->GetNumIntroducedInstanceFields())); FieldDesc *pFD = pMT->GetClass()->GetFieldDescListRaw() + m_pFieldRIDs[id-1]-1; _ASSERTE(pFD != NULL); return pFD; }
MethodDesc *Binder::LookupMethod(BinderMethodID id) { _ASSERTE(m_pModule != NULL); _ASSERTE(id != METHOD__NIL); _ASSERTE(id <= m_cMethodRIDs); THROWSCOMPLUSEXCEPTION(); const MethodDescription *d = m_methodDescriptions + id - 1; MethodTable *pMT = FetchClass(d->classID); MethodDesc *pMD = pMT->GetClass()->FindMethod(d->name, d->sig); _ASSERTE(pMD != NULL || !"EE expects method to exist"); _ASSERTE(pMD->GetSlot()+1 <= USHRT_MAX); m_pMethodRIDs[id-1] = (USHORT) pMD->GetSlot()+1; // Go ahead and fill in the rid map since we're here anyway m_pModule->StoreMethodDef(pMD->GetMemberDef(), pMD); return pMD; }
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)); }
HRESULT STDMETHODCALLTYPE ICorDBPrivHelperImpl::CreateManagedObject( /*in*/ WCHAR *wszAssemblyName, /*in*/ WCHAR *wszModuleName, /*in*/ mdTypeDef classToken, /*in*/ void *rawData, /*out*/ IUnknown **ppUnk) { _ASSERTE(TypeFromToken((mdTypeDef)classToken) == mdtTypeDef); _ASSERTE(wszAssemblyName && wszModuleName && ppUnk); if (!wszAssemblyName || !wszModuleName || classToken == mdTokenNil) return E_INVALIDARG; if (!ppUnk) return E_POINTER; HRESULT hr = S_OK; BEGINCANNOTTHROWCOMPLUSEXCEPTION(); // This will set up a managed thread object if one does not already exist // for this particular thread. Thread* pThread = SetupThread(); if (pThread == NULL) { hr = E_OUTOFMEMORY; goto Exit; } // Start up COM Interop if (FAILED(hr = QuickCOMStartup())) goto Exit; { // Don't want to be interrupted... BOOL fWasGCEnabled = !pThread->PreemptiveGCDisabled(); if (fWasGCEnabled) pThread->DisablePreemptiveGC(); Assembly *pAssembly; Module *pModule; if (GetAppDomain() == NULL) hr = E_INVALIDARG; else { // Try and load the assembly, given the name provided. OBJECTREF pThrowable = NULL; GCPROTECT_BEGIN(pThrowable); hr = AssemblySpec::LoadAssembly(wszAssemblyName, &pAssembly, &pThrowable); GCPROTECT_END(); if (SUCCEEDED(hr)) { _ASSERTE(pAssembly); // Try and load the module, given the name provided. hr = pAssembly->GetModuleFromFilename(wszModuleName, &pModule); if (SUCCEEDED(hr)) { _ASSERTE(pModule); // If the class isn't known,then don't try and create it. if (!pModule->GetMDImport()->IsValidToken(classToken)) hr = E_INVALIDARG; else { COMPLUS_TRY { OBJECTREF obj = NULL; GCPROTECT_BEGIN(obj); // Now try and get the TypeHandle for the given token NameHandle nameHandle(pModule, classToken); TypeHandle typeHandle = pAssembly->LoadTypeHandle(&nameHandle, &obj); // If an exception was thrown at some point, convert // it to an HRESULT if (obj != NULL) hr = SecurityHelper::MapToHR(obj); // No longer need the object, can be GC'd if desired obj = NULL; if (SUCCEEDED(hr)) { _ASSERTE(typeHandle.AsMethodTable()); MethodTable *pMT = typeHandle.AsMethodTable(); if (!pMT->GetClass()->IsValueClass() || pMT->ContainsPointers()) hr = CORDBG_E_OBJECT_IS_NOT_COPYABLE_VALUE_CLASS; if (SUCCEEDED(hr)) { // Now run the class initialiser if (!pMT->CheckRunClassInit(&obj)) hr = SecurityHelper::MapToHR(obj); // No longer need the object, can be GC'd if // desired obj = NULL; if (SUCCEEDED(hr)) { // If successful, allocate an instance of // the class // This may throw an // OutOfMemoryException, but the below // COMPLUS_CATCH should handle it. If // the class is a ValueClass, the // created object will be a boxed // ValueClass. obj = AllocateObject(pMT); // Now create a COM wrapper around // this object. Note that this can // also throw. *ppUnk = GetComIPFromObjectRef(&obj); _ASSERTE(ppUnk); // This is the nasty part. We're gonna // copy the raw data we're given over // the new instance of the value // class... CopyValueClass(obj->UnBox(), rawData, pMT, obj->GetAppDomain()); // No longer need the object, can be GC'd // if desired obj = NULL; } } } GCPROTECT_END(); // obj } COMPLUS_CATCH { // If there's an exception, convert it to an HR hr = SecurityHelper::MapToHR(GETTHROWABLE()); } COMPLUS_END_CATCH } } } } if (fWasGCEnabled) pThread->EnablePreemptiveGC(); } Exit: ENDCANNOTTHROWCOMPLUSEXCEPTION(); return (hr); }
HRESULT STDMETHODCALLTYPE ICorDBPrivHelperImpl::GetManagedObjectContents( /* in */ IUnknown *pObject, /* in */ void *rawData, /* in */ ULONG32 dataSize) { if (!pObject || !rawData) return E_POINTER; if (dataSize == 0) return E_INVALIDARG; HRESULT hr = S_OK; BEGINCANNOTTHROWCOMPLUSEXCEPTION(); // This will set up a managed thread object if one does not already exist // for this particular thread. Thread* pThread = SetupThread(); if (pThread == NULL) { hr = E_OUTOFMEMORY; goto Exit; } { // Don't want to be interrupted... BOOL fWasGCEnabled = !pThread->PreemptiveGCDisabled(); if (fWasGCEnabled) pThread->DisablePreemptiveGC(); OBJECTREF obj = NULL; GCPROTECT_BEGIN(obj); COMPLUS_TRY { // Get the Object out of the IUnknown. obj = GetObjectRefFromComIP(pObject); MethodTable *pMT = obj->GetMethodTable(); if (!pMT->GetClass()->IsValueClass() || pMT->ContainsPointers() || (pMT->GetClass()->GetNumInstanceFieldBytes() != dataSize)) hr = CORDBG_E_OBJECT_IS_NOT_COPYABLE_VALUE_CLASS; // This is the nasty part. We're gonna copy the raw data out // of the object and pass it out. if (SUCCEEDED(hr)) { memcpy(rawData, obj->UnBox(), dataSize); } } COMPLUS_CATCH { // If there's an exception, convert it to an HR hr = SecurityHelper::MapToHR(GETTHROWABLE()); } COMPLUS_END_CATCH obj = NULL; GCPROTECT_END(); // obj if (fWasGCEnabled) pThread->EnablePreemptiveGC(); } Exit: ENDCANNOTTHROWCOMPLUSEXCEPTION(); return (hr); }