private bool?CanAccess(MethodDef md, GenericInstSig git) { if (md == null) { return(null); } var access = GetTypeAccess(md.DeclaringType, git); if (access == null) { return(null); } var acc = access.Value; if ((acc & CheckTypeAccess.Normal) == 0) { return(false); } if ((acc & CheckTypeAccess.FullMemberAccess) != 0) { return(true); } return(IsVisible(md, git)); }
private bool?CanAccess(TypeDef td, GenericInstSig git, MemberRef mr) { if (mr == null || td == null) { return(null); } if (mr.MethodSig != null) { var md = td.FindMethodCheckBaseType(mr.Name, mr.MethodSig); if (md == null) { // Assume that it's an array type if it's one of these methods if (mr.Name == "Get" || mr.Name == "Set" || mr.Name == "Address" || mr.Name == MethodDef.InstanceConstructorName) { return(true); } return(null); } return(CanAccess(md, git)); } if (mr.FieldSig != null) { return(CanAccess(td.FindFieldCheckBaseType(mr.Name, mr.FieldSig), git)); } return(null); }
/// <summary> /// Checks whether <see cref="userType" /> has access to <paramref name="td" />. /// <paramref name="td" /> is Family, FamANDAssem, or FamORAssem. /// </summary> /// <param name="td">Type</param> /// <param name="git">Generic instance of <paramref name="td" /> or <c>null</c> if none</param> private bool CheckFamily(TypeDef td, GenericInstSig git) { if (td == null) { return(false); } InitializeBaseTypes(); if (baseTypes.ContainsKey(git == null ? (IType)td : git)) { return(true); } // td is Family, FamANDAssem, or FamORAssem. If we derive from its enclosing type, // we have access to it. var td2 = td.DeclaringType; if (td2 != null && baseTypes.ContainsKey(td2)) { return(true); } // If one of our enclosing types derive from it, we also have access to it var userDeclType = userType.DeclaringType; if (userDeclType != null) { return(new AccessChecker(userDeclType).CheckFamily(td, git)); } return(false); }
internal TypeSig CreateTypeSig(IList <TSpec> tspecs, TypeSig currentSig) { foreach (var tspec in tspecs) { switch (tspec.etype) { case ElementType.SZArray: currentSig = new SZArraySig(currentSig); break; case ElementType.Array: var arraySpec = (ArraySpec)tspec; currentSig = new ArraySig(currentSig, arraySpec.rank, arraySpec.sizes, arraySpec.lowerBounds); break; case ElementType.GenericInst: var ginstSpec = (GenericInstSpec)tspec; currentSig = new GenericInstSig(currentSig as ClassOrValueTypeSig, ginstSpec.args); break; case ElementType.ByRef: currentSig = new ByRefSig(currentSig); break; case ElementType.Ptr: currentSig = new PtrSig(currentSig); break; default: Verify(false, "Unknown TSpec"); break; } } return(currentSig); }
CheckTypeAccess GetTypeAccess2(TypeDef td, GenericInstSig git) { while (td != null) { if (userType != td.DeclaringType && !IsVisible(td, git)) { return(CheckTypeAccess.None); } td = td.DeclaringType; git = null; } return(CheckTypeAccess.Normal); }
public static IMethod Create(IMethod method, GenericInstSig git) { if (git == null) return method; var mdr = method as IMethodDefOrRef; if (mdr != null) return Create(mdr, git); var ms = method as MethodSpec; if (ms != null) return Create(ms, git); return method; }
private bool IsVisible(MethodDef md, GenericInstSig git) { if (md == null) { return(false); } var mdDeclaringType = md.DeclaringType; if (mdDeclaringType == null) { return(false); } if (userType == mdDeclaringType) { return(true); } switch (md.Access) { case MethodAttributes.PrivateScope: // Private scope aka compiler controlled fields/methods can only be accessed // by a Field/Method token. This means they must be in the same module. return(userType.Module == mdDeclaringType.Module); case MethodAttributes.Private: return(false); case MethodAttributes.FamANDAssem: return(IsSameAssemblyOrFriendAssembly(mdDeclaringType.Module) && CheckFamily(mdDeclaringType, git)); case MethodAttributes.Assembly: return(IsSameAssemblyOrFriendAssembly(mdDeclaringType.Module)); case MethodAttributes.Family: return(CheckFamily(mdDeclaringType, git)); case MethodAttributes.FamORAssem: return(IsSameAssemblyOrFriendAssembly(mdDeclaringType.Module) || CheckFamily(mdDeclaringType, git)); case MethodAttributes.Public: return(true); default: return(false); } }
/// <summary> /// Checks whether <paramref name="td" /> is visible to us without checking whether they /// have any common enclosing types. /// </summary> /// <param name="td">Type</param> /// <param name="git">Generic instance of <paramref name="td" /> or <c>null</c> if none</param> private bool IsVisible(TypeDef td, GenericInstSig git) { if (td == null) { return(false); } if (td == userType) { return(true); } switch (td.Visibility) { case TypeAttributes.NotPublic: return(IsSameAssemblyOrFriendAssembly(td.Module)); case TypeAttributes.Public: return(true); case TypeAttributes.NestedPublic: return(true); case TypeAttributes.NestedPrivate: return(false); case TypeAttributes.NestedFamily: return(CheckFamily(td, git)); case TypeAttributes.NestedAssembly: return(IsSameAssemblyOrFriendAssembly(td.Module)); case TypeAttributes.NestedFamANDAssem: return(IsSameAssemblyOrFriendAssembly(td.Module) && CheckFamily(td, git)); case TypeAttributes.NestedFamORAssem: return(IsSameAssemblyOrFriendAssembly(td.Module) || CheckFamily(td, git)); default: return(false); } }
bool? CanAccess(MethodDef md, GenericInstSig git) { if (md == null) return null; var access = GetTypeAccess(md.DeclaringType, git); if (access == null) return null; var acc = access.Value; if ((acc & CheckTypeAccess.Normal) == 0) return false; if ((acc & CheckTypeAccess.FullMemberAccess) != 0) return true; return IsVisible(md, git); }
/// <summary> /// Checks whether <paramref name="td"/> is visible to us without checking whether they /// have any common enclosing types. /// </summary> /// <param name="td">Type</param> /// <param name="git">Generic instance of <paramref name="td"/> or <c>null</c> if none</param> bool IsVisible(TypeDef td, GenericInstSig git) { if (td == null) return false; if (td == userType) return true; switch (td.Visibility) { case TypeAttributes.NotPublic: return IsSameAssemblyOrFriendAssembly(td.Module); case TypeAttributes.Public: return true; case TypeAttributes.NestedPublic: return true; case TypeAttributes.NestedPrivate: return false; case TypeAttributes.NestedFamily: return CheckFamily(td, git); case TypeAttributes.NestedAssembly: return IsSameAssemblyOrFriendAssembly(td.Module); case TypeAttributes.NestedFamANDAssem: return IsSameAssemblyOrFriendAssembly(td.Module) && CheckFamily(td, git); case TypeAttributes.NestedFamORAssem: return IsSameAssemblyOrFriendAssembly(td.Module) || CheckFamily(td, git); default: return false; } }
/// <summary> /// Returns the access we have to <paramref name="td"/>. If <paramref name="td"/> is /// enclosing this type, we have private access to it and all its members. If its /// declaring type encloses us, we have private access to it, but only normal access /// to its members. Else, we only have normal access to it and its members. If we inherit /// it, we have protected access to it and its members. /// </summary> /// <param name="td">The type</param> /// <param name="git">Generic instance of <paramref name="td"/> or <c>null</c> if none</param> CheckTypeAccess? GetTypeAccess(TypeDef td, GenericInstSig git) { if (td == null) return null; if (userType == td) return CheckTypeAccess.Full; // If this is our nested type, we have private access to it itself, but normal // access to its members. if (td.DeclaringType == userType) return CheckTypeAccess.Normal | CheckTypeAccess.FullTypeAccess; // If we're not a nested type, td can't be our enclosing type if (userType.DeclaringType == null) return GetTypeAccess2(td, git); // Can't be an enclosing type if they're not in the same module if (userType.Module != td.Module) return GetTypeAccess2(td, git); var tdEncTypes = GetEnclosingTypes(td, true); var ourEncTypes = InitializeOurEnclosingTypes(); int maxChecks = Math.Min(tdEncTypes.Count, ourEncTypes.Count); int commonIndex; for (commonIndex = 0; commonIndex < maxChecks; commonIndex++) { if (tdEncTypes[commonIndex] != ourEncTypes[commonIndex]) break; } // If td encloses us, then we have access to td and all its members even if // they're private. if (commonIndex == tdEncTypes.Count) return CheckTypeAccess.Full; // If there are no common enclosing types, only check the visibility. if (commonIndex == 0) return GetTypeAccess2(td, git); // If td's declaring type encloses this, then we have full access to td even if // it's private, but only normal access to its members. if (commonIndex + 1 == tdEncTypes.Count) return CheckTypeAccess.Normal | CheckTypeAccess.FullTypeAccess; // Normal visibility checks starting from type after common enclosing type. // Note that we have full access to it so we don't need to check its access, // so start from the next one. for (int i = commonIndex + 1; i < tdEncTypes.Count; i++) { if (!IsVisible(tdEncTypes[i], null)) return CheckTypeAccess.None; } return CheckTypeAccess.Normal; }
TypeSig ResolveGenericArgs(TypeSig typeSig) { if (!recursionCounter.Increment()) { return(null); } if (ReplaceGenericArg(ref typeSig)) { recursionCounter.Decrement(); return(typeSig); } TypeSig result; switch (typeSig.ElementType) { case ElementType.Ptr: result = new PtrSig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.ByRef: result = new ByRefSig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.Var: result = new GenericVar((typeSig as GenericVar).Number); break; case ElementType.ValueArray: result = new ValueArraySig(ResolveGenericArgs(typeSig.Next), (typeSig as ValueArraySig).Size); break; case ElementType.SZArray: result = new SZArraySig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.MVar: result = new GenericMVar((typeSig as GenericMVar).Number); break; case ElementType.CModReqd: result = new CModReqdSig((typeSig as ModifierSig).Modifier, ResolveGenericArgs(typeSig.Next)); break; case ElementType.CModOpt: result = new CModOptSig((typeSig as ModifierSig).Modifier, ResolveGenericArgs(typeSig.Next)); break; case ElementType.Module: result = new ModuleSig((typeSig as ModuleSig).Index, ResolveGenericArgs(typeSig.Next)); break; case ElementType.Pinned: result = new PinnedSig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.FnPtr: throw new NotSupportedException("FnPtr is not supported."); case ElementType.Array: ArraySig arraySig = (ArraySig)typeSig; List <uint> sizes = new List <uint>(arraySig.Sizes); List <int> lbounds = new List <int>(arraySig.LowerBounds); result = new ArraySig(ResolveGenericArgs(typeSig.Next), arraySig.Rank, sizes, lbounds); break; case ElementType.GenericInst: GenericInstSig gis = (GenericInstSig)typeSig; List <TypeSig> genArgs = new List <TypeSig>(gis.GenericArguments.Count); foreach (TypeSig ga in gis.GenericArguments) { genArgs.Add(ResolveGenericArgs(ga)); } result = new GenericInstSig(ResolveGenericArgs((TypeSig)gis.GenericType) as ClassOrValueTypeSig, genArgs); break; default: result = typeSig; break; } recursionCounter.Decrement(); return(result); }
private TypeSig ResolveGenericArgs(TypeSig typeSig) { if (!recursionCounter.Increment()) return null; if (ReplaceGenericArg(ref typeSig)) { recursionCounter.Decrement(); return typeSig; } TypeSig result; switch (typeSig.ElementType) { case ElementType.Ptr: result = new PtrSig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.ByRef: result = new ByRefSig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.Var: result = new GenericVar((typeSig as GenericVar).Number); break; case ElementType.ValueArray: result = new ValueArraySig(ResolveGenericArgs(typeSig.Next), (typeSig as ValueArraySig).Size); break; case ElementType.SZArray: result = new SZArraySig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.MVar: result = new GenericMVar((typeSig as GenericMVar).Number); break; case ElementType.CModReqd: result = new CModReqdSig((typeSig as ModifierSig).Modifier, ResolveGenericArgs(typeSig.Next)); break; case ElementType.CModOpt: result = new CModOptSig((typeSig as ModifierSig).Modifier, ResolveGenericArgs(typeSig.Next)); break; case ElementType.Module: result = new ModuleSig((typeSig as ModuleSig).Index, ResolveGenericArgs(typeSig.Next)); break; case ElementType.Pinned: result = new PinnedSig(ResolveGenericArgs(typeSig.Next)); break; case ElementType.FnPtr: throw new NotSupportedException("FnPtr is not supported."); case ElementType.Array: var arraySig = (ArraySig)typeSig; var sizes = new List<uint>(arraySig.Sizes); var lbounds = new List<int>(arraySig.LowerBounds); result = new ArraySig(ResolveGenericArgs(typeSig.Next), arraySig.Rank, sizes, lbounds); break; case ElementType.GenericInst: var gis = (GenericInstSig)typeSig; var genArgs = new List<TypeSig>(gis.GenericArguments.Count); foreach (TypeSig ga in gis.GenericArguments) { genArgs.Add(ResolveGenericArgs(ga)); } result = new GenericInstSig(ResolveGenericArgs(gis.GenericType) as ClassOrValueTypeSig, genArgs); break; default: result = typeSig; break; } recursionCounter.Decrement(); return result; }
TypeSig CreateNullableType(TypeSig type) { if (type == null) return null; var t = new GenericInstSig((ClassOrValueTypeSig)typeSystem.GetTypeRef("System", "Nullable`1").ToTypeSig()); t.GenericArguments.Add(type); return t; }
GenericInstSig ReadGenericInstanceType(out List<int> genericArgs) { var git = new GenericInstSig(ReadTypeSig() as ClassOrValueTypeSig); int numArgs = ReadVariableLengthInt32(); genericArgs = new List<int>(numArgs); for (int i = 0; i < numArgs; i++) genericArgs.Add(ReadVariableLengthInt32()); return git; }
public static IMethodDefOrRef Create(IMethodDefOrRef method, GenericInstSig git, IList<TypeSig> genericMethodArgs) { return Create(method, git == null ? null : git.GenericArguments, genericMethodArgs); }
public static IMethodDefOrRef Create(IMethodDefOrRef method, GenericInstSig git) { if (git == null) return method; return Create(method, git.GenericArguments); }
public static MethodSpec Create(MethodSpec method, GenericInstSig git) { if (method == null || git == null) return method; var newMethod = Create(method.Method, git); var newInst = Create(method.GenericInstMethodSig, git); bool updated = newMethod != method.Method || newInst != method.GenericInstMethodSig; return updated ? new MethodSpecUser(newMethod, newInst) : method; }
public void InitializeFrom(MethodInstances other, GenericInstSig git) { foreach (var list in other.methodInstances.Values) { foreach (var methodInst in list) { var newMethod = GenericArgsSubstitutor.Create(methodInst.methodRef, git); Add(new MethodInst(methodInst.origMethodDef, newMethod)); } } }
public TypeInfo(TypeInfo other, GenericInstSig git) { this.typeRef = GenericArgsSubstitutor.Create(other.typeRef, git); this.typeDef = other.typeDef; }
public void InitializeFrom(InterfaceMethodInfos other, GenericInstSig git) { foreach (var pair in other.interfaceMethods) { var oldTypeInfo = pair.Value.IFace; var newTypeInfo = new TypeInfo(oldTypeInfo, git); var oldKey = oldTypeInfo.typeRef; var newKey = newTypeInfo.typeRef; InterfaceMethodInfo newMethodsInfo = new InterfaceMethodInfo(newTypeInfo, other.interfaceMethods[oldKey]); if (interfaceMethods.ContainsKey(newKey)) newMethodsInfo.Merge(interfaceMethods[newKey]); interfaceMethods[newKey] = newMethodsInfo; } }
/// <summary> /// Returns the access we have to <paramref name="td" />. If <paramref name="td" /> is /// enclosing this type, we have private access to it and all its members. If its /// declaring type encloses us, we have private access to it, but only normal access /// to its members. Else, we only have normal access to it and its members. If we inherit /// it, we have protected access to it and its members. /// </summary> /// <param name="td">The type</param> /// <param name="git">Generic instance of <paramref name="td" /> or <c>null</c> if none</param> private CheckTypeAccess?GetTypeAccess(TypeDef td, GenericInstSig git) { if (td == null) { return(null); } if (userType == td) { return(CheckTypeAccess.Full); } // If this is our nested type, we have private access to it itself, but normal // access to its members. if (td.DeclaringType == userType) { return(CheckTypeAccess.Normal | CheckTypeAccess.FullTypeAccess); } // If we're not a nested type, td can't be our enclosing type if (userType.DeclaringType == null) { return(GetTypeAccess2(td, git)); } // Can't be an enclosing type if they're not in the same module if (userType.Module != td.Module) { return(GetTypeAccess2(td, git)); } var tdEncTypes = GetEnclosingTypes(td, true); var ourEncTypes = InitializeOurEnclosingTypes(); var maxChecks = Math.Min(tdEncTypes.Count, ourEncTypes.Count); int commonIndex; for (commonIndex = 0; commonIndex < maxChecks; commonIndex++) { if (tdEncTypes[commonIndex] != ourEncTypes[commonIndex]) { break; } } // If td encloses us, then we have access to td and all its members even if // they're private. if (commonIndex == tdEncTypes.Count) { return(CheckTypeAccess.Full); } // If there are no common enclosing types, only check the visibility. if (commonIndex == 0) { return(GetTypeAccess2(td, git)); } // If td's declaring type encloses this, then we have full access to td even if // it's private, but only normal access to its members. if (commonIndex + 1 == tdEncTypes.Count) { return(CheckTypeAccess.Normal | CheckTypeAccess.FullTypeAccess); } // Normal visibility checks starting from type after common enclosing type. // Note that we have full access to it so we don't need to check its access, // so start from the next one. for (var i = commonIndex + 1; i < tdEncTypes.Count; i++) { if (!IsVisible(tdEncTypes[i], null)) { return(CheckTypeAccess.None); } } return(CheckTypeAccess.Normal); }
/// <summary> /// Imports a <see cref="TypeSig"/> /// </summary> /// <param name="type">The type</param> /// <returns>The imported type or <c>null</c></returns> public TypeSig Import(TypeSig type) { if (type == null) { return(null); } if (!recursionCounter.Increment()) { return(null); } TypeSig result; switch (type.ElementType) { case ElementType.Void: result = module.CorLibTypes.Void; break; case ElementType.Boolean: result = module.CorLibTypes.Boolean; break; case ElementType.Char: result = module.CorLibTypes.Char; break; case ElementType.I1: result = module.CorLibTypes.SByte; break; case ElementType.U1: result = module.CorLibTypes.Byte; break; case ElementType.I2: result = module.CorLibTypes.Int16; break; case ElementType.U2: result = module.CorLibTypes.UInt16; break; case ElementType.I4: result = module.CorLibTypes.Int32; break; case ElementType.U4: result = module.CorLibTypes.UInt32; break; case ElementType.I8: result = module.CorLibTypes.Int64; break; case ElementType.U8: result = module.CorLibTypes.UInt64; break; case ElementType.R4: result = module.CorLibTypes.Single; break; case ElementType.R8: result = module.CorLibTypes.Double; break; case ElementType.String: result = module.CorLibTypes.String; break; case ElementType.TypedByRef: result = module.CorLibTypes.TypedReference; break; case ElementType.I: result = module.CorLibTypes.IntPtr; break; case ElementType.U: result = module.CorLibTypes.UIntPtr; break; case ElementType.Object: result = module.CorLibTypes.Object; break; case ElementType.Ptr: result = new PtrSig(Import(type.Next)); break; case ElementType.ByRef: result = new ByRefSig(Import(type.Next)); break; case ElementType.ValueType: result = CreateClassOrValueType((type as ClassOrValueTypeSig).TypeDefOrRef, true); break; case ElementType.Class: result = CreateClassOrValueType((type as ClassOrValueTypeSig).TypeDefOrRef, false); break; case ElementType.Var: result = new GenericVar((type as GenericVar).Number); break; case ElementType.ValueArray: result = new ValueArraySig(Import(type.Next), (type as ValueArraySig).Size); break; case ElementType.FnPtr: result = new FnPtrSig(Import((type as FnPtrSig).Signature)); break; case ElementType.SZArray: result = new SZArraySig(Import(type.Next)); break; case ElementType.MVar: result = new GenericMVar((type as GenericMVar).Number); break; case ElementType.CModReqd: result = new CModReqdSig(Import((type as ModifierSig).Modifier), Import(type.Next)); break; case ElementType.CModOpt: result = new CModOptSig(Import((type as ModifierSig).Modifier), Import(type.Next)); break; case ElementType.Module: result = new ModuleSig((type as ModuleSig).Index, Import(type.Next)); break; case ElementType.Sentinel: result = new SentinelSig(); break; case ElementType.Pinned: result = new PinnedSig(Import(type.Next)); break; case ElementType.Array: var arraySig = (ArraySig)type; var sizes = new List <uint>(arraySig.Sizes); var lbounds = new List <int>(arraySig.LowerBounds); result = new ArraySig(Import(type.Next), arraySig.Rank, sizes, lbounds); break; case ElementType.GenericInst: var gis = (GenericInstSig)type; var genArgs = new List <TypeSig>(gis.GenericArguments.Count); foreach (var ga in gis.GenericArguments) { genArgs.Add(Import(ga)); } result = new GenericInstSig(Import(gis.GenericType) as ClassOrValueTypeSig, genArgs); break; case ElementType.End: case ElementType.R: case ElementType.Internal: default: result = null; break; } recursionCounter.Decrement(); return(result); }
TypeSig Create2(TypeSig type) { if (type == null) return type; TypeSig result; GenericSig varSig; switch (type.ElementType) { case ElementType.Void: case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: case ElementType.I8: case ElementType.U8: case ElementType.R4: case ElementType.R8: case ElementType.String: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.Object: result = type; break; case ElementType.Ptr: result = new PtrSig(Create2(type.Next)); break; case ElementType.ByRef: result = new ByRefSig(Create2(type.Next)); break; case ElementType.Array: var ary = (ArraySig)type; result = new ArraySig(ary.Next, ary.Rank, ary.Sizes, ary.LowerBounds); break; case ElementType.SZArray: result = new SZArraySig(Create2(type.Next)); break; case ElementType.Pinned: result = new PinnedSig(Create2(type.Next)); break; case ElementType.ValueType: case ElementType.Class: result = type; break; case ElementType.Var: varSig = (GenericSig)type; if (genericArgs != null && varSig.Number < (uint)genericArgs.Count) { result = genericArgs[(int)varSig.Number]; updated = true; } else result = type; break; case ElementType.MVar: varSig = (GenericSig)type; if (genericMethodArgs != null && varSig.Number < (uint)genericMethodArgs.Count) { result = genericMethodArgs[(int)varSig.Number]; updated = true; } else result = type; break; case ElementType.GenericInst: var gis = (GenericInstSig)type; var newGis = new GenericInstSig(Create2(gis.GenericType) as ClassOrValueTypeSig, gis.GenericArguments.Count); for (int i = 0; i < gis.GenericArguments.Count; i++) newGis.GenericArguments.Add(Create2(gis.GenericArguments[i])); result = newGis; break; case ElementType.ValueArray: result = new ValueArraySig(type.Next, ((ValueArraySig)type).Size); break; case ElementType.Module: result = new ModuleSig(((ModuleSig)type).Index, type.Next); break; case ElementType.CModReqd: result = new CModReqdSig(((ModifierSig)type).Modifier, type.Next); break; case ElementType.CModOpt: result = new CModOptSig(((ModifierSig)type).Modifier, type.Next); break; case ElementType.FnPtr: result = new FnPtrSig(Create(((FnPtrSig)type).MethodSig)); break; case ElementType.End: case ElementType.R: case ElementType.Sentinel: case ElementType.Internal: default: result = type; break; } return result; }
TypeSpec ApplyGenerics(ITypeDefOrRef type, IList<TypeSig> generics) { ClassOrValueTypeSig typeSig = type.ToTypeSig().ToClassOrValueTypeSig(); GenericInstSig genericSig = new GenericInstSig(typeSig, generics); return new TypeSpecUser(genericSig); }
public static ITypeDefOrRef Create(ITypeDefOrRef type, GenericInstSig git) { if (git == null) return type; return Create(type, git.GenericArguments); }
/// <summary> /// Reads the next type /// </summary> /// <returns>A new <see cref="TypeSig"/> instance or <c>null</c> if invalid element type</returns> TypeSig ReadType() { if (!recursionCounter.Increment()) { return(null); } uint num; TypeSig nextType, result = null; switch ((ElementType)reader.ReadByte()) { case ElementType.Void: result = corLibTypes.Void; break; case ElementType.Boolean: result = corLibTypes.Boolean; break; case ElementType.Char: result = corLibTypes.Char; break; case ElementType.I1: result = corLibTypes.SByte; break; case ElementType.U1: result = corLibTypes.Byte; break; case ElementType.I2: result = corLibTypes.Int16; break; case ElementType.U2: result = corLibTypes.UInt16; break; case ElementType.I4: result = corLibTypes.Int32; break; case ElementType.U4: result = corLibTypes.UInt32; break; case ElementType.I8: result = corLibTypes.Int64; break; case ElementType.U8: result = corLibTypes.UInt64; break; case ElementType.R4: result = corLibTypes.Single; break; case ElementType.R8: result = corLibTypes.Double; break; case ElementType.String: result = corLibTypes.String; break; case ElementType.TypedByRef: result = corLibTypes.TypedReference; break; case ElementType.I: result = corLibTypes.IntPtr; break; case ElementType.U: result = corLibTypes.UIntPtr; break; case ElementType.Object: result = corLibTypes.Object; break; case ElementType.Ptr: result = new PtrSig(ReadType()); break; case ElementType.ByRef: result = new ByRefSig(ReadType()); break; case ElementType.ValueType: result = new ValueTypeSig(ReadTypeDefOrRef()); break; case ElementType.Class: result = new ClassSig(ReadTypeDefOrRef()); break; case ElementType.FnPtr: result = new FnPtrSig(ReadSig()); break; case ElementType.SZArray: result = new SZArraySig(ReadType()); break; case ElementType.CModReqd: result = new CModReqdSig(ReadTypeDefOrRef(), ReadType()); break; case ElementType.CModOpt: result = new CModOptSig(ReadTypeDefOrRef(), ReadType()); break; case ElementType.Sentinel: result = new SentinelSig(); break; case ElementType.Pinned: result = new PinnedSig(ReadType()); break; case ElementType.Var: if (!reader.ReadCompressedUInt32(out num)) { break; } result = new GenericVar(num, gpContext.Type); break; case ElementType.MVar: if (!reader.ReadCompressedUInt32(out num)) { break; } result = new GenericMVar(num, gpContext.Method); break; case ElementType.ValueArray: nextType = ReadType(); if (!reader.ReadCompressedUInt32(out num)) { break; } result = new ValueArraySig(nextType, num); break; case ElementType.Module: if (!reader.ReadCompressedUInt32(out num)) { break; } result = new ModuleSig(num, ReadType()); break; case ElementType.GenericInst: nextType = ReadType(); if (!reader.ReadCompressedUInt32(out num)) { break; } var genericInstSig = new GenericInstSig(nextType as ClassOrValueTypeSig, num); var args = genericInstSig.GenericArguments; for (uint i = 0; i < num; i++) { args.Add(ReadType()); } result = genericInstSig; break; case ElementType.Array: nextType = ReadType(); uint rank; if (!reader.ReadCompressedUInt32(out rank)) { break; } if (rank == 0) { result = new ArraySig(nextType, rank); break; } if (!reader.ReadCompressedUInt32(out num)) { break; } var sizes = new List <uint>((int)num); for (uint i = 0; i < num; i++) { uint size; if (!reader.ReadCompressedUInt32(out size)) { goto exit; } sizes.Add(size); } if (!reader.ReadCompressedUInt32(out num)) { break; } var lowerBounds = new List <int>((int)num); for (uint i = 0; i < num; i++) { int size; if (!reader.ReadCompressedInt32(out size)) { goto exit; } lowerBounds.Add(size); } result = new ArraySig(nextType, rank, sizes, lowerBounds); break; case ElementType.Internal: IntPtr address; if (IntPtr.Size == 4) { address = new IntPtr(reader.ReadInt32()); } else { address = new IntPtr(reader.ReadInt64()); } result = helper.ConvertRTInternalAddress(address); break; case ElementType.End: case ElementType.R: default: result = null; break; } exit: recursionCounter.Decrement(); return(result); }
public static IField Create(IField field, GenericInstSig git) { if (git == null) return field; return Create(field, git.GenericArguments); }
internal TypeSig CreateTypeSig(IList<TSpec> tspecs, TypeSig currentSig) { foreach (var tspec in tspecs) { switch (tspec.etype) { case ElementType.SZArray: currentSig = new SZArraySig(currentSig); break; case ElementType.Array: var arraySpec = (ArraySpec)tspec; currentSig = new ArraySig(currentSig, arraySpec.rank, arraySpec.sizes, arraySpec.lowerBounds); break; case ElementType.GenericInst: var ginstSpec = (GenericInstSpec)tspec; currentSig = new GenericInstSig(currentSig as ClassOrValueTypeSig, ginstSpec.args); break; case ElementType.ByRef: currentSig = new ByRefSig(currentSig); break; case ElementType.Ptr: currentSig = new PtrSig(currentSig); break; default: Verify(false, "Unknown TSpec"); break; } } return currentSig; }
public static FieldSig Create(FieldSig sig, GenericInstSig git) { if (git == null) return sig; return Create(sig, git.GenericArguments); }
void FindEncryptedResourceReader() { var type = GetTypeFromCode(encryptedResourceSet_GetDefaultReader); if (type == null) return; if (type.BaseType == null || !HasInterface(type, "System.Resources.IResourceReader")) return; if (!new FieldTypes(type).All(encryptedResourceReaderType_fields)) return; var dictType = GetDlxResDict(type); if (dictType == null) return; if (FindXxteaMethod(type) == null) return; encryptedResourceReaderType = type; encryptedResourceReaderTypeDict = dictType; }
bool? CanAccess(TypeDef td, GenericInstSig git, MemberRef mr) { if (mr == null || td == null) return null; if (mr.MethodSig != null) { var md = td.FindMethodCheckBaseType(mr.Name, mr.MethodSig); if (md == null) { // Assume that it's an array type if it's one of these methods if (mr.Name == "Get" || mr.Name == "Set" || mr.Name == "Address" || mr.Name == ".ctor") return true; return null; } return CanAccess(md, git); } if (mr.FieldSig != null) return CanAccess(td.FindFieldCheckBaseType(mr.Name, mr.FieldSig), git); return null; }
CheckTypeAccess GetTypeAccess2(TypeDef td, GenericInstSig git) { while (td != null) { if (userType != td.DeclaringType && !IsVisible(td, git)) return CheckTypeAccess.None; td = td.DeclaringType; git = null; } return CheckTypeAccess.Normal; }
public static IList<TypeSig> ReplaceGenericParameters(GenericInstSig typeOwner, MethodSpec methodOwner, IList<TypeSig> types) { if (typeOwner == null && methodOwner == null) return types; for (int i = 0; i < types.Count; i++) types[i] = GetGenericArgument(typeOwner, methodOwner, types[i]); return types; }
/// <summary> /// Checks whether <see cref="userType"/> has access to <paramref name="td"/>. /// <paramref name="td"/> is Family, FamANDAssem, or FamORAssem. /// </summary> /// <param name="td">Type</param> /// <param name="git">Generic instance of <paramref name="td"/> or <c>null</c> if none</param> bool CheckFamily(TypeDef td, GenericInstSig git) { if (td == null) return false; InitializeBaseTypes(); if (baseTypes.ContainsKey(git == null ? (IType)td : git)) return true; // td is Family, FamANDAssem, or FamORAssem. If we derive from its enclosing type, // we have access to it. var td2 = td.DeclaringType; if (td2 != null && baseTypes.ContainsKey(td2)) return true; // If one of our enclosing types derive from it, we also have access to it if (userType.DeclaringType != null) return new AccessChecker(userType.DeclaringType).CheckFamily(td, git); return false; }
void AddGenericInstSig() { var origType = GetTypeSig(dnSpy_AsmEditor_Resources.Pick_GenericType, VisibleMembersFlags.GenericTypeDef); if (origType == null) return; var type = origType as ClassOrValueTypeSig; if (type == null) { ShowWarning(null, dnSpy_AsmEditor_Resources.TypeMustBeGeneric); return; } var genericType = type.TypeDefOrRef.ResolveTypeDef(); if (genericType == null) { ShowWarning(null, dnSpy_AsmEditor_Resources.CouldNotResolveType); return; } if (genericType.GenericParameters.Count == 0) { ShowWarning(null, string.Format(dnSpy_AsmEditor_Resources.NotGenericType, genericType.FullName)); return; } var genArgs = createTypeSigArray.Create(options.Clone(dnSpy_AsmEditor_Resources.CreateGenericInstanceTypeArguments), genericType.GenericParameters.Count, null); if (genArgs == null) return; TypeSig = new GenericInstSig(type, genArgs); }
bool IsVisible(MethodDef md, GenericInstSig git) { if (md == null) return false; var mdDeclaringType = md.DeclaringType; if (mdDeclaringType == null) return false; if (userType == mdDeclaringType) return true; switch (md.Access) { case MethodAttributes.PrivateScope: // Private scope aka compiler controlled fields/methods can only be accessed // by a Field/Method token. This means they must be in the same module. return userType.Module == mdDeclaringType.Module; case MethodAttributes.Private: return false; case MethodAttributes.FamANDAssem: return IsSameAssemblyOrFriendAssembly(mdDeclaringType.Module) && CheckFamily(mdDeclaringType, git); case MethodAttributes.Assembly: return IsSameAssemblyOrFriendAssembly(mdDeclaringType.Module); case MethodAttributes.Family: return CheckFamily(mdDeclaringType, git); case MethodAttributes.FamORAssem: return IsSameAssemblyOrFriendAssembly(mdDeclaringType.Module) || CheckFamily(mdDeclaringType, git); case MethodAttributes.Public: return true; default: return false; } }
TypeSig ImportAsTypeSig(Type type, bool treatAsGenericInst) { if (type == null) { return(null); } switch (treatAsGenericInst ? ElementType.GenericInst : type.GetElementType2()) { case ElementType.Void: return(module.CorLibTypes.Void); case ElementType.Boolean: return(module.CorLibTypes.Boolean); case ElementType.Char: return(module.CorLibTypes.Char); case ElementType.I1: return(module.CorLibTypes.SByte); case ElementType.U1: return(module.CorLibTypes.Byte); case ElementType.I2: return(module.CorLibTypes.Int16); case ElementType.U2: return(module.CorLibTypes.UInt16); case ElementType.I4: return(module.CorLibTypes.Int32); case ElementType.U4: return(module.CorLibTypes.UInt32); case ElementType.I8: return(module.CorLibTypes.Int64); case ElementType.U8: return(module.CorLibTypes.UInt64); case ElementType.R4: return(module.CorLibTypes.Single); case ElementType.R8: return(module.CorLibTypes.Double); case ElementType.String: return(module.CorLibTypes.String); case ElementType.TypedByRef: return(module.CorLibTypes.TypedReference); case ElementType.U: return(module.CorLibTypes.UIntPtr); case ElementType.Object: return(module.CorLibTypes.Object); case ElementType.Ptr: return(new PtrSig(ImportAsTypeSig(type.GetElementType(), treatAsGenericInst))); case ElementType.ByRef: return(new ByRefSig(ImportAsTypeSig(type.GetElementType(), treatAsGenericInst))); case ElementType.SZArray: return(new SZArraySig(ImportAsTypeSig(type.GetElementType(), treatAsGenericInst))); case ElementType.ValueType: return(new ValueTypeSig(CreateTypeRef(type))); case ElementType.Class: return(new ClassSig(CreateTypeRef(type))); case ElementType.Var: return(new GenericVar((uint)type.GenericParameterPosition)); case ElementType.MVar: return(new GenericMVar((uint)type.GenericParameterPosition)); case ElementType.I: FixSignature = true; // FnPtr is mapped to System.IntPtr return(module.CorLibTypes.IntPtr); case ElementType.Array: FixSignature = true; // We don't know sizes and lower bounds return(new ArraySig(ImportAsTypeSig(type.GetElementType(), treatAsGenericInst), (uint)type.GetArrayRank())); case ElementType.GenericInst: var typeGenArgs = type.GetGenericArguments(); var git = new GenericInstSig(ImportAsTypeSig(type.GetGenericTypeDefinition()) as ClassOrValueTypeSig, (uint)typeGenArgs.Length); foreach (var ga in typeGenArgs) { git.GenericArguments.Add(ImportAsTypeSig(ga)); } return(git); case ElementType.Sentinel: case ElementType.Pinned: case ElementType.FnPtr: // mapped to System.IntPtr case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.ValueArray: case ElementType.R: case ElementType.Internal: case ElementType.Module: case ElementType.End: default: return(null); } }
private static VTable ResolveGenericArgument(TypeDef openType, GenericInstSig genInst, VTable vTable) { Debug.Assert(openType == vTable.Type); var ret = new VTable(openType); ret.GenericArguments = genInst.GenericArguments; foreach (VTableSlot slot in vTable.Slots) { MethodSig newSig = GenericArgumentResolver.Resolve(slot.Signature.MethodSig, genInst.GenericArguments); TypeSig newDecl = slot.DeclaringType; if (new SigComparer().Equals(newDecl, openType)) newDecl = new GenericInstSig((ClassOrValueTypeSig)openType.ToTypeSig(), genInst.GenericArguments.ToArray()); else newDecl = GenericArgumentResolver.Resolve(newDecl, genInst.GenericArguments); ret.Slots.Add(new VTableSlot(ret, slot.MethodDef, newDecl, new VTableSignature(genInst, newSig, slot.Signature.Name)).Override(slot)); } return ret; }
public static void Run() { // This is the file that will be created string newFileName = @"GenericExample1.exe"; // Create the module var mod = new ModuleDefUser("GenericExample1", Guid.NewGuid(), new AssemblyRefUser(new AssemblyNameInfo(typeof(int).Assembly.GetName().FullName))); // It's a console app mod.Kind = ModuleKind.Console; // Create the assembly and add the created module to it new AssemblyDefUser("GenericExample1", new Version(1, 2, 3, 4)).Modules.Add(mod); // Add the startup type. It derives from System.Object. TypeDef startUpType = new TypeDefUser("My.Namespace", "Startup", mod.CorLibTypes.Object.TypeDefOrRef); startUpType.Attributes = TypeAttributes.NotPublic | TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.AnsiClass; // Add the type to the module mod.Types.Add(startUpType); // Create the entry point method MethodDef entryPoint = new MethodDefUser("Main", MethodSig.CreateStatic(mod.CorLibTypes.Int32, new SZArraySig(mod.CorLibTypes.String))); entryPoint.Attributes = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.ReuseSlot; entryPoint.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed; // Name the 1st argument (argument 0 is the return type) entryPoint.ParamDefs.Add(new ParamDefUser("args", 1)); // Add the method to the startup type startUpType.Methods.Add(entryPoint); // Set module entry point mod.EntryPoint = entryPoint; // Create System.Console type reference var systemConsole = mod.CorLibTypes.GetTypeRef("System", "Console"); // Create 'void System.Console.WriteLine(string,object)' method reference var writeLine2 = new MemberRefUser(mod, "WriteLine", MethodSig.CreateStatic(mod.CorLibTypes.Void, mod.CorLibTypes.String, mod.CorLibTypes.Object), systemConsole); // // Method 1: Create List<String> inst signature by importing (easy way) // -------------------------------------------------------------------- //Importer importer = new Importer(mod); //var listGenericInstSig = importer.ImportAsTypeSig(typeof(System.Collections.Generic.List<String>)); // // Method 2: Create List<String> inst signature manually (harder way) // ------------------------------------------------------------------ var assemblyRef = mod.CorLibTypes.AssemblyRef; var listRef = new TypeRefUser(mod, @"System.Collections.Generic", "List`1", assemblyRef); // Create the GenericInstSig from a ClassSig with <String> generic arg var listGenericInstSig = new GenericInstSig(new ClassSig(listRef), mod.CorLibTypes.String); // Create TypeSpec from GenericInstSig var listTypeSpec = new TypeSpecUser(listGenericInstSig); // Create System.Collections.Generic.List<String>::.ctor method reference var listCtor = new MemberRefUser(mod, ".ctor", MethodSig.CreateInstance(mod.CorLibTypes.Void), listTypeSpec); // Create Add(!0) method reference, !0 signifying first generic argument of declaring type // In this case, would be Add(String item) // (GenericMVar would be used for method generic argument, such as Add<!!0>(!!0)) var listAdd = new MemberRefUser(mod, "Add", MethodSig.CreateInstance(mod.CorLibTypes.Void, new GenericVar(0)), listTypeSpec); var listGetCount = new MemberRefUser(mod, "get_Count", MethodSig.CreateInstance(mod.CorLibTypes.Int32), listTypeSpec); IList<Local> locals = new List<Local>(); locals.Add(new Local(listGenericInstSig)); // local[0]: class [mscorlib]System.Collections.Generic.List`1<string> var body = new CilBody(true, new List<Instruction>(), new List<ExceptionHandler>(), locals); // Call the list .ctor body.Instructions.Add(OpCodes.Newobj.ToInstruction(listCtor)); body.Instructions.Add(OpCodes.Stloc_0.ToInstruction()); // Store list to local[0] // list.Add("Item 1") body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction()); body.Instructions.Add(OpCodes.Ldstr.ToInstruction("Item 1")); body.Instructions.Add(OpCodes.Callvirt.ToInstruction(listAdd)); // WriteLine("Array: {0}", list.ToArray()); //body.Instructions.Add(OpCodes.Ldstr.ToInstruction("Array: {0}")); //body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction()); // Load list from local[0] //body.Instructions.Add(OpCodes.Callvirt.ToInstruction(listToArray)); //body.Instructions.Add(OpCodes.Call.ToInstruction(writeLine2)); // WriteLine("Count: {0}", list.Count) body.Instructions.Add(OpCodes.Ldstr.ToInstruction("Count: {0}")); body.Instructions.Add(OpCodes.Ldloc_0.ToInstruction()); // Load list from local[0] body.Instructions.Add(OpCodes.Callvirt.ToInstruction(listGetCount)); body.Instructions.Add(OpCodes.Box.ToInstruction(mod.CorLibTypes.Int32)); body.Instructions.Add(OpCodes.Call.ToInstruction(writeLine2)); // return 0; body.Instructions.Add(OpCodes.Ldc_I4_0.ToInstruction()); body.Instructions.Add(OpCodes.Ret.ToInstruction()); entryPoint.Body = body; // Save the assembly mod.Write(newFileName); }
public static TypeSig GetGenericArgument(GenericInstSig typeOwner, MethodSpec methodOwner, TypeSig type) { var typeArgs = typeOwner == null ? null : typeOwner.GenericArguments; var genMethodArgs = methodOwner == null || methodOwner.GenericInstMethodSig == null ? null : methodOwner.GenericInstMethodSig.GenericArguments; return GenericArgsSubstitutor.Create(type, typeArgs, genMethodArgs); }
void AddGenericInstSig() { var origType = GetTypeSig(VisibleMembersFlags.GenericTypeDef); if (origType == null) return; var type = origType as ClassOrValueTypeSig; if (type == null) { ShowWarning(null, "The type must be a generic type"); return; } var genericType = type.TypeDefOrRef.ResolveTypeDef(); if (genericType == null) { ShowWarning(null, "Could not resolve the type. Make sure that its assembly has already been loaded."); return; } if (genericType.GenericParameters.Count == 0) { ShowWarning(null, string.Format("{0} is not a generic type", genericType.FullName)); return; } var genArgs = createTypeSigArray.Create(options.Clone("Create Generic Instance Type Arguments"), genericType.GenericParameters.Count, null); if (genArgs == null) return; TypeSig = new GenericInstSig(type, genArgs); }