예제 #1
0
        public virtual void Init()
        {
            DecompilerContext.SetProperty(DecompilerContext.Current_Class, classStruct);
            DecompilerContext.SetProperty(DecompilerContext.Current_Class_Wrapper, this);
            DecompilerContext.GetLogger().StartClass(classStruct.qualifiedName);
            int maxSec = System.Convert.ToInt32(DecompilerContext.GetProperty(IFernflowerPreferences
                                                                              .Max_Processing_Method).ToString());
            bool testMode = DecompilerContext.GetOption(IFernflowerPreferences.Unit_Test_Mode
                                                        );

            foreach (StructMethod mt in classStruct.GetMethods())
            {
                DecompilerContext.GetLogger().StartMethod(mt.GetName() + " " + mt.GetDescriptor()
                                                          );
                MethodDescriptor md      = MethodDescriptor.ParseDescriptor(mt.GetDescriptor());
                VarProcessor     varProc = new VarProcessor(mt, md);
                DecompilerContext.StartMethod(varProc);
                VarNamesCollector vc      = varProc.GetVarNamesCollector();
                CounterContainer  counter = DecompilerContext.GetCounterContainer();
                RootStatement     root    = null;
                bool isError = false;
                try
                {
                    if (mt.ContainsCode())
                    {
                        if (maxSec == 0 || testMode)
                        {
                            root = MethodProcessorRunnable.CodeToJava(mt, md, varProc);
                        }
                        else
                        {
                            MethodProcessorRunnable mtProc = new MethodProcessorRunnable(mt, md, varProc, DecompilerContext
                                                                                         .GetCurrentContext());
                            Thread mtThread = new Thread(o => mtProc.Run())
                            {
                                Name = "Java decompiler"
                            };
                            long stopAt = Runtime.CurrentTimeMillis() + maxSec * 1000L;
                            mtThread.Start();
                            while (!mtProc.IsFinished())
                            {
                                try
                                {
                                    lock (mtProc.Lock)
                                    {
                                        Thread.Sleep(200);
                                    }
                                }
                                catch (Exception e)
                                {
                                    KillThread(mtThread);
                                    throw;
                                }
                                if (Runtime.CurrentTimeMillis() >= stopAt)
                                {
                                    string message = "Processing time limit exceeded for method " + mt.GetName() + ", execution interrupted.";
                                    DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Error
                                                                               );
                                    KillThread(mtThread);
                                    isError = true;
                                    break;
                                }
                            }
                            if (!isError)
                            {
                                root = mtProc.GetResult();
                            }
                        }
                    }
                    else
                    {
                        bool thisVar    = !mt.HasModifier(ICodeConstants.Acc_Static);
                        int  paramCount = 0;
                        if (thisVar)
                        {
                            Sharpen.Collections.Put(varProc.GetThisVars(), new VarVersionPair(0, 0), classStruct
                                                    .qualifiedName);
                            paramCount = 1;
                        }
                        paramCount += [email protected];
                        int varIndex = 0;
                        for (int i = 0; i < paramCount; i++)
                        {
                            varProc.SetVarName(new VarVersionPair(varIndex, 0), vc.GetFreeName(varIndex));
                            if (thisVar)
                            {
                                if (i == 0)
                                {
                                    varIndex++;
                                }
                                else
                                {
                                    varIndex += md.@params[i - 1].stackSize;
                                }
                            }
                            else
                            {
                                varIndex += md.@params[i].stackSize;
                            }
                        }
                    }
                }
                catch (Exception t)
                {
                    string message = "Method " + mt.GetName() + " " + mt.GetDescriptor() + " couldn't be decompiled.";
                    DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn
                                                               , t);
                    isError = true;
                }
                MethodWrapper methodWrapper = new MethodWrapper(root, varProc, mt, counter);
                methodWrapper.decompiledWithErrors = isError;
                methods.AddWithKey(methodWrapper, InterpreterUtil.MakeUniqueKey(mt.GetName(), mt.
                                                                                GetDescriptor()));
                if (!isError)
                {
                    // rename vars so that no one has the same name as a field
                    VarNamesCollector namesCollector = new VarNamesCollector();
                    classStruct.GetFields().ForEach((StructField f) => namesCollector.AddName(f.GetName
                                                                                                  ()));
                    varProc.RefreshVarNames(namesCollector);
                    // if debug information present and should be used
                    if (DecompilerContext.GetOption(IFernflowerPreferences.Use_Debug_Var_Names))
                    {
                        StructLocalVariableTableAttribute attr = mt.GetLocalVariableAttr();
                        if (attr != null)
                        {
                            // only param names here
                            varProc.SetDebugVarNames(attr.GetMapParamNames());
                            // the rest is here
                            methodWrapper.GetOrBuildGraph().IterateExprents((Exprent exprent) => {
                                List <Exprent> lst = exprent.GetAllExprents(true);
                                lst.Add(exprent);
                                lst.Where(e => e.type == Exprent.Exprent_Var).ToList().ForEach((Exprent
                                                                                                e) => {
                                    VarExprent varExprent = (VarExprent)e;
                                    string name           = varExprent.GetDebugName(mt);
                                    if (name != null)
                                    {
                                        varProc.SetVarName(varExprent.GetVarVersionPair(), name);
                                    }
                                }
                                                                                               );
                                return(0);
                            }
                                                                            );
                        }
                    }
                }
                DecompilerContext.GetLogger().EndMethod();
            }
            DecompilerContext.GetLogger().EndClass();
        }
예제 #2
0
        private static bool IsAnonymous(StructClass cl, StructClass enclosingCl)
        {
            // checking super class and interfaces
            int[] interfaces = cl.GetInterfaces();
            if (interfaces.Length > 0)
            {
                bool hasNonTrivialSuperClass = cl.superClass != null && !VarType.Vartype_Object.Equals
                                                   (new VarType(cl.superClass.GetString(), true));
                if (hasNonTrivialSuperClass || interfaces.Length > 1)
                {
                    // can't have multiple 'sources'
                    string message = "Inconsistent anonymous class definition: '" + cl.qualifiedName
                                     + "'. Multiple interfaces and/or super class defined.";
                    DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn
                                                               );
                    return(false);
                }
            }
            else if (cl.superClass == null)
            {
                // neither interface nor super class defined
                string message = "Inconsistent anonymous class definition: '" + cl.qualifiedName
                                 + "'. Neither interface nor super class defined.";
                DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn
                                                           );
                return(false);
            }
            // FIXME: check constructors
            // FIXME: check enclosing class/method
            ConstantPool pool       = enclosingCl.GetPool();
            int          refCounter = 0;
            bool         refNotNew  = false;
            StructEnclosingMethodAttribute attribute = cl.GetAttribute(StructGeneralAttribute
                                                                       .Attribute_Enclosing_Method);
            string enclosingMethod = attribute != null?attribute.GetMethodName() : null;

            // checking references in the enclosing class
            foreach (StructMethod mt in enclosingCl.GetMethods())
            {
                if (enclosingMethod != null && !enclosingMethod.Equals(mt.GetName()))
                {
                    continue;
                }
                try
                {
                    mt.ExpandData();
                    InstructionSequence seq = mt.GetInstructionSequence();
                    if (seq != null)
                    {
                        int len = seq.Length();
                        for (int i = 0; i < len; i++)
                        {
                            Instruction instr = seq.GetInstr(i);
                            switch (instr.opcode)
                            {
                            case opc_checkcast:
                            case opc_instanceof:
                            {
                                if (cl.qualifiedName.Equals(pool.GetPrimitiveConstant(instr.Operand(0)).GetString
                                                                ()))
                                {
                                    refCounter++;
                                    refNotNew = true;
                                }
                                break;
                            }

                            case opc_new:
                            case opc_anewarray:
                            case opc_multianewarray:
                            {
                                if (cl.qualifiedName.Equals(pool.GetPrimitiveConstant(instr.Operand(0)).GetString
                                                                ()))
                                {
                                    refCounter++;
                                }
                                break;
                            }

                            case opc_getstatic:
                            case opc_putstatic:
                            {
                                if (cl.qualifiedName.Equals(pool.GetLinkConstant(instr.Operand(0)).classname))
                                {
                                    refCounter++;
                                    refNotNew = true;
                                }
                                break;
                            }
                            }
                        }
                    }
                    mt.ReleaseResources();
                }
                catch (IOException)
                {
                    string message = "Could not read method while checking anonymous class definition: '"
                                     + enclosingCl.qualifiedName + "', '" + InterpreterUtil.MakeUniqueKey(mt.GetName
                                                                                                              (), mt.GetDescriptor()) + "'";
                    DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn
                                                               );
                    return(false);
                }
                if (refCounter > 1 || refNotNew)
                {
                    string message = "Inconsistent references to the class '" + cl.qualifiedName + "' which is supposed to be anonymous";
                    DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn
                                                               );
                    return(false);
                }
            }
            return(true);
        }
예제 #3
0
        private BitSet GetAmbiguousParameters()
        {
            StructClass cl = DecompilerContext.GetStructContext().GetClass(classname);

            if (cl == null)
            {
                return(Empty_Bit_Set);
            }
            // check number of matches
            List <MethodDescriptor> matches = new List <MethodDescriptor>();

            foreach (StructMethod mt in cl.GetMethods())
            {
                if (name.Equals(mt.GetName()))
                {
                    MethodDescriptor md = MethodDescriptor.ParseDescriptor(mt.GetDescriptor());
                    if ([email protected] == [email protected])
                    {
                        for (int i = 0; i < [email protected]; i++)
                        {
                            if (md.@params[i].typeFamily != descriptor.@params[i].typeFamily)
                            {
                                goto nextMethod_continue;
                            }
                        }
                        matches.Add(md);
                    }
                }
            }
            nextMethod_break    :;
            nextMethod_continue :
            if (matches.Count == 1)
            {
                return(Empty_Bit_Set);
            }
            // check if a call is unambiguous
            StructMethod mt_1 = cl.GetMethod(InterpreterUtil.MakeUniqueKey(name, stringDescriptor
                                                                           ));

            if (mt_1 != null)
            {
                MethodDescriptor md = MethodDescriptor.ParseDescriptor(mt_1.GetDescriptor());
                if ([email protected] == lstParameters.Count)
                {
                    bool exact = true;
                    for (int i = 0; i < [email protected]; i++)
                    {
                        if (!md.@params[i].Equals(lstParameters[i].GetExprType()))
                        {
                            exact = false;
                            break;
                        }
                    }
                    if (exact)
                    {
                        return(Empty_Bit_Set);
                    }
                }
            }
            // mark parameters
            BitSet ambiguous = new BitSet([email protected]);

            for (int i = 0; i < [email protected]; i++)
            {
                VarType paramType = descriptor.@params[i];
                foreach (MethodDescriptor md in matches)
                {
                    if (!paramType.Equals(md.@params[i]))
                    {
                        ambiguous.Set(i);
                        break;
                    }
                }
            }
            return(ambiguous);
        }
예제 #4
0
        private void RenameClassIdentifiers(StructClass cl, Dictionary <string, string> names
                                            )
        {
            // all classes are already renamed
            string classOldFullName = cl.qualifiedName;
            string classNewFullName = interceptor.GetName(classOldFullName);

            if (classNewFullName == null)
            {
                classNewFullName = classOldFullName;
            }
            // methods
            HashSet <string> setMethodNames = new HashSet <string>();

            foreach (StructMethod md in cl.GetMethods())
            {
                setMethodNames.Add(md.GetName());
            }
            VBStyleCollection <StructMethod, string> methods = cl.GetMethods();

            for (int i = 0; i < methods.Count; i++)
            {
                StructMethod mt        = methods[i];
                string       key       = methods.GetKey(i);
                bool         isPrivate = mt.HasModifier(ICodeConstants.Acc_Private);
                string       name      = mt.GetName();
                if (!cl.IsOwn() || mt.HasModifier(ICodeConstants.Acc_Native))
                {
                    // external and native methods must not be renamed
                    if (!isPrivate)
                    {
                        Sharpen.Collections.Put(names, key, name);
                    }
                }
                else if (helper.ToBeRenamed(IIdentifierRenamer.Type.Element_Method, classOldFullName
                                            , name, mt.GetDescriptor()))
                {
                    if (isPrivate || !names.ContainsKey(key))
                    {
                        do
                        {
                            name = helper.GetNextMethodName(classOldFullName, name, mt.GetDescriptor());
                        }while (setMethodNames.Contains(name));
                        if (!isPrivate)
                        {
                            Sharpen.Collections.Put(names, key, name);
                        }
                    }
                    else
                    {
                        name = names.GetOrNull(key);
                    }
                    interceptor.AddName(classOldFullName + " " + mt.GetName() + " " + mt.GetDescriptor
                                            (), classNewFullName + " " + name + " " + BuildNewDescriptor(false, mt.GetDescriptor
                                                                                                             ()));
                }
            }
            // external fields are not being renamed
            if (!cl.IsOwn())
            {
                return;
            }
            // fields
            // FIXME: should overloaded fields become the same name?
            HashSet <string> setFieldNames = new HashSet <string>();

            foreach (StructField fd in cl.GetFields())
            {
                setFieldNames.Add(fd.GetName());
            }
            foreach (StructField fd in cl.GetFields())
            {
                if (helper.ToBeRenamed(IIdentifierRenamer.Type.Element_Field, classOldFullName, fd
                                       .GetName(), fd.GetDescriptor()))
                {
                    string newName;
                    do
                    {
                        newName = helper.GetNextFieldName(classOldFullName, fd.GetName(), fd.GetDescriptor
                                                              ());
                    }while (setFieldNames.Contains(newName));
                    interceptor.AddName(classOldFullName + " " + fd.GetName() + " " + fd.GetDescriptor
                                            (), classNewFullName + " " + newName + " " + BuildNewDescriptor(true, fd.GetDescriptor
                                                                                                                ()));
                }
            }
        }
예제 #5
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;
                    }
                }
            }
        }