diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 6190744c1..85caf26b5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -4045,7 +4045,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { int mi = ((TraitMethodGetterSetter) t).method_info; try { - documentPack.abc.findBody(mi).convert(getAbcIndex(), new ConvertData(), "??", ScriptExportMode.AS, true, mi, documentPack.scriptIndex, cindex, documentPack.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(documentPack.abc.findBody(mi)); + documentPack.abc.findBody(mi).convert(callStack, getAbcIndex(), new ConvertData(), "??", ScriptExportMode.AS, true, mi, documentPack.scriptIndex, cindex, documentPack.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()); List infos = documentPack.abc.findBody(mi).convertedItems; if (!infos.isEmpty()) { if (infos.get(0) instanceof IfItem) { @@ -4121,7 +4123,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { if (tr instanceof TraitClass) { int ci = ((TraitClass) tr).class_info; int cinit = p.abc.class_info.get(ci).cinit_index; - p.abc.findBody(cinit).convert(getAbcIndex(), new ConvertData(), "??", ScriptExportMode.AS, true, cinit, p.scriptIndex, cindex, p.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()); + callStack = new ArrayList<>(); + callStack.add(p.abc.findBody(cinit)); + p.abc.findBody(cinit).convert(callStack, getAbcIndex(), new ConvertData(), "??", ScriptExportMode.AS, true, cinit, p.scriptIndex, cindex, p.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()); List cinitBody = p.abc.findBody(cinit).convertedItems; for (GraphTargetItem cit : cinitBody) { if (cit instanceof SetPropertyAVM2Item) { 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 f187b4a54..428880e9b 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 @@ -52,6 +52,8 @@ public class AVM2LocalData extends BaseLocalData { public ScopeStack scopeStack; public MethodBody methodBody; + + public List callStack; public ABC abc; @@ -145,6 +147,7 @@ public class AVM2LocalData extends BaseLocalData { localRegs = localData.localRegs; scopeStack = localData.scopeStack; methodBody = localData.methodBody; + callStack = localData.callStack; abc = localData.abc; abcIndex = localData.abcIndex; localRegNames = localData.localRegNames; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java index a44099446..d3c87f1f7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java @@ -191,7 +191,9 @@ public class ScriptPack extends AS3ClassTreeItem { } ts.add(abc.script_info.get(scriptIndex).traits); writer.mark(); - abc.bodies.get(sinit_bodyIndex).convert(abcIndex, convertData, path +/*packageName +*/ "/.scriptinitializer", exportMode, true, sinit_index, scriptIndex, -1, abc, null, new ScopeStack(), GraphTextWriter.TRAIT_SCRIPT_INITIALIZER, writer, new ArrayList<>(), ts, true, new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(abc.bodies.get(sinit_bodyIndex)); + abc.bodies.get(sinit_bodyIndex).convert(callStack, abcIndex, convertData, path +/*packageName +*/ "/.scriptinitializer", exportMode, true, sinit_index, scriptIndex, -1, abc, null, new ScopeStack(), GraphTextWriter.TRAIT_SCRIPT_INITIALIZER, writer, new ArrayList<>(), ts, true, new HashSet<>()); scriptInitializerIsEmpty = !writer.getMark(); } @@ -220,7 +222,9 @@ public class ScriptPack extends AS3ClassTreeItem { if (exportMode != ScriptExportMode.AS_METHOD_STUBS) { if (!scriptInitializerIsEmpty) { writer.startBlock(); - abc.bodies.get(bodyIndex).toString(abcIndex, path +/*packageName +*/ "/.scriptinitializer", exportMode, abc, null, writer, new ArrayList<>(), new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(abc.bodies.get(bodyIndex)); + abc.bodies.get(bodyIndex).toString(callStack, abcIndex, path +/*packageName +*/ "/.scriptinitializer", exportMode, abc, null, writer, new ArrayList<>(), new HashSet<>()); writer.endBlock(); } else { writer.append(" "); 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 3623fbf11..6d63513db 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 @@ -1589,7 +1589,7 @@ public class AVM2Code implements Cloneable { return pos2adr(getIpThroughJumpAndDebugLine(adr2pos(addr, true))); } - public ConvertOutput toSourceOutput(AbcIndexing abcIndex, 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, HashMap localRegTypes, List fullyQualifiedNames, boolean[] visited, HashMap localRegAssigmentIps, HashMap> refs) throws ConvertException, InterruptedException { + public ConvertOutput toSourceOutput(List callStack, AbcIndexing abcIndex, 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, HashMap localRegTypes, List fullyQualifiedNames, boolean[] visited, HashMap localRegAssigmentIps, HashMap> refs) throws ConvertException, InterruptedException { calcKilledStats(body); boolean debugMode = DEBUG_MODE; if (debugMode) { @@ -1664,7 +1664,7 @@ public class AVM2Code implements Cloneable { do { AVM2Instruction insAfter = ip + 1 < code.size() ? code.get(ip + 1) : null; if (insAfter == null) { - ins.definition.translate(abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ins.definition.translate(callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); ip++; break; } @@ -1686,14 +1686,14 @@ public class AVM2Code implements Cloneable { //stack.add("(" + stack.pop() + ")||"); isAnd = false; } else { - ins.definition.translate(abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ins.definition.translate(callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, 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(abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ins.definition.translate(callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); //ip = end + 1; break; } else if (ins.definition instanceof NewFunctionIns) { @@ -1729,13 +1729,13 @@ public class AVM2Code implements Cloneable { } } // What to do when hasDup is false? - ins.definition.translate(abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ins.definition.translate(callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); NewFunctionAVM2Item nft = (NewFunctionAVM2Item) stack.peek(); nft.functionName = functionName; ip++; } else { try { - ins.definition.translate(abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); + ins.definition.translate(callStack, abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive); } catch (RuntimeException re) { /*String last=""; int len=5; @@ -2135,7 +2135,7 @@ public class AVM2Code implements Cloneable { }*/ } - public List toGraphTargetItems(AbcIndexing abcIndex, boolean thisHasDefaultToPrimitive, ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap localRegNames, ScopeStack scopeStack, int initializerType, List fullyQualifiedNames, List initTraits, int staticOperation, HashMap localRegAssigmentIps, HashMap> refs) throws InterruptedException { + public List toGraphTargetItems(List callStack, AbcIndexing abcIndex, boolean thisHasDefaultToPrimitive, ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap localRegNames, ScopeStack scopeStack, int initializerType, List fullyQualifiedNames, List initTraits, int staticOperation, HashMap localRegAssigmentIps, HashMap> refs) throws InterruptedException { initToSource(); List list; HashMap localRegs = new HashMap<>(); @@ -2150,7 +2150,7 @@ public class AVM2Code implements Cloneable { } //try { - list = AVM2Graph.translateViaGraph(abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, localRegTypes, fullyQualifiedNames, staticOperation, localRegAssigmentIps, refs, thisHasDefaultToPrimitive); + list = AVM2Graph.translateViaGraph(callStack, abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, localRegTypes, fullyQualifiedNames, staticOperation, localRegAssigmentIps, refs, thisHasDefaultToPrimitive); if (initTraits != null) { loopi: diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/CodeStats.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/CodeStats.java index 8ada73806..7c3866391 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/CodeStats.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/CodeStats.java @@ -17,9 +17,11 @@ package com.jpexs.decompiler.flash.abc.avm2; import com.jpexs.decompiler.flash.abc.ABC; +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.model.LocalData; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -52,7 +54,7 @@ public class CodeStats { if (stats.stackpos > ms) { ms = stats.stackpos; } - writer.appendNoHilight(i + ":" + stats.stackpos + (deltastack >= 0 ? "+" + deltastack : deltastack) + "," + stats.scopepos + " " + stats.ins.toString(writer, LocalData.create(null, abc, null, fullyQualifiedNames, new HashSet<>()))).newLine(); + writer.appendNoHilight(i + ":" + stats.stackpos + (deltastack >= 0 ? "+" + deltastack : deltastack) + "," + stats.scopepos + " " + stats.ins.toString(writer, LocalData.create(new ArrayList<>(), null, abc, null, fullyQualifiedNames, new HashSet<>()))).newLine(); i++; } return writer; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorGetSet.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorGetSet.java index bd066a657..5c014b9af 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorGetSet.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorGetSet.java @@ -109,6 +109,9 @@ public class AVM2DeobfuscatorGetSet extends SWFDecompilerAdapter { localData.localRegs = new HashMap<>(body.max_regs); localData.localRegAssignmentIps = new HashMap<>(); localData.scopeStack = new ScopeStack(true); + List callStack = new ArrayList<>(); + callStack.add(body); + localData.callStack = callStack; localData.methodBody = body; localData.abc = abc; localData.localRegNames = new HashMap<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java index 52164d7ed..754ab5c0c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java @@ -199,6 +199,9 @@ public class AVM2DeobfuscatorSimpleOld extends AVM2DeobfuscatorZeroJumpsNullPush localData.localRegs = new HashMap<>(body.max_regs); localData.localRegAssignmentIps = new HashMap<>(); localData.scopeStack = new ScopeStack(true); + List callStack = new ArrayList<>(); + callStack.add(body); + localData.callStack = callStack; localData.methodBody = body; localData.abc = abc; localData.localRegNames = new HashMap<>(); 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 062442bdd..6e2308144 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 @@ -633,7 +633,7 @@ public class AVM2Graph extends Graph { return setLocalPosToGetLocalPos; } - public static List translateViaGraph(AbcIndexing abcIndex, String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, ScopeStack scopeStack, HashMap localRegNames, HashMap localRegTypes, List fullyQualifiedNames, int staticOperation, HashMap localRegAssigmentIps, HashMap> refs, boolean thisHasDefaultToPrimitive) throws InterruptedException { + public static List translateViaGraph(List callStack, AbcIndexing abcIndex, String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, ScopeStack scopeStack, HashMap localRegNames, HashMap localRegTypes, List fullyQualifiedNames, int staticOperation, HashMap localRegAssigmentIps, HashMap> refs, boolean thisHasDefaultToPrimitive) throws InterruptedException { AVM2Graph g = new AVM2Graph(abcIndex, code, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, fullyQualifiedNames, localRegAssigmentIps, refs); AVM2LocalData localData = new AVM2LocalData(); @@ -643,6 +643,7 @@ public class AVM2Graph extends Graph { localData.localRegs = localRegs; localData.scopeStack = scopeStack; localData.methodBody = body; + localData.callStack = callStack; localData.abc = abc; localData.abcIndex = abcIndex; localData.localRegNames = localRegNames; 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 b0bc1cf24..94049e433 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 @@ -119,7 +119,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).abcIndex, ((AVM2LocalData) localData).setLocalPosToGetLocalPos, ((AVM2LocalData) localData).thisHasDefaultToPrimitive, lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, newstack, abc, body, start, end, localRegNames, ((AVM2LocalData) localData).localRegTypes, fullyQualifiedNames, new boolean[size()], localRegAssigmentIps, refs); + ConvertOutput co = code.toSourceOutput(((AVM2LocalData) localData).callStack, ((AVM2LocalData) localData).abcIndex, ((AVM2LocalData) localData).setLocalPosToGetLocalPos, ((AVM2LocalData) localData).thisHasDefaultToPrimitive, lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, newstack, abc, body, start, end, localRegNames, ((AVM2LocalData) localData).localRegTypes, 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 3c06bb785..088c11742 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 @@ -171,7 +171,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(AbcIndexing abcIndex, 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, HashMap localRegTypes, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code, boolean thisHasDefaultToPrimitive) throws InterruptedException { + public void translate(List callStack, AbcIndexing abcIndex, 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, HashMap localRegTypes, 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; @@ -180,6 +180,7 @@ public abstract class InstructionDefinition implements Serializable { localData.localRegs = localRegs; localData.scopeStack = scopeStack; localData.methodBody = body; + localData.callStack = callStack; localData.abc = abc; localData.abcIndex = abcIndex; localData.localRegNames = localRegNames; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewClassIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewClassIns.java index 033fbfb1b..a023e5971 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewClassIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewClassIns.java @@ -44,7 +44,7 @@ public class NewClassIns extends InstructionDefinition { public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) throws InterruptedException { int clsIndex = ins.operands[0]; HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); - stack.pop().toString(writer, LocalData.create(localData.abcIndex, localData.abc, localData.localRegNames, localData.fullyQualifiedNames, new HashSet<>())); + stack.pop().toString(writer, LocalData.create(localData.callStack /*??*/, localData.abcIndex, localData.abc, localData.localRegNames, localData.fullyQualifiedNames, new HashSet<>())); String baseType = writer.toString(); ABC abc = localData.abc; stack.push(new UnparsedAVM2Item(ins, localData.lineStartInstruction, "§§newclass(" + abc.constants.getMultiname(abc.instance_info.get(clsIndex).name_index).getName(localData.getConstants(), localData.fullyQualifiedNames, false, true) + "," + baseType + ")")); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetLexIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetLexIns.java index c3405f71e..ef5864cce 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetLexIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetLexIns.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.GetLexAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.avm2.parser.script.PropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.traits.Trait; @@ -57,17 +58,20 @@ public class GetLexIns extends InstructionDefinition { type.setVal(TypeItem.UNBOUNDED); callType.setVal(TypeItem.UNBOUNDED); String multinameStr = localData.abc.constants.getMultiname(multinameIndex).getName(localData.abc.constants, new ArrayList<>(), true, true); - for (Trait t : localData.methodBody.traits.traits) { - if (t instanceof TraitSlotConst) { - TraitSlotConst tsc = (TraitSlotConst) t; - if (Objects.equals( - tsc.getName(localData.abc).getName(localData.abc.constants, new ArrayList<>(), true, true), - multinameStr - )) { - GraphTargetItem ty = PropertyAVM2Item.multinameToType(tsc.type_index, localData.abc.constants); - type.setVal(ty); - callType.setVal(ty); - return; + for (int b = localData.callStack.size() - 1; b >= 0; b--) { + MethodBody body = localData.callStack.get(b); + for (Trait t : body.traits.traits) { + if (t instanceof TraitSlotConst) { + TraitSlotConst tsc = (TraitSlotConst) t; + if (Objects.equals( + tsc.getName(localData.abc).getName(localData.abc.constants, new ArrayList<>(), true, true), + multinameStr + )) { + GraphTargetItem ty = PropertyAVM2Item.multinameToType(tsc.type_index, localData.abc.constants); + type.setVal(ty); + callType.setVal(ty); + return; + } } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetPropertyIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetPropertyIns.java index 446f52abc..78f5dc113 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetPropertyIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/GetPropertyIns.java @@ -33,6 +33,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.avm2.parser.script.PropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.traits.Trait; @@ -152,17 +153,20 @@ public class GetPropertyIns extends InstructionDefinition { if (obj instanceof FindPropertyAVM2Item) { FindPropertyAVM2Item fprop = (FindPropertyAVM2Item) obj; if (fprop.propertyName.equals(multiname)) { - for (Trait t : localData.methodBody.traits.traits) { - if (t instanceof TraitSlotConst) { - TraitSlotConst tsc = (TraitSlotConst) t; - if (Objects.equals( - tsc.getName(localData.abc).getName(localData.abc.constants, new ArrayList<>(), true, true), - multinameStr - )) { - GraphTargetItem ty = PropertyAVM2Item.multinameToType(tsc.type_index, localData.abc.constants); - type.setVal(ty); - callType.setVal(ty); - return; + for (int b = localData.callStack.size() - 1; b >= 0; b--) { + MethodBody body = localData.callStack.get(b); + for (Trait t : body.traits.traits) { + if (t instanceof TraitSlotConst) { + TraitSlotConst tsc = (TraitSlotConst) t; + if (Objects.equals( + tsc.getName(localData.abc).getName(localData.abc.constants, new ArrayList<>(), true, true), + multinameStr + )) { + GraphTargetItem ty = PropertyAVM2Item.multinameToType(tsc.type_index, localData.abc.constants); + type.setVal(ty); + callType.setVal(ty); + return; + } } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/FullMultinameAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/FullMultinameAVM2Item.java index 7ebadfc87..95844d39e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/FullMultinameAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/FullMultinameAVM2Item.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.abc.avm2.model; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.DottedChain; @@ -92,13 +93,13 @@ public class FullMultinameAVM2Item extends AVM2Item { public boolean isTopLevel(String tname, ABC abc, HashMap localRegNames, List fullyQualifiedNames, Set seenMethods) throws InterruptedException { String cname; if (name != null) { - cname = name.toString(LocalData.create(null, abc, localRegNames, fullyQualifiedNames, seenMethods)); + cname = name.toString(LocalData.create(new ArrayList<>(), null, abc, localRegNames, fullyQualifiedNames, seenMethods)); } else { cname = (abc.constants.getMultiname(multinameIndex).getName(abc.constants, fullyQualifiedNames, true, true)); } String cns = ""; if (namespace != null) { - cns = namespace.toString(LocalData.create(null, abc, localRegNames, fullyQualifiedNames, seenMethods)); + cns = namespace.toString(LocalData.create(new ArrayList<>(), null, abc, localRegNames, fullyQualifiedNames, seenMethods)); } else { Namespace ns = abc.constants.getMultiname(multinameIndex).getNamespace(abc.constants); if ((ns != null) && (ns.name_index != 0)) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java index 9c3bf932b..e1e3e585c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java @@ -30,6 +30,7 @@ import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -94,8 +95,10 @@ public class NewFunctionAVM2Item extends AVM2Item { abc.method_info.get(methodIndex).getReturnTypeStr(writer, abc.constants, fullyQualifiedNames); writer.startBlock(); if (body != null) { - body.convert(localData.abcIndex, new ConvertData(), path + "/inner", ScriptExportMode.AS, isStatic, methodIndex, scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), fullyQualifiedNames, null, false, new HashSet<>(localData.seenMethods)); - body.toString(localData.abcIndex, path + "/inner", ScriptExportMode.AS, abc, null, writer, fullyQualifiedNames, new HashSet<>(localData.seenMethods)); + List callStack = new ArrayList<>(localData.callStack); + callStack.add(body); + body.convert(callStack, localData.abcIndex, new ConvertData(), path + "/inner", ScriptExportMode.AS, isStatic, methodIndex, scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), fullyQualifiedNames, null, false, new HashSet<>(localData.seenMethods)); + body.toString(callStack, localData.abcIndex, path + "/inner", ScriptExportMode.AS, abc, null, writer, fullyQualifiedNames, new HashSet<>(localData.seenMethods)); } writer.endBlock(); writer.endMethod(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index bce844be4..d4ef4ab75 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -1312,9 +1312,10 @@ public class AVM2SourceGenerator implements SourceGenerator { List initt = new ArrayList<>(); initt.add(ci.abc.class_info.get(ci.index).static_traits); - + List callStack = new ArrayList<>(); + callStack.add(pcinit); try { - pcinit.convert(null, d, "-", ScriptExportMode.AS, true, mi, -1, ci.index, ci.abc, null, new ScopeStack(), GraphTextWriter.TRAIT_CLASS_INITIALIZER, new NulWriter(), new ArrayList<>(), initt, false, new HashSet<>()); + pcinit.convert(callStack, null, d, "-", ScriptExportMode.AS, true, mi, -1, ci.index, ci.abc, null, new ScopeStack(), GraphTextWriter.TRAIT_CLASS_INITIALIZER, new NulWriter(), new ArrayList<>(), initt, false, new HashSet<>()); //FIXME! Add skinparts from _skinParts attribute of parent class!!! } catch (InterruptedException ex) { Logger.getLogger(AVM2SourceGenerator.class.getName()).log(Level.SEVERE, "Getting parent skinparts interrupted", ex); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 6851e4257..e3615ad22 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -287,7 +287,7 @@ public final class MethodBody implements Cloneable { return ret; } - public void convert(AbcIndexing abcIndex, final ConvertData convertData, final String path, ScriptExportMode exportMode, final boolean isStatic, final int methodIndex, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ScopeStack scopeStack, final int initializerType, final NulWriter writer, final List fullyQualifiedNames, final List initTraits, boolean firstLevel, Set seenMethods) throws InterruptedException { + public void convert(List callStack, AbcIndexing abcIndex, final ConvertData convertData, final String path, ScriptExportMode exportMode, final boolean isStatic, final int methodIndex, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ScopeStack scopeStack, final int initializerType, final NulWriter writer, final List fullyQualifiedNames, final List initTraits, boolean firstLevel, Set seenMethods) throws InterruptedException { seenMethods.add(this.method_info); if (debugMode) { System.err.println("Decompiling " + path); @@ -310,10 +310,10 @@ public final class MethodBody implements Cloneable { HashMap localRegNames = getLocalRegNames(abc); List convertedItems1; try (Statistics s = new Statistics("AVM2Code.toGraphTargetItems")) { - convertedItems1 = converted.getCode().toGraphTargetItems(abcIndex, convertData.thisHasDefaultToPrimitive, convertData, path, methodIndex, isStatic, scriptIndex, classIndex, abc, converted, localRegNames, scopeStack, initializerType, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap<>(), converted.getCode().visitCode(converted)); + convertedItems1 = converted.getCode().toGraphTargetItems(callStack, abcIndex, convertData.thisHasDefaultToPrimitive, convertData, path, methodIndex, isStatic, scriptIndex, classIndex, abc, converted, localRegNames, scopeStack, initializerType, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap<>(), converted.getCode().visitCode(converted)); } try (Statistics s = new Statistics("Graph.graphToString")) { - Graph.graphToString(convertedItems1, writer, LocalData.create(abcIndex, abc, localRegNames, fullyQualifiedNames, seenMethods)); + Graph.graphToString(convertedItems1, writer, LocalData.create(callStack, abcIndex, abc, localRegNames, fullyQualifiedNames, seenMethods)); } convertedItems = convertedItems1; } @@ -345,7 +345,7 @@ public final class MethodBody implements Cloneable { } } - public GraphTextWriter toString(AbcIndexing abcIndex, final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final GraphTextWriter writer, final List fullyQualifiedNames, Set seenMethods) throws InterruptedException { + public GraphTextWriter toString(List callStack, AbcIndexing abcIndex, final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final GraphTextWriter writer, final List fullyQualifiedNames, Set seenMethods) throws InterruptedException { seenMethods.add(method_info); if (exportMode != ScriptExportMode.AS) { @@ -370,7 +370,7 @@ public final class MethodBody implements Cloneable { writer.appendNoHilight(this.method_info); writer.newLine(); } - Graph.graphToString(convertedItems, writer, LocalData.create(abcIndex, abc, localRegNames, fullyQualifiedNames, seenMethods)); + Graph.graphToString(convertedItems, writer, LocalData.create(callStack, abcIndex, abc, localRegNames, fullyQualifiedNames, seenMethods)); //writer.endMethod(); } else if (convertException instanceof TimeoutException) { // exception was logged in convert method @@ -420,14 +420,14 @@ public final class MethodBody implements Cloneable { return body; } - public String toSource(AbcIndexing abcIndex, int scriptIndex, Set seenMethods) { + public String toSource(List callStack, AbcIndexing abcIndex, int scriptIndex, Set seenMethods) { ConvertData convertData = new ConvertData(); convertData.deobfuscationMode = 0; try { - convert(abcIndex, convertData, "", ScriptExportMode.AS, false, method_info, 0, 0, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, seenMethods); + convert(callStack, abcIndex, convertData, "", ScriptExportMode.AS, false, method_info, 0, 0, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, seenMethods); HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); writer.indent().indent().indent(); - toString(abcIndex, "", ScriptExportMode.AS, abc, null, writer, new ArrayList<>(), seenMethods); + toString(callStack, abcIndex, "", ScriptExportMode.AS, abc, null, writer, new ArrayList<>(), seenMethods); writer.unindent().unindent().unindent(); return writer.toString(); } catch (InterruptedException ex) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index 61a091777..05cb34b62 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -146,7 +146,9 @@ public class TraitClass extends Trait implements TraitWithSlot { if (exportMode != ScriptExportMode.AS_METHOD_STUBS) { if (!classInitializerIsEmpty) { writer.startBlock(); - abc.bodies.get(bodyIndex).toString(abcIndex, path +/*packageName +*/ "/" + instanceInfoName + ".staticinitializer", exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(abc.bodies.get(bodyIndex)); + abc.bodies.get(bodyIndex).toString(callStack, abcIndex, path +/*packageName +*/ "/" + instanceInfoName + ".staticinitializer", exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); writer.endBlock(); } else { //Note: There must be trait/method highlight even if the initializer is empty to TraitList in GUI to work correctly @@ -194,7 +196,9 @@ public class TraitClass extends Trait implements TraitWithSlot { writer.appendNoHilight(")").startBlock(); if (exportMode != ScriptExportMode.AS_METHOD_STUBS) { if (body != null) { - body.toString(abcIndex, path +/*packageName +*/ "/" + instanceInfoName + ".initializer", exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(body); + body.toString(callStack, abcIndex, path +/*packageName +*/ "/" + instanceInfoName + ".initializer", exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); } } @@ -244,7 +248,9 @@ public class TraitClass extends Trait implements TraitWithSlot { writer.mark(); List ts = new ArrayList<>(); ts.add(classInfo.static_traits); - abc.bodies.get(bodyIndex).convert(abcIndex, convertData, path +/*packageName +*/ "/" + instanceInfoName + ".staticinitializer", exportMode, true, classInfo.cinit_index, scriptIndex, class_info, abc, this, new ScopeStack(), GraphTextWriter.TRAIT_CLASS_INITIALIZER, writer, fullyQualifiedNames, ts, true, new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(abc.bodies.get(bodyIndex)); + abc.bodies.get(bodyIndex).convert(callStack, abcIndex, convertData, path +/*packageName +*/ "/" + instanceInfoName + ".staticinitializer", exportMode, true, classInfo.cinit_index, scriptIndex, class_info, abc, this, new ScopeStack(), GraphTextWriter.TRAIT_CLASS_INITIALIZER, writer, fullyQualifiedNames, ts, true, new HashSet<>()); classInitializerIsEmpty = !writer.getMark(); } @@ -255,7 +261,9 @@ public class TraitClass extends Trait implements TraitWithSlot { List ts = new ArrayList<>(); ts.add(instanceInfo.instance_traits); MethodBody constructorBody = abc.bodies.get(bodyIndex); - constructorBody.convert(abcIndex, convertData, path +/*packageName +*/ "/" + instanceInfoName + ".initializer", exportMode, false, instanceInfo.iinit_index, scriptIndex, class_info, abc, this, new ScopeStack(), GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, writer, fullyQualifiedNames, ts, true, new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(constructorBody); + constructorBody.convert(callStack, abcIndex, convertData, path +/*packageName +*/ "/" + instanceInfoName + ".initializer", exportMode, false, instanceInfo.iinit_index, scriptIndex, class_info, abc, this, new ScopeStack(), GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, writer, fullyQualifiedNames, ts, true, new HashSet<>()); if (convertData.ignoreFrameScripts) { //find all addFrameScript(xx,this.method) in constructor diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java index bb5cff694..d7b68e43d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java @@ -90,8 +90,10 @@ public class TraitFunction extends Trait implements TraitWithSlot { writer.startBlock(); int bodyIndex = abc.findBodyIndex(method_info); if (bodyIndex != -1) { - //writeUses(scriptIndex, classIndex, isStatic, abc, writer); - abc.bodies.get(bodyIndex).toString(abcIndex,path + "." + abc.constants.getMultiname(name_index).getName(abc.constants, fullyQualifiedNames, false, true), exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); + //writeUses(scriptIndex, classIndex, isStatic, abc, writer); + List callStack = new ArrayList<>(); + callStack.add(abc.bodies.get(bodyIndex)); + abc.bodies.get(bodyIndex).toString(callStack, abcIndex,path + "." + abc.constants.getMultiname(name_index).getName(abc.constants, fullyQualifiedNames, false, true), exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); } writer.endBlock(); @@ -108,7 +110,9 @@ public class TraitFunction extends Trait implements TraitWithSlot { convertHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); int bodyIndex = abc.findBodyIndex(method_info); if (bodyIndex != -1) { - abc.bodies.get(bodyIndex).convert(abcIndex, convertData, path + "." + abc.constants.getMultiname(name_index).getName(abc.constants, fullyQualifiedNames, false, true), exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, new ScopeStack(), 0, writer, fullyQualifiedNames, null, true, new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(abc.bodies.get(bodyIndex)); + abc.bodies.get(bodyIndex).convert(callStack, abcIndex, convertData, path + "." + abc.constants.getMultiname(name_index).getName(abc.constants, fullyQualifiedNames, false, true), exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, new ScopeStack(), 0, writer, fullyQualifiedNames, null, true, new HashSet<>()); } writer.endMethod(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java index 51bc0ba67..7b91eefcc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java @@ -118,7 +118,9 @@ public class TraitMethodGetterSetter extends Trait { if (exportMode != ScriptExportMode.AS_METHOD_STUBS) { if (!(classIndex != -1 && abc.instance_info.get(classIndex).isInterface() || bodyIndex == -1)) { if (bodyIndex != -1) { - abc.bodies.get(bodyIndex).convert(abcIndex, convertData, path, exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, new ScopeStack(), 0, writer, fullyQualifiedNames, null, true, new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(abc.bodies.get(bodyIndex)); + abc.bodies.get(bodyIndex).convert(callStack, abcIndex, convertData, path, exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, new ScopeStack(), 0, writer, fullyQualifiedNames, null, true, new HashSet<>()); } } } @@ -146,7 +148,9 @@ public class TraitMethodGetterSetter extends Trait { } if (bodyIndex != -1) { //writeUses(scriptIndex, classIndex, isStatic, abc, writer); - abc.bodies.get(bodyIndex).toString(abcIndex, path, exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(abc.bodies.get(bodyIndex)); + abc.bodies.get(bodyIndex).toString(callStack, abcIndex, path, exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>()); } } else { String retTypeRaw = abc.method_info.get(method_info).getReturnTypeRaw(abc.constants, fullyQualifiedNames); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java index 9c66a821b..9f782d06d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java @@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.NewFunctionAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.types.AssignedValue; import com.jpexs.decompiler.flash.abc.types.ConvertData; +import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.ValueKind; @@ -135,7 +136,9 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { writer.newLine(); } if (exportMode != ScriptExportMode.AS_METHOD_STUBS) { - assignment.value.toString(writer, LocalData.create(abcIndex, abc, new HashMap<>(), fullyQualifiedNames, new HashSet<>())); + List callStack = new ArrayList<>(); + callStack.add(abc.bodies.get(abc.findBodyIndex(assignment.method))); + assignment.value.toString(writer, LocalData.create(callStack, abcIndex, abc, new HashMap<>(), fullyQualifiedNames, new HashSet<>())); } writer.endMethod(); writer.endTrait(); @@ -175,7 +178,10 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { if (convertData.assignedValues.containsKey(this)) { GraphTargetItem val = convertData.assignedValues.get(this).value; if (val instanceof NewFunctionAVM2Item) { - return val.toString(writer, LocalData.create(abcIndex, abc, new HashMap<>(), fullyQualifiedNames, new HashSet<>())); + List callStack = new ArrayList<>(); + AssignedValue assignment = convertData.assignedValues.get(this); + callStack.add(abc.bodies.get(abc.findBodyIndex(assignment.method))); + return val.toString(writer, LocalData.create(callStack, abcIndex, abc, new HashMap<>(), fullyQualifiedNames, new HashSet<>())); } } getNameStr(writer, abc, fullyQualifiedNames); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java index 2e016aa6f..c6db6385e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/AS3ScriptExporter.java @@ -34,6 +34,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.ThisAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.DeclarationAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.types.ConvertData; +import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; @@ -107,7 +108,9 @@ public class AS3ScriptExporter { StringBuilder out = new StringBuilder(); int method = t.method_info; try { - pack.abc.findBody(method).convert(abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, method, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(pack.abc.findBody(method)); + pack.abc.findBody(method).convert(callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, method, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()); List ci = pack.abc.findBody(method).convertedItems; if (!ci.isEmpty()) { @@ -180,7 +183,9 @@ public class AS3ScriptExporter { StringBuilder out = new StringBuilder(); int method = t.method_info; try { - pack.abc.findBody(method).convert(abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, method, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()/*??*/); + List callStack = new ArrayList<>(); + callStack.add(pack.abc.findBody(method)); + pack.abc.findBody(method).convert(callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, method, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()/*??*/); List ci = pack.abc.findBody(method).convertedItems; if (!ci.isEmpty() && (ci.get(0) instanceof DeclarationAVM2Item)) { @@ -271,7 +276,9 @@ public class AS3ScriptExporter { int iinit = pack.abc.instance_info.get(cindex).iinit_index; try { - pack.abc.findBody(iinit).convert(abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, iinit, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(pack.abc.findBody(iinit)); + pack.abc.findBody(iinit).convert(callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, iinit, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()); List iinitBody = pack.abc.findBody(iinit).convertedItems; for (GraphTargetItem it : iinitBody) { if (it instanceof InitPropertyAVM2Item) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index 49d5e9ed1..8287c5d36 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -2626,7 +2626,9 @@ public class XFLConverter { int constructorMethodIndex = instanceInfo.iinit_index; MethodBody constructorBody = abc.findBody(constructorMethodIndex); try { - constructorBody.convert(abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(constructorBody); + constructorBody.convert(callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()); Map frameToTraitMultiname = new HashMap<>(); @@ -2692,9 +2694,11 @@ public class XFLConverter { MethodBody frameBody = abc.findBody(methodIndex); StringBuilder scriptBuilder = new StringBuilder(); - frameBody.convert(abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, methodIndex, pack.scriptIndex, classIndex, abc, methodTrait, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()); + callStack = new ArrayList<>(); + callStack.add(frameBody); + frameBody.convert(callStack, abcIndex, new ConvertData(), "??", ScriptExportMode.AS, false, methodIndex, pack.scriptIndex, classIndex, abc, methodTrait, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()); StringBuilderTextWriter writer = new StringBuilderTextWriter(Configuration.getCodeFormatting(), scriptBuilder); - frameBody.toString(abcIndex, "??", ScriptExportMode.AS, abc, methodTrait, writer, new ArrayList<>(), new HashSet<>()); + frameBody.toString(callStack, abcIndex, "??", ScriptExportMode.AS, abc, methodTrait, writer, new ArrayList<>(), new HashSet<>()); String script = scriptBuilder.toString(); ret.put(frame, script); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LocalData.java index 567f8ad46..5d4c9227d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LocalData.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.graph.model; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; +import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.action.model.ConstantPool; import com.jpexs.decompiler.graph.DottedChain; import java.util.HashMap; @@ -39,6 +40,8 @@ public class LocalData { public AVM2ConstantPool constantsAvm2; public AbcIndexing abcIndex; + + public List callStack; public HashMap localRegNames; @@ -54,7 +57,7 @@ public class LocalData { return localData; } - public static LocalData create(AbcIndexing abcIndex, ABC abc, HashMap localRegNames, List fullyQualifiedNames, Set seenMethods) { + public static LocalData create(List callStack, AbcIndexing abcIndex, ABC abc, HashMap localRegNames, List fullyQualifiedNames, Set seenMethods) { LocalData localData = new LocalData(); localData.abc = abc; localData.constantsAvm2 = abc.constants; @@ -62,6 +65,7 @@ public class LocalData { localData.fullyQualifiedNames = fullyQualifiedNames; localData.seenMethods = seenMethods; localData.abcIndex = abcIndex; + localData.callStack = callStack; return localData; } } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java index 7ff00cea9..6ac857238 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.types.ConvertData; +import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.traits.Traits; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; @@ -108,9 +109,11 @@ public abstract class ActionScript3DecompileTestBase extends ActionScriptTestBas Configuration.autoDeobfuscate.set(methodName.toLowerCase().contains("obfus")); - abc.bodies.get(bodyIndex).convert(swf.getAbcIndex(), new ConvertData(), "run", ScriptExportMode.AS, isStatic, abc.bodies.get(bodyIndex).method_info, scriptIndex, clsIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), ts, true, new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(abc.bodies.get(bodyIndex)); + abc.bodies.get(bodyIndex).convert(callStack, swf.getAbcIndex(), new ConvertData(), "run", ScriptExportMode.AS, isStatic, abc.bodies.get(bodyIndex).method_info, scriptIndex, clsIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), ts, true, new HashSet<>()); writer = new HighlightedTextWriter(new CodeFormatting(), false); - abc.bodies.get(bodyIndex).toString(swf.getAbcIndex(), "run", ScriptExportMode.AS, abc, null, writer, new ArrayList<>(), new HashSet<>()); + abc.bodies.get(bodyIndex).toString(callStack, swf.getAbcIndex(), "run", ScriptExportMode.AS, abc, null, writer, new ArrayList<>(), new HashSet<>()); } catch (InterruptedException ex) { fail(); return; diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java index cfa2aa708..026360c1d 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java @@ -145,8 +145,10 @@ public class AS3Generator { Configuration.autoDeobfuscate.set(clsName.toLowerCase().contains("obfus")); - b.convert(swf.getAbcIndex(),new ConvertData(), "", ScriptExportMode.AS, false, ((TraitMethodGetterSetter) t).method_info, pack.scriptIndex, classId, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), ts, true, new HashSet<>()); - b.toString(swf.getAbcIndex(), "", ScriptExportMode.AS, abc, null, src, new ArrayList<>(), new HashSet<>()); + List callStack = new ArrayList<>(); + callStack.add(b); + b.convert(callStack, swf.getAbcIndex(),new ConvertData(), "", ScriptExportMode.AS, false, ((TraitMethodGetterSetter) t).method_info, pack.scriptIndex, classId, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), ts, true, new HashSet<>()); + b.toString(callStack, swf.getAbcIndex(), "", ScriptExportMode.AS, abc, null, src, new ArrayList<>(), new HashSet<>()); String[] srcs = src.toString().split("[\r\n]+"); for (int i = 0; i < srcs.length; i++) { String ss = srcs[i];