void MetaData_Fill_FieldDef(tMD_TypeDef *pParentType, tMD_FieldDef *pFieldDef, U32 memOffset, tMD_TypeDef **ppClassTypeArgs) {
	U32 sigLength;
	PTR sig;
	tMetaData *pMetaData;
	//log_f(5,"MetaData_Fill_FieldDef %s.%s\n", pParentType->name,pFieldDef->name);

	pFieldDef->pParentType = pParentType;

	sig = MetaData_GetBlob(pFieldDef->signature, &sigLength);

	MetaData_DecodeSigEntry(&sig); // First entry always 0x06
	pFieldDef->pType = Type_GetTypeFromSig(pFieldDef->pMetaData, &sig, ppClassTypeArgs, NULL);
	if (pFieldDef->pType == NULL) {
		// If the field is a core generic type definition, then we can't do anything more
		return;
	}
	MetaData_Fill_TypeDef(pFieldDef->pType, NULL, NULL);
	// A check for 0 is done so if a type has a field of it's own type it is handled correctly.
	pFieldDef->memSize = (pFieldDef->pType->stackSize>0)?pFieldDef->pType->stackSize:sizeof(void*);
	pFieldDef->memOffset = memOffset;
	pFieldDef->pFieldDef = pFieldDef;

	pMetaData = pFieldDef->pMetaData;
	if (FIELD_HASFIELDRVA(pFieldDef)) {
		U32 i, top;

		// Field has RVA, so load it from FieldRVA
		top = pMetaData->tables.numRows[MD_TABLE_FIELDRVA];
		for (i=1; i<=top; i++) {
			tMD_FieldRVA *pFieldRVA;

			pFieldRVA = (tMD_FieldRVA*)MetaData_GetTableRow(pMetaData, MAKE_TABLE_INDEX(MD_TABLE_FIELDRVA, i));
			if (pFieldRVA->field == pFieldDef->tableIndex) {
				pFieldDef->pMemory = (PTR)pFieldRVA->rva;
				break;
			}
		}
	} else if (FIELD_ISLITERAL(pFieldDef)) {
		// Field is literal, so make pMemory point to the value signature
		U32 i, top;

		top = pMetaData->tables.numRows[MD_TABLE_CONSTANT];
		for (i=1; i<=top; i++) {
			tMD_Constant *pConst;
			pConst = (tMD_Constant*)MetaData_GetTableRow(pMetaData, MAKE_TABLE_INDEX(MD_TABLE_CONSTANT, i));
			if (pConst->parent == pFieldDef->tableIndex) {
				// Found the field
				pFieldDef->pMemory = (PTR)pConst;
				break;
			}
		}
	}
}
Example #2
0
// Find the method that has been overridden by pMethodDef.
// This is to get the correct vTable offset for the method.
// This must search the MethodImpl table to see if the default inheritence rules are being overridden.
// Return NULL if this method does not override anything.
static tMD_MethodDef* FindVirtualOverriddenMethod(tMD_TypeDef *pTypeDef, tMD_MethodDef *pMethodDef)
{
	U32 i;

	do 
	{
		// Search MethodImpl table
		for (i=pTypeDef->pMetaData->tables.numRows[MD_TABLE_METHODIMPL]; i>0; i--) 
		{
			tMD_MethodImpl *pMethodImpl;

			pMethodImpl = (tMD_MethodImpl*)MetaData_GetTableRow(pTypeDef->pMetaData, MAKE_TABLE_INDEX(MD_TABLE_METHODIMPL, i));
			if (pMethodImpl->class_ == pTypeDef->tableIndex)
			{
				tMD_MethodDef *pMethodDeclDef;

				pMethodDeclDef = MetaData_GetMethodDefFromDefRefOrSpec(pTypeDef->pMetaData, pMethodImpl->methodDeclaration, pTypeDef->ppClassTypeArgs, pMethodDef->ppMethodTypeArgs);
				if (pMethodDeclDef->tableIndex == pMethodDef->tableIndex)
				{
					IDX_TABLE methodToken;
					tMD_MethodDef *pMethod;

					methodToken = pMethodImpl->methodBody;
					pMethod = (tMD_MethodDef*)MetaData_GetTableRow(pTypeDef->pMetaData, methodToken);
					return pMethod;
				}
			}
		}

		// Use normal inheritence rules
		// It must be a virtual method that's being overridden.
		for (i=pTypeDef->numVirtualMethods - 1; i != 0xffffffff; i--)
		{
			if (MetaData_CompareNameAndSig(pMethodDef->name, pMethodDef->signature, pMethodDef->pMetaData, pMethodDef->pParentType->ppClassTypeArgs, pMethodDef->ppMethodTypeArgs, pTypeDef->pVTable[i], pTypeDef->ppClassTypeArgs, NULL)) 
			{
				return pTypeDef->pVTable[i];
			}
		}
		pTypeDef = pTypeDef->pParent;
	} while (pTypeDef != NULL);

	return NULL;
}
tMD_MethodDef* MetaData_GetMethodDefFromDefRefOrSpec(tMetaData *pMetaData, IDX_TABLE token, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) {
	void *pTableEntry;

	pTableEntry = MetaData_GetTableRow(pMetaData, token);
	if (((tMDC_ToMethodDef*)pTableEntry)->pMethodDef != NULL) {
		return ((tMDC_ToMethodDef*)pTableEntry)->pMethodDef;
	}

	switch (TABLE_ID(token)) {
		case MD_TABLE_METHODDEF:
			((tMDC_ToMethodDef*)pTableEntry)->pMethodDef = (tMD_MethodDef*)pTableEntry;
			return (tMD_MethodDef*)pTableEntry;
		case MD_TABLE_MEMBERREF:
			{
				tMD_MemberRef *pMemberRef;

				pMemberRef = (tMD_MemberRef*)pTableEntry;
				switch (TABLE_ID(pMemberRef->class_))
				{
				case MD_TABLE_TYPEREF:
				case MD_TABLE_TYPESPEC:
					{
						tMD_TypeDef *pTypeDef;
						tMD_MethodDef *pMethodDef;

						pTypeDef = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, pMemberRef->class_, ppClassTypeArgs, ppMethodTypeArgs);
						MetaData_Fill_TypeDef(pTypeDef, NULL, NULL);
						pMethodDef = FindMethodInType(pTypeDef, pMemberRef->name, pMetaData, pMemberRef->signature, pTypeDef->ppClassTypeArgs, ppMethodTypeArgs);
						//pMethodDef->pMethodDef = pMethodDef;
						return pMethodDef;
					}
				default:
					Crash("MetaData_GetMethodDefFromMethodDefOrRef(): Cannot handle pMemberRef->class_=0x%08x", pMemberRef->class_);
				}
			}
		case MD_TABLE_METHODSPEC:
			{
				tMD_MethodSpec *pMethodSpec;
				tMD_MethodDef *pMethodDef;

				pMethodSpec = (tMD_MethodSpec*)pTableEntry;
				pMethodDef = Generics_GetMethodDefFromSpec(pMethodSpec, ppClassTypeArgs, ppMethodTypeArgs);

				// Note: Cannot cache the MethodDef from the MethodSpec, as class generic arguments
				// may be different.
				
				return pMethodDef;
			}
	}

	Crash("MetaData_GetMethodDefFromMethodDefOrRef(): Cannot handle token: 0x%08x", token);
	FAKE_RETURN;
}
tMD_ImplMap* MetaData_GetImplMap(tMetaData *pMetaData, IDX_TABLE memberForwardedToken) {
	U32 i;

	for (i=pMetaData->tables.numRows[MD_TABLE_IMPLMAP]; i >= 1; i--) {
		tMD_ImplMap *pImplMap = (tMD_ImplMap*)MetaData_GetTableRow(pMetaData, MAKE_TABLE_INDEX(MD_TABLE_IMPLMAP, i));
		if (pImplMap->memberForwarded == memberForwardedToken) {
			return pImplMap;
		}
	}

	Crash("MetaData_GetImplMap() Cannot find mapping for token: 0x%08x", memberForwardedToken);
	FAKE_RETURN;
}
Example #5
0
// TODO: This is not the most efficient way of doing this, as it has to search through all the
// entries in the GenericParams table for all lookups. This can be improved.
static tMD_GenericParam* FindGenericParam(tMD_TypeDef *pCoreType, U32 typeArgIndex) {
	tMD_GenericParam *pGenericParam;
	U32 i;

	pGenericParam = (tMD_GenericParam*)MetaData_GetTableRow(pCoreType->pMetaData, MAKE_TABLE_INDEX(MD_TABLE_GENERICPARAM, 1));

	for (i=0; i<pCoreType->pMetaData->tables.numRows[MD_TABLE_GENERICPARAM]; i++, pGenericParam++) {
		if (pGenericParam->owner == pCoreType->tableIndex && pGenericParam->number == typeArgIndex) {
			return pGenericParam;
		}
	}
	return NULL;
}
tMD_TypeDef* MetaData_GetTypeDefFromDefRefOrSpec(tMetaData *pMetaData, IDX_TABLE token, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) {
	void *pTableEntry;

	pTableEntry = MetaData_GetTableRow(pMetaData, token);
	if (pTableEntry == NULL) {
		return NULL;
	}
	if (((tMDC_ToTypeDef*)pTableEntry)->pTypeDef != NULL) {
		return ((tMDC_ToTypeDef*)pTableEntry)->pTypeDef;
	}

	switch (TABLE_ID(token)) {
		case MD_TABLE_TYPEDEF:
			((tMDC_ToTypeDef*)pTableEntry)->pTypeDef = (tMD_TypeDef*)pTableEntry;
			return (tMD_TypeDef*)pTableEntry;
		case MD_TABLE_TYPEREF:
			{
				tMetaData *pTypeDefMetaData;
				tMD_TypeRef *pTypeRef;
				tMD_TypeDef *pTypeDef;
				tMD_TypeDef *pInNestedClass;

				pTypeRef = (tMD_TypeRef*)pTableEntry;
				pTypeDefMetaData = MetaData_GetResolutionScopeMetaData(pMetaData, pTypeRef->resolutionScope, &pInNestedClass);
				pTypeDef = MetaData_GetTypeDefFromName(pTypeDefMetaData, pTypeRef->nameSpace, pTypeRef->name, pInNestedClass);
				pTypeRef->pTypeDef = pTypeDef;
				return pTypeDef;
			}
		case MD_TABLE_TYPESPEC:
			{
				tMD_TypeSpec *pTypeSpec;
				tMD_TypeDef *pTypeDef;
				SIG sig;

				pTypeSpec = (tMD_TypeSpec*)pTableEntry;
				sig = MetaData_GetBlob(pTypeSpec->signature, NULL);
				pTypeDef = Type_GetTypeFromSig(pTypeSpec->pMetaData, &sig, ppClassTypeArgs, ppMethodTypeArgs);
				// Note: Cannot cache the TypeDef for this TypeSpec because it
				// can change depending on class arguemnts given.

				return pTypeDef;
			}
			return NULL;
		default:
			Crash("MetaData_GetTypeDefFromDefRefOrSpec(): Cannot handle token: 0x%08x", token);
			FAKE_RETURN;
	}
}
tMD_TypeDef* MetaData_GetTypeDefFromFieldDef(tMD_FieldDef *pFieldDef) {
	tMetaData *pMetaData;
	U32 i;

	pMetaData = pFieldDef->pMetaData;
	for (i=pMetaData->tables.numRows[MD_TABLE_TYPEDEF]; i>0; i--) {
		tMD_TypeDef *pTypeDef;

		pTypeDef = (tMD_TypeDef*)MetaData_GetTableRow(pMetaData, MAKE_TABLE_INDEX(MD_TABLE_TYPEDEF, i));
		if (pTypeDef->fieldList <= pFieldDef->tableIndex) {
			return pTypeDef;
		}
	}

	Crash("MetaData_GetTypeDefFromFieldDef(): Cannot find type for field: %s", pFieldDef->name);
	FAKE_RETURN;
}
tMD_TypeDef* MetaData_GetTypeDefFromName(tMetaData *pMetaData, STRING nameSpace, STRING name, tMD_TypeDef *pInNestedClass) {
	U32 i;

	for (i=1; i<=pMetaData->tables.numRows[MD_TABLE_TYPEDEF]; i++) {
		tMD_TypeDef *pTypeDef;

		pTypeDef = (tMD_TypeDef*)MetaData_GetTableRow(pMetaData, MAKE_TABLE_INDEX(MD_TABLE_TYPEDEF, i));
		if (pInNestedClass == pTypeDef->pNestedIn &&
			strcmp(name, pTypeDef->name) == 0 &&
			(pInNestedClass != NULL || strcmp(nameSpace, pTypeDef->nameSpace) == 0)) {
			return pTypeDef;
		}
	}

	Crash("MetaData_GetTypeDefFromName(): Cannot find type %s.%s", nameSpace, name);
	FAKE_RETURN;
}
tMD_FieldDef* MetaData_GetFieldDefFromDefOrRef(tMetaData *pMetaData, IDX_TABLE token, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) {
	void *pTableEntry;

	pTableEntry = MetaData_GetTableRow(pMetaData, token);
	if (((tMDC_ToFieldDef*)pTableEntry)->pFieldDef != NULL) {
		return ((tMDC_ToFieldDef*)pTableEntry)->pFieldDef;
	}

	switch (TABLE_ID(token)) {
		case MD_TABLE_FIELDDEF:
			((tMDC_ToFieldDef*)pTableEntry)->pFieldDef = (tMD_FieldDef*)pTableEntry;
			return (tMD_FieldDef*)pTableEntry;
		case MD_TABLE_MEMBERREF:
			{
				tMD_MemberRef *pMemberRef;

				pMemberRef = (tMD_MemberRef*)pTableEntry;
				switch (TABLE_ID(pMemberRef->class_))
				{
				case MD_TABLE_TYPEREF:
				case MD_TABLE_TYPESPEC:
					{
						tMD_TypeDef *pTypeDef;
						tMD_FieldDef *pFieldDef;

						pTypeDef = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, pMemberRef->class_, ppClassTypeArgs, ppMethodTypeArgs);
						pFieldDef = FindFieldInType(pTypeDef, pMemberRef->name);
						if (TABLE_ID(pMemberRef->class_) == MD_TABLE_TYPEREF) {
							// Can't do this for TypeSpec because the resulting TypeDef will change
							// depending on what the class type arguments are.
							((tMDC_ToFieldDef*)pTableEntry)->pFieldDef = pFieldDef;
						}
						return pFieldDef;
					}
				default:
					Crash("MetaData_GetMethodDefFromMethodDefOrRef(): Cannot handle pMemberRef->class_=0x%08x", pMemberRef->class_);
				}
			}
	}

	Crash("MetaData_GetFieldDefFromDefOrRef(): Cannot handle token: 0x%08x", token);
	FAKE_RETURN;
}
tMetaData* MetaData_GetResolutionScopeMetaData(tMetaData *pMetaData, IDX_TABLE resolutionScopeToken, tMD_TypeDef **ppInNestedType) {
	switch (TABLE_ID(resolutionScopeToken)) {
		case MD_TABLE_ASSEMBLYREF:
			{
				tMD_AssemblyRef *pAssemblyRef;

				pAssemblyRef = (tMD_AssemblyRef*)MetaData_GetTableRow(pMetaData, resolutionScopeToken);
				*ppInNestedType = NULL;
				return CLIFile_GetMetaDataForAssembly(pAssemblyRef->name);
			}
		case MD_TABLE_TYPEREF:
			{
				tMD_TypeDef *pTypeDef;

				pTypeDef = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, resolutionScopeToken, NULL, NULL);
				*ppInNestedType = pTypeDef;
				return pTypeDef->pMetaData;
			}
		default:
			Crash("MetaData_GetResolutionScopeMetaData(): Cannot resolve token: 0x%08x", resolutionScopeToken);
			FAKE_RETURN;
	}
}
Example #11
0
tMetaData* CLIFile_GetMetaDataForAssembly(unsigned char *pAssemblyName) {
	tFilesLoaded *pFiles;

	// Convert "mscorlib" to "corlib"
	if (strcmp(pAssemblyName, "mscorlib") == 0) {
		pAssemblyName = "corlib";
	}

	// Look in already-loaded files first
	pFiles = pFilesLoaded;
	while (pFiles != NULL) {
		tCLIFile *pCLIFile;
		tMD_Assembly *pThisAssembly;

		pCLIFile = pFiles->pCLIFile;
		// Get the assembly info - there is only ever one of these in the each file's metadata
		pThisAssembly = MetaData_GetTableRow(pCLIFile->pMetaData, MAKE_TABLE_INDEX(0x20, 1));
		if (strcmp(pAssemblyName, pThisAssembly->name) == 0) {
			// Found the correct assembly, so return its meta-data
			return pCLIFile->pMetaData;
		}
		pFiles = pFiles->pNext;
	}

	// Assembly not loaded, so load it if possible
	{
		tCLIFile *pCLIFile;
		unsigned char fileName[128];
		sprintf(fileName, "%s.dll", pAssemblyName);
		pCLIFile = CLIFile_Load(fileName);
		if (pCLIFile == NULL) {
			Crash("Cannot load required assembly file: %s", fileName);
		}
		return pCLIFile->pMetaData;
	}
}
Example #12
0
static void GetMethodDefs() {
	IDX_TABLE token, last;
	tMetaData *pMetaData;

	pMetaData = types[TYPE_SYSTEM_ARRAY_NO_TYPE]->pMetaData;
	last = types[TYPE_SYSTEM_ARRAY_NO_TYPE]->isLast?
		MAKE_TABLE_INDEX(MD_TABLE_METHODDEF, pMetaData->tables.numRows[MD_TABLE_METHODDEF]):
		(types[TYPE_SYSTEM_ARRAY_NO_TYPE][1].methodList - 1);
	token = types[TYPE_SYSTEM_ARRAY_NO_TYPE]->methodList;
	for (; token <= last; token++) {
		tMD_MethodDef *pMethod;
		U32 i;

		pMethod = (tMD_MethodDef*)MetaData_GetTableRow(pMetaData, token);
		for (i=0; i<GENERICARRAYMETHODS_NUM; i++) {
			if (strcmp(pMethod->name, pGenericArrayMethodsInit[i]) == 0) {
				ppGenericArrayMethods[i] = pMethod;
				break;
			}
		}

	}
	genericArrayMethodsInited = 1;
}
STRING MetaData_GetModuleRefName(tMetaData *pMetaData, IDX_TABLE memberRefToken) {
	tMD_ModuleRef *pModRef = (tMD_ModuleRef*)MetaData_GetTableRow(pMetaData, memberRefToken);
	return pModRef->name;
}
// Return pointer to the relevant Def structure.
// pObjectType returns:
// 0 - tMD_TypeDef
// 1 - tMD_MethodDef
// 2 - tMD_FieldDef
// (These link up with the JIT_LOADTOKEN_* opcodes)
PTR MetaData_GetTypeMethodField(tMetaData *pMetaData, IDX_TABLE token, U32 *pObjectType, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) {
	switch (TABLE_ID(token)) {
		case MD_TABLE_TYPEDEF:
		case MD_TABLE_TYPEREF:
		case MD_TABLE_TYPESPEC:
			{
				tMD_TypeDef *pTypeDef;

				pTypeDef = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs);
				MetaData_Fill_TypeDef(pTypeDef, NULL, NULL);
				*pObjectType = 0;
				return (PTR)pTypeDef;
			}
		case MD_TABLE_METHODDEF:
method:
			{
				tMD_MethodDef *pMethodDef;

				pMethodDef = MetaData_GetMethodDefFromDefRefOrSpec(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs);
				if (pMethodDef->isFilled == 0) {
					tMD_TypeDef *pTypeDef;

					pTypeDef = MetaData_GetTypeDefFromMethodDef(pMethodDef);
					MetaData_Fill_TypeDef(pTypeDef, NULL, NULL);
				}
				*pObjectType = 1;
				return (PTR)pMethodDef;
			}
		case MD_TABLE_FIELDDEF:
field:
			{
				tMD_FieldDef *pFieldDef;

				pFieldDef = MetaData_GetFieldDefFromDefOrRef(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs);
				if (pFieldDef->pParentType == NULL) {
					tMD_TypeDef *pTypeDef;

					pTypeDef = MetaData_GetTypeDefFromFieldDef(pFieldDef);
					MetaData_Fill_TypeDef(pTypeDef, NULL, NULL);
				}
				*pObjectType = 2;
				return (PTR)pFieldDef;
			}
		case MD_TABLE_MEMBERREF:
			{
				tMD_MemberRef *pMemberRef;
				SIG sig;

				pMemberRef = (tMD_MemberRef*)MetaData_GetTableRow(pMetaData, token);
				sig = MetaData_GetBlob(pMemberRef->signature, NULL);
				if (*(U8*)sig == 0x06) {
					// Field
					goto field;
				} else {
					// Method
					goto method;
				}
			}
	}

	Crash("MetaData_GetTypeMethodField(): Cannot handle token: 0x%08x", token);
	FAKE_RETURN;
}
Example #15
0
static tCLIFile* LoadPEFile(void *pData) {
	tCLIFile *pRet = TMALLOC(tCLIFile);

	unsigned char *pMSDOSHeader = (unsigned char*)&(((unsigned char*)pData)[0]);
	unsigned char *pPEHeader;
	unsigned char *pPEOptionalHeader;
	unsigned char *pPESectionHeaders;
	unsigned char *pCLIHeader;
	unsigned char *pRawMetaData;

	int i;
	unsigned int lfanew;
	unsigned short machine;
	int numSections;
	unsigned int imageBase;
	int fileAlignment;
	unsigned int cliHeaderRVA, cliHeaderSize;
	unsigned int metaDataRVA, metaDataSize;
	tMetaData *pMetaData;

	pRet->pRVA = RVA();
	pRet->pMetaData = pMetaData = MetaData();

	lfanew = *(unsigned int*)&(pMSDOSHeader[0x3c]);
	pPEHeader = pMSDOSHeader + lfanew + 4;
	pPEOptionalHeader = pPEHeader + 20;
	pPESectionHeaders = pPEOptionalHeader + 224;

	machine = *(unsigned short*)&(pPEHeader[0]);
	if (machine != DOT_NET_MACHINE) {
		return NULL;
	}
	numSections = *(unsigned short*)&(pPEHeader[2]);

	imageBase = *(unsigned int*)&(pPEOptionalHeader[28]);
	fileAlignment = *(int*)&(pPEOptionalHeader[36]);

	for (i=0; i<numSections; i++) {
		unsigned char *pSection = pPESectionHeaders + i * 40;
		RVA_Create(pRet->pRVA, pData, pSection);
	}

	cliHeaderRVA = *(unsigned int*)&(pPEOptionalHeader[208]);
	cliHeaderSize = *(unsigned int*)&(pPEOptionalHeader[212]);

	pCLIHeader = RVA_FindData(pRet->pRVA, cliHeaderRVA);

	metaDataRVA = *(unsigned int*)&(pCLIHeader[8]);
	metaDataSize = *(unsigned int*)&(pCLIHeader[12]);
	pRet->entryPoint = *(unsigned int*)&(pCLIHeader[20]);
	pRawMetaData = RVA_FindData(pRet->pRVA, metaDataRVA);

	// Load all metadata
	{
		unsigned int versionLen = *(unsigned int*)&(pRawMetaData[12]);
		unsigned int ofs, numberOfStreams;
		void *pTableStream = NULL;
		unsigned int tableStreamSize;
		pRet->pVersion = &(pRawMetaData[16]);
		log_f(1, "CLI version: %s\n", pRet->pVersion);
		ofs = 16 + versionLen;
		numberOfStreams = *(unsigned short*)&(pRawMetaData[ofs + 2]);
		ofs += 4;

		for (i=0; i<(signed)numberOfStreams; i++) {
			unsigned int streamOffset = *(unsigned int*)&pRawMetaData[ofs];
			unsigned int streamSize = *(unsigned int*)&pRawMetaData[ofs+4];
			unsigned char *pStreamName = &pRawMetaData[ofs+8];
			void *pStream = pRawMetaData + streamOffset;
			ofs += (unsigned int)((strlen(pStreamName)+4) & (~0x3)) + 8;
			if (strcasecmp(pStreamName, "#Strings") == 0) {
				MetaData_LoadStrings(pMetaData, pStream, streamSize);
			} else if (strcasecmp(pStreamName, "#US") == 0) {
				MetaData_LoadUserStrings(pMetaData, pStream, streamSize);
			} else if (strcasecmp(pStreamName, "#Blob") == 0) {
				MetaData_LoadBlobs(pMetaData, pStream, streamSize);
			} else if (strcasecmp(pStreamName, "#GUID") == 0) {
				MetaData_LoadGUIDs(pMetaData, pStream, streamSize);
			} else if (strcasecmp(pStreamName, "#~") == 0) {
				pTableStream = pStream;
				tableStreamSize = streamSize;
			}
		}
		// Must load tables last
		if (pTableStream != NULL) {
			MetaData_LoadTables(pMetaData, pRet->pRVA, pTableStream, tableStreamSize);
		}
	}

	// Mark all generic definition types and methods as such
	for (i=pMetaData->tables.numRows[MD_TABLE_GENERICPARAM]; i>0; i--) {
		tMD_GenericParam *pGenericParam;
		IDX_TABLE ownerIdx;

		pGenericParam = (tMD_GenericParam*)MetaData_GetTableRow
			(pMetaData, MAKE_TABLE_INDEX(MD_TABLE_GENERICPARAM, i));
		ownerIdx = pGenericParam->owner;
		switch (TABLE_ID(ownerIdx)) {
			case MD_TABLE_TYPEDEF:
				{
					tMD_TypeDef *pTypeDef = (tMD_TypeDef*)MetaData_GetTableRow(pMetaData, ownerIdx);
					pTypeDef->isGenericDefinition = 1;
				}
				break;
			case MD_TABLE_METHODDEF:
				{
					tMD_MethodDef *pMethodDef = (tMD_MethodDef*)MetaData_GetTableRow(pMetaData, ownerIdx);
					pMethodDef->isGenericDefinition = 1;
				}
				break;
			default:
				Crash("Wrong generic parameter owner: 0x%08x", ownerIdx);
		}
	}

	// Mark all nested classes as such
	for (i=pMetaData->tables.numRows[MD_TABLE_NESTEDCLASS]; i>0; i--) {
		tMD_NestedClass *pNested;
		tMD_TypeDef *pParent, *pChild;

		pNested = (tMD_NestedClass*)MetaData_GetTableRow(pMetaData, MAKE_TABLE_INDEX(MD_TABLE_NESTEDCLASS, i));
		pParent = (tMD_TypeDef*)MetaData_GetTableRow(pMetaData, pNested->enclosingClass);
		pChild = (tMD_TypeDef*)MetaData_GetTableRow(pMetaData, pNested->nestedClass);
		pChild->pNestedIn = pParent;
	}

	return pRet;
}
Example #16
0
void MetaData_Fill_TypeDef_(tMD_TypeDef *pTypeDef, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) 
{
	IDX_TABLE firstIdx, lastIdx, token;
	U32 instanceMemSize, staticMemSize, virtualOfs, i, j;
	tMetaData *pMetaData;
	tMD_TypeDef *pParent;

	pMetaData = pTypeDef->pMetaData;
	pTypeDef->isFilled = 1;
	pTypeDef->pTypeDef = pTypeDef;

	pTypeDef->pParent = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, pTypeDef->extends, ppClassTypeArgs, ppMethodTypeArgs);
	pParent = pTypeDef->pParent;

	if (pParent != NULL) 
	{
		MetaData_Fill_TypeDef(pParent, NULL, NULL);
		virtualOfs = pParent->numVirtualMethods;
	} 
	else 
	{
		virtualOfs = 0;
	}
	pTypeDef->isValueType = (U8)Type_IsValueType(pTypeDef);

	// If not primed, then work out how many methods & fields there are.
	if (!pTypeDef->isPrimed)
	{
		// Methods
		lastIdx = (pTypeDef->isLast)?
			MAKE_TABLE_INDEX(MD_TABLE_METHODDEF, pTypeDef->pMetaData->tables.numRows[MD_TABLE_METHODDEF]):
			(pTypeDef[1].methodList - 1);
		pTypeDef->numMethods = lastIdx - pTypeDef->methodList + 1;
		// Fields
		lastIdx = (pTypeDef->isLast)?
			MAKE_TABLE_INDEX(MD_TABLE_FIELDDEF, pTypeDef->pMetaData->tables.numRows[MD_TABLE_FIELDDEF]):
			(pTypeDef[1].fieldList - 1);
		pTypeDef->numFields = lastIdx - pTypeDef->fieldList + 1;
	}

	// Must create the virtual method table BEFORE any other type resolution is done
	// Note that this must not do ANY filling of types or methods.
	// This is to ensure that the parent object(s) in any type inheritance hierachy are allocated
	// their virtual method offset before derived types.
	firstIdx = pTypeDef->methodList;
	lastIdx = firstIdx + pTypeDef->numMethods - 1;
	// This only needs to be done for non-generic types, or for generic types that are not a definition
	// I.e. Fully instantiated generic types
	if (!pTypeDef->isGenericDefinition) 
	{
		for (token = firstIdx; token <= lastIdx; token++)
		{
			tMD_MethodDef *pMethodDef;

			pMethodDef = MetaData_GetMethodDefFromDefRefOrSpec(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs);

			// This is needed, so array resolution can work correctly and FindVirtualOverriddenMethod() can work.
			pMethodDef->pParentType = pTypeDef;

			if (METHOD_ISVIRTUAL(pMethodDef))
			{
				if (METHOD_ISNEWSLOT(pMethodDef) || pTypeDef->pParent == NULL) 
				{
					// Allocate a new vTable slot if method is explicitly marked as NewSlot, or
					// this is of type Object.
					pMethodDef->vTableOfs = virtualOfs++;
				} 
				else 
				{
					tMD_MethodDef *pVirtualOveriddenMethod;

					pVirtualOveriddenMethod = FindVirtualOverriddenMethod(pTypeDef->pParent, pMethodDef);
					Assert(pVirtualOveriddenMethod != NULL);
					pMethodDef->vTableOfs = pVirtualOveriddenMethod->vTableOfs;
				}
			} 
			else 
			{
				// Dummy value - make it obvious it's not valid!
				pMethodDef->vTableOfs = 0xffffffff;
			}

		}
		// Create the virtual method table
		pTypeDef->numVirtualMethods = virtualOfs;

		// Resolve fields, members, interfaces.
		// Only needs to be done if it's not a generic definition type

		// It it's not a value-type and the stack-size is not preset, then set it up now.
		// It needs to be done here as non-static fields in non-value types can point to the containing type
		if (pTypeDef->stackSize == 0 && !pTypeDef->isValueType)
		{
			pTypeDef->stackType = EVALSTACK_O;
			pTypeDef->stackSize = sizeof(void*);
		}
		// Resolve all fields - instance ONLY at this point,
		// because static fields in value-types can be of the containing type, and the size is not yet known.
		firstIdx = pTypeDef->fieldList;
		lastIdx = firstIdx + pTypeDef->numFields - 1;
		staticMemSize = 0;
		if (pTypeDef->numFields > 0) 
		{
			pTypeDef->ppFields = mallocForever(pTypeDef->numFields * sizeof(tMD_FieldDef*));
		}
		instanceMemSize = (pTypeDef->pParent == NULL)?0:pTypeDef->pParent->instanceMemSize;
		for (token = firstIdx, i=0; token <= lastIdx; token++, i++) 
		{
			tMD_FieldDef *pFieldDef;

			pFieldDef = MetaData_GetFieldDefFromDefOrRef(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs);
			if (!FIELD_ISSTATIC(pFieldDef))
			{
				// Only handle non-static fields at the moment
				if (pTypeDef->pGenericDefinition != NULL)
				{
					// If this is a generic instantiation type, then all field defs need to be copied,
					// as there will be lots of different instantiations.
					tMD_FieldDef *pFieldCopy = TMALLOCFOREVER(tMD_FieldDef);
					memcpy(pFieldCopy, pFieldDef, sizeof(tMD_FieldDef));
					pFieldDef = pFieldCopy;
				}
				if (FIELD_ISLITERAL(pFieldDef) || FIELD_HASFIELDRVA(pFieldDef))
				{
					// If it's a literal, then analyse the field, but don't include it in any memory allocation
					// If is has an RVA, then analyse the field, but don't include it in any memory allocation
					MetaData_Fill_FieldDef(pTypeDef, pFieldDef, 0, ppClassTypeArgs);
				}
				else 
				{
					MetaData_Fill_FieldDef(pTypeDef, pFieldDef, instanceMemSize, ppClassTypeArgs);
					instanceMemSize += pFieldDef->memSize;
				}
				pTypeDef->ppFields[i] = pFieldDef;
			}
		}
		if (pTypeDef->instanceMemSize == 0)
		{
			pTypeDef->instanceMemSize = instanceMemSize;
		}

		// Sort out stack type and size.
		// Note that this may already be set, as some basic types have this preset;
		// or if it's not a value-type it'll already be set
		if (pTypeDef->stackSize == 0) 
		{
			// if it gets here then it must be a value type
			pTypeDef->stackType = EVALSTACK_VALUETYPE;
			pTypeDef->stackSize = pTypeDef->instanceMemSize;
		}
		// Sort out array element size. Note that some basic types will have this preset.
		if (pTypeDef->arrayElementSize == 0) 
		{
			pTypeDef->arrayElementSize = pTypeDef->stackSize;
		}

		// Handle static fields
		for (token = firstIdx, i=0; token <= lastIdx; token++, i++)
		{
			tMD_FieldDef *pFieldDef;

			pFieldDef = MetaData_GetFieldDefFromDefOrRef(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs);
			if (FIELD_ISSTATIC(pFieldDef))
			{
				// Only handle static fields here
				if (pTypeDef->pGenericDefinition != NULL)
				{
					// If this is a generic instantiation type, then all field defs need to be copied,
					// as there will be lots of different instantiations.
					tMD_FieldDef *pFieldCopy = TMALLOCFOREVER(tMD_FieldDef);
					memcpy(pFieldCopy, pFieldDef, sizeof(tMD_FieldDef));
					pFieldDef = pFieldCopy;
				}
				if (FIELD_ISLITERAL(pFieldDef) || FIELD_HASFIELDRVA(pFieldDef))
				{
					// If it's a literal, then analyse the field, but don't include it in any memory allocation
					// If is has an RVA, then analyse the field, but don't include it in any memory allocation
					MetaData_Fill_FieldDef(pTypeDef, pFieldDef, 0, ppClassTypeArgs);
				} 
				else
				{
					MetaData_Fill_FieldDef(pTypeDef, pFieldDef, staticMemSize, ppClassTypeArgs);
					staticMemSize += pFieldDef->memSize;
				}
				pTypeDef->ppFields[i] = pFieldDef;
			}
		}
		if (staticMemSize > 0) {
			pTypeDef->pStaticFields = mallocForever(staticMemSize);
			memset(pTypeDef->pStaticFields, 0, staticMemSize);
			// Set the field addresses (->pMemory) of all static fields
			for (i = 0; i<pTypeDef->numFields; i++) {
				tMD_FieldDef *pFieldDef;

				pFieldDef = pTypeDef->ppFields[i];
				if (FIELD_ISSTATIC(pFieldDef) && pFieldDef->pMemory == NULL) {
					// Only set it if it isn't already set. It will be already set if this field has an RVA
					pFieldDef->pMemory = pTypeDef->pStaticFields + pFieldDef->memOffset;
				}
			}
			pTypeDef->staticFieldSize = staticMemSize;
		}

		// Resolve all members
		firstIdx = pTypeDef->methodList;
		lastIdx = firstIdx + pTypeDef->numMethods - 1;
		pTypeDef->ppMethods = mallocForever(pTypeDef->numMethods * sizeof(tMD_MethodDef*));
		pTypeDef->pVTable = mallocForever(pTypeDef->numVirtualMethods * sizeof(tMD_MethodDef*));
		// Copy initial vTable from parent
		if (pTypeDef->pParent != NULL) {
			memcpy(pTypeDef->pVTable, pTypeDef->pParent->pVTable, pTypeDef->pParent->numVirtualMethods * sizeof(tMD_MethodDef*));
		}
		for (token = firstIdx, i = 0; token <= lastIdx; token++, i++) {
			tMD_MethodDef *pMethodDef;

			pMethodDef = MetaData_GetMethodDefFromDefRefOrSpec(pMetaData, token, ppClassTypeArgs, ppMethodTypeArgs);
			if (pTypeDef->pGenericDefinition != NULL) {
				// If this is a generic instantiation type, then all method defs need to be copied,
				// as there will be lots of different instantiations.
				tMD_MethodDef *pMethodCopy = TMALLOCFOREVER(tMD_MethodDef);
				memcpy(pMethodCopy, pMethodDef, sizeof(tMD_MethodDef));
				pMethodDef = pMethodCopy;
			}
			if (METHOD_ISSTATIC(pMethodDef) && strcmp(pMethodDef->name, ".cctor") == 0) {
				// This is a static constructor
				pTypeDef->pStaticConstructor = pMethodDef;
			}
			if (!METHOD_ISSTATIC(pMethodDef) && pTypeDef->pParent != NULL &&
				strcmp(pMethodDef->name, "Finalize") == 0) {
				// This is a Finalizer method, but not for Object.
				// Delibrately miss out Object's Finalizer because it's empty and will cause every object
				// of any type to have a Finalizer which will be terrible for performance.
				pTypeDef->pFinalizer = pMethodDef;
			}
			if (METHOD_ISVIRTUAL(pMethodDef)) {
				// This is a virtual method, so enter it in the vTable
				pTypeDef->pVTable[pMethodDef->vTableOfs] = pMethodDef;
			}
			pTypeDef->ppMethods[i] = pMethodDef;
		}
		// Find inherited Finalizer, if this type doesn't have an explicit Finalizer, and if there is one
		if (pTypeDef->pFinalizer == NULL) {
			tMD_TypeDef *pInheritedType = pTypeDef->pParent;
			while (pInheritedType != NULL) {
				if (pInheritedType->pFinalizer != NULL) {
					pTypeDef->pFinalizer = pInheritedType->pFinalizer;
					break;
				}
				pInheritedType = pInheritedType->pParent;
			}
		}
		// Fill all method definitions for this type
		for (i=0; i<pTypeDef->numMethods; i++) {
			MetaData_Fill_MethodDef(pTypeDef, pTypeDef->ppMethods[i], ppClassTypeArgs, ppMethodTypeArgs);
		}

		// Map all interface method calls. This only needs to be done for Classes, not Interfaces
		// And is not done for generic definitions.
		if (!TYPE_ISINTERFACE(pTypeDef)) {
			firstIdx = 0;
			if (pTypeDef->pParent != NULL) {
				j = pTypeDef->numInterfaces = pTypeDef->pParent->numInterfaces;
			} else {
				j = 0;
			}
			// TODO: Better to do this once during file load (the bit in this for loop)
			for (i=1; i<=pMetaData->tables.numRows[MD_TABLE_INTERFACEIMPL]; i++) {
				tMD_InterfaceImpl *pInterfaceImpl;

				pInterfaceImpl = (tMD_InterfaceImpl*)MetaData_GetTableRow(pMetaData, MAKE_TABLE_INDEX(MD_TABLE_INTERFACEIMPL, i));
				if (pInterfaceImpl->class_ == pTypeDef->tableIndex) {
					// count how many interfaces are implemented
					pTypeDef->numInterfaces++;
					if (firstIdx == 0) {
						firstIdx = MAKE_TABLE_INDEX(MD_TABLE_INTERFACEIMPL, i);
					}
					lastIdx = MAKE_TABLE_INDEX(MD_TABLE_INTERFACEIMPL, i);
				}
			}
			if (pTypeDef->numInterfaces > 0 && !pTypeDef->isGenericDefinition) {
				U32 mapNum;

				pTypeDef->pInterfaceMaps = (tInterfaceMap*)mallocForever(pTypeDef->numInterfaces * sizeof(tInterfaceMap));
				// Copy interface maps from parent type
				if (j > 0) {
					memcpy(pTypeDef->pInterfaceMaps, pTypeDef->pParent->pInterfaceMaps, j * sizeof(tInterfaceMap));
				}
				mapNum = j;
				if (firstIdx > 0) {
					for (token=firstIdx; token<=lastIdx; token++, mapNum++) {
						tMD_InterfaceImpl *pInterfaceImpl;

						pInterfaceImpl = (tMD_InterfaceImpl*)MetaData_GetTableRow(pMetaData, token);
						if (pInterfaceImpl->class_ == pTypeDef->tableIndex) {
							tMD_TypeDef *pInterface;
							tInterfaceMap *pMap;

							// Get the interface that this type implements
							pInterface = MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, pInterfaceImpl->interface_, ppClassTypeArgs, ppMethodTypeArgs);
							MetaData_Fill_TypeDef(pInterface, NULL, NULL);
							pMap = &pTypeDef->pInterfaceMaps[mapNum];
							pMap->pInterface = pInterface;
							pMap->pVTableLookup = (U32*)mallocForever(pInterface->numVirtualMethods * sizeof(U32));
							pMap->ppMethodVLookup = NULL;
							// Discover interface mapping for each interface method
							for (i=0; i<pInterface->numVirtualMethods; i++) {
								tMD_MethodDef *pInterfaceMethod, *pOverriddenMethod;

								pInterfaceMethod = pInterface->pVTable[i];
								pOverriddenMethod = FindVirtualOverriddenMethod(pTypeDef, pInterfaceMethod);
								Assert(pOverriddenMethod != NULL);
								pMap->pVTableLookup[i] = pOverriddenMethod->vTableOfs;
							}
						} else {
							Crash("Problem with interface class");
						}
					}
				}
			}
		}

		// If this is an enum type, then pretend its stack type is its underlying type
		if (pTypeDef->pParent == types[TYPE_SYSTEM_ENUM]) {
			pTypeDef->stackType = EVALSTACK_INT32;
		}
	}

	// If this is a nested type, then find the namespace of it
	if (pTypeDef->pNestedIn != NULL) {
		tMD_TypeDef *pRootTypeDef = pTypeDef->pNestedIn;
		while (pRootTypeDef->pNestedIn != NULL) {
			pRootTypeDef = pRootTypeDef->pNestedIn;
		}
		pTypeDef->nameSpace = pRootTypeDef->nameSpace;
	}

	log_f(2, "Type:  %s.%s\n", pTypeDef->nameSpace, pTypeDef->name);
}