public virtual void InlineJsr(StructMethod mt) { ProcessJsr(); RemoveJsr(mt); RemoveMarkers(); DeadCodeHelper.RemoveEmptyBlocks(this); }
private static BasicBlock GetUniqueNext(ControlFlowGraph graph, HashSet <BasicBlock []> setNext) { // precondition: there is at most one true exit path in a finally statement BasicBlock next = null; bool multiple = false; foreach (BasicBlock[] arr in setNext) { if (arr[2] != null) { next = arr[1]; multiple = false; break; } else { if (next == null) { next = arr[1]; } else if (next != arr[1]) { multiple = true; } if (arr[1].GetPreds().Count == 1) { next = arr[1]; } } } if (multiple) { // TODO: generic solution foreach (BasicBlock[] arr in setNext) { BasicBlock block = arr[1]; if (block != next) { if (InterpreterUtil.EqualSets(next.GetSuccs(), block.GetSuccs())) { InstructionSequence seqNext = next.GetSeq(); InstructionSequence seqBlock = block.GetSeq(); if (seqNext.Length() == seqBlock.Length()) { for (int i = 0; i < seqNext.Length(); i++) { Instruction instrNext = seqNext.GetInstr(i); Instruction instrBlock = seqBlock.GetInstr(i); if (!Instruction.Equals(instrNext, instrBlock)) { return(null); } for (int j = 0; j < instrNext.OperandsCount(); j++) { if (instrNext.Operand(j) != instrBlock.Operand(j)) { return(null); } } } } else { return(null); } } else { return(null); } } } // try { // DotExporter.toDotFile(graph, new File("c:\\Temp\\fern5.dot"), true); // } catch(IOException ex) { // ex.printStackTrace(); // } foreach (BasicBlock[] arr in setNext) { if (arr[1] != next) { // FIXME: exception edge possible? arr[0].RemoveSuccessor(arr[1]); arr[0].AddSuccessor(next); } } DeadCodeHelper.RemoveDeadBlocks(graph); } return(next); }
private bool ProcessStatementEx(StructMethod mt, RootStatement root, ControlFlowGraph graph) { int bytecode_version = mt.GetClassStruct().GetBytecodeVersion(); LinkedList <Statement> stack = new LinkedList <Statement>(); stack.AddLast(root); while (!(stack.Count == 0)) { Statement stat = Sharpen.Collections.RemoveLast(stack); Statement parent = stat.GetParent(); if (parent != null && parent.type == Statement.Type_Catchall && stat == parent.GetFirst () && !parent.IsCopied()) { CatchAllStatement fin = (CatchAllStatement)parent; BasicBlock head = fin.GetBasichead().GetBlock(); BasicBlock handler = fin.GetHandler().GetBasichead().GetBlock(); if (catchallBlockIDs.ContainsKey(handler.id)) { } else if (finallyBlockIDs.ContainsKey(handler.id)) { // do nothing fin.SetFinally(true); int?var = finallyBlockIDs.GetOrNullable(handler.id); fin.SetMonitor(var == null ? null : new VarExprent(var.Value, VarType.Vartype_Int , varProcessor)); } else { FinallyProcessor.Record inf = GetFinallyInformation(mt, root, fin); if (inf == null) { // inconsistent finally Sharpen.Collections.Put(catchallBlockIDs, handler.id, null); } else { if (DecompilerContext.GetOption(IFernflowerPreferences.Finally_Deinline) && VerifyFinallyEx (graph, fin, inf)) { Sharpen.Collections.Put(finallyBlockIDs, handler.id, null); } else { int varindex = DecompilerContext.GetCounterContainer().GetCounterAndIncrement(CounterContainer .Var_Counter); InsertSemaphore(graph, GetAllBasicBlocks(fin.GetFirst()), head, handler, varindex , inf, bytecode_version); Sharpen.Collections.Put(finallyBlockIDs, handler.id, varindex); } DeadCodeHelper.RemoveDeadBlocks(graph); // e.g. multiple return blocks after a nested finally DeadCodeHelper.RemoveEmptyBlocks(graph); DeadCodeHelper.MergeBasicBlocks(graph); } return(true); } } Sharpen.Collections.AddAll(stack, stat.GetStats()); } return(false); }
private HashSet <BasicBlock> GetJsrRange(BasicBlock jsr, BasicBlock ret) { HashSet <BasicBlock> blocks = new HashSet <BasicBlock>(); List <BasicBlock> lstNodes = new List <BasicBlock>(); lstNodes.Add(jsr); BasicBlock dom = jsr.GetSuccs()[0]; while (!(lstNodes.Count == 0)) { BasicBlock node = lstNodes.RemoveAtReturningValue(0); for (int j = 0; j < 2; j++) { List <BasicBlock> lst; if (j == 0) { if (node.GetLastInstruction().opcode == ICodeConstants.opc_ret) { if (node.GetSuccs().Contains(ret)) { continue; } } lst = node.GetSuccs(); } else { if (node == jsr) { continue; } lst = node.GetSuccExceptions(); } for (int i = lst.Count - 1; i >= 0; i--) { BasicBlock child = lst[i]; if (!blocks.Contains(child)) { if (node != jsr) { for (int k = 0; k < child.GetPreds().Count; k++) { if (!DeadCodeHelper.IsDominator(this, child.GetPreds()[k], dom)) { goto CHILD_continue; } } for (int k = 0; k < child.GetPredExceptions().Count; k++) { if (!DeadCodeHelper.IsDominator(this, child.GetPredExceptions()[k], dom)) { goto CHILD_continue; } } } // last block is a dummy one if (child != last) { blocks.Add(child); } lstNodes.Add(child); } CHILD_continue :; } CHILD_break :; } } return(blocks); }
/// <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); }