AS3: Larger classes support

SetSlot fix
This commit is contained in:
Jindra Pet��k
2013-02-09 10:45:23 +01:00
parent 4a387a8df0
commit 2e9e7b4191
8 changed files with 99 additions and 58 deletions
+5 -5
View File
@@ -477,17 +477,17 @@ public class ABC {
if (!s.contains("\r\n")) {
parts = s.split("\n");
}
String ret = "";
StringBuilder ret = new StringBuilder();
for (int i = 0; i < parts.length; i++) {
for (int t = 0; t < tabs; t++) {
ret += IDENT_STRING;
ret.append(IDENT_STRING);
}
ret += parts[i];
ret.append(parts[i]);
if (i < parts.length - 1) {
ret += "\r\n";
ret.append("\r\n");
}
}
return ret;
return ret.toString();
}
public Trait findTraitByTraitId(int classIndex, int traitId) {
@@ -704,11 +704,11 @@ public class AVM2Code implements Serializable {
public String toASMSource(ConstantPool constants, MethodBody body, List<Integer> outputMap) {
invalidateCache();
String ret = "";
StringBuffer ret = new StringBuffer();
String t = "";
for (int e = 0; e < body.exceptions.length; e++) {
ret += "exception " + e + " m[" + body.exceptions[e].name_index + "]\"" + Helper.escapeString(body.exceptions[e].getVarName(constants, new ArrayList<String>())) + "\" "
+ "m[" + body.exceptions[e].type_index + "]\"" + Helper.escapeString(body.exceptions[e].getTypeName(constants, new ArrayList<String>())) + "\"\n";
ret.append("exception " + e + " m[" + body.exceptions[e].name_index + "]\"" + Helper.escapeString(body.exceptions[e].getVarName(constants, new ArrayList<String>())) + "\" "
+ "m[" + body.exceptions[e].type_index + "]\"" + Helper.escapeString(body.exceptions[e].getTypeName(constants, new ArrayList<String>())) + "\"\n");
}
List<Long> offsets = new ArrayList<Long>();
for (AVM2Instruction ins : code) {
@@ -728,21 +728,23 @@ public class AVM2Code implements Serializable {
}
long ofs = 0;
int ip = 0;
int largeLimit = 20000;
boolean markOffsets=code.size()<=largeLimit;
for (AVM2Instruction ins : code) {
if (ins.labelname != null) {
ret += ins.labelname + ":";
ret.append(ins.labelname + ":");
} else if (offsets.contains(ofs)) {
ret += "ofs" + Helper.formatAddress(ofs) + ":";
ret.append("ofs" + Helper.formatAddress(ofs) + ":");
}
for (int e = 0; e < body.exceptions.length; e++) {
if (body.exceptions[e].start == ofs) {
ret += "exceptionstart " + e + ":";
ret.append("exceptionstart " + e + ":");
}
if (body.exceptions[e].end == ofs) {
ret += "exceptionend " + e + ":";
ret.append("exceptionend " + e + ":");
}
if (body.exceptions[e].target == ofs) {
ret += "exceptiontarget " + e + ":";
ret.append("exceptiontarget " + e + ":");
}
}
if (ins.replaceWith != null) {
@@ -753,36 +755,40 @@ public class AVM2Code implements Serializable {
continue;
}
t = Highlighting.hilighOffset("", ins2.mappedOffset>-1?ins2.mappedOffset:ofs) + ins2.toStringNoAddress(constants, new ArrayList<String>()) + " ;copy from " + Helper.formatAddress(pos2adr((Integer) o)) + "\n";
ret += t;
ret.append(t);
outputMap.add((Integer) o);
} else if (o instanceof ControlFlowTag) {
ControlFlowTag cft = (ControlFlowTag) o;
if (cft.name.equals("appendjump")) {
t = "jump ofs" + Helper.formatAddress(pos2adr(cft.value)) + "\n";
ret += t;
ret.append(t);
outputMap.add(-1);
}
if (cft.name.equals("mark")) {
ret += "ofs" + Helper.formatAddress(pos2adr(cft.value)) + ":";
ret.append("ofs" + Helper.formatAddress(pos2adr(cft.value)) + ":");
}
}
}
} else {
if (!ins.isIgnored()) {
String t1 = ins.toStringNoAddress(constants, new ArrayList<String>());
t = ins.toStringNoAddress(constants, new ArrayList<String>());
if (ins.changeJumpTo > -1) {
t1 = ins.definition.instructionName + " ofs" + Helper.formatAddress(pos2adr(ins.changeJumpTo));
t = ins.definition.instructionName + " ofs" + Helper.formatAddress(pos2adr(ins.changeJumpTo));
}
t = Highlighting.hilighOffset("", ins.mappedOffset>-1?ins.mappedOffset:ofs) + t1 + "\n";
ret += t;
if(markOffsets){
t = Highlighting.hilighOffset("", ins.mappedOffset>-1?ins.mappedOffset:ofs) + t + "\n";
}else{
t = t + "\n";
}
ret.append(t);
outputMap.add(ip);
}
}
ofs += ins.getBytes().length;
ip++;
}
return ret;
String r=ret.toString();
return r;
}
private boolean cacheActual = false;
private List<Long> posCache;
@@ -821,12 +827,12 @@ public class AVM2Code implements Serializable {
}
public static String listToString(List<TreeItem> stack, ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
String ret = "";
StringBuffer ret = new StringBuffer();
for (int d = 0; d < stack.size(); d++) {
TreeItem o = stack.get(d);
ret += o.toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n";
ret.append(o.toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n");
}
return ret;
return ret.toString();
}
private static String innerStackToString(List stack) {
@@ -1897,6 +1903,7 @@ public class AVM2Code implements Serializable {
try{
list = Graph.translateViaGraph(path,this, abc, body);
}catch(Exception ex2){
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, "Decompilation error in "+path,ex2);
return "/*\r\n * Decompilation error\r\n * Code may be obfuscated\r\n * Error Message: " + ex2.getMessage() + "\r\n */";
}
/*try{
@@ -1985,7 +1992,7 @@ public class AVM2Code implements Serializable {
}
}
s = listToString(list, constants, localRegNames, fullyQualifiedNames);
s = listToString(list, constants, localRegNames, fullyQualifiedNames);
/*} catch (Exception ex) {
Logger.getLogger(AVM2Code.class.getName()).log(Level.SEVERE, "Error in method "+path, ex);
s = "/ *\r\n * Decompilation error\r\n * Code may be obfuscated\r\n * Error Message: " + ex.getMessage() + "\r\n * /";
@@ -1993,13 +2000,13 @@ public class AVM2Code implements Serializable {
}*/
String sub = "";
StringBuffer sub = new StringBuffer();
int level = 0;
String parts[] = s.split("\r\n");
boolean processLoops = true;
if (processLoops) {
try {
Stack<String> loopStack = new Stack<String>();
@@ -2066,20 +2073,22 @@ public class AVM2Code implements Serializable {
level--;
} else if (strippedP.equals("{")) {
level++;
sub += tabString(level) + parts[p] + "\r\n";
sub.append(tabString(level) + parts[p] + "\r\n");
level++;
} else if (strippedP.equals("}") || strippedP.equals("};")) {
level--;
sub += tabString(level) + parts[p] + "\r\n";
sub.append(tabString(level) + parts[p] + "\r\n");
level--;
} else {
sub += tabString(level) + parts[p] + "\r\n";
sub.append(tabString(level) + parts[p] + "\r\n");
}
}
if (!hilighted) {
sub = Highlighting.stripHilights(sub);
return Highlighting.stripHilights(sub.toString());
}
return sub;
String ret=sub.toString();
return ret;
}
public static void main(String[] args) {
@@ -22,12 +22,14 @@ import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.asdec.abc.avm2.instructions.SetTypeIns;
import com.jpexs.asdec.abc.avm2.treemodel.ClassTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.DecrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.GetSlotTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.IncrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.PostDecrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.PostIncrementTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.SetSlotTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.ThisTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.clauses.ExceptionTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.operations.PreDecrementTreeItem;
@@ -50,24 +52,31 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns {
int slotIndex = ins.operands[0];
TreeItem value = (TreeItem) stack.pop();
TreeItem obj = (TreeItem) stack.pop(); //scopeId
if (obj instanceof ExceptionTreeItem) {
return;
}
//if(value.startsWith("catched ")) return;
Multiname slotname = null;
for (int t = 0; t < body.traits.traits.length; t++) {
if (body.traits.traits[t] instanceof TraitSlotConst) {
if (((TraitSlotConst) body.traits.traits[t]).slot_id == slotIndex) {
slotname = body.traits.traits[t].getName(abc);
}
}
if (obj instanceof ExceptionTreeItem) {
slotname = constants.constant_multiname[((ExceptionTreeItem) obj).exception.name_index];
} else if (obj instanceof ClassTreeItem) {
slotname = ((ClassTreeItem) obj).className;
} else if (obj instanceof ThisTreeItem) {
slotname = ((ThisTreeItem) obj).className;
} else {
//if(value.startsWith("catched ")) return;
for (int t = 0; t < body.traits.traits.length; t++) {
if (body.traits.traits[t] instanceof TraitSlotConst) {
if (((TraitSlotConst) body.traits.traits[t]).slot_id == slotIndex) {
slotname = body.traits.traits[t].getName(abc);
}
}
}
}
if (localRegNames.containsValue(slotname.getName(constants, fullyQualifiedNames))) {
return;
};
if (slotname != null) {
if (localRegNames.containsValue(slotname.getName(constants, fullyQualifiedNames))) {
return;
};
}
if (value.getNotCoerced() instanceof IncrementTreeItem) {
TreeItem inside = ((IncrementTreeItem) value.getNotCoerced()).object.getThroughRegister().getNotCoerced();
@@ -56,6 +56,9 @@ public class SetSlotTreeItem extends TreeItem implements SetTypeTreeItem, Assign
}
}
}*/
if(slotName==null){
return ret+"/*UnknownSlot*/";
}
return ret + hilight(slotName.getName(constants, fullyQualifiedNames));
}
@@ -82,6 +82,9 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
}
private boolean displayMethod(int pos, int methodIndex) {
if(abc==null){
return false;
}
int bi = abc.findBodyIndex(methodIndex);
if (bi == -1) {
return false;
@@ -134,11 +137,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
break;
}
}
if (classIndex == -1) {
setNoTrait();
return;
}
for (Highlighting tm : methodHighlights) {
if ((pos >= tm.startPos) && (pos < tm.startPos + tm.len)) {
displayMethod(pos, (int) tm.offset);
@@ -152,6 +151,11 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
return;
}
}
if (classIndex == -1) {
setNoTrait();
return;
}
for (Highlighting th : traitHighlights) {
if ((pos >= th.startPos) && (pos < th.startPos + th.len)) {
lastTraitIndex = (int) th.offset;
@@ -36,7 +36,7 @@ import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
public class MethodBody implements Cloneable,Serializable {
public class MethodBody implements Cloneable, Serializable {
public int method_info;
public int max_stack;
@@ -94,26 +94,33 @@ public class MethodBody implements Cloneable,Serializable {
return ret;
}
public String toString(String path,boolean pcode, boolean isStatic, int classIndex, ABC abc, ConstantPool constants, MethodInfo method_info[], Stack<TreeItem> scopeStack, boolean isStaticInitializer, boolean hilight, List<String> fullyQualifiedNames, Traits initTraits) {
public String toString(String path, boolean pcode, boolean isStatic, int classIndex, ABC abc, ConstantPool constants, MethodInfo method_info[], Stack<TreeItem> scopeStack, boolean isStaticInitializer, boolean hilight, List<String> fullyQualifiedNames, Traits initTraits) {
String s = "";
if (!Main.DO_DECOMPILE) {
s = "//NOT DECOMPILED";
if (hilight) {
s = Highlighting.hilighMethod(s, this.method_info);
}
return s;
}
if (pcode) {
s += code.toASMSource(constants, this);
} else {
AVM2Code deobfuscated = null;
MethodBody b=(MethodBody)Helper.deepCopy(this);
MethodBody b = (MethodBody) Helper.deepCopy(this);
deobfuscated = b.code;
deobfuscated.markMappedOffsets();
deobfuscated.removeTraps(constants, b);
deobfuscated.restoreControlFlow(constants, b);
deobfuscated.restoreControlFlow(constants, b);
try {
s += deobfuscated.toSource(path,isStatic, classIndex, abc, constants, method_info, b, hilight, getLocalRegNames(abc), scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits);
s += deobfuscated.toSource(path, isStatic, classIndex, abc, constants, method_info, b, hilight, getLocalRegNames(abc), scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits);
s = s.trim();
if (hilight) {
s = Highlighting.hilighMethod(s, this.method_info);
}
} catch (Exception ex) {
s = "//error:" + ex.toString();
}
}
}
return s;
}
@@ -282,6 +282,14 @@ public class TraitClass extends Trait {
return imports;
}
@Override
public String convertHeader(String path, List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
String classHeader = abc.instance_info[class_info].getClassHeaderStr(abc, fullyQualifiedNames);
return classHeader;
}
@Override
public String convert(String path,List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
if (!highlight) {
@@ -56,6 +56,7 @@ public class Traits implements Serializable{
s += "\r\n\r\n";
}
String plus;
//System.out.println(path+":"+traits[t].convertHeader(path, abcTags, abc, isStatic, pcode, classIndex, highlighting, fullyQualifiedNames));
if (makePackages) {
plus = traits[t].convertPackaged(path,abcTags, abc, isStatic, pcode, classIndex, highlighting, fullyQualifiedNames);
} else {