diff --git a/trunk/src/com/jpexs/asdec/abc/avm2/AVM2Code.java b/trunk/src/com/jpexs/asdec/abc/avm2/AVM2Code.java index 3f6428766..cdd385731 100644 --- a/trunk/src/com/jpexs/asdec/abc/avm2/AVM2Code.java +++ b/trunk/src/com/jpexs/asdec/abc/avm2/AVM2Code.java @@ -20,7 +20,7 @@ import com.jpexs.asdec.Main; import com.jpexs.asdec.abc.ABC; import com.jpexs.asdec.abc.ABCInputStream; import com.jpexs.asdec.abc.CopyOutputStream; -import com.jpexs.asdec.abc.avm2.flowgraph.Graph; +import com.jpexs.asdec.abc.avm2.graph.AVM2Graph; import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction; import com.jpexs.asdec.abc.avm2.instructions.IfTypeIns; import com.jpexs.asdec.abc.avm2.instructions.InstructionDefinition; @@ -1901,7 +1901,7 @@ public class AVM2Code implements Serializable { //try { try{ - list = Graph.translateViaGraph(path,this, abc, body); + list = AVM2Graph.translateViaGraph(path,this, abc, body); }catch(Exception ex2){ Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, "Decompilation error in "+path,ex2); return "/*\r\n * Decompilation error\r\n * Code may be obfuscated\r\n * Error Message: " + ex2.getMessage() + "\r\n */"; diff --git a/trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/Graph.java b/trunk/src/com/jpexs/asdec/abc/avm2/graph/AVM2Graph.java similarity index 84% rename from trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/Graph.java rename to trunk/src/com/jpexs/asdec/abc/avm2/graph/AVM2Graph.java index ffab8f10f..9d21407df 100644 --- a/trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/Graph.java +++ b/trunk/src/com/jpexs/asdec/abc/avm2/graph/AVM2Graph.java @@ -14,8 +14,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.jpexs.asdec.abc.avm2.flowgraph; +package com.jpexs.asdec.abc.avm2.graph; +import com.jpexs.asdec.graph.Graph; +import com.jpexs.asdec.graph.GraphPart; +import com.jpexs.asdec.graph.Loop; +import com.jpexs.asdec.graph.GraphPartMulti; import com.jpexs.asdec.abc.ABC; import com.jpexs.asdec.abc.avm2.AVM2Code; import com.jpexs.asdec.abc.avm2.ConvertException; @@ -85,69 +89,26 @@ import java.util.logging.Logger; * * @author JPEXS */ -public class Graph { +public class AVM2Graph extends Graph{ - public List heads; private AVM2Code code; private ABC abc; private MethodBody body; - public Graph(AVM2Code code, ABC abc, MethodBody body) { + public AVM2Graph(AVM2Code code, ABC abc, MethodBody body) { heads = makeGraph(code, new ArrayList(), body); this.code = code; this.abc = abc; this.body = body; for (GraphPart head : heads) { - fixGraph(head); - //makeMulti(head, new ArrayList()); + fixGraph(head); } } - private void makeMulti(GraphPart part, List visited) { - if (visited.contains(part)) { - return; - } - visited.add(part); - GraphPart p = part; - List multiList = new ArrayList(); - multiList.add(p); - while ((p.nextParts.size() == 1) && (p.nextParts.get(0).refs.size() == 1)) { - p = p.nextParts.get(0); - multiList.add(p); - } - if (multiList.size() > 1) { - GraphPartMulti gpm = new GraphPartMulti(multiList); - gpm.refs = part.refs; - GraphPart lastPart = multiList.get(multiList.size() - 1); - gpm.nextParts = lastPart.nextParts; - for (GraphPart next : gpm.nextParts) { - int index = next.refs.indexOf(lastPart); - if (index == -1) { - - continue; - } - next.refs.remove(lastPart); - next.refs.add(index, gpm); - } - for (GraphPart parent : part.refs) { - if (parent.start == -1) { - continue; - } - int index = parent.nextParts.indexOf(part); - if (index == -1) { - continue; - } - parent.nextParts.remove(part); - parent.nextParts.add(index, gpm); - } - } - for (int i = 0; i < part.nextParts.size(); i++) { - makeMulti(part.nextParts.get(i), visited); - } - } + public static List translateViaGraph(String path, AVM2Code code, ABC abc, MethodBody body) { - Graph g = new Graph(code, abc, body); + AVM2Graph g = new AVM2Graph(code, abc, body); List allParts = new ArrayList(); for (GraphPart head : g.heads) { populateParts(head, allParts); @@ -155,37 +116,7 @@ public class Graph { return g.printGraph(path, new Stack(), new Stack(), allParts, new ArrayList(), new ArrayList(), 0, null, g.heads.get(0), null, new ArrayList(), new HashMap(), body, new ArrayList()); } - private static void populateParts(GraphPart part, List allParts) { - if (allParts.contains(part)) { - return; - } - allParts.add(part); - for (GraphPart p : part.nextParts) { - populateParts(p, allParts); - } - } - - private String strOfChars(int len, String chars) { - String ret = ""; - for (int i = 0; i < len; i++) { - ret += chars; - } - return ret; - } - private static final String TAB = " "; - - private String printOutput(int level, List output, List fqn, HashMap lrn) { - String s = Highlighting.stripHilights(code.listToString(output, abc.constants, lrn, fqn)); - String parts[] = s.split("\n"); - String ret = ""; - for (String p : parts) { - if (p.trim().equals("")) { - continue; - } - ret += (strOfChars(level, TAB) + p.trim()) + "\r\n"; - } - return ret; - } + private TreeItem checkLoop(GraphPart part, GraphPart stopPart, List loops) { if (part == stopPart) { @@ -394,7 +325,7 @@ public class Graph { //((IfTypeIns)ins.definition).translateInverted(new HashMap(), co.stack, ins); } } catch (ConvertException ex) { - Logger.getLogger(Graph.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(AVM2Graph.class.getName()).log(Level.SEVERE, null, ex); } int ip = part.start; @@ -615,8 +546,11 @@ public class Graph { } finalPart = fex.continuePart; isFor = true; - for (ContinueTreeItem cti : finalPart.forContinues) { - cti.loopPos = breakIp; + for (Object o : finalPart.forContinues) { + if(o instanceof ContinueTreeItem) + { + ((ContinueTreeItem)o).loopPos = breakIp; + } } } if (isFor) { @@ -867,135 +801,7 @@ public class Graph { return ret; } - private void fixGraph(GraphPart part) { - while (fixGraphOnce(part, new ArrayList(), false)) { - } - } - - private boolean fixGraphOnce(GraphPart part, List visited, boolean doChildren) { - if (visited.contains(part)) { - return false; - } - visited.add(part); - boolean fixed = false; - /*System.out.print("Part " + part.start + "-" + part.end + " refs:"); - for (GraphPart gp : part.refs) { - System.out.print(gp.path + " "); - } - System.out.println("");*/ - int i = 1; - String lastpref = null; - boolean modify = true; - int prvni = -1; - - if (!doChildren) { - - List uniqueRefs = new ArrayList(); - for (GraphPart r : part.refs) { - if (!uniqueRefs.contains(r)) { - uniqueRefs.add(r); - } - } - loopi: - for (; i <= part.path.length(); i++) { - lastpref = null; - int pos = -1; - for (GraphPart r : uniqueRefs) { - pos++; - if (r.path.startsWith("e")) { - continue; - } - if (part.leadsTo(r, new ArrayList())) { - //modify=false; - //continue; - } - - prvni = pos; - if (i > r.path.length()) { - i--; - break loopi; - } - if (lastpref == null) { - lastpref = r.path.substring(0, i); - } else { - if (!r.path.startsWith(lastpref)) { - i--; - break loopi; - } - } - } - } - if (i > part.path.length()) { - i = part.path.length(); - } - if (modify && ((uniqueRefs.size() > 1) && (prvni >= 0))) { - String newpath = uniqueRefs.get(prvni).path.substring(0, i); - if (!part.path.equals(newpath)) { - if (part.path.startsWith(newpath)) { - String origPath = part.path; - GraphPart p = part; - part.path = newpath; - while (p.nextParts.size() == 1) { - p = p.nextParts.get(0); - if (!p.path.equals(origPath)) { - break; - } - p.path = newpath; - } - fixGraphOnce(part, new ArrayList(), true); - fixed = true; - } - } - } - } else { - - if (!fixed) { - if (part.nextParts.size() == 1) { - if (!(part.path.startsWith("e") && (!part.nextParts.get(0).path.startsWith("e")))) { - if (part.nextParts.get(0).path.length() > part.path.length()) { - part.nextParts.get(0).path = part.path; - fixed = true; - } - } - } - if (part.nextParts.size() > 1) { - for (int j = 0; j < part.nextParts.size(); j++) { - GraphPart npart = part.nextParts.get(j); - - if (npart.path.length() > part.path.length() + 1) { - npart.path = part.path + "" + j; - fixed = true; - } - } - } - } - - } - /* if (part.nextParts.size() == 2) { - GraphPart left = part.nextParts.get(0); - GraphPart right = part.nextParts.get(1); - if ((left.nextParts.size() == 1) && (right.nextParts.size() == 1)) { - if (left.nextParts.get(0) == right.nextParts.get(0)) { - if (!left.nextParts.get(0).path.equals(part.path)) { - String origPath = left.nextParts.get(0).path; - GraphPart p = left; - while (p.nextParts.size() == 1) { - p = p.nextParts.get(0); - if (!p.path.equals(origPath)) { - break; - } - p.path = part.path; - } - fixed = true; - } - } - } - }*/ - for (GraphPart p : part.nextParts) { - fixGraphOnce(p, visited, doChildren); - } - return fixed; - } + private List makeGraph(AVM2Code code, List allBlocks, MethodBody body) { HashMap> refs = code.visitCode(body); diff --git a/trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/ForException.java b/trunk/src/com/jpexs/asdec/abc/avm2/graph/ForException.java similarity index 82% rename from trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/ForException.java rename to trunk/src/com/jpexs/asdec/abc/avm2/graph/ForException.java index 89acd134b..2059ca970 100644 --- a/trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/ForException.java +++ b/trunk/src/com/jpexs/asdec/abc/avm2/graph/ForException.java @@ -1,5 +1,6 @@ -package com.jpexs.asdec.abc.avm2.flowgraph; +package com.jpexs.asdec.abc.avm2.graph; +import com.jpexs.asdec.graph.GraphPart; import com.jpexs.asdec.abc.avm2.treemodel.TreeItem; import java.util.List; diff --git a/trunk/src/com/jpexs/asdec/abc/gui/ASMSourceEditorPane.java b/trunk/src/com/jpexs/asdec/abc/gui/ASMSourceEditorPane.java index ed933e755..278e8a547 100644 --- a/trunk/src/com/jpexs/asdec/abc/gui/ASMSourceEditorPane.java +++ b/trunk/src/com/jpexs/asdec/abc/gui/ASMSourceEditorPane.java @@ -19,7 +19,7 @@ package com.jpexs.asdec.abc.gui; import com.jpexs.asdec.abc.ABC; import com.jpexs.asdec.abc.avm2.AVM2Code; import com.jpexs.asdec.abc.avm2.ConstantPool; -import com.jpexs.asdec.abc.avm2.flowgraph.Graph; +import com.jpexs.asdec.abc.avm2.graph.AVM2Graph; import com.jpexs.asdec.abc.avm2.parser.ASM3Parser; import com.jpexs.asdec.abc.avm2.parser.ParseException; import com.jpexs.asdec.helpers.Highlighting; @@ -73,7 +73,7 @@ public class ASMSourceEditorPane extends LineMarkedEditorPane implements CaretLi } public void graph() { - Graph gr = new Graph(abc.bodies[bodyIndex].code,abc,abc.bodies[bodyIndex]); + AVM2Graph gr = new AVM2Graph(abc.bodies[bodyIndex].code,abc,abc.bodies[bodyIndex]); (new GraphFrame(gr, "")).setVisible(true); } diff --git a/trunk/src/com/jpexs/asdec/abc/gui/GraphFrame.java b/trunk/src/com/jpexs/asdec/abc/gui/GraphFrame.java index 1d8f70e9b..c36fa6b83 100644 --- a/trunk/src/com/jpexs/asdec/abc/gui/GraphFrame.java +++ b/trunk/src/com/jpexs/asdec/abc/gui/GraphFrame.java @@ -16,8 +16,8 @@ */ package com.jpexs.asdec.abc.gui; -import com.jpexs.asdec.abc.avm2.flowgraph.Graph; -import com.jpexs.asdec.abc.avm2.flowgraph.GraphPart; +import com.jpexs.asdec.abc.avm2.graph.AVM2Graph; +import com.jpexs.asdec.graph.GraphPart; import com.jpexs.asdec.gui.View; import java.awt.*; import java.util.ArrayList; @@ -41,9 +41,9 @@ public class GraphFrame extends JFrame { private static final int SPACE_HORIZONTAL = 10; private static final int BLOCK_WIDTH = 200; private static final int BLOCK_HEIGHT = 20; - private Graph graph; + private AVM2Graph graph; - public GraphPanel(Graph graph) { + public GraphPanel(AVM2Graph graph) { this.graph = graph; setPreferredSize(new Dimension((BLOCK_WIDTH + SPACE_HORIZONTAL) * getPartWidth(graph.heads.get(0), new HashSet()), (BLOCK_HEIGHT + SPACE_VERTICAL) * getPartHeight(graph.heads.get(0), new ArrayList()))); } @@ -121,7 +121,7 @@ public class GraphFrame extends JFrame { } } - public GraphFrame(Graph graph, String name) { + public GraphFrame(AVM2Graph graph, String name) { setSize(500, 500); Container cnt = getContentPane(); cnt.setLayout(new BorderLayout()); diff --git a/trunk/src/com/jpexs/asdec/abc/gui/GraphTreeFrame.java b/trunk/src/com/jpexs/asdec/abc/gui/GraphTreeFrame.java index 568af4eb7..d1776a490 100644 --- a/trunk/src/com/jpexs/asdec/abc/gui/GraphTreeFrame.java +++ b/trunk/src/com/jpexs/asdec/abc/gui/GraphTreeFrame.java @@ -16,8 +16,8 @@ */ package com.jpexs.asdec.abc.gui; -import com.jpexs.asdec.abc.avm2.flowgraph.Graph; -import com.jpexs.asdec.abc.avm2.flowgraph.GraphPart; +import com.jpexs.asdec.abc.avm2.graph.AVM2Graph; +import com.jpexs.asdec.graph.GraphPart; import java.awt.BorderLayout; import java.awt.Container; import javax.swing.JFrame; @@ -34,7 +34,7 @@ public class GraphTreeFrame extends JFrame { public JTree graphTree; - public GraphTreeFrame(final Graph graph) { + public GraphTreeFrame(final AVM2Graph graph) { setSize(400, 400); graphTree = new JTree(new TreeModel() { public Object getRoot() { diff --git a/trunk/src/com/jpexs/asdec/abc/types/traits/TraitMethodGetterSetter.java b/trunk/src/com/jpexs/asdec/abc/types/traits/TraitMethodGetterSetter.java index 3717909fd..e378119d6 100644 --- a/trunk/src/com/jpexs/asdec/abc/types/traits/TraitMethodGetterSetter.java +++ b/trunk/src/com/jpexs/asdec/abc/types/traits/TraitMethodGetterSetter.java @@ -17,7 +17,7 @@ package com.jpexs.asdec.abc.types.traits; import com.jpexs.asdec.abc.ABC; -import com.jpexs.asdec.abc.avm2.flowgraph.Graph; +import com.jpexs.asdec.abc.avm2.graph.AVM2Graph; import com.jpexs.asdec.abc.avm2.treemodel.TreeItem; import com.jpexs.asdec.abc.types.MethodBody; import com.jpexs.asdec.helpers.Helper; diff --git a/trunk/src/com/jpexs/asdec/graph/Graph.java b/trunk/src/com/jpexs/asdec/graph/Graph.java new file mode 100644 index 000000000..34d85685f --- /dev/null +++ b/trunk/src/com/jpexs/asdec/graph/Graph.java @@ -0,0 +1,170 @@ +package com.jpexs.asdec.graph; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +public abstract class Graph { + public List heads; + + protected static void populateParts(GraphPart part, List allParts) { + if (allParts.contains(part)) { + return; + } + allParts.add(part); + for (GraphPart p : part.nextParts) { + populateParts(p, allParts); + } + } + + protected void fixGraph(GraphPart part) { + while (fixGraphOnce(part, new ArrayList(), false)) { + } + } + + private boolean fixGraphOnce(GraphPart part, List visited, boolean doChildren) { + if (visited.contains(part)) { + return false; + } + visited.add(part); + boolean fixed = false; + int i = 1; + String lastpref = null; + boolean modify = true; + int prvni = -1; + + if (!doChildren) { + + List uniqueRefs = new ArrayList(); + for (GraphPart r : part.refs) { + if (!uniqueRefs.contains(r)) { + uniqueRefs.add(r); + } + } + loopi: + for (; i <= part.path.length(); i++) { + lastpref = null; + int pos = -1; + for (GraphPart r : uniqueRefs) { + pos++; + if (r.path.startsWith("e")) { + continue; + } + if (part.leadsTo(r, new ArrayList())) { + //modify=false; + //continue; + } + + prvni = pos; + if (i > r.path.length()) { + i--; + break loopi; + } + if (lastpref == null) { + lastpref = r.path.substring(0, i); + } else { + if (!r.path.startsWith(lastpref)) { + i--; + break loopi; + } + } + } + } + if (i > part.path.length()) { + i = part.path.length(); + } + if (modify && ((uniqueRefs.size() > 1) && (prvni >= 0))) { + String newpath = uniqueRefs.get(prvni).path.substring(0, i); + if (!part.path.equals(newpath)) { + if (part.path.startsWith(newpath)) { + String origPath = part.path; + GraphPart p = part; + part.path = newpath; + while (p.nextParts.size() == 1) { + p = p.nextParts.get(0); + if (!p.path.equals(origPath)) { + break; + } + p.path = newpath; + } + fixGraphOnce(part, new ArrayList(), true); + fixed = true; + } + } + } + } else { + + if (!fixed) { + if (part.nextParts.size() == 1) { + if (!(part.path.startsWith("e") && (!part.nextParts.get(0).path.startsWith("e")))) { + if (part.nextParts.get(0).path.length() > part.path.length()) { + part.nextParts.get(0).path = part.path; + fixed = true; + } + } + } + if (part.nextParts.size() > 1) { + for (int j = 0; j < part.nextParts.size(); j++) { + GraphPart npart = part.nextParts.get(j); + + if (npart.path.length() > part.path.length() + 1) { + npart.path = part.path + "" + j; + fixed = true; + } + } + } + } + + } + for (GraphPart p : part.nextParts) { + fixGraphOnce(p, visited, doChildren); + } + return fixed; + } + + protected void makeMulti(GraphPart part, List visited) { + if (visited.contains(part)) { + return; + } + visited.add(part); + GraphPart p = part; + List multiList = new ArrayList(); + multiList.add(p); + while ((p.nextParts.size() == 1) && (p.nextParts.get(0).refs.size() == 1)) { + p = p.nextParts.get(0); + multiList.add(p); + } + if (multiList.size() > 1) { + GraphPartMulti gpm = new GraphPartMulti(multiList); + gpm.refs = part.refs; + GraphPart lastPart = multiList.get(multiList.size() - 1); + gpm.nextParts = lastPart.nextParts; + for (GraphPart next : gpm.nextParts) { + int index = next.refs.indexOf(lastPart); + if (index == -1) { + + continue; + } + next.refs.remove(lastPart); + next.refs.add(index, gpm); + } + for (GraphPart parent : part.refs) { + if (parent.start == -1) { + continue; + } + int index = parent.nextParts.indexOf(part); + if (index == -1) { + continue; + } + parent.nextParts.remove(part); + parent.nextParts.add(index, gpm); + } + } + for (int i = 0; i < part.nextParts.size(); i++) { + makeMulti(part.nextParts.get(i), visited); + } + } +} diff --git a/trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/GraphPart.java b/trunk/src/com/jpexs/asdec/graph/GraphPart.java similarity index 93% rename from trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/GraphPart.java rename to trunk/src/com/jpexs/asdec/graph/GraphPart.java index 87ffd547b..90853466b 100644 --- a/trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/GraphPart.java +++ b/trunk/src/com/jpexs/asdec/graph/GraphPart.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.jpexs.asdec.abc.avm2.flowgraph; +package com.jpexs.asdec.graph; import com.jpexs.asdec.abc.avm2.treemodel.ContinueTreeItem; import java.util.ArrayList; @@ -37,7 +37,7 @@ public class GraphPart { public String path=""; public List refs=new ArrayList(); public boolean ignored=false; - public List forContinues=new ArrayList(); + public List forContinues=new ArrayList(); private boolean leadsTo(GraphPart part,List visited,List ignored){ if(visited.contains(this)){ diff --git a/trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/GraphPartMulti.java b/trunk/src/com/jpexs/asdec/graph/GraphPartMulti.java similarity index 86% rename from trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/GraphPartMulti.java rename to trunk/src/com/jpexs/asdec/graph/GraphPartMulti.java index 220825f32..8293355fe 100644 --- a/trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/GraphPartMulti.java +++ b/trunk/src/com/jpexs/asdec/graph/GraphPartMulti.java @@ -1,4 +1,4 @@ -package com.jpexs.asdec.abc.avm2.flowgraph; +package com.jpexs.asdec.graph; import java.util.List; @@ -8,7 +8,7 @@ import java.util.List; */ public class GraphPartMulti extends GraphPart { - List parts; + public List parts; public GraphPartMulti(List parts) { super(parts.get(0).start, parts.get(parts.size() - 1).end); diff --git a/trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/Loop.java b/trunk/src/com/jpexs/asdec/graph/Loop.java similarity index 81% rename from trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/Loop.java rename to trunk/src/com/jpexs/asdec/graph/Loop.java index 1ef87f94c..18a4a2e56 100644 --- a/trunk/src/com/jpexs/asdec/abc/avm2/flowgraph/Loop.java +++ b/trunk/src/com/jpexs/asdec/graph/Loop.java @@ -1,4 +1,4 @@ -package com.jpexs.asdec.abc.avm2.flowgraph; +package com.jpexs.asdec.graph; /** *