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(); }
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); }
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); }
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 ())); } } }
/// <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; } } } }