Merge branch 'graphviz-detect' into dev

This commit is contained in:
Jindra Petřík
2018-05-26 18:38:29 +02:00
34 changed files with 999 additions and 261 deletions
@@ -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++) {
@@ -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();
@@ -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
}
@@ -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
}
@@ -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);
@@ -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");
}
}
@@ -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();
}