diff --git a/trunk/src/com/jpexs/decompiler/flash/SWF.java b/trunk/src/com/jpexs/decompiler/flash/SWF.java index 7a4558a9e..8f4bf0c14 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWF.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWF.java @@ -1100,7 +1100,7 @@ public class SWF { } } for (ASMSource src : actionsMap.keySet()) { - actionsMap.put(src, Action.removeNops(actionsMap.get(src), version)); + actionsMap.put(src, Action.removeNops(0, actionsMap.get(src), version, 0)); src.setActions(actionsMap.get(src), version); } return ret; diff --git a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java index 44df6e619..0867b283a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -18,8 +18,6 @@ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionGraphSource; -import com.jpexs.decompiler.flash.action.parser.ASMParser; -import com.jpexs.decompiler.flash.action.parser.ParseException; import com.jpexs.decompiler.flash.action.special.ActionContainer; import com.jpexs.decompiler.flash.action.special.ActionEnd; import com.jpexs.decompiler.flash.action.special.ActionNop; @@ -51,7 +49,6 @@ import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord; import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -490,9 +487,13 @@ public class SWFInputStream extends InputStream { return ret; } - public List readActionList() throws IOException { + public List readActionList(long address, long containerSWFOffset) throws IOException { ReReadableInputStream rri = new ReReadableInputStream(this); - return readActionList(rri, version, 0); + return readActionList(address, containerSWFOffset, rri, version, 0, -1); + } + + public List readActionList(long address, long containerSWFOffset, ReReadableInputStream rri, int maxlen) throws IOException { + return readActionList(address, containerSWFOffset, rri, version, rri.getPos(), rri.getPos() + maxlen); } private static void getConstantPool(ConstantPool cpool, List localData, Stack stack, List output, ActionGraphSource code, int ip, int lastIp, List constantPools, List visited, int version) { @@ -559,7 +560,7 @@ public class SWFInputStream extends InputStream { ins.setIgnored(true); } if ((!aif.ignoreUsed) && aif.jumpUsed) { - ActionJump jmpIns = new ActionJump(aif.offset); + ActionJump jmpIns = new ActionJump(aif.getJumpOffset()); ((ActionJump) jmpIns).setAddress(aif.getAddress(), version); code.set(ip, (ActionJump) jmpIns); } @@ -572,11 +573,11 @@ public class SWFInputStream extends InputStream { ((ActionPush) ig.item).ignoredParts.add(ig.pos); if (((ActionPush) ig.item).ignoredParts.size() == ((ActionPush) ig.item).values.size()) { - ((Action) ig.item).ignored = true; + ((Action) ig.item).setIgnored(true); } } } else { - ((Action) ig.item).ignored = true; + ((Action) ig.item).setIgnored(true); } } } @@ -589,7 +590,7 @@ public class SWFInputStream extends InputStream { } } stack.pop(); - getConstantPool(cpool, localData, stack, output, code, condition ? (code.adr2pos(((ActionIf) ins).getAddress() + ((ActionIf) ins).getBytes(code.version).length + ((ActionIf) ins).offset)) : ip + 1, ip, constantPools, visited, version); + getConstantPool(cpool, localData, stack, output, code, condition ? (code.adr2pos(((ActionIf) ins).getAddress() + ((ActionIf) ins).getBytes(code.version).length + ((ActionIf) ins).getJumpOffset())) : ip + 1, ip, constantPools, visited, version); } else { if (ins instanceof ActionIf) { stack.pop(); @@ -634,7 +635,7 @@ public class SWFInputStream extends InputStream { * @return List of actions * @throws IOException */ - public static List readActionList(ReReadableInputStream rri, int version, int ip) throws IOException { + public static List readActionList(long address, long containerSWFOffset, ReReadableInputStream rri, int version, int ip, int endip) throws IOException { List retdups = new ArrayList(); ConstantPool cpool = new ConstantPool(); @@ -652,7 +653,7 @@ public class SWFInputStream extends InputStream { method = 2; goesPrev = readActionListAtPos(true, localData, stack, cpool, sis, rri, ip, retdups, ip); }*/ - goesPrev = readActionListAtPos(false, true, localData, stack, cpool, sis, rri, ip, retdups, ip); + goesPrev = readActionListAtPos(address, containerSWFOffset, false, true, localData, stack, cpool, sis, rri, ip, retdups, ip, endip); if (goesPrev) { } else { @@ -676,7 +677,7 @@ public class SWFInputStream extends InputStream { if (a instanceof ActionEnd) { if (i < retdups.size() - 1) { ActionJump jmp = new ActionJump(0); - jmp.offset = retdups.size() - i - jmp.getBytes(version).length; + jmp.setJumpOffset(retdups.size() - i - jmp.getBytes(version).length); a.replaceWith = jmp; } } @@ -699,16 +700,18 @@ public class SWFInputStream extends InputStream { String s = null; //Action.setConstantPool(ret, cpool); - try { - s = Highlighting.stripHilights(Action.actionsToString(ret, null, version, false)); - ret = ASMParser.parse(false, new ByteArrayInputStream(s.getBytes()), SWF.DEFAULT_VERSION); - } catch (ParseException ex) { - Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, "parsing error", ex); - } + /* try { + s = Highlighting.stripHilights(Action.actionsToString(address,ret, null, version, false,containerSWFOffset)); + //System.out.println("PARSE:"+s); + Helper.writeFile("t.txt", s.getBytes()); + ret = ASMParser.parse(address,containerSWFOffset,false, new ByteArrayInputStream(s.getBytes()), SWF.DEFAULT_VERSION); + } catch (ParseException ex) { + Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, "parsing error", ex); + }*/ return ret; } - private static boolean readActionListAtPos(boolean notCompileTime, boolean enableVariables, List localData, Stack stack, ConstantPool cpool, SWFInputStream sis, ReReadableInputStream rri, int ip, List ret, int startIp) throws IOException { + private static boolean readActionListAtPos(long address, long containerSWFOffset, boolean notCompileTime, boolean enableVariables, List localData, Stack stack, ConstantPool cpool, SWFInputStream sis, ReReadableInputStream rri, int ip, List ret, int startIp, int endip) throws IOException { boolean debugMode = false; boolean decideBranch = false; boolean retv = false; @@ -718,12 +721,21 @@ public class SWFInputStream extends InputStream { long filePos = rri.getPos(); Scanner sc = new Scanner(System.in); int prevIp = ip; - while ((a = sis.readAction()) != null) { + while (((endip == -1) || (endip > ip)) && (a = sis.readAction(rri)) != null) { if ((ip < ret.size()) && (!(ret.get(ip) instanceof ActionNop))) { a = ret.get(ip); } - a.setAddress(prevIp, SWF.DEFAULT_VERSION); + a.containerSWFOffset = containerSWFOffset; + a.setAddress(prevIp, SWF.DEFAULT_VERSION, false); int info = a.actionLength + 1 + ((a.actionCode > 0x80) ? 2 : 0); + byte b[] = a.getBytes(sis.version); + int infoCorrect = info; + if (a instanceof ActionContainer) { + infoCorrect += ((ActionContainer) a).getDataLength(); + } + if (b.length != infoCorrect) { + //throw new RuntimeException("Wrong length "+a.toString()+" info:"+infoCorrect+" actual:"+b.length+" datalen:"+(infoCorrect-info)); + } int actual = 0; if (a instanceof ActionContainer) { actual = ((ActionContainer) a).getHeaderBytes().length; @@ -742,10 +754,24 @@ public class SWFInputStream extends InputStream { retv = true; } if (debugMode) { - //if(a instanceof ActionIf){ - System.out.println("readActionListAtPos ip: " + (ip - startIp) + " action(len " + a.actionLength + "): " + a + (a.isIgnored() ? " (ignored)" : "") + " stack:" + Highlighting.stripHilights(stack.toString()) + " " + Helper.byteArrToString(a.getBytes(SWF.DEFAULT_VERSION))); + //if(a instanceof ActionIf){ + String atos = a.getASMSource(new ArrayList(), cpool.constants, sis.version, false); + if (a instanceof ActionContainer) { + atos = a.toString(); + } + System.err.println("readActionListAtPos ip: " + (ip - startIp) + " (0x" + Helper.formatAddress(ip - startIp) + ") " + " action(len " + a.actionLength + "): " + atos + (a.isIgnored() ? " (ignored)" : "") + " stack:" + Helper.stackToString(stack, Helper.toList(cpool)) + " " + Helper.byteArrToString(a.getBytes(SWF.DEFAULT_VERSION))); //} + String add = ""; + if (a instanceof ActionIf) { + add = " change: " + ((ActionIf) a).getJumpOffset(); + } + if (a instanceof ActionJump) { + add = " change: " + ((ActionJump) a).getJumpOffset(); + } + System.err.println(add); } + + /*if(a instanceof ActionConstantPool){ throw new IllegalArgumentException("CP found"); } */ @@ -792,14 +818,14 @@ public class SWFInputStream extends InputStream { GraphTargetItem top = null; top = stack.pop(); - int nip = rri.getPos() + aif.offset; + int nip = rri.getPos() + aif.getJumpOffset(); if (decideBranch) { System.out.print("newip " + nip + ", "); System.out.print("Action: jump(j),ignore(i),compute(c)?"); String next = sc.next(); if (next.equals("j")) { - newip = rri.getPos() + aif.offset; + newip = rri.getPos() + aif.getJumpOffset(); rri.setPos(newip); } else if (next.equals("i")) { @@ -816,10 +842,10 @@ public class SWFInputStream extends InputStream { System.out.print("is compiletime -> "); } if (top.toBoolean()) { - newip = rri.getPos() + aif.offset; + newip = rri.getPos() + aif.getJumpOffset(); //rri.setPos(newip); if (((!enableVariables) || (!top.isVariableComputed())) && (!aif.ignoreUsed)) { - a = new ActionJump(aif.offset); + a = new ActionJump(aif.getJumpOffset()); a.setAddress(aif.getAddress(), SWF.DEFAULT_VERSION); } aif.jumpUsed = true; @@ -854,11 +880,11 @@ public class SWFInputStream extends InputStream { ((ActionPush) ig.item).ignoredParts.add(ig.pos); if (((ActionPush) ig.item).ignoredParts.size() == ((ActionPush) ig.item).values.size()) { - ((Action) ig.item).ignored = true; + ((Action) ig.item).setIgnored(true); } } } else { - ((Action) ig.item).ignored = true; + ((Action) ig.item).setIgnored(true); } } } @@ -871,7 +897,7 @@ public class SWFInputStream extends InputStream { goaif = true; } } else if (a instanceof ActionJump) { - newip = rri.getPos() + ((ActionJump) a).offset; + newip = rri.getPos() + ((ActionJump) a).getJumpOffset(); //if(newip>=0){ //rri.setPos(newip); //} @@ -932,7 +958,7 @@ public class SWFInputStream extends InputStream { aif.jumpUsed = true; int oldPos = rri.getPos(); Stack substack = (Stack) stack.clone(); - if (readActionListAtPos(true, enableVariables, localData, substack, cpool, sis, rri, rri.getPos() + aif.offset, ret, startIp)) { + if (readActionListAtPos(address, containerSWFOffset, true, enableVariables, localData, substack, cpool, sis, rri, rri.getPos() + aif.getJumpOffset(), ret, startIp, endip)) { retv = true; } rri.setPos(oldPos); @@ -1281,13 +1307,17 @@ public class SWFInputStream extends InputStream { return ret; } + public Action readAction() throws IOException { + return readAction(new ReReadableInputStream(this)); + } + /** * Reads one Action from the stream * * @return Action or null when ActionEndFlag or end of the stream * @throws IOException */ - public Action readAction() throws IOException { + public Action readAction(ReReadableInputStream rri) throws IOException { { int actionCode = readUI8(); if (actionCode == 0) { @@ -1415,7 +1445,7 @@ public class SWFInputStream extends InputStream { case 0x88: return new ActionConstantPool(actionLength, this, version); case 0x9B: - return new ActionDefineFunction(actionLength, this, version); + return new ActionDefineFunction(actionLength, this, rri, version); case 0x3C: return new ActionDefineLocal(); case 0x41: @@ -1443,7 +1473,7 @@ public class SWFInputStream extends InputStream { case 0x45: return new ActionTargetPath(); case 0x94: - return new ActionWith(this, version); + return new ActionWith(this, rri, version); case 0x4A: return new ActionToNumber(); case 0x4B: @@ -1493,7 +1523,7 @@ public class SWFInputStream extends InputStream { return new ActionStringGreater(); //SWF7 Actions case 0x8E: - return new ActionDefineFunction2(actionLength, this, version); + return new ActionDefineFunction2(actionLength, this, rri, version); case 0x69: return new ActionExtends(); case 0x2B: @@ -1501,7 +1531,7 @@ public class SWFInputStream extends InputStream { case 0x2C: return new ActionImplementsOp(); case 0x8F: - return new ActionTry(actionLength, this, version); + return new ActionTry(actionLength, this, rri, version); case 0x2A: return new ActionThrow(); default: @@ -1643,17 +1673,10 @@ public class SWFInputStream extends InputStream { * @throws IOException */ public CLIPACTIONRECORD readCLIPACTIONRECORD() throws IOException { - CLIPACTIONRECORD ret = new CLIPACTIONRECORD(); - ret.eventFlags = readCLIPEVENTFLAGS(); + CLIPACTIONRECORD ret = new CLIPACTIONRECORD(this, version, getPos()); if (ret.eventFlags.isClear()) { return null; } - long actionRecordSize = readUI32(); - if (ret.eventFlags.clipEventKeyPress) { - ret.keyCode = readUI8(); - actionRecordSize--; - } - ret.actionBytes = readBytes(actionRecordSize); //ret.actions = (new SWFInputStream(new ByteArrayInputStream(readBytes(actionRecordSize)), version)).readActionList(); return ret; } @@ -2030,24 +2053,7 @@ public class SWFInputStream extends InputStream { * @throws IOException */ public BUTTONCONDACTION readBUTTONCONDACTION() throws IOException { - BUTTONCONDACTION ret = new BUTTONCONDACTION(); - int condActionSize = readUI16(); - ret.isLast = condActionSize <= 0; - ret.condIdleToOverDown = readUB(1) == 1; - ret.condOutDownToIdle = readUB(1) == 1; - ret.condOutDownToOverDown = readUB(1) == 1; - ret.condOverDownToOutDown = readUB(1) == 1; - ret.condOverDownToOverUp = readUB(1) == 1; - ret.condOverUpToOverDown = readUB(1) == 1; - ret.condOverUpToIddle = readUB(1) == 1; - ret.condIdleToOverUp = readUB(1) == 1; - ret.condKeyPress = (int) readUB(7); - ret.condOverDownToIddle = readUB(1) == 1; - if (condActionSize <= 0) { - ret.actionBytes = readBytes(available()); - } else { - ret.actionBytes = readBytes(condActionSize - 4); - } + BUTTONCONDACTION ret = new BUTTONCONDACTION(this, version, getPos()); //ret.actions = readActionList(); return ret; } diff --git a/trunk/src/com/jpexs/decompiler/flash/SWFOutputStream.java b/trunk/src/com/jpexs/decompiler/flash/SWFOutputStream.java index 47d6d836f..6da44b4a3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWFOutputStream.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWFOutputStream.java @@ -986,8 +986,6 @@ public class SWFOutputStream extends OutputStream { * @throws IOException */ public void writeBUTTONCONDACTION(BUTTONCONDACTION value, boolean isLast) throws IOException { - BUTTONCONDACTION ret = new BUTTONCONDACTION(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); SWFOutputStream sos = new SWFOutputStream(baos, version); sos.writeUB(1, value.condIdleToOverDown ? 1 : 0); diff --git a/trunk/src/com/jpexs/decompiler/flash/action/Action.java b/trunk/src/com/jpexs/decompiler/flash/action/Action.java index 42c7390ff..c96ed42d5 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/Action.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/Action.java @@ -54,7 +54,7 @@ public class Action implements GraphSourceItem { public Action beforeInsert; public Action afterInsert; public Action replaceWith; - public boolean ignored = false; + private boolean ignored = false; /** * Action type identifier */ @@ -63,7 +63,12 @@ public class Action implements GraphSourceItem { * Length of action data */ public int actionLength; + public long containerSWFOffset; private long address; + + public long getFileAddress() { + return containerSWFOffset + getAddress(); + } /** * Names of ActionScript properties */ @@ -161,17 +166,17 @@ public class Action implements GraphSourceItem { List ret = new ArrayList(); for (Action a : list) { if (a.replaceWith != null) { - a.replaceWith.setAddress(a.getAddress(), version); + a.replaceWith.setAddress(a.getAddress(), version, false); ret.addAll(a.replaceWith.getAllRefs(version)); } if (a.beforeInsert != null) { - a.beforeInsert.setAddress(a.getAddress(), version); + a.beforeInsert.setAddress(a.getAddress(), version, false); ret.addAll(a.beforeInsert.getAllRefs(version)); } List part = a.getAllRefs(version); ret.addAll(part); if (a.afterInsert != null) { - a.afterInsert.setAddress(a.getAddress(), version); + a.afterInsert.setAddress(a.getAddress(), version, false); ret.addAll(a.afterInsert.getAllRefs(version)); } } @@ -184,7 +189,11 @@ public class Action implements GraphSourceItem { * @param address Address * @param version SWF version */ - public void setAddress(long address, int version) { + public final void setAddress(long address, int version) { + setAddress(address, version, true); + } + + public void setAddress(long address, int version, boolean recursive) { this.address = address; } @@ -354,8 +363,8 @@ public class Action implements GraphSourceItem { * @param hex Add hexadecimal? * @return ASM source as String */ - public static String actionsToString(List list, List importantOffsets, int version, boolean hex) { - return actionsToString(list, importantOffsets, new ArrayList(), version, hex); + public static String actionsToString(long address, List list, List importantOffsets, int version, boolean hex, long swfPos) { + return actionsToString(address, list, importantOffsets, new ArrayList(), version, hex, swfPos); } /** @@ -368,7 +377,7 @@ public class Action implements GraphSourceItem { * @param hex Add hexadecimal? * @return ASM source as String */ - public static String actionsToString(List list, List importantOffsets, List constantPool, int version, boolean hex) { + public static String actionsToString(long address, List list, List importantOffsets, List constantPool, int version, boolean hex, long swfPos) { String ret = ""; long offset; if (importantOffsets == null) { @@ -376,10 +385,12 @@ public class Action implements GraphSourceItem { importantOffsets = getActionsAllRefs(list, version); } - offset = 0; + offset = address; + int pos = -1; for (Action a : list) { + pos++; if (hex) { - ret += "" + Helper.bytesToHexString((a instanceof ActionContainer) ? ((ActionContainer) a).getHeaderBytes() : a.getBytes(version)) + "\r\n"; + ret += "" +/*"0x"+Helper.formatAddress(a.getFileAddress())+": "+*/ Helper.bytesToHexString((a instanceof ActionContainer) ? ((ActionContainer) a).getHeaderBytes() : a.getBytes(version)) + "\r\n"; } offset = a.getAddress(); if (importantOffsets.contains(offset)) { @@ -389,7 +400,12 @@ public class Action implements GraphSourceItem { if (a.replaceWith != null) { ret += Highlighting.hilighOffset("", offset) + a.replaceWith.getASMSource(importantOffsets, constantPool, version, hex) + "\r\n"; } else if (a.ignored) { - int len = a.getBytes(version).length; + int len = 0; + if (pos + 1 < list.size()) { + len = (int) (list.get(pos + 1).getAddress() - a.getAddress()); + } else { + len = a.getBytes(version).length; + } for (int i = 0; i < len; i++) { ret += "Nop\r\n"; } @@ -398,9 +414,16 @@ public class Action implements GraphSourceItem { ret += a.beforeInsert.getASMSource(importantOffsets, constantPool, version, hex) + "\r\n"; } //if (!(a instanceof ActionNop)) { - ret += Highlighting.hilighOffset("", offset) + a.getASMSourceReplaced(importantOffsets, constantPool, version, hex) + (a.ignored ? "; ignored" : "") + "\r\n"; - - //} + /*String add=""; + if(a instanceof ActionIf){ + add = " change: "+((ActionIf)a).getJumpOffset(); + } + if(a instanceof ActionJump){ + add = " change: "+((ActionJump)a).getJumpOffset(); + }*/ + ret += Highlighting.hilighOffset("", offset) + a.getASMSourceReplaced(importantOffsets, constantPool, version, hex) + (a.ignored ? "; ignored" : "")+/*"; ofs"+Helper.formatAddress(offset)+add +*/ "\r\n"; + + //} if (a.afterInsert != null) { ret += a.afterInsert.getASMSource(importantOffsets, constantPool, version, hex) + "\r\n"; } @@ -649,6 +672,10 @@ public class Action implements GraphSourceItem { break; } Action action = actions.get(ip); + if (action.isIgnored()) { + ip++; + continue; + } //System.out.println(" ip "+ip+" "+action); //return in for..in if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) instanceof Null)) { @@ -657,7 +684,7 @@ public class Action implements GraphSourceItem { if (actions.get(ip + 2) instanceof ActionNot) { if (actions.get(ip + 3) instanceof ActionIf) { ActionIf aif = (ActionIf) actions.get(ip + 3); - if (adr2ip(actions, ip2adr(actions, ip + 4, version) + aif.offset, version) == ip) { + if (adr2ip(actions, ip2adr(actions, ip + 4, version) + aif.getJumpOffset(), version) == ip) { ip += 4; continue; } @@ -897,6 +924,21 @@ public class Action implements GraphSourceItem { break; } pos++; + } else if (((StoreRegisterTreeItem) parts.get(pos)).value instanceof NewObjectTreeItem) { + if (parts.get(pos + 1) instanceof SetMemberTreeItem) { + if (((SetMemberTreeItem) parts.get(pos + 1)).value == ((StoreRegisterTreeItem) parts.get(pos)).value) { + instanceReg = ((StoreRegisterTreeItem) parts.get(pos)).register.number; + NewObjectTreeItem nm = (NewObjectTreeItem) ((StoreRegisterTreeItem) parts.get(pos)).value; + extendsOp = new GetVariableTreeItem(null, nm.objectName); + } else { + ok = false; + break; + } + } else { + ok = false; + break; + } + pos++; } else { ok = false; break; @@ -1037,12 +1079,12 @@ public class Action implements GraphSourceItem { return false; } - public static List removeNops(List actions, int version) { + public static List removeNops(long address, List actions, int version, long swfPos) { List ret = actions; String s = null; try { - s = Highlighting.stripHilights(Action.actionsToString(ret, null, version, false)); - ret = ASMParser.parse(true, new ByteArrayInputStream(s.getBytes()), SWF.DEFAULT_VERSION); + s = Highlighting.stripHilights(Action.actionsToString(address, ret, null, version, false, swfPos)); + ret = ASMParser.parse(address, swfPos, true, new ByteArrayInputStream(s.getBytes()), SWF.DEFAULT_VERSION); } catch (Exception ex) { Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, "parsing error", ex); } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/ActionGraph.java b/trunk/src/com/jpexs/decompiler/flash/action/ActionGraph.java index 01ae0b418..b368feb52 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/ActionGraph.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/ActionGraph.java @@ -311,641 +311,6 @@ public class ActionGraph extends Graph { } return ret; } - /* - private TreeItem translatePartGetStack(GraphPart part, Stack stack, HashMap registerNames) { - stack = (Stack) stack.clone(); - translatePart(part, stack, registerNames); - return stack.pop(); - } - - private List translatePart(GraphPart part, Stack stack, HashMap registerNames) { - List sub = part.getSubParts(); - List ret = new ArrayList(); - int end = 0; - for (GraphPart p : sub) { - if (p.end == -1) { - p.end = code.size() - 1; - } - if (p.start == code.size()) { - continue; - } else if (p.end == code.size()) { - p.end--; - } - end = p.end; - int start = p.start; - if (code.get(end) instanceof ActionJump) { - end--; - } else if (code.get(end) instanceof ActionIf) { - end--; - } - ret.addAll(Action.actionsPartToTree(registerNames, stack, code, start, end, version)); - } - return ret; - } - - private TreeItem checkLoop(GraphPart part, GraphPart stopPart, List loops) { - if (part == stopPart) { - return null; - } - for (Loop l : loops) { - if (l.loopContinue == part) { - return (new ContinueTreeItem(null, l.loopBreak == null ? -1 : l.loopBreak.start)); - } - if (l.loopBreak == part) { - return (new BreakTreeItem(null, part.start)); - } - } - return null; - } - private boolean doDecompile = true; - - private List printGraph(HashMap registerNames, Stack stack, List allParts, GraphPart parent, GraphPart part, GraphPart stopPart, List loops, HashMap> forFinalCommands) { - List ret = new ArrayList(); - boolean debugMode = false; - if (part.start >= code.size()) { - return ret; - } - - if (!doDecompile) { - // ret.add(new CommentTreeItem(null, "not decompiled")); - return ret; - } - - if (debugMode) { - System.err.println("PART " + part); - } - - if (part == stopPart) { - return ret; - } - if (part.ignored) { - return ret; - } - List fqn = new ArrayList(); - HashMap lrn = new HashMap(); - List output = new ArrayList(); - boolean isSwitch = false; - List parts = new ArrayList(); - if (part instanceof GraphPartMulti) { - parts = ((GraphPartMulti) part).parts; - } else { - parts.add(part); - } - boolean isIf = false; - int end = part.end; - if (end == -1) { - end = code.size() - 1; - } - if (end == code.size()) { - end--; - } - output.addAll(translatePart(part, stack, registerNames)); - if (end > -1) { - if (code.get(end) instanceof ActionJump) { - end--; - } else if (code.get(end) instanceof ActionIf) { - end--; - isIf = true; - } - } - if (isIf) { - Action ins = code.get(end + 1); - if ((stack.size() >= 2) && (stack.get(stack.size() - 1) instanceof NotTreeItem) && (((NotTreeItem) stack.get(stack.size() - 1)).value == stack.get(stack.size() - 2))) { - ret.addAll(output); - printGraph(registerNames, stack, allParts, parent, part.nextParts.get(1), part.nextParts.get(0), loops, forFinalCommands); - TreeItem second = stack.pop(); - TreeItem first = stack.pop(); - stack.push(new AndTreeItem(ins, first, second)); - ret.addAll(printGraph(registerNames, stack, allParts, parent, part.nextParts.get(0), stopPart, loops, forFinalCommands)); - return ret; - } else if ((stack.size() >= 2) && (stack.get(stack.size() - 1) == stack.get(stack.size() - 2))) { - ret.addAll(output); - printGraph(registerNames, stack, allParts, parent, part.nextParts.get(1), part.nextParts.get(0), loops, forFinalCommands); - TreeItem second = stack.pop(); - TreeItem first = stack.pop(); - stack.push(new OrTreeItem(ins, first, second)); - ret.addAll(printGraph(registerNames, stack, allParts, parent, part.nextParts.get(0), stopPart, loops, forFinalCommands)); - return ret; - } else if (stack.peek() instanceof StrictEqTreeItem) { - - TreeItem switchedObject = null; - if (!output.isEmpty()) { - if (output.get(output.size() - 1) instanceof StoreRegisterTreeItem) { - switchedObject = ((StoreRegisterTreeItem) output.get(output.size() - 1)).value; - } - } - if (switchedObject == null) { - switchedObject = new DirectValueTreeItem(null, -1, new Null(), null); - } - HashMap caseValuesMap = new HashMap(); - - int pos = 0; - StrictEqTreeItem set = (StrictEqTreeItem) stack.pop(); - caseValuesMap.put(pos, set.rightSide); - - //GraphPart switchLoc = part.nextParts.get(1).nextParts.get(0); - List caseBodyParts = new ArrayList(); - caseBodyParts.add(part.nextParts.get(0)); - TreeItem top = null; - int cnt = 1; - while (part.nextParts.size() > 1 - && part.nextParts.get(1).getHeight() > 1 - && code.get(part.nextParts.get(1).end) instanceof ActionIf - && ((top = translatePartGetStack(part.nextParts.get(1), stack, registerNames)) instanceof StrictEqTreeItem)) { - cnt++; - part = part.nextParts.get(1); - pos++; - caseBodyParts.add(part.nextParts.get(0)); - - set = (StrictEqTreeItem) top; - caseValuesMap.put(pos, set.rightSide); - } - if (cnt == 1) { - stack.push(set); - } else { - part = part.nextParts.get(1); - - GraphPart defaultPart = part; - //caseBodyParts.add(defaultPart); - - - - List defaultAndLastPart = new ArrayList(); - defaultAndLastPart.add(defaultPart); - defaultAndLastPart.add(caseBodyParts.get(caseBodyParts.size() - 1)); - - GraphPart defaultPart2 = getCommonPart(defaultAndLastPart); - - List defaultCommands = new ArrayList(); - - defaultCommands = printGraph(registerNames, stack, allParts, null, defaultPart, defaultPart2, loops, forFinalCommands); - - - List loopContinues = new ArrayList(); - for (Loop l : loops) { - if (l.loopContinue != null) { - loopContinues.add(l.loopContinue); - } - } - - List breakParts = new ArrayList(); - for (int g = 0; g < caseBodyParts.size(); g++) { - if (g < caseBodyParts.size() - 1) { - if (caseBodyParts.get(g).leadsTo(caseBodyParts.get(g + 1), loopContinues)) { - continue; - } - } - GraphPart nsp = caseBodyParts.get(g).getNextSuperPartPath(loopContinues); - if (nsp != null) { - breakParts.add(nsp); - } - } - Collections.sort(breakParts, new Comparator() { - @Override - public int compare(GraphPart o1, GraphPart o2) { - return o2.path.length() - o1.path.length(); - } - }); - - GraphPart breakPart = breakParts.isEmpty() ? null : breakParts.get(0); - if ((defaultPart2 != breakPart) && (defaultCommands.isEmpty())) { - defaultPart = defaultPart2; - } - - - List caseValues = new ArrayList(); - for (int i = 0; i < caseBodyParts.size(); i++) { - if (caseValuesMap.containsKey(i)) { - caseValues.add(caseValuesMap.get(i)); - } else { - continue; - } - } - - List> caseCommands = new ArrayList>(); - GraphPart next = null; - - - - next = breakPart; - - TreeItem ti = checkLoop(next, stopPart, loops); - loops.add(new Loop(null, next)); - //switchLoc.getNextPartPath(new ArrayList()); - List valuesMapping = new ArrayList(); - List caseBodies = new ArrayList(); - for (int i = 0; i < caseValues.size(); i++) { - GraphPart cur = caseBodyParts.get(i); - if (!caseBodies.contains(cur)) { - caseBodies.add(cur); - } - valuesMapping.add(caseBodies.indexOf(cur)); - } - - - - - if (defaultPart == breakPart) { - defaultPart = null; - } - if ((defaultPart != null) && (defaultCommands.isEmpty())) { - defaultCommands = printGraph(registerNames, stack, allParts, null, defaultPart, next, loops, forFinalCommands); - } - - List ignored = new ArrayList(); - for (Loop l : loops) { - ignored.add(l.loopContinue); - } - - for (int i = 0; i < caseBodies.size(); i++) { - List cc = new ArrayList(); - GraphPart nextCase = null; - nextCase = next; - if (next != null) { - if (i < caseBodies.size() - 1) { - if (!caseBodies.get(i).leadsTo(caseBodies.get(i + 1), ignored)) { - cc.add(new BreakTreeItem(null, next.start)); - } else { - nextCase = caseBodies.get(i + 1); - } - } else if (!defaultCommands.isEmpty()) { - if (!caseBodies.get(i).leadsTo(defaultPart, ignored)) { - cc.add(new BreakTreeItem(null, next.start)); - } else { - nextCase = defaultPart; - } - } - } - cc.addAll(0, printGraph(registerNames, stack, allParts, null, caseBodies.get(i), nextCase, loops, forFinalCommands)); - if (cc.size() >= 2) { - if (cc.get(cc.size() - 1) instanceof BreakTreeItem) { - if ((cc.get(cc.size() - 2) instanceof ContinueTreeItem) || (cc.get(cc.size() - 2) instanceof BreakTreeItem)) { - cc.remove(cc.size() - 1); - } - } - } - caseCommands.add(cc); - } - - SwitchTreeItem sti = new SwitchTreeItem(null, next == null ? -1 : next.start, switchedObject, caseValues, caseCommands, defaultCommands, valuesMapping); - ret.add(sti); - - if (next != null) { - if (ti != null) { - ret.add(ti); - } else { - ret.addAll(printGraph(registerNames, stack, allParts, null, next, stopPart, loops, forFinalCommands)); - } - } - return ret; - } - } else { - //ins.translate - } - //((IfTypeIns)ins.definition).translateInverted(new HashMap(), co.stack, ins); - } - - int ip = part.start; - List loopContinues = new ArrayList(); - for (Loop l : loops) { - if (l.loopContinue != null) { - loopContinues.add(l.loopContinue); - } - } - boolean loop = false; - boolean reversed = false; - if ((!part.nextParts.isEmpty()) && part.nextParts.get(0).leadsTo(part, loopContinues)) { - loop = true; - } else if ((part.nextParts.size() > 1) && part.nextParts.get(1).leadsTo(part, loopContinues)) { - loop = true; - reversed = true; - } - if (((part.nextParts.size() == 2) || ((part.nextParts.size() == 1) && loop)) && (!isSwitch)) { - - boolean doWhile = loop; - if (loop && output.isEmpty()) { - doWhile = false; - } - Loop currentLoop = new Loop(part, null); - if (loop) { - loops.add(currentLoop); - } - - - - loopContinues = new ArrayList(); - for (Loop l : loops) { - if (l.loopContinue != null) { - loopContinues.add(l.loopContinue); - } - } - - if (part.nextParts.size() > 1) { - currentLoop.loopBreak = part.nextParts.get(reversed ? 0 : 1); - } - - forFinalCommands.put(currentLoop, new ArrayList()); - - int breakIp = -1; - if (currentLoop.loopBreak != null) { - breakIp = currentLoop.loopBreak.start; - } - TreeItem expr = null; - if ((code.get(part.end) instanceof ActionJump) || (!(code.get(part.end) instanceof ActionIf))) { - expr = new DirectValueTreeItem(null, -1, (Boolean) true, new ArrayList()); - } else { - if (stack.isEmpty()) { - } - expr = stack.pop(); - } - if (doWhile) { - ret.add(new DoWhileTreeItem(null, breakIp, part.start, output, expr)); - } else { - ret.addAll(output); - } - - GraphPart next = part.getNextPartPath(loopContinues); - - if (loop && (!doWhile)) { - - if (reversed && (expr instanceof LogicalOp)) { - expr = ((LogicalOp) expr).invert(); - } - List loopBody = null; - List finalCommands = null; - GraphPart finalPart = null; - loopBody = printGraph(registerNames, stack, allParts, part, part.nextParts.get(reversed ? 1 : 0), stopPart, loops, forFinalCommands); - - finalCommands = forFinalCommands.get(currentLoop); - if (!finalCommands.isEmpty()) { - ret.add(new ForTreeItem(null, breakIp, currentLoop.loopContinue.start, new ArrayList(), expr, finalCommands, loopBody)); - } else { - ret.add(new WhileTreeItem(null, breakIp, part.start, expr, loopBody)); - } - } else if (!loop) { - if (expr instanceof LogicalOp) { - expr = ((LogicalOp) expr).invert(); - } else { - expr = new NotTreeItem(null, expr); - } - - int stackSizeBefore = stack.size(); - Stack trueStack = (Stack) stack.clone(); - Stack falseStack = (Stack) stack.clone(); - TreeItem lopTrue = checkLoop(part.nextParts.get(1), stopPart, loops); - TreeItem lopFalse = null; - if (next != part.nextParts.get(0)) { - lopFalse = checkLoop(part.nextParts.get(0), stopPart, loops); - } - List onTrue = new ArrayList(); - if (lopTrue != null) { - onTrue.add(lopTrue); - } else { - if (debugMode) { - System.err.println("ONTRUE: (inside " + part + ")"); - } - onTrue = printGraph(registerNames, trueStack, allParts, part, part.nextParts.get(1), next == null ? stopPart : next, loops, forFinalCommands); - if (debugMode) { - System.err.println("/ONTRUE (inside " + part + ")"); - } - } - List onFalse = new ArrayList(); - if (lopFalse != null) { - onFalse.add(lopFalse); - } else { - if (debugMode) { - System.err.println("ONFALSE: (inside " + part + ")"); - } - onFalse = (((next == part.nextParts.get(0)) || (part.nextParts.get(0).path.equals(part.path) || part.nextParts.get(0).path.length() < part.path.length())) ? new ArrayList() : printGraph(registerNames, falseStack, allParts, part, part.nextParts.get(0), next == null ? stopPart : next, loops, forFinalCommands)); - if (debugMode) { - System.err.println("/ONFALSE (inside " + part + ")"); - } - } - - if (onTrue.isEmpty() && onFalse.isEmpty() && (trueStack.size() > stackSizeBefore) && (falseStack.size() > stackSizeBefore)) { - stack.push(new TernarOpTreeItem(null, expr, trueStack.pop(), falseStack.pop())); - } else { - ret.add(new IfTreeItem(null, expr, onTrue, onFalse)); - - //Same continues in onTrue and onFalse gets continue on parent level - if ((!onTrue.isEmpty()) && (!onFalse.isEmpty())) { - if (onTrue.get(onTrue.size() - 1) instanceof ContinueTreeItem) { - if (onFalse.get(onFalse.size() - 1) instanceof ContinueTreeItem) { - if (((ContinueTreeItem) onTrue.get(onTrue.size() - 1)).loopPos == ((ContinueTreeItem) onFalse.get(onFalse.size() - 1)).loopPos) { - onTrue.remove(onTrue.size() - 1); - ret.add(onFalse.remove(onFalse.size() - 1)); - } - } - } - } - } - } - if (loop && (part.nextParts.size() > 1)) { - loops.remove(currentLoop); //remove loop so no break shows up - ret.addAll(printGraph(registerNames, stack, allParts, part, part.nextParts.get(reversed ? 0 : 1), stopPart, loops, forFinalCommands)); - } - - if (next != null) { - TreeItem ti = checkLoop(next, stopPart, loops); - if (ti != null) { - ret.add(ti); - } else { - if (debugMode) { - System.err.println("NEXT: (inside " + part + ")"); - } - ret.addAll(printGraph(registerNames, stack, allParts, part, next, stopPart, loops, forFinalCommands)); - if (debugMode) { - System.err.println("/NEXT: (inside " + part + ")"); - } - } - - } - } else { - ret.addAll(output); - } - onepart: - if (part.nextParts.size() == 1 && (!loop)) { - - - GraphPart p = part.nextParts.get(0); - TreeItem lop = checkLoop(p, stopPart, loops); - if (lop == null) { - if (p.path.length() == part.path.length()) { - ret.addAll(printGraph(registerNames, stack, allParts, part, p, stopPart, loops, forFinalCommands)); - } else { - if ((p != stopPart) && (p.refs.size() > 1)) { - List nextList = new ArrayList(); - populateParts(p, nextList); - Loop nearestLoop = null; - loopn: - for (GraphPart n : nextList) { - for (Loop l : loops) { - if (l.loopContinue == n) { - nearestLoop = l; - break loopn; - } - } - } - if ((nearestLoop != null) && (nearestLoop.loopBreak != null)) { - List finalCommands = printGraph(registerNames, stack, allParts, part, p, nearestLoop.loopContinue, loops, forFinalCommands); - nearestLoop.loopContinue = p; - forFinalCommands.put(nearestLoop, finalCommands); - ContinueTreeItem cti = new ContinueTreeItem(null, nearestLoop.loopBreak.start); - ret.add(cti); - } - } - } - } else { - ret.add(lop); - } - } - return ret; - } - private List posCache; - - private void buildCache() { - posCache = new ArrayList(); - int pos = 0; - for (int i = 0; i < code.size(); i++) { - posCache.add(pos); - pos += code.get(i).getBytes(version).length; - } - posCache.add(pos); - } - - private int pos2adr(int pos) { - if (posCache == null) { - buildCache(); - } - return posCache.get(pos); - } - - private int adr2pos(int adr) { - if (posCache == null) { - buildCache(); - } - return posCache.indexOf(adr); - } - - private void visitCode(int ip, int lastIp, HashMap> refs) { - while (ip < code.size()) { - refs.get(ip).add(lastIp); - lastIp = ip; - if (refs.get(ip).size() > 1) { - break; - } - Action ins = code.get(ip); - if (ins instanceof ActionThrow) { - break; - } - if (ins instanceof ActionReturn) { - break; - } - - if (ins instanceof ActionJump) { - ip = adr2pos(pos2adr(ip) + ins.getBytes(version).length + ((ActionJump) ins).offset); - continue; - } else if (ins instanceof ActionIf) { - visitCode(adr2pos(pos2adr(ip) + ins.getBytes(version).length + ((ActionIf) ins).offset), ip, refs); - } - ip++; - }; - } - - public HashMap> visitCode() { - HashMap> refs = new HashMap>(); - for (int i = 0; i < code.size(); i++) { - refs.put(i, new ArrayList()); - } - visitCode(0, 0, refs); - return refs; - } - - private List makeGraph(List actions, List allBlocks) { - HashMap> refs = visitCode(); - List ret = new ArrayList(); - boolean visited[] = new boolean[code.size()]; - ret.add(makeGraph(null, "0", code, 0, 0, allBlocks, refs, visited)); - return ret; - } - - private GraphPart makeGraph(GraphPart parent, String path, List code, int startip, int lastIp, List allBlocks, HashMap> refs, boolean visited2[]) { - - int ip = startip; - for (GraphPart p : allBlocks) { - if (p.start == ip) { - p.refs.add(parent); - return p; - } - } - GraphPart g; - GraphPart ret = new GraphPart(ip, -1); - ret.path = path; - GraphPart part = ret; - while (ip < code.size()) { - if (visited2[ip] || ((ip != startip) && (refs.get(ip).size() > 1))) { - part.end = lastIp; - GraphPart found = null; - for (GraphPart p : allBlocks) { - if (p.start == ip) { - found = p; - break; - } - } - - allBlocks.add(part); - - if (found != null) { - part.nextParts.add(found); - found.refs.add(part); - break; - } else { - GraphPart gp = new GraphPart(ip, -1); - gp.path = path; - part.nextParts.add(gp); - gp.refs.add(part); - part = gp; - } - } - lastIp = ip; - Action ins = code.get(ip); - if ((ins instanceof ActionThrow) || (ins instanceof ActionReturn)) { - part.end = ip; - allBlocks.add(part); - break; - } - if (ins instanceof ActionJump) { - part.end = ip; - allBlocks.add(part); - int newip = adr2pos(pos2adr(ip) + ins.getBytes(version).length + ((ActionJump) ins).offset); - part.nextParts.add(g = makeGraph(part, path, code, newip, lastIp, allBlocks, refs, visited2)); - g.refs.add(part); - break; - } else if (ins instanceof ActionIf) { - part.end = ip; - allBlocks.add(part); - part.nextParts.add(g = makeGraph(part, path + "0", code, adr2pos(pos2adr(ip) + ins.getBytes(version).length + ((ActionIf) ins).offset), ip, allBlocks, refs, visited2)); - g.refs.add(part); - part.nextParts.add(g = makeGraph(part, path + "1", code, ip + 1, ip, allBlocks, refs, visited2)); - g.refs.add(part); - - break; - } - ip++; - }; - if (ip == code.size()) { - allBlocks.add(part); - if (part.start == ip) { - part.end = ip; - } else { - part.end = code.size() - 1; - part.nextParts.add(makeGraph(part, path, code, ip, ip, allBlocks, refs, visited2)); - } - - } - return ret; - } - */ @Override protected int checkIp(int ip) { @@ -958,7 +323,7 @@ public class ActionGraph extends Graph { if (code.get(ip + 2) instanceof ActionNot) { if (code.get(ip + 3) instanceof ActionIf) { ActionIf aif = (ActionIf) code.get(ip + 3); - if (code.adr2pos(code.pos2adr(ip + 4) + aif.offset) == ip) { + if (code.adr2pos(code.pos2adr(ip + 4) + aif.getJumpOffset()) == ip) { ip += 4; } } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java b/trunk/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java index d89fbc0e0..f272020f3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java @@ -69,6 +69,7 @@ public class ActionGraphSource extends GraphSource { if (adr == 0) { return 0; } + //throw new RuntimeException("Address "+Helper.formatAddress(adr)+" not found"); return -1; } diff --git a/trunk/src/com/jpexs/decompiler/flash/action/gui/ActionPanel.java b/trunk/src/com/jpexs/decompiler/flash/action/gui/ActionPanel.java index bf5da6af2..b0767a63c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/gui/ActionPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/gui/ActionPanel.java @@ -115,7 +115,7 @@ public class ActionPanel extends JPanel implements ActionListener { if (Main.DO_DECOMPILE) { List as = asm.getActions(SWF.DEFAULT_VERSION); lastCode = as; - com.jpexs.decompiler.flash.action.Action.setActionsAddresses(as, 0, SWF.DEFAULT_VERSION); + //com.jpexs.decompiler.flash.action.Action.setActionsAddresses(as, 0, SWF.DEFAULT_VERSION); String s = com.jpexs.decompiler.flash.action.Action.actionsToSource(as, SWF.DEFAULT_VERSION); decompiledHilights = Highlighting.getInstrHighlights(s); decompiledEditor.setText(Highlighting.stripHilights(s)); @@ -316,7 +316,7 @@ public class ActionPanel extends JPanel implements ActionListener { setHex(hexButton.isSelected()); } else if (e.getActionCommand().equals("SAVEACTION")) { try { - src.setActions(ASMParser.parse(true, new ByteArrayInputStream(editor.getText().getBytes()), SWF.DEFAULT_VERSION), SWF.DEFAULT_VERSION); + src.setActions(ASMParser.parse(0, src.getPos(), true, new ByteArrayInputStream(editor.getText().getBytes()), SWF.DEFAULT_VERSION), SWF.DEFAULT_VERSION); setSource(this.src); JOptionPane.showMessageDialog(this, "Code successfully saved"); } catch (IOException ex) { diff --git a/trunk/src/com/jpexs/decompiler/flash/action/parser/ASMParser.java b/trunk/src/com/jpexs/decompiler/flash/action/parser/ASMParser.java index 541a1907c..cd98d7203 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/parser/ASMParser.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/parser/ASMParser.java @@ -25,14 +25,17 @@ import com.jpexs.decompiler.flash.action.swf4.*; import com.jpexs.decompiler.flash.action.swf5.*; import com.jpexs.decompiler.flash.action.swf6.*; import com.jpexs.decompiler.flash.action.swf7.*; +import com.jpexs.decompiler.flash.helpers.Helper; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; public class ASMParser { - public static List parse(boolean ignoreNops, List