diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs index 1b3032a24607c..dd0b5cf897f4d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs @@ -472,6 +472,7 @@ public override IList NamedArguments if (p.EncodedArgument is not null && p.EncodedArgument.CustomAttributeType.EncodedType != CustomAttributeEncoding.Undefined) { + Debug.Assert(p.MemberInfo is not null); namedArgs[j++] = new CustomAttributeNamedArgument( p.MemberInfo, new CustomAttributeTypedArgument(m_scope, p.EncodedArgument)); @@ -1114,7 +1115,7 @@ public CustomAttributeType(RuntimeType parameterType) public Type? EnumType { get; } } - internal static unsafe class CustomAttribute + internal static unsafe partial class CustomAttribute { #region Internal Static Members internal static bool IsDefined(RuntimeType type, RuntimeType? caType, bool inherit) @@ -1526,7 +1527,7 @@ private static void AddCustomAttributes( object attribute; if (ctorWithParameters is not null) { - attribute = CreateCaObject(decoratedModule, attributeType, ctorWithParameters, ref blobStart, blobEnd, out cNamedArgs); + attribute = CreateCustomAttributeInstance(decoratedModule, attributeType, ctorWithParameters, ref blobStart, blobEnd, out cNamedArgs); } else { @@ -1794,8 +1795,16 @@ internal static AttributeUsageAttribute GetAttributeUsage(RuntimeType decoratedA if (attributeUsageAttribute is not null) throw new FormatException(SR.Format(SR.Format_AttributeUsage, attributeType)); - ParseAttributeUsageAttribute(caRecord.blob, out AttributeTargets targets, out bool inherited, out bool allowMultiple); - attributeUsageAttribute = new AttributeUsageAttribute(targets, allowMultiple, inherited); + if (!ParseAttributeUsageAttribute( + caRecord.blob, + out AttributeTargets attrTargets, + out bool allowMultiple, + out bool inherited)) + { + throw new CustomAttributeFormatException(); + } + + attributeUsageAttribute = new AttributeUsageAttribute(attrTargets, allowMultiple: allowMultiple, inherited: inherited); } return attributeUsageAttribute ?? AttributeUsageAttribute.Default; @@ -1838,42 +1847,93 @@ internal static object[] CreateAttributeArrayHelper(RuntimeType caType, int elem } #endregion - #region Private Static FCalls - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _ParseAttributeUsageAttribute( - IntPtr pCa, int cCa, out int targets, out bool inherited, out bool allowMultiple); - private static void ParseAttributeUsageAttribute( - ConstArray ca, out AttributeTargets targets, out bool inherited, out bool allowMultiple) - { - _ParseAttributeUsageAttribute(ca.Signature, ca.Length, out int _targets, out inherited, out allowMultiple); - targets = (AttributeTargets)_targets; - } - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern object _CreateCaObject(RuntimeModule pModule, RuntimeType type, IRuntimeMethodInfo pCtor, byte** ppBlob, byte* pEndBlob, int* pcNamedArgs); - private static object CreateCaObject(RuntimeModule module, RuntimeType type, IRuntimeMethodInfo ctor, ref IntPtr blob, IntPtr blobEnd, out int namedArgs) - { - byte* pBlob = (byte*)blob; - byte* pBlobEnd = (byte*)blobEnd; - int cNamedArgs; - object ca = _CreateCaObject(module, type, ctor, &pBlob, pBlobEnd, &cNamedArgs); - blob = (IntPtr)pBlob; - namedArgs = cNamedArgs; - return ca; - } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "CustomAttribute_ParseAttributeUsageAttribute")] + [SuppressGCTransition] + private static partial int ParseAttributeUsageAttribute( + IntPtr pData, + int cData, + int* pTargets, + int* pAllowMultiple, + int* pInherited); + + private static bool ParseAttributeUsageAttribute( + ConstArray blob, + out AttributeTargets attrTargets, + out bool allowMultiple, + out bool inherited) + { + int attrTargetsLocal = 0; + int allowMultipleLocal = 0; + int inheritedLocal = 0; + int result = ParseAttributeUsageAttribute(blob.Signature, blob.Length, &attrTargetsLocal, &allowMultipleLocal, &inheritedLocal); + attrTargets = (AttributeTargets)attrTargetsLocal; + allowMultiple = allowMultipleLocal != 0; + inherited = inheritedLocal != 0; + return result != 0; + } + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "CustomAttribute_CreateCustomAttributeInstance")] + private static partial void CreateCustomAttributeInstance( + QCallModule pModule, + ObjectHandleOnStack type, + ObjectHandleOnStack pCtor, + ref IntPtr ppBlob, + IntPtr pEndBlob, + out int pcNamedArgs, + ObjectHandleOnStack instance); + + private static object CreateCustomAttributeInstance(RuntimeModule module, RuntimeType type, IRuntimeMethodInfo ctor, ref IntPtr blob, IntPtr blobEnd, out int namedArgs) + { + if (module is null) + { + throw new ArgumentNullException(SR.Arg_InvalidHandle); + } + + object? result = null; + CreateCustomAttributeInstance( + new QCallModule(ref module), + ObjectHandleOnStack.Create(ref type), + ObjectHandleOnStack.Create(ref ctor), + ref blob, + blobEnd, + out namedArgs, + ObjectHandleOnStack.Create(ref result)); + return result!; + } + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "CustomAttribute_CreatePropertyOrFieldData", StringMarshalling = StringMarshalling.Utf16)] + private static partial void CreatePropertyOrFieldData( + QCallModule pModule, + ref IntPtr ppBlobStart, + IntPtr pBlobEnd, + StringHandleOnStack name, + [MarshalAs(UnmanagedType.Bool)] out bool bIsProperty, + ObjectHandleOnStack type, + ObjectHandleOnStack value); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetPropertyOrFieldData( - RuntimeModule pModule, byte** ppBlobStart, byte* pBlobEnd, out string name, out bool bIsProperty, out RuntimeType type, out object value); private static void GetPropertyOrFieldData( RuntimeModule module, ref IntPtr blobStart, IntPtr blobEnd, out string name, out bool isProperty, out RuntimeType? type, out object? value) { - byte* pBlobStart = (byte*)blobStart; - _GetPropertyOrFieldData( - module, &pBlobStart, (byte*)blobEnd, out name, out isProperty, out type, out value); - blobStart = (IntPtr)pBlobStart; + if (module is null) + { + throw new ArgumentNullException(SR.Arg_InvalidHandle); + } + + string? nameLocal = null; + RuntimeType? typeLocal = null; + object? valueLocal = null; + CreatePropertyOrFieldData( + new QCallModule(ref module), + ref blobStart, + blobEnd, + new StringHandleOnStack(ref nameLocal), + out isProperty, + ObjectHandleOnStack.Create(ref typeLocal), + ObjectHandleOnStack.Create(ref valueLocal)); + name = nameLocal!; + type = typeLocal; + value = valueLocal; } - #endregion } internal static class PseudoCustomAttribute @@ -1918,12 +1978,18 @@ private static HashSet CreatePseudoCustomAttributeHashSet() private static void VerifyPseudoCustomAttribute(RuntimeType pca) { // If any of these are invariants are no longer true will have to - // re-architect the PCA product logic and test cases -- you've been warned! - Debug.Assert(pca.BaseType == typeof(Attribute), "Pseudo CA Error"); + // re-architect the PCA product logic and test cases. + Debug.Assert(pca.BaseType == typeof(Attribute), "Pseudo CA Error - Incorrect base type"); AttributeUsageAttribute usage = CustomAttribute.GetAttributeUsage(pca); - Debug.Assert(!usage.Inherited, "Pseudo CA Error"); - // AllowMultiple is true for TypeForwardedToAttribute - // Debug.Assert(usage.AllowMultiple == false, "Pseudo CA Error"); + Debug.Assert(!usage.Inherited, "Pseudo CA Error - Unexpected Inherited value"); + if (pca == typeof(TypeForwardedToAttribute)) + { + Debug.Assert(usage.AllowMultiple, "Pseudo CA Error - Unexpected AllowMultiple value"); + } + else + { + Debug.Assert(!usage.AllowMultiple, "Pseudo CA Error - Unexpected AllowMultiple value"); + } } #endregion diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index 00a8d78685d4d..6a1fae9e05c70 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -2373,7 +2373,9 @@ private static bool FilterApplyMethodBase( #region Private Data Members #pragma warning disable CA1823 +#pragma warning disable CS0169 private readonly object m_keepalive; // This will be filled with a LoaderAllocator reference when this RuntimeType represents a collectible type +#pragma warning restore CS0169 #pragma warning restore CA1823 private IntPtr m_cache; internal IntPtr m_handle; diff --git a/src/coreclr/vm/callconvbuilder.cpp b/src/coreclr/vm/callconvbuilder.cpp index 3075087ee7b83..7303cd960fa10 100644 --- a/src/coreclr/vm/callconvbuilder.cpp +++ b/src/coreclr/vm/callconvbuilder.cpp @@ -453,7 +453,7 @@ HRESULT CallConv::TryGetCallingConventionFromUnmanagedCallConv( InlineFactory, 4> caValueArrayFactory; DomainAssembly* domainAssembly = pMD->GetLoaderModule()->GetDomainAssembly(); - IfFailThrow(Attribute::ParseAttributeArgumentValues( + IfFailThrow(Attribute::ParseArgumentValues( pData, cData, &caValueArrayFactory, @@ -528,7 +528,7 @@ bool CallConv::TryGetCallingConventionFromUnmanagedCallersOnly(_In_ MethodDesc* InlineFactory, 4> caValueArrayFactory; DomainAssembly* domainAssembly = pMD->GetLoaderModule()->GetDomainAssembly(); - IfFailThrow(Attribute::ParseAttributeArgumentValues( + IfFailThrow(Attribute::ParseArgumentValues( pData, cData, &caValueArrayFactory, diff --git a/src/coreclr/vm/customattribute.cpp b/src/coreclr/vm/customattribute.cpp index b86ca79db9281..efa355602c90b 100644 --- a/src/coreclr/vm/customattribute.cpp +++ b/src/coreclr/vm/customattribute.cpp @@ -326,8 +326,7 @@ static HRESULT ParseCaNamedArgs( return hr; } -/*static*/ -HRESULT Attribute::ParseAttributeArgumentValues( +HRESULT Attribute::ParseArgumentValues( void* pCa, INT32 cCa, CaValueArrayFactory* pCaValueArrayFactory, @@ -349,340 +348,47 @@ HRESULT Attribute::ParseAttributeArgumentValues( return hr; } -FCIMPL6(LPVOID, COMCustomAttribute::CreateCaObject, ReflectModuleBaseObject* pAttributedModuleUNSAFE, ReflectClassBaseObject* pCaTypeUNSAFE, ReflectMethodObject *pMethodUNSAFE, BYTE** ppBlob, BYTE* pEndBlob, INT32* pcNamedArgs) +// retrieve the string size in a CA blob. Advance the blob pointer to point to +// the beginning of the string immediately following the size +static int GetStringSize(BYTE **pBlob, const BYTE *endBlob) { - FCALL_CONTRACT; - - struct - { - REFLECTCLASSBASEREF refCaType; - OBJECTREF ca; - REFLECTMETHODREF refCtor; - REFLECTMODULEBASEREF refAttributedModule; - } gc; - gc.refCaType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pCaTypeUNSAFE); - TypeHandle th = gc.refCaType->GetType(); - - gc.ca = NULL; - gc.refCtor = (REFLECTMETHODREF)ObjectToOBJECTREF(pMethodUNSAFE); - gc.refAttributedModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pAttributedModuleUNSAFE); - - if(gc.refAttributedModule == NULL) - FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); - - MethodDesc* pCtorMD = gc.refCtor->GetMethod(); - - HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); + CONTRACTL { - MethodDescCallSite ctorCallSite(pCtorMD, th); - MetaSig* pSig = ctorCallSite.GetMetaSig(); - BYTE* pBlob = *ppBlob; - - // get the number of arguments and allocate an array for the args - ARG_SLOT *args = NULL; - UINT cArgs = pSig->NumFixedArgs() + 1; // make room for the this pointer - UINT i = 1; // used to flag that we actually get the right number of arg from the blob - - args = (ARG_SLOT*)_alloca(cArgs * sizeof(ARG_SLOT)); - memset((void*)args, 0, cArgs * sizeof(ARG_SLOT)); - - OBJECTREF *argToProtect = (OBJECTREF*)_alloca(cArgs * sizeof(OBJECTREF)); - memset((void*)argToProtect, 0, cArgs * sizeof(OBJECTREF)); - - // load the this pointer - argToProtect[0] = gc.refCaType->GetType().GetMethodTable()->Allocate(); // this is the value to return after the ctor invocation - - if (pBlob) - { - if (pBlob < pEndBlob) - { - if (pBlob + 2 > pEndBlob) - { - COMPlusThrow(kCustomAttributeFormatException); - } - INT16 prolog = GET_UNALIGNED_VAL16(pBlob); - if (prolog != 1) - COMPlusThrow(kCustomAttributeFormatException); - pBlob += 2; - } - - if (cArgs > 1) - { - GCPROTECT_ARRAY_BEGIN(*argToProtect, cArgs); - { - // loop through the args - for (i = 1; i < cArgs; i++) { - CorElementType type = pSig->NextArg(); - if (type == ELEMENT_TYPE_END) - break; - BOOL bObjectCreated = FALSE; - TypeHandle th = pSig->GetLastTypeHandleThrowing(); - if (th.IsArray()) - // get the array element - th = th.GetArrayElementTypeHandle(); - ARG_SLOT data = GetDataFromBlob(pCtorMD->GetAssembly(), (CorSerializationType)type, th, &pBlob, pEndBlob, gc.refAttributedModule->GetModule(), &bObjectCreated); - if (bObjectCreated) - argToProtect[i] = ArgSlotToObj(data); - else - args[i] = data; - } - } - GCPROTECT_END(); - - // We have borrowed the signature from MethodDescCallSite. We have to put it back into the initial position - // because of that's where MethodDescCallSite expects to find it below. - pSig->Reset(); - - for (i = 1; i < cArgs; i++) - { - if (argToProtect[i] != NULL) - { - _ASSERTE(args[i] == NULL); - args[i] = ObjToArgSlot(argToProtect[i]); - } - } - } - } - args[0] = ObjToArgSlot(argToProtect[0]); - - if (i != cArgs) - COMPlusThrow(kCustomAttributeFormatException); - - // check if there are any named properties to invoke, - // if so set the by ref int passed in to point - // to the blob position where name properties start - *pcNamedArgs = 0; - - if (pBlob && pBlob != pEndBlob) - { - if (pBlob + 2 > pEndBlob) - COMPlusThrow(kCustomAttributeFormatException); - - *pcNamedArgs = GET_UNALIGNED_VAL16(pBlob); - - pBlob += 2; - } - - *ppBlob = pBlob; - - if (*pcNamedArgs == 0 && pBlob != pEndBlob) - COMPlusThrow(kCustomAttributeFormatException); - - // make the invocation to the ctor - gc.ca = ArgSlotToObj(args[0]); - if (pCtorMD->GetMethodTable()->IsValueType()) - args[0] = PtrToArgSlot(OBJECTREFToObject(gc.ca)->UnBox()); - - ctorCallSite.CallWithValueTypes(args); + MODE_COOPERATIVE; + THROWS; } - HELPER_METHOD_FRAME_END(); - - return OBJECTREFToObject(gc.ca); -} -FCIMPLEND - -FCIMPL5(VOID, COMCustomAttribute::ParseAttributeUsageAttribute, PVOID pData, ULONG cData, ULONG* pTargets, CLR_BOOL* pInherited, CLR_BOOL* pAllowMultiple) -{ - FCALL_CONTRACT; - - int inherited = 0; - int allowMultiple = 1; - - { - CustomAttributeParser ca(pData, cData); - - CaArg args[1]; - args[0].InitEnum(SERIALIZATION_TYPE_I4, 0); - if (FAILED(::ParseKnownCaArgs(ca, args, ARRAY_SIZE(args)))) - { - HELPER_METHOD_FRAME_BEGIN_0(); - COMPlusThrow(kCustomAttributeFormatException); - HELPER_METHOD_FRAME_END(); - } - - *pTargets = args[0].val.u4; - - CaNamedArg namedArgs[2]; - CaType namedArgTypes[2]; - namedArgTypes[inherited].Init(SERIALIZATION_TYPE_BOOLEAN); - namedArgTypes[allowMultiple].Init(SERIALIZATION_TYPE_BOOLEAN); - namedArgs[inherited].Init("Inherited", SERIALIZATION_TYPE_PROPERTY, namedArgTypes[inherited], TRUE); - namedArgs[allowMultiple].Init("AllowMultiple", SERIALIZATION_TYPE_PROPERTY, namedArgTypes[allowMultiple], FALSE); - if (FAILED(::ParseKnownCaNamedArgs(ca, namedArgs, ARRAY_SIZE(namedArgs)))) - { - HELPER_METHOD_FRAME_BEGIN_0(); - COMPlusThrow(kCustomAttributeFormatException); - HELPER_METHOD_FRAME_END(); - } + CONTRACTL_END; - *pInherited = namedArgs[inherited].val.boolean == TRUE; - *pAllowMultiple = namedArgs[allowMultiple].val.boolean == TRUE; + if (*pBlob >= endBlob ) + { // No buffer at all, or buffer overrun + COMPlusThrow(kCustomAttributeFormatException); } -} -FCIMPLEND - - -FCIMPL7(void, COMCustomAttribute::GetPropertyOrFieldData, ReflectModuleBaseObject *pModuleUNSAFE, BYTE** ppBlobStart, BYTE* pBlobEnd, STRINGREF* pName, CLR_BOOL* pbIsProperty, OBJECTREF* pType, OBJECTREF* value) -{ - FCALL_CONTRACT; - - BYTE* pBlob = *ppBlobStart; - *pType = NULL; - REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE); - - if(refModule == NULL) - FCThrowResVoid(kArgumentNullException, W("Arg_InvalidHandle")); - - Module *pModule = refModule->GetModule(); + if (**pBlob == 0xFF) + { // Special case null string. + ++(*pBlob); + return -1; + } - HELPER_METHOD_FRAME_BEGIN_1(refModule); + ULONG ulSize; + if (FAILED(CPackedLen::SafeGetData((BYTE const *)*pBlob, (BYTE const *)endBlob, (ULONG *)&ulSize, (BYTE const **)pBlob))) { - Assembly *pCtorAssembly = NULL; - - MethodTable *pMTValue = NULL; - CorSerializationType arrayType = SERIALIZATION_TYPE_BOOLEAN; - BOOL bObjectCreated = FALSE; - TypeHandle nullTH; - - if (pBlob + 2 > pBlobEnd) - COMPlusThrow(kCustomAttributeFormatException); - - // get whether it is a field or a property - CorSerializationType propOrField = (CorSerializationType)*pBlob; - pBlob++; - if (propOrField == SERIALIZATION_TYPE_FIELD) - *pbIsProperty = FALSE; - else if (propOrField == SERIALIZATION_TYPE_PROPERTY) - *pbIsProperty = TRUE; - else - COMPlusThrow(kCustomAttributeFormatException); - - // get the type of the field - CorSerializationType fieldType = (CorSerializationType)*pBlob; - pBlob++; - if (fieldType == SERIALIZATION_TYPE_SZARRAY) - { - arrayType = (CorSerializationType)*pBlob; - - if (pBlob + 1 > pBlobEnd) - COMPlusThrow(kCustomAttributeFormatException); - - pBlob++; - } - if (fieldType == SERIALIZATION_TYPE_ENUM || arrayType == SERIALIZATION_TYPE_ENUM) - { - // get the enum type - ReflectClassBaseObject *pEnum = - (ReflectClassBaseObject*)OBJECTREFToObject(ArgSlotToObj(GetDataFromBlob( - pCtorAssembly, SERIALIZATION_TYPE_TYPE, nullTH, &pBlob, pBlobEnd, pModule, &bObjectCreated))); - - if (pEnum == NULL) - COMPlusThrow(kCustomAttributeFormatException); - - _ASSERTE(bObjectCreated); - - TypeHandle th = pEnum->GetType(); - _ASSERTE(th.IsEnum()); - - pMTValue = th.AsMethodTable(); - if (fieldType == SERIALIZATION_TYPE_ENUM) - // load the enum type to pass it back - *pType = th.GetManagedClassObject(); - else - nullTH = th; - } - - // get the string representing the field/property name - *pName = ArgSlotToString(GetDataFromBlob( - pCtorAssembly, SERIALIZATION_TYPE_STRING, nullTH, &pBlob, pBlobEnd, pModule, &bObjectCreated)); - _ASSERTE(bObjectCreated || *pName == NULL); - - // create the object and return it - switch (fieldType) - { - case SERIALIZATION_TYPE_TAGGED_OBJECT: - *pType = g_pObjectClass->GetManagedClassObject(); - FALLTHROUGH; - case SERIALIZATION_TYPE_TYPE: - case SERIALIZATION_TYPE_STRING: - *value = ArgSlotToObj(GetDataFromBlob( - pCtorAssembly, fieldType, nullTH, &pBlob, pBlobEnd, pModule, &bObjectCreated)); - _ASSERTE(bObjectCreated || *value == NULL); - - if (*value == NULL) - { - // load the proper type so that code in managed knows which property to load - if (fieldType == SERIALIZATION_TYPE_STRING) - *pType = CoreLibBinder::GetElementType(ELEMENT_TYPE_STRING)->GetManagedClassObject(); - else if (fieldType == SERIALIZATION_TYPE_TYPE) - *pType = CoreLibBinder::GetClass(CLASS__TYPE)->GetManagedClassObject(); - } - break; - case SERIALIZATION_TYPE_SZARRAY: - { - *value = NULL; - int arraySize = (int)GetDataFromBlob(pCtorAssembly, SERIALIZATION_TYPE_I4, nullTH, &pBlob, pBlobEnd, pModule, &bObjectCreated); - - if (arraySize != -1) - { - _ASSERTE(!bObjectCreated); - if (arrayType == SERIALIZATION_TYPE_STRING) - nullTH = TypeHandle(CoreLibBinder::GetElementType(ELEMENT_TYPE_STRING)); - else if (arrayType == SERIALIZATION_TYPE_TYPE) - nullTH = TypeHandle(CoreLibBinder::GetClass(CLASS__TYPE)); - else if (arrayType == SERIALIZATION_TYPE_TAGGED_OBJECT) - nullTH = TypeHandle(g_pObjectClass); - ReadArray(pCtorAssembly, arrayType, arraySize, nullTH, &pBlob, pBlobEnd, pModule, (BASEARRAYREF*)value); - } - if (*value == NULL) - { - TypeHandle arrayTH; - switch (arrayType) - { - case SERIALIZATION_TYPE_STRING: - arrayTH = TypeHandle(CoreLibBinder::GetElementType(ELEMENT_TYPE_STRING)); - break; - case SERIALIZATION_TYPE_TYPE: - arrayTH = TypeHandle(CoreLibBinder::GetClass(CLASS__TYPE)); - break; - case SERIALIZATION_TYPE_TAGGED_OBJECT: - arrayTH = TypeHandle(g_pObjectClass); - break; - default: - if (SERIALIZATION_TYPE_BOOLEAN <= arrayType && arrayType <= SERIALIZATION_TYPE_R8) - arrayTH = TypeHandle(CoreLibBinder::GetElementType((CorElementType)arrayType)); - } - if (!arrayTH.IsNull()) - { - arrayTH = ClassLoader::LoadArrayTypeThrowing(arrayTH); - *pType = arrayTH.GetManagedClassObject(); - } - } - break; - } - default: - if (SERIALIZATION_TYPE_BOOLEAN <= fieldType && fieldType <= SERIALIZATION_TYPE_R8) - pMTValue = CoreLibBinder::GetElementType((CorElementType)fieldType); - else if(fieldType == SERIALIZATION_TYPE_ENUM) - fieldType = (CorSerializationType)pMTValue->GetInternalCorElementType(); - else - COMPlusThrow(kCustomAttributeFormatException); - - ARG_SLOT val = GetDataFromBlob(pCtorAssembly, fieldType, nullTH, &pBlob, pBlobEnd, pModule, &bObjectCreated); - _ASSERTE(!bObjectCreated); - - *value = pMTValue->Box((void*)ArgSlotEndiannessFixup(&val, pMTValue->GetNumInstanceFieldBytes())); - } - - *ppBlobStart = pBlob; + COMPlusThrow(kCustomAttributeFormatException); } - HELPER_METHOD_FRAME_END(); + + return (int)ulSize; } -FCIMPLEND -/*static*/ -TypeHandle COMCustomAttribute::GetTypeHandleFromBlob(Assembly *pCtorAssembly, +// Forward declaration +static ARG_SLOT GetDataFromBlob(Assembly *pCtorAssembly, + CorSerializationType type, + TypeHandle th, + BYTE **pBlob, + const BYTE *endBlob, + Module *pModule, + BOOL *bObjectCreated); + +static TypeHandle GetTypeHandleFromBlob(Assembly *pCtorAssembly, CorSerializationType objType, BYTE **pBlob, const BYTE *endBlob, @@ -690,6 +396,7 @@ TypeHandle COMCustomAttribute::GetTypeHandleFromBlob(Assembly *pCtorAssembly, { CONTRACTL { + MODE_COOPERATIVE; THROWS; } CONTRACTL_END; @@ -776,50 +483,25 @@ TypeHandle COMCustomAttribute::GetTypeHandleFromBlob(Assembly *pCtorAssembly, return RtnTypeHnd; } -// retrieve the string size in a CA blob. Advance the blob pointer to point to -// the beginning of the string immediately following the size -/*static*/ -int COMCustomAttribute::GetStringSize(BYTE **pBlob, const BYTE *endBlob) +// copy the values of an array of integers from a CA blob +// (i.e., always stored in little-endian, and needs not be aligned). +// Returns TRUE on success, FALSE if the blob was not big enough. +// Advances *pBlob by the amount copied. +template +static bool CopyArrayVAL(BASEARRAYREF pArray, int nElements, BYTE **pBlob, const BYTE *endBlob) { CONTRACTL { - THROWS; + MODE_COOPERATIVE; + NOTHROW; } CONTRACTL_END; - if (*pBlob >= endBlob ) - { // No buffer at all, or buffer overrun - COMPlusThrow(kCustomAttributeFormatException); - } - - if (**pBlob == 0xFF) - { // Special case null string. - ++(*pBlob); - return -1; - } - - ULONG ulSize; - if (FAILED(CPackedLen::SafeGetData((BYTE const *)*pBlob, (BYTE const *)endBlob, (ULONG *)&ulSize, (BYTE const **)pBlob))) - { - COMPlusThrow(kCustomAttributeFormatException); - } - - return (int)ulSize; -} - -// copy the values of an array of integers from a CA blob -// (i.e., always stored in little-endian, and needs not be aligned). -// Returns TRUE on success, FALSE if the blob was not big enough. -// Advances *pBlob by the amount copied. -/*static*/ -template < typename T > -BOOL COMCustomAttribute::CopyArrayVAL(BASEARRAYREF pArray, int nElements, BYTE **pBlob, const BYTE *endBlob) -{ int sizeData; // = size * 2; with integer overflow check if (!ClrSafeInt::multiply(nElements, sizeof(T), sizeData)) - return FALSE; + return false; if (sizeData > endBlob - *pBlob) // integer overflow check - return FALSE; + return false; #if BIGENDIAN T *ptDest = reinterpret_cast(pArray->GetDataPtr()); for (int iElement = 0; iElement < nElements; iElement++) @@ -837,34 +519,36 @@ BOOL COMCustomAttribute::CopyArrayVAL(BASEARRAYREF pArray, int nElements, BYTE * memcpyNoGCRefs(pArray->GetDataPtr(), *pBlob, sizeData); #endif // BIGENDIAN *pBlob += sizeData; - return TRUE; + return true; } // read the whole array as a chunk -/*static*/ -void COMCustomAttribute::ReadArray(Assembly *pCtorAssembly, +static BASEARRAYREF ReadArray(Assembly *pCtorAssembly, CorSerializationType arrayType, int size, TypeHandle th, BYTE **pBlob, const BYTE *endBlob, - Module *pModule, - BASEARRAYREF *pArray) + Module *pModule) { CONTRACTL { + MODE_COOPERATIVE; THROWS; } CONTRACTL_END; ARG_SLOT element = 0; + BASEARRAYREF array = NULL; + GCPROTECT_BEGIN(array); + switch ((DWORD)arrayType) { case SERIALIZATION_TYPE_BOOLEAN: case SERIALIZATION_TYPE_I1: case SERIALIZATION_TYPE_U1: - *pArray = (BASEARRAYREF)AllocatePrimitiveArray((CorElementType)arrayType, size); - if (!CopyArrayVAL(*pArray, size, pBlob, endBlob)) + array = (BASEARRAYREF)AllocatePrimitiveArray((CorElementType)arrayType, size); + if (!CopyArrayVAL(array, size, pBlob, endBlob)) goto badBlob; break; @@ -872,8 +556,8 @@ void COMCustomAttribute::ReadArray(Assembly *pCtorAssembly, case SERIALIZATION_TYPE_I2: case SERIALIZATION_TYPE_U2: { - *pArray = (BASEARRAYREF)AllocatePrimitiveArray((CorElementType)arrayType, size); - if (!CopyArrayVAL(*pArray, size, pBlob, endBlob)) + array = (BASEARRAYREF)AllocatePrimitiveArray((CorElementType)arrayType, size); + if (!CopyArrayVAL(array, size, pBlob, endBlob)) goto badBlob; break; } @@ -881,8 +565,8 @@ void COMCustomAttribute::ReadArray(Assembly *pCtorAssembly, case SERIALIZATION_TYPE_U4: case SERIALIZATION_TYPE_R4: { - *pArray = (BASEARRAYREF)AllocatePrimitiveArray((CorElementType)arrayType, size); - if (!CopyArrayVAL(*pArray, size, pBlob, endBlob)) + array = (BASEARRAYREF)AllocatePrimitiveArray((CorElementType)arrayType, size); + if (!CopyArrayVAL(array, size, pBlob, endBlob)) goto badBlob; break; } @@ -890,8 +574,8 @@ void COMCustomAttribute::ReadArray(Assembly *pCtorAssembly, case SERIALIZATION_TYPE_U8: case SERIALIZATION_TYPE_R8: { - *pArray = (BASEARRAYREF)AllocatePrimitiveArray((CorElementType)arrayType, size); - if (!CopyArrayVAL(*pArray, size, pBlob, endBlob)) + array = (BASEARRAYREF)AllocatePrimitiveArray((CorElementType)arrayType, size); + if (!CopyArrayVAL(array, size, pBlob, endBlob)) goto badBlob; break; } @@ -907,14 +591,14 @@ void COMCustomAttribute::ReadArray(Assembly *pCtorAssembly, if (th.IsNull()) goto badBlob; - *pArray = (BASEARRAYREF)AllocateObjectArray(size, th); + array = (BASEARRAYREF)AllocateObjectArray(size, th); if (arrayType == SERIALIZATION_TYPE_SZARRAY) // switch the th to be the proper one th = th.GetArrayElementTypeHandle(); for (int i = 0; i < size; i++) { element = GetDataFromBlob(pCtorAssembly, arrayType, th, pBlob, endBlob, pModule, &isObject); _ASSERTE(isObject || element == NULL); - ((PTRARRAYREF)(*pArray))->SetAt(i, ArgSlotToObj(element)); + ((PTRARRAYREF)(array))->SetAt(i, ArgSlotToObj(element)); } break; } @@ -931,21 +615,21 @@ void COMCustomAttribute::ReadArray(Assembly *pCtorAssembly, TypeHandle arrayHandle = ClassLoader::LoadArrayTypeThrowing(th); if (arrayHandle.IsNull()) goto badBlob; - *pArray = (BASEARRAYREF)AllocateSzArray(arrayHandle, bounds); + array = (BASEARRAYREF)AllocateSzArray(arrayHandle, bounds); BOOL fSuccess; switch (elementSize) { case 1: - fSuccess = CopyArrayVAL(*pArray, size, pBlob, endBlob); + fSuccess = CopyArrayVAL(array, size, pBlob, endBlob); break; case 2: - fSuccess = CopyArrayVAL(*pArray, size, pBlob, endBlob); + fSuccess = CopyArrayVAL(array, size, pBlob, endBlob); break; case 4: - fSuccess = CopyArrayVAL(*pArray, size, pBlob, endBlob); + fSuccess = CopyArrayVAL(array, size, pBlob, endBlob); break; case 8: - fSuccess = CopyArrayVAL(*pArray, size, pBlob, endBlob); + fSuccess = CopyArrayVAL(array, size, pBlob, endBlob); break; default: fSuccess = FALSE; @@ -960,11 +644,12 @@ void COMCustomAttribute::ReadArray(Assembly *pCtorAssembly, COMPlusThrow(kCustomAttributeFormatException); } + GCPROTECT_END(); + return array; } // get data out of the blob according to a CorElementType -/*static*/ -ARG_SLOT COMCustomAttribute::GetDataFromBlob(Assembly *pCtorAssembly, +static ARG_SLOT GetDataFromBlob(Assembly *pCtorAssembly, CorSerializationType type, TypeHandle th, BYTE **pBlob, @@ -974,6 +659,7 @@ ARG_SLOT COMCustomAttribute::GetDataFromBlob(Assembly *pCtorAssembly, { CONTRACTL { + MODE_COOPERATIVE; THROWS; } CONTRACTL_END; @@ -1162,11 +848,7 @@ ARG_SLOT COMCustomAttribute::GetDataFromBlob(Assembly *pCtorAssembly, else arrayType = (CorSerializationType)th.GetInternalCorElementType(); - BASEARRAYREF array = NULL; - GCPROTECT_BEGIN(array); - ReadArray(pCtorAssembly, arrayType, size, th, pBlob, endBlob, pModule, &array); - retValue = ObjToArgSlot(array); - GCPROTECT_END(); + retValue = ObjToArgSlot(ReadArray(pCtorAssembly, arrayType, size, th, pBlob, endBlob, pModule)); } *bObjectCreated = TRUE; break; @@ -1180,3 +862,317 @@ ARG_SLOT COMCustomAttribute::GetDataFromBlob(Assembly *pCtorAssembly, return retValue; } + +extern "C" BOOL QCALLTYPE CustomAttribute_ParseAttributeUsageAttribute( + PVOID pData, + ULONG cData, + ULONG* pTargets, + BOOL* pAllowMultiple, + BOOL* pInherited) +{ + QCALL_CONTRACT_NO_GC_TRANSITION; + + CustomAttributeParser ca(pData, cData); + CaArg args[1]; + args[0].InitEnum(SERIALIZATION_TYPE_I4, 0); + if (FAILED(::ParseKnownCaArgs(ca, args, ARRAY_SIZE(args)))) + return FALSE; + *pTargets = args[0].val.u4; + + // Define index values. + const int allowMultiple = 0; + const int inherited = 1; + + CaNamedArg namedArgs[2]; + CaType namedArgTypes[2]; + namedArgTypes[allowMultiple].Init(SERIALIZATION_TYPE_BOOLEAN); + namedArgTypes[inherited].Init(SERIALIZATION_TYPE_BOOLEAN); + namedArgs[allowMultiple].Init("AllowMultiple", SERIALIZATION_TYPE_PROPERTY, namedArgTypes[allowMultiple], FALSE); + namedArgs[inherited].Init("Inherited", SERIALIZATION_TYPE_PROPERTY, namedArgTypes[inherited], TRUE); + if (FAILED(::ParseKnownCaNamedArgs(ca, namedArgs, ARRAY_SIZE(namedArgs)))) + return FALSE; + + *pAllowMultiple = namedArgs[allowMultiple].val.boolean ? TRUE : FALSE; + *pInherited = namedArgs[inherited].val.boolean ? TRUE : FALSE; + return TRUE; +} + +extern "C" void QCALLTYPE CustomAttribute_CreateCustomAttributeInstance( + QCall::ModuleHandle pModule, + QCall::ObjectHandleOnStack pCaType, + QCall::ObjectHandleOnStack pMethod, + BYTE** ppBlob, + BYTE* pEndBlob, + INT32* pcNamedArgs, + QCall::ObjectHandleOnStack result) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + GCX_COOP(); + + MethodDesc* pCtorMD = ((REFLECTMETHODREF)pMethod.Get())->GetMethod(); + TypeHandle th = ((REFLECTCLASSBASEREF)pCaType.Get())->GetType(); + + MethodDescCallSite ctorCallSite(pCtorMD, th); + MetaSig* pSig = ctorCallSite.GetMetaSig(); + BYTE* pBlob = *ppBlob; + + // get the number of arguments and allocate an array for the args + ARG_SLOT *args = NULL; + UINT cArgs = pSig->NumFixedArgs() + 1; // make room for the this pointer + UINT i = 1; // used to flag that we actually get the right number of arg from the blob + + args = (ARG_SLOT*)_alloca(cArgs * sizeof(ARG_SLOT)); + memset((void*)args, 0, cArgs * sizeof(ARG_SLOT)); + + OBJECTREF *argToProtect = (OBJECTREF*)_alloca(cArgs * sizeof(OBJECTREF)); + memset((void*)argToProtect, 0, cArgs * sizeof(OBJECTREF)); + + // load the this pointer + argToProtect[0] = th.GetMethodTable()->Allocate(); // this is the value to return after the ctor invocation + + if (pBlob) + { + if (pBlob < pEndBlob) + { + if (pBlob + 2 > pEndBlob) + { + COMPlusThrow(kCustomAttributeFormatException); + } + INT16 prolog = GET_UNALIGNED_VAL16(pBlob); + if (prolog != 1) + COMPlusThrow(kCustomAttributeFormatException); + pBlob += 2; + } + + if (cArgs > 1) + { + GCPROTECT_ARRAY_BEGIN(*argToProtect, cArgs); + { + // loop through the args + for (i = 1; i < cArgs; i++) { + CorElementType type = pSig->NextArg(); + if (type == ELEMENT_TYPE_END) + break; + BOOL bObjectCreated = FALSE; + TypeHandle th = pSig->GetLastTypeHandleThrowing(); + if (th.IsArray()) + // get the array element + th = th.GetArrayElementTypeHandle(); + ARG_SLOT data = GetDataFromBlob(pCtorMD->GetAssembly(), (CorSerializationType)type, th, &pBlob, pEndBlob, pModule, &bObjectCreated); + if (bObjectCreated) + argToProtect[i] = ArgSlotToObj(data); + else + args[i] = data; + } + } + GCPROTECT_END(); + + // We have borrowed the signature from MethodDescCallSite. We have to put it back into the initial position + // because of that's where MethodDescCallSite expects to find it below. + pSig->Reset(); + + for (i = 1; i < cArgs; i++) + { + if (argToProtect[i] != NULL) + { + _ASSERTE(args[i] == NULL); + args[i] = ObjToArgSlot(argToProtect[i]); + } + } + } + } + args[0] = ObjToArgSlot(argToProtect[0]); + + if (i != cArgs) + COMPlusThrow(kCustomAttributeFormatException); + + // check if there are any named properties to invoke, + // if so set the by ref int passed in to point + // to the blob position where name properties start + *pcNamedArgs = 0; + + if (pBlob && pBlob != pEndBlob) + { + if (pBlob + 2 > pEndBlob) + COMPlusThrow(kCustomAttributeFormatException); + + *pcNamedArgs = GET_UNALIGNED_VAL16(pBlob); + + pBlob += 2; + } + + *ppBlob = pBlob; + + if (*pcNamedArgs == 0 && pBlob != pEndBlob) + COMPlusThrow(kCustomAttributeFormatException); + + // make the invocation to the ctor + result.Set(ArgSlotToObj(args[0])); + if (pCtorMD->GetMethodTable()->IsValueType()) + args[0] = PtrToArgSlot(OBJECTREFToObject(result.Get())->UnBox()); + + ctorCallSite.CallWithValueTypes(args); + + END_QCALL; +} + +extern "C" void QCALLTYPE CustomAttribute_CreatePropertyOrFieldData( + QCall::ModuleHandle pModule, + BYTE** ppBlobStart, + BYTE* pBlobEnd, + QCall::StringHandleOnStack pName, + BOOL* pbIsProperty, + QCall::ObjectHandleOnStack pType, + QCall::ObjectHandleOnStack pValue) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + BYTE* pBlob = *ppBlobStart; + + GCX_COOP(); + + Assembly *pCtorAssembly = NULL; + + MethodTable *pMTValue = NULL; + CorSerializationType arrayType = SERIALIZATION_TYPE_BOOLEAN; + BOOL bObjectCreated = FALSE; + TypeHandle nullTH; + + if (pBlob + 2 > pBlobEnd) + COMPlusThrow(kCustomAttributeFormatException); + + // get whether it is a field or a property + CorSerializationType propOrField = (CorSerializationType)*pBlob; + pBlob++; + if (propOrField == SERIALIZATION_TYPE_FIELD) + *pbIsProperty = FALSE; + else if (propOrField == SERIALIZATION_TYPE_PROPERTY) + *pbIsProperty = TRUE; + else + COMPlusThrow(kCustomAttributeFormatException); + + // get the type of the field + CorSerializationType fieldType = (CorSerializationType)*pBlob; + pBlob++; + if (fieldType == SERIALIZATION_TYPE_SZARRAY) + { + arrayType = (CorSerializationType)*pBlob; + + if (pBlob + 1 > pBlobEnd) + COMPlusThrow(kCustomAttributeFormatException); + + pBlob++; + } + if (fieldType == SERIALIZATION_TYPE_ENUM || arrayType == SERIALIZATION_TYPE_ENUM) + { + // get the enum type + ReflectClassBaseObject *pEnum = + (ReflectClassBaseObject*)OBJECTREFToObject(ArgSlotToObj(GetDataFromBlob( + pCtorAssembly, SERIALIZATION_TYPE_TYPE, nullTH, &pBlob, pBlobEnd, pModule, &bObjectCreated))); + + if (pEnum == NULL) + COMPlusThrow(kCustomAttributeFormatException); + + _ASSERTE(bObjectCreated); + + TypeHandle th = pEnum->GetType(); + _ASSERTE(th.IsEnum()); + + pMTValue = th.AsMethodTable(); + if (fieldType == SERIALIZATION_TYPE_ENUM) + // load the enum type to pass it back + pType.Set(th.GetManagedClassObject()); + else + nullTH = th; + } + + // get the string representing the field/property name + pName.Set(ArgSlotToString(GetDataFromBlob( + pCtorAssembly, SERIALIZATION_TYPE_STRING, nullTH, &pBlob, pBlobEnd, pModule, &bObjectCreated))); + _ASSERTE(bObjectCreated || pName.Get() == NULL); + + // create the object and return it + switch (fieldType) + { + case SERIALIZATION_TYPE_TAGGED_OBJECT: + pType.Set(g_pObjectClass->GetManagedClassObject()); + FALLTHROUGH; + case SERIALIZATION_TYPE_TYPE: + case SERIALIZATION_TYPE_STRING: + pValue.Set(ArgSlotToObj(GetDataFromBlob( + pCtorAssembly, fieldType, nullTH, &pBlob, pBlobEnd, pModule, &bObjectCreated))); + _ASSERTE(bObjectCreated || pValue.Get() == NULL); + + if (pValue.Get() == NULL) + { + // load the proper type so that code in managed knows which property to load + if (fieldType == SERIALIZATION_TYPE_STRING) + pType.Set(CoreLibBinder::GetElementType(ELEMENT_TYPE_STRING)->GetManagedClassObject()); + else if (fieldType == SERIALIZATION_TYPE_TYPE) + pType.Set(CoreLibBinder::GetClass(CLASS__TYPE)->GetManagedClassObject()); + } + break; + case SERIALIZATION_TYPE_SZARRAY: + { + pValue.Set(NULL); + int arraySize = (int)GetDataFromBlob(pCtorAssembly, SERIALIZATION_TYPE_I4, nullTH, &pBlob, pBlobEnd, pModule, &bObjectCreated); + + if (arraySize != -1) + { + _ASSERTE(!bObjectCreated); + if (arrayType == SERIALIZATION_TYPE_STRING) + nullTH = TypeHandle(CoreLibBinder::GetElementType(ELEMENT_TYPE_STRING)); + else if (arrayType == SERIALIZATION_TYPE_TYPE) + nullTH = TypeHandle(CoreLibBinder::GetClass(CLASS__TYPE)); + else if (arrayType == SERIALIZATION_TYPE_TAGGED_OBJECT) + nullTH = TypeHandle(g_pObjectClass); + pValue.Set(ReadArray(pCtorAssembly, arrayType, arraySize, nullTH, &pBlob, pBlobEnd, pModule)); + } + if (pValue.Get() == NULL) + { + TypeHandle arrayTH; + switch (arrayType) + { + case SERIALIZATION_TYPE_STRING: + arrayTH = TypeHandle(CoreLibBinder::GetElementType(ELEMENT_TYPE_STRING)); + break; + case SERIALIZATION_TYPE_TYPE: + arrayTH = TypeHandle(CoreLibBinder::GetClass(CLASS__TYPE)); + break; + case SERIALIZATION_TYPE_TAGGED_OBJECT: + arrayTH = TypeHandle(g_pObjectClass); + break; + default: + if (SERIALIZATION_TYPE_BOOLEAN <= arrayType && arrayType <= SERIALIZATION_TYPE_R8) + arrayTH = TypeHandle(CoreLibBinder::GetElementType((CorElementType)arrayType)); + } + if (!arrayTH.IsNull()) + { + arrayTH = ClassLoader::LoadArrayTypeThrowing(arrayTH); + pType.Set(arrayTH.GetManagedClassObject()); + } + } + break; + } + default: + if (SERIALIZATION_TYPE_BOOLEAN <= fieldType && fieldType <= SERIALIZATION_TYPE_R8) + pMTValue = CoreLibBinder::GetElementType((CorElementType)fieldType); + else if(fieldType == SERIALIZATION_TYPE_ENUM) + fieldType = (CorSerializationType)pMTValue->GetInternalCorElementType(); + else + COMPlusThrow(kCustomAttributeFormatException); + + ARG_SLOT val = GetDataFromBlob(pCtorAssembly, fieldType, nullTH, &pBlob, pBlobEnd, pModule, &bObjectCreated); + _ASSERTE(!bObjectCreated); + + pValue.Set(pMTValue->Box((void*)ArgSlotEndiannessFixup(&val, pMTValue->GetNumInstanceFieldBytes()))); + } + + *ppBlobStart = pBlob; + END_QCALL; +} diff --git a/src/coreclr/vm/customattribute.h b/src/coreclr/vm/customattribute.h index 14ce07c785d5c..5ad802fc7fc0a 100644 --- a/src/coreclr/vm/customattribute.h +++ b/src/coreclr/vm/customattribute.h @@ -8,12 +8,11 @@ #include "fcall.h" #include "../md/compiler/custattr.h" -typedef Factory< SArray > CaValueArrayFactory; +using CaValueArrayFactory = Factory>; -class Attribute +namespace Attribute { -public: - static HRESULT ParseAttributeArgumentValues( + HRESULT ParseArgumentValues( void* pCa, INT32 cCa, CaValueArrayFactory* pCaValueArrayFactory, @@ -22,56 +21,31 @@ class Attribute CaNamedArg* pCaNamedArgs, COUNT_T cNamedArgs, DomainAssembly* pDomainAssembly); -}; - -class COMCustomAttribute -{ -public: - - // custom attributes utility functions - static FCDECL5(VOID, ParseAttributeUsageAttribute, PVOID pData, ULONG cData, ULONG* pTargets, CLR_BOOL* pInherited, CLR_BOOL* pAllowMultiple); - static FCDECL6(LPVOID, CreateCaObject, ReflectModuleBaseObject* pAttributedModuleUNSAFE, ReflectClassBaseObject* pCaTypeUNSAFE, ReflectMethodObject *pMethodUNSAFE, BYTE** ppBlob, BYTE* pEndBlob, INT32* pcNamedArgs); - static FCDECL7(void, GetPropertyOrFieldData, ReflectModuleBaseObject *pModuleUNSAFE, BYTE** ppBlobStart, BYTE* pBlobEnd, STRINGREF* pName, CLR_BOOL* pbIsProperty, OBJECTREF* pType, OBJECTREF* value); - -private: - - static TypeHandle GetTypeHandleFromBlob( - Assembly *pCtorAssembly, - CorSerializationType objType, - BYTE **pBlob, - const BYTE *endBlob, - Module *pModule); - - static ARG_SLOT GetDataFromBlob( - Assembly *pCtorAssembly, - CorSerializationType type, - TypeHandle th, - BYTE **pBlob, - const BYTE *endBlob, - Module *pModule, - BOOL *bObjectCreated); - - static void ReadArray( - Assembly *pCtorAssembly, - CorSerializationType arrayType, - int size, - TypeHandle th, - BYTE **pBlob, - const BYTE *endBlob, - Module *pModule, - BASEARRAYREF *pArray); - - static int GetStringSize( - BYTE **pBlob, - const BYTE *endBlob); - - template < typename T > - static BOOL CopyArrayVAL( - BASEARRAYREF pArray, - int nElements, - BYTE **pBlob, - const BYTE *endBlob); -}; - -#endif - +} + +extern "C" BOOL QCALLTYPE CustomAttribute_ParseAttributeUsageAttribute( + PVOID pData, + ULONG cData, + ULONG* pTargets, + BOOL* pAllowMultiple, + BOOL* pInherited); + +extern "C" void QCALLTYPE CustomAttribute_CreateCustomAttributeInstance( + QCall::ModuleHandle pModule, + QCall::ObjectHandleOnStack pCaType, + QCall::ObjectHandleOnStack pMethod, + BYTE** ppBlob, + BYTE* pEndBlob, + INT32* pcNamedArgs, + QCall::ObjectHandleOnStack result); + +extern "C" void QCALLTYPE CustomAttribute_CreatePropertyOrFieldData( + QCall::ModuleHandle pModule, + BYTE** ppBlobStart, + BYTE* pBlobEnd, + QCall::StringHandleOnStack pName, + BOOL* pbIsProperty, + QCall::ObjectHandleOnStack pType, + QCall::ObjectHandleOnStack value); + +#endif // _CUSTOMATTRIBUTE_H_ diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 9d7e8f7125c39..0fe7f4b1479ca 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -244,12 +244,6 @@ FCFuncStart(gCOMModuleHandleFuncs) FCFuncElement("GetMDStreamVersion", ModuleHandle::GetMDStreamVersion) FCFuncEnd() -FCFuncStart(gCOMCustomAttributeFuncs) - FCFuncElement("_ParseAttributeUsageAttribute", COMCustomAttribute::ParseAttributeUsageAttribute) - FCFuncElement("_CreateCaObject", COMCustomAttribute::CreateCaObject) - FCFuncElement("_GetPropertyOrFieldData", COMCustomAttribute::GetPropertyOrFieldData) -FCFuncEnd() - FCFuncStart(gRuntimeAssemblyFuncs) FCFuncElement("FCallIsDynamic", AssemblyNative::IsDynamic) FCFuncElement("GetManifestModule", AssemblyHandle::GetManifestModule) @@ -556,7 +550,6 @@ FCClassElement("AssemblyLoadContext", "System.Runtime.Loader", gAssemblyLoadCont FCClassElement("Buffer", "System", gBufferFuncs) FCClassElement("CastHelpers", "System.Runtime.CompilerServices", gCastHelpers) FCClassElement("ComAwareWeakReference", "System", gComAwareWeakReferenceFuncs) -FCClassElement("CustomAttribute", "System.Reflection", gCOMCustomAttributeFuncs) FCClassElement("Debugger", "System.Diagnostics", gDiagnosticsDebugger) FCClassElement("Delegate", "System", gDelegateFuncs) FCClassElement("DependentHandle", "System.Runtime", gDependentHandleFuncs) diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 8ff379f40f6e0..1150c55aa36d1 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -81,6 +81,9 @@ static const Entry s_QCall[] = DllImportEntry(ArgIterator_GetNextArgType) DllImportEntry(ArgIterator_GetNextArg) DllImportEntry(ArgIterator_GetNextArg2) + DllImportEntry(CustomAttribute_ParseAttributeUsageAttribute) + DllImportEntry(CustomAttribute_CreateCustomAttributeInstance) + DllImportEntry(CustomAttribute_CreatePropertyOrFieldData) DllImportEntry(Enum_GetValuesAndNames) DllImportEntry(DebugDebugger_Launch) DllImportEntry(DebugDebugger_Log)