2021-09-20 18:20:01 +02:00

1205 lines
48 KiB
C#

/*
Copyright (C) 2014-2019 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using dnlib.DotNet;
using dnlib.DotNet.MD;
using SSP = System.Security.Permissions;
namespace dnSpy.Debugger.DotNet.Metadata.Impl.COMD {
sealed class DmdComMetadataReader : DmdMetadataReaderBase, IMethodBodyResolver {
public override Guid ModuleVersionId {
get {
if (!modulePropsInitd)
InitializeModuleProperties();
return __moduleVersionId_DONT_USE;
}
}
public override int MDStreamVersion {
get {
if (!modulePropsInitd)
InitializeModuleProperties();
return __mdStreamVersion_DONT_USE;
}
}
public override string ModuleScopeName {
get {
if (!modulePropsInitd)
InitializeModuleProperties();
return __moduleScopeName_DONT_USE!;
}
}
public override string ImageRuntimeVersion {
get {
if (!modulePropsInitd)
InitializeModuleProperties();
return __imageRuntimeVersion_DONT_USE!;
}
}
void InitializeModuleProperties() {
if (modulePropsInitd)
return;
if (IsCOMThread)
InitializeModuleProperties_COMThread();
else
COMThread(InitializeModuleProperties_COMThread);
}
void InitializeModuleProperties_COMThread() {
dispatcher.VerifyAccess();
if (modulePropsInitd)
return;
__imageRuntimeVersion_DONT_USE = MDAPI.GetModuleVersionString(MetaDataImport) ?? string.Empty;
__moduleVersionId_DONT_USE = MDAPI.GetModuleMvid(MetaDataImport) ?? Guid.Empty;
__moduleScopeName_DONT_USE = MDAPI.GetModuleName(MetaDataImport) ?? string.Empty;
__machine_DONT_USE = MDAPI.GetModuleMachineAndPEKind(MetaDataImport, out __peKind_DONT_USE) ?? DmdImageFileMachine.I386;
bool isV1x =
__imageRuntimeVersion_DONT_USE.StartsWith("v1.", StringComparison.OrdinalIgnoreCase) ||
StringComparer.OrdinalIgnoreCase.Equals(__imageRuntimeVersion_DONT_USE, MDHeaderRuntimeVersion.MS_CLR_10_RETAIL) ||
StringComparer.OrdinalIgnoreCase.Equals(__imageRuntimeVersion_DONT_USE, MDHeaderRuntimeVersion.MS_CLR_10_COMPLUS);
if (isV1x)
__mdStreamVersion_DONT_USE = 0x00010000;
else
__mdStreamVersion_DONT_USE = 0x00020000;
modulePropsInitd = true;
}
bool modulePropsInitd;
Guid __moduleVersionId_DONT_USE;
int __mdStreamVersion_DONT_USE;
string? __moduleScopeName_DONT_USE;
string? __imageRuntimeVersion_DONT_USE;
DmdPortableExecutableKinds __peKind_DONT_USE;
DmdImageFileMachine __machine_DONT_USE;
// It doesn't seem to be possible to get the entry point from the COM MetaData API
public override DmdMethodInfo? EntryPoint => null;
internal IMetaDataImport2 MetaDataImport {
get {
Debug.Assert(IsCOMThread);
return __metaDataImport_DONT_USE;
}
}
internal IMetaDataAssemblyImport MetaDataAssemblyImport {
get {
Debug.Assert(IsCOMThread);
// It's initialized lazily and not in the ctor because the ctor is not necessarily running
// on the COM thread.
if (__metaDataAssemblyImport_DONT_USE is null)
__metaDataAssemblyImport_DONT_USE = (IMetaDataAssemblyImport)__metaDataImport_DONT_USE;
return __metaDataAssemblyImport_DONT_USE;
}
}
internal DmdModule Module => module;
internal DmdDispatcher Dispatcher => dispatcher;
readonly DmdModuleImpl module;
readonly IMetaDataImport2 __metaDataImport_DONT_USE;
IMetaDataAssemblyImport? __metaDataAssemblyImport_DONT_USE;
readonly DmdDynamicModuleHelper dynamicModuleHelper;
readonly DmdDispatcher dispatcher;
Dictionary<uint, List<uint>?>? ridToNested;
Dictionary<uint, uint>? ridToEnclosing;
readonly LazyList<DmdTypeRef> typeRefList;
readonly LazyList<DmdFieldDef, DmdTypeDef?> fieldList;
readonly LazyList<DmdTypeDef> typeDefList;
readonly LazyList<DmdMethodBase, DmdTypeDef?> methodList;
readonly LazyList2<DmdMemberInfo, IList<DmdType>?, IList<DmdType>?> memberRefList;
readonly LazyList<DmdEventDef, DmdTypeDef?> eventList;
readonly LazyList<DmdPropertyDef, DmdTypeDef?> propertyList;
readonly LazyList2<DmdType, IList<DmdType>?, IList<DmdType>?> typeSpecList;
readonly LazyList<DmdTypeRef> exportedTypeList;
readonly DmdNullGlobalType globalTypeIfThereAreNoTypes;
readonly Dictionary<IntPtr, DmdType?> fieldTypeCache;
readonly Dictionary<IntPtr, DmdMethodSignature?> methodSignatureCache;
public DmdComMetadataReader(DmdModuleImpl module, IMetaDataImport2 metaDataImport, DmdDynamicModuleHelper dynamicModuleHelper, DmdDispatcher dispatcher) {
this.module = module ?? throw new ArgumentNullException(nameof(module));
__metaDataImport_DONT_USE = metaDataImport ?? throw new ArgumentNullException(nameof(metaDataImport));
this.dynamicModuleHelper = dynamicModuleHelper ?? throw new ArgumentNullException(nameof(dynamicModuleHelper));
this.dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
fieldTypeCache = new Dictionary<IntPtr, DmdType?>();
methodSignatureCache = new Dictionary<IntPtr, DmdMethodSignature?>();
typeRefList = new LazyList<DmdTypeRef>(TryCreateTypeRefCOMD_COMThread);
fieldList = new LazyList<DmdFieldDef, DmdTypeDef?>(CreateResolvedField_COMThread);
typeDefList = new LazyList<DmdTypeDef>(TryCreateTypeDefCOMD_COMThread);
methodList = new LazyList<DmdMethodBase, DmdTypeDef?>(CreateResolvedMethod_COMThread);
memberRefList = new LazyList2<DmdMemberInfo, IList<DmdType>?, IList<DmdType>?>(CreateResolvedMemberRef_COMThread);
eventList = new LazyList<DmdEventDef, DmdTypeDef?>(CreateResolvedEvent_COMThread);
propertyList = new LazyList<DmdPropertyDef, DmdTypeDef?>(CreateResolvedProperty_COMThread);
typeSpecList = new LazyList2<DmdType, IList<DmdType>?, IList<DmdType>?>(TryCreateTypeSpecCOMD_COMThread);
exportedTypeList = new LazyList<DmdTypeRef>(TryCreateExportedTypeCOMD_COMThread);
globalTypeIfThereAreNoTypes = new DmdNullGlobalType(module, null);
dynamicModuleHelper.TypeLoaded += DmdDynamicModuleHelper_TypeLoaded_COMThread;
}
bool IsCOMThread => dispatcher.CheckAccess();
void COMThread(Action action) {
Debug.Assert(!IsCOMThread);
dispatcher.Invoke(action);
}
T COMThread<T>(Func<T> action) {
Debug.Assert(!IsCOMThread);
return dispatcher.Invoke(action);
}
DmdTypeRefCOMD? TryCreateTypeRefCOMD_COMThread(uint rid) {
dispatcher.VerifyAccess();
if (!MDAPI.IsValidToken(MetaDataImport, 0x01000000 + rid))
return null;
return new DmdTypeRefCOMD(this, rid, null);
}
DmdTypeDefCOMD? TryCreateTypeDefCOMD_COMThread(uint rid) {
dispatcher.VerifyAccess();
if (!MDAPI.IsValidToken(MetaDataImport, 0x02000000 + rid))
return null;
return new DmdTypeDefCOMD(this, rid, null);
}
DmdExportedTypeCOMD? TryCreateExportedTypeCOMD_COMThread(uint rid) {
dispatcher.VerifyAccess();
if (!MDAPI.IsValidToken(MetaDataImport, 0x27000000 + rid))
return null;
return new DmdExportedTypeCOMD(this, rid, null);
}
internal uint GetEnclosingTypeDefRid_COMThread(uint typeDefRid) {
dispatcher.VerifyAccess();
InitializeTypeTables_COMThread();
Debug2.Assert(ridToEnclosing is not null);
bool b = ridToEnclosing.TryGetValue(typeDefRid, out uint enclTypeRid);
Debug.Assert(b);
return enclTypeRid;
}
internal uint[] GetTypeDefNestedClassRids_COMThread(uint typeDefRid) {
dispatcher.VerifyAccess();
InitializeTypeTables_COMThread();
Debug2.Assert(ridToNested is not null);
bool b = ridToNested.TryGetValue(typeDefRid, out var list);
Debug.Assert(b);
return list is null || list.Count == 0 ? Array.Empty<uint>() : list.ToArray();
}
void InitializeTypeTables_COMThread() {
dispatcher.VerifyAccess();
if (ridToNested is not null)
return;
var allTypes = MDAPI.GetTypeDefTokens(MetaDataImport);
int capacity = allTypes.Length;
ridToNested = new Dictionary<uint, List<uint>?>(capacity);
ridToEnclosing = new Dictionary<uint, uint>(capacity);
UpdateTypeTables_COMThread(allTypes);
}
void UpdateTypeTables_COMThread(uint[] tokens) {
dispatcher.VerifyAccess();
Debug2.Assert(ridToNested is not null);
Debug2.Assert(ridToEnclosing is not null);
Array.Sort(tokens);
foreach (uint token in tokens) {
uint rid = token & 0x00FFFFFF;
Debug.Assert(rid != 0);
Debug.Assert(!ridToNested.ContainsKey(rid));
var enclTypeToken = new MDToken(MDAPI.GetTypeDefEnclosingType(MetaDataImport, token));
if (enclTypeToken.Rid != 0 && !MDAPI.IsValidToken(MetaDataImport, enclTypeToken.Raw)) {
// Here if it's an obfuscated assembly with invalid MD
enclTypeToken = new MDToken(Table.TypeDef, 0);
}
var enclTypeRid = enclTypeToken.Rid;
if (enclTypeRid == 0) {
} // All nested types must be after their enclosing type
else if (!ridToNested.TryGetValue(enclTypeRid, out var enclTypeList)) {
// Here if it's an obfuscated assembly with invalid MD
enclTypeRid = 0;
}
else {
if (enclTypeList is null)
ridToNested[enclTypeRid] = enclTypeList = new List<uint>();
enclTypeList.Add(rid);
}
ridToNested[rid] = null;
ridToEnclosing[rid] = enclTypeRid;
}
}
void DmdDynamicModuleHelper_TypeLoaded_COMThread(object? sender, DmdTypeLoadedEventArgs e) {
dispatcher.VerifyAccess();
bool b = (e.MetadataToken >> 24) == 0x02 && (e.MetadataToken & 0x00FFFFFF) != 0 && MDAPI.IsValidToken(MetaDataImport, (uint)e.MetadataToken);
Debug.Assert(b);
if (!b)
return;
if (!module.IsDynamic)
return;
uint typeToken = (uint)e.MetadataToken;
uint[] newTokens;
if (ridToNested is not null)
newTokens = UpdateTypeTables_COMThread(typeToken);
else
newTokens = GetNewTokens_COMThread(typeToken);
typeDefList.TryGet(typeToken)?.DynamicType_InvalidateCachedMembers();
TypesUpdated?.Invoke(this, new DmdTypesUpdatedEventArgs(newTokens));
}
public override event EventHandler<DmdTypesUpdatedEventArgs>? TypesUpdated;
uint[] UpdateTypeTables_COMThread(uint typeToken) {
dispatcher.VerifyAccess();
uint typeRid = typeToken & 0x00FFFFFF;
bool b = ridToEnclosing is not null && !ridToEnclosing.ContainsKey(typeRid);
Debug.Assert(b);
if (!b)
return new[] { typeToken };
Debug2.Assert(ridToEnclosing is not null);
var tokens = GetNewTokens_COMThread(typeRid);
UpdateTypeTables_COMThread(tokens);
foreach (var token in tokens) {
uint rid = token & 0x00FFFFFF;
if (token != typeToken) {
b = typeDefList.TryGet(rid) is not null;
Debug.Assert(!b);
if (b)
continue;
_ = typeDefList[rid - 1];
}
b = ridToEnclosing.TryGetValue(rid, out uint enclTypeRid);
Debug.Assert(b);
if (enclTypeRid != 0) {
var enclType = typeDefList.TryGet(enclTypeRid);
enclType?.DynamicType_InvalidateCachedNestedTypes();
}
}
return tokens;
}
uint[] GetNewTokens_COMThread(uint rid) {
dispatcher.VerifyAccess();
if (ridToEnclosing is null)
return new[] { rid };
var hash = tmpHash;
hash.Clear();
for (;;) {
if (ridToEnclosing.ContainsKey(rid))
break;
if (rid == 0 || !hash.Add(rid))
break;
rid = MDAPI.GetTypeDefEnclosingType(MetaDataImport, 0x02000000 + rid) & 0x00FFFFFF;
}
var tokens = new uint[hash.Count];
int i = 0;
foreach (uint rid2 in hash)
tokens[i++] = 0x02000000 + rid2;
return tokens;
}
readonly HashSet<uint> tmpHash = new HashSet<uint>();
(DmdType? type, bool containedGenericParams) TryCreateTypeSpecCOMD_COMThread(uint rid, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
dispatcher.VerifyAccess();
uint token = 0x1B000000 + rid;
if (!MDAPI.IsValidToken(MetaDataImport, token))
return (null, containedGenericParams: true);
var blob = MDAPI.GetTypeSpecSignatureBlob(MetaDataImport, token);
return DmdSignatureReader.ReadTypeSignature(module, new DmdPointerDataStream(blob), genericTypeArguments, genericMethodArguments, resolveTypes);
}
DmdFieldDefCOMD? CreateResolvedField_COMThread(uint rid, DmdTypeDef? declaringType) {
dispatcher.VerifyAccess();
uint token = 0x04000000 + rid;
if (!MDAPI.IsValidToken(MetaDataImport, token))
return null;
if (declaringType is null)
declaringType = ResolveTypeDef_COMThread(MDAPI.GetFieldOwnerRid(MetaDataImport, token)) ?? globalTypeIfThereAreNoTypes;
else
Debug.Assert((object)declaringType == ResolveTypeDef_COMThread(MDAPI.GetFieldOwnerRid(MetaDataImport, token)));
return CreateFieldDefCore_COMThread(rid, declaringType, declaringType);
}
internal DmdFieldDef CreateFieldDef_COMThread(uint rid, DmdType declaringType, DmdType reflectedType) {
dispatcher.VerifyAccess();
if ((object)declaringType == reflectedType && declaringType is DmdTypeDef declaringTypeDef)
return ResolveFieldDef_COMThread(rid, declaringTypeDef)!;
return CreateFieldDefCore_COMThread(rid, declaringType, reflectedType);
}
DmdFieldDefCOMD CreateFieldDefCore_COMThread(uint rid, DmdType declaringType, DmdType reflectedType) {
dispatcher.VerifyAccess();
return new DmdFieldDefCOMD(this, rid, declaringType, reflectedType);
}
internal DmdType ReadFieldType_COMThread((IntPtr addr, uint size) signature, IList<DmdType> genericTypeArguments) {
dispatcher.VerifyAccess();
if (fieldTypeCache.TryGetValue(signature.addr, out var fieldType)) {
if (fieldType is not null)
return fieldType;
var info = ReadFieldTypeCore_COMThread(signature, genericTypeArguments);
Debug.Assert(info.containedGenericParams);
return info.fieldType;
}
else {
var info = ReadFieldTypeCore_COMThread(signature, genericTypeArguments);
if (info.containedGenericParams)
fieldTypeCache.Add(signature.addr, null);
else
fieldTypeCache.Add(signature.addr, info.fieldType);
return info.fieldType;
}
}
(DmdType fieldType, bool containedGenericParams) ReadFieldTypeCore_COMThread((IntPtr addr, uint size) signature, IList<DmdType>? genericTypeArguments) {
dispatcher.VerifyAccess();
if (signature.addr == IntPtr.Zero)
return (module.AppDomain.System_Void, false);
return DmdSignatureReader.ReadFieldSignature(module, new DmdPointerDataStream(signature), genericTypeArguments, resolveTypes);
}
DmdMethodBase? CreateResolvedMethod_COMThread(uint rid, DmdTypeDef? declaringType) {
dispatcher.VerifyAccess();
uint token = 0x06000000 + rid;
if (!MDAPI.IsValidToken(MetaDataImport, token))
return null;
if (declaringType is null)
declaringType = ResolveTypeDef_COMThread(MDAPI.GetMethodOwnerRid(MetaDataImport, token)) ?? globalTypeIfThereAreNoTypes;
else
Debug.Assert((object)declaringType == ResolveTypeDef_COMThread(MDAPI.GetMethodOwnerRid(MetaDataImport, token)));
return CreateMethodDefCore_COMThread(rid, declaringType, declaringType);
}
internal DmdMethodBase CreateMethodDef_COMThread(uint rid, DmdType declaringType, DmdType reflectedType) {
dispatcher.VerifyAccess();
if ((object)declaringType == reflectedType && declaringType is DmdTypeDef declaringTypeDef)
return ResolveMethodDef_COMThread(rid, declaringTypeDef)!;
return CreateMethodDefCore_COMThread(rid, declaringType, reflectedType);
}
DmdMethodBase CreateMethodDefCore_COMThread(uint rid, DmdType declaringType, DmdType reflectedType) {
dispatcher.VerifyAccess();
uint token = 0x06000000 + rid;
var name = MDAPI.GetMethodName(MetaDataImport, token) ?? string.Empty;
MDAPI.GetMethodAttributes(MetaDataImport, token, out var attrs, out var implAttrs);
if ((attrs & DmdMethodAttributes.RTSpecialName) != 0 && name.Length > 0 && name[0] == '.') {
if (name == DmdConstructorInfo.ConstructorName || name == DmdConstructorInfo.TypeConstructorName)
return new DmdConstructorDefCOMD(this, attrs, implAttrs, rid, name, declaringType, reflectedType);
}
return new DmdMethodDefCOMD(this, attrs, implAttrs, rid, name, declaringType, reflectedType);
}
internal DmdMethodSignature ReadMethodSignature_COMThread((IntPtr addr, uint size) signature, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments, bool isProperty) {
dispatcher.VerifyAccess();
if (methodSignatureCache.TryGetValue(signature.addr, out var methodSignature)) {
if (methodSignature is not null)
return methodSignature;
var info = ReadMethodSignatureCore_COMThread(signature, genericTypeArguments, genericMethodArguments, isProperty);
Debug.Assert(info.containedGenericParams);
return info.methodSignature;
}
else {
var info = ReadMethodSignatureCore_COMThread(signature, genericTypeArguments, genericMethodArguments, isProperty);
if (info.containedGenericParams)
methodSignatureCache.Add(signature.addr, null);
else
methodSignatureCache.Add(signature.addr, info.methodSignature);
return info.methodSignature;
}
}
(DmdMethodSignature methodSignature, bool containedGenericParams) ReadMethodSignatureCore_COMThread((IntPtr addr, uint size) signature, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments, bool isProperty) {
dispatcher.VerifyAccess();
return DmdSignatureReader.ReadMethodSignature(module, new DmdPointerDataStream(signature), genericTypeArguments, genericMethodArguments, isProperty, resolveTypes);
}
internal (DmdParameterInfo? returnParameter, DmdParameterInfo[] parameters) CreateParameters_COMThread(DmdMethodBase method, bool createReturnParameter) {
dispatcher.VerifyAccess();
var tokens = MDAPI.GetParamTokens(MetaDataImport, (uint)method.MetadataToken);
var methodSignature = method.GetMethodSignature();
var sigParamTypes = methodSignature.GetParameterTypes();
DmdParameterInfo? returnParameter = null;
var parameters = sigParamTypes.Count == 0 ? Array.Empty<DmdParameterInfo>() : new DmdParameterInfo[sigParamTypes.Count];
for (int i = 0; i < tokens.Length; i++) {
uint token = tokens[i];
uint rid = token & 0x00FFFFFF;
var name = MDAPI.GetParamName(MetaDataImport, token);
if (!MDAPI.GetParamSeqAndAttrs(MetaDataImport, token, out uint seq, out var attrs))
continue;
if (seq == 0) {
if (createReturnParameter && returnParameter is null)
returnParameter = new DmdParameterDefCOMD(this, rid, name, attrs, method, -1, methodSignature.ReturnType);
}
else {
int paramIndex = (int)seq - 1;
if ((uint)paramIndex < (uint)parameters.Length) {
if (parameters[paramIndex] is null)
parameters[paramIndex] = new DmdParameterDefCOMD(this, rid, name, attrs, method, paramIndex, sigParamTypes[paramIndex]);
}
}
}
for (int i = 0; i < parameters.Length; i++) {
if (parameters[i] is null)
parameters[i] = new DmdCreatedParameterDef(method, i, sigParamTypes[i]);
}
if (createReturnParameter && returnParameter is null)
returnParameter = new DmdCreatedParameterDef(method, -1, methodSignature.ReturnType);
return (returnParameter, parameters);
}
DmdEventDef? CreateResolvedEvent_COMThread(uint rid, DmdTypeDef? declaringType) {
dispatcher.VerifyAccess();
uint token = 0x14000000 + rid;
if (!MDAPI.IsValidToken(MetaDataImport, token))
return null;
if (declaringType is null)
declaringType = ResolveTypeDef_COMThread(MDAPI.GetEventOwnerRid(MetaDataImport, token)) ?? globalTypeIfThereAreNoTypes;
else
Debug.Assert((object)declaringType == ResolveTypeDef_COMThread(MDAPI.GetEventOwnerRid(MetaDataImport, token)));
return CreateEventDefCore_COMThread(rid, declaringType, declaringType);
}
internal DmdEventDef CreateEventDef_COMThread(uint rid, DmdType declaringType, DmdType reflectedType) {
dispatcher.VerifyAccess();
if ((object)declaringType == reflectedType && declaringType is DmdTypeDef declaringTypeDef)
return ResolveEventDef_COMThread(rid, declaringTypeDef)!;
return CreateEventDefCore_COMThread(rid, declaringType, reflectedType);
}
DmdEventDef CreateEventDefCore_COMThread(uint rid, DmdType declaringType, DmdType reflectedType) {
dispatcher.VerifyAccess();
return new DmdEventDefCOMD(this, rid, declaringType, reflectedType);
}
DmdPropertyDef? CreateResolvedProperty_COMThread(uint rid, DmdTypeDef? declaringType) {
dispatcher.VerifyAccess();
uint token = 0x17000000 + rid;
if (!MDAPI.IsValidToken(MetaDataImport, token))
return null;
if (declaringType is null)
declaringType = ResolveTypeDef_COMThread(MDAPI.GetPropertyOwnerRid(MetaDataImport, token)) ?? globalTypeIfThereAreNoTypes;
else
Debug.Assert((object)declaringType == ResolveTypeDef_COMThread(MDAPI.GetPropertyOwnerRid(MetaDataImport, token)));
return CreatePropertyDefCore_COMThread(rid, declaringType, declaringType);
}
internal DmdPropertyDef CreatePropertyDef_COMThread(uint rid, DmdType declaringType, DmdType reflectedType) {
dispatcher.VerifyAccess();
if ((object)declaringType == reflectedType && declaringType is DmdTypeDef declaringTypeDef)
return ResolvePropertyDef_COMThread(rid, declaringTypeDef)!;
return CreatePropertyDefCore_COMThread(rid, declaringType, reflectedType);
}
DmdPropertyDef CreatePropertyDefCore_COMThread(uint rid, DmdType declaringType, DmdType reflectedType) {
dispatcher.VerifyAccess();
return new DmdPropertyDefCOMD(this, rid, declaringType, reflectedType);
}
internal DmdType[]? CreateGenericParameters_COMThread(DmdMethodBase method) {
dispatcher.VerifyAccess();
var tokens = MDAPI.GetGenericParamTokens(MetaDataImport, (uint)method.MetadataToken);
if (tokens.Length == 0)
return null;
var genericParams = new DmdType[tokens.Length];
for (int i = 0; i < genericParams.Length; i++) {
uint token = tokens[i];
uint rid = token & 0x00FFFFFF;
var gpName = MDAPI.GetGenericParamName(MetaDataImport, token) ?? string.Empty;
if (!MDAPI.GetGenericParamNumAndAttrs(MetaDataImport, token, out var gpNumber, out var gpAttrs))
return null;
var gpType = new DmdGenericParameterTypeCOMD(this, rid, method, gpName, gpNumber, gpAttrs, null);
genericParams[i] = gpType;
}
return genericParams;
}
(DmdMemberInfo member, bool containedGenericParams) CreateResolvedMemberRef_COMThread(uint rid, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
dispatcher.VerifyAccess();
uint token = 0x0A000000 + rid;
var signature = MDAPI.GetMemberRefSignatureBlob(MetaDataImport, token);
var name = MDAPI.GetMemberRefName(MetaDataImport, token) ?? string.Empty;
uint classToken = MDAPI.GetMemberRefClassToken(MetaDataImport, token);
var reflectedTypeRef = GetMemberRefParent_COMThread(classToken, genericTypeArguments, genericMethodArguments);
if (reflectedTypeRef is DmdGenericInstanceType || reflectedTypeRef is DmdGenericInstanceTypeRef)
genericTypeArguments = reflectedTypeRef.GetGenericArguments();
var info = ReadMethodSignatureOrFieldType_COMThread(signature, genericTypeArguments, genericMethodArguments);
var rawInfo = info.containedGenericParams ? ReadMethodSignatureOrFieldType_COMThread(signature, null, null) : info;
bool containedGenericParams = info.containedGenericParams;
if ((classToken >> 24) == 0x1B)
containedGenericParams = true;
if (info.fieldType is not null) {
var fieldRef = new DmdFieldRef(reflectedTypeRef, name, rawInfo.fieldType!, info.fieldType);
return (fieldRef, containedGenericParams);
}
else {
Debug2.Assert(info.methodSignature is not null);
if (name == DmdConstructorInfo.ConstructorName || name == DmdConstructorInfo.TypeConstructorName) {
var ctorRef = new DmdConstructorRef(reflectedTypeRef, name, rawInfo.methodSignature!, info.methodSignature);
return (ctorRef, containedGenericParams);
}
else {
var methodRef = new DmdMethodRefCOMD(this, signature, genericTypeArguments, reflectedTypeRef, name, rawInfo.methodSignature!, info.methodSignature);
return (methodRef, containedGenericParams);
}
}
}
DmdType GetMemberRefParent_COMThread(uint classToken, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
dispatcher.VerifyAccess();
uint rid = classToken & 0x00FFFFFF;
switch ((Table)(classToken >> 24)) {
case Table.TypeRef:
case Table.TypeDef:
case Table.TypeSpec:
return ResolveType((int)classToken, genericTypeArguments, genericMethodArguments, DmdResolveOptions.None) ?? Module.AppDomain.System_Void;
case Table.ModuleRef:
var moduleName = MDAPI.GetModuleRefName(MetaDataImport, classToken) ?? string.Empty;
if (StringComparer.OrdinalIgnoreCase.Equals(moduleName, Module.ScopeName))
return Module.GlobalType;
var referencedModule = Module.Assembly.GetModule(moduleName);
return referencedModule?.GlobalType ?? Module.AppDomain.System_Void;
case Table.Method:
return ResolveMethodDef_COMThread(rid)?.DeclaringType ?? Module.AppDomain.System_Void;
default:
return Module.AppDomain.System_Void;
}
}
(DmdType? fieldType, DmdMethodSignature? methodSignature, bool containedGenericParams) ReadMethodSignatureOrFieldType_COMThread((IntPtr addr, uint size) signature, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
dispatcher.VerifyAccess();
if (methodSignatureCache.TryGetValue(signature.addr, out var methodSignature)) {
if (methodSignature is not null)
return (null, methodSignature, false);
var info = ReadMethodSignatureCore_COMThread(signature, genericTypeArguments, genericMethodArguments, isProperty: false);
if (info.methodSignature is null)
throw new InvalidOperationException();
Debug.Assert(info.containedGenericParams);
return (null, info.methodSignature, info.containedGenericParams);
}
else if (fieldTypeCache.TryGetValue(signature.addr, out var fieldType)) {
if (fieldType is not null)
return (fieldType, null, false);
var info = ReadFieldTypeCore_COMThread(signature, genericTypeArguments);
if (info.fieldType is null)
throw new InvalidOperationException();
Debug.Assert(info.containedGenericParams);
return (info.fieldType, null, info.containedGenericParams);
}
else {
var info = DmdSignatureReader.ReadMethodSignatureOrFieldType(module, new DmdPointerDataStream(signature), genericTypeArguments, genericMethodArguments, resolveTypes);
if (info.fieldType is not null) {
if (info.containedGenericParams)
fieldTypeCache.Add(signature.addr, null);
else
fieldTypeCache.Add(signature.addr, info.fieldType);
return (info.fieldType, null, info.containedGenericParams);
}
else {
Debug2.Assert(info.methodSignature is not null);
if (info.containedGenericParams)
methodSignatureCache.Add(signature.addr, null);
else
methodSignatureCache.Add(signature.addr, info.methodSignature);
return (null, info.methodSignature, info.containedGenericParams);
}
}
}
internal DmdMethodBody? GetMethodBody_COMThread(DmdMethodBase method, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
dispatcher.VerifyAccess();
if ((method.MethodImplementationFlags & DmdMethodImplAttributes.CodeTypeMask) != DmdMethodImplAttributes.IL)
return null;
var rvaTmp = MDAPI.GetRVA(MetaDataImport, (uint)method.MetadataToken);
if (rvaTmp is null)
return null;
uint rva = rvaTmp.Value;
// dynamic modules can have methods with RVA == 0 because it's relative to the .text section
// and not really an RVA.
if (!module.IsDynamic) {
if (rva == 0)
return null;
}
else {
if ((method.Attributes & DmdMethodAttributes.Abstract) != 0 && rva == 0)
return null;
}
var bodyStream = dynamicModuleHelper.TryGetMethodBody(method.Module, method.MetadataToken, rva);
if (bodyStream is null)
return null;
using (bodyStream) {
var body = DmdMethodBodyReader.Create(this, bodyStream, genericTypeArguments, genericMethodArguments);
Debug2.Assert(body is not null);
return body;
}
}
(DmdType type, bool isPinned)[] IMethodBodyResolver.ReadLocals(int localSignatureMetadataToken, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
dispatcher.VerifyAccess();
if ((localSignatureMetadataToken & 0x00FFFFFF) == 0 || (localSignatureMetadataToken >> 24) != 0x11)
return Array.Empty<(DmdType, bool)>();
var signature = MDAPI.GetStandAloneSigBlob(MetaDataImport, (uint)localSignatureMetadataToken);
if (signature.addr == IntPtr.Zero)
return Array.Empty<(DmdType, bool)>();
return DmdSignatureReader.ReadLocalsSignature(module, new DmdPointerDataStream(signature), genericTypeArguments, genericMethodArguments, resolveTypes);
}
public override DmdTypeDef[] GetTypes() {
if (IsCOMThread)
return GetTypes_COMThread();
else
return COMThread(GetTypes_COMThread);
}
DmdTypeDef[] GetTypes_COMThread() {
dispatcher.VerifyAccess();
var result = new List<DmdTypeDef>();
for (uint rid = 1; rid <= 0x00FFFFFF; rid++) {
var type = ResolveTypeDef_COMThread(rid);
if (type is null)
break;
result.Add(type);
}
// This should never happen but we must return at least one type
if (result.Count == 0)
return new DmdTypeDef[] { globalTypeIfThereAreNoTypes };
return result.ToArray();
}
public override DmdTypeRef[] GetExportedTypes() {
if (IsCOMThread)
return GetExportedTypes_COMThread();
else
return COMThread(GetExportedTypes_COMThread);
}
DmdTypeRef[] GetExportedTypes_COMThread() {
dispatcher.VerifyAccess();
List<DmdTypeRef>? result = null;
for (uint rid = 1; rid <= 0x00FFFFFF; rid++) {
var type = ResolveExportedType_COMThread(rid);
if (type is null)
break;
if (result is null)
result = new List<DmdTypeRef>();
result.Add(type);
}
return result?.ToArray() ?? Array.Empty<DmdTypeRef>();
}
protected override DmdTypeRef? ResolveTypeRef(uint rid) {
if (IsCOMThread)
return ResolveTypeRef_COMThread(rid);
else
return COMThread(() => ResolveTypeRef_COMThread(rid));
}
DmdTypeRef? ResolveTypeRef_COMThread(uint rid) {
dispatcher.VerifyAccess();
return typeRefList[rid - 1];
}
protected override DmdTypeDef? ResolveTypeDef(uint rid) {
if (IsCOMThread)
return ResolveTypeDef_COMThread(rid);
else
return COMThread(() => ResolveTypeDef_COMThread(rid));
}
DmdTypeDef? ResolveTypeDef_COMThread(uint rid) {
dispatcher.VerifyAccess();
var type = typeDefList[rid - 1];
if (type is null && rid == 1)
return globalTypeIfThereAreNoTypes;
return type;
}
protected override DmdFieldDef? ResolveFieldDef(uint rid) {
if (IsCOMThread)
return ResolveFieldDef_COMThread(rid);
else
return COMThread(() => ResolveFieldDef_COMThread(rid));
}
DmdFieldDef? ResolveFieldDef_COMThread(uint rid) {
dispatcher.VerifyAccess();
return fieldList[rid - 1, null];
}
DmdFieldDef? ResolveFieldDef_COMThread(uint rid, DmdTypeDef declaringType) {
dispatcher.VerifyAccess();
return fieldList[rid - 1, declaringType];
}
protected override DmdMethodBase? ResolveMethodDef(uint rid) {
if (IsCOMThread)
return ResolveMethodDef_COMThread(rid);
else
return COMThread(() => ResolveMethodDef_COMThread(rid));
}
DmdMethodBase? ResolveMethodDef_COMThread(uint rid) {
dispatcher.VerifyAccess();
return methodList[rid - 1, null];
}
DmdMethodBase? ResolveMethodDef_COMThread(uint rid, DmdTypeDef declaringType) {
dispatcher.VerifyAccess();
return methodList[rid - 1, declaringType];
}
protected override DmdMemberInfo? ResolveMemberRef(uint rid, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
if (IsCOMThread)
return ResolveMemberRef_COMThread(rid, genericTypeArguments, genericMethodArguments);
else
return COMThread(() => ResolveMemberRef_COMThread(rid, genericTypeArguments, genericMethodArguments));
}
DmdMemberInfo? ResolveMemberRef_COMThread(uint rid, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
dispatcher.VerifyAccess();
return memberRefList[rid - 1, genericTypeArguments, genericMethodArguments]; ;
}
protected override DmdEventDef? ResolveEventDef(uint rid) {
if (IsCOMThread)
return ResolveEventDef_COMThread(rid);
else
return COMThread(() => ResolveEventDef_COMThread(rid));
}
DmdEventDef? ResolveEventDef_COMThread(uint rid) {
dispatcher.VerifyAccess();
return eventList[rid - 1, null];
}
DmdEventDef? ResolveEventDef_COMThread(uint rid, DmdTypeDef declaringType) {
dispatcher.VerifyAccess();
return eventList[rid - 1, declaringType];
}
protected override DmdPropertyDef? ResolvePropertyDef(uint rid) {
if (IsCOMThread)
return ResolvePropertyDef_COMThread(rid);
else
return COMThread(() => ResolvePropertyDef_COMThread(rid));
}
DmdPropertyDef? ResolvePropertyDef_COMThread(uint rid) {
dispatcher.VerifyAccess();
return propertyList[rid - 1, null];
}
DmdPropertyDef? ResolvePropertyDef_COMThread(uint rid, DmdTypeDef declaringType) {
dispatcher.VerifyAccess();
return propertyList[rid - 1, declaringType];
}
protected override DmdType? ResolveTypeSpec(uint rid, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
if (IsCOMThread)
return ResolveTypeSpec_COMThread(rid, genericTypeArguments, genericMethodArguments);
else
return COMThread(() => ResolveTypeSpec_COMThread(rid, genericTypeArguments, genericMethodArguments));
}
DmdType? ResolveTypeSpec_COMThread(uint rid, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
dispatcher.VerifyAccess();
return typeSpecList[rid - 1, genericTypeArguments, genericMethodArguments];
}
protected override DmdTypeRef? ResolveExportedType(uint rid) {
if (IsCOMThread)
return ResolveExportedType_COMThread(rid);
else
return COMThread(() => ResolveExportedType_COMThread(rid));
}
DmdTypeRef? ResolveExportedType_COMThread(uint rid) {
dispatcher.VerifyAccess();
return exportedTypeList[rid - 1];
}
protected override DmdMethodBase? ResolveMethodSpec(uint rid, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
if (IsCOMThread)
return ResolveMethodSpec_COMThread(rid, genericTypeArguments, genericMethodArguments);
else
return COMThread(() => ResolveMethodSpec_COMThread(rid, genericTypeArguments, genericMethodArguments));
}
DmdMethodBase? ResolveMethodSpec_COMThread(uint rid, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
dispatcher.VerifyAccess();
uint token = 0x2B000000 + rid;
if (!MDAPI.IsValidToken(MetaDataImport, token))
return null;
var signature = MDAPI.GetMethodSpecProps(MetaDataImport, token, out var methodToken);
var instantiation = DmdSignatureReader.ReadMethodSpecSignature(module, new DmdPointerDataStream(signature), genericTypeArguments, genericMethodArguments, resolveTypes).types;
var genericMethod = ResolveMethod((int)methodToken, genericTypeArguments, genericMethodArguments, DmdResolveOptions.None) as DmdMethodInfo;
if (genericMethod?.IsGenericMethodDefinition != true)
return null;
return genericMethod.MakeGenericMethod(instantiation);
}
protected override DmdMethodSignature? ResolveMethodSignature(uint rid, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
if (IsCOMThread)
return ResolveMethodSignature_COMThread(rid, genericTypeArguments, genericMethodArguments);
else
return COMThread(() => ResolveMethodSignature_COMThread(rid, genericTypeArguments, genericMethodArguments));
}
DmdMethodSignature? ResolveMethodSignature_COMThread(uint rid, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) {
dispatcher.VerifyAccess();
var signature = MDAPI.GetStandAloneSigBlob(MetaDataImport, 0x11000000 + rid);
if (signature.addr == IntPtr.Zero)
return null;
return ReadMethodSignature_COMThread(signature, genericTypeArguments, genericMethodArguments, isProperty: false);
}
protected override byte[]? ResolveFieldSignature(uint rid) {
if (IsCOMThread)
return ResolveFieldSignature_COMThread(rid);
else
return COMThread(() => ResolveFieldSignature_COMThread(rid));
}
protected override byte[]? ResolveMethodSignature(uint rid) {
if (IsCOMThread)
return ResolveMethodSignature_COMThread(rid);
else
return COMThread(() => ResolveMethodSignature_COMThread(rid));
}
protected override byte[]? ResolveMemberRefSignature(uint rid) {
if (IsCOMThread)
return ResolveMemberRefSignature_COMThread(rid);
else
return COMThread(() => ResolveMemberRefSignature_COMThread(rid));
}
protected override byte[]? ResolveStandAloneSigSignature(uint rid) {
if (IsCOMThread)
return ResolveStandAloneSigSignature_COMThread(rid);
else
return COMThread(() => ResolveStandAloneSigSignature_COMThread(rid));
}
protected override byte[]? ResolveTypeSpecSignature(uint rid) {
if (IsCOMThread)
return ResolveTypeSpecSignature_COMThread(rid);
else
return COMThread(() => ResolveTypeSpecSignature_COMThread(rid));
}
protected override byte[]? ResolveMethodSpecSignature(uint rid) {
if (IsCOMThread)
return ResolveMethodSpecSignature_COMThread(rid);
else
return COMThread(() => ResolveMethodSpecSignature_COMThread(rid));
}
static byte[] GetData((IntPtr addr, uint size) info) {
if (info.addr == IntPtr.Zero)
return Array.Empty<byte>();
var sig = new byte[info.size];
Marshal.Copy(info.addr, sig, 0, sig.Length);
return sig;
}
byte[] ResolveFieldSignature_COMThread(uint rid) {
dispatcher.VerifyAccess();
return GetData(MDAPI.GetFieldSignatureBlob(MetaDataImport, 0x04000000 + rid));
}
byte[] ResolveMethodSignature_COMThread(uint rid) {
dispatcher.VerifyAccess();
return GetData(MDAPI.GetMethodSignatureBlob(MetaDataImport, 0x06000000 + rid));
}
byte[] ResolveMemberRefSignature_COMThread(uint rid) {
dispatcher.VerifyAccess();
return GetData(MDAPI.GetMemberRefSignatureBlob(MetaDataImport, 0x0A000000 + rid));
}
byte[] ResolveStandAloneSigSignature_COMThread(uint rid) {
dispatcher.VerifyAccess();
return GetData(MDAPI.GetStandAloneSigBlob(MetaDataImport, 0x11000000 + rid));
}
byte[] ResolveTypeSpecSignature_COMThread(uint rid) {
dispatcher.VerifyAccess();
return GetData(MDAPI.GetTypeSpecSignatureBlob(MetaDataImport, 0x1B000000 + rid));
}
byte[] ResolveMethodSpecSignature_COMThread(uint rid) {
dispatcher.VerifyAccess();
return GetData(MDAPI.GetMethodSpecProps(MetaDataImport, 0x2B000000 + rid, out _));
}
protected override string ResolveStringCore(uint offset) {
if (IsCOMThread)
return ResolveStringCore_COMThread(offset);
else
return COMThread(() => ResolveStringCore_COMThread(offset));
}
string ResolveStringCore_COMThread(uint offset) {
dispatcher.VerifyAccess();
return MDAPI.GetUserString(MetaDataImport, 0x70000000 + offset) ?? string.Empty;
}
public override void GetPEKind(out DmdPortableExecutableKinds peKind, out DmdImageFileMachine machine) {
if (!modulePropsInitd)
InitializeModuleProperties();
peKind = __peKind_DONT_USE;
machine = __machine_DONT_USE;
}
public override DmdReadOnlyAssemblyName GetName() {
if (assemblyName is null)
InitializeAssemblyName();
Debug2.Assert(assemblyName is not null);
return assemblyName;
}
DmdReadOnlyAssemblyName? assemblyName;
void InitializeAssemblyName() {
if (assemblyName is not null)
return;
if (IsCOMThread)
InitializeAssemblyName_COMThread();
else
COMThread(InitializeAssemblyName_COMThread);
}
void InitializeAssemblyName_COMThread() {
dispatcher.VerifyAccess();
if (assemblyName is not null)
return;
const uint token = 0x20000001;
var version = MDAPI.GetAssemblyVersionAndLocale(MetaDataAssemblyImport, token, out var locale) ?? new Version(0, 0, 0, 0);
var name = MDAPI.GetAssemblySimpleName(MetaDataAssemblyImport, token) ?? string.Empty;
var cultureName = locale ?? string.Empty;
var hashAlgorithm = MDAPI.GetAssemblyHashAlgorithm(MetaDataAssemblyImport, token) ?? DmdAssemblyHashAlgorithm.SHA1;
var publicKey = MDAPI.GetAssemblyPublicKey(MetaDataAssemblyImport, token) ?? Array.Empty<byte>();
var flags = MDAPI.GetAssemblyAttributes(MetaDataAssemblyImport, token) ?? DmdAssemblyNameFlags.None;
assemblyName = new DmdReadOnlyAssemblyName(name, version, cultureName, flags, publicKey, null, hashAlgorithm);
}
public override DmdReadOnlyAssemblyName[] GetReferencedAssemblies() {
if (IsCOMThread)
return GetReferencedAssemblies_COMThread();
else
return COMThread(GetReferencedAssemblies_COMThread);
}
DmdReadOnlyAssemblyName[] GetReferencedAssemblies_COMThread() {
dispatcher.VerifyAccess();
var list = new List<DmdReadOnlyAssemblyName>();
for (uint token = 0x23000001; ; token++) {
if (!MDAPI.IsValidToken(MetaDataImport, token))
break;
list.Add(ReadAssemblyName_COMThread(token & 0x00FFFFFF));
}
return list.ToArray();
}
internal DmdReadOnlyAssemblyName ReadAssemblyName_COMThread(uint rid) {
dispatcher.VerifyAccess();
uint token = 0x23000000 + rid;
var name = MDAPI.GetAssemblyRefSimpleName(MetaDataAssemblyImport, token) ?? string.Empty;
var version = MDAPI.GetAssemblyRefVersionAndLocale(MetaDataAssemblyImport, token, out var locale) ?? new Version(0, 0, 0, 0);
var cultureName = locale ?? string.Empty;
var publicKeyOrToken = MDAPI.GetAssemblyRefPublicKeyOrToken(MetaDataAssemblyImport, token, out var flags);
return new DmdReadOnlyAssemblyName(name, version, cultureName, flags, publicKeyOrToken, DmdAssemblyHashAlgorithm.None);
}
public override unsafe bool ReadMemory(uint rva, void* destination, int size) => false;
protected override DmdCustomAttributeData[] ReadAssemblyCustomAttributes(uint rid) => ReadCustomAttributesCore(0x20000000 + rid);
protected override DmdCustomAttributeData[] ReadModuleCustomAttributes(uint rid) => ReadCustomAttributesCore(0x00000000 + rid);
protected override DmdCustomAttributeData[] ReadTypeDefCustomAttributes(uint rid) => ReadCustomAttributesCore(0x02000000 + rid);
protected override DmdCustomAttributeData[] ReadFieldCustomAttributes(uint rid) => ReadCustomAttributesCore(0x04000000 + rid);
protected override DmdCustomAttributeData[] ReadMethodCustomAttributes(uint rid) => ReadCustomAttributesCore(0x06000000 + rid);
protected override DmdCustomAttributeData[] ReadParamCustomAttributes(uint rid) => ReadCustomAttributesCore(0x08000000 + rid);
protected override DmdCustomAttributeData[] ReadEventCustomAttributes(uint rid) => ReadCustomAttributesCore(0x14000000 + rid);
protected override DmdCustomAttributeData[] ReadPropertyCustomAttributes(uint rid) => ReadCustomAttributesCore(0x17000000 + rid);
DmdCustomAttributeData[] ReadCustomAttributesCore(uint token) {
if (IsCOMThread)
return ReadCustomAttributesCore_COMThread(token);
else
return COMThread(() => ReadCustomAttributesCore_COMThread(token));
}
internal DmdCustomAttributeData[] ReadCustomAttributesCore_COMThread(uint token) {
dispatcher.VerifyAccess();
var tokens = MDAPI.GetCustomAttributeTokens(MetaDataImport, token);
if (tokens.Length == 0)
return Array.Empty<DmdCustomAttributeData>();
var res = new DmdCustomAttributeData[tokens.Length];
int w = 0;
for (int i = 0; i < tokens.Length; i++) {
var info = MDAPI.GetCustomAttributeBlob(MetaDataImport, tokens[i]);
if (info.addr == IntPtr.Zero)
continue;
var ctor = ResolveMethod(info.typeToken, null, null, DmdResolveOptions.None) as DmdConstructorInfo;
if (ctor is null)
continue;
var ca = DmdCustomAttributeReader.Read(module, new DmdPointerDataStream(info.addr, info.size), ctor);
if (ca is null)
continue;
res[w++] = ca;
}
if (res.Length != w)
Array.Resize(ref res, w);
return res;
}
protected override DmdCustomAttributeData[] ReadAssemblySecurityAttributes(uint rid) => ReadSecurityAttributesCore(0x20000000 + rid);
protected override DmdCustomAttributeData[] ReadTypeDefSecurityAttributes(uint rid) => ReadSecurityAttributesCore(0x02000000 + rid);
protected override DmdCustomAttributeData[] ReadMethodSecurityAttributes(uint rid) => ReadSecurityAttributesCore(0x06000000 + rid);
DmdCustomAttributeData[] ReadSecurityAttributesCore(uint token) {
if (IsCOMThread)
return ReadSecurityAttributesCore_COMThread(token);
else
return COMThread(() => ReadSecurityAttributesCore_COMThread(token));
}
#pragma warning disable SYSLIB0003 // SecurityAction
internal DmdCustomAttributeData[] ReadSecurityAttributesCore_COMThread(uint token) {
dispatcher.VerifyAccess();
var tokens = MDAPI.GetPermissionSetTokens(MetaDataImport, token);
if (tokens.Length == 0)
return Array.Empty<DmdCustomAttributeData>();
IList<DmdType>? genericTypeArguments = null;
DmdCustomAttributeData[]? firstCas = null;
SSP.SecurityAction firstAction = 0;
List<(DmdCustomAttributeData[] cas, SSP.SecurityAction action)>? res = null;
for (int i = 0; i < tokens.Length; i++) {
if (!MDAPI.IsValidToken(MetaDataImport, tokens[i]))
continue;
var info = MDAPI.GetPermissionSetBlob(MetaDataImport, tokens[i]);
if (info.addr == IntPtr.Zero)
continue;
var action = (SSP.SecurityAction)(info.action & 0x1F);
var cas = DmdDeclSecurityReader.Read(module, new DmdPointerDataStream(info.addr, (int)info.size), action, genericTypeArguments);
if (cas.Length == 0)
continue;
if (res is null && firstCas is null) {
firstAction = action;
firstCas = cas;
}
else {
if (res is null) {
res = new List<(DmdCustomAttributeData[], SSP.SecurityAction)>(firstCas!.Length + cas.Length);
res.Add((firstCas, firstAction));
firstCas = null;
}
res.Add((cas, action));
}
}
if (firstCas is not null)
return firstCas;
if (res is null)
return Array.Empty<DmdCustomAttributeData>();
// Reflection sorts it by action
res.Sort((a, b) => (int)a.action - (int)b.action);
int count = 0;
for (int i = 0; i < res.Count; i++)
count += res[i].cas.Length;
var sas = new DmdCustomAttributeData[count];
int w = 0;
for (int i = 0; i < res.Count; i++) {
foreach (var ca in res[i].cas)
sas[w++] = ca;
}
if (sas.Length != w)
throw new InvalidOperationException();
return sas;
}
#pragma warning restore SYSLIB0003 // SecurityAction
internal DmdMarshalType? ReadFieldMarshalType_COMThread(int metadataToken, DmdModule module, IList<DmdType>? genericTypeArguments) {
dispatcher.VerifyAccess();
var signature = MDAPI.GetFieldMarshalBlob(MetaDataImport, (uint)metadataToken);
if (signature.addr == IntPtr.Zero)
return null;
return DmdMarshalBlobReader.Read(module, new DmdPointerDataStream(signature), genericTypeArguments);
}
internal (object? value, bool hasValue) ReadFieldConstant_COMThread(int metadataToken) {
dispatcher.VerifyAccess();
var c = MDAPI.GetFieldConstant(MetaDataImport, (uint)metadataToken, out var etype);
if (etype == ElementType.End)
return (null, false);
return (c, true);
}
internal (object? value, bool hasValue) ReadParamConstant_COMThread(int metadataToken) {
dispatcher.VerifyAccess();
var c = MDAPI.GetParamConstant(MetaDataImport, (uint)metadataToken, out var etype);
if (etype == ElementType.End)
return (null, false);
return (c, true);
}
internal (object? value, bool hasValue) ReadPropertyConstant_COMThread(int metadataToken) {
dispatcher.VerifyAccess();
var c = MDAPI.GetPropertyConstant(MetaDataImport, (uint)metadataToken, out var etype);
if (etype == ElementType.End)
return (null, false);
return (c, true);
}
}
}