mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-26 17:31:05 +00:00
Merge branch 'graphviz-detect' into dev
This commit is contained in:
+10
@@ -303,6 +303,16 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
|
||||
public long pos2adr(int pos) {
|
||||
return code.pos2adr(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getImportantAddresses() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String insToString(int pos) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
});
|
||||
idx = branches.get(0);
|
||||
for (int n = 1; n < branches.size(); n++) {
|
||||
|
||||
+10
@@ -266,6 +266,16 @@ public class AVM2DeobfuscatorRegistersOld extends AVM2DeobfuscatorSimpleOld {
|
||||
public long pos2adr(int pos) {
|
||||
return code.pos2adr(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getImportantAddresses() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String insToString(int pos) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
});
|
||||
idx = branches.get(0);
|
||||
for (int n = 1; n < branches.size(); n++) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.abc.avm2.ConvertOutput;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphSource;
|
||||
@@ -34,6 +35,7 @@ import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -85,6 +87,19 @@ public class AVM2GraphSource extends GraphSource {
|
||||
code.calculateDebugFileLine(abc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getImportantAddresses() {
|
||||
return code.getImportantOffsets(body, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String insToString(int pos) {
|
||||
if (pos < code.code.size()) {
|
||||
return code.code.get(pos).toStringNoAddress(abc.constants, fullyQualifiedNames);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return code.code.size();
|
||||
|
||||
+3
-1
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.␍ */
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2.instructions;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
@@ -123,6 +124,7 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
|
||||
return bos.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBytesLength() {
|
||||
int cnt = 1;
|
||||
for (int i = 0; i < definition.operands.length; i++) {
|
||||
|
||||
@@ -347,6 +347,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
*
|
||||
* @return Length
|
||||
*/
|
||||
@Override
|
||||
public final int getBytesLength() {
|
||||
return getContentBytesLength() + (actionCode >= 0x80 ? 3 : 1);
|
||||
}
|
||||
|
||||
@@ -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<String, Graph> getSubGraphs() {
|
||||
LinkedHashMap<String, Graph> subgraphs = new LinkedHashMap<>();
|
||||
List<Action> 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<ActionList> 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;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphSource;
|
||||
@@ -27,6 +29,7 @@ import com.jpexs.helpers.Helper;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -36,7 +39,7 @@ import java.util.logging.Logger;
|
||||
*/
|
||||
public class ActionGraphSource extends GraphSource {
|
||||
|
||||
private final List<Action> actions;
|
||||
private final ActionList actions;
|
||||
|
||||
public int version;
|
||||
|
||||
@@ -55,7 +58,7 @@ public class ActionGraphSource extends GraphSource {
|
||||
}
|
||||
|
||||
public ActionGraphSource(String path, boolean insideDoInitAction, List<Action> actions, int version, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions) {
|
||||
this.actions = actions;
|
||||
this.actions = actions instanceof ActionList ? (ActionList) actions : new ActionList(actions);
|
||||
this.version = version;
|
||||
this.registerNames = registerNames;
|
||||
this.variables = variables;
|
||||
@@ -64,6 +67,19 @@ public class ActionGraphSource extends GraphSource {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getImportantAddresses() {
|
||||
return Action.getActionsAllRefs(actions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String insToString(int pos) {
|
||||
if (pos < actions.size()) {
|
||||
return actions.get(pos).getASMSource(actions, getImportantAddresses(), ScriptExportMode.PCODE);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return actions.size();
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.␍ */
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.configuration;
|
||||
|
||||
import com.jpexs.decompiler.flash.ApplicationInfo;
|
||||
@@ -631,6 +632,11 @@ public final class Configuration {
|
||||
@ConfigurationCategory("ui")
|
||||
public static final ConfigurationItem<Boolean> showSetAdvanceValuesMessage = null;
|
||||
|
||||
@ConfigurationDefaultString("")
|
||||
@ConfigurationCategory("paths")
|
||||
@ConfigurationFile
|
||||
public static final ConfigurationItem<String> graphVizDotLocation = null;
|
||||
|
||||
private enum OSId {
|
||||
WINDOWS, OSX, UNIX
|
||||
}
|
||||
|
||||
+4
-2
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.␍ */
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.exporters.modes;
|
||||
|
||||
/**
|
||||
@@ -23,7 +24,8 @@ public enum ScriptExportMode {
|
||||
AS,
|
||||
PCODE,
|
||||
PCODE_HEX,
|
||||
PCODE_GRAPHVIZ,
|
||||
HEX,
|
||||
CONSTANTS, // AS1/2 ConstantPool
|
||||
AS_METHOD_STUBS;
|
||||
AS_METHOD_STUBS
|
||||
}
|
||||
|
||||
+4
-1
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.␍ */
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.exporters.script;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
@@ -98,6 +99,8 @@ public class ExportScriptTask implements Callable<File> {
|
||||
asm.getActionSourcePrefix(writer2);
|
||||
asm.getActionBytesAsHex(writer2);
|
||||
asm.getActionSourceSuffix(writer2);
|
||||
} else if (exportMode == ScriptExportMode.PCODE_GRAPHVIZ) {
|
||||
new PcodeGraphVizExporter().exportAs12(asm, writer2);
|
||||
} else if (exportMode != ScriptExportMode.AS) {
|
||||
asm.getActionSourcePrefix(writer2);
|
||||
asm.getASMSource(exportMode, writer2, null);
|
||||
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2018 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
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;
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class PcodeGraphVizExporter {
|
||||
|
||||
private final String BLOCK_STYLE = "shape=\"box\"";
|
||||
|
||||
private static final int INS_LEN_LIMIT = 50;
|
||||
private static final String ELIPSIS = "...";
|
||||
|
||||
private String getBlockName(GraphSource list, GraphPart part) {
|
||||
return "loc" + Helper.formatAddress(list.pos2adr(part.start, true));
|
||||
}
|
||||
|
||||
private boolean isEndOfScript(GraphSource list, GraphPart part) {
|
||||
if (part.start >= list.size()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void populateParts(GraphPart part, Set<GraphPart> allParts) {
|
||||
if (allParts.contains(part)) {
|
||||
return;
|
||||
}
|
||||
allParts.add(part);
|
||||
for (GraphPart p : part.nextParts) {
|
||||
populateParts(p, allParts);
|
||||
}
|
||||
}
|
||||
|
||||
public void exportAs12(ASMSource src, GraphTextWriter writer) throws InterruptedException {
|
||||
ActionList alist = src.getActions();
|
||||
ActionGraph gr = new ActionGraph("", false, alist, new HashMap<>(), new HashMap<>(), new HashMap<>(), SWF.DEFAULT_VERSION);
|
||||
export(gr, writer);
|
||||
}
|
||||
|
||||
public void exportAs3(ABC abc, MethodBody body, GraphTextWriter writer) throws InterruptedException {
|
||||
AVM2Graph gr = new AVM2Graph(body.getCode(), abc, body, false, -1, -1, new HashMap<>(), new ScopeStack(), new HashMap<>(), new ArrayList<>(), new HashMap<>(), body.getCode().visitCode(body));
|
||||
export(gr, writer);
|
||||
}
|
||||
|
||||
private void exportGraph(Graph graph, GraphTextWriter writer) throws InterruptedException {
|
||||
graph.init(null);
|
||||
GraphSource graphSource = graph.getGraphCode();
|
||||
Set<GraphPart> allBlocks = new HashSet<>();
|
||||
List<GraphPart> heads = graph.heads;
|
||||
for (GraphPart h : heads) {
|
||||
populateParts(h, allBlocks);
|
||||
}
|
||||
|
||||
Set<Long> knownAddresses = graphSource.getImportantAddresses();
|
||||
int h = 0;
|
||||
for (GraphPart head : heads) {
|
||||
String headName = "start";
|
||||
if (heads.size() > 1) {
|
||||
h++;
|
||||
headName = "start" + h;
|
||||
}
|
||||
writer.append(headName + " [shape=\"circle\"]\r\n");
|
||||
writer.append(headName + ":s -> " + getBlockName(graphSource, head) + ":n;\r\n");
|
||||
}
|
||||
for (GraphPart part : allBlocks) {
|
||||
StringBuilder blkCodeBuilder = new StringBuilder();
|
||||
for (int j = part.start; j <= part.end; j++) {
|
||||
if (j < graphSource.size()) {
|
||||
if (knownAddresses.contains(graphSource.get(j).getAddress())) {
|
||||
blkCodeBuilder.append("loc").append(Helper.formatAddress(graphSource.get(j).getAddress())).append(":\r\n");
|
||||
}
|
||||
String insStr = graphSource.insToString(j);
|
||||
if (insStr.length() > INS_LEN_LIMIT) {
|
||||
insStr = insStr.substring(0, INS_LEN_LIMIT - ELIPSIS.length()) + ELIPSIS;
|
||||
}
|
||||
blkCodeBuilder.append(insStr).append("\r\n");
|
||||
}
|
||||
}
|
||||
String labelStr = blkCodeBuilder.toString();
|
||||
labelStr = labelStr.replace("\"", "\\\"");
|
||||
labelStr = labelStr.replace("\r\n", "\\l");
|
||||
String partBlockName = getBlockName(graphSource, part);
|
||||
String blkStyle = BLOCK_STYLE;
|
||||
if (isEndOfScript(graphSource, part)) {
|
||||
blkStyle = "shape=\"circle\"";
|
||||
labelStr = "FINISH";
|
||||
}
|
||||
writer.append(partBlockName + " [" + blkStyle + " label=\"" + labelStr + "\"];\r\n");
|
||||
for (int n = 0; n < part.nextParts.size(); n++) {
|
||||
GraphPart next = part.nextParts.get(n);
|
||||
String orientation = ":s";
|
||||
if (part.nextParts.size() == 2 && n == 0) {
|
||||
orientation = "";
|
||||
}
|
||||
if (part.nextParts.size() == 2 && n == 1) {
|
||||
orientation = "";
|
||||
}
|
||||
String nextBlockName = getBlockName(graphSource, next);
|
||||
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<String, Graph> 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");
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.␍ */
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.exporters.settings;
|
||||
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
@@ -42,6 +43,8 @@ public class ScriptExportSettings {
|
||||
case AS:
|
||||
case AS_METHOD_STUBS:
|
||||
return ".as";
|
||||
case PCODE_GRAPHVIZ:
|
||||
return ".gv";
|
||||
case PCODE:
|
||||
case PCODE_HEX:
|
||||
return ".pcode";
|
||||
|
||||
@@ -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;
|
||||
@@ -80,6 +83,14 @@ public class Graph {
|
||||
private boolean debugGetLoops = false;
|
||||
private boolean debugPrintGraph = false;
|
||||
|
||||
public GraphSource getGraphCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public LinkedHashMap<String, Graph> getSubGraphs() {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify loop exits
|
||||
*
|
||||
@@ -1141,6 +1152,7 @@ public class Graph {
|
||||
}
|
||||
|
||||
if (stopPart.contains(part)) {
|
||||
//System.err.println("/stopped part " + part);
|
||||
return;
|
||||
}
|
||||
for (Loop el : loops) {
|
||||
@@ -1163,9 +1175,11 @@ public class Graph {
|
||||
|
||||
if (visited.contains(part)) {
|
||||
part.level = 0;
|
||||
//System.err.println("set level " + part + " to zero");
|
||||
} else {
|
||||
visited.add(part);
|
||||
part.level = level;
|
||||
//System.err.println("set level " + part + " to " + level);
|
||||
}
|
||||
|
||||
boolean isLoop = false;
|
||||
@@ -1183,9 +1197,18 @@ public class Graph {
|
||||
if (nextParts == null) {
|
||||
nextParts = part.nextParts;
|
||||
}
|
||||
nextParts = new ArrayList<>(nextParts);
|
||||
|
||||
if (nextParts.size() == 2 && stopPart.contains(nextParts.get(1))) {
|
||||
nextParts.remove(1);
|
||||
}
|
||||
if (nextParts.size() >= 1 && stopPart.contains(nextParts.get(0))) {
|
||||
nextParts.remove(0);
|
||||
}
|
||||
|
||||
if (nextParts.size() == 2) {
|
||||
GraphPart next = getCommonPart(localData, nextParts, loops);//part.getNextPartPath(new ArrayList<GraphPart>());
|
||||
//System.err.println("- common part of " + nextParts.get(0) + " and " + nextParts.get(1) + " is " + next);
|
||||
List<GraphPart> stopParts2 = new ArrayList<>(); //stopPart);
|
||||
if (next != null) {
|
||||
stopParts2.add(next);
|
||||
@@ -1193,12 +1216,20 @@ public class Graph {
|
||||
stopParts2.add(stopPart.get(stopPart.size() - 1));
|
||||
}
|
||||
if (next != nextParts.get(0)) {
|
||||
// System.err.println("- going to branch 0 nextpart from " + part + " to " + nextParts.get(0));
|
||||
markLevels(path, localData, nextParts.get(0), allParts, loops, next == null ? stopPart : stopParts2, level + 1, visited, recursionLevel + 1);
|
||||
} else {
|
||||
//System.err.println("- branch 0 of " + part + " is skipped (=next)");
|
||||
}
|
||||
|
||||
if (next != nextParts.get(1)) {
|
||||
//System.err.println("- going to branch 1 nextpart from " + part + " to " + nextParts.get(1));
|
||||
markLevels(path, localData, nextParts.get(1), allParts, loops, next == null ? stopPart : stopParts2, level + 1, visited, recursionLevel + 1);
|
||||
} else {
|
||||
//System.err.println("- branch 1 of " + part + " is skipped (=next)");
|
||||
}
|
||||
if (next != null) {
|
||||
//System.err.println("- going to next from " + part + " to " + next);
|
||||
markLevels(path, localData, next, allParts, loops, stopPart, level, visited, recursionLevel + 1);
|
||||
}
|
||||
}
|
||||
@@ -1235,6 +1266,7 @@ public class Graph {
|
||||
}
|
||||
|
||||
if (nextParts.size() == 1) {
|
||||
//System.err.println("going to one nexpart from " + part + " to " + nextParts.get(0));
|
||||
markLevels(path, localData, nextParts.get(0), allParts, loops, stopPart, level, visited, recursionLevel + 1);
|
||||
}
|
||||
|
||||
@@ -1258,6 +1290,7 @@ public class Graph {
|
||||
if (isLoop) {
|
||||
if (currentLoop != null && currentLoop.loopBreak != null) {
|
||||
currentLoop.phase = 2;
|
||||
//System.err.println("- going to break of loop " + currentLoop.loopBreak);
|
||||
markLevels(path, localData, currentLoop.loopBreak, allParts, loops, stopPart, level, visited, recursionLevel + 1);
|
||||
}
|
||||
}
|
||||
@@ -2179,13 +2212,6 @@ public class Graph {
|
||||
|
||||
if (!bodyBranch.isEmpty()) {
|
||||
ret.add(index, loopItem);
|
||||
/*
|
||||
loopItem.commands.remove(loopItem.commands.size() - 1);
|
||||
exprList.addAll(loopItem.commands);
|
||||
commands.addAll(bodyBranch);
|
||||
exprList.add(expr);
|
||||
checkContinueAtTheEnd(commands, currentLoop);
|
||||
ret.add(index, li = new WhileItem(null, currentLoop, exprList, commands));*/
|
||||
} else {
|
||||
loopItem.commands.remove(loopItem.commands.size() - 1);
|
||||
commands.addAll(loopItem.commands);
|
||||
@@ -2267,7 +2293,7 @@ public class Graph {
|
||||
protected void checkGraph(List<GraphPart> allBlocks) {
|
||||
}
|
||||
|
||||
private List<GraphPart> makeGraph(GraphSource code, List<GraphPart> allBlocks, List<Integer> alternateEntries) throws InterruptedException {
|
||||
public List<GraphPart> makeGraph(GraphSource code, List<GraphPart> allBlocks, List<Integer> alternateEntries) throws InterruptedException {
|
||||
HashMap<Integer, List<Integer>> refs = code.visitCode(alternateEntries);
|
||||
List<GraphPart> ret = new ArrayList<>();
|
||||
boolean[] visited = new boolean[code.size()];
|
||||
@@ -2344,7 +2370,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;
|
||||
|
||||
@@ -18,10 +18,12 @@ package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -37,6 +39,10 @@ public abstract class GraphSource implements Serializable {
|
||||
|
||||
public abstract List<GraphTargetItem> translatePart(GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException;
|
||||
|
||||
public abstract Set<Long> getImportantAddresses();
|
||||
|
||||
public abstract String insToString(int pos);
|
||||
|
||||
private void visitCode(int ip, int lastIp, HashMap<Integer, List<Integer>> refs, int endIp) throws InterruptedException {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
@@ -109,4 +115,20 @@ public abstract class GraphSource implements Serializable {
|
||||
public abstract int adr2pos(long adr);
|
||||
|
||||
public abstract long pos2adr(int pos);
|
||||
|
||||
public long getAddressAfterCode() {
|
||||
if (isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
long lastAddr = pos2adr(size() - 1);
|
||||
return lastAddr + get(size() - 1).getBytesLength();
|
||||
}
|
||||
|
||||
public final long pos2adr(int pos, boolean allowPosAfterCode) {
|
||||
if (pos == size() && allowPosAfterCode) {
|
||||
return getAddressAfterCode();
|
||||
}
|
||||
return pos2adr(pos);
|
||||
}
|
||||
;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
*/
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
@@ -56,4 +57,6 @@ public interface GraphSourceItem extends Serializable, Cloneable {
|
||||
public int getLine();
|
||||
|
||||
public String getFile();
|
||||
|
||||
public abstract int getBytesLength();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user