diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java index 1b7283dda..a0c7e3031 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -661,14 +661,14 @@ public class ABC { aos.writeTraits(si.traits); } - aos.writeU30(bodies.size()); + aos.writeU30(bodies.size()); for (MethodBody mb : bodies) { aos.writeU30(mb.method_info); aos.writeU30(mb.max_stack); aos.writeU30(mb.max_regs); aos.writeU30(mb.init_scope_depth); aos.writeU30(mb.max_scope_depth); - byte[] codeBytes = mb.getCode().getBytes(); + byte[] codeBytes = mb.getCode().getBytes(); aos.writeU30(codeBytes.length); aos.write(codeBytes); aos.writeU30(mb.exceptions.length); 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 3b0999aec..72804cbe1 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 @@ -784,75 +784,62 @@ public class AVM2Code implements Cloneable { return null; } - public AVM2Code(ABCInputStream ais) throws IOException { + public AVM2Code(ABCInputStream ais) throws IOException { + //Note: special jump handling like in AS1/2 is not needed as code must pass FlashPlayer verification + Map codeMap = new TreeMap<>(); DumpInfo diParent = ais.dumpInfo; - List addresses = new ArrayList<>(); - addresses.add(ais.getPosition()); - while (!addresses.isEmpty()) { - long address = addresses.remove(0); - if (codeMap.containsKey(address)) { - continue; - } - try { - ais.seek(address); - while (ais.available() > 0) { - DumpInfo di = ais.newDumpLevel("instruction", "instruction"); - long startOffset = ais.getPosition(); - int instructionCode = ais.read("instructionCode"); - InstructionDefinition instr = instructionSetByCode[instructionCode]; - if (di != null) { - di.name = instr.instructionName; - } - if (instr != null) { - int[] actualOperands = null; - if (instructionCode == 0x1b) { //switch - int firstOperand = ais.readS24("default_offset"); - int case_count = ais.readU30("case_count"); - actualOperands = new int[case_count + 3]; - actualOperands[0] = firstOperand; - actualOperands[1] = case_count; - for (int c = 0; c < case_count + 1; c++) { - actualOperands[2 + c] = ais.readS24("actualOperand"); - } - } else { - if (instr.operands.length > 0) { - actualOperands = new int[instr.operands.length]; - for (int op = 0; op < instr.operands.length; op++) { - switch (instr.operands[op] & 0xff00) { - case OPT_U30: - actualOperands[op] = ais.readU30("operand"); - break; - case OPT_U8: - actualOperands[op] = ais.read("operand"); - break; - case OPT_BYTE: - actualOperands[op] = (byte) ais.read("operand"); - break; - case OPT_S24: - actualOperands[op] = ais.readS24("operand"); - break; - } + try { + while (ais.available() > 0) { + DumpInfo di = ais.newDumpLevel("instruction", "instruction"); + long startOffset = ais.getPosition(); + int instructionCode = ais.read("instructionCode"); + InstructionDefinition instr = instructionSetByCode[instructionCode]; + if (di != null) { + di.name = instr.instructionName; + } + if (instr != null) { + int[] actualOperands = null; + if (instructionCode == 0x1b) { //switch + int firstOperand = ais.readS24("default_offset"); + int case_count = ais.readU30("case_count"); + actualOperands = new int[case_count + 3]; + actualOperands[0] = firstOperand; + actualOperands[1] = case_count; + for (int c = 0; c < case_count + 1; c++) { + actualOperands[2 + c] = ais.readS24("operand"); + } + } else { + if (instr.operands.length > 0) { + actualOperands = new int[instr.operands.length]; + for (int op = 0; op < instr.operands.length; op++) { + switch (instr.operands[op] & 0xff00) { + case OPT_U30: + actualOperands[op] = ais.readU30("operand"); + break; + case OPT_U8: + actualOperands[op] = ais.readU8("operand"); + break; + case OPT_BYTE: + actualOperands[op] = (byte) ais.read("operand"); + break; + case OPT_S24: + actualOperands[op] = ais.readS24("operand"); + break; } } } - - if (instr instanceof IfTypeIns) { - long target = ais.getPosition() + actualOperands[0]; - addresses.add(target); - } - codeMap.put(startOffset, new AVM2Instruction(startOffset, instr, actualOperands)); - ais.endDumpLevel(instr.instructionCode); - } else { - ais.endDumpLevel(); - break; // Unknown instructions are ignored (Some of the obfuscators add unknown instructions) - //throw new UnknownInstructionCode(instructionCode); } + + codeMap.put(startOffset, new AVM2Instruction(startOffset, instr, actualOperands)); + ais.endDumpLevel(instr.instructionCode); + } else { + ais.endDumpLevel(); + break; // Unknown instructions are ignored (Some of the obfuscators add unknown instructions) } - } catch (EndOfStreamException ex) { - // lookupswitch obfuscation, ignore - ais.endDumpLevelUntil(diParent); } + } catch (EndOfStreamException ex) { + ais.endDumpLevelUntil(diParent); } code.addAll(codeMap.values()); @@ -1599,6 +1586,7 @@ public class AVM2Code implements Cloneable { prev = ins; } return ret; + } private class Slot { @@ -2256,6 +2244,7 @@ public class AVM2Code implements Cloneable { prev = ins; }; return ret; + } private static class ControlFlowTag { @@ -2483,6 +2472,7 @@ public class AVM2Code implements Cloneable { for (int i = 0; i < code.size(); i++) { code.get(i).mappedOffset = ofs; ofs += code.get(i).getBytes().length; + } }