diff options
Diffstat (limited to 'src/vm/staticallocationhelpers.inl')
-rw-r--r-- | src/vm/staticallocationhelpers.inl | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/vm/staticallocationhelpers.inl b/src/vm/staticallocationhelpers.inl new file mode 100644 index 0000000000..26c2573762 --- /dev/null +++ b/src/vm/staticallocationhelpers.inl @@ -0,0 +1,160 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// StaticAllocationHelpers.inl - +// + +// +// Helpers used to determine static offset allocation. +// +// +#ifndef StaticAllocationHelpers_INL +#define StaticAllocationHelpers_INL + +// Will return underlying type if it's an enum +// ELEMENT_TYPE_VALUETYPE if it is a non enum +// ELEMENT_TYPE_END if it doesn't know (we may not want to load other assemblies) +static CorElementType ParseMetadataForStaticsIsValueTypeEnum(Module * pModule, IMDInternalImport *pImport, mdToken tk) +{ + STANDARD_VM_CONTRACT; + + if (TypeFromToken(tk) != mdtTypeDef) + { + // At this point, we would have to load other assemblies. The only one we have guaranteed + // to be there is mscorlib. + return ELEMENT_TYPE_END; + } + + // The only condition we will be checking is that the parent of the type is System.Enum + // Rest of the checks will be handed by class loader, which will fail to load if it's malformed + // hence, no need to do all the checks here. + mdToken tkParent = 0; + DWORD dwParentAttr = 0; + + if (FAILED(pImport->GetTypeDefProps(tk, &dwParentAttr, &tkParent))) + { + return ELEMENT_TYPE_END; + } + + if (RidFromToken(tkParent) == 0) + { + return ELEMENT_TYPE_END; + } + + LPCSTR szName = NULL; + LPCSTR szNamespace = NULL; + + switch (TypeFromToken(tkParent)) + { + case mdtTypeDef: + if (FAILED(pImport->GetNameOfTypeDef(tkParent, &szName, &szNamespace))) + { + return ELEMENT_TYPE_END; + } + break; + case mdtTypeRef: + if (FAILED(pImport->GetNameOfTypeRef(tkParent, &szNamespace, &szName))) + { + return ELEMENT_TYPE_END; + } + break; + default: + return ELEMENT_TYPE_END; + } + + if (szName == NULL || szNamespace == NULL) + { + return ELEMENT_TYPE_END; + } + + // If it doesn't inherit from System.Enum, then it must be a value type + // Note that loader will not load malformed types so this check is enough + if (strcmp(szName,"Enum") != 0 || strcmp(szNamespace,"System") != 0) + { + return ELEMENT_TYPE_VALUETYPE; + } + + // OK, it's an enum; find its instance field and get its type + HENUMInternalHolder hEnum(pImport); + mdToken tkField; + hEnum.EnumInit(mdtFieldDef,tk); + while (pImport->EnumNext(&hEnum,&tkField)) + { + PCCOR_SIGNATURE pMemberSignature; + DWORD cMemberSignature; + + // Get the type of the static field. + DWORD dwMemberAttribs; + + IfFailThrow(pImport->GetFieldDefProps(tkField, &dwMemberAttribs)); + + if (!IsFdStatic(dwMemberAttribs)) + { + IfFailThrow(pImport->GetSigOfFieldDef(tkField, &cMemberSignature, &pMemberSignature)); + + IfFailThrow(validateTokenSig(tkField,pMemberSignature,cMemberSignature,dwMemberAttribs,pImport)); + + SigTypeContext typeContext; + MetaSig fsig(pMemberSignature, cMemberSignature, pModule, &typeContext, MetaSig::sigField); + CorElementType ElementType = fsig.NextArg(); + return ElementType; + } + } + + // no instance field found -- error! + return ELEMENT_TYPE_END; +} + +static BOOL GetStaticFieldElementTypeForFieldDef(Module * pModule, IMDInternalImport *pImport, mdToken field, CorElementType *pElementType, mdToken *ptkValueTypeToken, int *pkk) +{ + STANDARD_VM_CONTRACT; + + PCCOR_SIGNATURE pMemberSignature; + DWORD cMemberSignature; + DWORD dwMemberAttribs; + IfFailThrow(pImport->GetFieldDefProps(field, &dwMemberAttribs)); + + // Skip non-static and literal fields + if (!IsFdStatic(dwMemberAttribs) || IsFdLiteral(dwMemberAttribs)) + return TRUE; + + // We need to do an extra check to see if this field is ThreadStatic + HRESULT hr = pImport->GetCustomAttributeByName((mdToken)field, + g_ThreadStaticAttributeClassName, + NULL, NULL); + IfFailThrow(hr); + + // Use one set of variables for regular statics, and the other set for thread statics + *pkk = (hr == S_OK) ? 1 : 0; + + + // Get the type of the static field. + IfFailThrow(pImport->GetSigOfFieldDef(field, &cMemberSignature, &pMemberSignature)); + IfFailThrow(validateTokenSig(field,pMemberSignature,cMemberSignature,dwMemberAttribs,pImport)); + + SigTypeContext typeContext; // <TODO> this is an empty type context: is this right? Should we be explicitly excluding all generic types from this iteration? </TODO> + MetaSig fsig(pMemberSignature, cMemberSignature, pModule, &typeContext, MetaSig::sigField); + CorElementType ElementType = fsig.NextArg(); + + if (ElementType == ELEMENT_TYPE_VALUETYPE) + { + // See if we can figure out what the value type is + Module *pTokenModule; + mdToken tk = fsig.GetArgProps().PeekValueTypeTokenClosed(pModule, &typeContext, &pTokenModule); + + *ptkValueTypeToken = tk; + + // As the current class is not generic, this should never happen, but if it did happen, we + // would have a problem. + if (pTokenModule != pModule) + { + ThrowHR(COR_E_BADIMAGEFORMAT, BFA_METADATA_CORRUPT); + } + + ElementType = ParseMetadataForStaticsIsValueTypeEnum(pModule, pImport, tk); + } + + *pElementType = ElementType; + return FALSE; +} +#endif // StaticAllocationHelpers_INL |