Exemplo n.º 1
0
        /// <exception cref="IOException"/>
        public virtual void ProcessClass(ClassesProcessor.ClassNode node)
        {
            foreach (ClassesProcessor.ClassNode child in node.nested)
            {
                ProcessClass(child);
            }
            ClassesProcessor clProcessor = DecompilerContext.GetClassProcessor();
            StructClass      cl          = node.classStruct;

            if (cl.GetBytecodeVersion() < ICodeConstants.Bytecode_Java_8)
            {
                // lambda beginning with Java 8
                return;
            }
            StructBootstrapMethodsAttribute bootstrap = cl.GetAttribute(StructGeneralAttribute
                                                                        .Attribute_Bootstrap_Methods);

            if (bootstrap == null || bootstrap.GetMethodsNumber() == 0)
            {
                return;
            }
            // no bootstrap constants in pool
            BitSet lambda_methods = new BitSet();

            // find lambda bootstrap constants
            for (int i = 0; i < bootstrap.GetMethodsNumber(); ++i)
            {
                LinkConstant method_ref = bootstrap.GetMethodReference(i);
                // method handle
                // FIXME: extend for Eclipse etc. at some point
                if (Javac_Lambda_Class.Equals(method_ref.classname) && (Javac_Lambda_Method.Equals
                                                                            (method_ref.elementname) || Javac_Lambda_Alt_Method.Equals(method_ref.elementname
                                                                                                                                       )))
                {
                    lambda_methods.Set(i);
                }
            }
            if (lambda_methods.IsEmpty())
            {
                return;
            }
            // no lambda bootstrap constant found
            Dictionary <string, string> mapMethodsLambda = new Dictionary <string, string>();

            // iterate over code and find invocations of bootstrap methods. Replace them with anonymous classes.
            foreach (StructMethod mt in cl.GetMethods())
            {
                mt.ExpandData();
                InstructionSequence seq = mt.GetInstructionSequence();
                if (seq != null && seq.Length() > 0)
                {
                    int len = seq.Length();
                    for (int i = 0; i < len; ++i)
                    {
                        Instruction instr = seq.GetInstr(i);
                        if (instr.opcode == ICodeConstants.opc_invokedynamic)
                        {
                            LinkConstant invoke_dynamic = cl.GetPool().GetLinkConstant(instr.Operand(0));
                            if (lambda_methods.Get(invoke_dynamic.index1))
                            {
                                // lambda invocation found
                                List <PooledConstant> bootstrap_arguments = bootstrap.GetMethodArguments(invoke_dynamic
                                                                                                         .index1);
                                MethodDescriptor md = MethodDescriptor.ParseDescriptor(invoke_dynamic.descriptor);
                                string           lambda_class_name        = md.ret.value;
                                string           lambda_method_name       = invoke_dynamic.elementname;
                                string           lambda_method_descriptor = ((PrimitiveConstant)bootstrap_arguments[2]).GetString
                                                                                ();
                                // method type
                                LinkConstant content_method_handle     = (LinkConstant)bootstrap_arguments[1];
                                ClassesProcessor.ClassNode node_lambda = new ClassesProcessor.ClassNode(content_method_handle
                                                                                                        .classname, content_method_handle.elementname, content_method_handle.descriptor,
                                                                                                        content_method_handle.index1, lambda_class_name, lambda_method_name, lambda_method_descriptor
                                                                                                        , cl);
                                node_lambda.simpleName = cl.qualifiedName + "##Lambda_" + invoke_dynamic.index1 +
                                                         "_" + invoke_dynamic.index2;
                                node_lambda.enclosingMethod = InterpreterUtil.MakeUniqueKey(mt.GetName(), mt.GetDescriptor
                                                                                                ());
                                node.nested.Add(node_lambda);
                                node_lambda.parent = node;
                                Sharpen.Collections.Put(clProcessor.GetMapRootClasses(), node_lambda.simpleName,
                                                        node_lambda);
                                if (!node_lambda.lambdaInformation.is_method_reference)
                                {
                                    Sharpen.Collections.Put(mapMethodsLambda, node_lambda.lambdaInformation.content_method_key
                                                            , node_lambda.simpleName);
                                }
                            }
                        }
                    }
                }
                mt.ReleaseResources();
            }
            // build class hierarchy on lambda
            foreach (ClassesProcessor.ClassNode nd in node.nested)
            {
                if (nd.type == ClassesProcessor.ClassNode.Class_Lambda)
                {
                    string parent_class_name = mapMethodsLambda.GetOrNull(nd.enclosingMethod);
                    if (parent_class_name != null)
                    {
                        ClassesProcessor.ClassNode parent_class = clProcessor.GetMapRootClasses().GetOrNull
                                                                      (parent_class_name);
                        parent_class.nested.Add(nd);
                        nd.parent = parent_class;
                    }
                }
            }
        }
        /// <exception cref="System.IO.IOException"/>
        public static RootStatement CodeToJava(StructMethod mt, MethodDescriptor md, VarProcessor
                                               varProc)
        {
            StructClass cl            = mt.GetClassStruct();
            bool        isInitializer = ICodeConstants.Clinit_Name.Equals(mt.GetName());

            // for now static initializer only
            mt.ExpandData();
            InstructionSequence seq   = mt.GetInstructionSequence();
            ControlFlowGraph    graph = new ControlFlowGraph(seq);

            DeadCodeHelper.RemoveDeadBlocks(graph);
            graph.InlineJsr(mt);
            // TODO: move to the start, before jsr inlining
            DeadCodeHelper.ConnectDummyExitBlock(graph);
            DeadCodeHelper.RemoveGotos(graph);
            ExceptionDeobfuscator.RemoveCircularRanges(graph);
            ExceptionDeobfuscator.RestorePopRanges(graph);
            if (DecompilerContext.GetOption(IFernflowerPreferences.Remove_Empty_Ranges))
            {
                ExceptionDeobfuscator.RemoveEmptyRanges(graph);
            }
            if (DecompilerContext.GetOption(IFernflowerPreferences.Ensure_Synchronized_Monitor
                                            ))
            {
                // special case: search for 'synchronized' ranges w/o monitorexit instruction (as generated by Kotlin and Scala)
                DeadCodeHelper.ExtendSynchronizedRangeToMonitorexit(graph);
            }
            if (DecompilerContext.GetOption(IFernflowerPreferences.No_Exceptions_Return))
            {
                // special case: single return instruction outside of a protected range
                DeadCodeHelper.IncorporateValueReturns(graph);
            }
            //		ExceptionDeobfuscator.restorePopRanges(graph);
            ExceptionDeobfuscator.InsertEmptyExceptionHandlerBlocks(graph);
            DeadCodeHelper.MergeBasicBlocks(graph);
            DecompilerContext.GetCounterContainer().SetCounter(CounterContainer.Var_Counter,
                                                               mt.GetLocalVariables());
            if (ExceptionDeobfuscator.HasObfuscatedExceptions(graph))
            {
                DecompilerContext.GetLogger().WriteMessage("Heavily obfuscated exception ranges found!"
                                                           , IFernflowerLogger.Severity.Warn);
                if (!ExceptionDeobfuscator.HandleMultipleEntryExceptionRanges(graph))
                {
                    DecompilerContext.GetLogger().WriteMessage("Found multiple entry exception ranges which could not be splitted"
                                                               , IFernflowerLogger.Severity.Warn);
                }
                ExceptionDeobfuscator.InsertDummyExceptionHandlerBlocks(graph, cl.GetBytecodeVersion
                                                                            ());
            }
            RootStatement    root  = DomHelper.ParseGraph(graph);
            FinallyProcessor fProc = new FinallyProcessor(md, varProc);

            while (fProc.IterateGraph(mt, root, graph))
            {
                root = DomHelper.ParseGraph(graph);
            }
            // remove synchronized exception handler
            // not until now because of comparison between synchronized statements in the finally cycle
            DomHelper.RemoveSynchronizedHandler(root);
            //		LabelHelper.lowContinueLabels(root, new HashSet<StatEdge>());
            SequenceHelper.CondenseSequences(root);
            ClearStructHelper.ClearStatements(root);
            ExprProcessor proc = new ExprProcessor(md, varProc);

            proc.ProcessStatement(root, cl);
            SequenceHelper.CondenseSequences(root);
            StackVarsProcessor stackProc = new StackVarsProcessor();

            do
            {
                stackProc.SimplifyStackVars(root, mt, cl);
                varProc.SetVarVersions(root);
            }while (new PPandMMHelper().FindPPandMM(root));
            while (true)
            {
                LabelHelper.CleanUpEdges(root);
                do
                {
                    MergeHelper.EnhanceLoops(root);
                }while (LoopExtractHelper.ExtractLoops(root) || IfHelper.MergeAllIfs(root));
                if (DecompilerContext.GetOption(IFernflowerPreferences.Idea_Not_Null_Annotation))
                {
                    if (IdeaNotNullHelper.RemoveHardcodedChecks(root, mt))
                    {
                        SequenceHelper.CondenseSequences(root);
                        stackProc.SimplifyStackVars(root, mt, cl);
                        varProc.SetVarVersions(root);
                    }
                }
                LabelHelper.IdentifyLabels(root);
                if (InlineSingleBlockHelper.InlineSingleBlocks(root))
                {
                    continue;
                }
                // initializer may have at most one return point, so no transformation of method exits permitted
                if (isInitializer || !ExitHelper.CondenseExits(root))
                {
                    break;
                }
            }
            // FIXME: !!
            //if(!EliminateLoopsHelper.eliminateLoops(root)) {
            //  break;
            //}
            ExitHelper.RemoveRedundantReturns(root);
            SecondaryFunctionsHelper.IdentifySecondaryFunctions(root, varProc);
            varProc.SetVarDefinitions(root);
            // must be the last invocation, because it makes the statement structure inconsistent
            // FIXME: new edge type needed
            LabelHelper.ReplaceContinueWithBreak(root);
            mt.ReleaseResources();
            return(root);
        }