private IMethodDefinition CreateInitMethod(IMethodDefinition incomingMethodDefinition, IFieldReference loadLibraryModule, IFieldReference methodField, IMethodReference isLibraryInitMethod, IPlatformInvokeInformation platformInvokeInformation) { var methodDefinition = new MethodDefinition { IsStatic = true, Type = this.platformType.SystemVoid, ContainingTypeDefinition = incomingMethodDefinition.ContainingTypeDefinition, Name = this.nameTable.GetNameFor("init_" + incomingMethodDefinition.Name.Value), IsNeverInlined = true, Visibility = TypeMemberVisibility.Private }; var ilGenerator = new ILGenerator(this.host, methodDefinition); ilGenerator.Emit(OperationCode.Ldsfld, loadLibraryModule); ilGenerator.Emit(OperationCode.Dup); ilGenerator.Emit(OperationCode.Ldstr, platformInvokeInformation.ImportModule.Name.Value); ilGenerator.Emit(OperationCode.Call, isLibraryInitMethod); ilGenerator.Emit(OperationCode.Ldstr, platformInvokeInformation.ImportName.Value); ilGenerator.Emit(OperationCode.Call, this.getProcAddress); ilGenerator.Emit(OperationCode.Stsfld, methodField); ilGenerator.Emit(OperationCode.Ret); var ilMethodBody = new ILGeneratorMethodBody(ilGenerator, false, 2, methodDefinition, Enumerable.Empty <ILocalDefinition>(), Enumerable.Empty <ITypeDefinition>()); methodDefinition.Body = ilMethodBody; return(methodDefinition); }
private void InjectMethodToDumpCounters() { var dumper = new MethodDefinition() { ContainingTypeDefinition = this.counterFieldsForCurrentMethod, InternFactory = this.host.InternFactory, IsCil = true, IsStatic = true, Name = this.host.NameTable.GetNameFor("DumpCounters"), Type = this.host.PlatformType.SystemVoid, Visibility = TypeMemberVisibility.Public, }; this.counterFieldsForCurrentMethod.Methods.Add(dumper); this.dumperMethods.Add(dumper); var ilGenerator = new ILGenerator(this.host, dumper); for (int i = 0, n = this.fieldOffsets.Count; i < n; i++) { ilGenerator.Emit(OperationCode.Ldsfld, this.counterFieldsForCurrentMethod.Fields[i]); ilGenerator.Emit(OperationCode.Call, this.logger); } ilGenerator.Emit(OperationCode.Ret); var body = new ILGeneratorMethodBody(ilGenerator, false, 2, dumper, Enumerable <ILocalDefinition> .Empty, Enumerable <ITypeDefinition> .Empty); dumper.Body = body; }
private IMethodDefinition CreateLoadLibraryMethod(ITypeDefinition typeDefinition, IModuleReference moduleRef, IFieldReference fieldRef) { var methodDefinition = new MethodDefinition { IsStatic = true, Type = this.platformType.SystemVoid, ContainingTypeDefinition = typeDefinition, Name = this.nameTable.GetNameFor("LoadLibrary" + moduleRef.Name.Value), IsNeverInlined = true, Visibility = TypeMemberVisibility.Public, Parameters = new List <IParameterDefinition> { new ParameterDefinition { Index = 0, Type = this.platformType.SystemString, Name = this.host.NameTable.GetNameFor("nativeLibraryFilePath") } } }; var ilGenerator = new ILGenerator(this.host, methodDefinition); ilGenerator.Emit(OperationCode.Ldarg_0); ilGenerator.Emit(OperationCode.Call, this.loadLibrary); ilGenerator.Emit(OperationCode.Stsfld, fieldRef); ilGenerator.Emit(OperationCode.Ret); var ilMethodBody = new ILGeneratorMethodBody(ilGenerator, false, 2, methodDefinition, Enumerable.Empty <ILocalDefinition>(), Enumerable.Empty <ITypeDefinition>()); methodDefinition.Body = ilMethodBody; return(methodDefinition); }
private void TransformPInvokeMethodDefinitionToImplementedMethodDefinition(MethodDefinition methodDefinition) { methodDefinition.IsPlatformInvoke = false; methodDefinition.IsExternal = false; methodDefinition.PreserveSignature = false; var ilGenerator = new ILGenerator(this.host, methodDefinition); var label = new ILGeneratorLabel(); var transformationMetadata = this.metadataProvider.Retrieve(methodDefinition); var fieldDef = transformationMetadata.FunctionPointer; var locals = new List <ILocalDefinition>(); var paramToLocalMap = new Dictionary <IParameterDefinition, ILocalDefinition>(); ilGenerator.Emit(OperationCode.Ldsfld, fieldDef); ilGenerator.Emit(OperationCode.Ldsfld, this.intPtrZero); ilGenerator.Emit(OperationCode.Call, this.intPtrOpEquality); ilGenerator.Emit(OperationCode.Brfalse_S, label); ilGenerator.Emit(OperationCode.Call, transformationMetadata.InitializeMethod); ilGenerator.MarkLabel(label); this.LoadArguments(locals, paramToLocalMap, ilGenerator, methodDefinition.ParameterCount, i => methodDefinition.Parameters[i], methodDefinition.PlatformInvokeData); ilGenerator.Emit(OperationCode.Ldsfld, fieldDef); ilGenerator.Emit(OperationCode.Call, transformationMetadata.NativeMethod); this.ReturnMarshalling(ilGenerator, methodDefinition); this.PostprocessNonBlittableArrayArguments(methodDefinition, locals, paramToLocalMap, ilGenerator); ilGenerator.Emit(OperationCode.Ret); var ilMethodBody = new ILGeneratorMethodBody(ilGenerator, true, (ushort)((methodDefinition.ParameterCount + 1) * 2), methodDefinition, locals, new List <ITypeDefinition>()); methodDefinition.PlatformInvokeData = null; methodDefinition.Body = ilMethodBody; }
private INamedTypeDefinition GenerateTypeA(IUnitNamespace rootNamespace) { var nt = Host.NameTable; var typeA = new NamespaceTypeDefinition { ContainingUnitNamespace = rootNamespace, Name = nt.GetNameFor("A"), InternFactory = Host.InternFactory, IsClass = true }; var typeParameter = new GenericTypeParameter { Name = nt.GetNameFor("T"), InternFactory = Host.InternFactory, DefiningType = typeA, }; typeA.GenericParameters.Add(typeParameter); var baseGetMethod = new MethodDefinition { Name = nt.GetNameFor("Get"), IsCil = true, IsVirtual = true, Visibility = TypeMemberVisibility.Assembly, Type = typeParameter, ContainingTypeDefinition = typeA, InternFactory = Host.InternFactory, IsNewSlot = true }; typeA.Methods.Add(baseGetMethod); var il = new ILGenerator(Host); var localVar = new LocalDefinition { Type = typeParameter, Name = nt.GetNameFor("local1"), }; // tricky moment, ILGeneratorMethodBody fills internal collection of local vars only in constructor. // lines below should not be swapped il.AddVariableToCurrentScope(localVar); var body = new ILGeneratorMethodBody(il, true, 1) { MethodDefinition = baseGetMethod }; baseGetMethod.Body = body; il.Emit(OperationCode.Ldloca, localVar); il.Emit(OperationCode.Initobj, typeParameter); il.Emit(OperationCode.Ldloc_0); il.Emit(OperationCode.Ret); return(typeA); }
// this function adds a new local variable to the method public void addLocalVariable(ILocalDefinition localVariable) { ILGenerator ilGenerator = new ILGenerator(this.host, this.methodCfg.method); // add local variable List <ILocalDefinition> variableListCopy = new List <ILocalDefinition>(this.methodCfg.method.Body.LocalVariables); variableListCopy.Add(localVariable); // create the body List <ITypeDefinition> privateHelperTypesListCopy = new List <ITypeDefinition>(this.methodCfg.method.Body.PrivateHelperTypes); var newBody = new ILGeneratorMethodBody(ilGenerator, this.methodCfg.method.Body.LocalsAreZeroed, 8, this.methodCfg.method, variableListCopy, privateHelperTypesListCopy); // TODO dynamic max stack size? this.methodCfg.method.Body = newBody; }
public override IMethodBody Rewrite(IMethodBody methodBody) { this.currentLocals = new List <ILocalDefinition>(methodBody.LocalVariables); try { ProcessOperations(methodBody); var newBody = new ILGeneratorMethodBody(this.currentGenerator, methodBody.LocalsAreZeroed, (ushort)(methodBody.MaxStack + 1), methodBody.MethodDefinition, this.currentLocals ?? new List <ILocalDefinition>(), Enumerable <ITypeDefinition> .Empty); return(newBody); } catch (ILMutatorException) { Console.WriteLine("Internal error during IL mutation for the method '{0}'.", MemberHelper.GetMemberSignature(methodBody.MethodDefinition, NameFormattingOptions.SmartTypeName)); return(methodBody); } finally { this.currentLocals = null; } }
private IMethodReference InjectNewEntryPoint(IMethodDefinition oldEntryPoint) { var containingType = (NamespaceTypeDefinition)oldEntryPoint.ContainingTypeDefinition; var entryPoint = new MethodDefinition() { ContainingTypeDefinition = containingType, InternFactory = this.host.InternFactory, IsCil = true, IsStatic = true, Name = this.host.NameTable.GetNameFor("InstrumentedMain"), Parameters = new List <IParameterDefinition>(oldEntryPoint.Parameters), Type = this.host.PlatformType.SystemVoid, Visibility = TypeMemberVisibility.Public, }; containingType.Methods.Add(entryPoint); var ilGenerator = new ILGenerator(host, entryPoint); foreach (var par in entryPoint.Parameters) { ilGenerator.Emit(OperationCode.Ldarg, par); } ilGenerator.Emit(OperationCode.Call, oldEntryPoint); foreach (var dumper in this.dumperMethods) { ilGenerator.Emit(OperationCode.Call, dumper); } ilGenerator.Emit(OperationCode.Ret); var body = new ILGeneratorMethodBody(ilGenerator, true, (ushort)entryPoint.Parameters.Count, entryPoint, Enumerable <ILocalDefinition> .Empty, Enumerable <ITypeDefinition> .Empty); entryPoint.Body = body; return(entryPoint); }
private NamespaceTypeDefinition GenerateTypeB(IUnitNamespace rootNamespace, ITypeReference baseType) { var nt = Host.NameTable; var typeB = new NamespaceTypeDefinition { ContainingUnitNamespace = rootNamespace, Name = nt.GetNameFor("B"), InternFactory = Host.InternFactory, IsClass = true, BaseClasses = { baseType } }; var overrideGetMethod = new MethodDefinition { Name = nt.GetNameFor("Get"), IsCil = true, IsVirtual = true, Visibility = TypeMemberVisibility.Assembly, Type = Host.PlatformType.SystemString, ContainingTypeDefinition = typeB, InternFactory = Host.InternFactory }; typeB.Methods.Add(overrideGetMethod); var il = new ILGenerator(Host); var body = new ILGeneratorMethodBody(il, true, 1) { MethodDefinition = overrideGetMethod }; overrideGetMethod.Body = body; il.Emit(OperationCode.Ldstr, "1"); il.Emit(OperationCode.Ret); return(typeB); }
private IMethodDefinition CreateNativeMethod(IMethodDefinition pinvokeMethodDefinition) { var pinvokeData = pinvokeMethodDefinition.PlatformInvokeData; var nativeMethodDef = CreateRegularMethodDefinitionFromPInvokeMethodDefinition(pinvokeMethodDefinition, this.host.PlatformType.SystemIntPtr, this.host.PlatformType.SystemInt32); nativeMethodDef.Parameters.Add(new ParameterDefinition { Type = this.platformType.SystemIntPtr, Index = pinvokeMethodDefinition.ParameterCount, Name = this.nameTable.GetNameFor("funcPtr") }); var ilGenerator = new ILGenerator(this.host, nativeMethodDef); LoadArguments(ilGenerator, pinvokeMethodDefinition.ParameterCount + 1, i => nativeMethodDef.Parameters[i]); var returnType = !IsBlittableType(pinvokeMethodDefinition.Type) ? (pinvokeMethodDefinition.Type.TypeCode == PrimitiveTypeCode.Boolean ? this.platformType.SystemInt32 : this.platformType.SystemIntPtr) : pinvokeMethodDefinition.Type; var funcPtr = new FunctionPointerTypeReference { Type = returnType, Parameters = new List <IParameterTypeInformation>() }; switch (pinvokeData.PInvokeCallingConvention) { case PInvokeCallingConvention.CDecl: funcPtr.CallingConvention = CallingConvention.C; break; case PInvokeCallingConvention.FastCall: funcPtr.CallingConvention = CallingConvention.FastCall; break; case PInvokeCallingConvention.StdCall: case PInvokeCallingConvention.WinApi: funcPtr.CallingConvention = CallingConvention.Standard; break; case PInvokeCallingConvention.ThisCall: funcPtr.CallingConvention = CallingConvention.ThisCall; break; } foreach (var parameter in pinvokeMethodDefinition.Parameters) { var paramDef = new ParameterDefinition { Type = parameter.Type }; if (!IsBlittableType(parameter.Type)) { paramDef.Type = parameter.Type.TypeCode == PrimitiveTypeCode.Boolean ? this.platformType.SystemInt32 : this.platformType.SystemIntPtr; } else if (parameter.IsByReference) { paramDef.Type = this.platformType.SystemIntPtr; } funcPtr.Parameters.Add(paramDef); } ilGenerator.Emit(OperationCode.Calli, (ISignature)funcPtr); ilGenerator.Emit(OperationCode.Ret); var ilMethodBody = new ILGeneratorMethodBody(ilGenerator, false, nativeMethodDef.ParameterCount, nativeMethodDef, Enumerable.Empty <ILocalDefinition>(), Enumerable.Empty <ITypeDefinition>()); nativeMethodDef.Body = ilMethodBody; return(nativeMethodDef); }
static void Main(string[] args) { var nameTable = new NameTable(); using (var host = new PeReader.DefaultHost(nameTable)) { var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity); var assembly = new Assembly() { Name = nameTable.GetNameFor("hello"), ModuleName = nameTable.GetNameFor("hello.exe"), PlatformType = host.PlatformType, Kind = ModuleKind.ConsoleApplication, RequiresStartupStub = host.PointerSize == 4, TargetRuntimeVersion = coreAssembly.TargetRuntimeVersion, }; assembly.AssemblyReferences.Add(coreAssembly); var rootUnitNamespace = new RootUnitNamespace(); assembly.UnitNamespaceRoot = rootUnitNamespace; rootUnitNamespace.Unit = assembly; var moduleClass = new NamespaceTypeDefinition() { ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, Name = nameTable.GetNameFor("<Module>"), }; assembly.AllTypes.Add(moduleClass); var testClass = new NamespaceTypeDefinition() { ContainingUnitNamespace = rootUnitNamespace, InternFactory = host.InternFactory, IsClass = true, IsPublic = true, Methods = new List <IMethodDefinition>(1), Name = nameTable.GetNameFor("Test"), }; rootUnitNamespace.Members.Add(testClass); assembly.AllTypes.Add(testClass); testClass.BaseClasses = new List <ITypeReference>() { host.PlatformType.SystemObject }; var mainMethod = new MethodDefinition() { ContainingTypeDefinition = testClass, InternFactory = host.InternFactory, IsCil = true, IsStatic = true, Name = nameTable.GetNameFor("Main"), Type = host.PlatformType.SystemVoid, Visibility = TypeMemberVisibility.Public, }; assembly.EntryPoint = mainMethod; testClass.Methods.Add(mainMethod); var ilGenerator = new ILGenerator(host, mainMethod); var systemConsole = UnitHelper.FindType(nameTable, coreAssembly, "System.Console"); var writeLine = TypeHelper.GetMethod(systemConsole, nameTable.GetNameFor("WriteLine"), host.PlatformType.SystemString); ilGenerator.Emit(OperationCode.Ldstr, "hello"); ilGenerator.Emit(OperationCode.Call, writeLine); ilGenerator.Emit(OperationCode.Ret); var body = new ILGeneratorMethodBody(ilGenerator, true, 1, mainMethod, Enumerable <ILocalDefinition> .Empty, Enumerable <ITypeDefinition> .Empty); mainMethod.Body = body; using (var peStream = File.Create("hello.exe")) { PeWriter.WritePeToStream(assembly, host, peStream); } } }
// adds the given interface to the given class public void addInterface(NamespaceTypeDefinition addTargetClass, ITypeDefinition interfaceToAdd) { // add interface to target class if (addTargetClass.Interfaces != null) { // check if interface is already implemented by class if (addTargetClass.Interfaces.Contains(interfaceToAdd)) { this.logger.writeLine("Class \"" + addTargetClass.ToString() + "\" already implements interface \"" + interfaceToAdd.ToString() + "\""); return; } else { this.logger.writeLine("Add interface \"" + interfaceToAdd.ToString() + "\" to class \"" + addTargetClass.ToString() + "\""); addTargetClass.Interfaces.Add(interfaceToAdd); } } else { List <ITypeReference> interfaceList = new List <ITypeReference>(); interfaceList.Add(interfaceToAdd); addTargetClass.Interfaces = interfaceList; } // copy all attributes from the interface to the target class if (interfaceToAdd.Fields != null) { foreach (FieldDefinition field in interfaceToAdd.Fields) { FieldDefinition copy = new FieldDefinition(); this.helperClass.copyField(copy, field); copy.ContainingTypeDefinition = addTargetClass; // set intern factory of the copied field to the one of the class // (without it, the generated binary file will have strange results like use only the same field) copy.InternFactory = addTargetClass.InternFactory; addTargetClass.Fields.Add(copy); } } // copy all methods from the interface to the target class if (interfaceToAdd.Methods != null) { foreach (IMethodDefinition method in interfaceToAdd.Methods) { // search through all methods in the target class // to see if this method was already added bool foundMethod = false; foreach (IMethodDefinition tempMethod in addTargetClass.Methods) { // skip constructors if (tempMethod.IsConstructor) { continue; } // check if the number of parameters are the same if (tempMethod.ParameterCount == method.ParameterCount) { // check if the parameters have the same type in the same order bool parameterCorrect = true; for (int i = 0; i < method.ParameterCount; i++) { if (method.Parameters.ElementAt(i).Type != tempMethod.Parameters.ElementAt(i).Type) { parameterCorrect = false; break; } } // check if the return type is the same bool returnTypeCorrect = false; if (method.Type.Equals(tempMethod.Type)) { returnTypeCorrect = true; } // check if both methods are static // (c# compiler does not allow static + non-static function with // same signature in same class, but CIL does) bool bothStatic = false; if (method.IsStatic == tempMethod.IsStatic) { bothStatic = true; } // if the parameters and return type are correct => check the name if (parameterCorrect && returnTypeCorrect && bothStatic) { if (method.Name.Equals(tempMethod.Name)) { // if name is the same => method already added foundMethod = true; break; } } } } // skip if method was already added if (foundMethod) { this.logger.writeLine("Method \"" + method.Name.ToString() + "\" already exists"); continue; } this.logger.writeLine("Add method: " + method.Name.ToString()); // copy method MethodDefinition copy = new MethodDefinition(); this.helperClass.copyMethod(copy, method); copy.ContainingTypeDefinition = addTargetClass; // generate random dead code for newly created method ILGenerator ilGenerator = new ILGenerator(host, method); foreach (IOperation tempOperation in CodeGenerator.generateDeadCode(true)) { ilGenerator.Emit(tempOperation.OperationCode, tempOperation.Value); } IMethodBody newBody = new ILGeneratorMethodBody(ilGenerator, true, 8, method, Enumerable <ILocalDefinition> .Empty, Enumerable <ITypeDefinition> .Empty); copy.Body = newBody; // set intern factory of the copied method to the one of the class // (without it, the generated binary file will have strange results like call always the same method) copy.InternFactory = addTargetClass.InternFactory; // set method to not abstract copy.IsAbstract = false; // set method to not external copy.IsExternal = false; // set intern factory of the copied method to the one of the class // (without it, the generating of the binary file will have strange results) copy.InternFactory = addTargetClass.InternFactory; // add method to the class addTargetClass.Methods.Add(copy); } } }
// makes a copy of the method public void copyMethod(MethodDefinition dest, IMethodDefinition source) { // only copy body if it is not a dummy (= empty) if (!(source.Body is Microsoft.Cci.Dummy)) { // copy instructions ILGenerator ilGenerator = new ILGenerator(this.host, dest); foreach (var operation in source.Body.Operations) { ilGenerator.Emit(operation.OperationCode, operation.Value); } // copy the exception handler foreach (IOperationExceptionInformation exceptionToCopy in source.Body.OperationExceptionInformation) { ILGeneratorLabel tryStart = new ILGeneratorLabel(); tryStart.Offset = exceptionToCopy.TryStartOffset; ILGeneratorLabel tryEnd = new ILGeneratorLabel(); tryEnd.Offset = exceptionToCopy.TryEndOffset; ILGeneratorLabel handlerStart = new ILGeneratorLabel(); handlerStart.Offset = exceptionToCopy.HandlerStartOffset; ILGeneratorLabel handlerEnd = new ILGeneratorLabel(); handlerEnd.Offset = exceptionToCopy.HandlerEndOffset; ILGeneratorLabel filterStart = new ILGeneratorLabel(); filterStart.Offset = exceptionToCopy.FilterDecisionStartOffset; ilGenerator.AddExceptionHandlerInformation(exceptionToCopy.HandlerKind, exceptionToCopy.ExceptionType, tryStart, tryEnd, handlerStart, handlerEnd, filterStart); } // create the body List <ILocalDefinition> variableListCopy = new List <ILocalDefinition>(source.Body.LocalVariables); List <ITypeDefinition> privateHelperTypesListCopy = new List <ITypeDefinition>(source.Body.PrivateHelperTypes); var newBody = new ILGeneratorMethodBody(ilGenerator, source.Body.LocalsAreZeroed, source.Body.MaxStack, dest, variableListCopy, privateHelperTypesListCopy); dest.Body = newBody; } dest.CallingConvention = source.CallingConvention; if (source.IsGeneric) { dest.GenericParameters = new List <IGenericMethodParameter>(source.GenericParameters); } else { dest.GenericParameters = null; } if (source.ParameterCount > 0) { dest.Parameters = new List <IParameterDefinition>(source.Parameters); } else { dest.Parameters = null; } if (source.IsPlatformInvoke) { dest.PlatformInvokeData = source.PlatformInvokeData; } else { dest.PlatformInvokeData = Dummy.PlatformInvokeInformation; } dest.ReturnValueAttributes = new List <ICustomAttribute>(source.ReturnValueAttributes); if (source.ReturnValueIsModified) { dest.ReturnValueCustomModifiers = new List <ICustomModifier>(source.ReturnValueCustomModifiers); } else { dest.ReturnValueCustomModifiers = new List <ICustomModifier>(0); } if (source.ReturnValueIsMarshalledExplicitly) { dest.ReturnValueMarshallingInformation = source.ReturnValueMarshallingInformation; } else { dest.ReturnValueMarshallingInformation = Dummy.MarshallingInformation; } if (source.HasDeclarativeSecurity && IteratorHelper.EnumerableIsNotEmpty(source.SecurityAttributes)) { dest.SecurityAttributes = new List <ISecurityAttribute>(source.SecurityAttributes); } else { dest.SecurityAttributes = null; } dest.Type = source.Type; dest.AcceptsExtraArguments = source.AcceptsExtraArguments; dest.HasDeclarativeSecurity = source.HasDeclarativeSecurity; dest.IsAbstract = source.IsAbstract; dest.IsAccessCheckedOnOverride = source.IsAccessCheckedOnOverride; dest.IsCil = source.IsCil; dest.IsExternal = source.IsExternal; dest.IsForwardReference = source.IsForwardReference; dest.IsHiddenBySignature = source.IsHiddenBySignature; dest.IsNativeCode = source.IsNativeCode; dest.IsNewSlot = source.IsNewSlot; dest.IsNeverInlined = source.IsNeverInlined; dest.IsAggressivelyInlined = source.IsAggressivelyInlined; dest.IsNeverOptimized = source.IsNeverOptimized; dest.IsPlatformInvoke = source.IsPlatformInvoke; dest.IsRuntimeImplemented = source.IsRuntimeImplemented; dest.IsRuntimeInternal = source.IsRuntimeInternal; dest.IsRuntimeSpecial = source.IsRuntimeSpecial; dest.IsSealed = source.IsSealed; dest.IsSpecialName = source.IsSpecialName; dest.IsStatic = source.IsStatic; dest.IsSynchronized = source.IsSynchronized; dest.IsUnmanaged = source.IsUnmanaged; if (dest.IsStatic) { dest.IsVirtual = false; } else { dest.IsVirtual = source.IsVirtual; } dest.PreserveSignature = source.PreserveSignature; dest.RequiresSecurityObject = source.RequiresSecurityObject; dest.ReturnValueIsByRef = source.ReturnValueIsByRef; dest.ReturnValueIsMarshalledExplicitly = source.ReturnValueIsMarshalledExplicitly; dest.ReturnValueName = source.ReturnValueName; dest.Name = source.Name; dest.Visibility = source.Visibility; }
static void copyMethod(MethodDefinition dest, IMethodDefinition source, PeReader.DefaultHost host) { // only copy body if it is not a dummy (= empty) if (!(source.Body is Microsoft.Cci.Dummy)) { // TODO // langsames kopieren des Bodies, schnellerer weg möglich? var testIlGenerator = new ILGenerator(host, dest); foreach (var operation in source.Body.Operations) { testIlGenerator.Emit(operation.OperationCode, operation.Value); } List <ILocalDefinition> variableListCopy = new List <ILocalDefinition>(source.Body.LocalVariables); List <ITypeDefinition> privateHelperTypesListCopy = new List <ITypeDefinition>(source.Body.PrivateHelperTypes); var newBody = new ILGeneratorMethodBody(testIlGenerator, source.Body.LocalsAreZeroed, source.Body.MaxStack, dest, variableListCopy, privateHelperTypesListCopy); dest.Body = newBody; } dest.CallingConvention = source.CallingConvention; if (source.IsGeneric) { dest.GenericParameters = new List <IGenericMethodParameter>(source.GenericParameters); } else { dest.GenericParameters = null; } if (source.ParameterCount > 0) { dest.Parameters = new List <IParameterDefinition>(source.Parameters); } else { dest.Parameters = null; } if (source.IsPlatformInvoke) { dest.PlatformInvokeData = source.PlatformInvokeData; } else { dest.PlatformInvokeData = Dummy.PlatformInvokeInformation; } dest.ReturnValueAttributes = new List <ICustomAttribute>(source.ReturnValueAttributes); if (source.ReturnValueIsModified) { dest.ReturnValueCustomModifiers = new List <ICustomModifier>(source.ReturnValueCustomModifiers); } else { dest.ReturnValueCustomModifiers = new List <ICustomModifier>(0); } if (source.ReturnValueIsMarshalledExplicitly) { dest.ReturnValueMarshallingInformation = source.ReturnValueMarshallingInformation; } else { dest.ReturnValueMarshallingInformation = Dummy.MarshallingInformation; } if (source.HasDeclarativeSecurity && IteratorHelper.EnumerableIsNotEmpty(source.SecurityAttributes)) { dest.SecurityAttributes = new List <ISecurityAttribute>(source.SecurityAttributes); } else { dest.SecurityAttributes = null; } dest.Type = source.Type; dest.AcceptsExtraArguments = source.AcceptsExtraArguments; dest.HasDeclarativeSecurity = source.HasDeclarativeSecurity; dest.IsAbstract = source.IsAbstract; dest.IsAccessCheckedOnOverride = source.IsAccessCheckedOnOverride; dest.IsCil = source.IsCil; dest.IsExternal = source.IsExternal; dest.IsForwardReference = source.IsForwardReference; dest.IsHiddenBySignature = source.IsHiddenBySignature; dest.IsNativeCode = source.IsNativeCode; dest.IsNewSlot = source.IsNewSlot; dest.IsNeverInlined = source.IsNeverInlined; dest.IsAggressivelyInlined = source.IsAggressivelyInlined; dest.IsNeverOptimized = source.IsNeverOptimized; dest.IsPlatformInvoke = source.IsPlatformInvoke; dest.IsRuntimeImplemented = source.IsRuntimeImplemented; dest.IsRuntimeInternal = source.IsRuntimeInternal; dest.IsRuntimeSpecial = source.IsRuntimeSpecial; dest.IsSealed = source.IsSealed; dest.IsSpecialName = source.IsSpecialName; dest.IsStatic = source.IsStatic; dest.IsSynchronized = source.IsSynchronized; dest.IsUnmanaged = source.IsUnmanaged; if (dest.IsStatic) { dest.IsVirtual = false; } else { dest.IsVirtual = source.IsVirtual; } dest.PreserveSignature = source.PreserveSignature; dest.RequiresSecurityObject = source.RequiresSecurityObject; dest.ReturnValueIsByRef = source.ReturnValueIsByRef; dest.ReturnValueIsMarshalledExplicitly = source.ReturnValueIsMarshalledExplicitly; dest.ReturnValueName = source.ReturnValueName; dest.Name = source.Name; dest.Visibility = source.Visibility; }
static void mergeClassWithAncestor(NamespaceTypeDefinition mergeTargetClass, PeReader.DefaultHost host) { // get class from which was inherited ITypeDefinition ancestorClass = null; INamedEntity ancestorClassName = null; if (mergeTargetClass.BaseClasses.Count == 1) { // TODO // entferne wenn Methode umgeschrieben /* * // ignore inheritance from System.Object * if (mergeTargetClass.BaseClasses[0].ToString() != "System.Object") { * ancestorClass = (mergeTargetClass.BaseClasses[0] as NamespaceTypeDefinition); * } * // return if ancestor class equals System.Object * else { * return; * } */ // check base class is of type NamespaceTypeDefinition if (mergeTargetClass.BaseClasses.ElementAt(0) as NamespaceTypeDefinition != null) { ancestorClass = (mergeTargetClass.BaseClasses.ElementAt(0) as ITypeDefinition); ancestorClassName = (mergeTargetClass.BaseClasses.ElementAt(0) as INamedEntity); } // ignore inheritance from System.Object else if (mergeTargetClass.BaseClasses[0].ToString() == "System.Object") { return; } // check for needed values in base class and its resolved value (for example when base class of type NamespaceTypeReference) else if ((mergeTargetClass.BaseClasses.ElementAt(0).ResolvedType as ITypeDefinition != null) && (mergeTargetClass.BaseClasses.ElementAt(0) as INamedEntity != null)) { // TODO // weiss nicht ob es Sinn macht externe Klassen wie z.B. system.ValueType // in die aktuelle Klasse rein zu mergen => denn Trick mit methoden auf Virtual stellen // damit JIT Compiler unsere Methoden aufruft klappt nicht in dem Fall (da wir die Methoden von System.ValueType nicht umschreiben koennen) //ancestorClass = (mergeTargetClass.BaseClasses[0].ResolvedType as ITypeDefinition); //ancestorClassName = (mergeTargetClass.BaseClasses[0].ResolvedType as INamedEntity); return; } else { throw new ArgumentException("Do not know how to handle base class."); } } else { throw new ArgumentException("Do not know how to handle multiple inheritance."); } // copy all attributes from the ancestor class to the current class if (ancestorClass.Fields != null) { globalLog.writeLine("Copying fileds"); foreach (FieldDefinition field in ancestorClass.Fields) { FieldDefinition copy = new FieldDefinition(); globalLog.writeLine("Copying field: " + field.Name.ToString()); copyField(copy, field); copy.ContainingTypeDefinition = mergeTargetClass; // set intern factory of the copied field to the one of the class // (without it, the generated binary file will have strange results like use only the same field) copy.InternFactory = mergeTargetClass.InternFactory; mergeTargetClass.Fields.Add(copy); } globalLog.writeLine(""); } // list of all constructors of the ancestor class List <MethodDefinition> copiedAncestorConstructors = new List <MethodDefinition>(); // copy methods from the ancestor class to the current class if (ancestorClass.Methods != null) { globalLog.writeLine("Copying methods"); foreach (IMethodDefinition method in ancestorClass.Methods) { globalLog.writeLine("Copying method: " + method.Name.ToString()); // check if the method is a constructor if (method.IsConstructor) { MethodDefinition copiedAncestorConstructor = new MethodDefinition(); copyMethod(copiedAncestorConstructor, method, host); // TODO // name muss noch geaendert werden String tempName = "ctor_" + ancestorClassName.Name.ToString(); copiedAncestorConstructor.Name = host.NameTable.GetNameFor(tempName); // constructor has the "SpecialName" (the name describes the functionality) // and "RTSpecialName" (runtime should check name encoding) flag set // runtime will raise an exception if these flags are set for a copied constructor // which is added as a normal function copiedAncestorConstructor.IsSpecialName = false; copiedAncestorConstructor.IsRuntimeSpecial = false; // TODO: // vielleicht einfach von späterer Schleife machen lassen (sollte jetzt schon gehen, aber noch nicht getestet, // deshalb erst ein mal drin gelassen) // copy constructor and rewrite instructions to use attributes and functions // inside the same class var testIlGenerator = new ILGenerator(host, copiedAncestorConstructor); foreach (var operation in copiedAncestorConstructor.Body.Operations) { switch (operation.OperationCode) { case OperationCode.Call: // HIER NOCH CHECKEN OB ANDERE FUNKTIONEN INNERHALB DES ANCESTORS AUFGERUFEN WERDEN // DIESE MUESSEN UMGELEITET WERDEN /* * Microsoft.Cci.MutableCodeModel.MethodDefinition blah = null; * if (operation.Value is Microsoft.Cci.MutableCodeModel.MethodDefinition) { * blah = (Microsoft.Cci.MutableCodeModel.MethodDefinition)(operation.Value); * NamespaceTypeDefinition test = (NamespaceTypeDefinition)blah.ContainingTypeDefinition; * * if (ancestorClass.Name.Equals(test.Name)) { * System.Console.WriteLine("Ja"); * } * * * } */ testIlGenerator.Emit(operation.OperationCode, operation.Value); break; case OperationCode.Stfld: FieldDefinition attribute = (FieldDefinition)operation.Value; // search for the method attribute that is used in the copied constructor // and replace it with the method attribute from the current class FieldDefinition foundField = null; foreach (FieldDefinition field in mergeTargetClass.Fields) { if (attribute.Name.Equals(field.Name) && attribute.Type.Equals(field.Type)) { foundField = field; break; } } if (foundField == null) { System.Console.WriteLine("Attribute not found"); return; } testIlGenerator.Emit(operation.OperationCode, foundField); break; default: testIlGenerator.Emit(operation.OperationCode, operation.Value); break; } } // create new body List <ILocalDefinition> variableListCopy = new List <ILocalDefinition>(method.Body.LocalVariables); List <ITypeDefinition> privateHelperTypesListCopy = new List <ITypeDefinition>(method.Body.PrivateHelperTypes); var newBody = new ILGeneratorMethodBody(testIlGenerator, method.Body.LocalsAreZeroed, method.Body.MaxStack, copiedAncestorConstructor, variableListCopy, privateHelperTypesListCopy); copiedAncestorConstructor.Body = newBody; // set intern factory of the copied constructor to the one of the class // (without it, the generated binary file will have strange results like call always the same method) copiedAncestorConstructor.InternFactory = mergeTargetClass.InternFactory; // add copied constructor to the class copiedAncestorConstructor.ContainingTypeDefinition = mergeTargetClass; copiedAncestorConstructor.Visibility = TypeMemberVisibility.Private; mergeTargetClass.Methods.Add(copiedAncestorConstructor); // add copied ancestor constructor to the list of copied ancestor constructors copiedAncestorConstructors.Add(copiedAncestorConstructor); continue; } else { // copy method MethodDefinition copy = new MethodDefinition(); copyMethod(copy, method, host); copy.ContainingTypeDefinition = mergeTargetClass; // set intern factory of the copied method to the one of the class // (without it, the generating of the binary file will have strange results) copy.InternFactory = mergeTargetClass.InternFactory; // add method to the class if (mergeTargetClass.Methods == null) { mergeTargetClass.Methods = new List <IMethodDefinition>(); } mergeTargetClass.Methods.Add(copy); } } globalLog.writeLine(""); } // rewrite constructors of the class to call the copied constructor instead of // the constructor of the ancestor class // (rewriting methods is handled later) foreach (MethodDefinition method in mergeTargetClass.Methods) { // check if method is a constructor if (method.IsConstructor) { var testIlGenerator = new ILGenerator(host, method); foreach (var operation in method.Body.Operations) { switch (operation.OperationCode) { // only call instructions that call a constructor have to be redirected case OperationCode.Call: MethodDefinition calledMethod = (MethodDefinition)operation.Value; if (calledMethod.IsConstructor) { // TODO hier treten noch Probleme auf, wenn System.Object ist nicht der oberste Ancestor // sondern z.B. System.ValueType // check if the called constructor is not the constructor of System.Object // and if the constructor that is called is not a constructor of THIS class NamespaceTypeDefinition calledMethodNamespace = (NamespaceTypeDefinition)calledMethod.ContainingTypeDefinition; if (calledMethodNamespace.ToString() != "System.Object" && !calledMethodNamespace.Name.Equals(mergeTargetClass.Name)) { // search for the copied constructor that has to be called // (it is searched by parameter types because they always are named the same ".ctor") MethodDefinition copiedConstructorToCall = null; foreach (MethodDefinition copiedAncestorConstructor in copiedAncestorConstructors) { // check if the count of the parameters of the called constructor and the copied constructor are the same if (copiedAncestorConstructor.ParameterCount == calledMethod.ParameterCount) { // check if the parameters have the same type in the same order bool found = true; for (int i = 0; i < calledMethod.ParameterCount; i++) { if (calledMethod.Parameters[i].Type != copiedAncestorConstructor.Parameters[i].Type) { found = false; break; } } if (found) { copiedConstructorToCall = copiedAncestorConstructor; break; } } } if (copiedConstructorToCall == null) { throw new ArgumentException("No copied constructor with the same parameter types in the same order."); } // call copied constructor instead of constructor of the ancestor testIlGenerator.Emit(operation.OperationCode, copiedConstructorToCall); } // just emit if the called constructor is the constructor of System.Object else { testIlGenerator.Emit(operation.OperationCode, operation.Value); } } // just emit operation if no constructor is called // (rewriting methods is handled later) else { testIlGenerator.Emit(operation.OperationCode, operation.Value); } break; // just emit operation if none of the above cases match default: testIlGenerator.Emit(operation.OperationCode, operation.Value); break; } } // create new body List <ILocalDefinition> variableListCopy = new List <ILocalDefinition>(method.Body.LocalVariables); List <ITypeDefinition> privateHelperTypesListCopy = new List <ITypeDefinition>(method.Body.PrivateHelperTypes); var newBody = new ILGeneratorMethodBody(testIlGenerator, method.Body.LocalsAreZeroed, method.Body.MaxStack, method, variableListCopy, privateHelperTypesListCopy); method.Body = newBody; } } // rewrite all methods to use local attributes/methods instead of the ones of the ancestor foreach (MethodDefinition method in mergeTargetClass.Methods) { var testIlGenerator = new ILGenerator(host, method); foreach (var operation in method.Body.Operations) { switch (operation.OperationCode) { case OperationCode.Stfld: case OperationCode.Ldfld: // get namespace of attribute FieldDefinition attribute = (FieldDefinition)operation.Value; INamedTypeDefinition attributeNamespace = (INamedTypeDefinition)attribute.ContainingTypeDefinition; // check if namespace of attribute equals the namespace of THIS class // => just emit operation if (mergeTargetClass.Name.Equals(attributeNamespace.Name)) { testIlGenerator.Emit(operation.OperationCode, operation.Value); continue; } // try the namespace of all ancestors of this class to see if it was copied else { // flag that indicates if the operation was emitted during the search loop bool operationEmitted = false; // search through all ancestors to find the namespace of the used attribute NamespaceTypeDefinition tempAncestorClass = mergeTargetClass; while (true) { // get class from which was inherited if (tempAncestorClass.BaseClasses.Count == 1) { // ignore inheritance from System.Object if (tempAncestorClass.BaseClasses[0].ToString() != "System.Object") { tempAncestorClass = (tempAncestorClass.BaseClasses[0] as NamespaceTypeDefinition); } // return if ancestor class equals System.Object else { break; } } else { throw new ArgumentException("Do not know how to handle multiple inheritance."); } // check namespace of used attribute is equal to namespace of ancestor // => change target of operation to THIS class if (tempAncestorClass.Name.Equals(attributeNamespace.Name)) { // search for the method attribute that is used in the copied method // and replace it with the method attribute from the current class FieldDefinition foundField = null; foreach (FieldDefinition field in mergeTargetClass.Fields) { if (attribute.Name.Equals(field.Name) && attribute.Type.Equals(field.Type)) { foundField = field; break; } } if (foundField == null) { throw new ArgumentException("Attribute not found."); } // emit operation and set flag that it was emitted operationEmitted = true; testIlGenerator.Emit(operation.OperationCode, foundField); break; } } // if operation was not emitted yet => emit it if (operationEmitted == false) { testIlGenerator.Emit(operation.OperationCode, operation.Value); } } break; case OperationCode.Call: // just emit if value is of type method reference if (operation.Value is Microsoft.Cci.MutableCodeModel.MethodReference) { testIlGenerator.Emit(operation.OperationCode, operation.Value); continue; } // get namespace of called method MethodDefinition calledMethod = (MethodDefinition)operation.Value; NamespaceTypeDefinition calledMethodNamespace = (NamespaceTypeDefinition)calledMethod.ContainingTypeDefinition; // check if namespace of called method equals the namespace of THIS class // => just emit operation if (mergeTargetClass.Name.Equals(calledMethodNamespace.Name)) { testIlGenerator.Emit(operation.OperationCode, operation.Value); continue; } // try the namespace of all ancestors of this class to see if it was copied else { // flag that indicates if the operation was emitted during the search loop bool operationEmitted = false; // search through all ancestors to find the namespace of the called method NamespaceTypeDefinition tempAncestorClass = mergeTargetClass; while (true) { // get class from which was inherited if (tempAncestorClass.BaseClasses.Count == 1) { // ignore inheritance from System.Object if (tempAncestorClass.BaseClasses[0].ToString() != "System.Object") { tempAncestorClass = (tempAncestorClass.BaseClasses[0] as NamespaceTypeDefinition); } // return if ancestor class equals System.Object else { break; } } else { throw new ArgumentException("Do not know how to handle multiple inheritance."); } // check namespace of called method is equal to namespace of ancestor, if the same // => find copied method in THIS class // => change target of operation to method in THIS class if (tempAncestorClass.Name.Equals(calledMethodNamespace.Name)) { // search through all methods in THISS class and search for the copied one MethodDefinition foundMethod = null; foreach (MethodDefinition newMethod in mergeTargetClass.Methods) { // skip constructors (can not be called from the ancestor) if (newMethod.IsConstructor) { continue; } if (newMethod.ParameterCount == calledMethod.ParameterCount) { // check if the parameters have the same type in the same order bool parameterCorrect = true; for (int i = 0; i < calledMethod.ParameterCount; i++) { if (calledMethod.Parameters[i].Type != newMethod.Parameters[i].Type) { parameterCorrect = false; break; } } // if the parameters are correct => check the name if (parameterCorrect) { if (calledMethod.Name.Equals(newMethod.Name)) { // if name is the same => found method to call foundMethod = newMethod; break; } } } } // check if the method we want to call was found if (foundMethod == null) { throw new ArgumentException("Did not find a method to call."); } // emit operation and set flag that it was emitted operationEmitted = true; testIlGenerator.Emit(operation.OperationCode, foundMethod); break; } } // if operation was not emitted yet => emit it if (operationEmitted == false) { testIlGenerator.Emit(operation.OperationCode, operation.Value); } } break; // just emit operation if none of the above cases match default: testIlGenerator.Emit(operation.OperationCode, operation.Value); break; } } // create new body List <ILocalDefinition> variableListCopy = new List <ILocalDefinition>(method.Body.LocalVariables); List <ITypeDefinition> privateHelperTypesListCopy = new List <ITypeDefinition>(method.Body.PrivateHelperTypes); var newBody = new ILGeneratorMethodBody(testIlGenerator, method.Body.LocalsAreZeroed, method.Body.MaxStack, method, variableListCopy, privateHelperTypesListCopy); method.Body = newBody; } }