ToString() 공개 메소드

public ToString ( ) : string
리턴 string
예제 #1
0
        private static Instruction GetFirstPreviousLdarg_0(this Instruction instruction)
        {
            var previous = instruction.Previous;

            if (previous == null)
            {
                Console.WriteLine(instruction.ToString());
                return(instruction);
            }
            if (previous.OpCode == OpCodes.Ldarg_0 || previous.OpCode == OpCodes.Ldarg && previous.Operand is ParameterDefinition && ((ParameterDefinition)previous.Operand).Name == string.Empty)
            {
                return(previous);
            }
            return(previous.GetFirstPreviousLdarg_0());
        }
예제 #2
0
        private static void Instrument (
                                      AssemblyDefinition assembly,
                                      TypeDefinition type,
                                       Instruction instruction,
                                       MethodReference countReference,
                                       MethodDefinition method,
                                       ILProcessor worker,
                                       string lastLine,
                                       InstrumentConfig config,
                                       TextWriter writer,
                                       ref int instrumentIndex)
        {
            //if the previous instruction is a Prefix instruction then this instruction MUST go with it.
            //we cannot put an instruction between the two.
            if (instruction.Previous != null && instruction.Previous.OpCode.OpCodeType == OpCodeType.Prefix)
                return;

            if (config.HasOffset (method.FullName, instruction.Offset))
                return;

            if (lastLine != null && config.HasLine (method.FullName, lastLine)) {
                return;
            }

            var lineNumStart = -1;
            var lineNumEnd = -1;
            if (instruction.SequencePoint != null) {
                lineNumStart = instruction.SequencePoint.StartLine;
                lineNumEnd = instruction.SequencePoint.EndLine;
            }

            var parentTypeRef = type;
            while (parentTypeRef.DeclaringType != null)
                parentTypeRef = parentTypeRef.DeclaringType;

            var line = string.Join ("\t",
                                   assembly.Name,  //0
                                   parentTypeRef.FullName,//1
                                   method.FullName, //2 
                                   lineNumStart, //3
                                   lineNumEnd, //4 
                                   instruction.Offset, //5
                                   instruction.ToString ().Replace ("\n", " "), //6
                                   instruction.SequencePoint?.Document.Url); //7

   
            writer.WriteLine (line);

            var pathParamLoadInstruction = worker.Create (OpCodes.Ldstr, config.HitsPathPrefix);
            var lineParamLoadInstruction = worker.Create (OpCodes.Ldc_I4, instrumentIndex);
            var registerInstruction = worker.Create (OpCodes.Call, countReference);

            //inserting method before instruction  because after will not happen after a method Ret instruction
            worker.InsertBefore (instruction, pathParamLoadInstruction);
            worker.InsertAfter (pathParamLoadInstruction, lineParamLoadInstruction);
            worker.InsertAfter (lineParamLoadInstruction, registerInstruction);

            ++instrumentIndex;

            //change try/finally etc to point to our first instruction if they referenced the one we inserted before
            foreach (var handler in method.Body.ExceptionHandlers) {
                if (handler.FilterStart == instruction)
                    handler.FilterStart = pathParamLoadInstruction;

                if (handler.TryStart == instruction)
                    handler.TryStart = pathParamLoadInstruction;
                if (handler.TryEnd == instruction)
                    handler.TryEnd = pathParamLoadInstruction;

                if (handler.HandlerStart == instruction)
                    handler.HandlerStart = pathParamLoadInstruction;
                if (handler.HandlerEnd == instruction)
                    handler.HandlerEnd = pathParamLoadInstruction;
            }

            //change instructions with a target instruction if they referenced the one we inserted before to be our first instruction
            foreach (var iteratedInstruction in method.Body.Instructions) {
                var operand = iteratedInstruction.Operand;
                if (operand == instruction) {
                    iteratedInstruction.Operand = pathParamLoadInstruction;
                    continue;
                }

                if (!(operand is Instruction []))
                    continue;

                var operands = (Instruction [])operand;
                for (var i = 0; i < operands.Length; ++i) {
                    if (operands [i] == instruction)
                        operands [i] = pathParamLoadInstruction;
                }
            }
        }
예제 #3
0
 /// <summary>
 /// Create an Instruction record in the database
 /// </summary>
 /// <param name="command">Command factory object</param>
 /// <param name="instruction">Instruction</param>
 private void CreateInstructionRecord(CommandFactory command, Instruction instruction)
 {
     command.Insert<InstructionField>(
         command.GetLastId<AssemblyField>(),
         command.GetLastId<ModuleField>(),
         command.GetLastId<TypeField>(),
         command.GetLastId<MethodField>(),
         instruction.ToString()
     );
 }
예제 #4
0
 private string InstructionToString(Instruction i)
 {
     return i.ToString().Split(new[] {": "}, 2, StringSplitOptions.None)[1];
 }
예제 #5
0
        public static void MethodInstrument(string targetAssembly, string src, string dst)
        {
            var inputAssembly = targetAssembly;
            var path          = Path.GetDirectoryName(inputAssembly);

            var assemblyResolver = new DefaultAssemblyResolver();
            var assemblyLocation = Path.GetDirectoryName(inputAssembly);

            assemblyResolver.AddSearchDirectory(assemblyLocation);

            var readerParameters = new ReaderParameters {
                AssemblyResolver = assemblyResolver
            };
            var  writerParameters = new WriterParameters();
            var  origPdb          = Path.ChangeExtension(inputAssembly, "pdb");
            bool existpdb         = false;

            if (File.Exists(origPdb))
            {
                existpdb = true;

                var symbolReaderProvider = new PdbReaderProvider();
                readerParameters.SymbolReaderProvider = symbolReaderProvider;
                readerParameters.ReadSymbols          = true;

                //var symbolWriterProvider = new PdbWriterProvider();
                //writerParameters.SymbolWriterProvider = symbolWriterProvider;
                writerParameters.WriteSymbols = true;
            }
            else
            {
                Console.WriteLine(".pdb file is unavailable.");
            }

            var assemblyDefinition = AssemblyDefinition.ReadAssembly(inputAssembly, readerParameters);
            var module             = assemblyDefinition.MainModule;
            //Mono.Collections.Generic.Collection<ModuleDefinition> modules = assemblyDefinition.Modules;
            //var module2 = ModuleDefinition.ReadModule(inputAssembly, readerParameters);


            //----------------------

            bool isChanged = false;

            //----------------------------

            foreach (var typeDefinition in module.Types)
            {
                if (typeDefinition.IsInterface)
                {
                    continue;
                }

                foreach (var methodDefinition in typeDefinition.Methods)
                {
                    ILProcessor ilprocessor = methodDefinition.Body.GetILProcessor();

                    Mono.Collections.Generic.Collection <Mono.Cecil.Cil.Instruction> allinstructions = methodDefinition.Body.Instructions;
                    int instructioncnt = allinstructions.Count;
                    for (int i = 0; i < instructioncnt; i++)
                    {
                        Mono.Cecil.Cil.Instruction instruction = allinstructions[i];

                        string instructpresent = instruction.ToString();

                        OpCode code        = instruction.OpCode;
                        string codepresent = code.Name;

                        var    operand    = instruction.Operand;
                        string methodname = "";
                        if (operand != null)
                        {
                            methodname = operand.ToString(); //with parameter
                        }

                        if ((code == OpCodes.Callvirt || code == OpCodes.Call) && //codepresent.Contains("call")
                            (isSameMethod(methodname, src)))                   //or (operand as MethodReference == module.Import(src as MethodInfo))
                        {
                            Console.WriteLine(codepresent + " " + methodname); //debug

                            //---------------------- remove --------------------------//
                            /**** remove instruction in case of no replacing method is provided ****/
                            //TODO: 1. I note the stack depth after the call and start removing instructions, beginning with the Code.Call
                            //  and moving backward until I get to that stack depth again.
                            //  2. return value handling

                            ilprocessor.Remove(instruction);
                            instructioncnt--;
                            if (allinstructions[i].OpCode == OpCodes.Pop) //TODO: just for test
                            {
                                ilprocessor.Remove(allinstructions[i]);
                                instructioncnt--;
                            }
                            i--;

                            if (dst == "")
                            {
                                continue;
                            }

                            //---------------------- replace (remove + insert) ------------------------//

                            /**** create new MethodInfo ****/
                            string     m_type = getNamespace(dst);
                            string     m_name = getMethodName(dst);
                            string []  m_para = getParameters(dst);
                            MethodInfo writeLineMethod;

                            //e.g. MethodInfo writeLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
                            if (m_para != null)
                            {
                                int    paraCnt     = m_para.Length;
                                Type[] m_para_type = new Type[paraCnt];
                                for (int k = 0; k < paraCnt; k++)
                                {
                                    m_para_type[k] = Type.GetType(m_para[k]);
                                }
                                writeLineMethod = Type.GetType(m_type).GetMethod(m_name, m_para_type);
                            }
                            else //the method does not have input parameters
                            {
                                writeLineMethod = Type.GetType(m_type).GetMethod(m_name, new Type[] { });
                            }

                            if (writeLineMethod == null)
                            {
                                throw new InvalidFileFormatException("no MethodInfo is created -- possibly a wrong method delaration.");
                            }

                            /*** Import the new (e.g. Console.WriteLine() method) ***/
                            MethodReference writeLine;
                            writeLine = module.Import(writeLineMethod); //convert "MethodInfo/MethodDefinition" to "MethodReference"

                            /*** Creates the CIL instruction for calling the new method (e.g. Console.WriteLine(string value) method) ***/
                            Mono.Cecil.Cil.Instruction callWriteLine;
                            callWriteLine = ilprocessor.Create(OpCodes.Call, writeLine);

                            /*** replace old instruction ***/
                            //TODO: 1. for simple-type parameters, create one instance and push to stack;
                            //  otherwise just a null object?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                            //  2. return value handling

                            ilprocessor.InsertAfter(allinstructions[i], callWriteLine);

                            //----------------------------------------------//

                            isChanged = true;
                        }
                    } //foreach instruction of a method
                }     //foreach method of a type/class
            }         //foreach type/class of loaded assembly

            if (isChanged)
            {
                var temporaryFileName = Path.Combine(path, string.Format("{0}_temp{1}", Path.GetFileNameWithoutExtension(inputAssembly),
                                                                         Path.GetExtension(inputAssembly)));
                var backupFileName = Path.Combine(path, string.Format("{0}_orig{1}", Path.GetFileNameWithoutExtension(inputAssembly),
                                                                      Path.GetExtension(inputAssembly)));

                var tmpPdb    = Path.Combine(path, string.Format("{0}_temp{1}", Path.GetFileNameWithoutExtension(inputAssembly), ".pdb"));
                var backupPdb = Path.Combine(path, string.Format("{0}_orig{1}", Path.GetFileNameWithoutExtension(inputAssembly), ".pdb"));

                //write an assembly with symbol file being rewritten
                //module.Write(temporaryFileName, writerParameters);
                assemblyDefinition.Write(temporaryFileName, writerParameters);

                File.Replace(temporaryFileName, inputAssembly, backupFileName);

                if (existpdb)
                {
                    File.Replace(tmpPdb, origPdb, backupPdb);
                }

                //TODO: add snkfile in configuration file and parse ([email protected])
                // If you have access to the key pair, you can ask Cecil to sign it directly.
                //if (snkFile != "")
                //{
                //sn -R inputAssembly snkFile
                //}
            }
        }