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); }
public virtual void LoadClasses(IIdentifierRenamer renamer) { Dictionary <string, ClassesProcessor.Inner> mapInnerClasses = new Dictionary <string , ClassesProcessor.Inner>(); Dictionary <string, HashSet <string> > mapNestedClassReferences = new Dictionary <string , HashSet <string> >(); Dictionary <string, HashSet <string> > mapEnclosingClassReferences = new Dictionary <string, HashSet <string> >(); Dictionary <string, string> mapNewSimpleNames = new Dictionary <string, string>(); bool bDecompileInner = DecompilerContext.GetOption(IFernflowerPreferences.Decompile_Inner ); bool verifyAnonymousClasses = DecompilerContext.GetOption(IFernflowerPreferences .Verify_Anonymous_Classes); // create class nodes foreach (StructClass cl in context.GetClasses().Values) { if (cl.IsOwn() && !mapRootClasses.ContainsKey(cl.qualifiedName)) { if (bDecompileInner) { StructInnerClassesAttribute inner = cl.GetAttribute(StructGeneralAttribute.Attribute_Inner_Classes ); if (inner != null) { foreach (StructInnerClassesAttribute.Entry entry in inner.GetEntries()) { string innerName = entry.innerName; // original simple name string simpleName = entry.simpleName; string savedName = mapNewSimpleNames.GetOrNull(innerName); if (savedName != null) { simpleName = savedName; } else if (simpleName != null && renamer != null && renamer.ToBeRenamed(IIdentifierRenamer.Type .Element_Class, simpleName, null, null)) { simpleName = renamer.GetNextClassName(innerName, simpleName); Sharpen.Collections.Put(mapNewSimpleNames, innerName, simpleName); } ClassesProcessor.Inner rec = new ClassesProcessor.Inner(); rec.simpleName = simpleName; rec.type = entry.simpleNameIdx == 0 ? ClassesProcessor.ClassNode.Class_Anonymous : entry.outerNameIdx == 0 ? ClassesProcessor.ClassNode.Class_Local : ClassesProcessor.ClassNode .Class_Member; rec.accessFlags = entry.accessFlags; // enclosing class string enclClassName = entry.outerNameIdx != 0 ? entry.enclosingName : cl.qualifiedName; if (enclClassName == null || innerName.Equals(enclClassName)) { continue; } // invalid name or self reference if (rec.type == ClassesProcessor.ClassNode.Class_Member && !innerName.Equals(enclClassName + '$' + entry.simpleName)) { continue; } // not a real inner class StructClass enclosingClass = context.GetClasses().GetOrNull(enclClassName); if (enclosingClass != null && enclosingClass.IsOwn()) { // own classes only ClassesProcessor.Inner existingRec = mapInnerClasses.GetOrNull(innerName); if (existingRec == null) { Sharpen.Collections.Put(mapInnerClasses, innerName, rec); } else if (!ClassesProcessor.Inner.Equal(existingRec, rec)) { string message = "Inconsistent inner class entries for " + innerName + "!"; DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn ); } // reference to the nested class mapNestedClassReferences.ComputeIfAbsent(enclClassName, (string k) => new HashSet <string>()).Add(innerName); // reference to the enclosing class mapEnclosingClassReferences.ComputeIfAbsent(innerName, (string k) => new HashSet < string>()).Add(enclClassName); } } } } ClassesProcessor.ClassNode node = new ClassesProcessor.ClassNode(ClassesProcessor.ClassNode .Class_Root, cl); node.access = cl.GetAccessFlags(); Sharpen.Collections.Put(mapRootClasses, cl.qualifiedName, node); } } if (bDecompileInner) { // connect nested classes foreach (KeyValuePair <string, ClassesProcessor.ClassNode> ent in mapRootClasses) { // root class? if (!mapInnerClasses.ContainsKey(ent.Key)) { HashSet <string> setVisited = new HashSet <string>(); LinkedList <string> stack = new LinkedList <string>(); stack.AddLast(ent.Key); setVisited.Add(ent.Key); while (!(stack.Count == 0)) { string superClass = Sharpen.Collections.RemoveFirst(stack); ClassesProcessor.ClassNode superNode = mapRootClasses.GetOrNull(superClass); HashSet <string> setNestedClasses = mapNestedClassReferences.GetOrNull(superClass); if (setNestedClasses != null) { StructClass scl = superNode.classStruct; StructInnerClassesAttribute inner = scl.GetAttribute(StructGeneralAttribute.Attribute_Inner_Classes ); if (inner == null || (inner.GetEntries().Count == 0)) { DecompilerContext.GetLogger().WriteMessage(superClass + " does not contain inner classes!" , IFernflowerLogger.Severity.Warn); continue; } foreach (StructInnerClassesAttribute.Entry entry in inner.GetEntries()) { string nestedClass = entry.innerName; if (!setNestedClasses.Contains(nestedClass)) { continue; } if (!setVisited.Add(nestedClass)) { continue; } ClassesProcessor.ClassNode nestedNode = mapRootClasses.GetOrNull(nestedClass); if (nestedNode == null) { DecompilerContext.GetLogger().WriteMessage("Nested class " + nestedClass + " missing!" , IFernflowerLogger.Severity.Warn); continue; } ClassesProcessor.Inner rec = mapInnerClasses.GetOrNull(nestedClass); //if ((Integer)arr[2] == ClassNode.CLASS_MEMBER) { // FIXME: check for consistent naming //} nestedNode.simpleName = rec.simpleName; nestedNode.type = rec.type; nestedNode.access = rec.accessFlags; // sanity checks of the class supposed to be anonymous if (verifyAnonymousClasses && nestedNode.type == ClassesProcessor.ClassNode.Class_Anonymous && !IsAnonymous(nestedNode.classStruct, scl)) { nestedNode.type = ClassesProcessor.ClassNode.Class_Local; } if (nestedNode.type == ClassesProcessor.ClassNode.Class_Anonymous) { StructClass cl = nestedNode.classStruct; // remove static if anonymous class (a common compiler bug) nestedNode.access &= ~ICodeConstants.Acc_Static; int[] interfaces = cl.GetInterfaces(); if (interfaces.Length > 0) { nestedNode.anonymousClassType = new VarType(cl.GetInterface(0), true); } else { nestedNode.anonymousClassType = new VarType(cl.superClass.GetString(), true); } } else if (nestedNode.type == ClassesProcessor.ClassNode.Class_Local) { // only abstract and final are permitted (a common compiler bug) nestedNode.access &= (ICodeConstants.Acc_Abstract | ICodeConstants.Acc_Final); } superNode.nested.Add(nestedNode); nestedNode.parent = superNode; Sharpen.Collections.AddAll(nestedNode.enclosingClasses, mapEnclosingClassReferences .GetOrNull(nestedClass)); stack.AddLast(nestedClass); } } } } } } }
private static string IsClass14Invocation(Exprent exprent, ClassWrapper wrapper, MethodWrapper meth) { if (exprent.type == Exprent.Exprent_Function) { FunctionExprent fexpr = (FunctionExprent)exprent; if (fexpr.GetFuncType() == FunctionExprent.Function_Iif) { if (fexpr.GetLstOperands()[0].type == Exprent.Exprent_Function) { FunctionExprent headexpr = (FunctionExprent)fexpr.GetLstOperands()[0]; if (headexpr.GetFuncType() == FunctionExprent.Function_Eq) { if (headexpr.GetLstOperands()[0].type == Exprent.Exprent_Field && headexpr.GetLstOperands ()[1].type == Exprent.Exprent_Const && ((ConstExprent)headexpr.GetLstOperands()[ 1]).GetConstType().Equals(VarType.Vartype_Null)) { FieldExprent field = (FieldExprent)headexpr.GetLstOperands()[0]; ClassesProcessor.ClassNode fieldnode = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(field.GetClassname()); if (fieldnode != null && fieldnode.classStruct.qualifiedName.Equals(wrapper.GetClassStruct ().qualifiedName)) { // source class StructField fd = wrapper.GetClassStruct().GetField(field.GetName(), field.GetDescriptor ().descriptorString); // FIXME: can be null! why?? if (fd != null && fd.HasModifier(ICodeConstants.Acc_Static) && (fd.IsSynthetic() || DecompilerContext.GetOption(IFernflowerPreferences.Synthetic_Not_Set))) { if (fexpr.GetLstOperands()[1].type == Exprent.Exprent_Assignment && fexpr.GetLstOperands ()[2].Equals(field)) { AssignmentExprent asexpr = (AssignmentExprent)fexpr.GetLstOperands()[1]; if (asexpr.GetLeft().Equals(field) && asexpr.GetRight().type == Exprent.Exprent_Invocation) { InvocationExprent invexpr = (InvocationExprent)asexpr.GetRight(); if (invexpr.GetClassname().Equals(wrapper.GetClassStruct().qualifiedName) && invexpr .GetName().Equals(meth.methodStruct.GetName()) && invexpr.GetStringDescriptor(). Equals(meth.methodStruct.GetDescriptor())) { if (invexpr.GetLstParameters()[0].type == Exprent.Exprent_Const) { wrapper.GetHiddenMembers().Add(InterpreterUtil.MakeUniqueKey(fd.GetName(), fd.GetDescriptor ())); // hide synthetic field return(((ConstExprent)invexpr.GetLstParameters()[0]).GetValue().ToString()); } } } } } } } } } } } return(null); }
private static bool ReplaceAssertion(Statement parent, IfStatement stat, string classname , string key) { bool throwInIf = true; Statement ifstat = stat.GetIfstat(); InvocationExprent throwError = IsAssertionError(ifstat); if (throwError == null) { //check else: Statement elsestat = stat.GetElsestat(); throwError = IsAssertionError(elsestat); if (throwError == null) { return(false); } else { throwInIf = false; } } object[] exprres = GetAssertionExprent(stat.GetHeadexprent().GetCondition().Copy( ), classname, key, throwInIf); if (!(bool)exprres[1]) { return(false); } List <Exprent> lstParams = new List <Exprent>(); Exprent ascond = null; Exprent retcond = null; if (throwInIf) { if (exprres[0] != null) { ascond = new FunctionExprent(FunctionExprent.Function_Bool_Not, (Exprent)exprres[ 0], throwError.bytecode); retcond = SecondaryFunctionsHelper.PropagateBoolNot(ascond); } } else { ascond = (Exprent)exprres[0]; retcond = ascond; } lstParams.Add(retcond == null ? ascond : retcond); if (!(throwError.GetLstParameters().Count == 0)) { lstParams.Add(throwError.GetLstParameters()[0]); } AssertExprent asexpr = new AssertExprent(lstParams); Statement newstat = new BasicBlockStatement(new BasicBlock(DecompilerContext.GetCounterContainer ().GetCounterAndIncrement(CounterContainer.Statement_Counter))); newstat.SetExprents(Sharpen.Arrays.AsList(new Exprent[] { asexpr })); Statement first = stat.GetFirst(); if (stat.iftype == IfStatement.Iftype_Ifelse || (first.GetExprents() != null && ! (first.GetExprents().Count == 0))) { first.RemoveSuccessor(stat.GetIfEdge()); first.RemoveSuccessor(stat.GetElseEdge()); List <Statement> lstStatements = new List <Statement>(); if (first.GetExprents() != null && !(first.GetExprents().Count == 0)) { lstStatements.Add(first); } lstStatements.Add(newstat); if (stat.iftype == IfStatement.Iftype_Ifelse) { if (throwInIf) { lstStatements.Add(stat.GetElsestat()); } else { lstStatements.Add(stat.GetIfstat()); } } SequenceStatement sequence = new SequenceStatement(lstStatements); sequence.SetAllParent(); for (int i = 0; i < sequence.GetStats().Count - 1; i++) { sequence.GetStats()[i].AddSuccessor(new StatEdge(StatEdge.Type_Regular, sequence. GetStats()[i], sequence.GetStats()[i + 1])); } if (stat.iftype == IfStatement.Iftype_Ifelse || !throwInIf) { Statement stmts; if (throwInIf) { stmts = stat.GetElsestat(); } else { stmts = stat.GetIfstat(); } List <StatEdge> lstSuccs = stmts.GetAllSuccessorEdges(); if (!(lstSuccs.Count == 0)) { StatEdge endedge = lstSuccs[0]; if (endedge.closure == stat) { sequence.AddLabeledEdge(endedge); } } } newstat = sequence; } Sharpen.Collections.AddAll(newstat.GetVarDefinitions(), stat.GetVarDefinitions()); parent.ReplaceStatement(stat, newstat); return(true); }
public virtual void ClearContext() { DecompilerContext.SetCurrentContext(null); }
private static void ExtractDynamicInitializers(ClassWrapper wrapper) { StructClass cl = wrapper.GetClassStruct(); bool isAnonymous = DecompilerContext.GetClassProcessor().GetMapRootClasses().GetOrNull (cl.qualifiedName).type == ClassesProcessor.ClassNode.Class_Anonymous; List <List <Exprent> > lstFirst = new List <List <Exprent> >(); List <MethodWrapper> lstMethodWrappers = new List <MethodWrapper>(); foreach (MethodWrapper method in wrapper.GetMethods()) { if (ICodeConstants.Init_Name.Equals(method.methodStruct.GetName()) && method.root != null) { // successfully decompiled constructor Statement firstData = Statements.FindFirstData(method.root); if (firstData == null || (firstData.GetExprents().Count == 0)) { return; } lstFirst.Add(firstData.GetExprents()); lstMethodWrappers.Add(method); Exprent exprent = firstData.GetExprents()[0]; if (!isAnonymous) { // FIXME: doesn't make sense if (exprent.type != Exprent.Exprent_Invocation || !Statements.IsInvocationInitConstructor ((InvocationExprent)exprent, method, wrapper, false)) { return; } } } } if ((lstFirst.Count == 0)) { return; } while (true) { string fieldWithDescr = null; Exprent value = null; for (int i = 0; i < lstFirst.Count; i++) { List <Exprent> lst = lstFirst[i]; if (lst.Count < (isAnonymous ? 1 : 2)) { return; } Exprent exprent = lst[isAnonymous ? 0 : 1]; bool found = false; if (exprent.type == Exprent.Exprent_Assignment) { AssignmentExprent assignExpr = (AssignmentExprent)exprent; if (assignExpr.GetLeft().type == Exprent.Exprent_Field) { FieldExprent fExpr = (FieldExprent)assignExpr.GetLeft(); if (!fExpr.IsStatic() && fExpr.GetClassname().Equals(cl.qualifiedName) && cl.HasField (fExpr.GetName(), fExpr.GetDescriptor().descriptorString)) { // check for the physical existence of the field. Could be defined in a superclass. if (IsExprentIndependent(assignExpr.GetRight(), lstMethodWrappers[i])) { string fieldKey = InterpreterUtil.MakeUniqueKey(fExpr.GetName(), fExpr.GetDescriptor ().descriptorString); if (fieldWithDescr == null) { fieldWithDescr = fieldKey; value = assignExpr.GetRight(); } else if (!fieldWithDescr.Equals(fieldKey) || !value.Equals(assignExpr.GetRight())) { return; } found = true; } } } } if (!found) { return; } } if (!wrapper.GetDynamicFieldInitializers().ContainsKey(fieldWithDescr)) { wrapper.GetDynamicFieldInitializers().AddWithKey(value, fieldWithDescr); foreach (List <Exprent> lst in lstFirst) { lst.RemoveAtReturningValue(isAnonymous ? 0 : 1); } } else { return; } } }
public static void SetCurrentContext(DecompilerContext context) { currentContext.Value = context; }