From d97b8647eda0b3bc0e9331ddd9192ac2017f9c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Sun, 30 Jun 2013 12:54:47 +0200 Subject: [PATCH] Issue #166 Fixed For detection Issue #165 Better support for direct lookupswitch --- .../flash/abc/avm2/graph/AVM2Graph.java | 8 +- .../jpexs/decompiler/flash/graph/Graph.java | 136 +++++++++++------- 2 files changed, 89 insertions(+), 55 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index 0b52d873b..94150b518 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -377,7 +377,7 @@ public class AVM2Graph extends Graph { } } } - if (code.code.get(part.end).definition instanceof LookupSwitchIns) { + if ((code.code.get(part.end).definition instanceof LookupSwitchIns) && ignoredSwitches.contains(part.end)) { ret = new ArrayList<>(); ret.addAll(output); return ret; @@ -395,6 +395,12 @@ public class AVM2Graph extends Graph { && (part.nextParts.get(1).getHeight() >= 2) && (code.code.get(code.fixIPAfterDebugLine(part.nextParts.get(1).start)).definition instanceof PushIntegerTypeIns) && (code.code.get(part.nextParts.get(1).nextParts.get(0).end).definition instanceof LookupSwitchIns))) { + + if (stack.peek() instanceof StrictEqTreeItem) { + ignoredSwitches.add(part.nextParts.get(0).nextParts.get(0).end); + } else { + ignoredSwitches.add(part.nextParts.get(1).nextParts.get(0).end); + } ret = new ArrayList<>(); ret.addAll(output); boolean reversed = false; diff --git a/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java b/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java index 5dcf1e675..25fc9cf4a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java +++ b/trunk/src/com/jpexs/decompiler/flash/graph/Graph.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.graph; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.helpers.Highlighting; +import java.awt.GradientPaint; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -550,11 +551,11 @@ public class Graph { } System.out.println("");*/ getPrecontinues(null, heads.get(0), loops, null); - /*System.out.println(""); + /*System.err.println(""); for (Loop el : loops) { - System.out.println(el); + System.err.println(el); } - System.out.println("");//*/ + System.err.println("");//*/ List ret = printGraph(new ArrayList(), localData, stack, allParts, null, heads.get(0), null, loops); processIfs(ret); @@ -822,6 +823,7 @@ public class Graph { } private void getPrecontinues(GraphPart parent, GraphPart part, List loops, List stopPart) { + markLevels(part, loops); //Note: this also marks part as precontinue when there is if /* while(k<10){ @@ -833,7 +835,7 @@ public class Graph { //precontinue k++; } - + */ looploops: for (Loop l : loops) { @@ -861,7 +863,7 @@ public class Graph { break; } } - if (part != l.loopContinue) { + if (part.level == 0 && part != l.loopContinue) { l.loopPreContinue = part; } } @@ -872,21 +874,26 @@ public class Graph { clearLoops(loops);*/ } - private void getPrecontinues(GraphPart parent, GraphPart part, List loops, List stopPart, int level, List visited) { - boolean debugMode = true; + private void markLevels(GraphPart part, List loops) { + clearLoops(loops); + markLevels(part, loops, new ArrayList(), 1, new ArrayList()); + clearLoops(loops); + } + + private void markLevels(GraphPart part, List loops, List stopPart, int level, List visited) { + boolean debugMode = false; if (stopPart == null) { stopPart = new ArrayList<>(); } if (debugMode) { - System.err.println("preco " + part); + System.err.println("markLevels " + part); } if (stopPart.contains(part)) { return; } for (Loop el : loops) { if ((el.phase == 2) && (el.loopContinue == part)) { - throw new RuntimeException("Phase 2 visited again:" + el); - //return; + return; } if (el.phase != 1) { if (debugMode) { @@ -906,35 +913,13 @@ public class Graph { } - if (visited.contains(part)) { //(part.level > level) { - List nextList = new ArrayList<>(); - populateParts(part, 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.loopContinue != part)) {// && (nearestLoop.loopBreak != null)) { - if (nearestLoop.phase == 1) { - if ((nearestLoop.loopPreContinue == null)) {// || (nearestLoop.loopPreContinue.leadsTo(code, part, getLoopsContinues(loops)))) { - nearestLoop.loopPreContinue = part; - return; - } - } - } - } - - if (!visited.contains(part)) { + if (visited.contains(part)) { + part.level = 0; + } else { visited.add(part); + part.level = level; } - List loopContinues = getLoopsContinues(loops); boolean isLoop = false; Loop currentLoop = null; for (Loop el : loops) { @@ -961,18 +946,18 @@ public class Graph { stopParts2.add(stopPart.get(stopPart.size() - 1)); } if (next != nextParts.get(0)) { - getPrecontinues(part, nextParts.get(0), loops, next == null ? stopPart : stopParts2, level + 1, visited); + markLevels(nextParts.get(0), loops, next == null ? stopPart : stopParts2, level + 1, visited); } if (next != nextParts.get(1)) { - getPrecontinues(part, nextParts.get(1), loops, next == null ? stopPart : stopParts2, level + 1, visited); + markLevels(nextParts.get(1), loops, next == null ? stopPart : stopParts2, level + 1, visited); } if (next != null) { - getPrecontinues(part, next, loops, stopPart, level, visited); + markLevels(next, loops, stopPart, level, visited); } } if (nextParts.size() > 2) { - GraphPart next = getCommonPart(nextParts, loops); + GraphPart next = getMostCommonPart(nextParts, loops); List vis = new ArrayList<>(); for (GraphPart p : nextParts) { if (vis.contains(p)) { @@ -988,41 +973,34 @@ public class Graph { if (p2 == p) { continue; } - List p12 = new ArrayList<>(); - p12.add(p); - p12.add(p2); - GraphPart n = getCommonPart(p12, loops); - if (!stopPart2.contains(n)) { - stopPart2.add(n); - } if (!stopPart2.contains(p2)) { stopPart2.add(p2); } } if (next != p) { - getPrecontinues(part, p, loops, stopPart2, level + 1, visited); + markLevels(p, loops, stopPart2, level + 1, visited); vis.add(p); } } if (next != null) { - getPrecontinues(part, next, loops, stopPart, level, visited); + markLevels(next, loops, stopPart, level, visited); } } if (nextParts.size() == 1) { - getPrecontinues(part, nextParts.get(0), loops, stopPart, level, visited); + markLevels(nextParts.get(0), loops, stopPart, level, visited); } for (GraphPart t : part.throwParts) { if (!visited.contains(t)) { - getPrecontinues(part, t, loops, stopPart, level, visited); + markLevels(t, loops, stopPart, level, visited); } } if (isLoop) { if (currentLoop.loopBreak != null) { currentLoop.phase = 2; - getPrecontinues(null, currentLoop.loopBreak, loops, stopPart, level, visited); + markLevels(currentLoop.loopBreak, loops, stopPart, level, visited); } } } @@ -1380,7 +1358,7 @@ public class Graph { if (debugMode) { - System.err.println("PART " + part); + System.err.println("PART " + part+" nextsize:"+part.nextParts.size()); } /*while (((part != null) && (part.getHeight() == 1)) && (code.size() > part.start) && (code.get(part.start).isJump())) { //Parts with only jump in it gets ignored @@ -1712,7 +1690,57 @@ public class Graph { if (parseNext) { - if (part.nextParts.size() == 2) { + if (part.nextParts.size() > 2) {//alchemy direct switch + GraphPart next = getMostCommonPart(part.nextParts, loops); + List vis = new ArrayList<>(); + GraphTargetItem switchedItem = stack.pop(); + List caseValues = new ArrayList<>(); + List> caseCommands = new ArrayList<>(); + List defaultCommands = new ArrayList<>(); + List valueMappings = new ArrayList<>(); + Loop swLoop = new Loop(loops.size(), null, next); + swLoop.phase = 1; + loops.add(swLoop); + boolean first = false; + for (GraphPart p : part.nextParts) { + if (vis.contains(p)) { + valueMappings.add(caseCommands.size() - 1); + continue; + } + if (!first) { + valueMappings.add(caseCommands.size()); + } + List stopPart2 = new ArrayList<>(); + if (next != null) { + stopPart2.add(next); + } else if (!stopPart.isEmpty()) { + stopPart2.add(stopPart.get(stopPart.size() - 1)); + } + for (GraphPart p2 : part.nextParts) { + if (p2 == p) { + continue; + } + if (!stopPart2.contains(p2)) { + stopPart2.add(p2); + } + } + if (next != p) { + if (first) { + defaultCommands = printGraph(visited, localData, stack, allParts, part, p, stopPart2, loops); + } else { + caseCommands.add(printGraph(visited, localData, stack, allParts, part, p, stopPart2, loops)); + } + vis.add(p); + } + first = false; + } + SwitchItem sw = new SwitchItem(null, null, switchedItem, caseValues, caseCommands, defaultCommands, valueMappings); + currentRet.add(sw); + swLoop.phase = 2; + if (next != null) { + currentRet.addAll(printGraph(visited, localData, stack, allParts, part, next, stopPart, loops)); + } + } else if (part.nextParts.size() == 2) { //List ignore = new ArrayList<>(); //ignore.addAll(loopContinues);