HRESULT CeeFileGenWriter::fixup() { HRESULT hr; m_fixed = true; if (!m_linked) IfFailRet(link()); CeeGenTokenMapper *pMapper = getTokenMapper(); // Apply token remaps if there are any. if (! m_fTokenMapSupported && pMapper != NULL) { IMetaDataImport *pImport; hr = pMapper->GetMetaData(&pImport); _ASSERTE(SUCCEEDED(hr)); hr = MapTokens(pMapper, pImport); pImport->Release(); } // remap the entry point if entry point token has been moved if (pMapper != NULL && !m_objSwitch) { mdToken tk = m_entryPoint; pMapper->HasTokenMoved(tk, tk); m_corHeader->EntryPointToken = VAL32(tk); } IfFailRet(getPEWriter().fixup(pMapper)); return S_OK; } // HRESULT CeeFileGenWriter::fixup()
FCIMPLEND //************************************************** // LoadInMemoryTypeByName // Explicitly loading an in memory type // <TODO>@todo: this function is not dealing with nested type correctly yet. // We will need to parse the full name by finding "+" for enclosing type, etc.</TODO> //************************************************** void QCALLTYPE COMModule::LoadInMemoryTypeByName(QCall::ModuleHandle pModule, LPCWSTR wszFullName) { QCALL_CONTRACT; TypeHandle typeHnd; BEGIN_QCALL; if (!pModule->IsReflection()) COMPlusThrow(kNotSupportedException, W("NotSupported_NonReflectedType")); RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter(); _ASSERTE(pRCW); // it is ok to use public import API because this is a dynamic module anyway. We are also receiving Unicode full name as // parameter. IMetaDataImport * pImport = pRCW->GetRWImporter(); if (wszFullName == NULL) IfFailThrow( E_FAIL ); // look up the handle mdTypeDef td; HRESULT hr = pImport->FindTypeDefByName(wszFullName, mdTokenNil, &td); if (FAILED(hr)) { if (hr != CLDB_E_RECORD_NOTFOUND) COMPlusThrowHR(hr); // Get the UTF8 version of strFullName MAKE_UTF8PTR_FROMWIDE(szFullName, wszFullName); pModule->GetAssembly()->ThrowTypeLoadException(szFullName, IDS_CLASSLOAD_GENERAL); } TypeKey typeKey(pModule, td); typeHnd = pModule->GetClassLoader()->LoadTypeHandleForTypeKey(&typeKey, TypeHandle()); END_QCALL; return; }
bool CProfilerCallback::GetClassNameFromClassId(ClassID classId, LPWSTR wszClass ) { ModuleID moduleId; mdTypeDef typeDef; wszClass[0] = 0; HRESULT hr = m_pICorProfilerInfo->GetClassIDInfo( classId, &moduleId, &typeDef ); if ( FAILED(hr) ) return false; if ( typeDef == 0 ) // ::GetClassIDInfo can fail, yet not set HRESULT { // __asm int 3 return false; } IMetaDataImport * pIMetaDataImport = 0; hr = m_pICorProfilerInfo->GetModuleMetaData( moduleId, ofRead, IID_IMetaDataImport, (LPUNKNOWN *)&pIMetaDataImport ); if ( FAILED(hr) ) return false; if ( !pIMetaDataImport ) return false; wchar_t wszTypeDef[512]; DWORD cchTypeDef = sizeof(wszTypeDef)/sizeof(wszTypeDef[0]); hr = pIMetaDataImport->GetTypeDefProps( typeDef, wszTypeDef, cchTypeDef, &cchTypeDef, 0, 0 ); if ( FAILED(hr) ) return false; lstrcpyW( wszClass, wszTypeDef ); // // If we were ambitious, we'd save the ClassID away in a map to avoid // needing to hit the metatdata APIs every time. // pIMetaDataImport->Release(); return true; }
// Gets a CordbModule that has the given metadata interface // // Arguments: // pIMetaData - metadata interface // // Returns: // CordbModule whose associated metadata matches the metadata interface provided here // Throws on error. Returns non-null // CordbModule * CordbAppDomain::GetModuleFromMetaDataInterface(IUnknown *pIMetaData) { HRESULT hr = S_OK; RSExtSmartPtr<IMetaDataImport> pImport; RSLockHolder lockHolder(GetProcess()->GetProcessLock()); // need for module enumeration // Grab the interface we need... hr = pIMetaData->QueryInterface(IID_IMetaDataImport, (void**)&pImport); if (FAILED(hr)) { ThrowHR(E_INVALIDARG); } // Get the mvid of the given module. GUID matchMVID; hr = pImport->GetScopeProps(NULL, 0, 0, &matchMVID); IfFailThrow(hr); CordbModule* pModule; HASHFIND findmodule; PrepopulateModules(); for (pModule = m_modules.FindFirst(&findmodule); pModule != NULL; pModule = m_modules.FindNext(&findmodule)) { IMetaDataImport * pImportCurrent = pModule->GetMetaDataImporter(); // throws _ASSERTE(pImportCurrent != NULL); // Get the mvid of this module GUID MVID; hr = pImportCurrent->GetScopeProps(NULL, 0, 0, &MVID); IfFailThrow(hr); if (MVID == matchMVID) { return pModule; } } ThrowHR(E_INVALIDARG); }
bool CProfilerCallback::GetMethodNameFromFunctionId(FunctionID functionId, LPWSTR wszClass, LPWSTR wszMethod) { mdToken dwToken; IMetaDataImport * pIMetaDataImport = 0; HRESULT hr = m_pICorProfilerInfo->GetTokenAndMetaDataFromFunction( functionId, IID_IMetaDataImport, (LPUNKNOWN *)&pIMetaDataImport, &dwToken ); if ( FAILED(hr) ) return false; wchar_t _wszMethod[512]; DWORD cchMethod = sizeof(_wszMethod)/sizeof(_wszMethod[0]); mdTypeDef mdClass; hr = pIMetaDataImport->GetMethodProps( dwToken, &mdClass, _wszMethod, cchMethod, &cchMethod, 0, 0, 0, 0, 0 ); if ( FAILED(hr) ) return false; lstrcpyW( wszMethod, _wszMethod ); wchar_t wszTypeDef[512]; DWORD cchTypeDef = sizeof(wszTypeDef)/sizeof(wszTypeDef[0]); if ( mdClass == 0x02000000 ) mdClass = 0x02000001; hr = pIMetaDataImport->GetTypeDefProps( mdClass, wszTypeDef, cchTypeDef, &cchTypeDef, 0, 0 ); if ( FAILED(hr) ) return false; lstrcpyW( wszClass, wszTypeDef ); pIMetaDataImport->Release(); // // If we were ambitious, we'd save every FunctionID away in a map to avoid // needing to hit the metatdata APIs every time. // return true; }
String^ ModuleWrapper::GetNameFromMetaData() { IMetaDataImport* import; CheckHResult(Module->GetMetaDataInterface(IID_IMetaDataImport, (IUnknown**)&import)); WCHAR *name = new WCHAR[DefaultCharArraySize]; ULONG expectedSize; GUID mvid; HRESULT hResult = import->GetScopeProps(name, DefaultCharArraySize, &expectedSize, &mvid); if (FAILED(hResult)) { delete [] name; } CheckHResult(hResult); if (expectedSize > DefaultCharArraySize) { delete [] name; name = new WCHAR[expectedSize]; hResult = import->GetScopeProps(name, DefaultCharArraySize, &expectedSize, &mvid); if (FAILED(hResult)) { delete [] name; } CheckHResult(hResult); } String^ result = gcnew String(name); delete [] name; import->Release(); return result; }
std::wstring GetFunctionName( UINT functionId ) { mdToken methodToken, classToken, newClassToken; IMetaDataImport * pm = NULL; if (FAILED(profiler->GetTokenAndMetaDataFromFunction( functionId, IID_IMetaDataImport, (IUnknown **) &pm, &methodToken ))) return L"<no metadata>"; wchar_t buf[512]; DWORD size = 512; if (FAILED(pm->GetMethodProps( methodToken, &classToken, buf, size, &size, NULL, NULL, NULL, NULL, NULL ))) { pm->Release(); return L"<no metadata>"; } std::wstring class_buf_string; while( true ) { wchar_t class_buf[512]; size = 512; if (FAILED(pm->GetTypeDefProps( classToken, class_buf, size, &size, NULL, NULL ))) { pm->Release(); return L"<no metadata>"; } class_buf_string = std::wstring( class_buf ) + class_buf_string; if( FAILED( pm->GetNestedClassProps( classToken, &newClassToken ) ) ) break; if( newClassToken == classToken || newClassToken == 0 ) break; class_buf_string = L"$" + class_buf_string; classToken = newClassToken; } pm->Release(); return class_buf_string + L"::" + std::wstring( buf ); }
//----------------------------------------------------------------------------- // Get a ICorDebugValue for a static field on this class. // // Parameters: // fieldDef - metadata token for field on this class. Can not be from an // inherited class. // pFrame - frame used to resolve Thread-static, AppDomain-static, etc. // ppValue - OUT: gets value of the field. // // Returns: // S_OK on success. // CORDBG_E_STATIC_VAR_NOT_AVAILABLE //----------------------------------------------------------------------------- HRESULT CordbClass::GetStaticFieldValue(mdFieldDef fieldDef, ICorDebugFrame *pFrame, ICorDebugValue **ppValue) { PUBLIC_REENTRANT_API_ENTRY(this); FAIL_IF_NEUTERED(this); VALIDATE_POINTER_TO_OBJECT(ppValue, ICorDebugValue **); ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); HRESULT hr = S_OK; *ppValue = NULL; BOOL fEnCHangingField = FALSE; IMetaDataImport * pImport = NULL; EX_TRY { pImport = GetModule()->GetMetaDataImporter(); // throws // Validate the token. if (!pImport->IsValidToken(fieldDef) || (TypeFromToken(fieldDef) != mdtFieldDef)) { ThrowHR(E_INVALIDARG); } // Make sure we have enough info about the class. Init(); // Uninstantiated generics (eg, Foo<T>) don't have static data. Must use instantiated (eg Foo<int>) // But all CordbClass instances are uninstantiated. So this should fail for all generic types. // Normally, debuggers should be using ICorDebugType instead. // Though in the forward compat case, they'll hit this. if (HasTypeParams()) { ThrowHR(CORDBG_E_STATIC_VAR_NOT_AVAILABLE); } // Lookup the field given its metadata token. FieldData *pFieldData; hr = GetFieldInfo(fieldDef, &pFieldData); // This field was added by EnC, need to use EnC specific code path if (hr == CORDBG_E_ENC_HANGING_FIELD) { // Static fields added with EnC hang off the EnCFieldDesc hr = GetEnCHangingField(fieldDef, &pFieldData, NULL); if (SUCCEEDED(hr)) { fEnCHangingField = TRUE; } // Note: the FieldOffset in pFieldData has been cooked to produce // the correct address of the field in the syncBlock. // @todo: extend Debugger_IPCEFieldData so we don't have to cook the offset here } IfFailThrow(hr); { Instantiation emptyInst; hr = CordbClass::GetStaticFieldValue2(GetModule(), pFieldData, fEnCHangingField, &emptyInst, pFrame, ppValue); // Let hr fall through } } EX_CATCH_HRESULT(hr); // Translate Failure HRs. if (pImport != NULL) { hr = CordbClass::PostProcessUnavailableHRESULT(hr, pImport, fieldDef); } return hr; }
HRESULT CAsmLink::ImportFile2(LPCWSTR pszFilename, LPCWSTR pszTargetName, IMetaDataAssemblyImport *pAssemblyScopeIn, BOOL fSmartImport, mdToken *pFileToken, IMetaDataAssemblyImport **ppAssemblyScope, DWORD *pdwCountOfScopes) { ASSERT(m_bInited); LPWSTR newTarget = NULL; bool bNewTarget = false; IMetaDataAssemblyImport *pAImport = NULL; IMetaDataImport *pImport = NULL; mdAssembly tkAssembly; if (pszFilename && wcslen(pszFilename) > MAX_PATH) return FileNameTooLong(pszFilename); if (pszTargetName && wcslen(pszTargetName) > MAX_PATH) return FileNameTooLong(pszTargetName); // File name too long if (pszTargetName == NULL) newTarget = VSAllocStr(pszFilename); else newTarget = VSAllocStr(pszTargetName); if (_wcsicmp(newTarget, pszFilename) == 0) { } else { bNewTarget = true; } if ((pAImport = pAssemblyScopeIn) != NULL) { pAImport->AddRef(); } else { HRESULT hr = m_pDisp->OpenScope(pszFilename, ofRead | ofNoTypeLib, IID_IMetaDataAssemblyImport, (IUnknown**)&pAImport); if (FAILED(hr)) { *pFileToken = 0; if (ppAssemblyScope) *ppAssemblyScope = NULL; if (pdwCountOfScopes) *pdwCountOfScopes = 0; VSFree(newTarget); return hr; } } HRESULT hr; VERIFY(SUCCEEDED(hr = pAImport->QueryInterface( IID_IMetaDataImport, (void**)&pImport))); hr = pAImport->GetAssemblyFromScope( &tkAssembly); if (FAILED(hr)) { hr = S_FALSE; // This is NOT an assembly if (ppAssemblyScope) *ppAssemblyScope = NULL; if (pdwCountOfScopes) *pdwCountOfScopes = 1; *pFileToken = mdTokenNil; CFile* file = new CFile(newTarget, pImport, m_pError, this); if (bNewTarget) { if (SUCCEEDED(hr = file->SetSource(pszFilename))) hr = file->UpdateModuleName(); } pAImport->Release(); pImport->Release(); if (SUCCEEDED(hr) && SUCCEEDED(hr = m_pModules->AddFile( file, 0, pFileToken))) { if (fSmartImport) hr = file->ImportFile( NULL, NULL); *pFileToken = TokenFromRid(RidFromToken(*pFileToken), mdtModule); } if (ppAssemblyScope) *ppAssemblyScope = NULL; if (pdwCountOfScopes) *pdwCountOfScopes = 1; VSFree(newTarget); return hr == S_OK ? S_FALSE : hr; } else { // It is an Assembly CAssemblyFile* assembly = new CAssemblyFile( pszFilename, pAImport, pImport, m_pError, this); if (ppAssemblyScope) *ppAssemblyScope = pAImport; else pAImport->Release(); pImport->Release(); if (m_bDontDoHashes) assembly->DontDoHash(); hr = assembly->ImportAssembly(pdwCountOfScopes, fSmartImport, m_pDisp); if (SUCCEEDED(hr) && bNewTarget) hr = assembly->ReportError( ERR_CantRenameAssembly, mdTokenNil, NULL, pszFilename); if (FAILED(hr)) { delete assembly; VSFree(newTarget); return hr; } VSFree(newTarget); if (FAILED(hr = m_pImports->AddFile( assembly, 0, pFileToken))) delete assembly; return SUCCEEDED(hr) ? S_OK : hr; } }
//************************************************** // GetTypeRef // This function will return the type token given full qual name. If the type // is defined locally, we will return the TypeDef token. Or we will return a TypeRef token // with proper resolution scope calculated. // wszFullName is escaped (TYPE_NAME_RESERVED_CHAR). It should not be byref or contain enclosing type name, // assembly name, and generic argument list. //************************************************** mdTypeRef QCALLTYPE COMModule::GetTypeRef(QCall::ModuleHandle pModule, LPCWSTR wszFullName, QCall::ModuleHandle pRefedModule, LPCWSTR wszRefedModuleFileName, INT32 tkResolutionArg) { QCALL_CONTRACT; mdTypeRef tr = 0; BEGIN_QCALL; RefClassWriter * pRCW = pModule->GetReflectionModule()->GetClassWriter(); _ASSERTE(pRCW); IMetaDataEmit * pEmit = pRCW->GetEmitter(); IMetaDataImport * pImport = pRCW->GetRWImporter(); if (wszFullName == NULL) { COMPlusThrow(kArgumentNullException, W("ArgumentNull_String")); } InlineSString<128> ssNameUnescaped; LPCWSTR wszTemp = wszFullName; WCHAR c; while(0 != (c = *wszTemp++)) { if ( c == W('\\') && IsTypeNameReservedChar(*wszTemp) ) { ssNameUnescaped.Append(*wszTemp++); } else { _ASSERTE( ! IsTypeNameReservedChar(c) ); ssNameUnescaped.Append(c); } } LPCWSTR wszFullNameUnescaped = ssNameUnescaped.GetUnicode(); Assembly * pThisAssembly = pModule->GetClassLoader()->GetAssembly(); Assembly * pRefedAssembly = pRefedModule->GetClassLoader()->GetAssembly(); if (pModule == pRefedModule) { // referenced type is from the same module so we must be able to find a TypeDef. IfFailThrow(pImport->FindTypeDefByName( wszFullNameUnescaped, RidFromToken(tkResolutionArg) ? tkResolutionArg : mdTypeDefNil, &tr)); } else { mdToken tkResolution = mdTokenNil; if (RidFromToken(tkResolutionArg)) { // reference to nested type tkResolution = tkResolutionArg; } else { // reference to top level type if ( pThisAssembly != pRefedAssembly ) { SafeComHolderPreemp<IMetaDataAssemblyEmit> pAssemblyEmit; // Generate AssemblyRef IfFailThrow( pEmit->QueryInterface(IID_IMetaDataAssemblyEmit, (void **) &pAssemblyEmit) ); tkResolution = pThisAssembly->AddAssemblyRef(pRefedAssembly, pAssemblyEmit); // Add the assembly ref token and the manifest module it is referring to this module's rid map. // This is needed regardless of whether the dynamic assembly has run access. Even in Save-only // or Refleciton-only mode, CreateType() of the referencing type may still need the referenced // type to be resolved and loaded, e.g. if the referencing type is a subclass of the referenced type. // // Don't cache if there is assembly associated with the token already. The assembly ref resolution // can be ambiguous because of reflection emit does not require unique assembly names. // We always let the first association win. Ideally, we would disallow this situation by throwing // exception, but that would be a breaking change. if(pModule->LookupAssemblyRef(tkResolution) == NULL) { pModule->ForceStoreAssemblyRef(tkResolution, pRefedAssembly); } } else { _ASSERTE(pModule != pRefedModule); _ASSERTE(wszRefedModuleFileName != NULL); // Generate ModuleRef IfFailThrow(pEmit->DefineModuleRef(wszRefedModuleFileName, &tkResolution)); } } IfFailThrow( pEmit->DefineTypeRefByName(tkResolution, wszFullNameUnescaped, &tr) ); } END_QCALL; return tr; }
HRESULT CMnProfiler::GetMethodInfo(FunctionID functionID, wstring& assemblyName, wstring& className, wstring& methodName, wstring& methodParameters) { IMetaDataImport* pIMetaDataImport = 0; HRESULT hr = S_OK; mdToken funcToken = 0; WCHAR szName[NAME_BUFFER_SIZE]; ClassID classId; ModuleID moduleId; hr = m_pICorProfilerInfo->GetFunctionInfo(functionID, &classId, &moduleId, &funcToken); if(SUCCEEDED(hr)) { AssemblyID assemblyID; ULONG cchModule; LPCBYTE baseLoadAddress; hr = m_pICorProfilerInfo->GetModuleInfo(moduleId, &baseLoadAddress, NAME_BUFFER_SIZE, &cchModule, szName, &assemblyID); if(SUCCEEDED(hr)) { AppDomainID appDomainId; hr = m_pICorProfilerInfo->GetAssemblyInfo(assemblyID, NAME_BUFFER_SIZE, &cchModule, szName, &appDomainId, &moduleId); if(SUCCEEDED(hr)) { assemblyName = wstring(szName, cchModule); hr = m_pICorProfilerInfo->GetTokenAndMetaDataFromFunction(functionID, IID_IMetaDataImport, (LPUNKNOWN *) &pIMetaDataImport, &funcToken); if(SUCCEEDED(hr)) { mdTypeDef classTypeDef; ULONG cchFunction; ULONG cchClass; PCCOR_SIGNATURE methodSignatureBlob; ULONG methodSignatureBlobSize; hr = pIMetaDataImport->GetMethodProps(funcToken, &classTypeDef, szName, NAME_BUFFER_SIZE, &cchFunction, 0, &methodSignatureBlob, &methodSignatureBlobSize, 0, 0); if (SUCCEEDED(hr)) { methodName = wstring(szName, cchFunction); if (CheckMethodName(methodName)) { hr = pIMetaDataImport->GetTypeDefProps(classTypeDef, szName, NAME_BUFFER_SIZE, &cchClass, 0, 0); if (SUCCEEDED(hr)) { className = wstring(szName, cchClass); if (CheckMethodName(className)) { hr = MnFunctionInfo::ParseFunctionParameters(pIMetaDataImport, funcToken, methodParameters); } else { hr = E_FAIL; } /*logs::Logger::OutputInfo(_T("%s: Method \"%s\" Class %s Signature %s"), _T(__FUNCTION__), methodName.c_str(), className.c_str(), methodParameters.c_str());*/ } } else { hr = E_FAIL; } } pIMetaDataImport->Release(); } } } } return hr; }