Пример #1
0
        /// <summary>
        /// Creates <see cref="SequencePointRemapper">SequencePointRemapper</see> - sequence point difference tool for
        /// specified method used in debug state refreshing and local variables definition.
        /// </summary>
        /// <param name="methodDef">Method to which generating takes place.</param>
        /// <returns>Instance of <see cref="SequencePointRemapper">SequencePointRemapper</see>.</returns>
        private SequencePointRemapper genSequencePointRemapper(MethodDefinition methodDefOld, MethodDefinition methodDefNew)
        {
            uint token = methodDefOld.MetadataToken.ToUInt32();

            List <SequencePoint> oldSeqs = SymbolWriterClass.GetMethodSequencePoints(
                Manager.ResourceManager.CurrentModule.SymReader, methodDefOld.MetadataToken.ToUInt32());

            List <SequencePoint> newSeqs = SymbolWriterClass.GetMethodSequencePoints(
                SymbolWriter.CorSymNewReader, methodDefNew.MetadataToken.ToUInt32());

            SequencePointRemapper remapper = new SequencePointRemapper(oldSeqs, newSeqs, Manager.ActualEditEvent.sourceTextChanges[token]);

            SequencePointRemappers.Add(token, remapper);

            return(remapper);
        }
Пример #2
0
        /// <summary>
        /// Change IL code and metadata for property.
        /// </summary>
        /// <param name="property">Interaface with info abour property.</param>
        /// <param name="isGetter">Determines whether it is getter method for property.</param>
        public void ChangeProperty(IProperty property, bool isGetter)
        {
            // Method RVA is offset to start of byte buffer
            uint RVA = (uint)dIL.Count + 4;

            PropertyDefinition targtProp, targtPropOld;
            MethodDefinition   targtMet, targtMetOld;

            // Find appropriete new version of method in new assembly.
            targtProp = Manager.MetadataManager.FindProperty(Manager.ResourceManager.NewAssembly,
                                                             Manager.ResourceManager.NewAssemblyName, property);
            if (targtProp == null)
            {
                new TranslatingException("Property " + property.ToString() + " could not be found in emitted module");
            }

            // Find appropriete original version of method in running assembly.
            targtPropOld = Manager.MetadataManager.FindProperty(Manager.ResourceManager.OldAssembly,
                                                                Manager.ResourceManager.CurrentModule.Name, property);
            if (targtPropOld == null)
            {
                new TranslatingException("Property " + property.ToString() + " could not be found in debugged module");
            }

            targtMet    = (isGetter ? targtProp.GetMethod : targtProp.SetMethod);
            targtMetOld = (isGetter ? targtPropOld.GetMethod : targtPropOld.SetMethod);

            SequencePointRemapper remapper = genSequencePointRemapper(targtMetOld, targtMet);
            // Translate tokens in methods IL code.
            MethodTranslator      translator = new MethodTranslator(this);
            Dictionary <int, int> placeholder;
            MethodDescriptor      log = translator.TranslateMethod(targtMet, targtMetOld, remapper, out placeholder);

            log.newRva = RVA;

            // Set method RVA.
            Manager.MetadataManager.OldEmitter.CorMetaDataEmit.SetRVA(targtMetOld.MetadataToken.ToUInt32(), RVA);

            // Store methods IL to buffer
            dIL.AddRange(log.codeIL);
            if (SymbolWriter != null)
            {
                SymbolWriter.EmitMethod(log.destToken, log.srcToken, placeholder);
            }
        }
Пример #3
0
        /// <summary>
        /// Translate method IL to other metadata scope, with respect to original
        /// method specified by <c>originMethod</c>.
        /// (Registers local structures validly in sense of EnC, used for changing methods bodies by EnC)
        /// </summary>
        /// <param name="newMethod">Definition of the new version of the method.</param>
        /// <param name="originMethod">Definition of the last version of the method.</param>
        /// <param name="remapper">IL offset remapper, used to build local variable changes.</param>
        /// <param name="placeholder">Product of method, represents translation from old variable set to the new one.</param>
        /// <returns>Descriptor of the new version of method in IL.</returns>
        public MethodDescriptor TranslateMethod(MethodDefinition newMethod, MethodDefinition originMethod,
                                                SequencePointRemapper remapper, out Dictionary <int, int> placeholder)
        {
            MethodDescriptor log;

            log.destToken = originMethod.MetadataToken.ToUInt32();
            log.srcToken  = newMethod.MetadataToken.ToUInt32();

            // build IL header

            log.localVarsToken = buildILHeader(newMethod, originMethod, remapper, out placeholder);

            // Add instructions

            processBody(newMethod, placeholder);

            log.newRva = 0;
            log.codeIL = buffer.ToArray();
            buffer.Clear();

            return(log);
        }
Пример #4
0
        //        +-----------------+ 0
        //        |	  delta header  |    ----->> size of the rest of IL in bytes
        //        +-----------------+ 4
        //        |    IL header    |
        //          +-----------------+
        //        |				    |
        //          |	    IL code     |
        //          |				    |
        //          +-----------------+
        /// <summary>
        /// Builds header of changing method.
        /// </summary>
        /// <param name="newMethod">MethodDefinition of new version of changing method.</param>
        /// <param name="originMethod">MethoDefinition of original version of changing method.</param>
        /// <param name="tkMethod">Metadata token pointing to place of method in running version of metadata.</param>
        /// <param name="remapper">IL offset remapper, used to build local variable changes.</param>
        /// <param name="placeholder">Product of method, represents translation from old variable set to the new one.</param>
        /// <returns>Metadata token pointing to lolcalVars signature, if not present, 0 is given.</returns>
        private uint buildILHeader(MethodDefinition newMethod, MethodDefinition originMethod,
            SequencePointRemapper remapper, out Dictionary<int, int> placeholder)
        {
            uint local_var_old, token;
            uint local_var = newMethod.Body.LocalVarToken.ToUInt32();
            uint code_size = (uint)newMethod.Body.CodeSize;
            uint max_stack_size = (uint)newMethod.Body.MaxStackSize;
            bool old_tiny = originMethod.Body.IsTiny;
            bool tiny = newMethod.Body.IsTiny;
            placeholder = null;

            if (old_tiny && !tiny) {
                // when new method is fat and the old tiny
                byte[] sig = metadata.NewImporter.GetSigantureSA(local_var);
                Signature signa = new Signature(sig);
                signa.Migrate(metadata);
                byte[] sig2 = signa.Compress();
                metadata.OldEmitter.CorMetaDataEmit.GetTokenFromSig(sig2, (uint)sig2.Length, out token);
                tiny = false;
            } else if (!old_tiny && tiny) {
                // when new method is tiny and old fat
                local_var_old = originMethod.Body.LocalVarToken.ToUInt32();
                local_var = local_var_old;
                max_stack_size = 8;
                tiny = false;
            } else if (!old_tiny && !tiny) {
                // both methods are fat
                Signature sigNew = new Signature(metadata.NewImporter.GetSigantureSA(local_var));
                Signature sigOld = new Signature(metadata.OldImporter.GetSigantureSA(originMethod.Body.LocalVarToken.ToUInt32()));
                sigNew.Migrate(metadata);

                // Instead of unused old local variables use placeholders
                LocalVarDiff varDiff = new LocalVarDiff(Builder.Manager.ResourceManager.CurrentModule.SymReader,
                    Builder.SymbolWriter.CorSymNewReader, remapper);

                byte[] sig = varDiff.makeSignature(sigOld, sigNew, out placeholder, originMethod.MetadataToken.ToUInt32(),
                    newMethod.MetadataToken.ToUInt32(),metadata).Compress();

                metadata.OldEmitter.CorMetaDataEmit.GetTokenFromSig(sig, (uint)sig.Length, out local_var);
            }

            //there is no need to change IL and MetaData when both methods are tiny

            if (!tiny) {
                uint header_flags = 0x3013;

                buffer.AddRange(BitConverter.GetBytes((ushort)header_flags));//BitConverter.GetBytes((ushort)header_flags));//.uintToByteArray(header_flags,2));
                buffer.AddRange(BitConverter.GetBytes((ushort)max_stack_size));//Util.uintToByteArray(max_stack_size,2));
                buffer.AddRange(BitConverter.GetBytes(code_size));//.uintToByteArray(code_size));
                buffer.AddRange(BitConverter.GetBytes(local_var));//.uintToByteArray(local_var));

                originMethod.Body.LocalVarToken = new MetadataToken(local_var);
                return local_var;
            } else {
                buffer.Add((byte)((code_size << 2) | 0x2));

                return 0;
            }
        }
Пример #5
0
        /// <summary>
        /// Translate method IL to other metadata scope, with respect to original
        /// method specified by <c>originMethod</c>. 
        /// (Registers local structures validly in sense of EnC, used for changing methods bodies by EnC)
        /// </summary>
        /// <param name="newMethod">Definition of the new version of the method.</param>
        /// <param name="originMethod">Definition of the last version of the method.</param>
        /// <param name="remapper">IL offset remapper, used to build local variable changes.</param>
        /// <param name="placeholder">Product of method, represents translation from old variable set to the new one.</param>
        /// <returns>Descriptor of the new version of method in IL.</returns>
        public MethodDescriptor TranslateMethod(MethodDefinition newMethod, MethodDefinition originMethod,
            SequencePointRemapper remapper, out Dictionary<int, int> placeholder)
        {
            MethodDescriptor log;

            log.destToken = originMethod.MetadataToken.ToUInt32();
            log.srcToken = newMethod.MetadataToken.ToUInt32();

            // build IL header

            log.localVarsToken = buildILHeader(newMethod, originMethod, remapper, out placeholder);

            // Add instructions

            processBody(newMethod, placeholder);

            log.newRva = 0;
            log.codeIL = buffer.ToArray();
            buffer.Clear();

            return log;
        }
Пример #6
0
        //        +-----------------+ 0
        //        |	  delta header  |    ----->> size of the rest of IL in bytes
        //        +-----------------+ 4
        //        |    IL header    |
        //		  +-----------------+
        //        |				    |
        //		  |	    IL code     |
        //		  |				    |
        //		  +-----------------+

        /// <summary>
        /// Builds header of changing method.
        /// </summary>
        /// <param name="newMethod">MethodDefinition of new version of changing method.</param>
        /// <param name="originMethod">MethoDefinition of original version of changing method.</param>
        /// <param name="tkMethod">Metadata token pointing to place of method in running version of metadata.</param>
        /// <param name="remapper">IL offset remapper, used to build local variable changes.</param>
        /// <param name="placeholder">Product of method, represents translation from old variable set to the new one.</param>
        /// <returns>Metadata token pointing to lolcalVars signature, if not present, 0 is given.</returns>
        private uint buildILHeader(MethodDefinition newMethod, MethodDefinition originMethod,
                                   SequencePointRemapper remapper, out Dictionary <int, int> placeholder)
        {
            uint local_var_old, token;
            uint local_var      = newMethod.Body.LocalVarToken.ToUInt32();
            uint code_size      = (uint)newMethod.Body.CodeSize;
            uint max_stack_size = (uint)newMethod.Body.MaxStackSize;
            bool old_tiny       = originMethod.Body.IsTiny;
            bool tiny           = newMethod.Body.IsTiny;

            placeholder = null;

            if (old_tiny && !tiny)
            {
                // when new method is fat and the old tiny
                byte[]    sig   = metadata.NewImporter.GetSigantureSA(local_var);
                Signature signa = new Signature(sig);
                signa.Migrate(metadata);
                byte[] sig2 = signa.Compress();
                metadata.OldEmitter.CorMetaDataEmit.GetTokenFromSig(sig2, (uint)sig2.Length, out token);
                tiny = false;
            }
            else if (!old_tiny && tiny)
            {
                // when new method is tiny and old fat
                local_var_old  = originMethod.Body.LocalVarToken.ToUInt32();
                local_var      = local_var_old;
                max_stack_size = 8;
                tiny           = false;
            }
            else if (!old_tiny && !tiny)
            {
                // both methods are fat
                Signature sigNew = new Signature(metadata.NewImporter.GetSigantureSA(local_var));
                Signature sigOld = new Signature(metadata.OldImporter.GetSigantureSA(originMethod.Body.LocalVarToken.ToUInt32()));
                sigNew.Migrate(metadata);

                // Instead of unused old local variables use placeholders
                LocalVarDiff varDiff = new LocalVarDiff(Builder.Manager.ResourceManager.CurrentModule.SymReader,
                                                        Builder.SymbolWriter.CorSymNewReader, remapper);

                byte[] sig = varDiff.makeSignature(sigOld, sigNew, out placeholder, originMethod.MetadataToken.ToUInt32(),
                                                   newMethod.MetadataToken.ToUInt32(), metadata).Compress();

                metadata.OldEmitter.CorMetaDataEmit.GetTokenFromSig(sig, (uint)sig.Length, out local_var);
            }

            //there is no need to change IL and MetaData when both methods are tiny

            if (!tiny)
            {
                uint header_flags = 0x3013;

                buffer.AddRange(BitConverter.GetBytes((ushort)header_flags));   //BitConverter.GetBytes((ushort)header_flags));//.uintToByteArray(header_flags,2));
                buffer.AddRange(BitConverter.GetBytes((ushort)max_stack_size)); //Util.uintToByteArray(max_stack_size,2));
                buffer.AddRange(BitConverter.GetBytes(code_size));              //.uintToByteArray(code_size));
                buffer.AddRange(BitConverter.GetBytes(local_var));              //.uintToByteArray(local_var));

                originMethod.Body.LocalVarToken = new MetadataToken(local_var);
                return(local_var);
            }
            else
            {
                buffer.Add((byte)((code_size << 2) | 0x2));

                return(0);
            }
        }
Пример #7
0
 public LocalVarDiff(ISymUnmanagedReader oldReader, ISymUnmanagedReader newReader, SequencePointRemapper remapper)
 {
     this.remapper = remapper;
     this.oldReader = oldReader;
     this.newReader = newReader;
 }
Пример #8
0
 public LocalVarDiff(ISymUnmanagedReader oldReader, ISymUnmanagedReader newReader, SequencePointRemapper remapper)
 {
     this.remapper  = remapper;
     this.oldReader = oldReader;
     this.newReader = newReader;
 }
Пример #9
0
        /// <summary>
        /// Creates <see cref="SequencePointRemapper">SequencePointRemapper</see> - sequence point difference tool for 
        /// specified method used in debug state refreshing and local variables definition.
        /// </summary>
        /// <param name="methodDef">Method to which generating takes place.</param>
        /// <returns>Instance of <see cref="SequencePointRemapper">SequencePointRemapper</see>.</returns>
        private SequencePointRemapper genSequencePointRemapper(MethodDefinition methodDefOld, MethodDefinition methodDefNew)
        {
            uint token = methodDefOld.MetadataToken.ToUInt32();

            List<SequencePoint> oldSeqs = SymbolWriterClass.GetMethodSequencePoints(
                Manager.ResourceManager.CurrentModule.SymReader, methodDefOld.MetadataToken.ToUInt32());

            List<SequencePoint> newSeqs = SymbolWriterClass.GetMethodSequencePoints(
                SymbolWriter.CorSymNewReader, methodDefNew.MetadataToken.ToUInt32());

            SequencePointRemapper remapper = new SequencePointRemapper(oldSeqs, newSeqs, Manager.ActualEditEvent.sourceTextChanges[token]);
            SequencePointRemappers.Add(token, remapper);

            return remapper;
        }