private static bool SplitExceptionRange(ExceptionRangeCFG range, HashSet <BasicBlock > setEntries, ControlFlowGraph graph, GenericDominatorEngine engine) { foreach (BasicBlock entry in setEntries) { List <BasicBlock> lstSubrangeBlocks = GetReachableBlocksRestricted(entry, range, engine); if (!(lstSubrangeBlocks.Count == 0) && lstSubrangeBlocks.Count < range.GetProtectedRange ().Count) { // add new range ExceptionRangeCFG subRange = new ExceptionRangeCFG(lstSubrangeBlocks, range.GetHandler (), range.GetExceptionTypes()); graph.GetExceptions().Add(subRange); // shrink the original range lstSubrangeBlocks.ForEach(block => range.GetProtectedRange().Remove(block)); return(true); } else { // should not happen DecompilerContext.GetLogger().WriteMessage("Inconsistency found while splitting protected range" , IFernflowerLogger.Severity.Warn); } } return(false); }
public virtual void CopyEntry(string source, string path, string archiveName, string entryName) { string file = Path.Combine(GetAbsolutePath(path), archiveName); if (!CheckEntry(entryName, file)) { return; } try { using (ZipArchive srcArchive = ZipFile.Open(source, ZipArchiveMode.Read)) { var entry = srcArchive.GetEntry(entryName); if (entry != null) { using (var @in = new MemoryStream(entry.Open().ReadFully()).ToInputStream()) { var @out = mapArchiveStreams.GetOrNull(file); var newEntry = @out.CreateEntry(entryName); InterpreterUtil.CopyStream(@in, newEntry.Open()); } } } } catch (IOException ex) { string message = "Cannot copy entry " + entryName + " from " + source + " to " + file; DecompilerContext.GetLogger().WriteMessage(message, ex); } }
public virtual void SaveClassEntry(string path, string archiveName, string qualifiedName , string entryName, string content) { string file = Path.Combine(GetAbsolutePath(path), archiveName); if (!CheckEntry(entryName, file)) { return; } try { var @out = mapArchiveStreams.GetOrNull(file); var newEntry = @out.CreateEntry(entryName); if (content != null) { var stream = newEntry.Open(); stream.Write(Sharpen.Runtime.GetBytesForString(content, "UTF-8")); stream.Flush(); stream.Close(); } } catch (IOException ex) { string message = "Cannot write entry " + entryName + " to " + file; DecompilerContext.GetLogger().WriteMessage(message, ex); } }
public static GenericClassDescriptor ParseClassSignature(string signature) { string original = signature; try { GenericClassDescriptor descriptor = new GenericClassDescriptor(); signature = ParseFormalParameters(signature, descriptor.fparameters, descriptor.fbounds ); string superCl = GenericType.GetNextType(signature); descriptor.superclass = new GenericType(superCl); signature = Sharpen.Runtime.Substring(signature, superCl.Length); while (signature.Length > 0) { string superIf = GenericType.GetNextType(signature); descriptor.superinterfaces.Add(new GenericType(superIf)); signature = Sharpen.Runtime.Substring(signature, superIf.Length); } return(descriptor); } catch (Exception) { DecompilerContext.GetLogger().WriteMessage("Invalid signature: " + original, IFernflowerLogger.Severity .Warn); return(null); } }
public virtual void CopyFile(string source, string path, string entryName) { try { InterpreterUtil.CopyFile(new FileInfo(source), new FileInfo(Path.Combine(GetAbsolutePath(path), entryName))); } catch (IOException ex) { DecompilerContext.GetLogger().WriteMessage("Cannot copy " + source + " to " + entryName , ex); } }
public static GenericFieldDescriptor ParseFieldSignature(string signature) { try { return(new GenericFieldDescriptor(new GenericType(signature))); } catch (Exception) { DecompilerContext.GetLogger().WriteMessage("Invalid signature: " + signature, IFernflowerLogger.Severity .Warn); return(null); } }
private bool CheckEntry(string entryName, string file) { HashSet <string> set = mapArchiveEntries.ComputeIfAbsent(file, (string k) => new HashSet <string>()); bool added = set.Add(entryName); if (!added) { string message = "Zip entry " + entryName + " already exists in " + file; DecompilerContext.GetLogger().WriteMessage(message, IFernflowerLogger.Severity.Warn ); } return(added); }
public virtual void SaveClassFile(string path, string qualifiedName, string entryName , string content, int[] mapping) { FileSystemInfo file = new FileInfo(Path.Combine(GetAbsolutePath(path), entryName)); try { File.WriteAllText(file.FullName, content); } catch (IOException ex) { DecompilerContext.GetLogger().WriteMessage("Cannot write class file " + file, ex); } }
public virtual void CreateArchive(string path, string archiveName, Manifest manifest ) { FileSystemInfo file = new FileInfo(Path.Combine(GetAbsolutePath(path), archiveName)); try { Sharpen.Collections.Put(mapArchiveStreams, file.FullName, ZipFile.Open(file.FullName, ZipArchiveMode.Update)); } catch (IOException ex) { DecompilerContext.GetLogger().WriteMessage("Cannot create archive " + file, ex); } }
public virtual void CloseArchive(string path, string archiveName) { string file = new FileInfo(Path.Combine(GetAbsolutePath(path), archiveName)).FullName; try { Sharpen.Collections.Remove(mapArchiveEntries, file); Sharpen.Collections.Remove(mapArchiveStreams, file).Dispose(); } catch (IOException) { DecompilerContext.GetLogger().WriteMessage("Cannot close " + file, IFernflowerLogger.Severity .Warn); } }
public static GenericMethodDescriptor ParseMethodSignature(string signature) { string original = signature; try { List <string> typeParameters = new List <string>(); List <List <GenericType> > typeParameterBounds = new List <List <GenericType> >(); signature = ParseFormalParameters(signature, typeParameters, typeParameterBounds); int to = signature.IndexOf(")"); string parameters = Sharpen.Runtime.Substring(signature, 1, to); signature = Sharpen.Runtime.Substring(signature, to + 1); List <GenericType> parameterTypes = new List <GenericType>(); while (parameters.Length > 0) { string par = GenericType.GetNextType(parameters); parameterTypes.Add(new GenericType(par)); parameters = Sharpen.Runtime.Substring(parameters, par.Length); } string ret = GenericType.GetNextType(signature); GenericType returnType = new GenericType(ret); signature = Sharpen.Runtime.Substring(signature, ret.Length); List <GenericType> exceptionTypes = new List <GenericType>(); if (signature.Length > 0) { string[] exceptions = signature.Split("\\^"); for (int i = 1; i < exceptions.Length; i++) { exceptionTypes.Add(new GenericType(exceptions[i])); } } return(new GenericMethodDescriptor(typeParameters, typeParameterBounds, parameterTypes , returnType, exceptionTypes)); } catch (Exception) { DecompilerContext.GetLogger().WriteMessage("Invalid signature: " + original, IFernflowerLogger.Severity .Warn); return(null); } }
public static void Simplify(SwitchStatement switchStatement) { SwitchExprent switchExprent = (SwitchExprent)switchStatement.GetHeadexprent(); Exprent value = switchExprent.GetValue(); if (IsEnumArray(value)) { List <List <Exprent> > caseValues = switchStatement.GetCaseValues(); Dictionary <Exprent, Exprent> mapping = new Dictionary <Exprent, Exprent>(caseValues .Count); ArrayExprent array = (ArrayExprent)value; FieldExprent arrayField = (FieldExprent)array.GetArray(); ClassesProcessor.ClassNode classNode = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(arrayField.GetClassname()); if (classNode != null) { MethodWrapper wrapper = classNode.GetWrapper().GetMethodWrapper(ICodeConstants.Clinit_Name , "()V"); if (wrapper != null && wrapper.root != null) { wrapper.GetOrBuildGraph().IterateExprents((Exprent exprent) => { if (exprent is AssignmentExprent) { AssignmentExprent assignment = (AssignmentExprent)exprent; Exprent left = assignment.GetLeft(); if (left.type == Exprent.Exprent_Array && ((ArrayExprent)left).GetArray().Equals( arrayField)) { Sharpen.Collections.Put(mapping, assignment.GetRight(), ((InvocationExprent)((ArrayExprent )left).GetIndex()).GetInstance()); } } return(0); } ); } } List <List <Exprent> > realCaseValues = new List <List <Exprent> >(caseValues.Count); foreach (List <Exprent> caseValue in caseValues) { List <Exprent> values = new List <Exprent>(caseValue.Count); realCaseValues.Add(values); foreach (Exprent exprent in caseValue) { if (exprent == null) { values.Add(null); } else { Exprent realConst = mapping.GetOrNull(exprent); if (realConst == null) { DecompilerContext.GetLogger().WriteMessage("Unable to simplify switch on enum: " + exprent + " not found, available: " + mapping, IFernflowerLogger.Severity.Error ); return; } values.Add(realConst.Copy()); } } } caseValues.Clear(); Sharpen.Collections.AddAll(caseValues, realCaseValues); switchExprent.ReplaceExprent(value, ((InvocationExprent)array.GetIndex()).GetInstance ().Copy()); } }
// precedence of new public override TextBuffer ToJava(int indent, BytecodeMappingTracer tracer) { TextBuffer buf = new TextBuffer(); if (anonymous) { ClassesProcessor.ClassNode child = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(newType.value); // IDEA-204310 - avoid backtracking later on for lambdas (causes spurious imports) if (!enumConst && (!lambda || DecompilerContext.GetOption(IFernflowerPreferences .Lambda_To_Anonymous_Class))) { string enclosing = null; if (!lambda && constructor != null) { enclosing = GetQualifiedNewInstance(child.anonymousClassType.value, constructor.GetLstParameters (), indent, tracer); if (enclosing != null) { buf.Append(enclosing).Append('.'); } } buf.Append("new "); string typename = ExprProcessor.GetCastTypeName(child.anonymousClassType); if (enclosing != null) { ClassesProcessor.ClassNode anonymousNode = DecompilerContext.GetClassProcessor(). GetMapRootClasses().GetOrNull(child.anonymousClassType.value); if (anonymousNode != null) { typename = anonymousNode.simpleName; } else { typename = Sharpen.Runtime.Substring(typename, typename.LastIndexOf('.') + 1); } } GenericClassDescriptor descriptor = ClassWriter.GetGenericClassDescriptor(child.classStruct ); if (descriptor != null) { if ((descriptor.superinterfaces.Count == 0)) { buf.Append(GenericMain.GetGenericCastTypeName(descriptor.superclass)); } else { if (descriptor.superinterfaces.Count > 1 && !lambda) { DecompilerContext.GetLogger().WriteMessage("Inconsistent anonymous class signature: " + child.classStruct.qualifiedName, IFernflowerLogger.Severity.Warn); } buf.Append(GenericMain.GetGenericCastTypeName(descriptor.superinterfaces[0])); } } else { buf.Append(typename); } } buf.Append('('); if (!lambda && constructor != null) { List <Exprent> parameters = constructor.GetLstParameters(); List <VarVersionPair> mask = child.GetWrapper().GetMethodWrapper(ICodeConstants.Init_Name , constructor.GetStringDescriptor()).synthParameters; if (mask == null) { InvocationExprent superCall = child.superInvocation; mask = ExprUtil.GetSyntheticParametersMask(superCall.GetClassname(), superCall.GetStringDescriptor (), parameters.Count); } int start = enumConst ? 2 : 0; bool firstParam = true; for (int i = start; i < parameters.Count; i++) { if (mask == null || mask[i] == null) { if (!firstParam) { buf.Append(", "); } ExprProcessor.GetCastedExprent(parameters[i], constructor.GetDescriptor().@params [i], buf, indent, true, tracer); firstParam = false; } } } buf.Append(')'); if (enumConst && buf.Length() == 2) { buf.SetLength(0); } if (lambda) { if (!DecompilerContext.GetOption(IFernflowerPreferences.Lambda_To_Anonymous_Class )) { buf.SetLength(0); } // remove the usual 'new <class>()', it will be replaced with lambda style '() ->' Exprent methodObject = constructor == null ? null : constructor.GetInstance(); TextBuffer clsBuf = new TextBuffer(); new ClassWriter().ClassLambdaToJava(child, clsBuf, methodObject, indent, tracer); buf.Append(clsBuf); tracer.IncrementCurrentSourceLine(clsBuf.CountLines()); } else { TextBuffer clsBuf = new TextBuffer(); new ClassWriter().ClassToJava(child, clsBuf, indent, tracer); buf.Append(clsBuf); tracer.IncrementCurrentSourceLine(clsBuf.CountLines()); } } else if (directArrayInit) { VarType leftType = newType.DecreaseArrayDim(); buf.Append('{'); for (int i = 0; i < lstArrayElements.Count; i++) { if (i > 0) { buf.Append(", "); } ExprProcessor.GetCastedExprent(lstArrayElements[i], leftType, buf, indent, false, tracer); } buf.Append('}'); } else if (newType.arrayDim == 0) { if (!enumConst) { string enclosing = null; if (constructor != null) { enclosing = GetQualifiedNewInstance(newType.value, constructor.GetLstParameters() , indent, tracer); if (enclosing != null) { buf.Append(enclosing).Append('.'); } } buf.Append("new "); string typename = ExprProcessor.GetTypeName(newType); if (enclosing != null) { ClassesProcessor.ClassNode newNode = DecompilerContext.GetClassProcessor().GetMapRootClasses ().GetOrNull(newType.value); if (newNode != null) { typename = newNode.simpleName; } else { typename = Sharpen.Runtime.Substring(typename, typename.LastIndexOf('.') + 1); } } buf.Append(typename); } if (constructor != null) { List <Exprent> parameters = constructor.GetLstParameters(); List <VarVersionPair> mask = ExprUtil.GetSyntheticParametersMask(constructor.GetClassname (), constructor.GetStringDescriptor(), parameters.Count); int start = enumConst ? 2 : 0; if (!enumConst || start < parameters.Count) { buf.Append('('); bool firstParam = true; for (int i = start; i < parameters.Count; i++) { if (mask == null || mask[i] == null) { Exprent expr = parameters[i]; VarType leftType = constructor.GetDescriptor().@params[i]; if (i == parameters.Count - 1 && expr.GetExprType() == VarType.Vartype_Null && ProbablySyntheticParameter (leftType.value)) { break; } // skip last parameter of synthetic constructor call if (!firstParam) { buf.Append(", "); } ExprProcessor.GetCastedExprent(expr, leftType, buf, indent, true, false, true, true , tracer); firstParam = false; } } buf.Append(')'); } } } else if (isVarArgParam) { // just print the array elements VarType leftType = newType.DecreaseArrayDim(); for (int i = 0; i < lstArrayElements.Count; i++) { if (i > 0) { buf.Append(", "); } // new String[][]{{"abc"}, {"DEF"}} => new String[]{"abc"}, new String[]{"DEF"} Exprent element = lstArrayElements[i]; if (element.type == Exprent_New) { ((NewExprent)element).SetDirectArrayInit(false); } ExprProcessor.GetCastedExprent(element, leftType, buf, indent, false, tracer); } // if there is just one element of Object[] type it needs to be casted to resolve ambiguity if (lstArrayElements.Count == 1) { VarType elementType = lstArrayElements[0].GetExprType(); if (elementType.type == ICodeConstants.Type_Object && elementType.value.Equals("java/lang/Object" ) && elementType.arrayDim >= 1) { buf.Prepend("(Object)"); } } } else { buf.Append("new ").Append(ExprProcessor.GetTypeName(newType)); if ((lstArrayElements.Count == 0)) { for (int i = 0; i < newType.arrayDim; i++) { buf.Append('['); if (i < lstDims.Count) { buf.Append(lstDims[i].ToJava(indent, tracer)); } buf.Append(']'); } } else { for (int i = 0; i < newType.arrayDim; i++) { buf.Append("[]"); } VarType leftType = newType.DecreaseArrayDim(); buf.Append('{'); for (int i = 0; i < lstArrayElements.Count; i++) { if (i > 0) { buf.Append(", "); } ExprProcessor.GetCastedExprent(lstArrayElements[i], leftType, buf, indent, false, tracer); } buf.Append('}'); } } return(buf); }
private void AddSpace(string path, FileSystemInfo file, bool isOwn, int level) { if (file is DirectoryInfo dirInfo) { if (level == 1) { path += dirInfo.Name; } else if (level > 1) { path += "/" + dirInfo.Name; } FileInfo[] files = dirInfo.GetFiles(); if (files != null) { for (int i = files.Length - 1; i >= 0; i--) { AddSpace(path, files[i], isOwn, level + 1); } } } else { string filename = file.Name; bool isArchive = false; try { if (filename.EndsWith(".jar")) { isArchive = true; AddArchive(path, file, ContextUnit.Type_Jar, isOwn); } else if (filename.EndsWith(".zip")) { isArchive = true; AddArchive(path, file, ContextUnit.Type_Zip, isOwn); } } catch (IOException ex) { string message = "Corrupted archive file: " + file; DecompilerContext.GetLogger().WriteMessage(message, ex); } if (isArchive) { return; } ContextUnit unit = units.GetOrNull(path); if (unit == null) { unit = new ContextUnit(ContextUnit.Type_Folder, null, path, isOwn, saver, decompiledData ); Sharpen.Collections.Put(units, path, unit); units.RemoveIf(c => string.IsNullOrEmpty(c.Key)); } if (filename.EndsWith(".class")) { try { using (DataInputFullStream @in = loader.GetClassStream(file.FullName, null )) { StructClass cl = new StructClass(@in, isOwn, loader); Sharpen.Collections.Put(classes, cl.qualifiedName, cl); unit.AddClass(cl, filename); loader.AddClassLink(cl.qualifiedName, new LazyLoader.Link(file.FullName, null)); } } catch (IOException ex) { string message = "Corrupted class file: " + file; DecompilerContext.GetLogger().WriteMessage(message, ex); } } else { unit.AddOtherEntry(file.FullName, filename); } } }
private static bool ProcessStatement(Statement general, Dictionary <int, HashSet <int > > mapExtPost) { if (general.type == Statement.Type_Root) { Statement stat = general.GetFirst(); if (stat.type != Statement.Type_General) { return(true); } else { bool complete = ProcessStatement(stat, mapExtPost); if (complete) { // replace general purpose statement with simple one general.ReplaceStatement(stat, stat.GetFirst()); } return(complete); } } bool mapRefreshed = (mapExtPost.Count == 0); for (int mapstage = 0; mapstage < 2; mapstage++) { for (int reducibility = 0; reducibility < 5; reducibility++) { // FIXME: implement proper node splitting. For now up to 5 nodes in sequence are splitted. if (reducibility > 0) { // try { // DotExporter.toDotFile(general, new File("c:\\Temp\\stat1.dot")); // } catch(Exception ex) {ex.printStackTrace();} // take care of irreducible control flow graphs if (IrreducibleCFGDeobfuscator.IsStatementIrreducible(general)) { if (!IrreducibleCFGDeobfuscator.SplitIrreducibleNode(general)) { DecompilerContext.GetLogger().WriteMessage("Irreducible statement cannot be decomposed!" , IFernflowerLogger.Severity.Error); break; } } else { if (mapstage == 2 || mapRefreshed) { // last chance lost DecompilerContext.GetLogger().WriteMessage("Statement cannot be decomposed although reducible!" , IFernflowerLogger.Severity.Error); } break; } // try { // DotExporter.toDotFile(general, new File("c:\\Temp\\stat1.dot")); // } catch(Exception ex) {ex.printStackTrace();} mapExtPost = new Dictionary <int, HashSet <int> >(); mapRefreshed = true; } for (int i = 0; i < 2; i++) { bool forceall = i != 0; while (true) { if (FindSimpleStatements(general, mapExtPost)) { reducibility = 0; } if (general.type == Statement.Type_Placeholder) { return(true); } Statement stat = FindGeneralStatement(general, forceall, mapExtPost); if (stat != null) { bool complete = ProcessStatement(stat, general.GetFirst() == stat ? mapExtPost : new Dictionary <int, HashSet <int> >()); if (complete) { // replace general purpose statement with simple one general.ReplaceStatement(stat, stat.GetFirst()); } else { return(false); } mapExtPost = new Dictionary <int, HashSet <int> >(); mapRefreshed = true; reducibility = 0; } else { break; } } } } // try { // DotExporter.toDotFile(general, new File("c:\\Temp\\stat1.dot")); // } catch (Exception ex) { // ex.printStackTrace(); // } if (mapRefreshed) { break; } else { mapExtPost = new Dictionary <int, HashSet <int> >(); } } return(false); }
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(); }
/// <exception cref="System.IO.IOException"/> public static RootStatement CodeToJava(StructMethod mt, MethodDescriptor md, VarProcessor varProc) { StructClass cl = mt.GetClassStruct(); bool isInitializer = ICodeConstants.Clinit_Name.Equals(mt.GetName()); // for now static initializer only mt.ExpandData(); InstructionSequence seq = mt.GetInstructionSequence(); ControlFlowGraph graph = new ControlFlowGraph(seq); DeadCodeHelper.RemoveDeadBlocks(graph); graph.InlineJsr(mt); // TODO: move to the start, before jsr inlining DeadCodeHelper.ConnectDummyExitBlock(graph); DeadCodeHelper.RemoveGotos(graph); ExceptionDeobfuscator.RemoveCircularRanges(graph); ExceptionDeobfuscator.RestorePopRanges(graph); if (DecompilerContext.GetOption(IFernflowerPreferences.Remove_Empty_Ranges)) { ExceptionDeobfuscator.RemoveEmptyRanges(graph); } if (DecompilerContext.GetOption(IFernflowerPreferences.Ensure_Synchronized_Monitor )) { // special case: search for 'synchronized' ranges w/o monitorexit instruction (as generated by Kotlin and Scala) DeadCodeHelper.ExtendSynchronizedRangeToMonitorexit(graph); } if (DecompilerContext.GetOption(IFernflowerPreferences.No_Exceptions_Return)) { // special case: single return instruction outside of a protected range DeadCodeHelper.IncorporateValueReturns(graph); } // ExceptionDeobfuscator.restorePopRanges(graph); ExceptionDeobfuscator.InsertEmptyExceptionHandlerBlocks(graph); DeadCodeHelper.MergeBasicBlocks(graph); DecompilerContext.GetCounterContainer().SetCounter(CounterContainer.Var_Counter, mt.GetLocalVariables()); if (ExceptionDeobfuscator.HasObfuscatedExceptions(graph)) { DecompilerContext.GetLogger().WriteMessage("Heavily obfuscated exception ranges found!" , IFernflowerLogger.Severity.Warn); if (!ExceptionDeobfuscator.HandleMultipleEntryExceptionRanges(graph)) { DecompilerContext.GetLogger().WriteMessage("Found multiple entry exception ranges which could not be splitted" , IFernflowerLogger.Severity.Warn); } ExceptionDeobfuscator.InsertDummyExceptionHandlerBlocks(graph, cl.GetBytecodeVersion ()); } RootStatement root = DomHelper.ParseGraph(graph); FinallyProcessor fProc = new FinallyProcessor(md, varProc); while (fProc.IterateGraph(mt, root, graph)) { root = DomHelper.ParseGraph(graph); } // remove synchronized exception handler // not until now because of comparison between synchronized statements in the finally cycle DomHelper.RemoveSynchronizedHandler(root); // LabelHelper.lowContinueLabels(root, new HashSet<StatEdge>()); SequenceHelper.CondenseSequences(root); ClearStructHelper.ClearStatements(root); ExprProcessor proc = new ExprProcessor(md, varProc); proc.ProcessStatement(root, cl); SequenceHelper.CondenseSequences(root); StackVarsProcessor stackProc = new StackVarsProcessor(); do { stackProc.SimplifyStackVars(root, mt, cl); varProc.SetVarVersions(root); }while (new PPandMMHelper().FindPPandMM(root)); while (true) { LabelHelper.CleanUpEdges(root); do { MergeHelper.EnhanceLoops(root); }while (LoopExtractHelper.ExtractLoops(root) || IfHelper.MergeAllIfs(root)); if (DecompilerContext.GetOption(IFernflowerPreferences.Idea_Not_Null_Annotation)) { if (IdeaNotNullHelper.RemoveHardcodedChecks(root, mt)) { SequenceHelper.CondenseSequences(root); stackProc.SimplifyStackVars(root, mt, cl); varProc.SetVarVersions(root); } } LabelHelper.IdentifyLabels(root); if (InlineSingleBlockHelper.InlineSingleBlocks(root)) { continue; } // initializer may have at most one return point, so no transformation of method exits permitted if (isInitializer || !ExitHelper.CondenseExits(root)) { break; } } // FIXME: !! //if(!EliminateLoopsHelper.eliminateLoops(root)) { // break; //} ExitHelper.RemoveRedundantReturns(root); SecondaryFunctionsHelper.IdentifySecondaryFunctions(root, varProc); varProc.SetVarDefinitions(root); // must be the last invocation, because it makes the statement structure inconsistent // FIXME: new edge type needed LabelHelper.ReplaceContinueWithBreak(root); mt.ReleaseResources(); return(root); }