diff --git a/lib/graphs.jar b/lib/graphs.jar index 868ace4e4..8d3a86ff0 100644 Binary files a/lib/graphs.jar and b/lib/graphs.jar differ diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java index 1ce070baa..2a5aa4585 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java @@ -18,6 +18,8 @@ package com.jpexs.decompiler.flash.action; import com.jpexs.decompiler.flash.BaseLocalData; import com.jpexs.decompiler.flash.FinalProcessLocalData; +import com.jpexs.decompiler.flash.SWF; +import static com.jpexs.decompiler.flash.action.Action.adr2ip; import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; import com.jpexs.decompiler.flash.action.model.EnumerateActionItem; import com.jpexs.decompiler.flash.action.model.FunctionActionItem; @@ -35,14 +37,17 @@ import com.jpexs.decompiler.flash.action.swf4.ActionJump; import com.jpexs.decompiler.flash.action.swf4.ActionNot; import com.jpexs.decompiler.flash.action.swf4.ActionPush; import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; +import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; import com.jpexs.decompiler.flash.ecma.Null; import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphPart; import com.jpexs.decompiler.graph.GraphSource; import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphSourceItemContainer; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.Loop; import com.jpexs.decompiler.graph.TranslateStack; @@ -52,8 +57,10 @@ import com.jpexs.decompiler.graph.model.DefaultItem; import com.jpexs.decompiler.graph.model.IfItem; import com.jpexs.decompiler.graph.model.SwitchItem; import com.jpexs.decompiler.graph.model.WhileItem; +import com.jpexs.helpers.Helper; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -71,6 +78,37 @@ public class ActionGraph extends Graph { this.insideDoInitAction = insideDoInitAction; } + @Override + public LinkedHashMap getSubGraphs() { + LinkedHashMap subgraphs = new LinkedHashMap<>(); + List alist = ((ActionGraphSource) code).getActions(); + int ip = 0; + for (Action action : alist) { + if ((action instanceof GraphSourceItemContainer) && ((action instanceof ActionDefineFunction) || (action instanceof ActionDefineFunction2))) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) action; + String functionName = (action instanceof ActionDefineFunction) ? ((ActionDefineFunction) action).functionName : ((ActionDefineFunction2) action).functionName; + long endAddr = action.getAddress() + cnt.getHeaderSize(); + List outs = new ArrayList<>(); + for (long size : cnt.getContainerSizes()) { + if (size == 0) { + outs.add(new ActionList()); + continue; + } + outs.add(new ActionList(alist.subList(adr2ip(alist, endAddr), adr2ip(alist, endAddr + size)))); + endAddr += size; + } + + for (ActionList al : outs) { + subgraphs.put("loc" + Helper.formatAddress(code.pos2adr(ip)) + ": function " + functionName, + new ActionGraph("", false, al, new HashMap<>(), new HashMap<>(), new HashMap<>(), SWF.DEFAULT_VERSION) + ); + } + } + ip++; + } + return subgraphs; + } + public boolean isInsideDoInitAction() { return insideDoInitAction; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/PcodeGraphVizExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/PcodeGraphVizExporter.java index 3a2ceb9f5..1d575dd8a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/PcodeGraphVizExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/PcodeGraphVizExporter.java @@ -16,15 +16,21 @@ */ package com.jpexs.decompiler.flash.exporters.script; +import com.jpexs.decompiler.flash.AppResources; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2Graph; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.action.Action; +import static com.jpexs.decompiler.flash.action.Action.adr2ip; import com.jpexs.decompiler.flash.action.ActionGraph; import com.jpexs.decompiler.flash.action.ActionGraphSource; import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionWith; +import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; +import com.jpexs.decompiler.flash.action.swf7.ActionTry; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.StringBuilderTextWriter; @@ -32,13 +38,20 @@ import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphPart; import com.jpexs.decompiler.graph.GraphSource; +import com.jpexs.decompiler.graph.GraphSourceItemContainer; +import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.model.CommentItem; +import com.jpexs.graphs.graphviz.dot.parser.DotId; import com.jpexs.helpers.Helper; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.logging.Level; /** * @@ -83,7 +96,7 @@ public class PcodeGraphVizExporter { export(gr, writer); } - public void export(Graph graph, GraphTextWriter writer) throws InterruptedException { + private void exportGraph(Graph graph, GraphTextWriter writer) throws InterruptedException { graph.init(null); GraphSource graphSource = graph.getGraphCode(); Set allBlocks = new HashSet<>(); @@ -92,7 +105,6 @@ public class PcodeGraphVizExporter { populateParts(h, allBlocks); } - writer.append("digraph pcode {\r\n"); Set knownAddresses = graphSource.getImportantAddresses(); int h = 0; for (GraphPart head : heads) { @@ -141,6 +153,20 @@ public class PcodeGraphVizExporter { writer.append(partBlockName + orientation + " -> " + nextBlockName + ":n;\r\n"); } } + } + + public void export(Graph graph, GraphTextWriter writer) throws InterruptedException { + writer.append("digraph pcode {\r\n"); + exportGraph(graph, writer); + int pos = 0; + Map subgraphs = graph.getSubGraphs(); + for (String name : subgraphs.keySet()) { + writer.append("subgraph cluster_" + pos + " {"); + writer.append("label=" + new DotId(name, false) + ";\r\n"); + pos++; + exportGraph(subgraphs.get(name), writer); + writer.append("}"); + } writer.append("}\r\n"); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index b3f49e3ab..e2f45dcb8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -20,6 +20,8 @@ import com.jpexs.decompiler.flash.BaseLocalData; import com.jpexs.decompiler.flash.FinalProcessLocalData; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.model.FunctionActionItem; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.model.AndItem; import com.jpexs.decompiler.graph.model.BreakItem; @@ -51,6 +53,7 @@ import com.jpexs.decompiler.graph.model.WhileItem; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -84,6 +87,10 @@ public class Graph { return code; } + public LinkedHashMap getSubGraphs() { + return new LinkedHashMap<>(); + } + /** * Identify loop exits * @@ -2348,7 +2355,18 @@ public class Graph { endAddr += size; } ip = code.adr2pos(endAddr); + + if ((ins instanceof ActionDefineFunction) || (ins instanceof ActionDefineFunction2)) { + part.end = lastIp; + allBlocks.add(part); + GraphPart gp = new GraphPart(ip, -1); + gp.path = path; + part.nextParts.add(gp); + gp.refs.add(part); + part = gp; + } } + continue; } else if (ins.isExit()) { part.end = ip;