From f5d37441caa4d94de2297890f21621d4170911b2 Mon Sep 17 00:00:00 2001 From: "honfika@gmail.com" Date: Sun, 27 Sep 2015 10:21:21 +0200 Subject: [PATCH] fix --- .../flash/action/FastActionList.java | 165 +++++++++++++++++- .../flash/action/swf4/ActionIf.java | 6 +- .../flash/action/swf4/ActionJump.java | 6 +- 3 files changed, 174 insertions(+), 3 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/FastActionList.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/FastActionList.java index 1e8f63a21..00b28fdc5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/FastActionList.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/FastActionList.java @@ -16,10 +16,17 @@ */ package com.jpexs.decompiler.flash.action; +import com.jpexs.decompiler.flash.action.special.ActionStore; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionJump; import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.graph.GraphSourceItemContainer; +import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; +import java.util.Map; /** * @@ -29,8 +36,161 @@ public class FastActionList { private LinkedList actions; - public FastActionList(List actions) { + private Map> containerLastActions; + + private Map jumps; + + public FastActionList(ActionList actions) { this.actions = new LinkedList<>(actions); + + Map> containerLastActions = new HashMap<>(); + getContainerLastActions(this.actions, actions, containerLastActions); + this.containerLastActions = containerLastActions; + + Map jumps = new HashMap<>(); + getJumps(actions, jumps); + this.jumps = jumps; + } + + private void getContainerLastActions(LinkedList linkedActions, ActionList actions, Map> lastActions) { + for (Action a : linkedActions) { + if (a instanceof GraphSourceItemContainer) { + lastActions.put(a, getContainerLastActions(actions, a)); + } + } + } + + private List getContainerLastActions(ActionList actions, Action action) { + GraphSourceItemContainer container = (GraphSourceItemContainer) action; + List sizes = container.getContainerSizes(); + long endAddress = action.getAddress() + container.getHeaderSize(); + List lasts = new ArrayList<>(sizes.size()); + for (long size : sizes) { + endAddress += size; + long lastActionAddress = getNearAddress(actions, endAddress - 1, false); + Action lastAction = null; + if (lastActionAddress != -1) { + lastAction = actions.getByAddress(lastActionAddress); + } + lasts.add(lastAction); + } + return lasts; + } + + private long getNearAddress(ActionList actions, long address, boolean next) { + int min = 0; + int max = actions.size() - 1; + + while (max >= min) { + int mid = (min + max) / 2; + long midValue = actions.get(mid).getAddress(); + if (midValue == address) { + return address; + } else if (midValue < address) { + min = mid + 1; + } else { + max = mid - 1; + } + } + + return next + ? (min < actions.size() ? actions.get(min).getAddress() : -1) + : (max >= 0 ? actions.get(max).getAddress() : -1); + } + + private static void getJumps(ActionList actions, Map jumps) { + for (Action a : actions) { + long target = -1; + if (a instanceof ActionIf) { + target = ((ActionIf) a).getTargetAddress(); + } else if (a instanceof ActionJump) { + target = ((ActionJump) a).getTargetAddress(); + } else if (a instanceof ActionStore) { + ActionStore aStore = (ActionStore) a; + int storeSize = aStore.getStoreSize(); + // skip storeSize + 1 actions (+1 is the current action) + Action targetAction = a; + for (int i = 0; i <= storeSize; i++) { + long address = targetAction.getAddress() + targetAction.getTotalActionLength(); + targetAction = actions.getByAddress(address); + if (targetAction == null) { + break; + } + } + jumps.put(a, targetAction); + } + if (target >= 0) { + Action targetAction = actions.getByAddress(target); + jumps.put(a, targetAction); + } + } + } + + private void updateJumps(Map jumps) { + if (actions.isEmpty()) { + return; + } + + long endAddress = actions.getLast().getAddress(); + for (Action a : actions) { + if (a instanceof ActionIf) { + ActionIf aIf = (ActionIf) a; + Action target = jumps.get(a); + long offset; + if (target != null) { + offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); + } else { + offset = endAddress - a.getAddress() - a.getTotalActionLength(); + } + aIf.setJumpOffset((int) offset); + } else if (a instanceof ActionJump) { + ActionJump aJump = (ActionJump) a; + Action target = jumps.get(a); + long offset; + if (target != null) { + offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); + } else { + offset = endAddress - a.getAddress() - a.getTotalActionLength(); + } + aJump.setJumpOffset((int) offset); + } + } + } + + private void updateActionStores(ActionList actionList, Map jumps) { + for (Action a : actions) { + if (a instanceof ActionStore) { + ActionStore aStore = (ActionStore) a; + Action nextActionAfterStore = jumps.get(a); + Action a1 = a; + List store = new ArrayList<>(); + while (true) { + long address = a1.getAddress() + a1.getTotalActionLength(); + a1 = actionList.getByAddress(address); + if (a1 == null || a1 == nextActionAfterStore) { + break; + } + store.add(a1); + } + aStore.setStore(store); + } + } + } + + private void updateContainerSizes(Map> containerLastActions) { + for (Action a : actions) { + if (a instanceof GraphSourceItemContainer) { + GraphSourceItemContainer container = (GraphSourceItemContainer) a; + List lastActions = containerLastActions.get(a); + long startAddress = a.getAddress() + container.getHeaderSize(); + for (int j = 0; j < lastActions.size(); j++) { + Action lastAction = lastActions.get(j); + int length = (int) (lastAction.getAddress() + lastAction.getTotalActionLength() - startAddress); + container.setContainerSize(j, length); + startAddress += length; + } + } + } } public void expandPushes() { @@ -67,6 +227,9 @@ public class FastActionList { public ActionList toActionList() { ActionList result = new ActionList(actions); updateActionAddressesAndLengths(); + updateJumps(jumps); + updateActionStores(result, jumps); + updateContainerSizes(containerLastActions); return result; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionIf.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionIf.java index f9af92b1b..967306273 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionIf.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionIf.java @@ -61,7 +61,11 @@ public class ActionIf extends Action { @Override public void getRef(Set refs) { - refs.add(getAddress() + getTotalActionLength() + offset); + refs.add(getTargetAddress()); + } + + public long getTargetAddress() { + return getAddress() + 5 /*getTotalActionLength()*/ + offset; } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionJump.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionJump.java index 91f8d50cd..72c84bfa3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionJump.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionJump.java @@ -61,7 +61,11 @@ public class ActionJump extends Action { @Override public void getRef(Set refs) { - refs.add(getAddress() + getTotalActionLength() + offset); + refs.add(getTargetAddress()); + } + + public long getTargetAddress() { + return getAddress() + 5 /*getTotalActionLength()*/ + offset; } @Override