summaryrefslogtreecommitdiffstats
path: root/src/org/jetbrains/java/decompiler/main/rels/MethodProcessorThread.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/jetbrains/java/decompiler/main/rels/MethodProcessorThread.java')
-rw-r--r--src/org/jetbrains/java/decompiler/main/rels/MethodProcessorThread.java488
1 files changed, 237 insertions, 251 deletions
diff --git a/src/org/jetbrains/java/decompiler/main/rels/MethodProcessorThread.java b/src/org/jetbrains/java/decompiler/main/rels/MethodProcessorThread.java
index c3c180b..038e057 100644
--- a/src/org/jetbrains/java/decompiler/main/rels/MethodProcessorThread.java
+++ b/src/org/jetbrains/java/decompiler/main/rels/MethodProcessorThread.java
@@ -1,21 +1,20 @@
/*
- * Fernflower - The Analytical Java Decompiler
- * http://www.reversed-java.com
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * (C) 2008 - 2010, Stiver
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This software is NEITHER public domain NOR free software
- * as per GNU License. See license.txt for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This software is distributed WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.jetbrains.java.decompiler.main.rels;
-import java.io.IOException;
-
import org.jetbrains.java.decompiler.code.InstructionSequence;
import org.jetbrains.java.decompiler.code.cfg.ControlFlowGraph;
import org.jetbrains.java.decompiler.main.DecompilerContext;
@@ -23,252 +22,239 @@ import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.modules.code.DeadCodeHelper;
-import org.jetbrains.java.decompiler.modules.decompiler.ClearStructHelper;
-import org.jetbrains.java.decompiler.modules.decompiler.DomHelper;
-import org.jetbrains.java.decompiler.modules.decompiler.ExitHelper;
-import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
-import org.jetbrains.java.decompiler.modules.decompiler.FinallyProcessor;
-import org.jetbrains.java.decompiler.modules.decompiler.IdeaNotNullHelper;
-import org.jetbrains.java.decompiler.modules.decompiler.IfHelper;
-import org.jetbrains.java.decompiler.modules.decompiler.InlineSingleBlockHelper;
-import org.jetbrains.java.decompiler.modules.decompiler.LabelHelper;
-import org.jetbrains.java.decompiler.modules.decompiler.LoopExtractHelper;
-import org.jetbrains.java.decompiler.modules.decompiler.MergeHelper;
-import org.jetbrains.java.decompiler.modules.decompiler.PPandMMHelper;
-import org.jetbrains.java.decompiler.modules.decompiler.SecondaryFunctionsHelper;
-import org.jetbrains.java.decompiler.modules.decompiler.SequenceHelper;
-import org.jetbrains.java.decompiler.modules.decompiler.StackVarsProcessor;
+import org.jetbrains.java.decompiler.modules.decompiler.*;
import org.jetbrains.java.decompiler.modules.decompiler.deobfuscator.ExceptionDeobfuscator;
import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.StructMethod;
+import java.io.IOException;
+
public class MethodProcessorThread implements Runnable {
- private StructMethod method;
- private VarProcessor varproc;
- private DecompilerContext parentContext;
-
- private RootStatement root;
-
- private Throwable error;
-
- public MethodProcessorThread(StructMethod method, VarProcessor varproc,
- DecompilerContext parentContext) {
- this.method = method;
- this.varproc = varproc;
- this.parentContext = parentContext;
- }
-
- public void run() {
-
- DecompilerContext.setCurrentContext(parentContext);
-
- error = null;
- root = null;
-
- try {
- root = codeToJava(method, varproc);
-
- synchronized(this) {
- this.notify();
- }
-
- } catch(ThreadDeath ex) {
- ;
- } catch(Throwable ex) {
- error = ex;
- }
-
- }
-
- public static RootStatement codeToJava(StructMethod mt, VarProcessor varproc) throws IOException {
-
- StructClass cl = mt.getClassStruct();
-
- boolean isInitializer = "<clinit>".equals(mt.getName()); // for now static initializer only
-
- mt.expandData();
- InstructionSequence seq = mt.getInstructionSequence();
- ControlFlowGraph graph = new ControlFlowGraph(seq);
-
-// System.out.println(graph.toString());
-
-
-// if(mt.getName().endsWith("_getActiveServers")) {
-// System.out.println();
-// }
-
- //DotExporter.toDotFile(graph, new File("c:\\Temp\\fern1.dot"), true);
-
- DeadCodeHelper.removeDeadBlocks(graph);
- graph.inlineJsr(mt);
-
-// DotExporter.toDotFile(graph, new File("c:\\Temp\\fern4.dot"), true);
-
- // TODO: move to the start, before jsr inlining
- DeadCodeHelper.connectDummyExitBlock(graph);
-
- DeadCodeHelper.removeGotos(graph);
- ExceptionDeobfuscator.removeCircularRanges(graph);
- //DeadCodeHelper.removeCircularRanges(graph);
-
-
-// DotExporter.toDotFile(graph, new File("c:\\Temp\\fern3.dot"), true);
-
- ExceptionDeobfuscator.restorePopRanges(graph);
-
- if(DecompilerContext.getOption(IFernflowerPreferences.REMOVE_EMPTY_RANGES)) {
- ExceptionDeobfuscator.removeEmptyRanges(graph);
- }
-
-// DotExporter.toDotFile(graph, new File("c:\\Temp\\fern3.dot"), true);
-
- if(DecompilerContext.getOption(IFernflowerPreferences.NO_EXCEPTIONS_RETURN)) {
- // special case: single return instruction outside of a protected range
- DeadCodeHelper.incorporateValueReturns(graph);
- }
-
-// DotExporter.toDotFile(graph, new File("c:\\Temp\\fern5.dot"), true);
-
-// ExceptionDeobfuscator.restorePopRanges(graph);
- ExceptionDeobfuscator.insertEmptyExceptionHandlerBlocks(graph);
-
- DeadCodeHelper.mergeBasicBlocks(graph);
-
- DecompilerContext.getCountercontainer().setCounter(CounterContainer.VAR_COUNTER, mt.getLocalVariables());
-
- //DotExporter.toDotFile(graph, new File("c:\\Temp\\fern3.dot"), true);
- //System.out.println(graph.toString());
-
- if(ExceptionDeobfuscator.hasObfuscatedExceptions(graph)) {
- DecompilerContext.getLogger().writeMessage("Heavily obfuscated exception ranges found!", IFernflowerLogger.WARNING);
- }
-
- RootStatement root = DomHelper.parseGraph(graph);
-
- if(!DecompilerContext.getOption(IFernflowerPreferences.FINALLY_CATCHALL)) {
- FinallyProcessor fproc = new FinallyProcessor(varproc);
- while(fproc.iterateGraph(mt, root, graph)) {
-
- //DotExporter.toDotFile(graph, new File("c:\\Temp\\fern2.dot"), true);
- //System.out.println(graph.toString());
-
- //System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
-
- root = DomHelper.parseGraph(graph);
- }
- }
-
- // remove synchronized exception handler
- // not until now because of comparison between synchronized statements in the finally cycle
- DomHelper.removeSynchronizedHandler(root);
-
-// DotExporter.toDotFile(graph, new File("c:\\Temp\\fern3.dot"), true);
-// System.out.println(graph.toString());
-
-// LabelHelper.lowContinueLabels(root, new HashSet<StatEdge>());
-
- SequenceHelper.condenseSequences(root);
-
- ClearStructHelper.clearStatements(root);
-
- ExprProcessor proc = new ExprProcessor();
- proc.processStatement(root, cl);
-
-// DotExporter.toDotFile(graph, new File("c:\\Temp\\fern3.dot"), true);
-// System.out.println(graph.toString());
-
- //System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
-
- for(;;) {
- StackVarsProcessor stackproc = new StackVarsProcessor();
- stackproc.simplifyStackVars(root, mt, cl);
-
- //System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
-
- varproc.setVarVersions(root);
-
-// System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
-
- if(!new PPandMMHelper().findPPandMM(root)) {
- break;
- }
- }
-
- for(;;) {
-
- LabelHelper.cleanUpEdges(root);
-
- for(;;) {
-
- MergeHelper.enhanceLoops(root);
-
- if(LoopExtractHelper.extractLoops(root)) {
- continue;
- }
-
- if(!IfHelper.mergeAllIfs(root)) {
- break;
- }
- }
-
- if(DecompilerContext.getOption(IFernflowerPreferences.IDEA_NOT_NULL_ANNOTATION)) {
-
- if(IdeaNotNullHelper.removeHardcodedChecks(root, mt)) {
-
- SequenceHelper.condenseSequences(root);
-
- StackVarsProcessor stackproc = new StackVarsProcessor();
- stackproc.simplifyStackVars(root, mt, cl);
-
- varproc.setVarVersions(root);
- }
- }
-
- LabelHelper.identifyLabels(root);
-
-// System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
-
- 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.setVarDefinitions(root);
-
- // must be the last invocation, because it makes the statement structure inconsistent
- // FIXME: new edge type needed
- LabelHelper.replaceContinueWithBreak(root);
-
- mt.releaseResources();
-
-// System.out.println("++++++++++++++++++++++/// \r\n"+root.toJava());
-
- return root;
- }
-
- public RootStatement getRoot() {
- return root;
- }
-
- public Throwable getError() {
- return error;
- }
-
+ private StructMethod method;
+ private VarProcessor varproc;
+ private DecompilerContext parentContext;
+
+ private RootStatement root;
+
+ private Throwable error;
+
+ public MethodProcessorThread(StructMethod method, VarProcessor varproc,
+ DecompilerContext parentContext) {
+ this.method = method;
+ this.varproc = varproc;
+ this.parentContext = parentContext;
+ }
+
+ public void run() {
+
+ DecompilerContext.setCurrentContext(parentContext);
+
+ error = null;
+ root = null;
+
+ try {
+ root = codeToJava(method, varproc);
+
+ synchronized (this) {
+ this.notify();
+ }
+ }
+ catch (ThreadDeath ex) {
+ ;
+ }
+ catch (Throwable ex) {
+ error = ex;
+ }
+ }
+
+ public static RootStatement codeToJava(StructMethod mt, VarProcessor varproc) throws IOException {
+
+ StructClass cl = mt.getClassStruct();
+
+ boolean isInitializer = "<clinit>".equals(mt.getName()); // for now static initializer only
+
+ mt.expandData();
+ InstructionSequence seq = mt.getInstructionSequence();
+ ControlFlowGraph graph = new ControlFlowGraph(seq);
+
+ // System.out.println(graph.toString());
+
+
+ // if(mt.getName().endsWith("_getActiveServers")) {
+ // System.out.println();
+ // }
+
+ //DotExporter.toDotFile(graph, new File("c:\\Temp\\fern1.dot"), true);
+
+ DeadCodeHelper.removeDeadBlocks(graph);
+ graph.inlineJsr(mt);
+
+ // DotExporter.toDotFile(graph, new File("c:\\Temp\\fern4.dot"), true);
+
+ // TODO: move to the start, before jsr inlining
+ DeadCodeHelper.connectDummyExitBlock(graph);
+
+ DeadCodeHelper.removeGotos(graph);
+ ExceptionDeobfuscator.removeCircularRanges(graph);
+ //DeadCodeHelper.removeCircularRanges(graph);
+
+
+ // DotExporter.toDotFile(graph, new File("c:\\Temp\\fern3.dot"), true);
+
+ ExceptionDeobfuscator.restorePopRanges(graph);
+
+ if (DecompilerContext.getOption(IFernflowerPreferences.REMOVE_EMPTY_RANGES)) {
+ ExceptionDeobfuscator.removeEmptyRanges(graph);
+ }
+
+ // DotExporter.toDotFile(graph, new File("c:\\Temp\\fern3.dot"), true);
+
+ if (DecompilerContext.getOption(IFernflowerPreferences.NO_EXCEPTIONS_RETURN)) {
+ // special case: single return instruction outside of a protected range
+ DeadCodeHelper.incorporateValueReturns(graph);
+ }
+
+ // DotExporter.toDotFile(graph, new File("c:\\Temp\\fern5.dot"), true);
+
+ // ExceptionDeobfuscator.restorePopRanges(graph);
+ ExceptionDeobfuscator.insertEmptyExceptionHandlerBlocks(graph);
+
+ DeadCodeHelper.mergeBasicBlocks(graph);
+
+ DecompilerContext.getCountercontainer().setCounter(CounterContainer.VAR_COUNTER, mt.getLocalVariables());
+
+ //DotExporter.toDotFile(graph, new File("c:\\Temp\\fern3.dot"), true);
+ //System.out.println(graph.toString());
+
+ if (ExceptionDeobfuscator.hasObfuscatedExceptions(graph)) {
+ DecompilerContext.getLogger().writeMessage("Heavily obfuscated exception ranges found!", IFernflowerLogger.WARNING);
+ }
+
+ RootStatement root = DomHelper.parseGraph(graph);
+
+ if (!DecompilerContext.getOption(IFernflowerPreferences.FINALLY_CATCHALL)) {
+ FinallyProcessor fproc = new FinallyProcessor(varproc);
+ while (fproc.iterateGraph(mt, root, graph)) {
+
+ //DotExporter.toDotFile(graph, new File("c:\\Temp\\fern2.dot"), true);
+ //System.out.println(graph.toString());
+
+ //System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
+
+ root = DomHelper.parseGraph(graph);
+ }
+ }
+
+ // remove synchronized exception handler
+ // not until now because of comparison between synchronized statements in the finally cycle
+ DomHelper.removeSynchronizedHandler(root);
+
+ // DotExporter.toDotFile(graph, new File("c:\\Temp\\fern3.dot"), true);
+ // System.out.println(graph.toString());
+
+ // LabelHelper.lowContinueLabels(root, new HashSet<StatEdge>());
+
+ SequenceHelper.condenseSequences(root);
+
+ ClearStructHelper.clearStatements(root);
+
+ ExprProcessor proc = new ExprProcessor();
+ proc.processStatement(root, cl);
+
+ // DotExporter.toDotFile(graph, new File("c:\\Temp\\fern3.dot"), true);
+ // System.out.println(graph.toString());
+
+ //System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
+
+ for (; ; ) {
+ StackVarsProcessor stackproc = new StackVarsProcessor();
+ stackproc.simplifyStackVars(root, mt, cl);
+
+ //System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
+
+ varproc.setVarVersions(root);
+
+ // System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
+
+ if (!new PPandMMHelper().findPPandMM(root)) {
+ break;
+ }
+ }
+
+ for (; ; ) {
+
+ LabelHelper.cleanUpEdges(root);
+
+ for (; ; ) {
+
+ MergeHelper.enhanceLoops(root);
+
+ if (LoopExtractHelper.extractLoops(root)) {
+ continue;
+ }
+
+ if (!IfHelper.mergeAllIfs(root)) {
+ break;
+ }
+ }
+
+ if (DecompilerContext.getOption(IFernflowerPreferences.IDEA_NOT_NULL_ANNOTATION)) {
+
+ if (IdeaNotNullHelper.removeHardcodedChecks(root, mt)) {
+
+ SequenceHelper.condenseSequences(root);
+
+ StackVarsProcessor stackproc = new StackVarsProcessor();
+ stackproc.simplifyStackVars(root, mt, cl);
+
+ varproc.setVarVersions(root);
+ }
+ }
+
+ LabelHelper.identifyLabels(root);
+
+ // System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
+
+ 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.setVarDefinitions(root);
+
+ // must be the last invocation, because it makes the statement structure inconsistent
+ // FIXME: new edge type needed
+ LabelHelper.replaceContinueWithBreak(root);
+
+ mt.releaseResources();
+
+ // System.out.println("++++++++++++++++++++++/// \r\n"+root.toJava());
+
+ return root;
+ }
+
+ public RootStatement getRoot() {
+ return root;
+ }
+
+ public Throwable getError() {
+ return error;
+ }
}