tCLIFile* CLIFile_Load(char *pFileName) { void *pRawFile; tCLIFile *pRet; tFilesLoaded *pNewFile; pRawFile = LoadFileFromDisk(pFileName); if (pRawFile == NULL) { Crash("Cannot load file: %s", pFileName); } log_f(1, "\n\n\nLoading file: %s\n", pFileName); pRet = LoadPEFile(pRawFile); pRet->pFileName = (char*)mallocForever((U32)strlen(pFileName) + 1); strcpy(pRet->pFileName, pFileName); // Record that we've loaded this file pNewFile = TMALLOCFOREVER(tFilesLoaded); pNewFile->pCLIFile = pRet; pNewFile->pNext = pFilesLoaded; pFilesLoaded = pNewFile; return pRet; }
// Returns a TypeDef for an array to the given element type tMD_TypeDef* Type_GetArrayTypeDef(tMD_TypeDef *pElementType, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) { tArrayTypeDefs *pIterArrays; if (pElementType == NULL) { return types[TYPE_SYSTEM_ARRAY_NO_TYPE]; } pIterArrays = pArrays; while (pIterArrays != NULL) { if (pIterArrays->pElementType == pElementType) { return pIterArrays->pArrayType; } pIterArrays = pIterArrays->pNext; } // Must have this new array type in the linked-list of array types before it is initialised // (otherwise it can get stuck in an infinite loop) pIterArrays = TMALLOCFOREVER(tArrayTypeDefs); pIterArrays->pElementType = pElementType; pIterArrays->pNext = pArrays; pArrays = pIterArrays; pIterArrays->pArrayType = TMALLOC(tMD_TypeDef); CreateNewArrayType(pIterArrays->pArrayType, pElementType, ppClassTypeArgs, ppMethodTypeArgs); return pIterArrays->pArrayType; }
static tLoadedLib* GetLib(STRING name) { // See if it's already loaded tLoadedLib *pLib = pLoadedLibs; char libName[256]; void *pNativeLib; while (pLib != NULL) { if (strcmp(name, pLib->name) == 0) { return pLib; } } sprintf(libName, "%s%s", LIB_PREFIX, name); if (strlen(libName) >= 4) { if (strcmp(".dll", libName + strlen(libName) - 4) == 0) { // Cut off the ".dll" suffix if it's there libName[strlen(libName) - 4] = 0; } } // Not loaded, so load it sprintf(strchr(libName, 0), ".%s", LIB_SUFFIX); #if WIN32 pNativeLib = LoadLibraryA(libName); #else pNativeLib = dlopen(libName, DL_LAZY); #endif if (pNativeLib == NULL) { // Failed to load library printf("Failed to load library: %s\n", libName); #ifndef WIN32 { char *pError; pError = dlerror(); if (pError) { printf("dlopen() Error: '%s'",pError); } } #endif return NULL; } pLib = TMALLOCFOREVER(tLoadedLib); pLib->pNext = pLoadedLibs; pLoadedLibs = pLib; pLib->name = name; pLib->pLib = pNativeLib; return pLib; }
tMD_MethodDef* Generics_GetMethodDefFromCoreMethod (tMD_MethodDef *pCoreMethod, tMD_TypeDef *pParentType, U32 numTypeArgs, tMD_TypeDef **ppTypeArgs) { tGenericMethodInstance *pInst; tMD_MethodDef *pMethod; // See if we already have an instance with the given type args pInst = pCoreMethod->pGenericMethodInstances; while (pInst != NULL) { if (pInst->numTypeArgs == numTypeArgs && memcmp(pInst->pTypeArgs, ppTypeArgs, numTypeArgs * sizeof(tMD_TypeDef*)) == 0) { return pInst->pInstanceMethodDef; } pInst = pInst->pNext; } // We don't have an instance so create one now. pInst = mallocForever(sizeof(tGenericMethodInstance) + numTypeArgs * sizeof(tMD_TypeDef*)); pInst->pNext = pCoreMethod->pGenericMethodInstances; pCoreMethod->pGenericMethodInstances = pInst; pInst->numTypeArgs = numTypeArgs; memcpy(pInst->pTypeArgs, ppTypeArgs, numTypeArgs * sizeof(tMD_TypeDef*)); pInst->pInstanceMethodDef = pMethod = TMALLOCFOREVER(tMD_MethodDef); memset(pMethod, 0, sizeof(tMD_MethodDef)); pMethod->pMethodDef = pMethod; pMethod->pMetaData = pCoreMethod->pMetaData; pMethod->pCIL = pCoreMethod->pCIL; pMethod->implFlags = pCoreMethod->implFlags; pMethod->flags = pCoreMethod->flags; pMethod->name = pCoreMethod->name; pMethod->signature = pCoreMethod->signature; pMethod->vTableOfs = pCoreMethod->vTableOfs; pMethod->ppMethodTypeArgs = pInst->pTypeArgs; MetaData_Fill_MethodDef(pParentType, pMethod, pParentType->ppClassTypeArgs, pInst->pTypeArgs); return pMethod; }
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); }
tMD_TypeDef* Generics_GetGenericTypeFromCoreType(tMD_TypeDef *pCoreType, U32 numTypeArgs, tMD_TypeDef **ppTypeArgs) { tGenericInstance *pInst; tMD_TypeDef *pTypeDef; U32 i; unsigned char name[2048]; tMetaData *pMetaData; pMetaData = pCoreType->pMetaData; MetaData_Fill_TypeDef(pCoreType, NULL, NULL); // See if we have already built an instantiation of this type with the given type args. pInst = pCoreType->pGenericInstances; while (pInst != NULL) { if (pInst->numTypeArgs == numTypeArgs && memcmp(pInst->pTypeArgs, ppTypeArgs, numTypeArgs * sizeof(tMD_TypeDef*)) == 0) { return pInst->pInstanceTypeDef; } pInst = pInst->pNext; } // This has not already been instantiated, so instantiate it now. pInst = (tGenericInstance*)mallocForever(sizeof(tGenericInstance) + numTypeArgs * sizeof(tMD_TypeDef*)); // Insert this into the chain of instantiations. pInst->pNext = pCoreType->pGenericInstances; pCoreType->pGenericInstances = pInst; // Copy the type args into the instantiation. pInst->numTypeArgs = numTypeArgs; memcpy(pInst->pTypeArgs, ppTypeArgs, numTypeArgs * sizeof(tMD_TypeDef*)); // Create the new instantiated type pInst->pInstanceTypeDef = pTypeDef = TMALLOCFOREVER(tMD_TypeDef); memset(pTypeDef, 0, sizeof(tMD_TypeDef)); // Make the name of the instantiation. strcpy(name, pCoreType->name); strcat(name, "["); for (i=0; i<numTypeArgs; i++) { if (i > 0) { strcat(name, ","); } if (ppTypeArgs[i] != NULL) { sprintf(strchr(name, 0), "%s.%s", ppTypeArgs[i]->nameSpace, ppTypeArgs[i]->name); } else { tMD_GenericParam *pGenericParam = FindGenericParam(pCoreType, i); if (pGenericParam != NULL) { sprintf(strchr(name, 0), pGenericParam->name); } else { sprintf(strchr(name, 0), "???"); } } } strcat(name, "]"); // Fill in the basic bits of the new type def. pTypeDef->pTypeDef = pTypeDef; pTypeDef->pMetaData = pMetaData; pTypeDef->flags = pCoreType->flags; pTypeDef->pGenericDefinition = pCoreType; for (i=0; i<numTypeArgs; i++) { if (ppTypeArgs[i] == NULL) { pTypeDef->isGenericDefinition = 1; break; } } pTypeDef->nameSpace = pCoreType->nameSpace; pTypeDef->name = (STRING)mallocForever((U32)strlen(name)+1); strcpy(pTypeDef->name, name); pTypeDef->ppClassTypeArgs = pInst->pTypeArgs; pTypeDef->extends = pCoreType->extends; pTypeDef->tableIndex = pCoreType->tableIndex; pTypeDef->fieldList = pCoreType->fieldList; pTypeDef->methodList = pCoreType->methodList; pTypeDef->numFields = pCoreType->numFields; pTypeDef->numMethods = pCoreType->numMethods; pTypeDef->numVirtualMethods = pCoreType->numVirtualMethods; pTypeDef->pNestedIn = pCoreType->pNestedIn; pTypeDef->isPrimed = 1; MetaData_Fill_TypeDef_(pTypeDef, ppTypeArgs, NULL); return pTypeDef; }