Example #1
0
        private SourceFile(ApkFile apk, JarFile jar, ISpySettings settings, MapFile mapFile, string singleFilePath = null)
        {
            this.apk = apk;
            this.jar = jar;
            this.settings = settings;
            this.mapFile = mapFile;
            this.singleFilePath = singleFilePath;

#if DEBUG
            classLoader = new AssemblyClassLoader(module.OnClassLoaded);
            var modParams = new ModuleParameters
            {
                AssemblyResolver = new AssemblyResolver(new[] { Frameworks.Instance.FirstOrDefault().Folder }, classLoader, module.OnAssemblyLoaded),
                Kind = ModuleKind.Dll
            };
            assembly = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition("spy", Version.Parse("1.0.0.0")), "main", modParams);
            classLoader.LoadAssembly(assembly);

            var dot42Assembly = modParams.AssemblyResolver.Resolve("dot42");

            // Force loading of classes
            if (jar != null)
            {
                foreach (var fileName in jar.ClassFileNames)
                {
                    OpenClass(fileName);
                }
            }
#endif
        }
Example #2
0
 /// <summary>
 /// Default ctor
 /// </summary>
 internal DebugProgram(DebugProcess process, DebuggerLib.Debugger debugger, string apkPath, MapFile mapFile, EngineEventCallback eventCallback)
     : base(debugger, mapFile)
 {
     this.process = process;
     this.apkPath = apkPath;
     this.eventCallback = eventCallback;
     programGuid = Guid.NewGuid();
     modules.Add(new DebugModule());
 }
Example #3
0
 /// <summary>
 /// Default ctor
 /// </summary>
 internal DebugProcess(DebugEngine engine, DebugPort port, DebuggerLib.Debugger debugger, int processId, Guid guid, string apkPath, MapFile mapFile, EngineEventCallback eventCallback)
 {
     this.engine = engine;
     this.port = port;
     this.debugger = debugger;
     this.processId = processId;
     this.guid = guid;
     this.apkPath = apkPath;
     this.eventCallback = eventCallback;
     creationDate = DateTime.Now;
     program = new DebugProgram(this, debugger, apkPath, mapFile, eventCallback);
     program.Terminated += OnProgramTerminated;
 }
Example #4
0
        public MapFileLookup(MapFile map)
        {
            _map = map;

            // note the OrderBy(MethodOffset), which allows us to perform a binary search later on.
            _positionsByMethodId = map.Documents.SelectMany(d => d.Positions, SourceCodePosition.Create)
                                                .GroupBy(p=>p.Position.MethodId)
                                                .ToDictionary(p=>p.Key, p=>p.OrderBy(dp=>dp.Position.MethodOffset).ToList());

            foreach (var entry in map.TypeEntries)
            {
                Add(entry);
            }
        }
Example #5
0
 /// <summary>
 /// Default ctor
 /// </summary>
 public DalvikProcess(Debugger debugger, MapFile mapFile, string apkPath)
 {
     ApkPath = apkPath;
     this.debugger = debugger;
     debugger.Process = this;
     this.mapFile = new MapFileLookup(mapFile);
     debugger.ConnectedChanged += OnDebuggerConnectionChanged;
     breakpointManager = new Lazy<DalvikBreakpointManager>(CreateBreakpointManager);
     exceptionManager = new Lazy<DalvikExceptionManager>(CreateExceptionManager);
     referenceTypeManager = new Lazy<DalvikReferenceTypeManager>(CreateReferenceTypeManager);
     threadManager = new Lazy<DalvikThreadManager>(CreateThreadManager);
     disassemblyProvider =
         new Lazy<DalvikDisassemblyProvider>(() => new DalvikDisassemblyProvider(this, ApkPath, this.mapFile));
 }
Example #6
0
        /// <summary>
        /// Connect to the VM in the given process id on the given device.
        /// </summary>
        public void Connect(IDevice device, int pid, MapFile mapFile)
        {
            // Disconnect any pending connections
            Disconnect();

            // Cleanup
            process = null;
            this.mapFile = mapFile;
            this.pid = pid;

            // Setup forward
            var port = GetFreePort();
            var adb = new Adb();
            adb.ForwardJdwp(device, port, pid);

            // Establish connection
            connection = new JdwpConnection(new IPEndPoint(IPAddress.Parse("127.0.0.1"), port), ChunkHandler, pid, PacketHandler);
            connection.Disconnect += OnConnectionDisconnect;

            // Notify
            ConnectedChanged.Fire(this);
        }
Example #7
0
 /// <summary>
 /// Default ctor
 /// </summary>
 public DebugProcess(Dot42.DebuggerLib.Debugger debugger, MapFile mapFile)
     : base(debugger, mapFile, null)
 {
 }
Example #8
0
 /// <summary>
 /// Compile RL into the Dex method body.
 /// </summary>
 internal void CompileToTarget(ITargetPackage targetPackage, bool generateDebugInfo, MapFile mapFile)
 {
     CompileToDex((DexTargetPackage) targetPackage, generateDebugInfo, mapFile);
 }
Example #9
0
        /// <summary>
        /// Compile RL into the Dex method body.
        /// </summary>
        private void CompileToDex(DexTargetPackage targetPackage, bool generateDebugInfo, MapFile mapFile)
        {
            var dmethod = DexMethod;
            if (dmethod == null)
                throw new ArgumentException("No DexMethod set");
            if ((dmethod.IsAbstract) || (dmethod.IsNative))
                return;
            var rlBody = RLBody;
            if (rlBody == null)
                throw new ArgumentException("No RL body set");

            // Ensure RL is optimized
            OptimizeRL(targetPackage.DexFile);

            // Compile to Dex
            var dbody = new Dot42.DexLib.Instructions.MethodBody(dmethod, 0);
            var dexCompiler = new DexCompiler(rlBody, dbody, InvocationFrame);
            regMapper = dexCompiler.Compile();

            // Optimize code
            //dbody.UpdateInstructionOffsets();
            DexOptimizer.DexOptimizer.Optimize(dbody);

            // Ensure correct offsets
            dbody.UpdateInstructionOffsets();
            dmethod.Body = dbody;

            if (generateDebugInfo || (mapFile != null))
            {
                // Add debug info
                var debugInfoBuilder = new DebugInfoBuilder(this);
                if (generateDebugInfo)
                    debugInfoBuilder.CreateDebugInfo(dbody, regMapper, targetPackage);
                if (mapFile != null)
                    debugInfoBuilder.AddDocumentMapping(mapFile);
            }
        }
Example #10
0
 public void RecordMapping(MapFile mapFile)
 {
 }
Example #11
0
        /// <summary>
        /// Compile RL into the Dex method body.
        /// </summary>
        private void CompileToDex(DexTargetPackage targetPackage, bool generateDebugInfo, MapFile mapFile)
        {
            var dmethod = DexMethod;
            if (dmethod == null)
                throw new ArgumentException("No DexMethod set");
            if ((dmethod.IsAbstract) || (dmethod.IsNative))
                return;

            var rlBody = RLBody;

            if (rlBody == null && dmethod.Body != null) // already satisfied from the cache?
                return;

            if (rlBody == null)
                throw new ArgumentException(string.Format("internal compiler error: No RL body set on method '{2}'.'{3}' => '{0}'.'{1}'", dmethod.Owner.Name, dmethod.Name, method == null ? null : method.DeclaringType.FullName, method == null ? null : method.Name));

            // Ensure RL is optimized
            OptimizeRL(targetPackage.DexFile);

            // Compile to Dex
            var dbody = new Dot42.DexLib.Instructions.MethodBody(dmethod, 0);
            var dexCompiler = new DexCompiler(rlBody, dbody, InvocationFrame);
            regMapper = dexCompiler.Compile();

            // Optimize code
            //dbody.UpdateInstructionOffsets();
            DexOptimizer.DexOptimizer.Optimize(dbody);

            // Ensure correct offsets
            dbody.UpdateInstructionOffsets();
            dmethod.Body = dbody;

            if (generateDebugInfo || (mapFile != null))
            {
                // Add debug info
                var debugInfoBuilder = new DebugInfoBuilder(this);
                if (generateDebugInfo)
                    debugInfoBuilder.CreateDebugInfo(dbody, regMapper, targetPackage);
                if (mapFile != null && dmethod.MapFileId != 0)
                    debugInfoBuilder.AddDocumentMapping(mapFile);
            }
        }
Example #12
0
        /// <summary>
        /// Add document and position data to the given map file.
        /// </summary> 
        internal void AddDocumentMapping(MapFile mapFile)
        {
            var source = compiledMethod.DexMethod;
            if ((source == null) || (source.Body == null) || (source.Body.Instructions.Count == 0))
                return;

            if (this.compiledMethod.DexMethod.Name == "testTryCatch")
            {
                
            }

            var sequencePointsInstr = source.Body.Instructions.Where(x => x.SequencePoint != null);
            foreach (var seqPointIns in sequencePointsInstr)
            {
                // Get document
                var seqPoint = (ISourceLocation)seqPointIns.SequencePoint;
                var doc = mapFile.GetOrCreateDocument(seqPoint.Document, true);

                // Add position
                var docPos = new DocumentPosition(seqPoint.StartLine, seqPoint.StartColumn, seqPoint.EndLine,
                                                  seqPoint.EndColumn, 
                                                  compiledMethod.DexMethod.Owner.MapFileId,
                                                  compiledMethod.DexMethod.MapFileId,
                                                  seqPointIns.Offset) { IsReturn = seqPointIns.OpCode.IsReturn() };
                doc.Positions.Add(docPos);
            }            
        }
Example #13
0
        /// <summary>
        /// Convert method arguments
        /// </summary>
        /// <param name="args"></param>
        /// <param name="map"></param>
        /// <returns></returns>
        private static string ConvertMethodArguments(Argument[] args, MapFile map)
        {
            StringBuilder sb = new StringBuilder();
            foreach (Argument arg in args)
            {
                if (sb.Length > 0) { sb.Append(", "); }

                sb.Append(arg.Type);
                sb.Append(' ');
                sb.Append(arg.Name);
            }

            return sb.ToString();
        }
Example #14
0
        /// <summary>
        /// Attach to the given process ID.
        /// </summary>
        private void Attach(int pid)
        {
            MapFile mapFile;
            string mapFileName;
            using (var dialog = new OpenFileDialog())
            {
                dialog.Title = "Select map file";
                dialog.DefaultExt = ".d42map";
                if (dialog.ShowDialog(this) != DialogResult.OK)
                    return;
                mapFileName = dialog.FileName;
                mapFile = new MapFile(mapFileName);
            }

            var device = lvDevices.SelectedDevice.Device;
            var connectTask = Task.Factory.StartNew(() => debugger.Connect(device, pid, mapFile, Path.ChangeExtension(mapFileName, "apk")));
            connectTask.ContinueWith(t => debugger.PrepareAsync());
        }
Example #15
0
        /// <summary>
        /// Record the mapping from .NET to Dex
        /// </summary>
        public void RecordMapping(MapFile mapFile)
        {
            // Create mapping
            var dexName = (classDef != null) ? classDef.Fullname : null;
            var mapFileId = (classDef != null) ? classDef.MapFileId : 0;
            var entry = new TypeEntry(typeDef.FullName, typeDef.Scope.Name, dexName, mapFileId);
            if (fieldBuilders != null) fieldBuilders.ForEach(x => x.RecordMapping(entry));
            if (methodBuilders != null) methodBuilders.ForEach(x => x.RecordMapping(entry));
            mapFile.Add(entry);

            // Create mapping of nested classes
            if (nestedBuilders != null) nestedBuilders.ForEach(x => x.RecordMapping(mapFile));
        }
Example #16
0
        /// <summary>
        /// Record the mapping from .NET to Dex
        /// </summary>
        public void RecordMapping(TypeEntry typeEntry, MapFile mapFile)
        {
            var entry = RecordMapping(typeEntry, xMethod, method, dmethod, compiledMethod);

            if (cachedBody != null)
            {
                // take the mapping and debug info from the cached body.
                foreach (var v in cachedBody.MethodEntry.Variables)
                    entry.Variables.Add(v);
                foreach (var p in cachedBody.MethodEntry.Parameters)
                    entry.Parameters.Add(p);

                if (cachedBody.SourceCodePositions.Count > 0)
                {
                    var doc = mapFile.GetOrCreateDocument(cachedBody.SourceCodePositions[0].Document.Path, true);
                    foreach (var pos in cachedBody.SourceCodePositions.Select(p=>p.Position))
                    {
                        var newPos = new DocumentPosition(pos.Start.Line,pos.Start.Column, pos.End.Line, pos.End.Column, typeEntry.Id, dmethod.MapFileId, pos.MethodOffset)
                        {
                            AlwaysKeep = true
                        };
                        doc.Positions.Add(newPos);
                    }
                        
                }
            }
        }
Example #17
0
        /// <summary>
        /// Record the mapping from .NET to Dex
        /// </summary>
        public virtual void RecordMapping(MapFile mapFile)
        {
            var entry = CreateMappingEntry();

            mapFile.Add(entry);

            if (fieldBuilders != null) fieldBuilders.ForEach(x => x.RecordMapping(entry));
            if (methodBuilders != null) methodBuilders.ForEach(x => x.RecordMapping(entry, mapFile));

            // Create mapping of nested classes
            if (nestedBuilders != null) nestedBuilders.ForEach(x => x.RecordMapping(mapFile));
        }
Example #18
0
 /// <summary>
 /// Record the mapping from .NET to Dex
 /// </summary>
 public void RecordMapping(MapFile mapFile)
 {
     var dexName = (classDef != null) ? classDef.Fullname : null;
     var mapFileId = (classDef != null) ? classDef.MapFileId : 0;
     var entry = new TypeEntry(typeDef.ClassName, "<java>", dexName, mapFileId);
     if (fieldBuilders != null) fieldBuilders.ForEach(x => x.RecordMapping(entry));
     if (methodBuilders != null) methodBuilders.ForEach(x => x.RecordMapping(entry));
     mapFile.Add(entry);
 }
Example #19
0
        public override void RecordMapping(MapFile mapFile)
        {
            base.RecordMapping(mapFile);

            // create the mapping for all our instance type.
            foreach (var instance in delegateType.Instances)
            {
                // Create mapping
                var dexName = instance.InstanceDefinition.Fullname;
                var mapFileId = instance.InstanceDefinition.MapFileId;
                var scopeId = XType.ScopeId.Substring(XType.ScopeId.IndexOf(':') + 1);
                scopeId += ":delegate:" + instance.CalledMethod.DeclaringType.ScopeId + "|" + instance.CalledMethod.ScopeId;
                
                var entry = new TypeEntry(Type.FullName, Type.Scope.Name, dexName, mapFileId, scopeId);
                mapFile.Add(entry);
            }
        }
Example #20
0
        /// <summary>
        /// Merge the given set of map files into 1.
        /// </summary>
        private static MapFile MergeMapFiles(List<MapFile> mapFiles)
        {
            if (mapFiles.Count == 0) return new MapFile();
            if (mapFiles.Count == 1) return mapFiles[0];

            var result = new MapFile();
            foreach (var entry in mapFiles.SelectMany(mapFile => mapFile))
            {
                result.Add(entry);
            }
            return result;
        }