public override void ValidateSemantics(SemanticsValidator validator) { foreach (var parameter in Parameters) { parameter.ValidateSemantics(validator); } this.StructClass = validator.Container.TryGetClass(CtorName); if (StructClass == null) { validator.AddError("Unknown struct type " + CtorName, ParsingContext); } if (StructClass.Type != ContainerType.@struct) { validator.AddError("Constructors can only be called on struct", ParsingContext); } this.StructClass = validator.Container[CtorName]; this.StructCtor = StructClass.GetCtor(); if (StructCtor == null) { validator.AddError("Unknown struct ctor \"" + StructClass.ClassName + "\"", ParsingContext); } else if (Parameters.Count != StructCtor.Parameters.Count) { validator.AddError("Invalid parameters count for Ctor \"" + StructClass.ClassName + "\"", ParsingContext); } }
public ClassNode(string content_class_name, string content_method_name, string content_method_descriptor , int content_method_invocation_type, string lambda_class_name, string lambda_method_name , string lambda_method_descriptor, StructClass classStruct) { // lambda class constructor this.type = Class_Lambda; this.classStruct = classStruct; // 'parent' class containing the static function lambdaInformation = new ClassesProcessor.ClassNode.LambdaInformation(); lambdaInformation.method_name = lambda_method_name; lambdaInformation.method_descriptor = lambda_method_descriptor; lambdaInformation.content_class_name = content_class_name; lambdaInformation.content_method_name = content_method_name; lambdaInformation.content_method_descriptor = content_method_descriptor; lambdaInformation.content_method_invocation_type = content_method_invocation_type; lambdaInformation.content_method_key = InterpreterUtil.MakeUniqueKey(lambdaInformation .content_method_name, lambdaInformation.content_method_descriptor); anonymousClassType = new VarType(lambda_class_name, true); bool is_method_reference = (content_class_name != classStruct.qualifiedName); if (!is_method_reference) { // content method in the same class, check synthetic flag StructMethod mt = classStruct.GetMethod(content_method_name, content_method_descriptor ); is_method_reference = !mt.IsSynthetic(); } // if not synthetic -> method reference lambdaInformation.is_method_reference = is_method_reference; lambdaInformation.is_content_method_static = (lambdaInformation.content_method_invocation_type == ICodeConstants.CONSTANT_MethodHandle_REF_invokeStatic); }
private static Exprent IsLambda(Exprent exprent, StructClass cl) { List <Exprent> lst = exprent.GetAllExprents(); foreach (Exprent expr in lst) { Exprent ret = IsLambda(expr, cl); if (ret != null) { exprent.ReplaceExprent(expr, ret); } } if (exprent.type == Exprent.Exprent_Invocation) { InvocationExprent @in = (InvocationExprent)exprent; if (@in.GetInvocationTyp() == InvocationExprent.Invoke_Dynamic) { string lambda_class_name = cl.qualifiedName + @in.GetInvokeDynamicClassSuffix(); ClassesProcessor.ClassNode lambda_class = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(lambda_class_name); if (lambda_class != null) { // real lambda class found, replace invocation with an anonymous class NewExprent newExpr = new NewExprent(new VarType(lambda_class_name, true), null, 0 , @in.bytecode); newExpr.SetConstructor(@in); // note: we don't set the instance to null with in.setInstance(null) like it is done for a common constructor invocation // lambda can also be a reference to a virtual method (e.g. String x; ...(x::toString);) // in this case instance will hold the corresponding object return(newExpr); } } } return(null); }
public void TestObjectWithStruct() { var nodeContainer = new NodeContainer(); var instance = new StructClass { Member1 = 3, Member2 = new Struct() }; var rootNode = nodeContainer.GetOrCreateNode(instance); var visitor = new TestVisitor(); visitor.Visit(rootNode); var expectedNodes = new IContentNode[] { rootNode, rootNode[nameof(StructClass.Member1)], rootNode[nameof(StructClass.Member2)], rootNode[nameof(StructClass.Member2)].Target, rootNode[nameof(StructClass.Member2)].Target[nameof(Struct.Member1)], rootNode[nameof(StructClass.Member2)].Target[nameof(Struct.Member2)], }; var expectedPaths = new[] { new GraphNodePath(rootNode), new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member1)), new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)), new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)).PushTarget(), new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)).PushTarget().PushMember(nameof(Struct.Member1)), new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)).PushTarget().PushMember(nameof(Struct.Member2)), }; VerifyNodesAndPath(expectedNodes, expectedPaths, visitor); }
/// <exception cref="System.IO.IOException"/> public virtual void WriteClass(StructClass cl, TextBuffer buffer) { ClassesProcessor.ClassNode root = mapRootClasses.GetOrNull(cl.qualifiedName); if (root.type != ClassesProcessor.ClassNode.Class_Root) { return; } DecompilerContext.GetLogger().StartReadingClass(cl.qualifiedName); try { ImportCollector importCollector = new ImportCollector(root); DecompilerContext.StartClass(importCollector); new LambdaProcessor().ProcessClass(root); // add simple class names to implicit import AddClassnameToImport(root, importCollector); // build wrappers for all nested classes (that's where actual processing takes place) InitWrappers(root); new NestedClassProcessor().ProcessClass(root, root); new NestedMemberAccess().PropagateMemberAccess(root); TextBuffer classBuffer = new TextBuffer(Average_Class_Size); new ClassWriter().ClassToJava(root, classBuffer, 0, null); int index = cl.qualifiedName.LastIndexOf("/"); if (index >= 0) { string packageName = Sharpen.Runtime.Substring(cl.qualifiedName, 0, index).Replace ('/', '.'); buffer.Append("package "); buffer.Append(packageName); buffer.Append(";"); buffer.AppendLineSeparator(); buffer.AppendLineSeparator(); } int import_lines_written = importCollector.WriteImports(buffer); if (import_lines_written > 0) { buffer.AppendLineSeparator(); } int offsetLines = buffer.CountLines(); buffer.Append(classBuffer); if (DecompilerContext.GetOption(IFernflowerPreferences.Bytecode_Source_Mapping)) { BytecodeSourceMapper mapper = DecompilerContext.GetBytecodeSourceMapper(); mapper.AddTotalOffset(offsetLines); if (DecompilerContext.GetOption(IFernflowerPreferences.Dump_Original_Lines)) { buffer.DumpOriginalLineNumbers(mapper.GetOriginalLinesMapping()); } if (DecompilerContext.GetOption(IFernflowerPreferences.Unit_Test_Mode)) { buffer.AppendLineSeparator(); mapper.DumpMapping(buffer, true); } } } finally { DestroyWrappers(root); DecompilerContext.GetLogger().EndReadingClass(); } }
public void TestObjectWithStruct() { var nodeContainer = new NodeContainer(); var instance = new StructClass { Member1 = 3, Member2 = new Struct() }; var rootNode = nodeContainer.GetOrCreateNode(instance); var visitor = new TestVisitor(); visitor.Visit(rootNode); var expectedNodes = new IGraphNode[] { rootNode, rootNode[nameof(StructClass.Member1)], rootNode[nameof(StructClass.Member2)], rootNode[nameof(StructClass.Member2)].Target, rootNode[nameof(StructClass.Member2)].Target[nameof(Struct.Member1)], rootNode[nameof(StructClass.Member2)].Target[nameof(Struct.Member2)], }; var expectedPaths = new GraphNodePath[6]; expectedPaths[0] = new GraphNodePath(rootNode); expectedPaths[1] = expectedPaths[0].Clone(); expectedPaths[1].PushMember(nameof(StructClass.Member1)); expectedPaths[2] = expectedPaths[0].Clone(); expectedPaths[2].PushMember(nameof(StructClass.Member2)); expectedPaths[3] = expectedPaths[2].Clone(); expectedPaths[3].PushTarget(); expectedPaths[4] = expectedPaths[3].Clone(); expectedPaths[4].PushMember(nameof(Struct.Member1)); expectedPaths[5] = expectedPaths[3].Clone(); expectedPaths[5].PushMember(nameof(Struct.Member2)); VerifyNodesAndPath(expectedNodes, expectedPaths, visitor); }
public void TestObjectWithStruct() { var nodeContainer = new NodeContainer(); var instance1 = new StructClass { Member1 = 3, Member2 = new Struct { Member2 = new SimpleClass() } }; var instance2 = new StructClass { Member1 = 3, Member2 = new Struct { Member2 = new SimpleClass() } }; var source = nodeContainer.GetOrCreateNode(instance1); var target = nodeContainer.GetOrCreateNode(instance2); var linker = new TestLinker(); linker.LinkGraph(source, target); var expectedLinks = new Dictionary <IGraphNode, IGraphNode> { { source, target }, { source.GetChild(nameof(StructClass.Member1)), target.GetChild(nameof(StructClass.Member1)) }, { source.GetChild(nameof(StructClass.Member2)), target.GetChild(nameof(StructClass.Member2)) }, { source.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member1)), target.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member1)) }, { source.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)), target.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)) }, { source.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)).GetTarget(), target.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)).GetTarget() }, { source.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)).GetTarget().GetChild(nameof(SimpleClass.Member1)), target.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)).GetTarget().GetChild(nameof(SimpleClass.Member1)) }, { source.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)).GetTarget().GetChild(nameof(SimpleClass.Member2)), target.GetChild(nameof(StructClass.Member2)).GetChild(nameof(Struct.Member2)).GetTarget().GetChild(nameof(SimpleClass.Member2)) }, }; VerifyLinks(expectedLinks, linker); }
private void RenameInterfaces() { List <ClassWrapperNode> lstInterfaces = GetReversePostOrderListIterative(rootInterfaces ); Dictionary <string, Dictionary <string, string> > interfaceNameMaps = new Dictionary <string, Dictionary <string, string> >(); // rename methods and fields foreach (ClassWrapperNode node in lstInterfaces) { StructClass cl = node.GetClassStruct(); Dictionary <string, string> names = new Dictionary <string, string>(); // merge information on super interfaces foreach (string ifName in cl.GetInterfaceNames()) { Dictionary <string, string> mapInt = interfaceNameMaps.GetOrNull(ifName); if (mapInt != null) { Sharpen.Collections.PutAll(names, mapInt); } } RenameClassIdentifiers(cl, names); Sharpen.Collections.Put(interfaceNameMaps, cl.qualifiedName, names); } this.interfaceNameMaps = interfaceNameMaps; }
public ClassNode(int type, StructClass classStruct) { // FIXME: redundant? this.type = type; this.classStruct = classStruct; simpleName = Sharpen.Runtime.Substring(classStruct.qualifiedName, classStruct.qualifiedName .LastIndexOf('/') + 1); }
public ImportCollector(ClassesProcessor.ClassNode root) { // set of field names in this class and all its predecessors. string clName = root.classStruct.qualifiedName; int index = clName.LastIndexOf('/'); if (index >= 0) { string packageName = Sharpen.Runtime.Substring(clName, 0, index); currentPackageSlash = packageName + '/'; currentPackagePoint = packageName.Replace('/', '.'); } else { currentPackageSlash = string.Empty; currentPackagePoint = string.Empty; } Dictionary <string, StructClass> classes = DecompilerContext.GetStructContext().GetClasses (); LinkedList <string> queue = new LinkedList <string>(); StructClass currentClass = root.classStruct; while (currentClass != null) { if (currentClass.superClass != null) { queue.AddLast(currentClass.superClass.GetString()); } Sharpen.Collections.AddAll(queue, currentClass.GetInterfaceNames()); // all field names for the current class .. foreach (StructField f in currentClass.GetFields()) { setFieldNames.Add(f.GetName()); } // .. all inner classes for the current class .. StructInnerClassesAttribute attribute = currentClass.GetAttribute(StructGeneralAttribute .Attribute_Inner_Classes); if (attribute != null) { foreach (StructInnerClassesAttribute.Entry entry in attribute.GetEntries()) { if (entry.enclosingName != null && entry.enclosingName.Equals(currentClass.qualifiedName )) { setInnerClassNames.Add(entry.simpleName); } } } // .. and traverse through parent. currentClass = !(queue.Count == 0) ? classes.GetOrNull(Sharpen.Collections.RemoveFirst (queue)) : null; while (currentClass == null && !(queue.Count == 0)) { currentClass = classes.GetOrNull(Sharpen.Collections.RemoveFirst(queue)); } } }
public static void ClearEnum(ClassWrapper wrapper) { StructClass cl = wrapper.GetClassStruct(); // hide values/valueOf methods and super() invocations foreach (MethodWrapper method in wrapper.GetMethods()) { StructMethod mt = method.methodStruct; string name = mt.GetName(); string descriptor = mt.GetDescriptor(); if ("values".Equals(name)) { if (descriptor.Equals("()[L" + cl.qualifiedName + ";")) { wrapper.GetHiddenMembers().Add(InterpreterUtil.MakeUniqueKey(name, descriptor)); } } else if ("valueOf".Equals(name)) { if (descriptor.Equals("(Ljava/lang/String;)L" + cl.qualifiedName + ";")) { wrapper.GetHiddenMembers().Add(InterpreterUtil.MakeUniqueKey(name, descriptor)); } } else if (ICodeConstants.Init_Name.Equals(name)) { Statement firstData = Statements.FindFirstData(method.root); if (firstData != null && !(firstData.GetExprents().Count == 0)) { Exprent exprent = firstData.GetExprents()[0]; if (exprent.type == Exprent.Exprent_Invocation) { InvocationExprent invExpr = (InvocationExprent)exprent; if (Statements.IsInvocationInitConstructor(invExpr, method, wrapper, false)) { firstData.GetExprents().RemoveAtReturningValue(0); } } } } } // hide synthetic fields of enum and it's constants foreach (StructField fd in cl.GetFields()) { string descriptor = fd.GetDescriptor(); if (fd.IsSynthetic() && descriptor.Equals("[L" + cl.qualifiedName + ";")) { wrapper.GetHiddenMembers().Add(InterpreterUtil.MakeUniqueKey(fd.GetName(), descriptor )); } } }
private void SetInitVars(RootStatement root) { bool thisVar = !method.HasModifier(ICodeConstants.Acc_Static); MethodDescriptor md = methodDescriptor; if (thisVar) { StructClass cl = (StructClass)DecompilerContext.GetProperty(DecompilerContext.Current_Class ); VarType clType = new VarType(ICodeConstants.Type_Object, 0, cl.qualifiedName); Sharpen.Collections.Put(mapExprentMinTypes, new VarVersionPair(0, 1), clType); Sharpen.Collections.Put(mapExprentMaxTypes, new VarVersionPair(0, 1), clType); } int varIndex = 0; for (int i = 0; i < [email protected]; i++) { Sharpen.Collections.Put(mapExprentMinTypes, new VarVersionPair(varIndex + (thisVar ? 1 : 0), 1), md.@params[i]); Sharpen.Collections.Put(mapExprentMaxTypes, new VarVersionPair(varIndex + (thisVar ? 1 : 0), 1), md.@params[i]); varIndex += md.@params[i].stackSize; } // catch variables LinkedList <Statement> stack = new LinkedList <Statement>(); stack.AddLast(root); while (!(stack.Count == 0)) { Statement stat = Sharpen.Collections.RemoveFirst(stack); List <VarExprent> lstVars = null; if (stat.type == Statement.Type_Catchall) { lstVars = ((CatchAllStatement)stat).GetVars(); } else if (stat.type == Statement.Type_Trycatch) { lstVars = ((CatchStatement)stat).GetVars(); } if (lstVars != null) { foreach (VarExprent var in lstVars) { Sharpen.Collections.Put(mapExprentMinTypes, new VarVersionPair(var.GetIndex(), 1) , var.GetVarType()); Sharpen.Collections.Put(mapExprentMaxTypes, new VarVersionPair(var.GetIndex(), 1) , var.GetVarType()); } } Sharpen.Collections.AddAll(stack, stat.GetStats()); } }
private static void ExtractStaticInitializers(ClassWrapper wrapper, MethodWrapper method) { RootStatement root = method.root; StructClass cl = wrapper.GetClassStruct(); Statement firstData = Statements.FindFirstData(root); if (firstData != null) { bool inlineInitializers = cl.HasModifier(ICodeConstants.Acc_Interface) || cl.HasModifier (ICodeConstants.Acc_Enum); while (!(firstData.GetExprents().Count == 0)) { Exprent exprent = firstData.GetExprents()[0]; 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)) { // interfaces fields should always be initialized inline if (inlineInitializers || IsExprentIndependent(assignExpr.GetRight(), method)) { string keyField = InterpreterUtil.MakeUniqueKey(fExpr.GetName(), fExpr.GetDescriptor ().descriptorString); if (!wrapper.GetStaticFieldInitializers().ContainsKey(keyField)) { wrapper.GetStaticFieldInitializers().AddWithKey(assignExpr.GetRight(), keyField); firstData.GetExprents().RemoveAtReturningValue(0); found = true; } } } } } if (!found) { break; } } } }
public virtual string GetClassContent(StructClass cl) { try { TextBuffer buffer = new TextBuffer(ClassesProcessor.Average_Class_Size); buffer.Append(DecompilerContext.GetProperty(IFernflowerPreferences.Banner).ToString ()); classProcessor.WriteClass(cl, buffer); return(buffer.ToString()); } catch (Exception t) { DecompilerContext.GetLogger().WriteMessage("Class " + cl.qualifiedName + " couldn't be fully decompiled." , t); return(null); } }
public static void Main() { MyStruct struct1 = new MyStruct { MyParam1 = 0 }; MyStruct struct2 = struct1; struct1.MyParam1 = 20; Console.WriteLine($"{struct1.GetHashCode()} != {struct2.GetHashCode()}"); Console.WriteLine($"{struct1.MyParam1} == 20"); Console.WriteLine($"{struct2.MyParam1} == 0"); var class1 = new StructClass(); var class2 = class1; Console.WriteLine($"{class1.GetHashCode()} == {class2.GetHashCode()}"); }
private void RenameClasses() { List <ClassWrapperNode> lstClasses = GetReversePostOrderListIterative(rootClasses ); Dictionary <string, Dictionary <string, string> > classNameMaps = new Dictionary <string , Dictionary <string, string> >(); foreach (ClassWrapperNode node in lstClasses) { StructClass cl = node.GetClassStruct(); Dictionary <string, string> names = new Dictionary <string, string>(); // merge information on super class if (cl.superClass != null) { Dictionary <string, string> mapClass = classNameMaps.GetOrNull(cl.superClass.GetString ()); if (mapClass != null) { Sharpen.Collections.PutAll(names, mapClass); } } // merge information on interfaces foreach (string ifName in cl.GetInterfaceNames()) { Dictionary <string, string> mapInt = interfaceNameMaps.GetOrNull(ifName); if (mapInt != null) { Sharpen.Collections.PutAll(names, mapInt); } else { StructClass clintr = context.GetClass(ifName); if (clintr != null) { Sharpen.Collections.PutAll(names, ProcessExternalInterface(clintr)); } } } RenameClassIdentifiers(cl, names); if (!(node.GetSubclasses().Count == 0)) { Sharpen.Collections.Put(classNameMaps, cl.qualifiedName, names); } } }
public virtual string GetClassEntryName(StructClass cl, string entryName) { ClassesProcessor.ClassNode node = classProcessor.GetMapRootClasses().GetOrNull(cl .qualifiedName); if (node.type != ClassesProcessor.ClassNode.Class_Root) { return(null); } else if (converter != null) { string simpleClassName = Sharpen.Runtime.Substring(cl.qualifiedName, cl.qualifiedName .LastIndexOf('/') + 1); return(Sharpen.Runtime.Substring(entryName, 0, entryName.LastIndexOf('/') + 1) + simpleClassName + ".java"); } else { return(Sharpen.Runtime.Substring(entryName, 0, entryName.LastIndexOf(".class")) + ".java"); } }
public virtual bool SimplifyStackVarsStatement(Statement stat, HashSet <int> setReorderedIfs , SSAConstructorSparseEx ssa, StructClass cl) { bool res = false; List <Exprent> expressions = stat.GetExprents(); if (expressions == null) { bool processClass14 = DecompilerContext.GetOption(IFernflowerPreferences.Decompile_Class_1_4 ); while (true) { bool changed = false; foreach (Statement st in stat.GetStats()) { res |= SimplifyStackVarsStatement(st, setReorderedIfs, ssa, cl); changed = IfHelper.MergeIfs(st, setReorderedIfs) || BuildIff(st, ssa) || processClass14 && CollapseInlinedClass14(st); // collapse composed if's // collapse iff ?: statement // collapse inlined .class property in version 1.4 and before if (changed) { break; } } res |= changed; if (!changed) { break; } } } else { res = SimplifyStackVarsExprents(expressions, cl); } return(res); }
private Dictionary <string, string> ProcessExternalInterface(StructClass cl) { Dictionary <string, string> names = new Dictionary <string, string>(); foreach (string ifName in cl.GetInterfaceNames()) { Dictionary <string, string> mapInt = interfaceNameMaps.GetOrNull(ifName); if (mapInt != null) { Sharpen.Collections.PutAll(names, mapInt); } else { StructClass clintr = context.GetClass(ifName); if (clintr != null) { Sharpen.Collections.PutAll(names, ProcessExternalInterface(clintr)); } } } RenameClassIdentifiers(cl, names); return(names); }
private bool IsVarArgCall() { StructClass cl = DecompilerContext.GetStructContext().GetClass(classname); if (cl != null) { StructMethod mt = cl.GetMethod(InterpreterUtil.MakeUniqueKey(name, stringDescriptor )); if (mt != null) { return(mt.HasModifier(ICodeConstants.Acc_Varargs)); } } else { // TODO: tap into IDEA indices to access libraries methods details // try to check the class on the classpath MethodInfo mtd = ClasspathHelper.FindMethod(classname, name, descriptor); return(mtd != null && mtd.GetParameters() .Any(param => Attribute.IsDefined(param, typeof(ParamArrayAttribute)))); } return(false); }
private static string GetQualifiedNewInstance(string classname, List <Exprent> lstParams , int indent, BytecodeMappingTracer tracer) { ClassesProcessor.ClassNode node = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(classname); if (node != null && node.type != ClassesProcessor.ClassNode.Class_Root && node.type != ClassesProcessor.ClassNode.Class_Local && (node.access & ICodeConstants.Acc_Static ) == 0) { if (!(lstParams.Count == 0)) { Exprent enclosing = lstParams[0]; bool isQualifiedNew = false; if (enclosing.type == Exprent.Exprent_Var) { VarExprent varEnclosing = (VarExprent)enclosing; StructClass current_class = ((ClassesProcessor.ClassNode)DecompilerContext.GetProperty (DecompilerContext.Current_Class_Node)).classStruct; string this_classname = varEnclosing.GetProcessor().GetThisVars().GetOrNull(new VarVersionPair (varEnclosing)); if (!current_class.qualifiedName.Equals(this_classname)) { isQualifiedNew = true; } } else { isQualifiedNew = true; } if (isQualifiedNew) { return(enclosing.ToJava(indent, tracer).ToString()); } } } return(null); }
private void RenameClass(StructClass cl) { if (!cl.IsOwn()) { return; } string classOldFullName = cl.qualifiedName; // TODO: rename packages string clSimpleName = ConverterHelper.GetSimpleClassName(classOldFullName); if (helper.ToBeRenamed(IIdentifierRenamer.Type.Element_Class, clSimpleName, null, null)) { string classNewFullName; do { string classname = helper.GetNextClassName(classOldFullName, ConverterHelper.GetSimpleClassName (classOldFullName)); classNewFullName = ConverterHelper.ReplaceSimpleClassName(classOldFullName, classname ); }while (context.GetClasses().ContainsKey(classNewFullName)); interceptor.AddName(classOldFullName, classNewFullName); } }
public virtual void SimplifyStackVars(RootStatement root, StructMethod mt, StructClass cl) { HashSet <int> setReorderedIfs = new HashSet <int>(); SSAUConstructorSparseEx ssau = null; while (true) { bool found = false; SSAConstructorSparseEx ssa = new SSAConstructorSparseEx(); ssa.SplitVariables(root, mt); SimplifyExprentsHelper sehelper = new SimplifyExprentsHelper(ssau == null); while (sehelper.SimplifyStackVarsStatement(root, setReorderedIfs, ssa, cl)) { found = true; } SetVersionsToNull(root); SequenceHelper.CondenseSequences(root); ssau = new SSAUConstructorSparseEx(); ssau.SplitVariables(root, mt); if (IterateStatements(root, ssau)) { found = true; } SetVersionsToNull(root); if (!found) { break; } } // remove unused assignments ssau = new SSAUConstructorSparseEx(); ssau.SplitVariables(root, mt); IterateStatements(root, ssau); SetVersionsToNull(root); }
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 void BuildInheritanceTree() { Dictionary <string, ClassWrapperNode> nodes = new Dictionary <string, ClassWrapperNode >(); Dictionary <string, StructClass> classes = context.GetClasses(); List <ClassWrapperNode> rootClasses = new List <ClassWrapperNode>(); List <ClassWrapperNode> rootInterfaces = new List <ClassWrapperNode>(); foreach (StructClass cl in classes.Values) { if (!cl.IsOwn()) { continue; } LinkedList <StructClass> stack = new LinkedList <StructClass>(); LinkedList <ClassWrapperNode> stackSubNodes = new LinkedList <ClassWrapperNode>(); stack.AddLast(cl); stackSubNodes.AddLast((ClassWrapperNode)null); while (!(stack.Count == 0)) { StructClass clStr = Sharpen.Collections.RemoveFirst(stack); ClassWrapperNode child = Sharpen.Collections.RemoveFirst(stackSubNodes); ClassWrapperNode node = nodes.GetOrNull(clStr.qualifiedName); bool isNewNode = (node == null); if (isNewNode) { Sharpen.Collections.Put(nodes, clStr.qualifiedName, node = new ClassWrapperNode(clStr )); } if (child != null) { node.AddSubclass(child); } if (!isNewNode) { break; } else { bool isInterface = clStr.HasModifier(ICodeConstants.Acc_Interface); bool found_parent = false; if (isInterface) { foreach (string ifName in clStr.GetInterfaceNames()) { StructClass clParent = classes.GetOrNull(ifName); if (clParent != null) { stack.AddLast(clParent); stackSubNodes.AddLast(node); found_parent = true; } } } else if (clStr.superClass != null) { // null iff java/lang/Object StructClass clParent = classes.GetOrNull(clStr.superClass.GetString()); if (clParent != null) { stack.AddLast(clParent); stackSubNodes.AddLast(node); found_parent = true; } } if (!found_parent) { // no super class or interface (isInterface ? rootInterfaces : rootClasses).Add(node); } } } } this.rootClasses = rootClasses; this.rootInterfaces = rootInterfaces; }
public VarDefinitionHelper(Statement root, StructMethod mt, VarProcessor varproc) { // statement.id, defined vars mapVarDefStatements = new Dictionary <int, Statement>(); mapStatementVars = new Dictionary <int, HashSet <int> >(); implDefVars = new HashSet <int>(); this.varproc = varproc; VarNamesCollector vc = varproc.GetVarNamesCollector(); bool thisvar = !mt.HasModifier(ICodeConstants.Acc_Static); MethodDescriptor md = MethodDescriptor.ParseDescriptor(mt.GetDescriptor()); int paramcount = 0; if (thisvar) { paramcount = 1; } paramcount += [email protected]; // method parameters are implicitly defined int varindex = 0; for (int i = 0; i < paramcount; i++) { implDefVars.Add(varindex); 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; } } if (thisvar) { StructClass current_class = (StructClass)DecompilerContext.GetProperty(DecompilerContext .Current_Class); Sharpen.Collections.Put(varproc.GetThisVars(), new VarVersionPair(0, 0), current_class .qualifiedName); varproc.SetVarName(new VarVersionPair(0, 0), "this"); vc.AddName("this"); } // catch variables are implicitly defined LinkedList <Statement> stack = new LinkedList <Statement>(); stack.AddLast(root); while (!(stack.Count == 0)) { Statement st = Sharpen.Collections.RemoveFirst(stack); List <VarExprent> lstVars = null; if (st.type == Statement.Type_Catchall) { lstVars = ((CatchAllStatement)st).GetVars(); } else if (st.type == Statement.Type_Trycatch) { lstVars = ((CatchStatement)st).GetVars(); } if (lstVars != null) { foreach (VarExprent var in lstVars) { implDefVars.Add(var.GetIndex()); varproc.SetVarName(new VarVersionPair(var), vc.GetFreeName(var.GetIndex())); var.SetDefinition(true); } } Sharpen.Collections.AddAll(stack, st.GetStats()); } InitStatement(root); }
public void TestObjectWithStruct() { var nodeContainer = new NodeContainer(); var instance = new StructClass { Member1 = 3, Member2 = new Struct() }; var rootNode = nodeContainer.GetOrCreateNode(instance); var visitor = new TestVisitor(); visitor.Visit(rootNode); var expectedNodes = new[] { rootNode, rootNode.TryGetChild(nameof(StructClass.Member1)), rootNode.TryGetChild(nameof(StructClass.Member2)), rootNode.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member1)), rootNode.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)), }; var expectedPaths = new[] { new GraphNodePath(rootNode), new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member1)), new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)), new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)).PushMember(nameof(Struct.Member1)), new GraphNodePath(rootNode).PushMember(nameof(StructClass.Member2)).PushMember(nameof(Struct.Member2)), }; VerifyNodesAndPath(expectedNodes, expectedPaths, visitor); }
public void TestObjectWithStruct() { var nodeContainer = new NodeContainer(); var instance1 = new StructClass { Member1 = 3, Member2 = new Struct { Member2 = new SimpleClass() } }; var instance2 = new StructClass { Member1 = 3, Member2 = new Struct { Member2 = new SimpleClass() } }; var source = nodeContainer.GetOrCreateNode(instance1); var target = nodeContainer.GetOrCreateNode(instance2); var linker = new TestLinker(); linker.LinkGraph(source, target); var expectedLinks = new Dictionary<IGraphNode, IGraphNode> { { source, target }, { source.TryGetChild(nameof(StructClass.Member1)), target.TryGetChild(nameof(StructClass.Member1)) }, { source.TryGetChild(nameof(StructClass.Member2)), target.TryGetChild(nameof(StructClass.Member2)) }, { source.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member1)), target.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member1)) }, { source.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)), target.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)) }, { source.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)).Target, target.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)).Target }, { source.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)).Target.TryGetChild(nameof(SimpleClass.Member1)), target.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)).Target.TryGetChild(nameof(SimpleClass.Member1)) }, { source.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)).Target.TryGetChild(nameof(SimpleClass.Member2)), target.TryGetChild(nameof(StructClass.Member2)).TryGetChild(nameof(Struct.Member2)).Target.TryGetChild(nameof(SimpleClass.Member2)) }, }; VerifyLinks(expectedLinks, linker); }
public ClassWrapper(StructClass classStruct) { this.classStruct = classStruct; }
private bool SimplifyStackVarsExprents(List <Exprent> list, StructClass cl) { bool res = false; int index = 0; while (index < list.Count) { Exprent current = list[index]; Exprent ret = IsSimpleConstructorInvocation(current); if (ret != null) { list[index] = ret; res = true; continue; } // lambda expression (Java 8) ret = IsLambda(current, cl); if (ret != null) { list[index] = ret; res = true; continue; } // remove monitor exit if (IsMonitorExit(current)) { list.RemoveAtReturningValue(index); res = true; continue; } // trivial assignment of a stack variable if (IsTrivialStackAssignment(current)) { list.RemoveAtReturningValue(index); res = true; continue; } if (index == list.Count - 1) { break; } Exprent next = list[index + 1]; // constructor invocation if (IsConstructorInvocationRemote(list, index)) { list.RemoveAtReturningValue(index); res = true; continue; } // remove getClass() invocation, which is part of a qualified new if (DecompilerContext.GetOption(IFernflowerPreferences.Remove_Get_Class_New)) { if (IsQualifiedNewGetClass(current, next)) { list.RemoveAtReturningValue(index); res = true; continue; } } // direct initialization of an array int arrCount = IsArrayInitializer(list, index); if (arrCount > 0) { for (int i = 0; i < arrCount; i++) { list.RemoveAtReturningValue(index + 1); } res = true; continue; } // add array initializer expression if (AddArrayInitializer(current, next)) { list.RemoveAtReturningValue(index + 1); res = true; continue; } // integer ++expr and --expr (except for vars!) Exprent func = IsPPIorMMI(current); if (func != null) { list[index] = func; res = true; continue; } // expr++ and expr-- if (IsIPPorIMM(current, next) || IsIPPorIMM2(current, next)) { list.RemoveAtReturningValue(index + 1); res = true; continue; } // assignment on stack if (IsStackAssignment(current, next)) { list.RemoveAtReturningValue(index + 1); res = true; continue; } if (!firstInvocation && IsStackAssignment2(current, next)) { list.RemoveAtReturningValue(index + 1); res = true; continue; } index++; } return(res); }
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 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); } } } } } } }