AS3: Decompiling via graph - good against obfuscators

This commit is contained in:
Jindra Petk
2013-02-08 22:31:47 +01:00
parent 5a422fd18f
commit 4a387a8df0
57 changed files with 1978 additions and 674 deletions

View File

@@ -17,12 +17,16 @@
package com.jpexs.asdec;
import com.jpexs.asdec.abc.avm2.AVM2Code;
import com.jpexs.asdec.abc.avm2.parser.ASM3Parser;
import com.jpexs.asdec.abc.avm2.parser.ParseException;
import com.jpexs.asdec.abc.types.MethodBody;
import com.jpexs.asdec.gui.AboutDialog;
import com.jpexs.asdec.gui.LoadingDialog;
import com.jpexs.asdec.gui.MainFrame;
import com.jpexs.asdec.gui.ModeFrame;
import com.jpexs.asdec.gui.View;
import com.jpexs.asdec.gui.proxy.ProxyFrame;
import com.jpexs.asdec.helpers.Highlighting;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -140,11 +144,11 @@ public class Main {
public static void startWork(String name) {
startWork(name, -1);
}
public static void startWork(String name, int percent) {
working = true;
if (mainFrame != null) {
mainFrame.setStatus(name);
mainFrame.setWorkStatus(name);
if (percent == -1) {
mainFrame.hidePercent();
} else {
@@ -167,7 +171,7 @@ public class Main {
public static void stopWork() {
working = false;
if (mainFrame != null) {
mainFrame.setStatus("");
mainFrame.setWorkStatus("");
}
if (loadingDialog != null) {
loadingDialog.setDetail("");
@@ -478,6 +482,13 @@ public class Main {
}
}
public static final void printASM(AVM2Code code){
String s=Highlighting.stripHilights(code.toASMSource(null, new MethodBody()));
String ss[]=s.split("\n");
for(int i=0;i<ss.length;i++){
System.out.println(""+i+":"+ss[i]);
}
}
/**
* @param args the command line arguments
*/
@@ -485,7 +496,7 @@ public class Main {
View.setLookAndFeel();
Configuration.load();
checkSWT(args);
int pos = 0;
if (args.length > 0) {
if (args[0].equals("-debug")) {

View File

@@ -21,12 +21,18 @@ import com.jpexs.asdec.abc.avm2.AVM2Code;
import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.abc.avm2.UnknownInstructionCode;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.parser.ASM3Parser;
import com.jpexs.asdec.abc.avm2.parser.ParseException;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import com.jpexs.asdec.abc.types.*;
import com.jpexs.asdec.abc.types.traits.Trait;
import com.jpexs.asdec.abc.types.traits.TraitClass;
import com.jpexs.asdec.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.asdec.abc.types.traits.TraitSlotConst;
import com.jpexs.asdec.abc.types.traits.Traits;
import com.jpexs.asdec.abc.usages.*;
import com.jpexs.asdec.helpers.Helper;
import com.jpexs.asdec.helpers.Highlighting;
import com.jpexs.asdec.tags.DoABCTag;
import java.io.*;
import java.util.ArrayList;
@@ -34,6 +40,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
@@ -263,7 +270,7 @@ public class ABC {
mb.code = new AVM2Code(new ByteArrayInputStream(mb.codeBytes));
} catch (UnknownInstructionCode re) {
mb.code = new AVM2Code();
System.err.println(re.toString());
Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, null, re);
}
mb.code.compact();
int ex_count = ais.readU30();
@@ -287,7 +294,20 @@ public class ABC {
System.out.println("--------------------------------------------");
System.out.println(findBody(si.init_index).toString(true, false, -1, this, constants, method_info,new Stack<TreeItem>(),false,false));
System.out.println("sitrait:"+si.traits.toString(this));
}*/
}*/
/*try {
MethodBody body=new MethodBody();
AVM2Code code=ASM3Parser.parse(new FileInputStream("D:\\tst2.txt"), constants, body);
//code.removeTraps(constants, body);
code.restoreControlFlow(constants, body);
FileOutputStream fos=new FileOutputStream("D:\\tst3.txt");
fos.write(Highlighting.stripHilights(code.toASMSource(constants, body)).getBytes());
fos.close();
System.out.println(code.toSource(false, 0, this, constants, method_info, body, new HashMap<Integer,String>(), new Stack<TreeItem>(), false, null, null));
System.exit(0);
} catch (Exception ex) {
Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, null, ex);
}*/
}
public void saveToStream(OutputStream os) throws IOException {

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,7 @@
*/
package com.jpexs.asdec.abc.avm2;
public class ConvertException extends Exception {
public class ConvertException extends RuntimeException {
public int line;

View File

@@ -0,0 +1,20 @@
package com.jpexs.asdec.abc.avm2;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class ConvertOutput {
public Stack<TreeItem> stack;
public List<TreeItem> output;
public ConvertOutput(Stack<TreeItem> stack, List<TreeItem> output) {
this.stack = stack;
this.output = output;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -31,18 +31,72 @@ public class GraphPart {
public List<GraphPart> nextParts = new ArrayList<GraphPart>();
public int posX = -1;
public int posY = -1;
public String path="";
public List<GraphPart> refs=new ArrayList<GraphPart>();
public boolean ignored=false;
private boolean leadsTo(GraphPart part,List<GraphPart> visited,List<GraphPart> ignored){
if(visited.contains(this)){
return false;
}
if(ignored.contains(this)){
return false;
}
visited.add(this);
for(GraphPart p:nextParts){
if(p==part){
return true;
}else{
if(p.leadsTo(part,visited,ignored)){
return true;
}
}
}
return false;
}
public boolean leadsTo(GraphPart part,List<GraphPart> ignored){
return leadsTo(part,new ArrayList<GraphPart>(),ignored);
}
public GraphPart(int start, int end) {
this.start = start;
this.end = end;
}
private GraphPart getNextPartPath(GraphPart original,String path,List<GraphPart> visited){
if(visited.contains(this)){
return null;
}
visited.add(this);
for(GraphPart p:nextParts){
if(p==original){
continue;
}
if(p.path.equals(path)){
return p;
}else if(p.path.length()>=path.length()){
GraphPart gp=p.getNextPartPath(original,path,visited);
if(gp!=null){
return gp;
}
}
}
return null;
}
public GraphPart getNextPartPath(List<GraphPart> ignored){
List<GraphPart> visited=new ArrayList<GraphPart>();
visited.addAll(ignored);
return getNextPartPath(this,path,visited);
}
@Override
public String toString() {
if (end < start) {
return "<->";
return "<-> "+(start+1)+"-"+(end+1);
}
return "" + (start + 1) + "-" + (end + 1) + (instanceCount > 1 ? "(" + instanceCount + " links)" : "");
return "" + (start + 1) + "-" + (end + 1) + (instanceCount > 1 ? "(" + instanceCount + " links)" : "")+" p"+path;
}
public boolean containsIP(int ip) {
@@ -65,6 +119,10 @@ public class GraphPart {
return false;
}
public int getHeight(){
return end-start+1;
}
public boolean containsPart(GraphPart what) {
return containsPart(this, what, new ArrayList<GraphPart>());
}

View File

@@ -0,0 +1,44 @@
package com.jpexs.asdec.abc.avm2.flowgraph;
import java.util.List;
/**
*
* @author JPEXS
*/
public class GraphPartMulti extends GraphPart {
List<GraphPart> parts;
public GraphPartMulti(List<GraphPart> parts) {
super(parts.get(0).start, parts.get(parts.size() - 1).end);
this.parts = parts;
this.path=parts.get(0).path;
}
@Override
public String toString() {
String ret="";
ret+="[multi ";
boolean first=true;
for(GraphPart g:parts){
if(first){
first=false;
}else{
ret+=", ";
}
ret+=g.toString();
}
ret+="]";
return ret;
}
@Override
public int getHeight(){
int ret=0;
for(GraphPart p:parts){
ret+=p.getHeight();
}
return ret;
}
}

View File

@@ -0,0 +1,16 @@
package com.jpexs.asdec.abc.avm2.flowgraph;
/**
*
* @author JPEXS
*/
public class Loop {
public GraphPart loopContinue;
public GraphPart loopBreak;
public Loop(GraphPart loopContinue, GraphPart loopBreak) {
this.loopContinue = loopContinue;
this.loopBreak = loopBreak;
}
}

View File

@@ -36,6 +36,7 @@ public class AVM2Instruction implements Serializable{
public boolean ignored = false;
public String labelname;
public long mappedOffset=-1;
public int changeJumpTo=-1;
public AVM2Instruction(long offset, InstructionDefinition definition, int[] operands, byte bytes[]) {
this.definition = definition;

View File

@@ -43,7 +43,7 @@ public class NewFunctionIns extends InstructionDefinition {
String bodyStr = "";
String paramStr = "";
if (mybody != null) {
bodyStr = Highlighting.hilighMethodEnd() + mybody.toString(false, isStatic, classIndex, abc, constants, method_info, new Stack<TreeItem>()/*scopeStack*/, false, true, fullyQualifiedNames, null) + Highlighting.hilighMethodBegin(body.method_info);
bodyStr = Highlighting.hilighMethodEnd() + mybody.toString("",false, isStatic, classIndex, abc, constants, method_info, new Stack<TreeItem>()/*scopeStack*/, false, true, fullyQualifiedNames, null) + Highlighting.hilighMethodBegin(body.method_info);
paramStr = method_info[methodIndex].getParamStr(constants, mybody, abc, fullyQualifiedNames);
}

View File

@@ -36,6 +36,9 @@ public class GetScopeObjectIns extends InstructionDefinition {
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, com.jpexs.asdec.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
int index = ins.operands[0];
if(scopeStack.size()<=index){
System.out.println("uuu");
}
stack.push(scopeStack.get(index));
}

View File

@@ -20,6 +20,7 @@ import com.jpexs.asdec.abc.avm2.AVM2Code;
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.treemodel.HasNextTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.InTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.LocalRegTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
@@ -39,6 +40,6 @@ public class HasNext2Ins extends InstructionDefinition {
int objectReg = ins.operands[0];
int indexReg = ins.operands[1];
//stack.push("_loc_" + objectReg + ".hasNext(cnt=_loc_" + indexReg + ")");
stack.push(new InTreeItem(ins, new LocalRegTreeItem(ins, indexReg, localRegs.get(indexReg)), localRegs.get(objectReg)));
stack.push(new HasNextTreeItem(ins, new LocalRegTreeItem(ins, indexReg, localRegs.get(indexReg)), localRegs.get(objectReg)));
}
}

View File

@@ -20,6 +20,7 @@ import com.jpexs.asdec.abc.ABC;
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.treemodel.HasNextTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.InTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import com.jpexs.asdec.abc.types.MethodInfo;
@@ -37,7 +38,7 @@ public class HasNextIns extends InstructionDefinition {
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, com.jpexs.asdec.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem curIndex = (TreeItem) stack.pop();
TreeItem obj = (TreeItem) stack.pop();
stack.push(new InTreeItem(ins, curIndex, obj));
stack.push(new HasNextTreeItem(ins, curIndex, obj));
}

View File

@@ -20,6 +20,7 @@ import com.jpexs.asdec.abc.ABC;
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.treemodel.NextNameTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import com.jpexs.asdec.abc.types.MethodInfo;
import java.util.HashMap;
@@ -36,8 +37,7 @@ public class NextNameIns extends InstructionDefinition {
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, com.jpexs.asdec.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem index = stack.pop();
TreeItem obj = stack.pop();
//stack.push(obj + ".nextName(" + index + ")");
stack.push(index);
stack.push(new NextNameTreeItem(ins, index, obj));
}
@Override

View File

@@ -20,6 +20,7 @@ import com.jpexs.asdec.abc.ABC;
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.treemodel.NextValueTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import com.jpexs.asdec.abc.types.MethodInfo;
import java.util.HashMap;
@@ -35,9 +36,8 @@ public class NextValueIns extends InstructionDefinition {
@Override
public void translate(boolean isStatic, int classIndex, java.util.HashMap<Integer, TreeItem> localRegs, Stack<TreeItem> stack, java.util.Stack<TreeItem> scopeStack, ConstantPool constants, AVM2Instruction ins, MethodInfo[] method_info, List<TreeItem> output, com.jpexs.asdec.abc.types.MethodBody body, com.jpexs.asdec.abc.ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
TreeItem index = stack.pop();
TreeItem obj = stack.pop();
//stack.push(obj + ".nextValue(" + index + ")");
stack.push(index);
TreeItem obj = stack.pop();
stack.push(new NextValueTreeItem(ins, index, obj));
}
@Override

View File

@@ -22,6 +22,7 @@ import com.jpexs.asdec.abc.avm2.LocalDataArea;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.WithEndTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.WithObjectTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.WithTreeItem;
import com.jpexs.asdec.abc.types.MethodBody;
@@ -47,27 +48,8 @@ public class PopScopeIns extends InstructionDefinition {
TreeItem scope = (TreeItem) scopeStack.pop();
if (scope instanceof WithObjectTreeItem) {
scope = ((WithObjectTreeItem) scope).scope;
}
for (int i = output.size() - 1; i >= 0; i--) {
if (output.get(i) instanceof WithTreeItem) {
WithTreeItem wti = (WithTreeItem) output.get(i);
if (wti.scope == scope) {
wti.items = new ArrayList<TreeItem>();
for (int k = i + 1; k < output.size(); k++) {
//output.subList(i+1, output.size());
wti.items.add(output.get(k));
}
while (output.size() > i + 1) {
output.remove(i + 1);
}
/*int count=output.size()-1-(i+1);
for(int c=0;c<count;c++){
output.remove(i+1);
}*/
break;
}
}
}
output.add(new WithEndTreeItem(ins,scope));
}
}
@Override

View File

@@ -0,0 +1,24 @@
package com.jpexs.asdec.abc.avm2.treemodel;
import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import java.util.HashMap;
import java.util.List;
/**
*
* @author JPEXS
*/
public class CommentTreeItem extends TreeItem {
public String comment;
public CommentTreeItem(AVM2Instruction instruction,String comment) {
super(instruction, NOPRECEDENCE);
this.comment=comment;
}
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
return "//"+comment;
}
}

View File

@@ -0,0 +1,27 @@
package com.jpexs.asdec.abc.avm2.treemodel;
import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import java.util.HashMap;
import java.util.List;
/**
*
* @author JPEXS
*/
public class HasNextTreeItem extends TreeItem {
public TreeItem object;
public TreeItem collection;
public HasNextTreeItem(AVM2Instruction instruction, TreeItem object, TreeItem collection) {
super(instruction, NOPRECEDENCE);
this.object=object;
this.collection=collection;
}
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
return collection.toString(constants, localRegNames, fullyQualifiedNames)+" hasNext "+object.toString(constants, localRegNames, fullyQualifiedNames);
}
}

View File

@@ -0,0 +1,27 @@
package com.jpexs.asdec.abc.avm2.treemodel;
import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import java.util.HashMap;
import java.util.List;
/**
*
* @author JPEXS
*/
public class NextNameTreeItem extends TreeItem {
TreeItem index;
TreeItem obj;
public NextNameTreeItem(AVM2Instruction instruction,TreeItem index,TreeItem obj) {
super(instruction, NOPRECEDENCE);
this.index=index;
this.obj=obj;
}
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
return "nextName("+index.toString(constants, localRegNames, fullyQualifiedNames) +","+obj.toString(constants, localRegNames, fullyQualifiedNames)+")";
}
}

View File

@@ -0,0 +1,27 @@
package com.jpexs.asdec.abc.avm2.treemodel;
import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import java.util.HashMap;
import java.util.List;
/**
*
* @author JPEXS
*/
public class NextValueTreeItem extends TreeItem {
TreeItem index;
TreeItem obj;
public NextValueTreeItem(AVM2Instruction instruction,TreeItem index,TreeItem obj) {
super(instruction, NOPRECEDENCE);
this.index=index;
this.obj=obj;
}
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
return "nextValue("+index.toString(constants, localRegNames, fullyQualifiedNames) +","+obj.toString(constants, localRegNames, fullyQualifiedNames)+")";
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2010-2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.asdec.abc.avm2.treemodel;
import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import java.util.HashMap;
import java.util.List;
public class WithEndTreeItem extends TreeItem {
public TreeItem scope;
public WithEndTreeItem(AVM2Instruction instruction, TreeItem scope) {
super(instruction, PRECEDENCE_PRIMARY);
this.scope = scope;
}
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
return hilight("}");
}
public boolean needsSemicolon() {
return false;
}
}

View File

@@ -43,10 +43,14 @@ public class WithTreeItem extends TreeItem {
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
String ret;
ret = hilight("with(") + scope.toString(constants, localRegNames, fullyQualifiedNames) + hilight(")\r\n{\r\n");
for (TreeItem ti : items) {
/*for (TreeItem ti : items) {
ret += ti.toString(constants, localRegNames, fullyQualifiedNames) + "\r\n";
}
ret += hilight("}");
ret += hilight("}");*/
return ret;
}
public boolean needsSemicolon() {
return false;
}
}

View File

@@ -38,6 +38,11 @@ public class DoWhileTreeItem extends LoopTreeItem implements Block {
super(instruction, loopBreak, loopContinue);
this.expression = expression;
this.commands = commands;
if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) {
if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) {
commands.remove(commands.size() - 1);
}
}
}
@Override

View File

@@ -47,6 +47,11 @@ public class ForEachInTreeItem extends LoopTreeItem implements Block {
}
this.expression = expression;
this.commands = commands;
if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) {
if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) {
commands.remove(commands.size() - 1);
}
}
}
@Override

View File

@@ -47,6 +47,12 @@ public class ForInTreeItem extends LoopTreeItem implements Block {
}
this.expression = expression;
this.commands = commands;
if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) {
if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) {
commands.remove(commands.size() - 1);
}
}
}
@Override

View File

@@ -37,6 +37,12 @@ public class ForTreeItem extends LoopTreeItem implements Block {
this.expression = expression;
this.finalCommands = finalCommands;
this.commands = commands;
if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) {
if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) {
commands.remove(commands.size() - 1);
}
}
}
private String stripSemicolon(String s) {

View File

@@ -19,6 +19,7 @@ package com.jpexs.asdec.abc.avm2.treemodel.clauses;
import com.jpexs.asdec.abc.avm2.AVM2Code;
import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.treemodel.BreakTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.ContinueTreeItem;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import java.util.ArrayList;
@@ -31,13 +32,15 @@ public class SwitchTreeItem extends LoopTreeItem implements Block {
public List<TreeItem> caseValues;
public List<List<TreeItem>> caseCommands;
public List<TreeItem> defaultCommands;
public List<Integer> valuesMapping;
public SwitchTreeItem(AVM2Instruction instruction, int switchBreak, TreeItem switchedObject, List<TreeItem> caseValues, List<List<TreeItem>> caseCommands, List<TreeItem> defaultCommands) {
public SwitchTreeItem(AVM2Instruction instruction, int switchBreak, TreeItem switchedObject, List<TreeItem> caseValues, List<List<TreeItem>> caseCommands, List<TreeItem> defaultCommands,List<Integer> valuesMapping) {
super(instruction, switchBreak, -1);
this.switchedObject = switchedObject;
this.caseValues = caseValues;
this.caseCommands = caseCommands;
this.defaultCommands = defaultCommands;
this.valuesMapping=valuesMapping;
}
@Override
@@ -45,8 +48,12 @@ public class SwitchTreeItem extends LoopTreeItem implements Block {
String ret = "";
ret += "loop" + loopBreak + ":\r\n";
ret += hilight("switch(") + switchedObject.toString(constants, localRegNames, fullyQualifiedNames) + hilight(")") + "\r\n{\r\n";
for (int i = 0; i < caseValues.size(); i++) {
ret += "case " + caseValues.get(i).toString(constants, localRegNames, fullyQualifiedNames) + ":\r\n";
for (int i = 0; i < caseCommands.size(); i++) {
for(int k=0;k<valuesMapping.size();k++){
if(valuesMapping.get(k)==i){
ret += "case " + caseValues.get(k).toString(constants, localRegNames, fullyQualifiedNames) + ":\r\n";
}
}
ret += AVM2Code.IDENTOPEN + "\r\n";
for (int j = 0; j < caseCommands.get(i).size(); j++) {
ret += caseCommands.get(i).get(j).toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n";
@@ -54,12 +61,15 @@ public class SwitchTreeItem extends LoopTreeItem implements Block {
ret += AVM2Code.IDENTCLOSE + "\r\n";
}
if (defaultCommands.size() > 0) {
ret += hilight("default") + ":\r\n";
ret += AVM2Code.IDENTOPEN + "\r\n";
for (int j = 0; j < defaultCommands.size(); j++) {
ret += defaultCommands.get(j).toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n";
if(!((defaultCommands.size()==1)&&(defaultCommands.get(0) instanceof BreakTreeItem)&&(((BreakTreeItem)defaultCommands.get(0)).loopPos==loopBreak))){
ret += hilight("default") + ":\r\n";
ret += AVM2Code.IDENTOPEN + "\r\n";
for (int j = 0; j < defaultCommands.size(); j++) {
ret += defaultCommands.get(j).toStringSemicoloned(constants, localRegNames, fullyQualifiedNames) + "\r\n";
}
ret += AVM2Code.IDENTCLOSE + "\r\n";
}
ret += AVM2Code.IDENTCLOSE + "\r\n";
}
ret += hilight("}") + "\r\n";
ret += ":loop" + loopBreak;

View File

@@ -33,6 +33,12 @@ public class WhileTreeItem extends LoopTreeItem implements Block {
super(instruction, loopBreak, loopContinue);
this.expression = expression;
this.commands = commands;
if ((!commands.isEmpty()) && (commands.get(commands.size() - 1) instanceof ContinueTreeItem)) {
if (((ContinueTreeItem) commands.get(commands.size() - 1)).loopPos == loopBreak) {
commands.remove(commands.size() - 1);
}
}
}
@Override

View File

@@ -19,9 +19,14 @@ package com.jpexs.asdec.abc.avm2.treemodel.operations;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
public class EqTreeItem extends BinaryOpTreeItem {
public class EqTreeItem extends BinaryOpTreeItem implements LogicalOp {
public EqTreeItem(AVM2Instruction instruction, TreeItem leftSide, TreeItem rightSide) {
super(instruction, PRECEDENCE_EQUALITY, leftSide, rightSide, "==");
}
@Override
public TreeItem invert() {
return new NeqTreeItem(instruction, leftSide, rightSide);
}
}

View File

@@ -19,9 +19,14 @@ package com.jpexs.asdec.abc.avm2.treemodel.operations;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
public class GeTreeItem extends BinaryOpTreeItem {
public class GeTreeItem extends BinaryOpTreeItem implements LogicalOp{
public GeTreeItem(AVM2Instruction instruction, TreeItem leftSide, TreeItem rightSide) {
super(instruction, PRECEDENCE_RELATIONAL, leftSide, rightSide, ">=");
}
@Override
public TreeItem invert() {
return new LtTreeItem(instruction, leftSide, rightSide);
}
}

View File

@@ -19,9 +19,14 @@ package com.jpexs.asdec.abc.avm2.treemodel.operations;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
public class GtTreeItem extends BinaryOpTreeItem {
public class GtTreeItem extends BinaryOpTreeItem implements LogicalOp{
public GtTreeItem(AVM2Instruction instruction, TreeItem leftSide, TreeItem rightSide) {
super(instruction, PRECEDENCE_RELATIONAL, leftSide, rightSide, ">");
}
@Override
public TreeItem invert() {
return new LeTreeItem(instruction, leftSide, rightSide);
}
}

View File

@@ -19,9 +19,14 @@ package com.jpexs.asdec.abc.avm2.treemodel.operations;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
public class LeTreeItem extends BinaryOpTreeItem {
public class LeTreeItem extends BinaryOpTreeItem implements LogicalOp{
public LeTreeItem(AVM2Instruction instruction, TreeItem leftSide, TreeItem rightSide) {
super(instruction, PRECEDENCE_RELATIONAL, leftSide, rightSide, "<=");
}
@Override
public TreeItem invert() {
return new GtTreeItem(instruction, leftSide, rightSide);
}
}

View File

@@ -0,0 +1,11 @@
package com.jpexs.asdec.abc.avm2.treemodel.operations;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
/**
*
* @author JPEXS
*/
public interface LogicalOp {
public TreeItem invert();
}

View File

@@ -19,9 +19,14 @@ package com.jpexs.asdec.abc.avm2.treemodel.operations;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
public class LtTreeItem extends BinaryOpTreeItem {
public class LtTreeItem extends BinaryOpTreeItem implements LogicalOp{
public LtTreeItem(AVM2Instruction instruction, TreeItem leftSide, TreeItem rightSide) {
super(instruction, PRECEDENCE_RELATIONAL, leftSide, rightSide, "<");
}
@Override
public TreeItem invert() {
return new GeTreeItem(instruction, leftSide, rightSide);
}
}

View File

@@ -19,9 +19,14 @@ package com.jpexs.asdec.abc.avm2.treemodel.operations;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
public class NeqTreeItem extends BinaryOpTreeItem {
public class NeqTreeItem extends BinaryOpTreeItem implements LogicalOp {
public NeqTreeItem(AVM2Instruction instruction, TreeItem leftSide, TreeItem rightSide) {
super(instruction, PRECEDENCE_EQUALITY, leftSide, rightSide, "!=");
}
@Override
public TreeItem invert() {
return new EqTreeItem(instruction, leftSide, rightSide);
}
}

View File

@@ -19,7 +19,7 @@ package com.jpexs.asdec.abc.avm2.treemodel.operations;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
public class NotTreeItem extends UnaryOpTreeItem {
public class NotTreeItem extends UnaryOpTreeItem implements LogicalOp{
public NotTreeItem(AVM2Instruction instruction, TreeItem value) {
super(instruction, PRECEDENCE_UNARY, value, "!");
@@ -34,4 +34,9 @@ public class NotTreeItem extends UnaryOpTreeItem {
public boolean isFalse() {
return !value.isFalse();
}
@Override
public TreeItem invert() {
return value;
}
}

View File

@@ -19,9 +19,14 @@ package com.jpexs.asdec.abc.avm2.treemodel.operations;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
public class StrictEqTreeItem extends BinaryOpTreeItem {
public class StrictEqTreeItem extends BinaryOpTreeItem implements LogicalOp{
public StrictEqTreeItem(AVM2Instruction instruction, TreeItem leftSide, TreeItem rightSide) {
super(instruction, PRECEDENCE_EQUALITY, leftSide, rightSide, "===");
}
@Override
public TreeItem invert() {
return new StrictNeqTreeItem(instruction, leftSide, rightSide);
}
}

View File

@@ -19,9 +19,14 @@ package com.jpexs.asdec.abc.avm2.treemodel.operations;
import com.jpexs.asdec.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
public class StrictNeqTreeItem extends BinaryOpTreeItem {
public class StrictNeqTreeItem extends BinaryOpTreeItem implements LogicalOp{
public StrictNeqTreeItem(AVM2Instruction instruction, TreeItem leftSide, TreeItem rightSide) {
super(instruction, PRECEDENCE_EQUALITY, leftSide, rightSide, "!==");
}
@Override
public TreeItem invert() {
return new StrictEqTreeItem(instruction, leftSide, rightSide);
}
}

View File

@@ -73,7 +73,7 @@ public class ASMSourceEditorPane extends LineMarkedEditorPane implements CaretLi
}
public void graph() {
Graph gr = new Graph(abc.bodies[bodyIndex].code);
Graph gr = new Graph(abc.bodies[bodyIndex].code,abc,abc.bodies[bodyIndex]);
(new GraphFrame(gr, "")).setVisible(true);
}

View File

@@ -262,7 +262,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
String hilightedCode;
if (!bufferedClasses.containsKey(script)) {
hilightedCode = script.convert(abcList, abc, false, true);
hilightedCode = script.convert(abcList, abc, false, true);
highlights = Highlighting.getInstrHighlights(hilightedCode);
traitHighlights = Highlighting.getTraitHighlights(hilightedCode);
methodHighlights = Highlighting.getMethodHighlights(hilightedCode);

View File

@@ -39,20 +39,20 @@ public class GraphFrame extends JFrame {
private static final int SPACE_VERTICAL = 10;
private static final int SPACE_HORIZONTAL = 10;
private static final int BLOCK_WIDTH = 100;
private static final int BLOCK_WIDTH = 200;
private static final int BLOCK_HEIGHT = 20;
private Graph graph;
public GraphPanel(Graph graph) {
this.graph = graph;
setPreferredSize(new Dimension((BLOCK_WIDTH + SPACE_HORIZONTAL) * getPartWidth(graph.head, new HashSet<GraphPart>()), (BLOCK_HEIGHT + SPACE_VERTICAL) * getPartHeight(graph.head, new ArrayList<GraphPart>())));
setPreferredSize(new Dimension((BLOCK_WIDTH + SPACE_HORIZONTAL) * getPartWidth(graph.heads.get(0), new HashSet<GraphPart>()), (BLOCK_HEIGHT + SPACE_VERTICAL) * getPartHeight(graph.heads.get(0), new ArrayList<GraphPart>())));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
paintPart(g, graph.head, 0, getPartWidth(graph.head, new HashSet<GraphPart>()) * (BLOCK_WIDTH + SPACE_HORIZONTAL) / 2, new HashMap<GraphPart,Point>());
paintPart(g, graph.heads.get(0), 0, getPartWidth(graph.heads.get(0), new HashSet<GraphPart>()) * (BLOCK_WIDTH + SPACE_HORIZONTAL) / 2, new HashMap<GraphPart,Point>());
}
private void paintPart(Graphics g, GraphPart part, int y, int x, HashMap<GraphPart,Point> used) {

View File

@@ -38,7 +38,7 @@ public class GraphTreeFrame extends JFrame {
setSize(400, 400);
graphTree = new JTree(new TreeModel() {
public Object getRoot() {
return graph.head;
return graph.heads.get(0);
}
public Object getChild(Object parent, int index) {

View File

@@ -46,9 +46,9 @@ public class TraitsListModel implements ListModel {
public Object getElementAt(int index) {
if (index < abc.class_info[classIndex].static_traits.traits.length) {
return abc.class_info[classIndex].static_traits.traits[index].convertHeader(abcTags, abc, true, false, classIndex, false, new ArrayList<String>());
return abc.class_info[classIndex].static_traits.traits[index].convertHeader("",abcTags, abc, true, false, classIndex, false, new ArrayList<String>());
} else if (index < abc.class_info[classIndex].static_traits.traits.length + abc.instance_info[classIndex].instance_traits.traits.length) {
return abc.instance_info[classIndex].instance_traits.traits[index - abc.class_info[classIndex].static_traits.traits.length].convertHeader(abcTags, abc, false, false, classIndex, false, new ArrayList<String>());
return abc.instance_info[classIndex].instance_traits.traits[index - abc.class_info[classIndex].static_traits.traits.length].convertHeader("",abcTags, abc, false, false, classIndex, false, new ArrayList<String>());
} else if (index == abc.class_info[classIndex].static_traits.traits.length + abc.instance_info[classIndex].instance_traits.traits.length) {
return STR_INSTANCE_INITIALIZER;
} else {

View File

@@ -20,9 +20,10 @@ import com.jpexs.asdec.abc.avm2.AVM2Code;
import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.abc.avm2.ConvertException;
import com.jpexs.asdec.helpers.Helper;
import java.io.Serializable;
import java.util.List;
public class ABCException {
public class ABCException implements Serializable{
public int start;
public int end;

View File

@@ -21,16 +21,22 @@ import com.jpexs.asdec.abc.ABC;
import com.jpexs.asdec.abc.avm2.AVM2Code;
import com.jpexs.asdec.abc.avm2.CodeStats;
import com.jpexs.asdec.abc.avm2.ConstantPool;
import com.jpexs.asdec.abc.avm2.parser.ASM3Parser;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import com.jpexs.asdec.abc.types.traits.Traits;
import com.jpexs.asdec.helpers.Helper;
import com.jpexs.asdec.helpers.Highlighting;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
public class MethodBody implements Cloneable {
public class MethodBody implements Cloneable,Serializable {
public int method_info;
public int max_stack;
@@ -88,25 +94,26 @@ public class MethodBody implements Cloneable {
return ret;
}
public String toString(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 (pcode) {
s += code.toASMSource(constants, this);
} else {
AVM2Code deobfuscated = null;
deobfuscated = code.deepCopy();
MethodBody b=(MethodBody)Helper.deepCopy(this);
deobfuscated = b.code;
deobfuscated.markMappedOffsets();
deobfuscated.removeTraps(constants, this);
deobfuscated.restoreControlFlow(constants, this);
deobfuscated.removeTraps(constants, b);
deobfuscated.restoreControlFlow(constants, b);
try {
s += deobfuscated.toSource(isStatic, classIndex, abc, constants, method_info, this, 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;
}

View File

@@ -52,7 +52,7 @@ public class ScriptInfo {
}
public String convert(List<DoABCTag> abcTags, ABC abc, boolean pcode, boolean highlighting) {
return traits.convert(abcTags, abc, false, pcode, true, -1, highlighting, new ArrayList<String>());
return traits.convert("",abcTags, abc, false, pcode, true, -1, highlighting, new ArrayList<String>());
}
public void export(ABC abc, List<DoABCTag> abcList, String directory, boolean pcode) throws IOException {

View File

@@ -21,9 +21,10 @@ import com.jpexs.asdec.abc.types.Multiname;
import com.jpexs.asdec.abc.types.Namespace;
import com.jpexs.asdec.helpers.Helper;
import com.jpexs.asdec.tags.DoABCTag;
import java.io.Serializable;
import java.util.List;
public abstract class Trait {
public abstract class Trait implements Serializable{
public int name_index;
public int kindType;
@@ -81,7 +82,7 @@ public abstract class Trait {
}
}
if (!nsname.contains(":")) {
if ((!nsname.contains(":"))&&(!nsname.equals(""))) {
ret += " " + nsname;
}
if (ns != null) {
@@ -108,16 +109,16 @@ public abstract class Trait {
return abc.constants.constant_multiname[name_index].toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata);
}
public String convert(List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
public String convert(String path, List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
return abc.constants.constant_multiname[name_index].toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata);
}
public String convertPackaged(List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcod, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
return makePackageFromIndex(abc, name_index, convert(abcTags, abc, isStatic, pcod, classIndex, highlight, fullyQualifiedNames));
public String convertPackaged(String path, List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcod, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
return makePackageFromIndex(abc, name_index, convert(path,abcTags, abc, isStatic, pcod, classIndex, highlight, fullyQualifiedNames));
}
public String convertHeader(List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
return convert(abcTags, abc, isStatic, pcode, classIndex, highlight, fullyQualifiedNames).trim();
public String convertHeader(String path,List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
return convert(path,abcTags, abc, isStatic, pcode, classIndex, highlight, fullyQualifiedNames).trim();
}
protected String makePackageFromIndex(ABC abc, int name_index, String value) {

View File

@@ -283,7 +283,7 @@ public class TraitClass extends Trait {
}
@Override
public String convert(List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
public String convert(String path,List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
if (!highlight) {
Highlighting.doHighlight = false;
}
@@ -295,12 +295,12 @@ public class TraitClass extends Trait {
List<String> namesInThisPackage = new ArrayList<String>();
for (DoABCTag tag : abcTags) {
for (ScriptInfo si : tag.abc.script_info) {
String path = si.getPath(tag.abc);
String spath = si.getPath(tag.abc);
String pkg = "";
String name = path;
if (path.contains(".")) {
pkg = path.substring(0, path.lastIndexOf("."));
name = path.substring(path.lastIndexOf(".") + 1);
String name = spath;
if (spath.contains(".")) {
pkg = spath.substring(0, spath.lastIndexOf("."));
name = spath.substring(spath.lastIndexOf(".") + 1);
}
if (pkg.equals(packageName)) {
namesInThisPackage.add(name);
@@ -316,8 +316,8 @@ public class TraitClass extends Trait {
List<String> importnames = new ArrayList<String>();
importnames.addAll(namesInThisPackage);
for (String path : imports) {
String name = path;
for (String ipath : imports) {
String name = ipath;
String pkg = "";
if (name.contains(".")) {
pkg = name.substring(0, name.lastIndexOf("."));
@@ -355,7 +355,7 @@ public class TraitClass extends Trait {
}
out.println();
//class header
//class header
String classHeader = abc.instance_info[class_info].getClassHeaderStr(abc, fullyQualifiedNames);
if (classHeader.startsWith("private ")) {
classHeader = classHeader.substring("private ".length());
@@ -371,7 +371,7 @@ public class TraitClass extends Trait {
String bodyStr = "";
bodyIndex = abc.findBodyIndex(abc.class_info[class_info].cinit_index);
if (bodyIndex != -1) {
bodyStr = abc.bodies[bodyIndex].toString(pcode, true, class_info, abc, abc.constants, abc.method_info, new Stack<TreeItem>(), true, highlight, fullyQualifiedNames, abc.class_info[class_info].static_traits);
bodyStr = abc.bodies[bodyIndex].toString(packageName+"."+abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames)+".staticinitializer",pcode, true, class_info, abc, abc.constants, abc.method_info, new Stack<TreeItem>(), true, highlight, fullyQualifiedNames, abc.class_info[class_info].static_traits);
}
if (Highlighting.stripHilights(bodyStr).equals("")) {
toPrint = ABC.addTabs(bodyStr, 3);
@@ -405,7 +405,7 @@ public class TraitClass extends Trait {
bodyStr = "";
bodyIndex = abc.findBodyIndex(abc.instance_info[class_info].iinit_index);
if (bodyIndex != -1) {
bodyStr = ABC.addTabs(abc.bodies[bodyIndex].toString(pcode, false, class_info, abc, abc.constants, abc.method_info, new Stack<TreeItem>(), false, highlight, fullyQualifiedNames, abc.instance_info[class_info].instance_traits), 3);
bodyStr = ABC.addTabs(abc.bodies[bodyIndex].toString(packageName+"."+abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames) +".initializer",pcode, false, class_info, abc, abc.constants, abc.method_info, new Stack<TreeItem>(), false, highlight, fullyQualifiedNames, abc.instance_info[class_info].instance_traits), 3);
constructorParams = abc.method_info[abc.instance_info[class_info].iinit_index].getParamStr(abc.constants, abc.bodies[bodyIndex], abc, fullyQualifiedNames);
} else {
constructorParams = abc.method_info[abc.instance_info[class_info].iinit_index].getParamStr(abc.constants, null, abc, fullyQualifiedNames);
@@ -419,9 +419,9 @@ public class TraitClass extends Trait {
//}
//static variables,constants & methods
outTraits.add(abc.class_info[class_info].static_traits.convert(abcTags, abc, true, pcode, false, class_info, highlight, fullyQualifiedNames));
outTraits.add(abc.class_info[class_info].static_traits.convert(packageName+"."+abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames),abcTags, abc, true, pcode, false, class_info, highlight, fullyQualifiedNames));
outTraits.add(abc.instance_info[class_info].instance_traits.convert(abcTags, abc, false, pcode, false, class_info, highlight, fullyQualifiedNames));
outTraits.add(abc.instance_info[class_info].instance_traits.convert(packageName+"."+abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames),abcTags, abc, false, pcode, false, class_info, highlight, fullyQualifiedNames));
out.println(Helper.joinStrings(outTraits, "\r\n\r\n"));
out.println(ABC.IDENT_STRING + "}");//class

View File

@@ -35,7 +35,7 @@ public class TraitFunction extends Trait {
}
@Override
public String convertHeader(List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
public String convertHeader(String path,List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
String modifier = getModifiers(abcTags, abc, isStatic) + " ";
if (modifier.equals(" ")) {
modifier = "";
@@ -45,12 +45,12 @@ public class TraitFunction extends Trait {
}
@Override
public String convert(List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
String header = convertHeader(abcTags, abc, isStatic, pcode, classIndex, highlight, fullyQualifiedNames);
public String convert(String path,List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
String header = convertHeader(path,abcTags, abc, isStatic, pcode, classIndex, highlight, fullyQualifiedNames);
String bodyStr = "";
int bodyIndex = abc.findBodyIndex(method_info);
if (bodyIndex != -1) {
bodyStr = ABC.addTabs(abc.bodies[bodyIndex].toString(pcode, isStatic, classIndex, abc, abc.constants, abc.method_info, new Stack<TreeItem>(), false, highlight, fullyQualifiedNames, null), 3);
bodyStr = ABC.addTabs(abc.bodies[bodyIndex].toString(path+"."+abc.constants.constant_multiname[name_index].getName(abc.constants, fullyQualifiedNames),pcode, isStatic, classIndex, abc, abc.constants, abc.method_info, new Stack<TreeItem>(), false, highlight, fullyQualifiedNames, null), 3);
}
return ABC.IDENT_STRING + ABC.IDENT_STRING + header + (abc.instance_info[classIndex].isInterface() ? ";" : " {\r\n" + bodyStr + "\r\n" + ABC.IDENT_STRING + ABC.IDENT_STRING + "}");

View File

@@ -17,6 +17,7 @@
package com.jpexs.asdec.abc.types.traits;
import com.jpexs.asdec.abc.ABC;
import com.jpexs.asdec.abc.avm2.flowgraph.Graph;
import com.jpexs.asdec.abc.avm2.treemodel.TreeItem;
import com.jpexs.asdec.abc.types.MethodBody;
import com.jpexs.asdec.helpers.Helper;
@@ -35,7 +36,7 @@ public class TraitMethodGetterSetter extends Trait {
}
@Override
public String convertHeader(List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
public String convertHeader(String path,List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
String modifier = getModifiers(abcTags, abc, isStatic) + " ";
if (modifier.equals(" ")) {
modifier = "";
@@ -53,14 +54,14 @@ public class TraitMethodGetterSetter extends Trait {
}
@Override
public String convert(List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
String header = convertHeader(abcTags, abc, isStatic, pcode, classIndex, highlight, fullyQualifiedNames);
public String convert(String path,List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
String header = convertHeader(path,abcTags, abc, isStatic, pcode, classIndex, highlight, fullyQualifiedNames);
String bodyStr = "";
int bodyIndex = abc.findBodyIndex(method_info);
if (bodyIndex != -1) {
bodyStr = ABC.addTabs(abc.bodies[bodyIndex].toString(pcode, isStatic, classIndex, abc, abc.constants, abc.method_info, new Stack<TreeItem>(), false, highlight, fullyQualifiedNames, null), 3);
bodyStr = ABC.addTabs(abc.bodies[bodyIndex].toString(path+"."+getName(abc).getName(abc.constants, fullyQualifiedNames),pcode, isStatic, classIndex, abc, abc.constants, abc.method_info, new Stack<TreeItem>(), false, highlight, fullyQualifiedNames, null), 3);
}
return ABC.IDENT_STRING + ABC.IDENT_STRING + header + (abc.instance_info[classIndex].isInterface() ? ";" : " {\r\n" + bodyStr + "\r\n" + ABC.IDENT_STRING + ABC.IDENT_STRING + "}");
return ABC.IDENT_STRING + ABC.IDENT_STRING + header + ((classIndex!=-1 && abc.instance_info[classIndex].isInterface()) ? ";" : " {\r\n" + bodyStr + "\r\n" + ABC.IDENT_STRING + ABC.IDENT_STRING + "}");
}
}

View File

@@ -90,7 +90,7 @@ public class TraitSlotConst extends Trait {
}
@Override
public String convert(List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
public String convert(String path,List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, int classIndex, boolean highlight, List<String> fullyQualifiedNames) {
String modifier = getModifiers(abcTags, abc, isStatic) + " ";
if (modifier.equals(" ")) {
modifier = "";

View File

@@ -19,9 +19,10 @@ package com.jpexs.asdec.abc.types.traits;
import com.jpexs.asdec.abc.ABC;
import com.jpexs.asdec.helpers.Highlighting;
import com.jpexs.asdec.tags.DoABCTag;
import java.io.Serializable;
import java.util.List;
public class Traits {
public class Traits implements Serializable{
public Trait traits[] = new Trait[0];
@@ -48,7 +49,7 @@ public class Traits {
return s;
}
public String convert(List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, boolean makePackages, int classIndex, boolean highlighting, List<String> fullyQualifiedNames) {
public String convert(String path,List<DoABCTag> abcTags, ABC abc, boolean isStatic, boolean pcode, boolean makePackages, int classIndex, boolean highlighting, List<String> fullyQualifiedNames) {
String s = "";
for (int t = 0; t < traits.length; t++) {
if (t > 0) {
@@ -56,9 +57,9 @@ public class Traits {
}
String plus;
if (makePackages) {
plus = traits[t].convertPackaged(abcTags, abc, isStatic, pcode, classIndex, highlighting, fullyQualifiedNames);
plus = traits[t].convertPackaged(path,abcTags, abc, isStatic, pcode, classIndex, highlighting, fullyQualifiedNames);
} else {
plus = traits[t].convert(abcTags, abc, isStatic, pcode, classIndex, highlighting, fullyQualifiedNames);
plus = traits[t].convert(path,abcTags, abc, isStatic, pcode, classIndex, highlighting, fullyQualifiedNames);
}
if (highlighting) {
int h = t;

View File

@@ -39,10 +39,10 @@ public abstract class ConstVarMultinameUsage extends TraitMultinameUsage {
return super.toString(abcTags, abc) + " "
+ (parentTraitIndex > -1
? (isStatic
? (((TraitMethodGetterSetter) abc.class_info[classIndex].static_traits.traits[parentTraitIndex]).convertHeader(abcTags, abc, isStatic, false, classIndex, false, new ArrayList<String>()))
: (((TraitMethodGetterSetter) abc.instance_info[classIndex].instance_traits.traits[parentTraitIndex]).convertHeader(abcTags, abc, isStatic, false, classIndex, false, new ArrayList<String>())))
? (((TraitMethodGetterSetter) abc.class_info[classIndex].static_traits.traits[parentTraitIndex]).convertHeader("",abcTags, abc, isStatic, false, classIndex, false, new ArrayList<String>()))
: (((TraitMethodGetterSetter) abc.instance_info[classIndex].instance_traits.traits[parentTraitIndex]).convertHeader("",abcTags, abc, isStatic, false, classIndex, false, new ArrayList<String>())))
: "")
+ ((TraitSlotConst) traits.traits[traitIndex]).convertHeader(abcTags, abc, isStatic, false, classIndex, false, new ArrayList<String>());
+ ((TraitSlotConst) traits.traits[traitIndex]).convertHeader("",abcTags, abc, isStatic, false, classIndex, false, new ArrayList<String>());
}
public int getTraitIndex() {

View File

@@ -48,10 +48,10 @@ public abstract class MethodMultinameUsage extends TraitMultinameUsage {
: "instance initializer")
: ((parentTraitIndex > -1
? (isStatic
? (((TraitMethodGetterSetter) abc.class_info[classIndex].static_traits.traits[parentTraitIndex]).convertHeader(abcTags, abc, isStatic, false, classIndex, false, new ArrayList<String>()))
: (((TraitMethodGetterSetter) abc.instance_info[classIndex].instance_traits.traits[parentTraitIndex]).convertHeader(abcTags, abc, isStatic, false, classIndex, false, new ArrayList<String>()))) + " "
? (((TraitMethodGetterSetter) abc.class_info[classIndex].static_traits.traits[parentTraitIndex]).convertHeader("",abcTags, abc, isStatic, false, classIndex, false, new ArrayList<String>()))
: (((TraitMethodGetterSetter) abc.instance_info[classIndex].instance_traits.traits[parentTraitIndex]).convertHeader("",abcTags, abc, isStatic, false, classIndex, false, new ArrayList<String>()))) + " "
: "")
+ (((TraitMethodGetterSetter) traits.traits[traitIndex]).convertHeader(abcTags, abc, isStatic, false, classIndex, false, new ArrayList<String>()))));
+ (((TraitMethodGetterSetter) traits.traits[traitIndex]).convertHeader("",abcTags, abc, isStatic, false, classIndex, false, new ArrayList<String>()))));
}
public int getTraitIndex() {

View File

@@ -23,6 +23,7 @@ import com.jpexs.asdec.abc.gui.ABCPanel;
import com.jpexs.asdec.abc.gui.DeobfuscationDialog;
import com.jpexs.asdec.abc.gui.TreeLeafScript;
import com.jpexs.asdec.action.gui.ActionPanel;
import com.jpexs.asdec.helpers.Helper;
import com.jpexs.asdec.tags.DefineBitsJPEG2Tag;
import com.jpexs.asdec.tags.DefineBitsJPEG3Tag;
import com.jpexs.asdec.tags.DefineBitsJPEG4Tag;
@@ -122,6 +123,9 @@ public class MainFrame extends JFrame implements ActionListener {
}
public void setStatus(String s) {
statusLabel.setText(s);
}
public void setWorkStatus(String s) {
if (s.equals("")) {
loadingPanel.setVisible(false);
} else {
@@ -686,6 +690,7 @@ public class MainFrame extends JFrame implements ActionListener {
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setAcceptAllFileFilterUsed(false);
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
final long timeBefore=System.currentTimeMillis();
Main.startWork("Exporting...");
final String selFile = chooser.getSelectedFile().getAbsolutePath();
Configuration.setConfig("lastExportDir", chooser.getSelectedFile().getParentFile().getAbsolutePath());
@@ -748,6 +753,21 @@ public class MainFrame extends JFrame implements ActionListener {
JOptionPane.showMessageDialog(null, "Cannot write to the file");
}
Main.stopWork();
long timeAfter=System.currentTimeMillis();
long timeMs=timeAfter-timeBefore;
long timeS=timeMs/1000;
timeMs=timeMs%1000;
long timeM=timeS/60;
timeS=timeS%60;
long timeH=timeM/60;
timeM=timeM%60;
String timeStr="";
if(timeH>0){
timeStr+=Helper.padZeros(timeH, 2)+":";
}
timeStr+=Helper.padZeros(timeM, 2)+":";
timeStr+=Helper.padZeros(timeS, 2)+"."+Helper.padZeros(timeMs,3);
setStatus("Exported in "+timeStr);
}
}).start();

View File

@@ -16,6 +16,10 @@
*/
package com.jpexs.asdec.helpers;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
/**
@@ -166,6 +170,14 @@ public class Helper {
sb.append(ss);
return sb.toString();
}
public static String padZeros(long number,int length){
String ret=""+number;
while(ret.length()<length){
ret="0"+ret;
}
return ret;
}
public static String bytesToHexString(byte bytes[], int start) {
StringBuilder sb = new StringBuilder();
@@ -235,4 +247,21 @@ public class Helper {
}
return ret;
}
public static Object deepCopy(Object o) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.flush();
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
Object copy = ois.readObject();
ois.close();
return copy;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
}