示例#1
0
 public Task <RegisterNames> GetRegisterNamesAsync()
 {
     if (registerNames != null)
     {
         return(registerNames.AsTask());
     }
     return(Task.Factory.StartNew(() =>
     {
         var loc = GetDocumentLocationAsync().Await(DalvikProcess.VmTimeout);
         MethodDisassembly methodDiss = thread.Manager.Process.DisassemblyProvider.GetFromLocation(loc);
         registerNames = new RegisterNames(methodDiss == null ? null : methodDiss.Method.Body,
                                           HasMethodParametersInLastRegisters);
         return registerNames;
     }));
 }
示例#2
0
        //private DalvikStackFrame GetUnwindStackFrame(DalvikThread thread, DebugCodeContext context)
        //{
        //    foreach (var stackFrame in thread.GetCallStack())
        //    {
        //        bool isSameMethodEarlierOrSame = stackFrame.Location.IsSameMethod(context.Location)
        //                                      && stackFrame.Location.Index >= context.Location.Index;
        //        if (isSameMethodEarlierOrSame)
        //            return stackFrame;
        //    }
        //    return null;
        //}

        /// <summary>
        /// Finds the next location with source starting from <paramref name="idx"/>.
        /// Will return null if no source is found. Will follow a single goto.
        /// Will return null if multiple gotos or if any other jump instruction is
        /// encountered.
        /// </summary>
        private int?FindNextLocationWithSource(MethodDisassembly disassembly, int idx)
        {
            var instructions = disassembly.Method.Body.Instructions;

            var ins = instructions[idx];

            // find the next instruction with source code.
            var loc = disassembly.FindNextSourceCode(ins.Offset);

            if (loc == null)
            {
                return(null);
            }

            int gotos = 0;

            for (; (ins = instructions[idx]).Offset < loc.Position.MethodOffset; ++idx)
            {
                // While working as expected, the following code as no effect on
                // foreach statements, since the target of the goto is a "IsSpecial"
                // branch instruction back to the very same goto.

                if (ins.OpCode == OpCodes.Goto || ins.OpCode == OpCodes.Goto_16 || ins.OpCode == OpCodes.Goto_32)
                {
                    // follow a single goto. this is typically encountered
                    // at the beginning of the loop of foreach statements.
                    if (gotos++ > 0)
                    {
                        return(null);
                    }
                    ins = (Instruction)ins.Operand;
                    loc = disassembly.FindNextSourceCode(ins.Offset);
                    if (loc == null)
                    {
                        return(null);
                    }
                    idx = instructions.IndexOf(ins) - 1;
                    continue;
                }

                if (ins.OpCode.IsJump())
                {
                    return(null);
                }
            }

            return(idx);
        }
示例#3
0
        public MethodBodyDisassemblyFormatter(MethodDefinition methodDef, MapFileLookup mapFile)
        {
            _methodDef = methodDef;
            _mapFile   = mapFile;

            TypeEntry   typeEntry   = null;
            MethodEntry methodEntry = null;

            if (mapFile != null)
            {
                typeEntry = mapFile.GetTypeByNewName(methodDef.Owner.Fullname);
                if (typeEntry != null)
                {
                    methodEntry = typeEntry.FindDexMethod(methodDef.Name, methodDef.Prototype.ToSignature());
                }
            }

            _dissassembly = new MethodDisassembly(methodDef, mapFile, typeEntry, methodEntry);

            _sourceDocument = new Lazy <string[]>(() =>
            {
                if (_dissassembly.MethodEntry == null)
                {
                    return(null);
                }
                var pos = _mapFile.GetSourceCodePositions(_dissassembly.MethodEntry).FirstOrDefault();
                if (pos == null)
                {
                    return(null);
                }

                try
                {
                    return(File.ReadAllLines(pos.Document.Path));
                }
                catch (Exception)
                {
                    return(null);
                }
            });
        }
示例#4
0
        /// <summary>
        /// Get all local registers for this frame.
        /// </summary>
        /// <returns></returns>
        public Task <List <DalvikStackFrameValue> > GetRegistersAsync(bool parametersOnly = false, Jdwp.Tag type = Jdwp.Tag.Int, params int[] indizes)
        {
            if (parametersOnly && parameters != null)
            {
                return(parameters.AsTask());
            }
            if (!parametersOnly && registers != null && indizes.Length == 0)
            {
                return(registers.AsTask());
            }

            return(Task.Factory.StartNew(() =>
            {
                var ret = new List <DalvikStackFrameValue>();

                var loc = GetDocumentLocationAsync().Await(DalvikProcess.VmTimeout);

                List <Register> regDefs;

                MethodDisassembly methodDiss = thread.Manager.Process.DisassemblyProvider.GetFromLocation(loc);

                registerNames = registerNames ??
                                new RegisterNames(methodDiss == null ? null : methodDiss.Method.Body, HasMethodParametersInLastRegisters);

                if (indizes.Length == 0)
                {
                    if (methodDiss == null)
                    {
                        return ret;
                    }

                    var body = methodDiss.Method.Body;

                    regDefs = (parametersOnly ? body.Registers.Where(r => registerNames.IsParameter(r))
                                              : body.Registers)
                              .Where(p => indizes.Length == 0 || indizes.Contains(p.Index))
                              .OrderBy(p => p.Index)
                              .ToList();
                }
                else
                {
                    regDefs = indizes.Select(i => new Register(i)).ToList();
                }

                var requests = regDefs.Select(reg => new SlotRequest(reg.Index, type)).ToList();

                var regValues = Debugger.StackFrame.GetValuesAsync(thread.Id, Id, requests.ToArray())
                                .Await(DalvikProcess.VmTimeout);

                var process = thread.Manager.Process;
                for (int i = 0; i < regDefs.Count && i < regValues.Count; ++i)
                {
                    var reg = regDefs[i];
                    int numRegs = methodDiss == null ? int.MaxValue : methodDiss.Method.Body.Instructions.Count;
                    bool isParam = registerNames.IsParameter(reg);
                    string regName = registerNames.GetName(reg);

                    var valInfo = new VariableInfo(0, regName, null, null, numRegs, reg.Index);

                    DalvikStackFrameValue val = new DalvikStackFrameValue(regValues[i], valInfo, isParam, process);
                    ret.Add(val);
                }

                if (indizes.Length > 0)
                {
                    return ret;
                }

                if (parametersOnly)
                {
                    parameters = parameters ?? ret;
                }
                else
                {
                    registers = registers ?? ret;
                }
                return ret;
            }));
        }
 public DebugDisassemblyStream(DebugProgram program, DebugCodeContext documentContext)
 {
     _loc    = documentContext.DocumentContext.DocumentLocation;
     _method = program.DisassemblyProvider.GetFromLocation(_loc);
 }
        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();
            }
        }
示例#7
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());
        }