示例#1
0
        public void Disassemble(MethodDef method, MemberMapping debugSymbols)
        {
            // start writing IL code
            CilBody body     = method.Body;
            uint    codeSize = (uint)body.GetCodeSize();
            uint    rva      = (uint)method.RVA;
            long    offset   = method.Module.ToFileOffset(rva);

            if (options.ShowTokenAndRvaComments)
            {
                output.WriteLine(string.Format("// Header Size: {0} {1}", method.Body.HeaderSize, method.Body.HeaderSize == 1 ? "byte" : "bytes"), TextTokenType.Comment);
                output.WriteLine(string.Format("// Code Size: {0} (0x{0:X}) {1}", codeSize, codeSize == 1 ? "byte" : "bytes"), TextTokenType.Comment);
                if (body.LocalVarSigTok != 0)
                {
                    output.WriteLine(string.Format("// LocalVarSig Token: 0x{0:X8} RID: {1}", body.LocalVarSigTok, body.LocalVarSigTok & 0xFFFFFF), TextTokenType.Comment);
                }
            }
            output.Write(".maxstack", TextTokenType.ILDirective);
            output.WriteSpace();
            output.WriteLine(string.Format("{0}", body.MaxStack), TextTokenType.Number);
            if (method.DeclaringType.Module.EntryPoint == method)
            {
                output.WriteLine(".entrypoint", TextTokenType.ILDirective);
            }

            if (method.Body.HasVariables)
            {
                output.Write(".locals", TextTokenType.ILDirective);
                output.WriteSpace();
                if (method.Body.InitLocals)
                {
                    output.Write("init", TextTokenType.Keyword);
                    output.WriteSpace();
                }
                output.WriteLine("(", TextTokenType.Operator);
                output.Indent();
                foreach (var v in method.Body.Variables)
                {
                    output.Write('[', TextTokenType.Operator);
                    output.WriteDefinition(v.Index.ToString(), v, TextTokenType.Number);
                    output.Write(']', TextTokenType.Operator);
                    output.WriteSpace();
                    v.Type.WriteTo(output);
                    if (!string.IsNullOrEmpty(v.Name))
                    {
                        output.WriteSpace();
                        output.Write(DisassemblerHelpers.Escape(v.Name), TextTokenType.Local);
                    }
                    if (v.Index + 1 < method.Body.Variables.Count)
                    {
                        output.Write(',', TextTokenType.Operator);
                    }
                    output.WriteLine();
                }
                output.Unindent();
                output.WriteLine(")", TextTokenType.Operator);
            }
            output.WriteLine();

            uint baseRva  = rva == 0 ? 0 : rva + method.Body.HeaderSize;
            long baseOffs = baseRva == 0 ? 0 : method.Module.ToFileOffset(baseRva);

            using (var byteReader = !options.ShowILBytes || options.CreateInstructionBytesReader == null ? null : options.CreateInstructionBytesReader(method)) {
                if (detectControlStructure && body.Instructions.Count > 0)
                {
                    int            index         = 0;
                    HashSet <uint> branchTargets = GetBranchTargets(body.Instructions);
                    WriteStructureBody(body, new ILStructure(body), branchTargets, ref index, debugSymbols, method.Body.GetCodeSize(), baseRva, baseOffs, byteReader, method);
                }
                else
                {
                    var instructions = method.Body.Instructions;
                    for (int i = 0; i < instructions.Count; i++)
                    {
                        var inst          = instructions[i];
                        var startLocation = output.Location;
                        inst.WriteTo(output, options, baseRva, baseOffs, byteReader, method);

                        if (debugSymbols != null)
                        {
                            // add IL code mappings - used in debugger
                            var next = i + 1 < instructions.Count ? instructions[i + 1] : null;
                            debugSymbols.MemberCodeMappings.Add(
                                new SourceCodeMapping()
                            {
                                StartLocation       = output.Location,
                                EndLocation         = output.Location,
                                ILInstructionOffset = new ILRange(inst.Offset, next == null ? (uint)method.Body.GetCodeSize() : next.Offset),
                                MemberMapping       = debugSymbols
                            });
                        }

                        output.WriteLine();
                    }
                    if (method.Body.HasExceptionHandlers)
                    {
                        output.WriteLine();
                        foreach (var eh in method.Body.ExceptionHandlers)
                        {
                            eh.WriteTo(output, method);
                            output.WriteLine();
                        }
                    }
                }
            }
        }
示例#2
0
        public ILStructure(CilBody body)
            : this(ILStructureType.Root, 0, body.GetCodeSize())
        {
            // Build the tree of exception structures:
            for (int i = 0; i < body.ExceptionHandlers.Count; i++)
            {
                ExceptionHandler eh = body.ExceptionHandlers[i];
                if (!body.ExceptionHandlers.Take(i).Any(oldEh => oldEh.TryStart == eh.TryStart && oldEh.TryEnd == eh.TryEnd))
                {
                    AddNestedStructure(new ILStructure(ILStructureType.Try, (int)eh.TryStart.Offset, (int)eh.TryEnd.Offset, eh));
                }
                if (eh.HandlerType == ExceptionHandlerType.Filter)
                {
                    AddNestedStructure(new ILStructure(ILStructureType.Filter, (int)eh.FilterStart.Offset, (int)eh.HandlerStart.Offset, eh));
                }
                AddNestedStructure(new ILStructure(ILStructureType.Handler, (int)eh.HandlerStart.Offset, eh.HandlerEnd == null ? body.GetCodeSize() : (int)eh.HandlerEnd.Offset, eh));
            }
            // Very simple loop detection: look for backward branches
            List <KeyValuePair <Instruction, Instruction> > allBranches = FindAllBranches(body);

            // We go through the branches in reverse so that we find the biggest possible loop boundary first (think loops with "continue;")
            for (int i = allBranches.Count - 1; i >= 0; i--)
            {
                int loopEnd   = allBranches[i].Key.GetEndOffset();
                int loopStart = (int)allBranches[i].Value.Offset;
                if (loopStart < loopEnd)
                {
                    // We found a backward branch. This is a potential loop.
                    // Check that is has only one entry point:
                    Instruction entryPoint = null;

                    // entry point is first instruction in loop if prev inst isn't an unconditional branch
                    Instruction prev = body.GetPrevious(allBranches[i].Value);
                    if (prev != null && !OpCodeInfo.IsUnconditionalBranch(prev.OpCode))
                    {
                        entryPoint = allBranches[i].Value;
                    }

                    bool multipleEntryPoints = false;
                    foreach (var pair in allBranches)
                    {
                        if (pair.Key.Offset < loopStart || pair.Key.Offset >= loopEnd)
                        {
                            if (loopStart <= pair.Value.Offset && pair.Value.Offset < loopEnd)
                            {
                                // jump from outside the loop into the loop
                                if (entryPoint == null)
                                {
                                    entryPoint = pair.Value;
                                }
                                else if (pair.Value != entryPoint)
                                {
                                    multipleEntryPoints = true;
                                }
                            }
                        }
                    }
                    if (!multipleEntryPoints)
                    {
                        AddNestedStructure(new ILStructure(ILStructureType.Loop, loopStart, loopEnd, entryPoint));
                    }
                }
            }
            SortChildren();
        }
示例#3
0
        public void Disassemble(MethodDef method, MemberMapping debugSymbols)
        {
            // start writing IL code
            CilBody body     = method.Body;
            uint    codeSize = (uint)body.GetCodeSize();

            output.WriteLine(string.Format("// RVA 0x{0:x8} - 0x{1:x8} ({2} (0x{2:x}) bytes)", (uint)method.RVA, (uint)method.RVA + codeSize, codeSize), TextTokenType.Comment);
            output.WriteLine(string.Format("// Metadata token 0x{0:x8} (RID {1})", method.MDToken.ToInt32(), method.Rid), TextTokenType.Comment);
            if (body.LocalVarSigTok != 0)
            {
                output.WriteLine(string.Format("// LocalVarSig token 0x{0:x8} (RID {1})", body.LocalVarSigTok, body.LocalVarSigTok & 0xFFFFFF), TextTokenType.Comment);
            }
            output.Write(".maxstack", TextTokenType.ILDirective);
            output.WriteSpace();
            output.WriteLine(string.Format("{0}", body.MaxStack), TextTokenType.Number);
            if (method.DeclaringType.Module.EntryPoint == method)
            {
                output.WriteLine(".entrypoint", TextTokenType.ILDirective);
            }

            if (method.Body.HasVariables)
            {
                output.Write(".locals", TextTokenType.ILDirective);
                output.WriteSpace();
                if (method.Body.InitLocals)
                {
                    output.Write("init", TextTokenType.Keyword);
                    output.WriteSpace();
                }
                output.WriteLine("(", TextTokenType.Operator);
                output.Indent();
                foreach (var v in method.Body.Variables)
                {
                    output.Write('[', TextTokenType.Operator);
                    output.WriteDefinition(v.Index.ToString(), v, TextTokenType.Number);
                    output.Write(']', TextTokenType.Operator);
                    output.WriteSpace();
                    v.Type.WriteTo(output);
                    if (!string.IsNullOrEmpty(v.Name))
                    {
                        output.WriteSpace();
                        output.Write(DisassemblerHelpers.Escape(v.Name), TextTokenType.Local);
                    }
                    if (v.Index + 1 < method.Body.Variables.Count)
                    {
                        output.Write(',', TextTokenType.Operator);
                    }
                    output.WriteLine();
                }
                output.Unindent();
                output.WriteLine(")", TextTokenType.Operator);
            }
            output.WriteLine();

            if (detectControlStructure && body.Instructions.Count > 0)
            {
                int            index         = 0;
                HashSet <uint> branchTargets = GetBranchTargets(body.Instructions);
                WriteStructureBody(body, new ILStructure(body), branchTargets, ref index, debugSymbols, method.Body.GetCodeSize());
            }
            else
            {
                var instructions = method.Body.Instructions;
                for (int i = 0; i < instructions.Count; i++)
                {
                    var inst          = instructions[i];
                    var startLocation = output.Location;
                    inst.WriteTo(output, options.GetOpCodeDocumentation);

                    if (debugSymbols != null)
                    {
                        // add IL code mappings - used in debugger
                        var next = i + 1 < instructions.Count ? instructions[i + 1] : null;
                        debugSymbols.MemberCodeMappings.Add(
                            new SourceCodeMapping()
                        {
                            StartLocation       = output.Location,
                            EndLocation         = output.Location,
                            ILInstructionOffset = new ILRange(inst.Offset, next == null ? (uint)method.Body.GetCodeSize() : next.Offset),
                            MemberMapping       = debugSymbols
                        });
                    }

                    output.WriteLine();
                }
                if (method.Body.HasExceptionHandlers)
                {
                    output.WriteLine();
                    foreach (var eh in method.Body.ExceptionHandlers)
                    {
                        eh.WriteTo(output);
                        output.WriteLine();
                    }
                }
            }
        }
        public void Disassemble(MethodDef method, CilBody body, MemberMapping methodMapping)
        {
            // start writing IL code
            output.WriteLineComment("// Method Token is 0x{0:x8}", method.MDToken.Raw);
            output.WriteLineComment("// Method begins at RVA 0x{0:x}", method.RVA);
            output.WriteLineComment("// Code size {0} (0x{0:x})", body.GetCodeSize());
            output.WriteKeyword(".maxstack ");
            output.WriteLiteral(body.MaxStack.ToString());
            output.WriteLine();
            if (method.DeclaringType.Module.Assembly != null && method.DeclaringType.Module.EntryPoint == method)
            {
                output.WriteKeyword(".entrypoint");
                output.WriteLine();
            }

            if (method.Body.HasVariables)
            {
                output.WriteKeyword(".locals ");
                if (method.Body.InitLocals)
                {
                    output.WriteKeyword("init ");
                }
                output.WriteLine("(");
                output.Indent();
                foreach (var v in method.Body.Variables)
                {
                    output.WriteDefinition("[" + v.Index + "]", v, true);
                    output.Write(" ");
                    v.Type.WriteTo(output);
                    if (!string.IsNullOrEmpty(v.Name))
                    {
                        output.Write(' ');
                        output.Write(DisassemblerHelpers.Escape(v.Name));
                    }
                    if (v.Index + 1 < method.Body.Variables.Count)
                    {
                        output.Write(',');
                    }
                    output.WriteLine();
                }
                output.Unindent();
                output.WriteLine(")");
            }
            output.WriteLine();

            if (detectControlStructure && body.Instructions.Count > 0)
            {
                Instruction inst          = body.Instructions[0];
                var         branchTargets = GetBranchTargets(body.Instructions);
                WriteStructureBody(method, body, new ILStructure(body), branchTargets, ref inst, methodMapping, method.Body.GetCodeSize());
            }
            else
            {
                foreach (var inst in method.Body.Instructions)
                {
                    var startLocation = output.Location;
                    inst.WriteTo(method, body, output);

                    if (methodMapping != null)
                    {
                        var next = inst.GetNext(body);
                        // add IL code mappings - used in debugger
                        methodMapping.MemberCodeMappings.Add(
                            new SourceCodeMapping()
                        {
                            StartLocation       = output.Location,
                            EndLocation         = output.Location,
                            ILInstructionOffset = new ILRange {
                                From = inst.Offset, To = next == null ? method.Body.GetCodeSize() : next.Offset
                            },
                            MemberMapping = methodMapping
                        });
                    }

                    output.WriteLine();
                }
                if (method.Body.HasExceptionHandlers)
                {
                    output.WriteLine();
                    foreach (var eh in method.Body.ExceptionHandlers)
                    {
                        eh.WriteTo(output);
                        output.WriteLine();
                    }
                }
            }
        }