From 2e9e7b419156680517ce240a9581b6d2c0e44caa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Sat, 9 Feb 2013 10:45:23 +0100 Subject: [PATCH] AS3: Larger classes support SetSlot fix --- trunk/src/com/jpexs/asdec/abc/ABC.java | 10 +-- .../com/jpexs/asdec/abc/avm2/AVM2Code.java | 65 +++++++++++-------- .../avm2/instructions/other/SetSlotIns.java | 37 +++++++---- .../abc/avm2/treemodel/SetSlotTreeItem.java | 3 + .../asdec/abc/gui/DecompiledEditorPane.java | 14 ++-- .../com/jpexs/asdec/abc/types/MethodBody.java | 19 ++++-- .../asdec/abc/types/traits/TraitClass.java | 8 +++ .../jpexs/asdec/abc/types/traits/Traits.java | 1 + 8 files changed, 99 insertions(+), 58 deletions(-) diff --git a/trunk/src/com/jpexs/asdec/abc/ABC.java b/trunk/src/com/jpexs/asdec/abc/ABC.java index c73ece160..7f5047707 100644 --- a/trunk/src/com/jpexs/asdec/abc/ABC.java +++ b/trunk/src/com/jpexs/asdec/abc/ABC.java @@ -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) { diff --git a/trunk/src/com/jpexs/asdec/abc/avm2/AVM2Code.java b/trunk/src/com/jpexs/asdec/abc/avm2/AVM2Code.java index 6ccf26201..dfb166c69 100644 --- a/trunk/src/com/jpexs/asdec/abc/avm2/AVM2Code.java +++ b/trunk/src/com/jpexs/asdec/abc/avm2/AVM2Code.java @@ -704,11 +704,11 @@ public class AVM2Code implements Serializable { public String toASMSource(ConstantPool constants, MethodBody body, List 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())) + "\" " - + "m[" + body.exceptions[e].type_index + "]\"" + Helper.escapeString(body.exceptions[e].getTypeName(constants, new ArrayList())) + "\"\n"; + ret.append("exception " + e + " m[" + body.exceptions[e].name_index + "]\"" + Helper.escapeString(body.exceptions[e].getVarName(constants, new ArrayList())) + "\" " + + "m[" + body.exceptions[e].type_index + "]\"" + Helper.escapeString(body.exceptions[e].getTypeName(constants, new ArrayList())) + "\"\n"); } List offsets = new ArrayList(); 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()) + " ;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()); + t = ins.toStringNoAddress(constants, new ArrayList()); 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 posCache; @@ -821,12 +827,12 @@ public class AVM2Code implements Serializable { } public static String listToString(List stack, ConstantPool constants, HashMap localRegNames, List 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 loopStack = new Stack(); @@ -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) { diff --git a/trunk/src/com/jpexs/asdec/abc/avm2/instructions/other/SetSlotIns.java b/trunk/src/com/jpexs/asdec/abc/avm2/instructions/other/SetSlotIns.java index a2fc322e2..1022337d4 100644 --- a/trunk/src/com/jpexs/asdec/abc/avm2/instructions/other/SetSlotIns.java +++ b/trunk/src/com/jpexs/asdec/abc/avm2/instructions/other/SetSlotIns.java @@ -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(); diff --git a/trunk/src/com/jpexs/asdec/abc/avm2/treemodel/SetSlotTreeItem.java b/trunk/src/com/jpexs/asdec/abc/avm2/treemodel/SetSlotTreeItem.java index 8222e970f..9ab785323 100644 --- a/trunk/src/com/jpexs/asdec/abc/avm2/treemodel/SetSlotTreeItem.java +++ b/trunk/src/com/jpexs/asdec/abc/avm2/treemodel/SetSlotTreeItem.java @@ -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)); } diff --git a/trunk/src/com/jpexs/asdec/abc/gui/DecompiledEditorPane.java b/trunk/src/com/jpexs/asdec/abc/gui/DecompiledEditorPane.java index 985f2b879..3c6285d3f 100644 --- a/trunk/src/com/jpexs/asdec/abc/gui/DecompiledEditorPane.java +++ b/trunk/src/com/jpexs/asdec/abc/gui/DecompiledEditorPane.java @@ -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; diff --git a/trunk/src/com/jpexs/asdec/abc/types/MethodBody.java b/trunk/src/com/jpexs/asdec/abc/types/MethodBody.java index 93e1820e3..ebc036241 100644 --- a/trunk/src/com/jpexs/asdec/abc/types/MethodBody.java +++ b/trunk/src/com/jpexs/asdec/abc/types/MethodBody.java @@ -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 scopeStack, boolean isStaticInitializer, boolean hilight, List fullyQualifiedNames, Traits initTraits) { + public String toString(String path, boolean pcode, boolean isStatic, int classIndex, ABC abc, ConstantPool constants, MethodInfo method_info[], Stack scopeStack, boolean isStaticInitializer, boolean hilight, List 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; } diff --git a/trunk/src/com/jpexs/asdec/abc/types/traits/TraitClass.java b/trunk/src/com/jpexs/asdec/abc/types/traits/TraitClass.java index 4e2883c7a..7a258914b 100644 --- a/trunk/src/com/jpexs/asdec/abc/types/traits/TraitClass.java +++ b/trunk/src/com/jpexs/asdec/abc/types/traits/TraitClass.java @@ -282,6 +282,14 @@ public class TraitClass extends Trait { return imports; } + @Override + public String convertHeader(String path, List abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List fullyQualifiedNames) { + String classHeader = abc.instance_info[class_info].getClassHeaderStr(abc, fullyQualifiedNames); + return classHeader; + } + + + @Override public String convert(String path,List abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List fullyQualifiedNames) { if (!highlight) { diff --git a/trunk/src/com/jpexs/asdec/abc/types/traits/Traits.java b/trunk/src/com/jpexs/asdec/abc/types/traits/Traits.java index 851047c56..a401f7413 100644 --- a/trunk/src/com/jpexs/asdec/abc/types/traits/Traits.java +++ b/trunk/src/com/jpexs/asdec/abc/types/traits/Traits.java @@ -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 {