/// <summary> /// Apply a series of modifiers ("[]", "*", "&") to a base TypeSig. /// </summary> /// <param name="baseSig">Base TypeSig</param> /// <param name="modifiers">Modifier strings</param> /// <returns>TypeSig</returns> public static TypeSig FromBaseSig(TypeSig baseSig, Stack<String> modifiers) { String mod; while (modifiers.Count > 0) { mod = modifiers.Pop(); switch (mod) { case "[]": baseSig = new SZArraySig(baseSig); break; case "*": baseSig = new PtrSig(baseSig); break; case "&": baseSig = new ByRefSig(baseSig); break; default: throw new Exception(String.Format("Unknown modifier: {0}", mod)); } } return baseSig; }
private MosaInstruction ResolveInstruction(MethodDef methodDef, CilBody body, int index, GenericArgumentResolver resolver) { Instruction instruction = body.Instructions[index]; int? prev = index == 0 ? null : (int?)body.Instructions[index - 1].Offset; int? next = index == body.Instructions.Count - 1 ? null : (int?)body.Instructions[index + 1].Offset; object operand = instruction.Operand; // Special case: newarr instructions need to have their operand changed now so that the type is a SZArray if (instruction.OpCode == OpCodes.Newarr) { var typeSig = resolver.Resolve(((ITypeDefOrRef)instruction.Operand).ToTypeSig()); var szArraySig = new SZArraySig(typeSig); operand = metadata.Loader.GetType(szArraySig); } else if (instruction.Operand is ITypeDefOrRef) { operand = ResolveTypeOperand((ITypeDefOrRef)instruction.Operand, resolver); } else if (instruction.Operand is MemberRef) { MemberRef memberRef = (MemberRef)instruction.Operand; if (memberRef.IsFieldRef) operand = ResolveFieldOperand(memberRef, resolver); else operand = ResolveMethodOperand(memberRef, resolver); } else if (instruction.Operand is IField) { operand = ResolveFieldOperand((IField)instruction.Operand, resolver); } else if (instruction.Operand is IMethod) { operand = ResolveMethodOperand((IMethod)instruction.Operand, resolver); } else if (instruction.Operand is Local) { operand = ((Local)instruction.Operand).Index; } else if (instruction.Operand is Parameter) { operand = ((Parameter)instruction.Operand).Index; } else if (instruction.Operand is Instruction) { operand = (int)((Instruction)instruction.Operand).Offset; } else if (instruction.Operand is Instruction[]) { Instruction[] targets = (Instruction[])instruction.Operand; int[] offsets = new int[targets.Length]; for (int i = 0; i < offsets.Length; i++) offsets[i] = (int)targets[i].Offset; operand = offsets; } else if (instruction.Operand is string) { operand = metadata.Cache.GetStringId((string)instruction.Operand); } ushort code = (ushort)instruction.OpCode.Code; if (code > 0xff) // To match compiler's opcode values code = (ushort)(0x100 + (code & 0xff)); return new MosaInstruction((int)instruction.Offset, code, operand, prev, next); }
TypeSig ReadFieldOrPropType() { if (!recursionCounter.Increment()) throw new CABlobParserException("Too much recursion"); TypeSig result; switch ((SerializationType)reader.ReadByte()) { case SerializationType.Boolean: result = module.CorLibTypes.Boolean; break; case SerializationType.Char: result = module.CorLibTypes.Char; break; case SerializationType.I1: result = module.CorLibTypes.SByte; break; case SerializationType.U1: result = module.CorLibTypes.Byte; break; case SerializationType.I2: result = module.CorLibTypes.Int16; break; case SerializationType.U2: result = module.CorLibTypes.UInt16; break; case SerializationType.I4: result = module.CorLibTypes.Int32; break; case SerializationType.U4: result = module.CorLibTypes.UInt32; break; case SerializationType.I8: result = module.CorLibTypes.Int64; break; case SerializationType.U8: result = module.CorLibTypes.UInt64; break; case SerializationType.R4: result = module.CorLibTypes.Single; break; case SerializationType.R8: result = module.CorLibTypes.Double; break; case SerializationType.String: result = module.CorLibTypes.String; break; case SerializationType.SZArray: result = new SZArraySig(ReadFieldOrPropType()); break; case SerializationType.Type: result = new ClassSig(module.CorLibTypes.GetTypeRef("System", "Type")); break; case SerializationType.TaggedObject: result = module.CorLibTypes.Object; break; case SerializationType.Enum: result = ReadType(); break; default: throw new CABlobParserException("Invalid type"); } recursionCounter.Decrement(); return result; }
CAArgument ReadArrayArgument(SZArraySig arrayType) { if (!recursionCounter.Increment()) throw new CABlobParserException("Too much recursion"); var arg = new CAArgument(arrayType); int arrayCount = reader.ReadInt32(); if (arrayCount == -1) { // -1 if it's null } else if (arrayCount < 0) throw new CABlobParserException("Array is too big"); else { var array = ThreadSafeListCreator.Create<CAArgument>(arrayCount); arg.Value = array; for (int i = 0; i < arrayCount; i++) array.Add(ReadFixedArg(FixTypeSig(arrayType.Next))); } recursionCounter.Decrement(); return arg; }
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; }
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; }
public ArrayInfo(int start, int len, FieldDef encryptedField, SZArraySig arrayType) { this.start = start; this.len = len; this.encryptedField = encryptedField; this.arrayType = arrayType; }
void AddSZArraySig() { TypeSig = new SZArraySig(TypeSig); }
TypeSig ResolveGenericArgs(TypeSig typeSig) { if (typeSig == null) { return(null); } 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: result = new FnPtrSig(ResolveGenericArgs(((FnPtrSig)typeSig).MethodSig)); break; 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(gis.GenericType as TypeSig) as ClassOrValueTypeSig, genArgs); break; default: result = typeSig; break; } recursionCounter.Decrement(); return(result); }
/// <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 TypeSig getLoadedType(MethodDef method, IList<Instruction> instructions, int instrIndex, int argIndexFromEnd, out bool wasNewobj) { wasNewobj = false; var pushedArgs = MethodStack.getPushedArgInstructions(instructions, instrIndex); var pushInstr = pushedArgs.getEnd(argIndexFromEnd); if (pushInstr == null) return null; TypeSig type; Local local; var corLibTypes = method.DeclaringType.Module.CorLibTypes; switch (pushInstr.OpCode.Code) { case Code.Ldstr: type = corLibTypes.String; break; case Code.Conv_I: case Code.Conv_Ovf_I: case Code.Conv_Ovf_I_Un: type = corLibTypes.IntPtr; break; case Code.Conv_U: case Code.Conv_Ovf_U: case Code.Conv_Ovf_U_Un: type = corLibTypes.UIntPtr; break; case Code.Conv_I8: case Code.Conv_Ovf_I8: case Code.Conv_Ovf_I8_Un: type = corLibTypes.Int64; break; case Code.Conv_U8: case Code.Conv_Ovf_U8: case Code.Conv_Ovf_U8_Un: type = corLibTypes.UInt64; break; case Code.Conv_R8: case Code.Ldc_R8: case Code.Ldelem_R8: case Code.Ldind_R8: type = corLibTypes.Double; break; case Code.Call: case Code.Calli: case Code.Callvirt: var calledMethod = pushInstr.Operand as IMethod; if (calledMethod == null) return null; type = calledMethod.MethodSig.GetRetType(); break; case Code.Newarr: var type2 = pushInstr.Operand as ITypeDefOrRef; if (type2 == null) return null; type = new SZArraySig(type2.ToTypeSig()); wasNewobj = true; break; case Code.Newobj: var ctor = pushInstr.Operand as IMethod; if (ctor == null) return null; type = ctor.DeclaringType.ToTypeSig(); wasNewobj = true; break; case Code.Castclass: case Code.Isinst: case Code.Unbox_Any: case Code.Ldelem: case Code.Ldobj: type = (pushInstr.Operand as ITypeDefOrRef).ToTypeSig(); break; case Code.Ldarg: case Code.Ldarg_S: case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: type = pushInstr.GetArgumentType(method.MethodSig, method.DeclaringType); break; case Code.Ldloc: case Code.Ldloc_S: case Code.Ldloc_0: case Code.Ldloc_1: case Code.Ldloc_2: case Code.Ldloc_3: local = pushInstr.GetLocal(method.Body.Variables); if (local == null) return null; type = local.Type.RemovePinned(); break; case Code.Ldloca: case Code.Ldloca_S: local = pushInstr.Operand as Local; if (local == null) return null; type = createByRefType(local.Type.RemovePinned()); break; case Code.Ldarga: case Code.Ldarga_S: type = createByRefType(pushInstr.GetArgumentType(method.MethodSig, method.DeclaringType)); break; case Code.Ldfld: case Code.Ldsfld: var field = pushInstr.Operand as IField; if (field == null || field.FieldSig == null) return null; type = field.FieldSig.GetFieldType(); break; case Code.Ldflda: case Code.Ldsflda: var field2 = pushInstr.Operand as IField; if (field2 == null || field2.FieldSig == null) return null; type = createByRefType(field2.FieldSig.GetFieldType()); break; case Code.Ldelema: case Code.Unbox: type = createByRefType(pushInstr.Operand as ITypeDefOrRef); break; default: return null; } return type; }
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; }
/// <summary> /// Tries to relocate the <see cref="SZArraySig"/>. /// </summary> /// <param name="szArraySig">The sz array sig.</param> /// <returns></returns> protected virtual TypeSig TryRelocateSZArray(SZArraySig szArraySig) { var nextType = TryRelocateTypeSig(szArraySig.Next); if (nextType == null) return null; return new SZArraySig(nextType); }
private TypeSig ReadFieldOrPropType() { if (!recursionCounter.Increment()) { throw new CABlobParserException("Too much recursion"); } TypeSig result; switch ((SerializationType)reader.ReadByte()) { case SerializationType.Boolean: result = module.CorLibTypes.Boolean; break; case SerializationType.Char: result = module.CorLibTypes.Char; break; case SerializationType.I1: result = module.CorLibTypes.SByte; break; case SerializationType.U1: result = module.CorLibTypes.Byte; break; case SerializationType.I2: result = module.CorLibTypes.Int16; break; case SerializationType.U2: result = module.CorLibTypes.UInt16; break; case SerializationType.I4: result = module.CorLibTypes.Int32; break; case SerializationType.U4: result = module.CorLibTypes.UInt32; break; case SerializationType.I8: result = module.CorLibTypes.Int64; break; case SerializationType.U8: result = module.CorLibTypes.UInt64; break; case SerializationType.R4: result = module.CorLibTypes.Single; break; case SerializationType.R8: result = module.CorLibTypes.Double; break; case SerializationType.String: result = module.CorLibTypes.String; break; case SerializationType.SZArray: result = new SZArraySig(ReadFieldOrPropType()); break; case SerializationType.Type: result = new ClassSig(module.CorLibTypes.GetTypeRef("System", "Type")); break; case SerializationType.TaggedObject: result = module.CorLibTypes.Object; break; case SerializationType.Enum: result = ReadType(false); break; default: throw new CABlobParserException("Invalid type"); } recursionCounter.Decrement(); return(result); }