static tMD_MethodDef* FindMethodInType(tMD_TypeDef *pTypeDef, STRING name, tMetaData *pSigMetaData, BLOB_ sigBlob, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) { U32 i; tMD_TypeDef *pLookInType = pTypeDef; do { for (i=0; i<pLookInType->numMethods; i++) { if (MetaData_CompareNameAndSig(name, sigBlob, pSigMetaData, ppClassTypeArgs, ppMethodTypeArgs, pLookInType->ppMethods[i], pLookInType->ppClassTypeArgs, NULL)) { return pLookInType->ppMethods[i]; } } pLookInType = pLookInType->pParent; } while (pLookInType != NULL); { // Error reporting!! U32 entry, numParams, i; SIG sig; char *pMsg; tMD_TypeDef *pParamTypeDef; pMsg = (char*)malloc(2048); *pMsg = 0; sig = MetaData_GetBlob(sigBlob, &i); entry = MetaData_DecodeSigEntry(&sig); if ((entry & SIG_METHODDEF_HASTHIS) == 0) { sprintf(strchr(pMsg, 0), "static "); } if (entry & SIG_METHODDEF_GENERIC) { // read number of generic type args - don't care what it is MetaData_DecodeSigEntry(&sig); } numParams = MetaData_DecodeSigEntry(&sig); pParamTypeDef = Type_GetTypeFromSig(pSigMetaData, &sig, ppClassTypeArgs, ppMethodTypeArgs); // return type if (pParamTypeDef != NULL) { sprintf(strchr(pMsg, 0), "%s ", pParamTypeDef->name); } sprintf(strchr(pMsg, 0), "%s.%s.%s(", pTypeDef->nameSpace, pTypeDef->name, name); for (i=0; i<numParams; i++) { pParamTypeDef = Type_GetTypeFromSig(pSigMetaData, &sig, ppClassTypeArgs, ppMethodTypeArgs); if (i > 0) { sprintf(strchr(pMsg, 0), ","); } if (pParamTypeDef != NULL) { sprintf(strchr(pMsg, 0), pParamTypeDef->name); } else { sprintf(strchr(pMsg, 0), "???"); } } Crash("FindMethodInType(): Cannot find method %s)", pMsg); } FAKE_RETURN; }
U32 MetaData_CompareNameAndSig(STRING name, BLOB_ sigBlob, tMetaData *pSigMetaData, tMD_TypeDef **ppSigClassTypeArgs, tMD_TypeDef **ppSigMethodTypeArgs, tMD_MethodDef *pMethod, tMD_TypeDef **ppMethodClassTypeArgs, tMD_TypeDef **ppMethodMethodTypeArgs) { if (strcmp(name, pMethod->name) == 0) { SIG sig, thisSig; U32 e, thisE, paramCount, i; sig = MetaData_GetBlob(sigBlob, NULL); thisSig = MetaData_GetBlob(pMethod->signature, NULL); e = MetaData_DecodeSigEntry(&sig); thisE = MetaData_DecodeSigEntry(&thisSig); // Check method call type (static, etc...) if (e != thisE) { return 0; } // If method has generic arguments, check the generic type argument count if (e & SIG_METHODDEF_GENERIC) { e = MetaData_DecodeSigEntry(&sig); thisE = MetaData_DecodeSigEntry(&thisSig); // Generic argument count if (e != thisE) { return 0; } } e = MetaData_DecodeSigEntry(&sig); thisE = MetaData_DecodeSigEntry(&thisSig); // check parameter count if (e != thisE) { return 0; } paramCount = e + 1; // +1 to include the return type // check all parameters for (i=0; i<paramCount; i++) { tMD_TypeDef *pParamType, *pThisParamType; pParamType = Type_GetTypeFromSig(pSigMetaData, &sig, ppSigClassTypeArgs, ppSigMethodTypeArgs); pThisParamType = Type_GetTypeFromSig(pMethod->pMetaData, &thisSig, ppMethodClassTypeArgs, ppMethodMethodTypeArgs); if (pParamType != pThisParamType) { return 0; } } // All parameters the same, so found the right method return 1; } return 0; }
tMD_MethodDef* Generics_GetMethodDefFromSpec (tMD_MethodSpec *pMethodSpec, tMD_TypeDef **ppCallingClassTypeArgs, tMD_TypeDef **ppCallingMethodTypeArgs) { tMD_MethodDef *pCoreMethod, *pMethod; SIG sig; U32 argCount, i; tMD_TypeDef **ppTypeArgs; pCoreMethod = MetaData_GetMethodDefFromDefRefOrSpec(pMethodSpec->pMetaData, pMethodSpec->method, NULL, NULL);//ppCallingClassTypeArgs, ppCallingMethodTypeArgs); //ppClassTypeArgs = pCoreMethod->pParentType->ppClassTypeArgs; sig = MetaData_GetBlob(pMethodSpec->instantiation, NULL); MetaData_DecodeSigEntry(&sig); // always 0x0a argCount = MetaData_DecodeSigEntry(&sig); ppTypeArgs = malloc(argCount * sizeof(tMD_TypeDef*)); for (i=0; i<argCount; i++) { tMD_TypeDef *pArgType; pArgType = Type_GetTypeFromSig(pMethodSpec->pMetaData, &sig, ppCallingClassTypeArgs, ppCallingMethodTypeArgs); ppTypeArgs[i] = pArgType; } pMethod = Generics_GetMethodDefFromCoreMethod(pCoreMethod, pCoreMethod->pParentType, argCount, ppTypeArgs); free(ppTypeArgs); return pMethod; }
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; } } } }
tMD_TypeDef* Generics_GetGenericTypeFromSig (tMetaData *pMetaData, SIG *pSig, tMD_TypeDef **ppCallingClassTypeArgs, tMD_TypeDef **ppCallingMethodTypeArgs) { tMD_TypeDef *pCoreType, *pRet; U32 numTypeArgs, i; tMD_TypeDef **ppTypeArgs; pCoreType = Type_GetTypeFromSig(pMetaData, pSig, ppCallingClassTypeArgs, ppCallingMethodTypeArgs); MetaData_Fill_TypeDef(pCoreType, ppCallingClassTypeArgs, ppCallingMethodTypeArgs); //NULL, NULL); numTypeArgs = MetaData_DecodeSigEntry(pSig); ppTypeArgs = (tMD_TypeDef**)malloc(numTypeArgs * sizeof(tMD_TypeDef*)); for (i=0; i<numTypeArgs; i++) { ppTypeArgs[i] = Type_GetTypeFromSig(pMetaData, pSig, ppCallingClassTypeArgs, ppCallingMethodTypeArgs); if (ppTypeArgs[i] != NULL) { MetaData_Fill_TypeDef(ppTypeArgs[i], NULL, NULL); } } pRet = Generics_GetGenericTypeFromCoreType(pCoreType, numTypeArgs, ppTypeArgs); free(ppTypeArgs); return pRet; }
U32 Type_IsMethod(tMD_MethodDef *pMethod, STRING name, tMD_TypeDef *pReturnType, U32 numParams, U8 *pParamTypeIndexs) { SIG sig; U32 sigLen, numSigParams, i, nameLen; nameLen = (U32)strlen(name); if (name[nameLen-1] == '>') { // Generic instance method if (strncmp(pMethod->name, name, nameLen - 1) != 0) { return 0; } } else { if (strcmp(pMethod->name, name) != 0) { return 0; } } sig = MetaData_GetBlob(pMethod->signature, &sigLen); i = MetaData_DecodeSigEntry(&sig); // Don't care about this if (i & SIG_METHODDEF_GENERIC) { MetaData_DecodeSigEntry(&sig); } numSigParams = MetaData_DecodeSigEntry(&sig); if (numParams != numSigParams) { return 0; } if (pReturnType == types[TYPE_SYSTEM_VOID]) { pReturnType = NULL; } for (i=0; i<numParams + 1; i++) { tMD_TypeDef *pSigType, *pParamType; pSigType = Type_GetTypeFromSig(pMethod->pMetaData, &sig, NULL, NULL); pParamType = (i == 0)?pReturnType:types[pParamTypeIndexs[i-1]]; if (pSigType != NULL && TYPE_ISARRAY(pSigType) && pParamType == types[TYPE_SYSTEM_ARRAY_NO_TYPE]) { // It's ok... } else { if (pSigType != pParamType) { goto endBad; } } } return 1; endBad: return 0; }
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; } }
void MetaData_Fill_MethodDef(tMD_TypeDef *pParentType, tMD_MethodDef *pMethodDef, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) { SIG sig; U32 i, entry, totalSize; pMethodDef->pParentType = pParentType; pMethodDef->pMethodDef = pMethodDef; pMethodDef->isFilled = 1; if (pMethodDef->isGenericDefinition) { // Generic definition method, so can't do any more. log_f(3, "Loaded Generic Method: %s.%s.%s()\n", pParentType->nameSpace, pParentType->name, pMethodDef->name); return; } sig = MetaData_GetBlob(pMethodDef->signature, NULL); entry = MetaData_DecodeSigEntry(&sig); if (entry & SIG_METHODDEF_GENERIC) { // Has generic parameters. Read how many, but don't care about the answer MetaData_DecodeSigEntry(&sig); } pMethodDef->numberOfParameters = MetaData_DecodeSigEntry(&sig) + (METHOD_ISSTATIC(pMethodDef)?0:1); pMethodDef->pReturnType = Type_GetTypeFromSig(pMethodDef->pMetaData, &sig, ppClassTypeArgs, ppMethodTypeArgs); if (pMethodDef->pReturnType != NULL) { MetaData_Fill_TypeDef(pMethodDef->pReturnType, NULL, NULL); } pMethodDef->pParams = (tParameter*)malloc(pMethodDef->numberOfParameters * sizeof(tParameter)); totalSize = 0; if (!METHOD_ISSTATIC(pMethodDef)) { // Fill in parameter info for the 'this' pointer pMethodDef->pParams->offset = 0; if (pParentType->isValueType) { // If this is a value-type then the 'this' pointer is actually an IntPtr to the value-type's location pMethodDef->pParams->size = 4; pMethodDef->pParams->pTypeDef = types[TYPE_SYSTEM_INTPTR]; } else { pMethodDef->pParams->size = 4; pMethodDef->pParams->pTypeDef = pParentType; } totalSize = 4; } for (i=totalSize>>2; i<pMethodDef->numberOfParameters; i++) { tMD_TypeDef *pTypeDef; U32 size; pTypeDef = Type_GetTypeFromSig(pMethodDef->pMetaData, &sig, ppClassTypeArgs, ppMethodTypeArgs); //if (pTypeDef != NULL) { MetaData_Fill_TypeDef(pTypeDef, NULL, NULL); size = pTypeDef->stackSize; //} else { // // If this method has generic-type-argument arguments, then we can't do anything very sensible yet // size = 0; //} pMethodDef->pParams[i].pTypeDef = pTypeDef; pMethodDef->pParams[i].offset = totalSize; pMethodDef->pParams[i].size = size; totalSize += size; } pMethodDef->parameterStackSize = totalSize; log_f(3, "Loaded Method %s.%s::%s \n", pParentType->nameSpace, pParentType->name, pMethodDef->name); }
// Get the TypeDef from the type signature // Also get the size of a field from the signature // This is needed to avoid recursive sizing of types like System.Boolean, // that has a field of type System.Boolean tMD_TypeDef* Type_GetTypeFromSig(tMetaData *pMetaData, SIG *pSig, tMD_TypeDef **ppClassTypeArgs, tMD_TypeDef **ppMethodTypeArgs) { U32 entry; entry = MetaData_DecodeSigEntry(pSig); switch (entry) { case ELEMENT_TYPE_VOID: return NULL; case ELEMENT_TYPE_BOOLEAN: return types[TYPE_SYSTEM_BOOLEAN]; case ELEMENT_TYPE_CHAR: return types[TYPE_SYSTEM_CHAR]; case ELEMENT_TYPE_I1: return types[TYPE_SYSTEM_SBYTE]; case ELEMENT_TYPE_U1: return types[TYPE_SYSTEM_BYTE]; case ELEMENT_TYPE_I2: return types[TYPE_SYSTEM_INT16]; case ELEMENT_TYPE_U2: return types[TYPE_SYSTEM_UINT16]; case ELEMENT_TYPE_I4: return types[TYPE_SYSTEM_INT32]; case ELEMENT_TYPE_I8: return types[TYPE_SYSTEM_INT64]; case ELEMENT_TYPE_U8: return types[TYPE_SYSTEM_UINT64]; case ELEMENT_TYPE_U4: return types[TYPE_SYSTEM_UINT32]; case ELEMENT_TYPE_R4: return types[TYPE_SYSTEM_SINGLE]; case ELEMENT_TYPE_R8: return types[TYPE_SYSTEM_DOUBLE]; case ELEMENT_TYPE_STRING: return types[TYPE_SYSTEM_STRING]; case ELEMENT_TYPE_PTR: return types[TYPE_SYSTEM_UINTPTR]; case ELEMENT_TYPE_BYREF: { tMD_TypeDef *pByRefType; // type of the by-ref parameter, don't care pByRefType = Type_GetTypeFromSig(pMetaData, pSig, ppClassTypeArgs, ppMethodTypeArgs); } // fall-through case ELEMENT_TYPE_INTPTR: return types[TYPE_SYSTEM_INTPTR]; case ELEMENT_TYPE_VALUETYPE: case ELEMENT_TYPE_CLASS: entry = MetaData_DecodeSigEntryToken(pSig); return MetaData_GetTypeDefFromDefRefOrSpec(pMetaData, entry, ppClassTypeArgs, ppMethodTypeArgs); case ELEMENT_TYPE_VAR: entry = MetaData_DecodeSigEntry(pSig); // This is the argument number if (ppClassTypeArgs == NULL) { // Return null here as we don't yet know what the type really is. // The generic instantiation code figures this out later. return NULL; } else { return ppClassTypeArgs[entry]; } case ELEMENT_TYPE_GENERICINST: { tMD_TypeDef *pType; pType = Generics_GetGenericTypeFromSig(pMetaData, pSig, ppClassTypeArgs, ppMethodTypeArgs); return pType; } //case ELEMENT_TYPE_INTPTR: // return types[TYPE_SYSTEM_INTPTR]; case ELEMENT_TYPE_UINTPTR: return types[TYPE_SYSTEM_UINTPTR]; case ELEMENT_TYPE_OBJECT: return types[TYPE_SYSTEM_OBJECT]; case ELEMENT_TYPE_SZARRAY: { tMD_TypeDef *pElementType; pElementType = Type_GetTypeFromSig(pMetaData, pSig, ppClassTypeArgs, ppMethodTypeArgs); return Type_GetArrayTypeDef(pElementType, ppClassTypeArgs, ppMethodTypeArgs); } case ELEMENT_TYPE_MVAR: entry = MetaData_DecodeSigEntry(pSig); // This is the argument number if (ppMethodTypeArgs == NULL) { // Can't do anything sensible, as we don't have any type args return NULL; } else { return ppMethodTypeArgs[entry]; } default: Crash("Type_GetTypeFromSig(): Cannot handle signature element type: 0x%02x", entry); FAKE_RETURN; } }