branch : 0.0.9.x
This commit is contained in:
Panxiaobo 2011-12-01 00:39:15 +08:00
parent 42ccfe45d3
commit 8c1cc56165
11 changed files with 869 additions and 68 deletions

View File

@ -37,7 +37,7 @@ public class DexLabel {
public String toString() {
if (offset >= 0) {
return String.format("L%x", offset);
return String.format("L%04x", offset);
}
return String.format("L%08x", this.hashCode());
}

View File

@ -0,0 +1,159 @@
package com.googlecode.dex2jar.analysis;
import java.util.ArrayList;
import java.util.Stack;
import com.googlecode.dex2jar.DexLabel;
import com.googlecode.dex2jar.OdexOpcodes;
public abstract class Analyzer implements OdexOpcodes {
private static void link(Node f, Node t) {
if (!f._cfg_tos.contains(t)) {
f._cfg_tos.add(t);
t._cfg_froms++;
}
}
private static boolean mayThrow(int opcode) {
switch (opcode) {
case OP_AGET:
case OP_ARRAY_LENGTH:
case OP_APUT:
case OP_CHECK_CAST:
case OP_CONST_CLASS:
case OP_DIV:
case OP_DIV_INT_LIT_X:
case OP_EXECUTE_INLINE:
case OP_IGET:
case OP_IGET_QUICK:
case OP_INVOKE_DIRECT:
case OP_INVOKE_INTERFACE:
case OP_INVOKE_STATIC:
case OP_INVOKE_SUPER:
case OP_INVOKE_SUPER_QUICK:
case OP_INVOKE_VIRTUAL:
case OP_INVOKE_VIRTUAL_QUICK:
case OP_IPUT:
case OP_IPUT_QUICK:
case OP_SGET:
case OP_SPUT:
case OP_THROW:
case OP_THROW_VERIFICATION_ERROR:
return true;
}
return false;
}
public Analyzer(CodeNode cn) {
super();
this.cn = cn;
this.totalReg = cn.total;
}
final protected CodeNode cn;
final protected int totalReg;;
public void analyze() {
// clean
for (Node p = cn.first; p != null; p = p.next) {
p._cfg_froms = 0;
if (p._cfg_tos != null) {
p._cfg_tos.clear();
} else {
p._cfg_tos = new ArrayList<Node>(5);
}
p._cfg_visited = false;
p.frame = null;
}
for (Node p = cn.first; p != null; p = p.next) {
switch (p.opcode) {
case OP_IF_EQZ:
case OP_IF_NEZ:
case OP_IF_LTZ:
case OP_IF_GEZ:
case OP_IF_GTZ:
case OP_IF_LEZ:
case OP_IF_EQ:
case OP_IF_NE:
case OP_IF_LT:
case OP_IF_GE:
case OP_IF_GT:
case OP_IF_LE:
link(p, p.next);
link(p, (Node) p.la.info);
break;
case OP_GOTO:
link(p, (Node) p.la.info);
break;
case OP_PACKED_SWITCH:
case OP_SPARSE_SWITCH:
link(p, (Node) p.la.info);
for (DexLabel dl : p.ls) {
link(p, (Node) dl.info);
}
break;
case OP_RETURN:
case OP_RETURN_VOID:
case OP_THROW:
case OP_THROW_VERIFICATION_ERROR:
break;
default:
if (p.opcode == CodeNode.OP_LABEL && p.next == null) {
// ignore last label
} else {
link(p, p.next);
}
break;
}
}
for (Node t : cn.trys) {
Node endNode = (Node) t.lb.info;
Node handlerNode = (Node) t.lc.info;
Node pre = (Node) t.la.info;
for (Node p = pre.next; p != endNode; p = p.next) {
if (mayThrow(p.opcode)) {
link(pre, handlerNode);
}
pre = p;
}
handlerNode.frame = createExceptionHandlerFrame(handlerNode, t.type == null ? "Ljava/lang/Throwable;"
: t.type);
}
Node p = cn.first;
p.frame = initFirstFrame(p);
Stack<Node> stack = new Stack<Node>();
// System.out.println();
stack.push(p);
while (!stack.empty()) {
p = stack.pop();
if (p._cfg_visited) {
continue;
}
p._cfg_visited = true;
// System.out.print(p);
Object frame = exec(p);
for (Node x : p._cfg_tos) {
merge(frame, x);
stack.push(x);
}
}
}
protected abstract Object exec(Node p);
protected abstract void merge(Object frame, Node target);
protected abstract Object initFirstFrame(Node p);
protected abstract Object createExceptionHandlerFrame(Node handlerNode, String string);
}

View File

@ -1,4 +1,4 @@
package com.googlecode.dex2jar.xir;
package com.googlecode.dex2jar.analysis;
import java.util.ArrayList;
import java.util.List;
@ -13,129 +13,138 @@ public class CodeNode implements OdexCodeVisitor {
public static final int OP_LABEL = -1;
public static final int OP_TRYS = -2;
public List<Node> insns = new ArrayList<Node>();
public Node first;
public Node last;
public List<Node> trys = new ArrayList<Node>(5);
int total;
int args[];
public int total;
public int args[];
public void addNode(Node node) {
if (first == null) {
first = last = node;
} else {
last.next = node;
last = node;
}
}
// public List<Insn> lines = new ArrayList(5);
@Override
public void visitArrayStmt(int opcode, int formOrToReg, int arrayReg, int indexReg, int xt) {
insns.add(new Node(opcode, formOrToReg, arrayReg, indexReg, xt));
addNode(new Node(opcode, formOrToReg, arrayReg, indexReg, xt));
}
@Override
public void visitBinopLitXStmt(int opcode, int distReg, int srcReg, int content) {
insns.add(new Node(opcode, distReg, srcReg, content));
addNode(new Node(opcode, distReg, srcReg, content));
}
@Override
public void visitBinopStmt(int opcode, int toReg, int r1, int r2, int xt) {
insns.add(new Node(opcode, toReg, r1, r2, xt));
addNode(new Node(opcode, toReg, r1, r2, xt));
}
@Override
public void visitClassStmt(int opcode, int a, int b, String type) {
insns.add(new Node(opcode, a, b, type));
addNode(new Node(opcode, a, b, type));
}
@Override
public void visitClassStmt(int opcode, int saveTo, String type) {
insns.add(new Node(opcode, saveTo, type));
addNode(new Node(opcode, saveTo, type));
}
@Override
public void visitCmpStmt(int opcode, int distReg, int bB, int cC, int xt) {
insns.add(new Node(opcode, distReg, bB, cC, xt));
addNode(new Node(opcode, distReg, bB, cC, xt));
}
@Override
public void visitConstStmt(int opcode, int toReg, Object value, int xt) {
insns.add(new Node(opcode, toReg, value, xt));
addNode(new Node(opcode, toReg, value, xt));
}
@Override
public void visitFieldStmt(int opcode, int fromOrToReg, Field field, int xt) {
insns.add(new Node(opcode, fromOrToReg, xt, field));
addNode(new Node(opcode, fromOrToReg, xt, field));
}
@Override
public void visitFieldStmt(int opcode, int fromOrToReg, int objReg, Field field, int xt) {
insns.add(new Node(opcode, fromOrToReg, objReg, xt, field));
addNode(new Node(opcode, fromOrToReg, objReg, xt, field));
}
@Override
public void visitFillArrayStmt(int opcode, int aA, int elemWidth, int initLength, Object[] values) {
insns.add(new Node(opcode, aA, elemWidth, values));
addNode(new Node(opcode, aA, elemWidth, values));
}
@Override
public void visitFilledNewArrayStmt(int opcode, int[] args, String type) {
insns.add(new Node(opcode, args, type));
addNode(new Node(opcode, args, type));
}
@Override
public void visitJumpStmt(int opcode, int a, int b, DexLabel label) {
insns.add(new Node(opcode, a, b, label));
addNode(new Node(opcode, a, b, label));
}
@Override
public void visitJumpStmt(int opcode, int reg, DexLabel label) {
insns.add(new Node(opcode, reg, label));
addNode(new Node(opcode, reg, label));
}
@Override
public void visitJumpStmt(int opcode, DexLabel label) {
insns.add(new Node(opcode, label));
addNode(new Node(opcode, label));
}
@Override
public void visitLookupSwitchStmt(int opcode, int aA, DexLabel label, int[] cases, DexLabel[] labels) {
insns.add(new Node(opcode, aA, label, cases, labels));
addNode(new Node(opcode, aA, label, cases, labels));
}
@Override
public void visitMethodStmt(int opcode, int[] args, Method method) {
insns.add(new Node(opcode, args, method));
addNode(new Node(opcode, args, method));
}
@Override
public void visitMonitorStmt(int opcode, int reg) {
insns.add(new Node(opcode, reg));
addNode(new Node(opcode, reg));
}
@Override
public void visitMoveStmt(int opcode, int toReg, int xt) {
insns.add(new Node(opcode, toReg, xt));
addNode(new Node(opcode, toReg, xt));
}
@Override
public void visitMoveStmt(int opcode, int toReg, int fromReg, int xt) {
insns.add(new Node(opcode, toReg, fromReg, xt));
addNode(new Node(opcode, toReg, fromReg, xt));
}
@Override
public void visitReturnStmt(int opcode) {
insns.add(new Node(opcode));
addNode(new Node(opcode));
}
@Override
public void visitReturnStmt(int opcode, int reg, int xt) {
insns.add(new Node(opcode, reg, xt));
addNode(new Node(opcode, reg, xt));
}
@Override
public void visitTableSwitchStmt(int opcode, int aA, DexLabel label, int first_case, int last_case,
DexLabel[] labels) {
insns.add(new Node(opcode, aA, label, first_case, last_case, labels));
addNode(new Node(opcode, aA, label, first_case, last_case, labels));
}
@Override
public void visitUnopStmt(int opcode, int toReg, int fromReg, int xt) {
insns.add(new Node(opcode, toReg, fromReg, xt));
addNode(new Node(opcode, toReg, fromReg, xt));
}
@Override
@ -155,7 +164,9 @@ public class CodeNode implements OdexCodeVisitor {
@Override
public void visitLabel(DexLabel label) {
insns.add(new Node(OP_LABEL, label));
Node node = new Node(OP_LABEL, label);
label.info = node;
addNode(node);
}
@Override
@ -172,22 +183,34 @@ public class CodeNode implements OdexCodeVisitor {
@Override
public void visitReturnStmt(int opcode, int cause, Object ref) {
insns.add(new Node(opcode, cause, ref));
addNode(new Node(opcode, cause, ref));
}
@Override
public void visitMethodStmt(int opcode, int[] args, int a) {
insns.add(new Node(opcode, args, a));
addNode(new Node(opcode, args, a));
}
@Override
public void visitFieldStmt(int opcode, int fromOrToReg, int objReg, int fieldoff, int xt) {
insns.add(new Node(opcode, fromOrToReg, objReg, fieldoff, xt));
addNode(new Node(opcode, fromOrToReg, objReg, fieldoff, xt));
}
@Override
public void visitUnopStmt(int opcode, int toReg, int fromReg, int xta, int xtb) {
insns.add(new Node(opcode, fromReg, xta, xtb));
addNode(new Node(opcode, toReg, fromReg, xta, xtb));
}
public String toString() {
StringBuilder sb = new StringBuilder();
NodeDump nd = new NodeDump();
for (Node p = first; p != null; p = p.next) {
p.accept(nd);
}
sb.append(nd.toString());
// TODO add trys
return sb.toString();
}
}

View File

@ -1,4 +1,6 @@
package com.googlecode.dex2jar.xir;
package com.googlecode.dex2jar.analysis;
import java.util.List;
import com.googlecode.dex2jar.DexLabel;
import com.googlecode.dex2jar.Field;
@ -17,6 +19,12 @@ public class Node implements OdexOpcodes {
public DexLabel la, lb, lc;
public DexLabel[] ls;
public Node next;
public Object frame;
public int _cfg_froms;
public List<Node> _cfg_tos;
public boolean _cfg_visited;
public Node(int opcode, int a, int b, String type) {
super();
this.opcode = opcode;
@ -158,11 +166,11 @@ public class Node implements OdexOpcodes {
this.c = c;
}
public Node(int opcode, int a, DexLabel la, int[] cst, DexLabel[] ls) {
public Node(int opcode, int a, DexLabel la, int[] args, DexLabel[] ls) {
this.opcode = opcode;
this.a = a;
this.la = la;
this.cst = cst;
this.args = args;
this.ls = ls;
}
@ -198,7 +206,7 @@ public class Node implements OdexOpcodes {
case OP_SHL_INT_LIT_X:
case OP_SHR_INT_LIT_X:
case OP_USHR_INT_LIT_X:
dcv.visitBinopLitXStmt(opcode, a, a, c);
dcv.visitBinopLitXStmt(opcode, a, b, c);
break;
case OP_ADD:
case OP_SUB:
@ -213,12 +221,12 @@ public class Node implements OdexOpcodes {
case OP_USHR:
dcv.visitBinopStmt(opcode, a, b, c, d);
break;
case OP_INSTANCE_OF:
case OP_NEW_ARRAY:
dcv.visitClassStmt(opcode, a, type);
break;
case OP_CHECK_CAST:
case OP_NEW_INSTANCE:
dcv.visitClassStmt(opcode, a, type);
break;
case OP_NEW_ARRAY:
case OP_INSTANCE_OF:
dcv.visitClassStmt(opcode, a, b, type);
break;
case OP_CMPL:
@ -275,7 +283,7 @@ public class Node implements OdexOpcodes {
case OP_INVOKE_DIRECT:
case OP_INVOKE_STATIC:
case OP_INVOKE_INTERFACE:
dcv.visitMethodStmt(opcode, args, a);
dcv.visitMethodStmt(opcode, args, method);
break;
case OP_MONITOR_ENTER:
case OP_MONITOR_EXIT:

View File

@ -1,4 +1,4 @@
package com.googlecode.dex2jar.xir;
package com.googlecode.dex2jar.analysis;
import com.googlecode.dex2jar.DexLabel;
import com.googlecode.dex2jar.DexOpcodeDump;
@ -22,6 +22,12 @@ public class NodeDump extends AbstractDumpDexCodeAdapter {
sb.append(String.format("%-20s|%5s:\n", "LABEL", labelToString(label)));
}
@Override
public void visitTryCatch(DexLabel start, DexLabel end, DexLabel handler, String type) {
sb.append(String.format("TRY %s %s %s > %s\n", labelToString(start), labelToString(end), labelToString(handler),
type == null ? "ALL" : type));
}
@Override
protected String labelToString(DexLabel label) {
return label.toString();

View File

@ -0,0 +1,256 @@
package com.googlecode.dex2jar.analysis.type;
import java.util.HashSet;
import java.util.Set;
import com.googlecode.dex2jar.Method;
import com.googlecode.dex2jar.analysis.Analyzer;
import com.googlecode.dex2jar.analysis.CodeNode;
import com.googlecode.dex2jar.analysis.Node;
public class TypeAnalyzer extends Analyzer {
public static class Reg {
/**
* Phi
*/
public Set<Reg> phi = new HashSet<Reg>(3);
public Set<String> typs = new HashSet<String>();
public boolean used;
public String toString() {
if (typs.size() == 0) {
return "?";
}
if (typs.size() == 1) {
return typs.iterator().next().substring(0, 1);
}
return sizeOf(this) == 1 ? "S" : "W";
}
}
public static int sizeOf(Reg reg) {
for (String s : reg.typs) {
switch (s.charAt(0)) {
case 'J':
case 'D':
return 2;
}
}
return 1;
}
final TypeVisitor<Reg> typeVisitor;
private final Reg[] frame;
final boolean isStatic;
final Method method;
public TypeAnalyzer(CodeNode cn, boolean isStatic, Method method) {
super(cn);
this.isStatic = isStatic;
this.method = method;
this.typeVisitor = new TypeVisitor<Reg>(totalReg, method.getReturnType()) {
@Override
public Reg _new() {
return new Reg();
}
@Override
public void _put(int reg, Reg n) {
frame[reg] = n;
}
@Override
public int _size(int i) {
return sizeOf((Reg) frame[i]);
}
@Override
public void _type(Reg r, String desc) {
Set<String> ts = r.typs;
if (ts.size() == 0) {
ts.add(desc);
return;
}
if (ts.contains(desc)) {
return;
}
switch (desc.charAt(0)) {
case '_': {
boolean f = false;
for (String s : ts) {
if (!s.startsWith("_")) {
f = true;
break;
}
}
if (!f) {
switch (desc.charAt(1)) {
case '1':
break;
case '2':
break;
case '3':
ts.remove(TypeVisitor.IFL);
ts.add(desc);
break;
}
}
}
break;
case '[': {
if (desc.length() > 1) {
if (desc.charAt(1) == '_') {
boolean f = false;
for (String s : ts) {
if (s.length() >= 2 && s.charAt(0) == '[' && s.charAt(1) != '_') {
f = true;
break;
}
}
if (!f) {
ts.add(desc);
}
} else {
ts.remove(TypeVisitor.AIFL);
ts.remove(TypeVisitor.AJD);
}
}
if (ts.contains(TypeVisitor.IFL) || ts.contains(TypeVisitor.IL)) {
ts.remove(TypeVisitor.IFL);
ts.remove(TypeVisitor.IL);
ts.add("L");
}
}
break;
case 'L':
if (desc.length() == 1) {
boolean f = false;
for (String s : ts) {
if (s.startsWith("L")) {
f = true;
break;
}
}
if (!f) {
ts.add(desc);
}
} else {
ts.remove("L");
ts.add(desc);
}
ts.remove(TypeVisitor.IFL);
ts.remove(TypeVisitor.IL);
ts.remove(TypeVisitor.JD);
break;
default: {
ts.remove(TypeVisitor.IFL);
ts.remove(TypeVisitor.IL);
ts.remove(TypeVisitor.JD);
ts.add(desc);
}
}
}
@Override
public Reg _use(int reg) {
Reg r = (Reg) frame[reg];
if (r != null) {
r.used = true;
}
return r;
}
};
frame = new Reg[totalReg + 2];
}
protected Object createExceptionHandlerFrame(Node handler, String type) {
Reg[] frame = (Reg[]) handler.frame;
Reg obj;
if (frame == null) {
frame = new Reg[totalReg + 2];
obj = frame[totalReg + 1] = typeVisitor._new();
} else {
obj = frame[totalReg + 1];
}
typeVisitor._type(obj, type);
return frame;
}
protected Object exec(Node p) {
Object[] frame = (Object[]) p.frame;
if (frame == null) {
for (int i = 0; i < this.frame.length; i++) {
this.frame[i] = null;
}
} else {
System.arraycopy(frame, 0, this.frame, 0, totalReg + 2);
}
p.accept(typeVisitor);
return this.frame;
}
protected Object initFirstFrame(Node p) {
int i = 0;
Reg[] frame = new Reg[totalReg + 2];
if (!isStatic) {
Reg obj = frame[cn.args[i]] = typeVisitor._new();
typeVisitor._type(obj, method.getOwner());
i++;
}
for (String pt : method.getParameterTypes()) {
Reg obj = frame[cn.args[i]] = typeVisitor._new();
typeVisitor._type(obj, pt);
i++;
}
return frame;
}
protected void merge(Object f, Node target) {
Object[] frame = (Object[]) f;
if (target._cfg_froms == 1) {// only from one node, direct copy node
if (target.frame == null) {
target.frame = new Object[totalReg + 2];
System.arraycopy(frame, 0, target.frame, 0, totalReg + 2);
} else {
Object[] targetFrame = (Object[]) target.frame;
for (int i = 0; i < totalReg + 2; i++) {
if (targetFrame[i] == null) {
targetFrame[i] = frame[i];
}
}
}
} else {// from 2+ node, insert a phi
if (target.frame == null) {
Object[] targetFrame;
target.frame = targetFrame = new Object[totalReg + 2];
for (int i = 0; i < totalReg + 2; i++) {
if (frame[i] != null) {
Reg reg = new Reg();
reg.phi.add((Reg) frame[i]);
targetFrame[i] = reg;
}
}
} else {
Object[] targetFrame = (Object[]) target.frame;
for (int i = 0; i < totalReg + 2; i++) {
if (frame[i] != null) {
Reg reg = (Reg) targetFrame[i];
if (reg == null) {
if (!target._cfg_visited) {
reg = new Reg();
targetFrame[i] = reg;
reg.phi.add((Reg) frame[i]);
}
} else {
reg.phi.add((Reg) frame[i]);
}
}
}
}
}
}
}

View File

@ -0,0 +1,293 @@
package com.googlecode.dex2jar.analysis.type;
import com.googlecode.dex2jar.DexLabel;
import com.googlecode.dex2jar.Field;
import com.googlecode.dex2jar.Method;
import com.googlecode.dex2jar.OdexOpcodes;
import com.googlecode.dex2jar.visitors.OdexCodeVisitor;
public abstract class TypeVisitor<T> implements OdexCodeVisitor, OdexOpcodes {
protected void useAndType(int reg, String desc) {
_type(_use(reg), desc);
}
final protected int totalReg;
final protected String returnType;
public TypeVisitor(int totalReg, String returnType) {
super();
this.totalReg = totalReg;
this.returnType = returnType;
}
protected void newAndType(int reg, String desc) {
T n = _new();
_type(n, desc);
_put(reg, n);
}
public abstract void _put(int reg, T n);
public abstract T _new();
public abstract T _use(int reg);
public abstract void _type(T n, String desc);
public abstract int _size(int i);
public static String IFL = "_1IFL";
public static String IL = "_3IL";
public static String JD = "_2JD";
public static String AIFL = "[_1IFL";
public static String AJD = "[_2JD";
static String[] descs = new String[] { IFL, JD, "L", "Z", "B", "C", "S", "I", "F", "J", "D" };
static String[] descsArray = new String[] { AIFL, AJD, "[L", "[Z", "[B", "[C", "[S", "[I", "[F", "[J", "[D" };
@Override
public void visitArrayStmt(int opcode, int formOrToReg, int arrayReg, int indexReg, int xt) {
useAndType(arrayReg, descsArray[xt]);
useAndType(indexReg, "I");
if (opcode == OP_AGET) {
newAndType(formOrToReg, descs[xt]);
} else {
useAndType(formOrToReg, descs[xt]);
}
}
@Override
public void visitBinopLitXStmt(int opcode, int distReg, int srcReg, int content) {
useAndType(srcReg, "I");
newAndType(distReg, "I");
}
@Override
public void visitBinopStmt(int opcode, int toReg, int r1, int r2, int xt) {
useAndType(r1, "I");
useAndType(r2, "I");
newAndType(toReg, "I");
}
@Override
public void visitClassStmt(int opcode, int a, int b, String type) {
if (opcode == OP_INSTANCE_OF) {
useAndType(b, "L");
newAndType(a, "Z");
} else {
useAndType(b, "I");
newAndType(a, type);
}
}
@Override
public void visitClassStmt(int opcode, int saveTo, String type) {
if (opcode == OP_CHECK_CAST) {
useAndType(saveTo, "L");
}
newAndType(saveTo, type);
}
@Override
public void visitCmpStmt(int opcode, int distReg, int bB, int cC, int xt) {
useAndType(bB, descs[xt]);
useAndType(cC, descs[xt]);
newAndType(distReg, "I");
}
@Override
public void visitConstStmt(int opcode, int toReg, Object value, int xt) {
if (opcode == OP_CONST_CLASS) {
newAndType(toReg, "Ljava/lang/Class;");
} else if (opcode == OP_CONST_STRING) {
newAndType(toReg, "Ljava/lang/String;");
} else {
newAndType(toReg, descs[xt]);
}
}
@Override
public void visitFieldStmt(int opcode, int fromOrToReg, Field field, int xt) {
if (opcode == OP_SGET) {
newAndType(fromOrToReg, field.getType());
} else {
useAndType(fromOrToReg, field.getType());
}
}
@Override
public void visitFieldStmt(int opcode, int fromOrToReg, int objReg, Field field, int xt) {
useAndType(objReg, field.getOwner());
if (opcode == OP_IGET) {
newAndType(fromOrToReg, field.getType());
} else {
useAndType(fromOrToReg, field.getType());
}
}
@Override
public void visitFillArrayStmt(int opcode, int aA, int elemWidth, int initLength, Object[] values) {
newAndType(aA, "[");
}
@Override
public void visitFilledNewArrayStmt(int opcode, int[] args, String type) {
String eType = type.substring(1);
for (int arg : args) {
useAndType(arg, eType);
}
newAndType(totalReg, type);
}
@Override
public void visitJumpStmt(int opcode, int a, int b, DexLabel label) {
if (opcode == OP_IF_EQ || opcode == OP_IF_NE) {
useAndType(a, IL);
useAndType(b, IL);
} else {
useAndType(a, "I");
useAndType(b, "I");
}
}
@Override
public void visitJumpStmt(int opcode, int a, DexLabel label) {
if (opcode == OP_IF_EQZ || opcode == OP_IF_NEZ) {
useAndType(a, IL);
} else {
useAndType(a, "I");
}
}
@Override
public void visitJumpStmt(int opcode, DexLabel label) {
}
@Override
public void visitLookupSwitchStmt(int opcode, int aA, DexLabel label, int[] cases, DexLabel[] labels) {
useAndType(aA, "I");
}
@Override
public void visitMethodStmt(int opcode, int[] args, Method method) {
int i = 0;
if (opcode != OP_INVOKE_STATIC) {
useAndType(args[i], method.getOwner());
i++;
}
for (String ps : method.getParameterTypes()) {
useAndType(args[i], ps);
i++;
}
if (!"V".equals(method.getReturnType())) {
newAndType(totalReg, method.getReturnType());
}
}
@Override
public void visitMonitorStmt(int opcode, int reg) {
useAndType(reg, "L");
}
@Override
public void visitMoveStmt(int opcode, int toReg, int xt) {
if (opcode == OP_MOVE_RESULT) {
useAndType(totalReg, descs[xt]);
_put(totalReg, null);
} else {
useAndType(totalReg + 1, descs[xt]);
_put(totalReg + 1, null);
}
newAndType(toReg, descs[xt]);
}
@Override
public void visitMoveStmt(int opcode, int toReg, int fromReg, int xt) {
useAndType(fromReg, descs[xt]);
newAndType(toReg, descs[xt]);
}
@Override
public void visitReturnStmt(int opcode) {
}
@Override
public void visitReturnStmt(int opcode, int reg, int xt) {
if (opcode == OP_THROW) {
useAndType(reg, "Ljava/lang/Throwable;");
} else {
useAndType(reg, this.returnType);
}
}
@Override
public void visitTableSwitchStmt(int opcode, int aA, DexLabel label, int first_case, int last_case,
DexLabel[] labels) {
useAndType(aA, "I");
}
@Override
public void visitUnopStmt(int opcode, int toReg, int fromReg, int xt) {
if (opcode == OP_ARRAY_LENGTH) {
useAndType(fromReg, "[");
newAndType(toReg, "I");
} else {
useAndType(fromReg, descs[xt]);
newAndType(toReg, descs[xt]);
}
}
@Override
public void visitUnopStmt(int opcode, int toReg, int fromReg, int xta, int xtb) {
useAndType(fromReg, descs[xta]);
newAndType(toReg, descs[xtb]);
}
@Override
public void visitTryCatch(DexLabel start, DexLabel end, DexLabel handler, String type) {
}
@Override
public void visitArguments(int total, int[] args) {
}
@Override
public void visitEnd() {
}
@Override
public void visitLabel(DexLabel label) {
}
@Override
public void visitLineNumber(int line, DexLabel label) {
}
@Override
public void visitLocalVariable(String name, String type, String signature, DexLabel start, DexLabel end, int reg) {
}
@Override
public void visitReturnStmt(int opcode, int cause, Object ref) {
}
@Override
public void visitMethodStmt(int opcode, int[] args, int a) {
for (int i = 0; i < args.length; i += _size(args[i])) {
_use(args[i]);
}
_put(totalReg, _new());
}
@Override
public void visitFieldStmt(int opcode, int fromOrToReg, int objReg, int fieldoff, int xt) {
useAndType(objReg, "L");
if (opcode == OP_IGET_QUICK) {
newAndType(fromOrToReg, descs[xt]);
} else {
useAndType(fromOrToReg, descs[xt]);
}
}
}

View File

@ -648,7 +648,7 @@ import com.googlecode.dex2jar.visitors.DexCodeVisitor;
*/
void order(int offset) {
if (!labels.containsKey(offset)) {
labels.put(offset, new DexLabel());
labels.put(offset, new DexLabel(offset));
}
}
}

View File

@ -278,7 +278,7 @@ public abstract class AbstractDumpDexCodeAdapter extends EmptyVisitor {
public void visitJumpStmt(int opcode, DexLabel label) {
switch (opcode) {
case OP_GOTO:
info(opcode, "goto L%s", labelToString(label));
info(opcode, "goto %s", labelToString(label));
break;
}
}
@ -286,22 +286,22 @@ public abstract class AbstractDumpDexCodeAdapter extends EmptyVisitor {
public void visitJumpStmt(int opcode, int reg, DexLabel label) {
switch (opcode) {
case OP_IF_EQZ:
info(opcode, "if v%d == 0 goto L%s", reg, labelToString(label));
info(opcode, "if v%d == 0 goto %s", reg, labelToString(label));
break;
case OP_IF_NEZ:
info(opcode, "if v%d != 0 goto L%s", reg, labelToString(label));
info(opcode, "if v%d != 0 goto %s", reg, labelToString(label));
break;
case OP_IF_LTZ:
info(opcode, "if v%d < 0 goto L%s", reg, labelToString(label));
info(opcode, "if v%d < 0 goto %s", reg, labelToString(label));
break;
case OP_IF_GEZ:
info(opcode, "if v%d >= 0 goto L%s", reg, labelToString(label));
info(opcode, "if v%d >= 0 goto %s", reg, labelToString(label));
break;
case OP_IF_GTZ:
info(opcode, "if v%d > 0 goto L%s", reg, labelToString(label));
info(opcode, "if v%d > 0 goto %s", reg, labelToString(label));
break;
case OP_IF_LEZ:
info(opcode, "if v%d <= 0 goto L%s", reg, labelToString(label));
info(opcode, "if v%d <= 0 goto %s", reg, labelToString(label));
break;
}
}
@ -315,22 +315,22 @@ public abstract class AbstractDumpDexCodeAdapter extends EmptyVisitor {
public void visitJumpStmt(int opcode, int reg1, int reg2, DexLabel label) {
switch (opcode) {
case OP_IF_EQ:
info(opcode, "if v%d == v%d goto L%s", reg1, reg2, labelToString(label));
info(opcode, "if v%d == v%d goto %s", reg1, reg2, labelToString(label));
break;
case OP_IF_NE:
info(opcode, "if v%d != v%d goto L%s", reg1, reg2, labelToString(label));
info(opcode, "if v%d != v%d goto %s", reg1, reg2, labelToString(label));
break;
case OP_IF_LT:
info(opcode, "if v%d < v%d goto L%s", reg1, reg2, labelToString(label));
info(opcode, "if v%d < v%d goto %s", reg1, reg2, labelToString(label));
break;
case OP_IF_GE:
info(opcode, "if v%d >= v%d goto L%s", reg1, reg2, labelToString(label));
info(opcode, "if v%d >= v%d goto %s", reg1, reg2, labelToString(label));
break;
case OP_IF_GT:
info(opcode, "if v%d > v%d goto L%s", reg1, reg2, labelToString(label));
info(opcode, "if v%d > v%d goto %s", reg1, reg2, labelToString(label));
break;
case OP_IF_LE:
info(opcode, "if v%d <= v%d goto L%s", reg1, reg2, labelToString(label));
info(opcode, "if v%d <= v%d goto %s", reg1, reg2, labelToString(label));
break;
}
}
@ -344,9 +344,9 @@ public abstract class AbstractDumpDexCodeAdapter extends EmptyVisitor {
public void visitLookupSwitchStmt(int opcode, int reg, DexLabel label, int[] cases, DexLabel[] label2) {
info(opcode, "switch(v%d)", reg);
for (int i = 0; i < cases.length; i++) {
info(-1, "case %d: goto L%s", cases[i], labelToString(label2[i]));
info(-1, "case %d: goto %s", cases[i], labelToString(label2[i]));
}
info(-1, "default: goto L%s", labelToString(label));
info(-1, "default: goto %s", labelToString(label));
}
@Override
@ -413,7 +413,6 @@ public abstract class AbstractDumpDexCodeAdapter extends EmptyVisitor {
info(opcode, "v%d.%s(%s) //%s", regs[0], method.getName(), sb.toString(), method.toString());
} else {
info(opcode, "TEMP=v%d.%s(%s) //%s", regs[0], method.getName(), sb.toString(), method.toString());
}
}
break;
@ -441,9 +440,11 @@ public abstract class AbstractDumpDexCodeAdapter extends EmptyVisitor {
public void visitMoveStmt(int opcode, int reg, int xt) {
switch (opcode) {
case OP_MOVE_RESULT:
case OP_MOVE_EXCEPTION:
info(opcode, "v%d=TEMP", reg);
break;
case OP_MOVE_EXCEPTION:
info(opcode, "v%d=@Exception", reg);
break;
}
}
@ -497,9 +498,9 @@ public abstract class AbstractDumpDexCodeAdapter extends EmptyVisitor {
DexLabel[] labels) {
info(opcode, "switch(v%d)", reg);
for (int i = 0; i < labels.length; i++) {
info(opcode, "case %d: goto L%s", first_case + i, labelToString(labels[i]));
info(opcode, "case %d: goto %s", first_case + i, labelToString(labels[i]));
}
info(opcode, "default: goto L%s", labelToString(label));
info(opcode, "default: goto %s", labelToString(label));
}
@Override

View File

@ -1,4 +0,0 @@
package com.googlecode.dex2jar.xir;
public class Ax {
}

View File

@ -0,0 +1,59 @@
package com.googlecode.dex2jar.test;
import java.io.File;
import org.junit.Test;
import org.objectweb.asm.Opcodes;
import com.googlecode.dex2jar.Method;
import com.googlecode.dex2jar.analysis.CodeNode;
import com.googlecode.dex2jar.analysis.type.TypeAnalyzer;
import com.googlecode.dex2jar.reader.DexFileReader;
import com.googlecode.dex2jar.v3.Main;
import com.googlecode.dex2jar.visitors.DexClassVisitor;
import com.googlecode.dex2jar.visitors.DexCodeVisitor;
import com.googlecode.dex2jar.visitors.DexMethodVisitor;
import com.googlecode.dex2jar.visitors.EmptyVisitor;
public class TypeAnalyzerTest {
@Test
public void test() throws Exception {
try {
for (File f : TestUtils.listTestDexFiles()) {
System.out.println("tyep-analyze file " + f);
new DexFileReader(f).accept(new EmptyVisitor() {
@Override
public DexClassVisitor visit(int access_flags, String className, String superClass,
String[] interfaceNames) {
return this;
}
Method method;
boolean isStatic;
@Override
public DexMethodVisitor visitMethod(int accessFlags, Method method) {
this.method = method;
this.isStatic = (accessFlags & Opcodes.ACC_STATIC) != 0;
return this;
}
@Override
public DexCodeVisitor visitCode() {
return new CodeNode() {
@Override
public void visitEnd() {
new TypeAnalyzer(this, isStatic, method).analyze();
}
};
}
}, DexFileReader.SKIP_DEBUG);
}
} catch (Exception e) {
Main.niceExceptionMessage(e, 0);
throw e;
}
}
}