예제 #1
0
파일: Helpers.cs 프로젝트: BlueSkeye/ApkRe
        internal static string GetClassAndPackageName(IAnnotatableClass item, out string[] packageNameItems)
        {
            if (null == item) { throw new ArgumentNullException(); }
            if (-1 != item.Name.IndexOf('$')) { throw new REException(); }

            string result = item.Name;
            List<string> namespaces = new List<string>();
            for (INamespace scannedNamespace = item.Namespace;
                !scannedNamespace.IsRoot;
                scannedNamespace = scannedNamespace.Parent)
            {
                namespaces.Insert(0, scannedNamespace.Name);
            }
            packageNameItems = (0 == namespaces.Count)
                ? null
                : namespaces.ToArray();
            return result;
        }
예제 #2
0
 internal FileInfo GetClassFileName(IAnnotatableClass item, bool doNotCreate = false)
 {
     string[] packageNameItems;
     string simpleClassName = Helpers.GetClassAndPackageName(item, out packageNameItems);
     DirectoryInfo currentDirectory = _baseDirectory;
     if (null != packageNameItems) {
         for (int index = 0; index < packageNameItems.Length; index++) {
             DirectoryInfo nextDirectory =
                 new DirectoryInfo(Path.Combine(currentDirectory.FullName, packageNameItems[index]));
             if (!nextDirectory.Exists && !doNotCreate) {
                 nextDirectory.Create();
                 nextDirectory.Refresh();
             }
             currentDirectory = nextDirectory;
         }
     }
     // Looks like the FileInfo instance Create call will from time to time trigger an
     // exception when we later attempt to open the file. So we stopped creating the file
     // here.
     return new FileInfo(Path.Combine(currentDirectory.FullName, simpleClassName + ".java"));
 }
예제 #3
0
        /// <summary>Reverse a single class and output result in a file named from
        /// the class name and located in the appropriate directory reflecting the
        /// class package name.</summary>
        /// <param name="item">The class to be reversed.</param>
        /// <param name="reversedMethodsCount">On return this parameter is updated
        /// with the count of methods reversed within this class.</param>
        private void ReverseClass(IAnnotatableClass item, out int reversedMethodsCount)
        {
            FileInfo targetFile = _treeHandler.GetClassFileName(item);
            List<string> headerSourceCode = new List<string>();
            List<string> methodsSourceCode = new List<string>();
            StringBuilder methodsSourceCodeBuilder = new StringBuilder();
            StringBuilder fieldsSourceCodeBuilder = new StringBuilder();
            // TODO : Get rid of this dictionary.
            Dictionary<string, string> namespaceByImportedType = new Dictionary<string,string>();
            List<IJavaType> importedTypes = new List<IJavaType>();

            reversedMethodsCount = 0;
            if (!item.IsAbstract) {
                foreach (IField field in item.EnumerateFields()) {
                    IJavaType fieldType = field.FieldType;
                    if (!importedTypes.Contains(fieldType)) {
                        importedTypes.Add(fieldType);
                    }
                    fieldsSourceCodeBuilder.AppendLine(
                        BuildFieldDefinition(field, namespaceByImportedType));
                }
            #if DBGCFG
                bool debugClassCfg = item.IsAnnotatedWith(CfgDebugAnnotation.Id);
            #endif
                foreach (IAnnotatableMethod method in item.EnumerateMethods()) {
            #if DBGCFG
                    bool debugMethodCfg = debugClassCfg || method.IsAnnotatedWith(CfgDebugAnnotation.Id);
            #endif
                    reversedMethodsCount++;
                    // Extract all instructions from the method byte code.
                    DalvikInstruction[] sparseInstructions = BuildInstructionList(method, _objectResolver);
                    // Construct a first version of the CFG graph.
                    CfgNode methodRootCfgNode = CfgBuilder.BuildBasicTree(method, sparseInstructions
            #if DBGCFG
                        , debugMethodCfg
            #endif
                        );
                    // Ensure each catch block from each try block starts on a block boundary.
                    // Eventually create additional block to enforce the constraint.
                    foreach (ITryBlock scannedBlock in method.EnumerateTryBlocks()) {
                        foreach (IGuardHandler scannedHandler in scannedBlock.EnumerateHandlers()) {
                            CfgBuilder.EnsureBlockBoundary(methodRootCfgNode, scannedHandler.HandlerMethodOffset);
                        }
                    }
                    // Detect cycles in CFG graph.
                    List<CircuitDefinition> circuits =
                        new DirectedGraphCycleFinder(methodRootCfgNode).Resolve();

                    if (0 < circuits.Count) {
                        int circuitId = 1;
                        foreach (CircuitDefinition circuit in circuits) {
                            Console.WriteLine("CIRCUIT #{0} ------------------", circuitId++);
                            circuit.Print();
                        }
                        int i = 1;
                    }
                    // Go on now with the AST tree. This is where we perform the real job.
                    // AstNode methodRootAstNode =
                    //    AstBuilder.BuildTree(method, sparseInstructions, methodRootCfgNode, _objectResolver);

                    //// Here we are we a basic CFG graph and an AST tree that is composed only
                    //// of disassembled instruction. Time to augment the AST.
                    //AstBuilder.CreateTryCatch(method, methodRootAstNode, methodRootCfgNode);
                    //methodsSourceCodeBuilder.Append(
                    //    BuildSourceCode(method, methodRootAstNode, namespaceByImportedType));
                    //methodsSourceCodeBuilder.AppendLine();
                }
            }

            FileStream stream = null;
            Console.WriteLine("Generating source code in {0} -------------------------",
                targetFile.FullName);

            try {
                stream = File.Open(targetFile.FullName, FileMode.Create, FileAccess.ReadWrite,
                    FileShare.ReadWrite);

                using (StreamWriter writer = new StreamWriter(stream)) {
                    writer.Write(BuildClassHeaderSourceCode(item, importedTypes).ToString());
                    writer.WriteLine("// FIELDS -----------------");
                    writer.Write(fieldsSourceCodeBuilder.ToString());
                    writer.WriteLine("// METHODS -----------------");
                    writer.Write(methodsSourceCodeBuilder.ToString());
                    // Class closing curly braces.
                    writer.WriteLine("}");
                }
            }
            finally { if (null != stream) { stream.Close(); } }
        }