private void MarkBranchTargets(string word, string lineText, TextLocation pos, IDocument document, TextArea text)
        {
            if (_branchMarkers.Count > 0)
            {
                foreach (var marker in _branchMarkers)
                {
                    document.MarkerStrategy.RemoveMarker(marker);
                }
                _branchMarkers.Clear();
                text.Refresh();
            }

            if (word == null)
            {
                return;
            }

            bool couldBeJump = Regex.IsMatch(word, "^[0-9a-fA-F]{3,4}$");

            if (!couldBeJump)
            {
                return;
            }

            int wordIdx;

            GetWordAtColumn(lineText, pos.Column, out wordIdx);

            bool isFirstWord       = lineText.IndexOf(word, StringComparison.Ordinal) == wordIdx;
            bool isJumpInstruction = false;

            if (!isFirstWord)
            {
                var words = GetWordAndPrevious(lineText, pos.Column);
                isJumpInstruction = words != null && words[0] == MethodDisassembly.JumpMarker;
            }

            if (!isFirstWord && !isJumpInstruction)
            {
                return;
            }

            HashSet <string> exceptionTargetOffsets = new HashSet <string>();

            if (isFirstWord)
            {
                int offset = int.Parse(word, NumberStyles.HexNumber);
                foreach (var ex in _methodDef.Body.Exceptions)
                {
                    if (offset >= ex.TryStart.Offset && offset <= ex.TryEnd.Offset)
                    {
                        foreach (var c in ex.Catches)
                        {
                            exceptionTargetOffsets.Add(MethodDisassembly.FormatOffset(c.Instruction.Offset).Trim());
                        }
                        if (ex.CatchAll != null)
                        {
                            exceptionTargetOffsets.Add(MethodDisassembly.FormatOffset(ex.CatchAll.Offset).Trim());
                        }
                    }
                }
            }

            LineSegment mainLine      = null;
            int         jumpMarkerLen = MethodDisassembly.JumpMarker.Length;

            // jump target?
            foreach (var line in document.LineSegmentCollection)
            {
                bool isLineFirstWord = true;

                string curLine = document.GetText(line);

                int curOffset = 0;

                foreach (var curWord in SplitAndKeep(curLine, SplitCharacters))
                {
                    if (curWord.Trim() == "")
                    {
                        curOffset += curWord.Length;
                        continue;
                    }
                    // mark all words matching the jump instruction
                    if (curWord == word)
                    {
                        if (isLineFirstWord && mainLine == null)
                        {
                            mainLine = line;
                        }
                        else
                        {
                            // add marker.
                            if (curOffset > 4 && curLine.Substring(curOffset - jumpMarkerLen - 1, jumpMarkerLen) == MethodDisassembly.JumpMarker)
                            {
                                AddBranchMarker(document, line.Offset + curOffset - jumpMarkerLen - 1,
                                                curWord.Length + jumpMarkerLen + 1);
                            }
                            else
                            {
                                AddBranchMarker(document, line.Offset + curOffset, curWord.Length);
                            }
                        }
                    }
                    else if (/*isLineFirstWord &&*/ exceptionTargetOffsets.Contains(curWord))
                    {
                        if (!isLineFirstWord)
                        {
                            AddBranchMarker(document, line.Offset + curOffset, curWord.Length, true);
                        }
                        else
                        {
                            AddBranchMarker(document, line.Offset, line.TotalLength, true);
                        }
                    }

                    curOffset      += curWord.Length;
                    isLineFirstWord = false;
                }
            }

            if (mainLine != null && _branchMarkers.Count > 0)
            {
                // better would be to mark the whole line, not only the words.
                AddBranchMarker(document, mainLine.Offset, mainLine.TotalLength);
            }

            if (_branchMarkers.Count > 0)
            {
                text.Refresh();
            }
        }
示例#2
0
        public string Format(FormatOptions options)
        {
            var nl = Environment.NewLine;
            var sb = new StringBuilder();

            var body = _methodDef.Body;
            var cfg  = new ControlFlowGraph(body);
            SourceCodePosition lastSource = null;

            _dissassembly.Format = options;

            var embedSource = options.HasFlag(FormatOptions.EmbedSourceCode) || options.HasFlag(FormatOptions.EmbedSourcePositions);

            if (embedSource && _dissassembly.MethodEntry != null)
            {
                var pos = _mapFile.GetSourceCodePositions(_dissassembly.MethodEntry).FirstOrDefault();
                if (pos != null)
                {
                    sb.Append(" // ----- Source Code: ");
                    sb.Append(pos.Document.Path);
                    sb.Append(nl);
                }
            }

            foreach (var block in cfg)
            {
                if (options.HasFlag(FormatOptions.ShowControlFlow))
                {
                    sb.AppendFormat(" // ----- Entry [{0}] Exit [{1}]{2}",
                                    string.Join(", ", block.EntryBlocks.Select(x => _dissassembly.FormatAddress(x.Entry).Trim())),
                                    string.Join(", ", block.ExitBlocks.Select(x => _dissassembly.FormatAddress(x.Entry).Trim())),
                                    nl);
                }


                foreach (var i in block.Instructions)
                {
                    if (embedSource)
                    {
                        var source = _dissassembly.FindSourceCode(i.Offset, false);

                        if (source != null && lastSource != null && source.Document.Path != lastSource.Document.Path)
                        {
                            // print document name.
                            sb.Append(" // ----- ");
                            sb.Append(source.Document.Path);
                            sb.Append(nl);
                            lastSource = null;
                        }

                        if (source == null && lastSource != null)
                        {
                            sb.AppendLine(" // ----- (no source)");
                        }
                        else if (source != null && (lastSource == null || !source.Position.EqualExceptOffset(lastSource.Position)))
                        {
                            if (options.HasFlag(FormatOptions.EmbedSourcePositions))
                            {
                                sb.AppendFormat(" // ----- Position: {0} - {1}{2}", source.Position.Start, source.Position.End, nl);
                            }

                            if (options.HasFlag(FormatOptions.EmbedSourceCode))
                            {
                                string[] lines = GetSourceCodeLines(source);
                                if (lines != null)
                                {
                                    sb.AppendLine(" // " + string.Join(nl + " // ", lines));
                                }
                            }
                        }
                        lastSource = source;
                    }

                    sb.AppendLine(_dissassembly.FormatInstruction(i));
                }
            }
            sb.AppendLine();

            if (body.Exceptions.Any())
            {
                sb.AppendLine("Exception handlers:");
                foreach (var handler in body.Exceptions)
                {
                    sb.AppendFormat("\t{0} - {1}{2}", _dissassembly.FormatAddress(handler.TryStart), _dissassembly.FormatAddress(handler.TryEnd), nl);
                    foreach (var c in handler.Catches)
                    {
                        sb.AppendFormat("\t\t{0} => {1}{2}", c.Type, _dissassembly.FormatAddress(c.Instruction), nl);
                    }
                    if (handler.CatchAll != null)
                    {
                        sb.AppendFormat("\t\t{0} => {1}{2}", "<any>", _dissassembly.FormatAddress(handler.CatchAll), nl);
                    }
                }
                sb.AppendLine();
            }

            if (_mapFile != null)
            {
                var typeEntry = _mapFile.GetTypeByNewName(_methodDef.Owner.Fullname);
                if (typeEntry != null)
                {
                    var methodEntry = typeEntry.FindDexMethod(_methodDef.Name, _methodDef.Prototype.ToSignature());
                    if (methodEntry != null)
                    {
                        _registersToVariableNames = new Dictionary <string, string>();

                        var validParameters = methodEntry.Parameters.Where(x => !string.IsNullOrEmpty(x.Name)).ToList();
                        if (validParameters.Any())
                        {
                            sb.AppendLine("Parameters:");
                            foreach (var p in validParameters)
                            {
                                var registerName = _dissassembly.FormatRegister(p.Register);
                                sb.AppendFormat("\t{0} (r{1}) -> {2}{3}", registerName, p.Register, p.Name, nl);

                                if (!string.IsNullOrEmpty(p.Name))
                                {
                                    _registersToVariableNames.Add(registerName, p.Name);
                                }
                            }
                            sb.AppendLine();
                        }

                        var validVariables = methodEntry.Variables.Where(x => !string.IsNullOrEmpty(x.Name)).ToList();
                        if (validVariables.Any())
                        {
                            sb.AppendLine("Variables:");
                            foreach (var p in validVariables)
                            {
                                var registerName = _dissassembly.FormatRegister(p.Register);
                                sb.AppendFormat("\t{0} -> {1}{2}", registerName, p.Name, nl);
                                if (!string.IsNullOrEmpty(p.Name))
                                {
                                    _registersToVariableNames.Add(registerName, p.Name);
                                }
                            }
                            sb.AppendLine();
                        }

                        sb.AppendLine("Source code positions:");
                        Document lastDocument = null;
                        foreach (var row in _mapFile.GetSourceCodePositions(methodEntry))
                        {
                            if (row.Document != lastDocument)
                            {
                                sb.AppendFormat("\t{0}{1}", row.Document.Path, nl);
                                lastDocument = row.Document;
                            }
                            var pos = row.Position;
                            sb.AppendFormat("\t{0}\t({1},{2}) - ({3},{4}){5}", MethodDisassembly.FormatOffset(pos.MethodOffset), pos.Start.Line, pos.Start.Column, pos.End.Line, pos.End.Column, nl);
                        }
                    }
                }
            }
            return(sb.ToString());
        }