diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java index 8e3e6f181..aaebe4a1a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java @@ -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; import com.jpexs.decompiler.flash.BaseLocalData; @@ -30,6 +31,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; /** * @@ -73,6 +75,8 @@ public class AVM2LocalData extends BaseLocalData { public boolean thisHasDefaultToPrimitive; + public Map> setLocalPosToGetLocalPos; + public AVM2LocalData() { } @@ -96,6 +100,7 @@ public class AVM2LocalData extends BaseLocalData { refs = localData.refs; code = localData.code; thisHasDefaultToPrimitive = localData.thisHasDefaultToPrimitive; + setLocalPosToGetLocalPos = localData.setLocalPosToGetLocalPos; } public AVM2ConstantPool getConstants() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 65896eb3e..33196ec0f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1532,7 +1532,7 @@ public class AVM2Code implements Cloneable { return pos2adr(fixIPAfterDebugLine(adr2pos(addr, true))); } - public ConvertOutput toSourceOutput(boolean thisHasDefaultToPrimitive, Reference lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, ABC abc, MethodBody body, int start, int end, HashMap localRegNames, List fullyQualifiedNames, boolean[] visited, HashMap localRegAssigmentIps, HashMap> refs) throws ConvertException, InterruptedException { + public ConvertOutput toSourceOutput(Map> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, ABC abc, MethodBody body, int start, int end, HashMap localRegNames, List fullyQualifiedNames, boolean[] visited, HashMap localRegAssigmentIps, HashMap> refs) throws ConvertException, InterruptedException { calcKilledStats(body); boolean debugMode = DEBUG_MODE; if (debugMode) { @@ -1637,12 +1637,12 @@ public class AVM2Code implements Cloneable { AVM2Instruction insAfter = code.get(ip + 1); if ((insAfter.definition instanceof GetLocalTypeIns) && (((GetLocalTypeIns) insAfter.definition).getRegisterId(insAfter) == ((SetLocalTypeIns) ins.definition).getRegisterId(ins))) { GraphTargetItem before = stack.peek(); - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); stack.push(before); ip += 2; continue iploop; } else { - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); ip++; continue iploop; } @@ -1651,7 +1651,7 @@ public class AVM2Code implements Cloneable { do { AVM2Instruction insAfter = ip + 1 < code.size() ? code.get(ip + 1) : null; if (insAfter == null) { - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); ip++; break; } @@ -1685,7 +1685,7 @@ public class AVM2Code implements Cloneable { if (((GetLocalTypeIns) code.get(t).definition).getRegisterId(code.get(t)) == reg) { if (code.get(t + 1).definition instanceof KillIns) { if (code.get(t + 1).operands[0] == reg) { - ConvertOutput assignment = toSourceOutput(thisHasDefaultToPrimitive, lineStartItem, path, part, processJumps, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, abc, body, ip + 2, t - 1, localRegNames, fullyQualifiedNames, visited, localRegAssigmentIps, refs); + ConvertOutput assignment = toSourceOutput(setLocalPosToGetLocalPos, thisHasDefaultToPrimitive, lineStartItem, path, part, processJumps, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, abc, body, ip + 2, t - 1, localRegNames, fullyQualifiedNames, visited, localRegAssigmentIps, refs); if (!assignment.output.isEmpty()) { GraphTargetItem tar = assignment.output.remove(assignment.output.size() - 1); tar.firstPart = part; @@ -1719,21 +1719,21 @@ public class AVM2Code implements Cloneable { } stack.push(vx); } else { - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); } ip++; break; //} } else { - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); ip++; break; //throw new ConvertException("Unknown pattern after DUP:" + insComparsion.toString()); } } while (ins.definition instanceof DupIns); } else if ((ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ReturnVoidIns) || (ins.definition instanceof ThrowIns)) { - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); //ip = end + 1; break; } else if (ins.definition instanceof NewFunctionIns) { @@ -1769,13 +1769,13 @@ public class AVM2Code implements Cloneable { } } // What to do when hasDup is false? - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); NewFunctionAVM2Item nft = (NewFunctionAVM2Item) stack.peek(); nft.functionName = functionName; ip++; } else { try { - ins.definition.translate(lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); } catch (RuntimeException re) { /*String last=""; int len=5; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index 6a8d4a144..d82cb23ec 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -28,6 +28,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.KillIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FilteredCheckAVM2Item; @@ -85,6 +86,9 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Stack; +import java.util.TreeMap; +import java.util.TreeSet; import java.util.logging.Logger; /** @@ -99,6 +103,8 @@ public class AVM2Graph extends Graph { private final MethodBody body; + private final Logger logger = Logger.getLogger(AVM2Graph.class.getName()); + public AVM2Code getCode() { return avm2code; } @@ -128,6 +134,104 @@ public class AVM2Graph extends Graph { } + @Override + protected void beforePrintGraph(BaseLocalData localData, String path, Set allParts, List loops) { + Map> setLocalPosToGetLocalPos = calculateLocalRegsUsage(path, allParts); + AVM2LocalData avm2LocalData = ((AVM2LocalData) localData); + avm2LocalData.setLocalPosToGetLocalPos = setLocalPosToGetLocalPos; + } + + + public Map> calculateLocalRegsUsage(String path, Set allParts) { + logger.fine("--- " + path + " ---"); + Map> setLocalPosToGetLocalPos = new TreeMap<>(); + Map>> partUnresolvedRegisterToGetLocalPos = new HashMap<>(); + Map> partRegisterToLastSetLocalPos = new HashMap<>(); + + for (GraphPart p : allParts) { + if (p.start < 0) { + continue; + } + Map registerToLastSetLocalPos = new HashMap<>(); + for (int ip = p.start; ip <= p.end; ip++) { + AVM2Instruction ins = avm2code.code.get(ip); + if (ins.definition instanceof SetLocalTypeIns) { + int regId = ((SetLocalTypeIns) ins.definition).getRegisterId(ins); + registerToLastSetLocalPos.put(regId, ip); + setLocalPosToGetLocalPos.put(ip, new TreeSet<>()); + } + if (ins.definition instanceof GetLocalTypeIns) { + int regId = ((GetLocalTypeIns) ins.definition).getRegisterId(ins); + if (registerToLastSetLocalPos.containsKey(regId)) { + int setLocalPos = registerToLastSetLocalPos.get(regId); + setLocalPosToGetLocalPos.get(setLocalPos).add(ip); + } else { + if (!partUnresolvedRegisterToGetLocalPos.containsKey(p)) { + partUnresolvedRegisterToGetLocalPos.put(p, new HashMap<>()); + } + if (!partUnresolvedRegisterToGetLocalPos.get(p).containsKey(regId)) { + partUnresolvedRegisterToGetLocalPos.get(p).put(regId, new ArrayList<>()); + } + partUnresolvedRegisterToGetLocalPos.get(p).get(regId).add(ip); + } + } + } + partRegisterToLastSetLocalPos.put(p, registerToLastSetLocalPos); + } + + Set pSet = new HashSet<>(partUnresolvedRegisterToGetLocalPos.keySet()); + for (GraphPart p : pSet) { + Map> unresolvedRegisterToGetLocalPos = partUnresolvedRegisterToGetLocalPos.get(p); + Set visited = new HashSet<>(); + visited.add(p); + for (GraphPart q : p.refs) { + calculateLocalRegsUsageWalk(q, unresolvedRegisterToGetLocalPos, visited, partRegisterToLastSetLocalPos, setLocalPosToGetLocalPos); + } + } + + for (int setLocalPos : setLocalPosToGetLocalPos.keySet()) { + AVM2Instruction ins = avm2code.code.get(setLocalPos); + int regId = ((SetLocalTypeIns) ins.definition).getRegisterId(ins); + logger.fine("set local reg " + regId + " at pos " + (setLocalPos + 1)); + + for (int getLocalPos : setLocalPosToGetLocalPos.get(setLocalPos)) { + logger.fine("- usage at pos " + (getLocalPos + 1)); + } + } + return setLocalPosToGetLocalPos; + } + + public void calculateLocalRegsUsageWalk(GraphPart q, + Map> unresolvedRegisterToGetLocalPos, + Set visited, + Map> partRegisterToLastSetLocalPos, + Map> setLocalPosToGetLocalPos) { + if (visited.contains(q)) { + return; + } + Set regIds = new HashSet<>(unresolvedRegisterToGetLocalPos.keySet()); + for (int regId : regIds) { + if (partRegisterToLastSetLocalPos.containsKey(q)) { + if (partRegisterToLastSetLocalPos.get(q).containsKey(regId)) { + int lastSetLocalPos = partRegisterToLastSetLocalPos.get(q).get(regId); + setLocalPosToGetLocalPos.get(lastSetLocalPos).addAll(unresolvedRegisterToGetLocalPos.get(regId)); + unresolvedRegisterToGetLocalPos = new HashMap<>(unresolvedRegisterToGetLocalPos); + unresolvedRegisterToGetLocalPos.remove(regId); + } + } + } + if (unresolvedRegisterToGetLocalPos.isEmpty()) { + return; + } + + + visited.add(q); + + for (GraphPart r : q.refs) { + calculateLocalRegsUsageWalk(r, unresolvedRegisterToGetLocalPos, visited, partRegisterToLastSetLocalPos, setLocalPosToGetLocalPos); + } + } + public static List translateViaGraph(String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, ScopeStack scopeStack, HashMap localRegNames, List fullyQualifiedNames, int staticOperation, HashMap localRegAssigmentIps, HashMap> refs, boolean thisHasDefaultToPrimitive) throws InterruptedException { AVM2Graph g = new AVM2Graph(code, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, fullyQualifiedNames, localRegAssigmentIps, refs); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java index 7d8d50788..5aa9b6c25 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java @@ -120,7 +120,7 @@ public class AVM2GraphSource extends GraphSource { List ret = new ArrayList<>(); ScopeStack newstack = ((AVM2LocalData) localData).scopeStack; Reference lineStartItem = new Reference<>(localData.lineStartInstruction); - ConvertOutput co = code.toSourceOutput(((AVM2LocalData) localData).thisHasDefaultToPrimitive, lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, newstack, abc, body, start, end, localRegNames, fullyQualifiedNames, new boolean[size()], localRegAssigmentIps, refs); + ConvertOutput co = code.toSourceOutput(((AVM2LocalData) localData).setLocalPosToGetLocalPos, ((AVM2LocalData) localData).thisHasDefaultToPrimitive, lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, newstack, abc, body, start, end, localRegNames, fullyQualifiedNames, new boolean[size()], localRegAssigmentIps, refs); localData.lineStartInstruction = lineStartItem.getVal(); ret.addAll(co.output); return ret; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java index 066712ffd..dbcef8710 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java @@ -30,6 +30,8 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.Multiname; @@ -44,6 +46,7 @@ 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.Stack; @@ -160,7 +163,7 @@ public abstract class InstructionDefinition implements Serializable { public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) throws InterruptedException { } - public void translate(Reference lineStartItem, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2Instruction ins, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code, boolean thisHasDefaultToPrimitive) throws InterruptedException { + public void translate(Map> setLocalPosToGetLocalPos, Reference lineStartItem, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2Instruction ins, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code, boolean thisHasDefaultToPrimitive) throws InterruptedException { AVM2LocalData localData = new AVM2LocalData(); localData.isStatic = isStatic; localData.scriptIndex = scriptIndex; @@ -177,6 +180,7 @@ public abstract class InstructionDefinition implements Serializable { localData.refs = refs; localData.code = code; localData.thisHasDefaultToPrimitive = thisHasDefaultToPrimitive; + localData.setLocalPosToGetLocalPos = setLocalPosToGetLocalPos; translate(localData, stack, ins, output, path); lineStartItem.setVal(localData.lineStartInstruction); } @@ -307,4 +311,25 @@ public abstract class InstructionDefinition implements Serializable { public boolean isExitInstruction() { return false; } + + public void cleanTempRegisters(AVM2LocalData localData, List output, List usedLocalRegs) { + for (LocalRegAVM2Item reg : usedLocalRegs) { + System.err.println(reg.regIndex); + for (int i = output.size() - 1; i >= 0; i--) { + if (output.get(i) instanceof SetLocalAVM2Item) { + SetLocalAVM2Item setLocal = (SetLocalAVM2Item) output.get(i); + if (setLocal.regIndex == reg.regIndex) { + int setLocalIp = localData.code.code.indexOf(setLocal.getSrc()); + Set usages = localData.setLocalPosToGetLocalPos.get(setLocalIp); + int usageIp = localData.code.code.indexOf(reg.getSrc()); + if (usages.size() == 1 && usages.iterator().next().equals(usageIp)) { + output.remove(i); + } + } + } else { + break; + } + } + } + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java index 637fa6a9f..bd96bfddd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/GetLocalTypeIns.java @@ -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.localregs; import com.jpexs.decompiler.flash.abc.ABC; @@ -78,16 +79,8 @@ public abstract class GetLocalTypeIns extends InstructionDefinition { assignCount = localData.localRegAssignmentIps.get(regId); } if (assignCount > 5) { //Do not allow change register more than 5 - for deobfuscation - computedValue = new NotCompileTimeItem(ins, localData.lineStartInstruction, computedValue); + //computedValue = new NotCompileTimeItem(ins, localData.lineStartInstruction, computedValue); } - /*if (!isRegisterCompileTime(regId, ip, refs, code)) { - computedValue = new NotCompileTimeAVM2Item(ins, localData.lineStartInstruction, computedValue); - } - if (computedValue == null) { - if (!localRegNames.containsKey(regId)) { - computedValue = new UndefinedAVM2Item(null); //In some obfuscated code there seems to be reading of undefined registers - } - }*/ stack.push(new LocalRegAVM2Item(ins, localData.lineStartInstruction, regId, computedValue)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java index a9ba01b0a..5a61b1c53 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java @@ -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.other; import com.jpexs.decompiler.flash.abc.ABC; @@ -61,17 +62,29 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); GraphTargetItem obj = stack.pop(); if (value.getThroughDuplicate().getThroughRegister().getThroughDuplicate() instanceof IncrementAVM2Item) { + List localRegs = new ArrayList<>(); + if (value.getThroughDuplicate() instanceof LocalRegAVM2Item) { + localRegs.add((LocalRegAVM2Item) value.getThroughDuplicate()); + } GraphTargetItem inside = ((IncrementAVM2Item) value.getThroughDuplicate().getThroughRegister().getThroughDuplicate()).value.getThroughRegister().getNotCoerced().getThroughDuplicate(); if (inside instanceof GetPropertyAVM2Item) { GetPropertyAVM2Item insideProp = ((GetPropertyAVM2Item) inside); if (((FullMultinameAVM2Item) insideProp.propertyName).compareSame(multiname)) { GraphTargetItem insideObj = obj.getThroughDuplicate(); if (insideObj instanceof LocalRegAVM2Item) { + localRegs.add((LocalRegAVM2Item) insideObj); if (((LocalRegAVM2Item) insideObj).computedValue != null) { insideObj = ((LocalRegAVM2Item) insideObj).computedValue.getThroughNotCompilable().getThroughDuplicate(); } } + if (multiname.name instanceof LocalRegAVM2Item) { + localRegs.add((LocalRegAVM2Item) multiname.name); + } + if (multiname.namespace instanceof LocalRegAVM2Item) { + localRegs.add((LocalRegAVM2Item) multiname.namespace); + } if (insideProp.object.getThroughDuplicate() == insideObj) { + cleanTempRegisters(localData, output, localRegs); if (stack.size() > 0) { GraphTargetItem top = stack.peek().getNotCoerced().getThroughDuplicate(); if (top == insideProp) { @@ -93,17 +106,30 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns } if (value.getThroughDuplicate().getThroughRegister().getThroughDuplicate() instanceof DecrementAVM2Item) { + List localRegs = new ArrayList<>(); + if (value.getThroughDuplicate() instanceof LocalRegAVM2Item) { + localRegs.add((LocalRegAVM2Item) value.getThroughDuplicate()); + } + GraphTargetItem inside = ((DecrementAVM2Item) value.getThroughDuplicate().getThroughRegister().getThroughDuplicate()).value.getThroughRegister().getNotCoerced().getThroughDuplicate(); if (inside instanceof GetPropertyAVM2Item) { GetPropertyAVM2Item insideProp = ((GetPropertyAVM2Item) inside); if (((FullMultinameAVM2Item) insideProp.propertyName).compareSame(multiname)) { GraphTargetItem insideObj = obj.getThroughDuplicate(); if (insideObj instanceof LocalRegAVM2Item) { + localRegs.add((LocalRegAVM2Item) insideObj); if (((LocalRegAVM2Item) insideObj).computedValue != null) { insideObj = ((LocalRegAVM2Item) insideObj).computedValue.getThroughNotCompilable().getThroughDuplicate(); } } + if (multiname.name instanceof LocalRegAVM2Item) { + localRegs.add((LocalRegAVM2Item) multiname.name); + } + if (multiname.namespace instanceof LocalRegAVM2Item) { + localRegs.add((LocalRegAVM2Item) multiname.namespace); + } if (insideProp.object.getThroughDuplicate() == insideObj) { + cleanTempRegisters(localData, output, localRegs); if (stack.size() > 0) { GraphTargetItem top = stack.peek().getNotCoerced().getThroughDuplicate(); if (top == insideProp) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index 51cfb13c1..70e965d32 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -545,6 +545,8 @@ public class Graph { } System.err.println("");//*/ List gotos = new ArrayList<>(); + + beforePrintGraph(localData, path, allParts, loops); List ret = printGraph(gotos, gotoTargets, new HashMap<>(), new HashMap<>(), localData, stack, allParts, null, heads.get(0), null, loops, staticOperation, path); processIfGotos(gotos, ret); @@ -572,6 +574,10 @@ public class Graph { return ret; } + protected void beforePrintGraph(BaseLocalData localData, String path, Set allParts, List loops) { + + } + private List getCommonPrefix(List> listOfLists) { List result = new ArrayList<>(); if (listOfLists.isEmpty()) {