|
|
@ -1,37 +1,21 @@ |
|
|
|
/* |
|
|
|
/* |
|
|
|
* Fernflower - The Analytical Java Decompiler |
|
|
|
* Copyright 2000-2014 JetBrains s.r.o. |
|
|
|
* http://www.reversed-java.com
|
|
|
|
|
|
|
|
* |
|
|
|
* |
|
|
|
* (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 |
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
* as per GNU License. See license.txt for more details. |
|
|
|
|
|
|
|
* |
|
|
|
* |
|
|
|
* This software is distributed WITHOUT ANY WARRANTY; without |
|
|
|
* Unless required by applicable law or agreed to in writing, software |
|
|
|
* even the implied warranty of MERCHANTABILITY or FITNESS FOR |
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
|
|
* A PARTICULAR PURPOSE. |
|
|
|
* 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.code.cfg; |
|
|
|
package org.jetbrains.java.decompiler.code.cfg; |
|
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
import org.jetbrains.java.decompiler.code.*; |
|
|
|
import java.util.Arrays; |
|
|
|
|
|
|
|
import java.util.HashMap; |
|
|
|
|
|
|
|
import java.util.HashSet; |
|
|
|
|
|
|
|
import java.util.Iterator; |
|
|
|
|
|
|
|
import java.util.LinkedList; |
|
|
|
|
|
|
|
import java.util.List; |
|
|
|
|
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
import java.util.Map.Entry; |
|
|
|
|
|
|
|
import java.util.Set; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import org.jetbrains.java.decompiler.code.CodeConstants; |
|
|
|
|
|
|
|
import org.jetbrains.java.decompiler.code.ExceptionHandler; |
|
|
|
|
|
|
|
import org.jetbrains.java.decompiler.code.Instruction; |
|
|
|
|
|
|
|
import org.jetbrains.java.decompiler.code.InstructionSequence; |
|
|
|
|
|
|
|
import org.jetbrains.java.decompiler.code.JumpInstruction; |
|
|
|
|
|
|
|
import org.jetbrains.java.decompiler.code.SimpleInstructionSequence; |
|
|
|
|
|
|
|
import org.jetbrains.java.decompiler.code.SwitchInstruction; |
|
|
|
|
|
|
|
import org.jetbrains.java.decompiler.code.interpreter.InstructionImpact; |
|
|
|
import org.jetbrains.java.decompiler.code.interpreter.InstructionImpact; |
|
|
|
import org.jetbrains.java.decompiler.main.DecompilerContext; |
|
|
|
import org.jetbrains.java.decompiler.main.DecompilerContext; |
|
|
|
import org.jetbrains.java.decompiler.modules.code.DeadCodeHelper; |
|
|
|
import org.jetbrains.java.decompiler.modules.code.DeadCodeHelper; |
|
|
@ -42,6 +26,9 @@ import org.jetbrains.java.decompiler.struct.gen.VarType; |
|
|
|
import org.jetbrains.java.decompiler.util.ListStack; |
|
|
|
import org.jetbrains.java.decompiler.util.ListStack; |
|
|
|
import org.jetbrains.java.decompiler.util.VBStyleCollection; |
|
|
|
import org.jetbrains.java.decompiler.util.VBStyleCollection; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.*; |
|
|
|
|
|
|
|
import java.util.Map.Entry; |
|
|
|
|
|
|
|
|
|
|
|
public class ControlFlowGraph implements CodeConstants { |
|
|
|
public class ControlFlowGraph implements CodeConstants { |
|
|
|
|
|
|
|
|
|
|
|
public int last_id = 0; |
|
|
|
public int last_id = 0; |
|
|
@ -116,11 +103,13 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
|
|
|
|
|
|
|
|
if (range == null) { |
|
|
|
if (range == null) { |
|
|
|
buf.append(">>>>>>>>(exception) Block " + handler.id + "\t" + "ERROR: range not found!" + new_line_separator); |
|
|
|
buf.append(">>>>>>>>(exception) Block " + handler.id + "\t" + "ERROR: range not found!" + new_line_separator); |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
List<String> exceptionTypes = range.getExceptionTypes(); |
|
|
|
List<String> exceptionTypes = range.getExceptionTypes(); |
|
|
|
if (exceptionTypes == null) { |
|
|
|
if (exceptionTypes == null) { |
|
|
|
buf.append(">>>>>>>>(exception) Block " + handler.id + "\t" + "NULL" + new_line_separator); |
|
|
|
buf.append(">>>>>>>>(exception) Block " + handler.id + "\t" + "NULL" + new_line_separator); |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
for (String exceptionType : exceptionTypes) { |
|
|
|
for (String exceptionType : exceptionTypes) { |
|
|
|
buf.append(">>>>>>>>(exception) Block " + handler.id + "\t" + exceptionType + new_line_separator); |
|
|
|
buf.append(">>>>>>>>(exception) Block " + handler.id + "\t" + exceptionType + new_line_separator); |
|
|
|
} |
|
|
|
} |
|
|
@ -128,11 +117,9 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
buf.append("----- ----- -----" + new_line_separator); |
|
|
|
buf.append("----- ----- -----" + new_line_separator); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return buf.toString(); |
|
|
|
return buf.toString(); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void inlineJsr(StructMethod mt) { |
|
|
|
public void inlineJsr(StructMethod mt) { |
|
|
@ -170,7 +157,8 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
ExceptionRangeCFG range = (ExceptionRangeCFG)exceptions.get(i); |
|
|
|
ExceptionRangeCFG range = (ExceptionRangeCFG)exceptions.get(i); |
|
|
|
if (range.getHandler() == block) { |
|
|
|
if (range.getHandler() == block) { |
|
|
|
exceptions.remove(i); |
|
|
|
exceptions.remove(i); |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
List<BasicBlock> lstRange = range.getProtectedRange(); |
|
|
|
List<BasicBlock> lstRange = range.getProtectedRange(); |
|
|
|
lstRange.remove(block); |
|
|
|
lstRange.remove(block); |
|
|
|
|
|
|
|
|
|
|
@ -187,7 +175,6 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
it.remove(); |
|
|
|
it.remove(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public ExceptionRangeCFG getExceptionRange(BasicBlock handler, BasicBlock block) { |
|
|
|
public ExceptionRangeCFG getExceptionRange(BasicBlock handler, BasicBlock block) { |
|
|
@ -376,7 +363,6 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
block.addSuccessor(defaultBlock); |
|
|
|
block.addSuccessor(defaultBlock); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void setExceptionEdges(InstructionSequence instrseq, HashMap<Integer, BasicBlock> instrBlocks) { |
|
|
|
private void setExceptionEdges(InstructionSequence instrseq, HashMap<Integer, BasicBlock> instrBlocks) { |
|
|
@ -396,7 +382,8 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
if (mapRanges.containsKey(key)) { |
|
|
|
if (mapRanges.containsKey(key)) { |
|
|
|
ExceptionRangeCFG range = mapRanges.get(key); |
|
|
|
ExceptionRangeCFG range = mapRanges.get(key); |
|
|
|
range.addExceptionType(handler.exceptionClass); |
|
|
|
range.addExceptionType(handler.exceptionClass); |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
|
|
|
|
List<BasicBlock> protectedRange = new ArrayList<BasicBlock>(); |
|
|
|
List<BasicBlock> protectedRange = new ArrayList<BasicBlock>(); |
|
|
|
for (int j = from.id; j < to.id; j++) { |
|
|
|
for (int j = from.id; j < to.id; j++) { |
|
|
@ -405,7 +392,9 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
block.addSuccessorException(handle); |
|
|
|
block.addSuccessorException(handle); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ExceptionRangeCFG range = new ExceptionRangeCFG(protectedRange, handle, handler.exceptionClass == null ? null : Arrays.asList(new String[]{handler.exceptionClass})); |
|
|
|
ExceptionRangeCFG range = new ExceptionRangeCFG(protectedRange, handle, handler.exceptionClass == null |
|
|
|
|
|
|
|
? null |
|
|
|
|
|
|
|
: Arrays.asList(new String[]{handler.exceptionClass})); |
|
|
|
mapRanges.put(key, range); |
|
|
|
mapRanges.put(key, range); |
|
|
|
|
|
|
|
|
|
|
|
exceptions.add(range); |
|
|
|
exceptions.add(range); |
|
|
@ -450,7 +439,8 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
} |
|
|
|
} |
|
|
|
jsrstack.removeLast(); |
|
|
|
jsrstack.removeLast(); |
|
|
|
subroutines.put(enter, exit); |
|
|
|
subroutines.put(enter, exit); |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
throw new RuntimeException("ERROR: last instruction jsr"); |
|
|
|
throw new RuntimeException("ERROR: last instruction jsr"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -549,7 +539,8 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
lst = node.getSuccs(); |
|
|
|
lst = node.getSuccs(); |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
if (node == jsr) { |
|
|
|
if (node == jsr) { |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
@ -611,7 +602,8 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
lst = node.getSuccs(); |
|
|
|
lst = node.getSuccs(); |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
if (node == jsr) { |
|
|
|
if (node == jsr) { |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
@ -626,7 +618,8 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
|
|
|
|
|
|
|
|
if (mapNewNodes.containsKey(childid)) { |
|
|
|
if (mapNewNodes.containsKey(childid)) { |
|
|
|
node.replaceSuccessor(child, (BasicBlock)mapNewNodes.get(childid)); |
|
|
|
node.replaceSuccessor(child, (BasicBlock)mapNewNodes.get(childid)); |
|
|
|
} else if(common_blocks.contains(child)) { |
|
|
|
} |
|
|
|
|
|
|
|
else if (common_blocks.contains(child)) { |
|
|
|
|
|
|
|
|
|
|
|
// make a copy of the current block
|
|
|
|
// make a copy of the current block
|
|
|
|
BasicBlock copy = (BasicBlock)child.clone(); |
|
|
|
BasicBlock copy = (BasicBlock)child.clone(); |
|
|
@ -636,7 +629,8 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
child.getSuccs().contains(ret)) { |
|
|
|
child.getSuccs().contains(ret)) { |
|
|
|
copy.addSuccessor(ret); |
|
|
|
copy.addSuccessor(ret); |
|
|
|
child.removeSuccessor(ret); |
|
|
|
child.removeSuccessor(ret); |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
for (int k = 0; k < child.getSuccs().size(); k++) { |
|
|
|
for (int k = 0; k < child.getSuccs().size(); k++) { |
|
|
|
copy.addSuccessor((BasicBlock)child.getSuccs().get(k)); |
|
|
|
copy.addSuccessor((BasicBlock)child.getSuccs().get(k)); |
|
|
|
} |
|
|
|
} |
|
|
@ -654,13 +648,13 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
|
|
|
|
|
|
|
|
node.replaceSuccessor(child, copy); |
|
|
|
node.replaceSuccessor(child, copy); |
|
|
|
blocks.addWithKey(copy, copy.id); |
|
|
|
blocks.addWithKey(copy, copy.id); |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
// stop at the first fixed node
|
|
|
|
// stop at the first fixed node
|
|
|
|
//lstNodes.add(child);
|
|
|
|
//lstNodes.add(child);
|
|
|
|
mapNewNodes.put(childid, child); |
|
|
|
mapNewNodes.put(childid, child); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -686,7 +680,8 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
ExceptionRangeCFG newRange = new ExceptionRangeCFG(lstNewRange, |
|
|
|
ExceptionRangeCFG newRange = new ExceptionRangeCFG(lstNewRange, |
|
|
|
(BasicBlock)mapNewNodes.get(range.getHandler().id), range.getExceptionTypes()); |
|
|
|
(BasicBlock)mapNewNodes.get(range.getHandler().id), range.getExceptionTypes()); |
|
|
|
exceptions.add(newRange); |
|
|
|
exceptions.add(newRange); |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
lstNewRange = lstRange; |
|
|
|
lstNewRange = lstRange; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -695,7 +690,6 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void removeJsr(StructMethod mt) { |
|
|
|
private void removeJsr(StructMethod mt) { |
|
|
@ -730,7 +724,6 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
i--; |
|
|
|
i--; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
block.mark = 1; |
|
|
|
block.mark = 1; |
|
|
@ -753,7 +746,6 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
removeJsrInstructions(pool, suc, point); |
|
|
|
removeJsrInstructions(pool, suc, point); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void setFirstAndLastBlocks() { |
|
|
|
private void setFirstAndLastBlocks() { |
|
|
@ -818,7 +810,6 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
stackNode.removeLast(); |
|
|
|
stackNode.removeLast(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -883,5 +874,4 @@ public class ControlFlowGraph implements CodeConstants { |
|
|
|
public void setFinallyExits(HashSet<BasicBlock> finallyExits) { |
|
|
|
public void setFinallyExits(HashSet<BasicBlock> finallyExits) { |
|
|
|
this.finallyExits = finallyExits; |
|
|
|
this.finallyExits = finallyExits; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|