Ejemplo n.º 1
0
        public override void Visit(MethodDefinition methodDefinition)
        {
            var xMethodDef = MethodsMap[methodDefinition];
            mILGenerator = new ILGenerator(mHostEnvironment, xMethodDef);
            mBody = new ILGeneratorMethodBody(mILGenerator, true, 65000);
            mBody.MethodDefinition=xMethodDef;
            xMethodDef.Body=mBody;

            base.Visit(methodDefinition);
        }
Ejemplo n.º 2
0
        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;
        }
Ejemplo n.º 3
0
        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;
            }
        }
    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 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;

    }
Ejemplo n.º 7
0
        // 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;

        }
        // 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);
                }
            }
        }
Ejemplo n.º 9
0
    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);
        }
      }
    }
Ejemplo n.º 10
0
        // creates a method for a given method CFG (IMPORTANT: it updates the operations
        // and exception handlers of the existing method, does not create a new method)
        public void createMethodFromCfg(MethodCfg methodCfg) {

            // list of basic blocks that belong together logically (i.e. BB2 lies directly behind BB1 because it reaches it without a branch)
            IList<BasicBlockUnion> basicBlockUnions = new List<BasicBlockUnion>();

            // first step: create basic block unions
            // create first basic block union starting from the start basic block
            BasicBlockUnion firstBasicBlockUnion = new BasicBlockUnion();
            this.createRecursivelyBasicBlockUnion(basicBlockUnions, firstBasicBlockUnion, methodCfg.startBasicBlock);
            basicBlockUnions.Add(firstBasicBlockUnion);

            // create basic block unions for the rest of the basic blocks
            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                // create a basic block union (if basic block is not contained by another existing basic block union)
                BasicBlockUnion basicBlockUnion = new BasicBlockUnion();
                this.createRecursivelyBasicBlockUnion(basicBlockUnions, basicBlockUnion, tempBB);

                // if the newly created basic block union contains basic blocks
                // => add to list of basic block unions
                if (basicBlockUnion.basicBlocks.Count() != 0) {
                    basicBlockUnions.Add(basicBlockUnion);
                }
            }


            // step two: merge basic block unions with respect to the exception handler
            foreach (OperationExceptionInformation exceptionHandler in methodCfg.method.Body.OperationExceptionInformation) {

                // create a temporary object to reorder the basic block unions with respect to the exception handler
                BasicBlockUnionExceptionHandlerOrder tempNewOrder = new BasicBlockUnionExceptionHandlerOrder();
                tempNewOrder.exceptionHandler = exceptionHandler;

                // find all basic blocks that are connected to the current exception handler
                foreach (BasicBlockUnion basicBlockUnion in basicBlockUnions) {
                    foreach (BasicBlock basicBlock in basicBlockUnion.basicBlocks) {

                        // ignore all basic blocks that do not have any try/catch/finally handler in it
                        if (basicBlock.tryBlocks.Count() == 0 && basicBlock.handlerBlocks.Count() == 0) {
                            continue;
                        }

                        // find the try block that is connected to the current exception handler
                        foreach (TryBlock tryBlock in basicBlock.tryBlocks) {

                            // ignore try blocks that do not belong to the current exception handler
                            if (tryBlock.exceptionHandler != exceptionHandler) {
                                continue;
                            }

                            // check if basic block union already resides in try body
                            // if not => add to try body
                            if (!tempNewOrder.tryBody.Contains(basicBlockUnion)) {
                                tempNewOrder.tryBody.Add(basicBlockUnion);
                            }

                            // check if the basic block starts the try block
                            if (tryBlock.firstBasicBlockOfTryBlock) {
                                tempNewOrder.tryStart = basicBlockUnion;
                            }

                            // check if the basic block ends the try block
                            if (tryBlock.lastBasicBlockOfTryBlock) {
                                tempNewOrder.tryEnd = basicBlockUnion;
                            }
                        }

                        // find the handler block that is connected to the current exception handler
                        foreach (HandlerBlock handlerBlock in basicBlock.handlerBlocks) {

                            // ignore handler blocks that do not belong to the current exception handler
                            if (handlerBlock.exceptionHandler != exceptionHandler) {
                                continue;
                            }

                            // check if basic block union already resides in handler body
                            // if not => add to handler body
                            if (!tempNewOrder.handlerBody.Contains(basicBlockUnion)) {
                                tempNewOrder.handlerBody.Add(basicBlockUnion);
                            }

                            // check if the basic block starts the handler block
                            if (handlerBlock.firstBasicBlockOfHandlerBlock) {
                                tempNewOrder.handlerStart = basicBlockUnion;
                            }

                            // check if the basic block ends the handler block
                            if (handlerBlock.lastBasicBlockOfHandlerBlock) {
                                tempNewOrder.handlerEnd = basicBlockUnion;
                            }
                        }
                    }
                }
                if (tempNewOrder.tryStart == null
                    || tempNewOrder.tryEnd == null
                    || tempNewOrder.handlerStart == null
                    || tempNewOrder.handlerEnd == null) {
                        throw new ArgumentException("Could not find all try/catch beginnings/ends.");
                }



                // merge basic block unions with respect to the current exception handler

                // check if the complete exception handling is done in only one basic block union
                // => ignore it
                if (tempNewOrder.tryStart == tempNewOrder.tryEnd
                    && tempNewOrder.handlerStart == tempNewOrder.handlerEnd
                    && tempNewOrder.tryStart == tempNewOrder.handlerStart) {
                    continue;
                }

                // if not everything lies in the same basic block union
                // extend the basic block union that starts the try block
                BasicBlockUnion extendedUnion = tempNewOrder.tryStart;

                // if try block start and end are the same => nothing to merge
                // else merge the basic block unions
                if (tempNewOrder.tryStart != tempNewOrder.tryEnd) {
                    foreach (BasicBlockUnion tryBodyBasicBlockUnion in tempNewOrder.tryBody) {

                        // ignore the basic block union that starts the try block (already in extended union)
                        // and ignore the basic block union that ends the try block (is added last)
                        if (tryBodyBasicBlockUnion == tempNewOrder.tryStart
                            || tryBodyBasicBlockUnion == tempNewOrder.tryEnd) {
                            continue;
                        }

                        // extend first basic block union with the basic block union of the
                        // try block body and remove the added one from the list of basic block unions
                        extendedUnion.basicBlocks.AddRange(tryBodyBasicBlockUnion.basicBlocks);
                        basicBlockUnions.Remove(tryBodyBasicBlockUnion);
                    }

                    // extend first basic block union with the basic block union of the
                    // try block end and remove the added one from the list of basic block unions
                    extendedUnion.basicBlocks.AddRange(tempNewOrder.tryEnd.basicBlocks);
                    basicBlockUnions.Remove(tempNewOrder.tryEnd);
                }

                // if the try block end and the handler block start are not the same basic block union
                // => merge the union of the handler block start to the current basic block union
                if (tempNewOrder.tryEnd != tempNewOrder.handlerStart) {
                    extendedUnion.basicBlocks.AddRange(tempNewOrder.handlerStart.basicBlocks);
                    basicBlockUnions.Remove(tempNewOrder.handlerStart);
                }

                // if handler block start and end are the same => nothing to merge
                // else merge the basic block unions
                if (tempNewOrder.handlerStart != tempNewOrder.handlerEnd) {
                    foreach (BasicBlockUnion handlerBodyBasicBlockUnion in tempNewOrder.handlerBody) {

                        // ignore the basic block union that starts the handler block (already in extended union)
                        // and ignore the basic block union that ends the handler block (is added last)
                        if (handlerBodyBasicBlockUnion == tempNewOrder.handlerStart
                            || handlerBodyBasicBlockUnion == tempNewOrder.handlerEnd) {
                            continue;
                        }

                        // add basic block union of the handler block body to the extended basic block union 
                        // and remove the added one from the list of basic block unions
                        extendedUnion.basicBlocks.AddRange(handlerBodyBasicBlockUnion.basicBlocks);
                        basicBlockUnions.Remove(handlerBodyBasicBlockUnion);
                    }

                    // extend the extended basic block union with the basic block union of the
                    // handler block end and remove the added one from the list of basic block unions
                    extendedUnion.basicBlocks.AddRange(tempNewOrder.handlerEnd.basicBlocks);
                    basicBlockUnions.Remove(tempNewOrder.handlerEnd);
                }
            }


            // step three: create one list of operations and modify jump offsets
            // create a list of operations from the basic blocks,
            // update basic block start/end indices accordingly
            // and update the offsets of the operations (needed to update branch operations)
            IList<IOperation> methodOperations = new List<IOperation>();
            int operationIdx = 0;
            uint currentOffset = 0;
            foreach (BasicBlockUnion basicBlockUnion in basicBlockUnions) {
                foreach (BasicBlock basicBlock in basicBlockUnion.basicBlocks) {
                    basicBlock.startIdx = operationIdx;
                    //foreach (IOperation operation in basicBlock.operations) {
                    for (int opIdx = 0; opIdx < basicBlock.operations.Count(); opIdx++) {
                        IOperation operation = basicBlock.operations.ElementAt(opIdx);

                        // a new operation object is needed because the old operations
                        // are read only due to cci
                        InternalOperation newOperation = new InternalOperation();

                        // exchange every short instruction with its larger one
                        switch (operation.OperationCode) {
                            case OperationCode.Beq_S:
                                newOperation.OperationCode = OperationCode.Beq;
                                break;
                            case OperationCode.Bge_S:
                                newOperation.OperationCode = OperationCode.Bge;
                                break;
                            case OperationCode.Bge_Un_S:
                                newOperation.OperationCode = OperationCode.Bge_Un;
                                break;
                            case OperationCode.Bgt_S:
                                newOperation.OperationCode = OperationCode.Bgt;
                                break;
                            case OperationCode.Bgt_Un_S:
                                newOperation.OperationCode = OperationCode.Bgt_Un;
                                break;
                            case OperationCode.Ble_S:
                                newOperation.OperationCode = OperationCode.Ble;
                                break;
                            case OperationCode.Ble_Un_S:
                                newOperation.OperationCode = OperationCode.Ble_Un;
                                break;
                            case OperationCode.Blt_S:
                                newOperation.OperationCode = OperationCode.Blt;
                                break;
                            case OperationCode.Blt_Un_S:
                                newOperation.OperationCode = OperationCode.Blt_Un;
                                break;
                            case OperationCode.Bne_Un_S:
                                newOperation.OperationCode = OperationCode.Bne_Un;
                                break;
                            case OperationCode.Br_S:
                                newOperation.OperationCode = OperationCode.Br;
                                break;
                            case OperationCode.Brfalse_S:
                                newOperation.OperationCode = OperationCode.Brfalse;
                                break;
                            case OperationCode.Brtrue_S:
                                newOperation.OperationCode = OperationCode.Brtrue;
                                break;
                            case OperationCode.Ldarg_S:
                                newOperation.OperationCode = OperationCode.Ldarg;
                                break;
                            case OperationCode.Ldarga_S:
                                newOperation.OperationCode = OperationCode.Ldarga;
                                break;
                            case OperationCode.Ldc_I4_S:
                                newOperation.OperationCode = OperationCode.Ldc_I4;
                                break;
                            case OperationCode.Ldloc_S:
                                newOperation.OperationCode = OperationCode.Ldloc;
                                break;
                            case OperationCode.Ldloca_S:
                                newOperation.OperationCode = OperationCode.Ldloca;
                                break;
                            case OperationCode.Leave_S:
                                newOperation.OperationCode = OperationCode.Leave;
                                break;
                            case OperationCode.Starg_S:
                                newOperation.OperationCode = OperationCode.Starg;
                                break;
                            case OperationCode.Stloc_S:
                                newOperation.OperationCode = OperationCode.Stloc;
                                break;
                            default:
                                newOperation.OperationCode = operation.OperationCode;
                                break;
                        }
                        newOperation.Value = operation.Value;
                        newOperation.Location = operation.Location;
                        newOperation.Offset = currentOffset;
                        methodOperations.Add(newOperation);

                        // replace old operation in basic block with newly created one
                        basicBlock.operations[opIdx] = newOperation;

                        operationIdx++;
                        currentOffset += CfgBuilder.getSizeOfOperation(newOperation);
                    }
                    basicBlock.endIdx = operationIdx - 1;
                }
            }


            // step four: update branches with new target offsets
            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {
                InternalOperation branchOperation = (InternalOperation)methodOperations.ElementAt(tempBB.endIdx);

                // check which kind of exit branch is used by this basic block and update its operation accordingly
                if (tempBB.exitBranch as NoBranchTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as TryBlockTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as ConditionalBranchTarget != null) {
                    ConditionalBranchTarget tempExitBranch = (tempBB.exitBranch as ConditionalBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // get index of the branch target
                    int targetBranchIdx = tempExitBranch.takenTarget.startIdx;

                    // update offset of the taken branch
                    branchOperation.Value = methodOperations.ElementAt(targetBranchIdx).Offset;
                }
                else if (tempBB.exitBranch as SwitchBranchTarget != null) {
                    SwitchBranchTarget tempExitBranch = (tempBB.exitBranch as SwitchBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // update all switch branches
                    for (int switchIdx = 0; switchIdx < tempExitBranch.takenTarget.Count(); switchIdx++) {

                        // get index of the branch target
                        int targetBranchIdx = tempExitBranch.takenTarget.ElementAt(switchIdx).startIdx;

                        // update offset of the taken branch
                        ((uint[])branchOperation.Value)[switchIdx] = methodOperations.ElementAt(targetBranchIdx).Offset;
                    }
                }
                else if (tempBB.exitBranch as UnconditionalBranchTarget != null) {
                    UnconditionalBranchTarget tempExitBranch = (tempBB.exitBranch as UnconditionalBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // get index of the branch target
                    int targetBranchIdx = tempExitBranch.takenTarget.startIdx;

                    // update offset of the taken branch
                    branchOperation.Value = methodOperations.ElementAt(targetBranchIdx).Offset;
                }
                else if (tempBB.exitBranch as ExitBranchTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as ThrowBranchTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as ExceptionBranchTarget != null) {
                    ExceptionBranchTarget tempExitBranch = (tempBB.exitBranch as ExceptionBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // get index of the branch target
                    int targetBranchIdx = tempExitBranch.exitTarget.startIdx;

                    // update offset of the taken branch
                    branchOperation.Value = methodOperations.ElementAt(targetBranchIdx).Offset;
                }
                else {
                    throw new ArgumentException("Do not know how to handle exit branch.");
                }
            }


            // step five: create new exception handler with updated offsets and
            // create new method body of the cci method
            MethodDefinition method = methodCfg.method;
            var ilGenerator = new ILGenerator(this.host, method);
            // emit all operations to the new body
            foreach (IOperation operation in methodOperations) {
                ilGenerator.Emit(operation.OperationCode, operation.Value);
            }

            // list that is used to replace the pointer to the old exception handler in the basic blocks to the new exception handler
            List<OldExceptionHandlerMapping> oldExceptionHandlerMappings = new List<OldExceptionHandlerMapping>();
            
            // create for each old exception handler a new one with updated data
            foreach (IOperationExceptionInformation exceptionHandler in method.Body.OperationExceptionInformation) {

                // create mapping object for old exception handler
                OldExceptionHandlerMapping oldExceptionHandlerMapping = new OldExceptionHandlerMapping();
                oldExceptionHandlerMapping.oldExceptionHandler = exceptionHandler;
                oldExceptionHandlerMappings.Add(oldExceptionHandlerMapping);

                ILGeneratorLabel tryStart = new ILGeneratorLabel();
                ILGeneratorLabel tryEnd = new ILGeneratorLabel();
                ILGeneratorLabel handlerStart = new ILGeneratorLabel();
                ILGeneratorLabel handlerEnd = new ILGeneratorLabel();
                ILGeneratorLabel filterStart = new ILGeneratorLabel();

                // search for the basic blocks that start/end the try block and handler block
                foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                    foreach (TryBlock tempTryBlock in tempBB.tryBlocks) {

                        // ignore try blocks that do not belong to the current exception handler
                        if (tempTryBlock.exceptionHandler != exceptionHandler) {
                            continue;
                        }

                        // get offset of the instruction that starts the try block
                        if (tempTryBlock.firstBasicBlockOfTryBlock) {
                            tryStart.Offset = tempBB.operations.ElementAt(0).Offset;
                            oldExceptionHandlerMapping.tryStartOffset = tryStart.Offset;
                        }

                        // get offset of the instruction that ends the try block (always the last instruction of the basic block)
                        if (tempTryBlock.lastBasicBlockOfTryBlock) {
                            tryEnd.Offset = tempBB.operations.ElementAt(tempBB.operations.Count() - 1).Offset;
                            // exception handler object needs offset of the end of the instruction (not the beginning)
                            tryEnd.Offset += CfgBuilder.getSizeOfOperation(tempBB.operations.ElementAt(tempBB.operations.Count() - 1));
                            oldExceptionHandlerMapping.tryEndOffset = tryEnd.Offset;
                        }
                    }

                    foreach (HandlerBlock tempHandlerBlock in tempBB.handlerBlocks) {

                        // ignore handler blocks that do not belong to the current exception handler
                        if (tempHandlerBlock.exceptionHandler != exceptionHandler) {
                            continue;
                        }

                        // get offset ot the instruction that starts the handler block
                        if (tempHandlerBlock.firstBasicBlockOfHandlerBlock) {
                            handlerStart.Offset = tempBB.operations.ElementAt(0).Offset;
                            oldExceptionHandlerMapping.handlerStartOffset = handlerStart.Offset;
                        }

                        // get offset of the instruction that ends the handler block
                        if (tempHandlerBlock.lastBasicBlockOfHandlerBlock) {
                            handlerEnd.Offset = tempBB.operations.ElementAt(tempBB.operations.Count() - 1).Offset;
                            // exception handler object needs offset of the end of the instruction (not the beginning)
                            handlerEnd.Offset += CfgBuilder.getSizeOfOperation(tempBB.operations.ElementAt(tempBB.operations.Count() - 1));
                            oldExceptionHandlerMapping.handlerEndOffset = handlerEnd.Offset;
                        }
                    }
                }

                // copy the exception handler filter
                filterStart.Offset = exceptionHandler.FilterDecisionStartOffset;
                oldExceptionHandlerMapping.filterStartOffset = filterStart.Offset;

                // add new exception handler
                oldExceptionHandlerMapping.exceptionType = exceptionHandler.ExceptionType;
                oldExceptionHandlerMapping.handlerKind = exceptionHandler.HandlerKind;
                ilGenerator.AddExceptionHandlerInformation(exceptionHandler.HandlerKind, exceptionHandler.ExceptionType, tryStart, tryEnd, handlerStart, handlerEnd, filterStart);
            }

            // create the body
            List<ILocalDefinition> variableListCopy = new List<ILocalDefinition>(method.Body.LocalVariables);
            List<ITypeDefinition> privateHelperTypesListCopy = new List<ITypeDefinition>(method.Body.PrivateHelperTypes);
            var newBody = new ILGeneratorMethodBody(ilGenerator, method.Body.LocalsAreZeroed, 8, method, variableListCopy, privateHelperTypesListCopy); // TODO dynamic max stack size?
            method.Body = newBody;


            // step six: replace pointer to the old exception handler with the new exception handler

            // map all old exception handler to the new objects
            foreach (IOperationExceptionInformation exceptionHandler in method.Body.OperationExceptionInformation) {

                // search for the new exception handler object to get the mapping to the old one
                bool found = false;
                foreach (OldExceptionHandlerMapping oldExceptionHandlerMapping in oldExceptionHandlerMappings) {
                    if (oldExceptionHandlerMapping.exceptionType == exceptionHandler.ExceptionType
                        && oldExceptionHandlerMapping.handlerKind == exceptionHandler.HandlerKind
                        && oldExceptionHandlerMapping.filterStartOffset == exceptionHandler.FilterDecisionStartOffset
                        && oldExceptionHandlerMapping.tryStartOffset == exceptionHandler.TryStartOffset
                        && oldExceptionHandlerMapping.tryEndOffset == exceptionHandler.TryEndOffset
                        && oldExceptionHandlerMapping.handlerStartOffset == exceptionHandler.HandlerStartOffset
                        && oldExceptionHandlerMapping.handlerEndOffset == exceptionHandler.HandlerEndOffset) {
                        oldExceptionHandlerMapping.newExceptionHandler = exceptionHandler;
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    throw new ArgumentException("Not able to map old exception handler to new one.");
                }
            }

            // replace all old exception handler in the basic blocks with the new exception handler
            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                // replace all exception handler in the try blocks
                foreach (TryBlock tryBlock in tempBB.tryBlocks) {
                    foreach (OldExceptionHandlerMapping oldExceptionHandlerMapping in oldExceptionHandlerMappings) {
                        if (tryBlock.exceptionHandler == oldExceptionHandlerMapping.oldExceptionHandler) {
                            tryBlock.exceptionHandler = oldExceptionHandlerMapping.newExceptionHandler;
                            break;
                        }
                    }
                }

                // replace all exception handler in the handler blocks
                foreach (HandlerBlock handlerBlock in tempBB.handlerBlocks) {
                    foreach (OldExceptionHandlerMapping oldExceptionHandlerMapping in oldExceptionHandlerMappings) {
                        if (handlerBlock.exceptionHandler == oldExceptionHandlerMapping.oldExceptionHandler) {
                            handlerBlock.exceptionHandler = oldExceptionHandlerMapping.newExceptionHandler;
                            break;
                        }
                    }
                }
            }

            
            // TODO
            // DEBUG
            /*
            // sanitize method name to store it as a file
            String invalidChars = System.Text.RegularExpressions.Regex.Escape(new string(System.IO.Path.GetInvalidFileNameChars()));
            String invalidRegStr = string.Format(@"([{0}]*\.+$)|([{0}]+)", invalidChars);
            String fileName = System.Text.RegularExpressions.Regex.Replace(methodCfg.method.ToString(), invalidRegStr, "_");
            fileName = fileName.Length >= 230 ? fileName.Substring(0, 230) : fileName;

            // dump cfg created from the exit branches
            System.IO.StreamWriter dotFile = new System.IO.StreamWriter("e:\\" + "\\BBUnion_" + fileName + ".dot");

            // start .dot file graph
            dotFile.WriteLine("digraph G {");

            for (int bbuidx = 0; bbuidx < basicBlockUnions.Count(); bbuidx++) {
                BasicBlockUnion basicBlockUnion = basicBlockUnions.ElementAt(bbuidx);
                    // write all basic blocks to .dot file
                    for (int idx = 0; idx < basicBlockUnion.basicBlocks.Count(); idx++) {

                        BasicBlock currentBasicBlock = basicBlockUnion.basicBlocks.ElementAt(idx);

                        // write the current basic block to the file and all its instructions
                        dotFile.WriteLine("BB" + bbuidx.ToString() + "_" + idx.ToString() + " [shape=record]");
                        bool first = true;
                        for (int opIdx = 0; opIdx < currentBasicBlock.operations.Count(); opIdx++) {
                            var operation = currentBasicBlock.operations.ElementAt(opIdx);
                            if (first) {
                                dotFile.Write("BB" + bbuidx.ToString() + "_" + idx.ToString() + " [label=\"{");
                                first = false;
                            }
                            else {
                                dotFile.Write("|");
                            }

                            // insert try block beginnings
                            foreach (var tryBlock in currentBasicBlock.tryBlocks) {
                                if (tryBlock.firstBasicBlockOfTryBlock && opIdx == 0) {
                                    dotFile.Write("TRY START (" + tryBlock.exceptionHandler.ExceptionType.ToString() + ")|");
                                }
                            }

                            // insert catch block beginnings
                            foreach (var handlerBlock in currentBasicBlock.handlerBlocks) {
                                if (handlerBlock.firstBasicBlockOfHandlerBlock && opIdx == 0) {
                                    if (handlerBlock.typeOfHandler == HandlerKind.Catch) {
                                        dotFile.Write("CATCH START (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")|");
                                    }
                                    else if (handlerBlock.typeOfHandler == HandlerKind.Finally) {
                                        dotFile.Write("FINALLY START (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")|");
                                    }
                                    else {
                                        throw new ArgumentException("Do not know how to handle handler.");
                                    }
                                }
                            }

                            // check if instruction has an argument
                            if (operation.Value != null) {
                                dotFile.Write(operation.OperationCode.ToString() + " " + operation.Value.ToString());
                            }
                            else {
                                dotFile.Write(operation.OperationCode.ToString());
                            }

                            // insert try block endings
                            foreach (var tryBlock in currentBasicBlock.tryBlocks) {
                                if (tryBlock.lastBasicBlockOfTryBlock && (currentBasicBlock.operations.Count() - 1) == opIdx) {
                                    dotFile.Write("|TRY END (" + tryBlock.exceptionHandler.ExceptionType.ToString() + ")");
                                }
                            }

                            // insert catch block endings
                            foreach (var handlerBlock in currentBasicBlock.handlerBlocks) {
                                if (handlerBlock.lastBasicBlockOfHandlerBlock && (currentBasicBlock.operations.Count() - 1) == opIdx) {
                                    if (handlerBlock.typeOfHandler == HandlerKind.Catch) {
                                        dotFile.Write("|CATCH END (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")");
                                    }
                                    else if (handlerBlock.typeOfHandler == HandlerKind.Finally) {
                                        dotFile.Write("|FINALLY END (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")");
                                    }
                                    else {
                                        throw new ArgumentException("Do not know how to handle handler.");
                                    }
                                }
                            }
                        }
                        dotFile.WriteLine("}\"]");


                        if ((idx + 1) < basicBlockUnion.basicBlocks.Count()) {
                            dotFile.WriteLine("BB" + bbuidx.ToString() + "_" + idx.ToString() + " -> BB" + bbuidx.ToString() + "_" + (idx + 1).ToString() + "[ color=\"blue\" ]");
                        }

                    }
                }


            // finish graph
            dotFile.WriteLine("}");

            dotFile.Close();
            */
        }
        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;
        }
        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;
        }
Ejemplo n.º 13
0
        // 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;
        }
Ejemplo n.º 14
0
        // this function creates all methods that are needed for the generated graph
        public void createGraphMethods() {

            this.logger.writeLine("Adding graph methods to \"" + this.targetClass.ToString() + "\"");

            // check if the graph is already initialized (needed to create the methods)
            if (this.graph == null) {
                throw new ArgumentException("Graph is not initialized.");
            }

            // if debugging is activated
            // => add field for the basic block trace file
            if (this.debugging
                || this.trace) {

                this.logger.writeLine("Debugging activated: Adding field for a basic block tracer file");

                // add trace writer field
                this.debuggingTraceWriter = new FieldDefinition();
                this.debuggingTraceWriter.IsCompileTimeConstant = false;
                this.debuggingTraceWriter.IsNotSerialized = false;
                this.debuggingTraceWriter.IsReadOnly = false;
                this.debuggingTraceWriter.IsRuntimeSpecial = false;
                this.debuggingTraceWriter.IsSpecialName = false;
                this.debuggingTraceWriter.Type = this.helperClass.systemIOStreamWriter;
                this.debuggingTraceWriter.IsStatic = false;
                this.debuggingTraceWriter.Name = host.NameTable.GetNameFor("DEBUG_traceWriter");
                this.debuggingTraceWriter.Visibility = TypeMemberVisibility.Public;
                this.debuggingTraceWriter.InternFactory = host.InternFactory;
                this.debuggingTraceWriter.ContainingTypeDefinition = this.targetClass;
                this.targetClass.Fields.Add(this.debuggingTraceWriter);

            }

            // create a method that can be called to generate the graph
            this.buildGraphMethod = this.helperClass.createNewMethod("buildGraph", this.targetClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, null, CallingConvention.HasThis, false, false, true); // TODO RENAME

            ILGenerator ilGenerator = new ILGenerator(host, this.buildGraphMethod);

            // check if graph was already build
            // => if it was jump to exit
            ILGeneratorLabel buildGraphExitLabel = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerGet);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brfalse, buildGraphExitLabel);
            
            // set initial node (root of the tree)
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldarg_0); // needed as argument for the constructor
            ilGenerator.Emit(OperationCode.Newobj, this.graph.startingNode.constructorToUse);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerSet);

            // build rest of graph in a "pseudo recursive" manner
            MethodDefinition newMethodToCall = this.addNodeRecursively(this.graph.startingNode, 1, "addNode_0"); // TODO: method name
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerGet);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Callvirt, newMethodToCall);

            // exit
            ilGenerator.MarkLabel(buildGraphExitLabel);
            ilGenerator.Emit(OperationCode.Ret);

            // create body
            IMethodBody body = new ILGeneratorMethodBody(ilGenerator, true, 8, this.buildGraphMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty);
            this.buildGraphMethod.Body = body;

            // create exchangeNodes method
            List<IParameterDefinition> parameters = new List<IParameterDefinition>();
            // node type parameter
            ParameterDefinition parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = this.nodeInterface;
            parameters.Add(parameter);
            // int array parameter for path to node one
            VectorTypeReference intArrayType = new VectorTypeReference();
            intArrayType.ElementType = this.host.PlatformType.SystemInt32;
            intArrayType.Rank = 1;
            intArrayType.IsFrozen = true;
            intArrayType.IsValueType = false;
            intArrayType.InternFactory = host.InternFactory;
            parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = intArrayType;
            parameters.Add(parameter);
            // int array parameter for path to node two
            parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = intArrayType;
            parameters.Add(parameter);

            this.exchangeNodesMethod = this.helperClass.createNewMethod("exchangeNodes", this.targetClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO RENAME

            ilGenerator = new ILGenerator(host, this.exchangeNodesMethod);
            List<ILocalDefinition> localVariables = new List<ILocalDefinition>();

            // create local integer variable needed for the loops
            LocalDefinition loopIntLocal = new LocalDefinition();
            loopIntLocal.IsReference = false;
            loopIntLocal.IsPinned = false;
            loopIntLocal.IsModified = false;
            loopIntLocal.Type = this.host.PlatformType.SystemInt32;
            loopIntLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(loopIntLocal);

            // create local iNode variable needed for nodeOne
            LocalDefinition nodeOneLocal = new LocalDefinition();
            nodeOneLocal.IsReference = false;
            nodeOneLocal.IsPinned = false;
            nodeOneLocal.IsModified = false;
            nodeOneLocal.Type = this.nodeInterface;
            nodeOneLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(nodeOneLocal);

            // create local iNode variable needed for prevNodeOne
            LocalDefinition prevNodeOneLocal = new LocalDefinition();
            prevNodeOneLocal.IsReference = false;
            prevNodeOneLocal.IsPinned = false;
            prevNodeOneLocal.IsModified = false;
            prevNodeOneLocal.Type = this.nodeInterface;
            prevNodeOneLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(prevNodeOneLocal);

            // create local integer variable needed for prevNodeOneIdx
            LocalDefinition prevNodeOneIdxLocal = new LocalDefinition();
            prevNodeOneIdxLocal.IsReference = false;
            prevNodeOneIdxLocal.IsPinned = false;
            prevNodeOneIdxLocal.IsModified = false;
            prevNodeOneIdxLocal.Type = this.host.PlatformType.SystemInt32;
            prevNodeOneIdxLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(prevNodeOneIdxLocal);

            // create local iNode variable needed for nodeTwo
            LocalDefinition nodeTwoLocal = new LocalDefinition();
            nodeTwoLocal.IsReference = false;
            nodeTwoLocal.IsPinned = false;
            nodeTwoLocal.IsModified = false;
            nodeTwoLocal.Type = this.nodeInterface;
            nodeTwoLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(nodeTwoLocal);

            // create local iNode variable needed for prevNodeOne
            LocalDefinition prevNodeTwoLocal = new LocalDefinition();
            prevNodeTwoLocal.IsReference = false;
            prevNodeTwoLocal.IsPinned = false;
            prevNodeTwoLocal.IsModified = false;
            prevNodeTwoLocal.Type = this.nodeInterface;
            prevNodeTwoLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(prevNodeTwoLocal);

            // create local integer variable needed for prevNodeOneIdx
            LocalDefinition prevNodeTwoIdxLocal = new LocalDefinition();
            prevNodeTwoIdxLocal.IsReference = false;
            prevNodeTwoIdxLocal.IsPinned = false;
            prevNodeTwoIdxLocal.IsModified = false;
            prevNodeTwoIdxLocal.Type = this.host.PlatformType.SystemInt32;
            prevNodeTwoIdxLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(prevNodeTwoIdxLocal);

            // create local iNode variable needed for temp
            LocalDefinition tempNodeLocal = new LocalDefinition();
            tempNodeLocal.IsReference = false;
            tempNodeLocal.IsPinned = false;
            tempNodeLocal.IsModified = false;
            tempNodeLocal.Type = this.nodeInterface;
            tempNodeLocal.MethodDefinition = this.exchangeNodesMethod;
            localVariables.Add(tempNodeLocal);

            // initialize local variables
            /*
            iNode nodeOne = givenStartingNode;
            iNode prevNodeOne = null;
            int prevNodeOneIdx = 0;
            */
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Stloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeOneIdxLocal);

            // initialize loop
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stloc, loopIntLocal);
            ILGeneratorLabel loopConditionAndIncBranch = new ILGeneratorLabel();
            ILGeneratorLabel loopConditionBranch = new ILGeneratorLabel();
            ILGeneratorLabel loopStartBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Br, loopConditionBranch);

            // start of the code in the loop
            /*
            if (nodeOne.getNode(pathToNodeOne[i]) != null) {
            */
            ilGenerator.MarkLabel(loopStartBranch);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldarg_2);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldelem_I4);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brtrue, loopConditionAndIncBranch);

            // get the node of the graph that should be exchanged (nodeOne)
            /*
            prevNodeOne = nodeOne;
            prevNodeOneIdx = pathToNodeOne[i];
            nodeOne = nodeOne.getNode(pathToNodeOne[i]);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldarg_2);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldelem_I4);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeOneIdxLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeOneIdxLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Stloc, nodeOneLocal);

            // increment counter of loop
            ilGenerator.MarkLabel(loopConditionAndIncBranch);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Add);
            ilGenerator.Emit(OperationCode.Stloc, loopIntLocal);

            // loop condition
            /*
            for (int i = 0; i < pathToNodeOne.Length; i++) {
            */
            ilGenerator.MarkLabel(loopConditionBranch);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldarg_2);
            ilGenerator.Emit(OperationCode.Ldlen);
            ilGenerator.Emit(OperationCode.Conv_I4);
            ilGenerator.Emit(OperationCode.Clt);
            ilGenerator.Emit(OperationCode.Brtrue, loopStartBranch);

            // initialize local variables
            /*
            iNode nodeTwo = givenStartingNode;
            iNode prevNodeTwo = null;
            int prevNodeTwoIdx = 0;
            */
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Stloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeTwoIdxLocal);

            // initialize loop
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stloc, loopIntLocal);
            loopConditionAndIncBranch = new ILGeneratorLabel();
            loopConditionBranch = new ILGeneratorLabel();
            loopStartBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Br, loopConditionBranch);

            // start of the code in the loop
            /*
            if (nodeTwo.getNode(pathToNodeTwo[i]) != null) {
            */
            ilGenerator.MarkLabel(loopStartBranch);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldarg_3);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldelem_I4);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brtrue, loopConditionAndIncBranch);

            // get the node of the graph that should be exchanged (nodeTwo)
            /*
            prevNodeTwo = nodeTwo;
            prevNodeTwoIdx = pathToNodeTwo[i];
            nodeTwo = nodeTwo.getNode(pathToNodeTwo[i]);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldarg_2);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldelem_I4);
            ilGenerator.Emit(OperationCode.Stloc, prevNodeTwoIdxLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeTwoIdxLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Stloc, nodeTwoLocal);

            // increment counter of loop
            ilGenerator.MarkLabel(loopConditionAndIncBranch);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Add);
            ilGenerator.Emit(OperationCode.Stloc, loopIntLocal);

            // loop condition
            /*
            for (int i = 0; i < pathToNodeTwo.Length; i++) {
            */
            ilGenerator.MarkLabel(loopConditionBranch);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldarg_3);
            ilGenerator.Emit(OperationCode.Ldlen);
            ilGenerator.Emit(OperationCode.Conv_I4);
            ilGenerator.Emit(OperationCode.Clt);
            ilGenerator.Emit(OperationCode.Brtrue, loopStartBranch);

            // initialize loop
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Stloc, loopIntLocal);
            loopConditionAndIncBranch = new ILGeneratorLabel();
            loopConditionBranch = new ILGeneratorLabel();
            loopStartBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Br, loopConditionBranch);

            // start of the code in the loop
            ilGenerator.MarkLabel(loopStartBranch);

            /*
            if (nodeOne.getNode(i) == nodeTwo) {
            */
            ILGeneratorLabel conditionBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brfalse, conditionBranch);

            /*
            nodeOne.setNode(nodeTwo.getNode(i), i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);

            /*
            nodeTwo.setNode(nodeOne, i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);
            ilGenerator.Emit(OperationCode.Br, loopConditionAndIncBranch);

            /*
            else if (nodeTwo.getNode(i) == nodeOne) {
            */
            ilGenerator.MarkLabel(conditionBranch);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ceq);
            conditionBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Brfalse, conditionBranch);

            /*
            nodeTwo.setNode(nodeOne.getNode(i), i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);

            /*
            nodeOne.setNode(nodeTwo, i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);
            ilGenerator.Emit(OperationCode.Br, loopConditionAndIncBranch);

            /*
            else {
            */
            ilGenerator.MarkLabel(conditionBranch);

            /*
            temp = nodeOne.getNode(i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Stloc, tempNodeLocal);

            /*
            nodeOne.setNode(nodeTwo.getNode(i), i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);

            /*
            nodeTwo.setNode(temp, i);
            */
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, tempNodeLocal);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);

            // increment counter of loop
            ilGenerator.MarkLabel(loopConditionAndIncBranch);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldc_I4_1);
            ilGenerator.Emit(OperationCode.Add);
            ilGenerator.Emit(OperationCode.Stloc, loopIntLocal);

            // loop condition
            /*
            for (int i = 0; i < GRAPH_DIMENSION; i++) {
            */
            ilGenerator.MarkLabel(loopConditionBranch);
            ilGenerator.Emit(OperationCode.Ldloc, loopIntLocal);
            ilGenerator.Emit(OperationCode.Ldc_I4, this.graphDimension);
            ilGenerator.Emit(OperationCode.Clt);
            ilGenerator.Emit(OperationCode.Brtrue, loopStartBranch);

            /*
            if (prevNodeOne != null) {
            */
            conditionBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brtrue, conditionBranch);

            /*
            if (prevNodeOne != nodeTwo) {
            */
            ILGeneratorLabel exitConditionBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brtrue, exitConditionBranch);

            /*
            prevNodeOne.setNode(nodeTwo, prevNodeOneIdx);
            */
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeOneIdxLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);
            ilGenerator.Emit(OperationCode.Br, exitConditionBranch);

            /*
            else {
            */
            ilGenerator.MarkLabel(conditionBranch);

            /*
            this.graphStartNode = nodeTwo;
            */
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldloc, nodeTwoLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerSet);

            ilGenerator.MarkLabel(exitConditionBranch);

            /*
            if (prevNodeTwo != null) {
            */
            conditionBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldnull);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brtrue, conditionBranch);

            /*
            if (prevNodeTwo != nodeOne) {
            */
            exitConditionBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Brtrue, exitConditionBranch);

            /*
            prevNodeTwo.setNode(nodeOne, prevNodeTwoIdx);
            */
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeTwoLocal);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Ldloc, prevNodeTwoIdxLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);
            ilGenerator.Emit(OperationCode.Br, exitConditionBranch);

            /*
            else {
            */
            ilGenerator.MarkLabel(conditionBranch);

            /*
            this.graphStartNode = nodeOne;
            */
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldloc, nodeOneLocal);
            ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerSet);

            ilGenerator.MarkLabel(exitConditionBranch);
            ilGenerator.Emit(OperationCode.Ret);

            // create body
            body = new ILGeneratorMethodBody(ilGenerator, true, 8, this.exchangeNodesMethod, localVariables, Enumerable<ITypeDefinition>.Empty);
            this.exchangeNodesMethod.Body = body;

            // check if debugging is activated
            // => add function to dump graph as .dot file
            if (this.debugging) {

                this.logger.writeLine("Debugging activated: Adding code to dump graph as .dot file");

                // create dumpGraph method
                parameters = new List<IParameterDefinition>();
                // string parameter
                parameter = new ParameterDefinition();
                parameter.IsIn = false;
                parameter.IsOptional = false;
                parameter.IsOut = false;
                parameter.Type = this.host.PlatformType.SystemString;
                parameter.Index = 0;
                parameters.Add(parameter);
                // node type parameter (current pointer of debug method)
                parameter = new ParameterDefinition();
                parameter.IsIn = false;
                parameter.IsOptional = false;
                parameter.IsOut = false;
                parameter.Type = this.nodeInterface;
                parameter.Index = 1;
                parameters.Add(parameter);
                // node type parameter (current pointer of caller)
                parameter = new ParameterDefinition();
                parameter.IsIn = false;
                parameter.IsOptional = false;
                parameter.IsOut = false;
                parameter.Type = this.nodeInterface;
                parameter.Index = 2;
                parameters.Add(parameter);

                this.debuggingDumpGraphMethod = this.helperClass.createNewMethod("DEBUG_dumpGraph", this.targetClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true);

                // create dumpGraphRec method
                parameters = new List<IParameterDefinition>();
                // stream writer parameter
                parameter = new ParameterDefinition();
                parameter.IsIn = false;
                parameter.IsOptional = false;
                parameter.IsOut = false;
                parameter.Type = this.helperClass.systemIOStreamWriter;
                parameter.Index = 0;
                parameters.Add(parameter);
                // string parameter
                parameter = new ParameterDefinition();
                parameter.IsIn = false;
                parameter.IsOptional = false;
                parameter.IsOut = false;
                parameter.Type = this.host.PlatformType.SystemString;
                parameter.Index = 1;
                parameters.Add(parameter);
                // node type parameter (current pointer of debug method)
                parameter = new ParameterDefinition();
                parameter.IsIn = false;
                parameter.IsOptional = false;
                parameter.IsOut = false;
                parameter.Type = this.nodeInterface;
                parameter.Index = 2;
                parameters.Add(parameter);
                // node type parameter (current pointer of caller)
                ParameterDefinition currentNodeCallerParameter = new ParameterDefinition();
                currentNodeCallerParameter.IsIn = false;
                currentNodeCallerParameter.IsOptional = false;
                currentNodeCallerParameter.IsOut = false;
                currentNodeCallerParameter.Type = this.nodeInterface;
                currentNodeCallerParameter.Index = 3;
                parameters.Add(currentNodeCallerParameter);

                MethodDefinition dumpGraphRecMethod = this.helperClass.createNewMethod("DEBUG_dumpGraphRec", this.targetClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true);
                currentNodeCallerParameter.ContainingSignature = dumpGraphRecMethod; // is needed when parameter is accessed via Ldarg

                // create body for dumpGraph method
                ilGenerator = new ILGenerator(host, this.debuggingDumpGraphMethod);
                localVariables = new List<ILocalDefinition>();

                // create local string variable needed for debugging code
                LocalDefinition nodeNameLocal = new LocalDefinition();
                nodeNameLocal.IsReference = false;
                nodeNameLocal.IsPinned = false;
                nodeNameLocal.IsModified = false;
                nodeNameLocal.Type = this.host.PlatformType.SystemString;
                nodeNameLocal.MethodDefinition = this.debuggingDumpGraphMethod;
                localVariables.Add(nodeNameLocal);

                // create local stream writer variable needed for debugging code
                LocalDefinition streamWriterLocal = new LocalDefinition();
                streamWriterLocal.IsReference = false;
                streamWriterLocal.IsPinned = false;
                streamWriterLocal.IsModified = false;
                streamWriterLocal.Type = this.helperClass.systemIOStreamWriter;
                streamWriterLocal.MethodDefinition = this.debuggingDumpGraphMethod;
                localVariables.Add(streamWriterLocal);

                // create local integer variable for the for loop needed for debugging code
                LocalDefinition forIntegerLocal = new LocalDefinition();
                forIntegerLocal.IsReference = false;
                forIntegerLocal.IsPinned = false;
                forIntegerLocal.IsModified = false;
                forIntegerLocal.Type = this.host.PlatformType.SystemInt32;
                forIntegerLocal.MethodDefinition = this.debuggingDumpGraphMethod;
                localVariables.Add(forIntegerLocal);

                // generate dump file location string
                ilGenerator.Emit(OperationCode.Ldstr, this.debuggingDumpLocation + this.debuggingDumpFilePrefix);
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldstr, ".dot");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // initialize io stream writer
                ilGenerator.Emit(OperationCode.Newobj, this.helperClass.streamWriterCtor);
                ilGenerator.Emit(OperationCode.Stloc, streamWriterLocal);

                // initialize .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "digraph G {");
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // check if the node to dump is the same as the current node of the class
                // if it is => color the current dumped node
                ilGenerator.Emit(OperationCode.Ldarg_3);
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ceq);
                ILGeneratorLabel currentNodeEqualDumpedNodeBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Brtrue, currentNodeEqualDumpedNodeBranch);

                // case: current dumped node is not the current node of the class
                // create name for the nodes
                ilGenerator.Emit(OperationCode.Ldstr, "node_0");
                ilGenerator.Emit(OperationCode.Stloc, nodeNameLocal);

                // write current node to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Ldstr, " [shape=record]");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // jump to the end of this case
                ILGeneratorLabel currentNodeDumpedBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Br, currentNodeDumpedBranch);

                // case: current dumped node is the current node of the class
                ilGenerator.MarkLabel(currentNodeEqualDumpedNodeBranch);

                // create name for the nodes
                ilGenerator.Emit(OperationCode.Ldstr, "node_0");
                ilGenerator.Emit(OperationCode.Stloc, nodeNameLocal);

                // write current node to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Ldstr, " [shape=record, color=blue]");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // end of the case
                ilGenerator.MarkLabel(currentNodeDumpedBranch);

                // write start of label of the current node to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Ldstr, " [label=\"{");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWrite);

                // write current node name to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "Node: ");
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "|");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWrite);

                // write current node id to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "Id: ");
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Callvirt, this.debuggingInterfaceIdGet);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWrite);

                // write end of label of the current node to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "}\"]");
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // initialize counter of for loop
                ilGenerator.Emit(OperationCode.Ldc_I4_0);
                ilGenerator.Emit(OperationCode.Stloc, forIntegerLocal);

                // jump to loop condition
                loopConditionBranch = new ILGeneratorLabel();
                loopStartBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Br, loopConditionBranch);

                // start of loop
                ilGenerator.MarkLabel(loopStartBranch);

                // check if childNodes[i] == startNode
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
                ilGenerator.Emit(OperationCode.Ldarg_0);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerGet);
                ilGenerator.Emit(OperationCode.Ceq);
                loopConditionAndIncBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Brtrue, loopConditionAndIncBranch);

                // write connection of current node to next node to .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);

                // generate first part of the string
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Ldstr, " -> ");
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // generate second part of string and concat to first part
                ilGenerator.Emit(OperationCode.Ldstr, "_");
                ilGenerator.Emit(OperationCode.Ldloca, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.int32ToString);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // write to .dot file
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // call method that dumps graph recursively ( this.dumpGraphRec(streamWriter, String name, nextNode) )
                ilGenerator.Emit(OperationCode.Ldarg_0);

                // push stream writer parameter
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);

                // push string parameter
                ilGenerator.Emit(OperationCode.Ldloc, nodeNameLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "_");
                ilGenerator.Emit(OperationCode.Ldloca, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.int32ToString);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // push node parameter (current pointer of debug method)
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);

                // push node parameter (current pointer of the caller)
                ilGenerator.Emit(OperationCode.Ldarg_3);

                ilGenerator.Emit(OperationCode.Callvirt, dumpGraphRecMethod);

                // increment loop counter
                ilGenerator.MarkLabel(loopConditionAndIncBranch);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Ldc_I4_1);
                ilGenerator.Emit(OperationCode.Add);
                ilGenerator.Emit(OperationCode.Stloc, forIntegerLocal);

                // loop condition
                ilGenerator.MarkLabel(loopConditionBranch);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Ldc_I4, this.graphDimension);
                ilGenerator.Emit(OperationCode.Clt);
                ilGenerator.Emit(OperationCode.Brtrue, loopStartBranch);

                // end .dot file
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Ldstr, "}");
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // close io stream writer                
                ilGenerator.Emit(OperationCode.Ldloc, streamWriterLocal);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterClose);

                ilGenerator.Emit(OperationCode.Ret);

                // create body
                body = new ILGeneratorMethodBody(ilGenerator, true, 8, this.debuggingDumpGraphMethod, localVariables, Enumerable<ITypeDefinition>.Empty);
                this.debuggingDumpGraphMethod.Body = body;

                // create body for dumpGraphRec method
                localVariables = new List<ILocalDefinition>();
                ilGenerator = new ILGenerator(host, dumpGraphRecMethod);

                // create local integer variable for the for loop needed for debugging code
                forIntegerLocal = new LocalDefinition();
                forIntegerLocal.IsReference = false;
                forIntegerLocal.IsPinned = false;
                forIntegerLocal.IsModified = false;
                forIntegerLocal.Type = this.host.PlatformType.SystemInt32;
                forIntegerLocal.MethodDefinition = dumpGraphRecMethod;
                localVariables.Add(forIntegerLocal);

                // check if the node to dump is the same as the current node of the class
                // if it is => color the current dumped node
                ilGenerator.Emit(OperationCode.Ldarg, currentNodeCallerParameter);
                ilGenerator.Emit(OperationCode.Ldarg_3);
                ilGenerator.Emit(OperationCode.Ceq);
                currentNodeEqualDumpedNodeBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Brtrue, currentNodeEqualDumpedNodeBranch);

                // case: current dumped node is not the current node of the class
                // write current node to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldstr, " [shape=record]");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // jump to the end of this case
                currentNodeDumpedBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Br, currentNodeDumpedBranch);

                // case: current dumped node is the current node of the class
                ilGenerator.MarkLabel(currentNodeEqualDumpedNodeBranch);

                // write current node to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldstr, " [shape=record, color=blue]");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // end of the case
                ilGenerator.MarkLabel(currentNodeDumpedBranch);

                // write start of label of the current node to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldstr, " [label=\"{");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWrite);

                // write current node name to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldstr, "Node: ");
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldstr, "|");
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWrite);

                // write current node id to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldstr, "Id: ");
                ilGenerator.Emit(OperationCode.Ldarg_3);
                ilGenerator.Emit(OperationCode.Callvirt, this.debuggingInterfaceIdGet);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatTwo);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWrite);

                // write end of label of the current node to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldstr, "}\"]");
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // initialize counter of for loop
                ilGenerator.Emit(OperationCode.Ldc_I4_0);
                ilGenerator.Emit(OperationCode.Stloc, forIntegerLocal);

                // jump to loop condition
                loopConditionBranch = new ILGeneratorLabel();
                loopStartBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Br, loopConditionBranch);

                // start of loop
                ilGenerator.MarkLabel(loopStartBranch);

                // check if childNodes[i] == startNode
                ilGenerator.Emit(OperationCode.Ldarg_3);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);
                ilGenerator.Emit(OperationCode.Ldarg_0);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerGet);
                ilGenerator.Emit(OperationCode.Ceq);
                loopConditionAndIncBranch = new ILGeneratorLabel();
                ilGenerator.Emit(OperationCode.Brtrue, loopConditionAndIncBranch);

                // write connection of current node to next node to .dot file
                ilGenerator.Emit(OperationCode.Ldarg_1);

                // generate first part of the string
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldstr, " -> ");
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // generate second part of string and concat to first part
                ilGenerator.Emit(OperationCode.Ldstr, "_");
                ilGenerator.Emit(OperationCode.Ldloca, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.int32ToString);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // write to .dot file
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.textWriterWriteLine);

                // call method that dumps graph recursively ( this.dumpGraphRec(streamWriter, String name, nextNode) )
                ilGenerator.Emit(OperationCode.Ldarg_0);

                // push stream writer parameter
                ilGenerator.Emit(OperationCode.Ldarg_1);

                // push string parameter
                ilGenerator.Emit(OperationCode.Ldarg_2);
                ilGenerator.Emit(OperationCode.Ldstr, "_");
                ilGenerator.Emit(OperationCode.Ldloca, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.int32ToString);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.stringConcatThree);

                // push node parameter (current pointer of debug method)
                ilGenerator.Emit(OperationCode.Ldarg_3);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);

                // push node parameter (current pointer of the caller)
                ilGenerator.Emit(OperationCode.Ldarg, currentNodeCallerParameter);

                ilGenerator.Emit(OperationCode.Callvirt, dumpGraphRecMethod);

                // increment loop counter
                ilGenerator.MarkLabel(loopConditionAndIncBranch);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Ldc_I4_1);
                ilGenerator.Emit(OperationCode.Add);
                ilGenerator.Emit(OperationCode.Stloc, forIntegerLocal);

                // loop condition
                ilGenerator.MarkLabel(loopConditionBranch);
                ilGenerator.Emit(OperationCode.Ldloc, forIntegerLocal);
                ilGenerator.Emit(OperationCode.Ldc_I4, this.graphDimension);
                ilGenerator.Emit(OperationCode.Clt);
                ilGenerator.Emit(OperationCode.Brtrue, loopStartBranch);

                ilGenerator.Emit(OperationCode.Ret);

                // create body
                body = new ILGeneratorMethodBody(ilGenerator, true, 8, dumpGraphRecMethod, localVariables, Enumerable<ITypeDefinition>.Empty);
                dumpGraphRecMethod.Body = body;

            }

            // inject code to build the graph to all constructors (except the artificial added ctor for a graph node)
            foreach (MethodDefinition ctorMethod in this.targetClass.Methods) {

                // only process constructors
                if (!ctorMethod.IsConstructor) {
                    continue;
                }

                // skip the artificial added ctor with the node interface as parameter
                bool skip = false;
                if (ctorMethod.Parameters != null) {
                    foreach (IParameterDefinition ctorParameter in ctorMethod.Parameters) {
                        if (ctorParameter.Type == this.nodeInterface) {
                            skip = true;
                            break;
                        }
                    }
                }
                if (skip) {
                    continue;
                }

                this.logger.writeLine("Injecting code to build graph to \"" + this.logger.makeFuncSigString(ctorMethod) + "\"");

                MethodCfg ctorMethodCfg = this.cfgBuilder.buildCfgForMethod(ctorMethod);

                // create new basic block that builds the graph
                // (will be the new starting basic block of the method)
                BasicBlock startBasicBlock = new BasicBlock();
                startBasicBlock.startIdx = 0;
                startBasicBlock.endIdx = 0;

                startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.buildGraphMethod));

                if (this.debugging) {

                    // dump generated graph
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, this.debuggingNumber.ToString().PadLeft(3, '0') + "_obfu_" + this.logger.makeFuncSigString(ctorMethodCfg.method)));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceStartPointerGet));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceStartPointerGet));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.debuggingDumpGraphMethod));

                }

                // create exit branch for the new start basic block
                NoBranchTarget startExitBranch = new NoBranchTarget();
                startExitBranch.sourceBasicBlock = startBasicBlock;
                startBasicBlock.exitBranch = startExitBranch;

                // set the original start basic block as the target of the exit branch
                startExitBranch.takenTarget = ctorMethodCfg.startBasicBlock;
                ctorMethodCfg.startBasicBlock.entryBranches.Add(startExitBranch);

                // set new start basic block as start basic block of the method cfg
                ctorMethodCfg.startBasicBlock = startBasicBlock;
                ctorMethodCfg.basicBlocks.Add(startBasicBlock);

                this.cfgBuilder.createMethodFromCfg(ctorMethodCfg);

            }

        }
Ejemplo n.º 15
0
        // this function adds the created iNode interface to the class and also implements all neded functions
        public void addNodeInterfaceToTargetClass(NamespaceTypeDefinition givenClass) {

            this.logger.writeLine("");
            this.logger.writeLine("Add node interface \"" + this.nodeInterface.ToString() + "\" to class \"" + givenClass.ToString() + "\"");

            // check if generated interface was already added to target class
            if (givenClass.Interfaces != null
                && givenClass.Interfaces.Contains(this.nodeInterface)) {
                this.logger.writeLine("Class \"" + givenClass.ToString() + "\" already contains node interface \"" + this.nodeInterface.ToString() + "\"");
                return;
            }

            // add nodes interface to class
            if (givenClass.Interfaces != null) {
                givenClass.Interfaces.Add(this.nodeInterface);
            }
            else {
                givenClass.Interfaces = new List<ITypeReference>();
                givenClass.Interfaces.Add(this.nodeInterface);
            }

            // add start pointer field
            FieldDefinition startPointerField = new FieldDefinition();
            startPointerField.IsCompileTimeConstant = false;
            startPointerField.IsNotSerialized = false;
            startPointerField.IsReadOnly = false;
            startPointerField.IsRuntimeSpecial = false;
            startPointerField.IsSpecialName = false;
            startPointerField.Type = this.nodeInterface;
            startPointerField.IsStatic = false;
            startPointerField.Visibility = TypeMemberVisibility.Public;
            startPointerField.Name = host.NameTable.GetNameFor("startPointer");
            startPointerField.InternFactory = host.InternFactory;
            startPointerField.ContainingTypeDefinition = givenClass;
            if (givenClass.Fields != null) {
                givenClass.Fields.Add(startPointerField);
            }
            else {
                givenClass.Fields = new List<IFieldDefinition>();
                givenClass.Fields.Add(startPointerField);
            }

            // create getter for the startPointer variable
            MethodDefinition startPointerGetMethod = this.helperClass.createNewMethod("startPointer_get", givenClass, this.nodeInterface, TypeMemberVisibility.Public, null, CallingConvention.HasThis, false, false, true); // TODO: method name

            // create a body for the getter method
            ILGenerator ilGenerator = new ILGenerator(host, startPointerGetMethod);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldfld, startPointerField);
            ilGenerator.Emit(OperationCode.Ret);
            IMethodBody body = new ILGeneratorMethodBody(ilGenerator, true, 1, startPointerGetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty);
            startPointerGetMethod.Body = body;

            // create setter for the startPointer variable
            List<IParameterDefinition> parameters = new List<IParameterDefinition>();
            ParameterDefinition parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Name = host.NameTable.GetNameFor("value");
            parameter.Type = this.nodeInterface;
            parameters.Add(parameter);
            MethodDefinition startPointerSetMethod = this.helperClass.createNewMethod("startPointer_set", givenClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name

            // create a body for the setter method
            ilGenerator = new ILGenerator(host, startPointerSetMethod);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Stfld, startPointerField);
            ilGenerator.Emit(OperationCode.Ret);
            body = new ILGeneratorMethodBody(ilGenerator, true, 1, startPointerSetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty);
            startPointerSetMethod.Body = body;

            // add childNodes array field
            FieldDefinition childNodesField = new FieldDefinition();
            childNodesField.IsCompileTimeConstant = false;
            childNodesField.IsNotSerialized = false;
            childNodesField.IsReadOnly = false;
            childNodesField.IsRuntimeSpecial = false;
            childNodesField.IsSpecialName = false;
            // create array of node interface type
            VectorTypeReference nodeInterfaceArrayType = new VectorTypeReference();
            nodeInterfaceArrayType.ElementType = this.nodeInterface;
            nodeInterfaceArrayType.Rank = 1;
            nodeInterfaceArrayType.IsFrozen = true;
            nodeInterfaceArrayType.IsValueType = false;
            nodeInterfaceArrayType.InternFactory = host.InternFactory;
            childNodesField.Type = nodeInterfaceArrayType;

            childNodesField.IsStatic = false;
            childNodesField.Visibility = TypeMemberVisibility.Public;
            childNodesField.Name = host.NameTable.GetNameFor("childNodes");
            childNodesField.InternFactory = host.InternFactory;
            childNodesField.ContainingTypeDefinition = givenClass;
            givenClass.Fields.Add(childNodesField);

            // create getter for the childNodes variable
            parameters = new List<IParameterDefinition>();
            // int parameter
            parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = this.host.PlatformType.SystemInt32;
            parameters.Add(parameter);
            MethodDefinition childNodesGetMethod = this.helperClass.createNewMethod("childNodes_get", givenClass, this.nodeInterface, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name

            // create a body for the getter method
            ilGenerator = new ILGenerator(host, childNodesGetMethod);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldfld, childNodesField);
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Ldelem_Ref);
            ilGenerator.Emit(OperationCode.Ret);
            body = new ILGeneratorMethodBody(ilGenerator, true, 1, childNodesGetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty);
            childNodesGetMethod.Body = body;

            // create setter for the childNodes variable
            parameters = new List<IParameterDefinition>();
            // iNode parameter
            parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = this.nodeInterface;
            parameters.Add(parameter);
            // int parameter
            parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = this.host.PlatformType.SystemInt32;
            parameters.Add(parameter);
            MethodDefinition childNodesSetMethod = this.helperClass.createNewMethod("childNodes_set", givenClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name

            // create a body for the setter method
            ilGenerator = new ILGenerator(host, childNodesSetMethod);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldfld, childNodesField);
            ilGenerator.Emit(OperationCode.Ldarg_2);
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Stelem_Ref);
            ilGenerator.Emit(OperationCode.Ret);
            body = new ILGeneratorMethodBody(ilGenerator, true, 1, childNodesSetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty);
            childNodesSetMethod.Body = body;

            // add current node field
            FieldDefinition currentNodeField = new FieldDefinition();
            currentNodeField.IsCompileTimeConstant = false;
            currentNodeField.IsNotSerialized = false;
            currentNodeField.IsReadOnly = false;
            currentNodeField.IsRuntimeSpecial = false;
            currentNodeField.IsSpecialName = false;
            currentNodeField.Type = this.nodeInterface;
            currentNodeField.IsStatic = false;
            currentNodeField.Visibility = TypeMemberVisibility.Public;
            currentNodeField.Name = host.NameTable.GetNameFor("currentNode");
            currentNodeField.InternFactory = host.InternFactory;
            currentNodeField.ContainingTypeDefinition = givenClass;
            givenClass.Fields.Add(currentNodeField);

            // create getter for the currentNode variable
            MethodDefinition currentNodeGetMethod = this.helperClass.createNewMethod("currentNode_get", givenClass, this.nodeInterface, TypeMemberVisibility.Public, null, CallingConvention.HasThis, false, false, true); // TODO: method name

            // create a body for the getter method
            ilGenerator = new ILGenerator(host, currentNodeGetMethod);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldfld, currentNodeField);
            ilGenerator.Emit(OperationCode.Ret);
            body = new ILGeneratorMethodBody(ilGenerator, true, 1, currentNodeGetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty);
            currentNodeGetMethod.Body = body;

            // create setter for the currentNode variable
            parameters = new List<IParameterDefinition>();
            parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Name = host.NameTable.GetNameFor("value");
            parameter.Type = this.nodeInterface;
            parameters.Add(parameter);
            MethodDefinition currentNodeSetMethod = this.helperClass.createNewMethod("currentNode_set", givenClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name

            // create a body for the setter method
            ilGenerator = new ILGenerator(host, currentNodeSetMethod);
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldarg_1);
            ilGenerator.Emit(OperationCode.Stfld, currentNodeField);
            ilGenerator.Emit(OperationCode.Ret);
            body = new ILGeneratorMethodBody(ilGenerator, true, 1, currentNodeSetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty);
            currentNodeSetMethod.Body = body;

            // check if debugging is activated
            // => add graph debugging attributes and methods
            MethodDefinition objectIdGetMethod = null;
            FieldDefinition objectIdField = null;
            if (this.debugging) {

                this.logger.writeLine("Debugging activated: Adding field for unique object id and getter method");

                // add objectId field
                objectIdField = new FieldDefinition();
                objectIdField.IsCompileTimeConstant = false;
                objectIdField.IsNotSerialized = false;
                objectIdField.IsReadOnly = false;
                objectIdField.IsRuntimeSpecial = false;
                objectIdField.IsSpecialName = false;
                objectIdField.Type = this.host.PlatformType.SystemString;
                objectIdField.IsStatic = false;
                objectIdField.Name = host.NameTable.GetNameFor("DEBUG_objectId");
                objectIdField.Visibility = TypeMemberVisibility.Public;
                objectIdField.InternFactory = host.InternFactory;
                objectIdField.ContainingTypeDefinition = givenClass;
                givenClass.Fields.Add(objectIdField);

                // create getter for the objectId variable
                objectIdGetMethod = this.helperClass.createNewMethod("DEBUG_objectId_get", givenClass, this.host.PlatformType.SystemString, TypeMemberVisibility.Public, null, CallingConvention.HasThis, false, false, true); // TODO: method name

                // create a body for the getter method
                ilGenerator = new ILGenerator(host, objectIdGetMethod);
                ilGenerator.Emit(OperationCode.Ldarg_0);
                ilGenerator.Emit(OperationCode.Ldfld, objectIdField);
                ilGenerator.Emit(OperationCode.Ret);
                body = new ILGeneratorMethodBody(ilGenerator, true, 1, objectIdGetMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty);
                objectIdGetMethod.Body = body;

            }

            // add .ctor(iNode) to target class
            parameters = new List<IParameterDefinition>();
            parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = this.nodeInterface;
            parameters.Add(parameter);

            MethodDefinition nodeConstructor = this.helperClass.createNewMethod(".ctor", givenClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, false);
            nodeConstructor.IsSpecialName = true;
            nodeConstructor.IsHiddenBySignature = true;
            nodeConstructor.IsRuntimeSpecial = true;

            // generate node constructor body
            ilGenerator = new ILGenerator(host, currentNodeSetMethod);

            // create local variable list
            List<ILocalDefinition> localVariables = new List<ILocalDefinition>();

            // call system.object constructor
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Call, this.helperClass.objectCtor);

            // initialize childNodes array
            ilGenerator.Emit(OperationCode.Ldarg_0);
            ilGenerator.Emit(OperationCode.Ldc_I4, this.graphDimension);
            ilGenerator.Emit(OperationCode.Newarr, nodeInterfaceArrayType);
            ilGenerator.Emit(OperationCode.Stfld, childNodesField);

            // check if debugging is activated
            // => add code to constructor that generates a unique id for this object
            if (this.debugging) {

                this.logger.writeLine("Debugging activated: Adding code to generate unique id to node constructor");

                // create local integer variable needed for debugging code
                LocalDefinition intLocal = new LocalDefinition();
                intLocal.IsReference = false;
                intLocal.IsPinned = false;
                intLocal.IsModified = false;
                intLocal.Type = this.host.PlatformType.SystemInt32;
                intLocal.MethodDefinition = nodeConstructor;
                localVariables.Add(intLocal);

                // use the hash code of this instance as unique object id
                ilGenerator.Emit(OperationCode.Ldarg_0);
                ilGenerator.Emit(OperationCode.Ldarg_0);
                ilGenerator.Emit(OperationCode.Callvirt, this.helperClass.objectGetHashCode);
                ilGenerator.Emit(OperationCode.Stloc, intLocal);

                // cast random integer to string and store in object id
                ilGenerator.Emit(OperationCode.Ldloca, intLocal);
                ilGenerator.Emit(OperationCode.Call, this.helperClass.int32ToString);
                ilGenerator.Emit(OperationCode.Stfld, objectIdField);

            }

            ilGenerator.Emit(OperationCode.Ret);
            body = new ILGeneratorMethodBody(ilGenerator, true, 8, nodeConstructor, localVariables, Enumerable<ITypeDefinition>.Empty);
            nodeConstructor.Body = body;


            // add class to the list of possible nodes for the graph
            PossibleNode tempStruct = new PossibleNode();
            tempStruct.nodeConstructor = nodeConstructor;
            tempStruct.givenClass = givenClass;

            // for each interface the class implements add it to the according list
            foreach (ITypeReference interfaceRef in givenClass.Interfaces) {

                this.logger.writeLine("Add class \"" + givenClass.ToString() + "\" to graph interface list \"" + interfaceRef.ToString() + "\"");

                // check if a list with this interface already exists
                // => if it does just add current class to list
                if (this.graphInterfaces.ContainsKey(interfaceRef)) {
                    List<PossibleNode> tempList = (List<PossibleNode>)this.graphInterfaces[interfaceRef];
                    tempList.Add(tempStruct);
                }
                // if not => add new list for this interface
                else {
                    List<PossibleNode> tempList = new List<PossibleNode>();
                    tempList.Add(tempStruct);
                    this.graphInterfaces.Add(interfaceRef, tempList);
                }
            }

            this.logger.writeLine("");

        }
Ejemplo n.º 16
0
        // this function adds recursively methods that adds the left and the right node to the current node in the graph
        // (and calls the next method that adds the left and right node)
        private MethodDefinition addNodeRecursively(NodeObject currentNode, int currentDepth, String newMethodName) {

            // create first parameter that is the current node in the graph
            List<IParameterDefinition> parameters = new List<IParameterDefinition>();
            ParameterDefinition parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = this.nodeInterface;
            parameters.Add(parameter);

            // create second parameter that is the current depth in the graph
            parameter = new ParameterDefinition();
            parameter.IsIn = false;
            parameter.IsOptional = false;
            parameter.IsOut = false;
            parameter.Type = host.PlatformType.SystemInt32;
            parameters.Add(parameter);

            // create method to add left and right node to the graph
            MethodDefinition newAddNodeMethod = this.helperClass.createNewMethod(newMethodName, this.targetClass, host.PlatformType.SystemVoid, TypeMemberVisibility.Public, parameters, CallingConvention.HasThis, false, false, true); // TODO: method name

            // create body of method
            ILGenerator ilGenerator = new ILGenerator(this.host, newAddNodeMethod);

            // check if max depth of tree is reached
            ilGenerator.Emit(OperationCode.Ldarg_2);
            ilGenerator.Emit(OperationCode.Ldc_I4, this.graph.graphDepth);
            ilGenerator.Emit(OperationCode.Ceq);
            ilGenerator.Emit(OperationCode.Ldc_I4_0);
            ilGenerator.Emit(OperationCode.Ceq);
            ILGeneratorLabel depthReachedBranch = new ILGeneratorLabel();
            ilGenerator.Emit(OperationCode.Brfalse, depthReachedBranch);

            // set child nodes of this node
            MethodDefinition constructorToUse;

            for (int i = 0; i < this.graphDimension; i++) {

                // get constructor of the child node element
                constructorToUse = null;

                // check if the child node exists in the graph and the max depth is not yet reached
                if (currentNode.nodeObjects[i] == null
                    && currentDepth != this.graph.graphDepth) {
                    throw new ArgumentException("Given depth of graph is larger than the actual graph.");
                }
                else {
                    // check if the child node does not exist
                    // => use a random constructor node
                    if (currentNode.nodeObjects[i] == null) {
                        constructorToUse = currentNode.constructorToUse; // TODO: use random node constructor here
                    }
                    // else use constructor of given graph node
                    else {
                        constructorToUse = currentNode.nodeObjects[i].constructorToUse;
                    }
                }

                // set child node
                ilGenerator.Emit(OperationCode.Ldarg_1); // current node from which the function is called
                ilGenerator.Emit(OperationCode.Ldarg_0); // needed as argument for the constructor
                ilGenerator.Emit(OperationCode.Newobj, constructorToUse); // iNode parameter
                ilGenerator.Emit(OperationCode.Ldc_I4, i); // index parameter
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);

                // get child node and set it recursively
                ilGenerator.Emit(OperationCode.Ldarg_0);
                ilGenerator.Emit(OperationCode.Ldarg_1); // current node from which the function is called
                ilGenerator.Emit(OperationCode.Ldc_I4, i); // index parameter
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesGet);

                ilGenerator.Emit(OperationCode.Ldarg_2); // arg2 (current depth) + 1
                ilGenerator.Emit(OperationCode.Ldc_I4_1);
                ilGenerator.Emit(OperationCode.Add);

                MethodDefinition newMethodToCall = null;
                if (currentDepth == this.graph.graphDepth) {
                    newMethodToCall = newAddNodeMethod; // TODO: call random node generation method here
                }
                else {
                    newMethodToCall = this.addNodeRecursively(currentNode.nodeObjects[i], currentDepth + 1, newMethodName + "_" + i.ToString()); // TODO: method name
                }

                ilGenerator.Emit(OperationCode.Callvirt, newMethodToCall);
            }

            ilGenerator.Emit(OperationCode.Ret);

            // set child nodes of this node to null
            ilGenerator.MarkLabel(depthReachedBranch);
            for (int i = 0; i < this.graphDimension; i++) {
                ilGenerator.Emit(OperationCode.Ldarg_1);
                ilGenerator.Emit(OperationCode.Ldarg_0);
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceStartPointerGet); // iNode parameter
                ilGenerator.Emit(OperationCode.Ldc_I4, i); // index parameter
                ilGenerator.Emit(OperationCode.Callvirt, this.interfaceChildNodesSet);
            }
            ilGenerator.Emit(OperationCode.Ret);

            // generate body
            IMethodBody body = new ILGeneratorMethodBody(ilGenerator, true, 8, newAddNodeMethod, Enumerable<ILocalDefinition>.Empty, Enumerable<ITypeDefinition>.Empty);
            newAddNodeMethod.Body = body;

            return newAddNodeMethod;
        }