Merge origin/master

This commit is contained in:
Jindra Petřík
2015-07-04 15:21:55 +02:00
14 changed files with 3416 additions and 3268 deletions

View File

@@ -1,285 +1,306 @@
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc;
import com.jpexs.decompiler.flash.abc.types.Decimal;
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
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;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
import com.jpexs.helpers.utf8.Utf8Helper;
import java.io.IOException;
import java.io.OutputStream;
public class ABCOutputStream extends OutputStream {
private final OutputStream os;
public ABCOutputStream(OutputStream os) {
this.os = os;
}
@Override
public void write(int b) throws IOException {
os.write(b);
}
public void writeU30(long value) throws IOException {
writeS32(value);
/*boolean loop = true;
boolean underZero=value<0;
if(underZero){
value = value & 0xFFFFFFFF;
}else{
value = value & 0x7FFFFFFF;
}
do {
int ret = (int) (value & 0x7F);
if (value < 0x80) {
loop = false;
}
if (value > 0x7F) {
ret += 0x80;
}
write(ret);
value = value >> 7;
} while (loop);
*/
}
public void writeU32(long value) throws IOException {
boolean loop = true;
value &= 0xFFFFFFFF;
do {
int ret = (int) (value & 0x7F);
if (value < 0x80) {
loop = false;
}
if (value > 0x7F) {
ret += 0x80;
}
write(ret);
value >>= 7;
} while (loop);
}
public void writeS24(long value) throws IOException {
int ret = (int) (value & 0xff);
write(ret);
value >>= 8;
ret = (int) (value & 0xff);
write(ret);
value >>= 8;
ret = (int) (value & 0xff);
write(ret);
}
public void writeS32(long value) throws IOException {
boolean belowZero = value < 0;
/*if (belowZero) {
value = -value;
}*/
int bitcount = 0;
boolean loop = true;
//value = value & 0xFFFFFFFF;
do {
bitcount += 7;
int ret = (int) (value & 0x7F);
if (value < 0x80) {
if (belowZero) { //&& bitcount < 35
ret += 0x80;
} else {
loop = false;
}
} else {
ret += 0x80;
}
if (bitcount == 35) {
ret &= 0xf;
}
write(ret);
if (bitcount == 35) {
break;
}
value >>= 7;
} while (loop);
}
public void writeLong(long value) throws IOException {
byte[] writeBuffer = new byte[8];
writeBuffer[7] = (byte) (value >>> 56);
writeBuffer[6] = (byte) (value >>> 48);
writeBuffer[5] = (byte) (value >>> 40);
writeBuffer[4] = (byte) (value >>> 32);
writeBuffer[3] = (byte) (value >>> 24);
writeBuffer[2] = (byte) (value >>> 16);
writeBuffer[1] = (byte) (value >>> 8);
writeBuffer[0] = (byte) (value);
write(writeBuffer);
}
public void writeDouble(double value) throws IOException {
writeLong(Double.doubleToLongBits(value));
}
public void writeU8(int value) throws IOException {
write(value);
}
public void writeU16(int value) throws IOException {
write(value & 0xff);
write((value >> 8) & 0xff);
}
public void writeString(String s) throws IOException {
byte[] sbytes = Utf8Helper.getBytes(s);
writeU30(sbytes.length);
write(sbytes);
}
public void writeNamespace(Namespace ns) throws IOException {
write(ns.kind);
boolean found = false;
for (int k = 0; k < Namespace.nameSpaceKinds.length; k++) {
if (Namespace.nameSpaceKinds[k] == ns.kind) {
writeU30(ns.name_index);
found = true;
break;
}
}
if (!found) {
throw new RuntimeException("Invalid ns kind:" + ns.kind);
}
}
public void writeMultiname(Multiname m) throws IOException {
writeU8(m.kind);
if ((m.kind == 7) || (m.kind == 0xd)) { // CONSTANT_QName and CONSTANT_QNameA.
writeU30(m.namespace_index);
writeU30(m.name_index);
}
if ((m.kind == 9) || (m.kind == 0xe)) { // CONSTANT_Multiname and CONSTANT_MultinameA.
writeU30(m.name_index);
writeU30(m.namespace_set_index);
}
if ((m.kind == 0xf) || (m.kind == 0x10)) { // CONSTANT_RTQName and CONSTANT_RTQNameA
writeU30(m.name_index);
}
if ((m.kind == 0x1B) || (m.kind == 0x1C)) { // CONSTANT_MultinameL and CONSTANT_MultinameLA
writeU30(m.namespace_set_index);
}
if (m.kind == 0x1D) {
writeU30(m.qname_index);
writeU30(m.params.size());
for (int i = 0; i < m.params.size(); i++) {
writeU30(m.params.get(i));
}
}
// kind==0x11,0x12 nothing CONSTANT_RTQNameL and CONSTANT_RTQNameLA.
}
public void writeMethodInfo(MethodInfo mi) throws IOException {
writeU30(mi.param_types.length);
writeU30(mi.ret_type);
for (int i = 0; i < mi.param_types.length; i++) {
writeU30(mi.param_types[i]);
}
writeU30(mi.name_index);
write(mi.flags);
if ((mi.flags & 8) == 8) {
writeU30(mi.optional.length);
for (int i = 0; i < mi.optional.length; i++) {
writeU30(mi.optional[i].value_index);
write(mi.optional[i].value_kind);
}
}
if ((mi.flags & 128) == 128) { // if has_paramnames
for (int i = 0; i < mi.paramNames.length; i++) {
writeU30(mi.paramNames[i]);
}
}
}
public void writeTrait(Trait t) throws IOException {
writeU30(t.name_index);
write((t.kindFlags << 4) + t.kindType);
if (t instanceof TraitSlotConst) {
TraitSlotConst t1 = (TraitSlotConst) t;
writeU30(t1.slot_id);
writeU30(t1.type_index);
writeU30(t1.value_index);
if (t1.value_index != 0) {
write(t1.value_kind);
}
}
if (t instanceof TraitMethodGetterSetter) {
TraitMethodGetterSetter t2 = (TraitMethodGetterSetter) t;
writeU30(t2.disp_id);
writeU30(t2.method_info);
}
if (t instanceof TraitClass) {
TraitClass t3 = (TraitClass) t;
writeU30(t3.slot_id);
writeU30(t3.class_info);
}
if (t instanceof TraitFunction) {
TraitFunction t4 = (TraitFunction) t;
writeU30(t4.slot_id);
writeU30(t4.method_info);
}
if ((t.kindFlags & 4) == 4) {
writeU30(t.metadata.length);
for (int i = 0; i < t.metadata.length; i++) {
writeU30(t.metadata[i]);
}
}
}
public void writeTraits(Traits t) throws IOException {
writeU30(t.traits.size());
for (int i = 0; i < t.traits.size(); i++) {
writeTrait(t.traits.get(i));
}
}
public void writeInstanceInfo(InstanceInfo ii) throws IOException {
writeU30(ii.name_index);
writeU30(ii.super_index);
write(ii.flags);
if ((ii.flags & 8) == 8) {
writeU30(ii.protectedNS);
}
writeU30(ii.interfaces.length);
for (int i = 0; i < ii.interfaces.length; i++) {
writeU30(ii.interfaces[i]);
}
writeU30(ii.iinit_index);
writeTraits(ii.instance_traits);
}
public void writeDecimal(Decimal value) throws IOException {
write(value.data);
}
/*
* Copyright (C) 2010-2015 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc;
import com.jpexs.decompiler.flash.abc.types.Decimal;
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
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;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
import com.jpexs.helpers.utf8.Utf8Helper;
import java.io.IOException;
import java.io.OutputStream;
public class ABCOutputStream extends OutputStream {
private final OutputStream os;
public ABCOutputStream(OutputStream os) {
this.os = os;
}
@Override
public void write(int b) throws IOException {
os.write(b);
}
public void writeU30(long value) throws IOException {
writeS32(value);
/*boolean loop = true;
boolean underZero=value<0;
if(underZero){
value = value & 0xFFFFFFFF;
}else{
value = value & 0x7FFFFFFF;
}
do {
int ret = (int) (value & 0x7F);
if (value < 0x80) {
loop = false;
}
if (value > 0x7F) {
ret += 0x80;
}
write(ret);
value = value >> 7;
} while (loop);
*/
}
public void writeU32(long value) throws IOException {
boolean loop = true;
value &= 0xFFFFFFFF;
do {
int ret = (int) (value & 0x7F);
if (value < 0x80) {
loop = false;
}
if (value > 0x7F) {
ret += 0x80;
}
write(ret);
value >>= 7;
} while (loop);
}
public void writeS24(long value) throws IOException {
int ret = (int) (value & 0xff);
write(ret);
value >>= 8;
ret = (int) (value & 0xff);
write(ret);
value >>= 8;
ret = (int) (value & 0xff);
write(ret);
}
public void writeS32(long value) throws IOException {
boolean belowZero = value < 0;
/*if (belowZero) {
value = -value;
}*/
int bitcount = 0;
boolean loop = true;
//value = value & 0xFFFFFFFF;
do {
bitcount += 7;
int ret = (int) (value & 0x7F);
if (value < 0x80) {
if (belowZero) { //&& bitcount < 35
ret += 0x80;
} else {
loop = false;
}
} else {
ret += 0x80;
}
if (bitcount == 35) {
ret &= 0xf;
}
write(ret);
if (bitcount == 35) {
break;
}
value >>= 7;
} while (loop);
}
public void writeLong(long value) throws IOException {
byte[] writeBuffer = new byte[8];
writeBuffer[7] = (byte) (value >>> 56);
writeBuffer[6] = (byte) (value >>> 48);
writeBuffer[5] = (byte) (value >>> 40);
writeBuffer[4] = (byte) (value >>> 32);
writeBuffer[3] = (byte) (value >>> 24);
writeBuffer[2] = (byte) (value >>> 16);
writeBuffer[1] = (byte) (value >>> 8);
writeBuffer[0] = (byte) (value);
write(writeBuffer);
}
public void writeDouble(double value) throws IOException {
writeLong(Double.doubleToLongBits(value));
}
public void writeU8(int value) throws IOException {
write(value);
}
public void writeU16(int value) throws IOException {
write(value & 0xff);
write((value >> 8) & 0xff);
}
public void writeString(String s) throws IOException {
byte[] sbytes = Utf8Helper.getBytes(s);
writeU30(sbytes.length);
write(sbytes);
}
public void writeNamespace(Namespace ns) throws IOException {
write(ns.kind);
boolean found = false;
for (int k = 0; k < Namespace.nameSpaceKinds.length; k++) {
if (Namespace.nameSpaceKinds[k] == ns.kind) {
writeU30(ns.name_index);
found = true;
break;
}
}
if (!found) {
throw new RuntimeException("Invalid ns kind:" + ns.kind);
}
}
public void writeMultiname(Multiname m) throws IOException {
writeU8(m.kind);
if ((m.kind == 7) || (m.kind == 0xd)) { // CONSTANT_QName and CONSTANT_QNameA.
writeU30(m.namespace_index);
writeU30(m.name_index);
}
if ((m.kind == 9) || (m.kind == 0xe)) { // CONSTANT_Multiname and CONSTANT_MultinameA.
writeU30(m.name_index);
writeU30(m.namespace_set_index);
}
if ((m.kind == 0xf) || (m.kind == 0x10)) { // CONSTANT_RTQName and CONSTANT_RTQNameA
writeU30(m.name_index);
}
if ((m.kind == 0x1B) || (m.kind == 0x1C)) { // CONSTANT_MultinameL and CONSTANT_MultinameLA
writeU30(m.namespace_set_index);
}
if (m.kind == 0x1D) {
writeU30(m.qname_index);
writeU30(m.params.size());
for (int i = 0; i < m.params.size(); i++) {
writeU30(m.params.get(i));
}
}
// kind==0x11,0x12 nothing CONSTANT_RTQNameL and CONSTANT_RTQNameLA.
}
public void writeMethodInfo(MethodInfo mi) throws IOException {
writeU30(mi.param_types.length);
writeU30(mi.ret_type);
for (int i = 0; i < mi.param_types.length; i++) {
writeU30(mi.param_types[i]);
}
writeU30(mi.name_index);
write(mi.flags);
if ((mi.flags & 8) == 8) {
writeU30(mi.optional.length);
for (int i = 0; i < mi.optional.length; i++) {
writeU30(mi.optional[i].value_index);
write(mi.optional[i].value_kind);
}
}
if ((mi.flags & 128) == 128) { // if has_paramnames
for (int i = 0; i < mi.paramNames.length; i++) {
writeU30(mi.paramNames[i]);
}
}
}
public void writeTrait(Trait t) throws IOException {
writeU30(t.name_index);
write((t.kindFlags << 4) + t.kindType);
if (t instanceof TraitSlotConst) {
TraitSlotConst t1 = (TraitSlotConst) t;
writeU30(t1.slot_id);
writeU30(t1.type_index);
writeU30(t1.value_index);
if (t1.value_index != 0) {
write(t1.value_kind);
}
}
if (t instanceof TraitMethodGetterSetter) {
TraitMethodGetterSetter t2 = (TraitMethodGetterSetter) t;
writeU30(t2.disp_id);
writeU30(t2.method_info);
}
if (t instanceof TraitClass) {
TraitClass t3 = (TraitClass) t;
writeU30(t3.slot_id);
writeU30(t3.class_info);
}
if (t instanceof TraitFunction) {
TraitFunction t4 = (TraitFunction) t;
writeU30(t4.slot_id);
writeU30(t4.method_info);
}
if ((t.kindFlags & 4) == 4) {
writeU30(t.metadata.length);
for (int i = 0; i < t.metadata.length; i++) {
writeU30(t.metadata[i]);
}
}
}
public void writeTraits(Traits t) throws IOException {
writeU30(t.traits.size());
for (int i = 0; i < t.traits.size(); i++) {
writeTrait(t.traits.get(i));
}
}
public void writeInstanceInfo(InstanceInfo ii) throws IOException {
writeU30(ii.name_index);
writeU30(ii.super_index);
write(ii.flags);
if ((ii.flags & 8) == 8) {
writeU30(ii.protectedNS);
}
writeU30(ii.interfaces.length);
for (int i = 0; i < ii.interfaces.length; i++) {
writeU30(ii.interfaces[i]);
}
writeU30(ii.iinit_index);
writeTraits(ii.instance_traits);
}
public void writeDecimal(Decimal value) throws IOException {
write(value.data);
}
public static int getU30ByteLength(long value) {
boolean belowZero = value < 0;
int bitcount = 0;
int result = 0;
boolean loop = true;
do {
bitcount += 7;
if (value < 0x80 && !belowZero) {
loop = false;
}
result++;
if (bitcount == 35) {
break;
}
value >>= 7;
} while (loop);
return result;
}
}

View File

@@ -712,14 +712,14 @@ public class AVM2Code implements Cloneable {
}
if (ins.definition instanceof JumpIns) {
try {
pos = adr2pos(pos2adr(pos) + ins.getBytes().length + ins.operands[0]);
pos = adr2pos(pos2adr(pos) + ins.getBytesLength() + ins.operands[0]);
continue;
} catch (ConvertException ex) {
return false;
}
} else if (ins.definition instanceof IfTypeIns) {
try {
int newpos = adr2pos(pos2adr(pos) + ins.getBytes().length + ins.operands[0]);
int newpos = adr2pos(pos2adr(pos) + ins.getBytesLength() + ins.operands[0]);
calculateDebugFileLine(debugFile, debugLine, newpos, abc, seen);
} catch (ConvertException ex) {
return false;
@@ -1115,7 +1115,7 @@ public class AVM2Code implements Cloneable {
writer.appendNoHilight(new DeobfuscatePopIns().instructionName).newLine();
}
if (fixBranch == 0) { // jump
writer.appendNoHilight(new JumpIns().instructionName + " ofs" + Helper.formatAddress(ofs + ins.getBytes().length + ins.operands[0]));
writer.appendNoHilight(new JumpIns().instructionName + " ofs" + Helper.formatAddress(ofs + ins.getBytesLength() + ins.operands[0]));
} else {
// nojump, ignore
}
@@ -1150,7 +1150,7 @@ public class AVM2Code implements Cloneable {
long a = 0;
for (int i = 0; i < code.size(); i++) {
posCache.add(a);
a += code.get(i).getBytes().length;
a += code.get(i).getBytesLength();
}
posCache.add(a);
cacheActual = true;
@@ -1801,7 +1801,7 @@ public class AVM2Code implements Cloneable {
}*/
//Faster, but not so universal
if ((ins.definition instanceof JumpIns) || (ins.definition instanceof IfTypeIns)) {
long target = ins.offset + ins.getBytes().length + ins.operands[0];
long target = ins.offset + ins.getBytesLength() + ins.operands[0];
ins.operands[0] = updater.updateOperandOffset(ins.offset, target, ins.operands[0]);
}
}
@@ -1815,13 +1815,34 @@ public class AVM2Code implements Cloneable {
}
}
public void fixJumps(MethodBody body) {
AVM2Instruction lastInstuction = code.get(code.size() - 1);
final long endOffset = lastInstuction.offset + lastInstuction.getBytesLength();
updateOffsets(new OffsetUpdater() {
@Override
public long updateInstructionOffset(long address) {
return address;
}
@Override
public int updateOperandOffset(long insAddr, long targetAddress, int offset) {
if (targetAddress > endOffset) {
return (int) (offset - targetAddress + endOffset);
}
return offset;
}
}, body);
}
private void checkValidOffsets(MethodBody body) {
updateOffsets(new OffsetUpdater() {
@Override
public long updateInstructionOffset(long offset) {
adr2pos(offset);
return offset;
public long updateInstructionOffset(long address) {
adr2pos(address);
return address;
}
@Override
@@ -1840,7 +1861,7 @@ public class AVM2Code implements Cloneable {
checkValidOffsets(body);
AVM2Instruction ins = code.get(pos);
final long remOffset = ins.offset;
final int byteCount = ins.getBytes().length;
final int byteCount = ins.getBytesLength();
updateOffsets(new OffsetUpdater() {
@Override
public long updateInstructionOffset(long address) {
@@ -1898,19 +1919,19 @@ public class AVM2Code implements Cloneable {
pos = code.size();
}
instruction.offset = code.get(pos).offset;
int oldByteCount = code.get(pos).getBytes().length;
int newByteCount = instruction.getBytes().length;
int oldByteCount = code.get(pos).getBytesLength();
int newByteCount = instruction.getBytesLength();
int byteDelta = newByteCount - oldByteCount;
if (byteDelta != 0) {
updateOffsets(new OffsetUpdater() {
@Override
public long updateInstructionOffset(long addr) {
if (addr > instruction.offset) {
return addr + byteDelta;
public long updateInstructionOffset(long address) {
if (address > instruction.offset) {
return address + byteDelta;
}
return addr;
return address;
}
@Override
@@ -1949,9 +1970,9 @@ public class AVM2Code implements Cloneable {
if (pos > code.size()) {
pos = code.size();
}
final int byteCount = instruction.getBytes().length;
final int byteCount = instruction.getBytesLength();
if (pos == code.size()) {
instruction.offset = code.get(pos - 1).offset + code.get(pos - 1).getBytes().length;
instruction.offset = code.get(pos - 1).offset + code.get(pos - 1).getBytesLength();
} else {
instruction.offset = code.get(pos).offset;
}
@@ -2108,14 +2129,14 @@ public class AVM2Code implements Cloneable {
}
if (ins.definition instanceof JumpIns) {
try {
pos = adr2pos(pos2adr(pos) + ins.getBytes().length + ins.operands[0]);
pos = adr2pos(pos2adr(pos) + ins.getBytesLength() + ins.operands[0]);
continue;
} catch (ConvertException ex) {
return false;
}
} else if (ins.definition instanceof IfTypeIns) {
try {
int newpos = adr2pos(pos2adr(pos) + ins.getBytes().length + ins.operands[0]);
int newpos = adr2pos(pos2adr(pos) + ins.getBytesLength() + ins.operands[0]);
walkCode(stats, newpos, stack, scope, abc);
} catch (ConvertException ex) {
return false;
@@ -2236,14 +2257,14 @@ public class AVM2Code implements Cloneable {
}
if (ins.definition instanceof JumpIns) {
try {
ip = adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]);
ip = adr2pos(pos2adr(ip) + ins.getBytesLength() + ins.operands[0]);
continue;
} catch (ConvertException ex) {
logger.log(Level.FINE, null, ex);
}
} else if (ins.definition instanceof IfTypeIns) {
try {
visitCode(adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]), ip, refs);
visitCode(adr2pos(pos2adr(ip) + ins.getBytesLength() + ins.operands[0]), ip, refs);
} catch (ConvertException ex) {
logger.log(Level.FINE, null, ex);
}
@@ -2304,7 +2325,7 @@ public class AVM2Code implements Cloneable {
}
if (ins.definition instanceof JumpIns) {
try {
ip = adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]);
ip = adr2pos(pos2adr(ip) + ins.getBytesLength() + ins.operands[0]);
prev2 = prev;
prev = ins;
continue;
@@ -2373,7 +2394,7 @@ public class AVM2Code implements Cloneable {
}
}
try {
ret += visitCodeTrap(adr2pos(pos2adr(ip) + ins.getBytes().length + ins.operands[0]), visited, prev, prev2);
ret += visitCodeTrap(adr2pos(pos2adr(ip) + ins.getBytesLength() + ins.operands[0]), visited, prev, prev2);
} catch (ConvertException ex) {
logger.log(Level.FINE, null, ex);
}
@@ -2616,7 +2637,7 @@ public class AVM2Code implements Cloneable {
int csize = code.size();
for (int i = 0; i < csize; i++) {
AVM2Instruction ins = code.get(i);
int insLen = code.get(i).getBytes().length;
int insLen = code.get(i).getBytesLength();
int ofs = pos2adr(i);
if (ins.definition instanceof JumpIns) {
int targetOfs = ofs + insLen + ins.operands[0];
@@ -2650,7 +2671,7 @@ public class AVM2Code implements Cloneable {
int ofs = 0;
for (int i = 0; i < code.size(); i++) {
code.get(i).mappedOffset = ofs;
ofs += code.get(i).getBytes().length;
ofs += code.get(i).getBytesLength();
}
}

View File

@@ -61,7 +61,7 @@ public class AVM2DeobfuscatorJumps extends AVM2DeobfuscatorSimple {
for (int i = 0; i < code.code.size(); i++) {
AVM2Instruction ins = code.code.get(i);
if (ins.definition instanceof JumpIns) {
long targetAddr = ins.offset + ins.operands[0] + ins.getBytes().length;
long targetAddr = ins.offset + ins.operands[0] + ins.getBytesLength();
{
for (int r : refs.get(i)) {
if (r >= 0) { //Not Exception start/end
@@ -70,7 +70,7 @@ public class AVM2DeobfuscatorJumps extends AVM2DeobfuscatorSimple {
if ((srcIns.definition instanceof JumpIns) || ((srcIns.definition instanceof IfTypeIns) && (r != i - 1))) {
{
int oldop = srcIns.operands[0];
srcIns.operands[0] = (int) (targetAddr - (srcIns.offset + srcIns.getBytes().length));
srcIns.operands[0] = (int) (targetAddr - (srcIns.offset + srcIns.getBytesLength()));
if (srcIns.operands[0] != oldop) {
found = true;
}
@@ -85,5 +85,4 @@ public class AVM2DeobfuscatorJumps extends AVM2DeobfuscatorSimple {
} while (found);
}
}

View File

@@ -164,7 +164,7 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
if (action.definition instanceof JumpIns) {
long address = action.offset + action.getBytes().length + action.operands[0];
long address = action.offset + action.getBytesLength() + action.operands[0];
idx = code.adr2pos(address);//code.indexOf(code.getByAddress(address));
if (idx == -1) {
throw new TranslateException("Jump target not found: " + address);

View File

@@ -324,7 +324,7 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
boolean ifed = false;
if (def instanceof JumpIns) {
//ActionJump jump = (ActionJump) action;
long address = action.offset + action.getBytes().length + action.operands[0];
long address = action.offset + action.getBytesLength() + action.operands[0];
idx = code.adr2pos(address);
if (idx == -1) {
@@ -334,7 +334,7 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
//ActionIf aif = (ActionIf) action;
GraphTargetItem top = stack.pop();
Object res = top.getResult();
long address = action.offset + action.getBytes().length + action.operands[0];
long address = action.offset + action.getBytesLength() + action.operands[0];
int nidx = code.adr2pos(address);//code.indexOf(code.getByAddress(address));
AVM2Instruction tarIns = code.code.get(nidx);
@@ -345,11 +345,11 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
AVM2Instruction jumpIns = new AVM2Instruction(0, new JumpIns(), new int[]{0});
//jumpIns.operands[0] = action.operands[0] /*- action.getBytes().length*/ + jumpIns.getBytes().length;
code.replaceInstruction(idx, jumpIns, body);
jumpIns.operands[0] = (int) (tarIns.offset - jumpIns.offset - jumpIns.getBytes().length);
jumpIns.operands[0] = (int) (tarIns.offset - jumpIns.offset - jumpIns.getBytesLength());
code.insertInstruction(idx, new AVM2Instruction(action.offset, new DeobfuscatePopIns(), new int[]{}), true, body);
idx = code.adr2pos(jumpIns.offset + jumpIns.getBytes().length + jumpIns.operands[0]);
idx = code.adr2pos(jumpIns.offset + jumpIns.getBytesLength() + jumpIns.operands[0]);
} else {
code.replaceInstruction(idx, new AVM2Instruction(action.offset, new DeobfuscatePopIns(), new int[]{}), body);
//action.definition = new DeobfuscatePopIns();
@@ -399,9 +399,11 @@ public class AVM2DeobfuscatorSimple implements SWFDecompilerListener {
}
public void deobfuscate(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException {
removeUnreachableActions(body.getCode(), cpool, trait, minfo, body);
AVM2Code code = body.getCode();
code.fixJumps(body);
removeUnreachableActions(code, cpool, trait, minfo, body);
removeObfuscationIfs(classIndex, isStatic, scriptIndex, abc, cpool, trait, minfo, body);
removeZeroJumps(body.getCode(), body);
removeZeroJumps(code, body);
}
class ExecutionResult {

View File

@@ -36,7 +36,6 @@ import com.jpexs.decompiler.flash.abc.avm2.model.HasNextAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.InAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.NextNameAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.NextValueAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item;
@@ -71,7 +70,6 @@ import com.jpexs.decompiler.graph.model.IfItem;
import com.jpexs.decompiler.graph.model.LoopItem;
import com.jpexs.decompiler.graph.model.NotItem;
import com.jpexs.decompiler.graph.model.PopItem;
import com.jpexs.decompiler.graph.model.PushItem;
import com.jpexs.decompiler.graph.model.SwitchItem;
import com.jpexs.decompiler.graph.model.WhileItem;
import java.util.ArrayList;
@@ -231,7 +229,7 @@ public class AVM2Graph extends Graph {
AVM2Instruction jmpIns = this.avm2code.code.get(code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end)));
if (jmpIns.definition instanceof JumpIns) {
finStart = code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytes().length + jmpIns.operands[0]);
finStart = code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytesLength() + jmpIns.operands[0]);
GraphPart fpart = null;
for (GraphPart p : allParts) {
@@ -247,7 +245,7 @@ public class AVM2Graph extends Graph {
if (this.avm2code.code.get(f).definition instanceof LookupSwitchIns) {
AVM2Instruction swins = this.avm2code.code.get(f);
if (swins.operands.length >= 3) {
if (swins.operands[0] == swins.getBytes().length) {
if (swins.operands[0] == swins.getBytesLength()) {
if (code.adr2pos(code.pos2adr(f) + swins.operands[2]) < finStart) {
//st.push(new ExceptionAVM2Item(body.exceptions[e]));
GraphPart fepart = null;
@@ -694,7 +692,7 @@ public class AVM2Graph extends Graph {
if (true) { //afterCatchPos + 1 == code.adr2pos(this.code.fixAddrAfterDebugLine(body.exceptions[e].end))) {
AVM2Instruction jmpIns = this.avm2code.code.get(avm2code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end)));
if (jmpIns.definition instanceof JumpIns) {
int finStart = avm2code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytes().length + jmpIns.operands[0]);
int finStart = avm2code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytesLength() + jmpIns.operands[0]);
if (!finallyJumps.containsKey(e)) {
finallyJumps.put(e, new ArrayList<>());
}

View File

@@ -92,11 +92,11 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
aos.writeU8(0xff & operands[i]);
break;
case AVM2Code.OPT_CASE_OFFSETS:
aos.writeU30(operands[i]); //case count
for (int j = i + 1; j < operands.length; j++) {
aos.writeS24(operands[j]);
}
break;
}
}
@@ -106,6 +106,40 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
return bos.toByteArray();
}
public int getBytesLength() {
int refCnt = getBytes().length;
int cnt = 1;
for (int i = 0; i < definition.operands.length; i++) {
int opt = definition.operands[i] & 0xff00;
switch (opt) {
case AVM2Code.OPT_S24:
cnt += 3;
break;
case AVM2Code.OPT_U30:
cnt += ABCOutputStream.getU30ByteLength(operands[i]);
break;
case AVM2Code.OPT_U8:
cnt++;
break;
case AVM2Code.OPT_BYTE:
cnt++;
break;
case AVM2Code.OPT_CASE_OFFSETS:
cnt += ABCOutputStream.getU30ByteLength(operands[i]); //case count
for (int j = i + 1; j < operands.length; j++) {
cnt += 3;
}
break;
}
}
if (refCnt != cnt) {
throw new Error("aaa");
}
return cnt;
}
@Override
public String toString() {
StringBuilder s = new StringBuilder();
@@ -125,7 +159,7 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
for (int i = 0; i < definition.operands.length; i++) {
switch (definition.operands[i]) {
case AVM2Code.DAT_OFFSET:
ret.add(offset + operands[i] + getBytes().length);
ret.add(offset + operands[i] + getBytesLength());
break;
case AVM2Code.DAT_CASE_BASEOFFSET:
ret.add(offset + operands[i]);
@@ -161,7 +195,7 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
s.add(constants.getDouble(operands[i]));
break;
case AVM2Code.DAT_OFFSET:
s.add(offset + operands[i] + getBytes().length);
s.add(offset + operands[i] + getBytesLength());
break;
case AVM2Code.DAT_CASE_BASEOFFSET:
s.add(offset + operands[i]);
@@ -243,7 +277,7 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
case AVM2Code.DAT_OFFSET:
s.append(" ");
s.append("ofs");
s.append(Helper.formatAddress(offset + operands[i] + getBytes().length));
s.append(Helper.formatAddress(offset + operands[i] + getBytesLength()));
break;
case AVM2Code.DAT_CASE_BASEOFFSET:
s.append(" ");
@@ -338,11 +372,11 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
if (definition instanceof IfTypeIns) {
if (fixedBranch == -1 || fixedBranch == 0) {
ret.add(code.adr2pos(offset + getBytes().length + operands[0]));
ret.add(code.adr2pos(offset + getBytesLength() + operands[0]));
}
if (!(definition instanceof JumpIns)) {
if (fixedBranch == -1 || fixedBranch == 1) {
ret.add(code.adr2pos(offset + getBytes().length));
ret.add(code.adr2pos(offset + getBytesLength()));
}
}
}

View File

@@ -394,7 +394,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
int pos = 0;
for (int a = 0; a < code.size(); a++) {
AVM2Instruction ins = code.get(a);
pos += ins.getBytes().length;
pos += ins.getBytesLength();
if (ins.definition instanceof JumpIns) {
if (ins.definition instanceof ContinueJumpIns) {
if (continueOffset != Integer.MAX_VALUE) {
@@ -924,7 +924,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
List<AVM2Instruction> finallySwitchCmds = new ArrayList<>();
finSwitch = new AVM2Instruction(0, new LookupSwitchIns(), new int[1 + 1 + 1]);
finSwitch.operands[0] = finSwitch.getBytes().length;
finSwitch.operands[0] = finSwitch.getBytesLength();
finSwitch.operands[1] = 0; //switch cnt
List<AVM2Instruction> preFinallySwitch = new ArrayList<>();
@@ -1004,7 +1004,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
continue;
}
}
pos += ins.getBytes().length;
pos += ins.getBytesLength();
}
}
@@ -1028,13 +1028,13 @@ public class AVM2SourceGenerator implements SourceGenerator {
if (wasDef) {
ins.operands[0] = 0;
} else {
ins.operands[0] = finallyPos - (pos + ins.getBytes().length);
ins.operands[0] = finallyPos - (pos + ins.getBytesLength());
}
ins.definition = new JumpIns();
switchLoc.add(pos + ins.getBytes().length + betLen - switchPos);
switchLoc.add(pos + ins.getBytesLength() + betLen - switchPos);
}
}
pos += ins.getBytes().length;
pos += ins.getBytesLength();
}
if (defPos == switchLoc.size() - 1) {
switchLoc.add(defLoc);
@@ -1043,7 +1043,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
}
finSwitch.operands = new int[1 + 1 + switchLoc.size()];
pushDefIns.operands[0] = defPos + 1;
int afterLoc = finSwitch.getBytes().length;
int afterLoc = finSwitch.getBytesLength();
finSwitch.operands[0] = afterLoc;
finSwitch.operands[1] = switchLoc.size() - 1;
for (int j = 0; j < switchLoc.size(); j++) {
@@ -1806,7 +1806,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
i--;
continue;
}
offset += ins.getBytes().length;
offset += ins.getBytesLength();
}
mbody.markOffsets();

View File

@@ -40,4 +40,9 @@ public class ExceptionMarkAVM2Instruction extends AVM2Instruction {
public byte[] getBytes() {
return new byte[0];
}
@Override
public int getBytesLength() {
return 0;
}
}

View File

@@ -146,7 +146,7 @@ public final class MethodBody implements Cloneable {
long offset = 0;
for (int i = 0; i < getCode().code.size(); i++) {
getCode().code.get(i).offset = offset;
offset += getCode().code.get(i).getBytes().length;
offset += getCode().code.get(i).getBytesLength();
}
}
@@ -241,7 +241,7 @@ public final class MethodBody implements Cloneable {
}
public void convert(final String path, ScriptExportMode exportMode, final boolean isStatic, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final AVM2ConstantPool constants, final List<MethodInfo> method_info, final ScopeStack scopeStack, final boolean isStaticInitializer, final GraphTextWriter writer, final List<String> fullyQualifiedNames, final Traits initTraits, boolean firstLevel) throws InterruptedException {
/*if (!path.contains("testCatchFinally")) {
/*if (!path.contains("forcedWidth")) {
return;
}*/
if (debugMode) {
@@ -290,7 +290,7 @@ public final class MethodBody implements Cloneable {
}
public GraphTextWriter toString(final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final AVM2ConstantPool constants, final List<MethodInfo> method_info, final GraphTextWriter writer, final List<String> fullyQualifiedNames) throws InterruptedException {
/*if (!path.contains("testCatchFinally")) {
/*if (!path.contains("forcedWidth")) {
return writer;
}*/
if (exportMode != ScriptExportMode.AS) {