use of com.googlecode.d2j.node.DexMethodNode in project dex2jar by pxb1988.
the class DexFix method fixStaticFinalFieldValue.
/**
* init value to default if the field is static and final, and the field is not init in clinit method
*
* erase the default value if the field is init in clinit method
*
* @param classNode
*/
public static void fixStaticFinalFieldValue(final DexClassNode classNode) {
if (classNode.fields == null) {
return;
}
final Map<String, DexFieldNode> fs = new HashMap<>();
final Map<String, DexFieldNode> shouldNotBeAssigned = new HashMap<>();
for (DexFieldNode fn : classNode.fields) {
if ((fn.access & ACC_STATIC_FINAL) == ACC_STATIC_FINAL) {
if (fn.cst == null) {
char t = fn.field.getType().charAt(0);
if (t == 'L' || t == '[') {
// ignore Object
continue;
}
fs.put(fn.field.getName() + ":" + fn.field.getType(), fn);
} else if (isPrimitiveZero(fn.field.getType(), fn.cst)) {
shouldNotBeAssigned.put(fn.field.getName() + ":" + fn.field.getType(), fn);
}
}
}
if (fs.isEmpty() && shouldNotBeAssigned.isEmpty()) {
return;
}
DexMethodNode node = null;
if (classNode.methods != null) {
for (DexMethodNode mn : classNode.methods) {
if (mn.method.getName().equals("<clinit>")) {
node = mn;
break;
}
}
}
if (node != null) {
if (node.codeNode != null) {
node.codeNode.accept(new DexCodeVisitor() {
@Override
public void visitFieldStmt(Op op, int a, int b, Field field) {
switch(op) {
case SPUT:
case SPUT_BOOLEAN:
case SPUT_BYTE:
case SPUT_CHAR:
case SPUT_OBJECT:
case SPUT_SHORT:
case SPUT_WIDE:
if (field.getOwner().equals(classNode.className)) {
String key = field.getName() + ":" + field.getType();
fs.remove(key);
DexFieldNode dn = shouldNotBeAssigned.get(key);
if (dn != null) {
//System.out.println(field.getName() + ":" + field.getType());
dn.cst = null;
}
}
break;
default:
// ignored
break;
}
}
});
} else {
// has init but no code
return;
}
}
for (DexFieldNode fn : fs.values()) {
fn.cst = getDefaultValueOfType(fn.field.getType().charAt(0));
}
}
use of com.googlecode.d2j.node.DexMethodNode in project dex2jar by pxb1988.
the class BaksmaliBaseDexExceptionHandler method dumpTxt0.
private void dumpTxt0(BufferedWriter writer, String[] originalArgs) throws IOException {
dumpSummary(originalArgs, writer);
int i = 0;
for (Map.Entry<DexMethodNode, Exception> e : exceptionMap.entrySet()) {
DexMethodNode dexMethodNode = e.getKey();
Exception ex = e.getValue();
writer.newLine();
writer.write("================= " + i++ + " ===================");
writer.newLine();
dumpMethod(writer, dexMethodNode, ex);
}
}
use of com.googlecode.d2j.node.DexMethodNode in project dex2jar by pxb1988.
the class DexWeaver method wrap.
public DexClassVisitor wrap(final String classNameDesc, final DexClassVisitor dcv) {
return dcv == null ? null : new DexClassVisitor(dcv) {
Map<MtdInfo, Method> cache = new HashMap<>();
@Override
public DexMethodVisitor visitMethod(final int accessFlags, Method method) {
final DexMethodVisitor dmv = superVisitDexMethod(accessFlags, method);
final MtdInfo mapTo = findDefinedTargetMethod(method.getOwner(), method.getName(), method.getDesc());
if (mapTo != null) {
final Method t = new Method(method.getOwner(), buildMethodAName(method.getName()), method.getParameterTypes(), method.getReturnType());
final Method src = method;
return new DexMethodNode(accessFlags, method) {
@Override
public void visitEnd() {
super.visitEnd();
DexCodeNode code = this.codeNode;
this.codeNode = null;
accept(dmv);
Op opcode;
if (Modifier.isStatic(access)) {
opcode = Op.INVOKE_STATIC_RANGE;
} else {
opcode = Op.INVOKE_VIRTUAL_RANGE;
}
generateMtdACode(opcode, t, mapTo, dmv, src);
// make sure public
int newAccess = (access & ~(DexConstants.ACC_PRIVATE | DexConstants.ACC_PROTECTED)) | DexConstants.ACC_PUBLIC;
code.accept(wrap(superVisitDexMethod(newAccess, t), dcv));
}
};
} else {
return wrap(dmv, dcv);
}
}
private DexMethodVisitor wrap(DexMethodVisitor dmv, final DexClassVisitor classVisitor) {
return dmv == null ? null : new DexMethodVisitor(dmv) {
@Override
public DexCodeVisitor visitCode() {
return wrap(super.visitCode(), classVisitor);
}
};
}
private DexCodeVisitor wrap(DexCodeVisitor dcv, final DexClassVisitor classVisitor) {
return dcv == null ? null : new DexCodeVisitor(dcv) {
@Override
public void visitMethodStmt(Op op, int[] args, Method method) {
MtdInfo mapTo = findTargetMethod(method.getOwner(), method.getName(), method.getDesc());
if (mapTo != null) {
Method methodA = cache.get(buildKey(method.getOwner(), method.getName(), method.getDesc()));
if (methodA == null) {
if (isStatic(op)) {
methodA = new Method(classNameDesc, buildMethodAName(method.getName()), method.getParameterTypes(), method.getReturnType());
} else {
methodA = new Method(classNameDesc, buildMethodAName(method.getName()), join(method.getOwner(), method.getParameterTypes()), method.getReturnType());
}
DexMethodVisitor dmv = classVisitor.visitMethod(DexConstants.ACC_PRIVATE | DexConstants.ACC_STATIC, methodA);
generateMtdACode(op, method, mapTo, dmv, method);
dmv.visitEnd();
cache.put(buildKey(method.getOwner(), method.getName(), method.getDesc()), methodA);
}
super.visitMethodStmt(isRange(op) ? Op.INVOKE_STATIC_RANGE : Op.INVOKE_STATIC, args, methodA);
} else {
super.visitMethodStmt(op, args, method);
}
}
};
}
private void generateMtdACode(Op opcode, Method t, MtdInfo mapTo, DexMethodVisitor dmv, Method src) {
DexCodeVisitor dcv = dmv.visitCode();
int countArge = countArgs(t);
boolean haveThis = haveThis(opcode);
int registers = 4 + (haveThis ? 1 : 0) + countArge;
dcv.visitRegister(registers);
int argStart = 4;
if (haveThis) {
dcv.visitStmt2R(Op.MOVE_OBJECT, 0, argStart);
argStart++;
} else {
dcv.visitConstStmt(Op.CONST_4, 0, 0);
}
if (t.getParameterTypes().length == 0) {
dcv.visitConstStmt(Op.CONST_4, 1, 0);
} else {
dcv.visitConstStmt(Op.CONST, 1, t.getParameterTypes().length);
dcv.visitTypeStmt(Op.NEW_ARRAY, 1, 1, "[Ljava/lang/Object;");
for (int i = 0; i < t.getParameterTypes().length; i++) {
char type = t.getParameterTypes()[i].charAt(0);
dcv.visitConstStmt(Op.CONST, 2, i);
box(type, argStart, 3, dcv);
dcv.visitStmt3R(Op.APUT_OBJECT, 3, 1, 2);
if (type == 'J' || type == 'D') {
argStart += 2;
} else {
argStart += 1;
}
}
}
int nextIdx = callbacks.size();
dcv.visitConstStmt(Op.CONST, 2, nextIdx);
String miTypeDesc = "L" + getCurrentInvocationName() + ";";
dcv.visitTypeStmt(Op.NEW_INSTANCE, 3, 0, miTypeDesc);
dcv.visitMethodStmt(Op.INVOKE_DIRECT, new int[] { 3, 0, 1, 2 }, new Method(miTypeDesc, "<init>", new String[] { "Ljava/lang/Object;", "[Ljava/lang/Object;", "I" }, "V"));
Method call = build(mapTo);
dcv.visitMethodStmt(Op.INVOKE_STATIC, new int[] { 3 }, call);
if (!"V".equals(t.getReturnType())) {
switch(call.getReturnType().charAt(0)) {
case '[':
case 'L':
dcv.visitStmt1R(Op.MOVE_RESULT_OBJECT, 0);
break;
case 'J':
case 'D':
dcv.visitStmt1R(Op.MOVE_RESULT_WIDE, 0);
break;
default:
dcv.visitStmt1R(Op.MOVE_RESULT, 0);
break;
}
unbox(t.getReturnType(), 0, dcv);
switch(t.getReturnType().charAt(0)) {
case '[':
case 'L':
dcv.visitStmt1R(Op.RETURN_OBJECT, 0);
break;
case 'J':
case 'D':
dcv.visitStmt1R(Op.RETURN_WIDE, 0);
break;
default:
dcv.visitStmt1R(Op.RETURN, 0);
break;
}
} else {
dcv.visitStmt0R(Op.RETURN_VOID);
}
Callback cb = new Callback();
cb.idx = nextIdx;
cb.callback = newMethodCallback(opcode, t);
cb.target = src;
cb.isSpecial = isSuper(opcode);
cb.isStatic = isStatic(opcode);
callbacks.add(cb);
}
private Method newMethodCallback(Op opcode, Method t) {
boolean isStatic = !haveThis(opcode);
boolean isSuper = isSuper(opcode);
Method m;
if (isSuper || isStatic) {
m = new Method(t.getOwner(), buildCallbackMethodName(t.getName()), new String[] { "[Ljava/lang/Object;" }, "Ljava/lang/Object;");
} else {
m = new Method(t.getOwner(), buildCallbackMethodName(t.getName()), new String[] { "Ljava/lang/Object;", "[Ljava/lang/Object;" }, "Ljava/lang/Object;");
}
DexMethodVisitor dmv = superVisitDexMethod(DexConstants.ACC_PUBLIC | (isSuper ? 0 : DexConstants.ACC_STATIC), m);
DexCodeVisitor dcv = dmv.visitCode();
int totalRegs;
int argStart;
if (isStatic) {
totalRegs = 1 + countArgs(t) + 1;
argStart = totalRegs - 1;
} else {
totalRegs = 1 + countArgs(t) + 2;
argStart = totalRegs - 2;
}
dcv.visitRegister(totalRegs);
int[] args = new int[countArgs(t) + (isStatic ? 0 : 1)];
int args_index = 0;
int i = 1;
if (!isStatic) {
if (i != argStart) {
dcv.visitStmt2R(Op.MOVE_OBJECT, i, argStart);
}
if (!isSuper) {
dcv.visitTypeStmt(Op.CHECK_CAST, i, -1, t.getOwner());
}
args[args_index++] = i;
i++;
argStart++;
}
String[] parameterTypes = t.getParameterTypes();
for (int i1 = 0; i1 < parameterTypes.length; i1++) {
String argType = parameterTypes[i1];
dcv.visitConstStmt(Op.CONST, 0, i1);
dcv.visitStmt3R(Op.AGET_OBJECT, i, argStart, 0);
unbox(argType, i, dcv);
args[args_index++] = i;
if (argType.charAt(0) == 'J' || argType.charAt(0) == 'D') {
args[args_index++] = i + 1;
i += 2;
} else {
i += 1;
}
}
dcv.visitMethodStmt(opcode, args, t);
if ("V".equals(t.getReturnType())) {
dcv.visitConstStmt(Op.CONST, 0, 0);
} else {
switch(t.getReturnType().charAt(0)) {
case '[':
case 'L':
dcv.visitStmt1R(Op.MOVE_RESULT_OBJECT, 0);
break;
case 'J':
case 'D':
dcv.visitStmt1R(Op.MOVE_RESULT_WIDE, 0);
break;
default:
dcv.visitStmt1R(Op.MOVE_RESULT, 0);
break;
}
box(t.getReturnType().charAt(0), 0, 0, dcv);
}
dcv.visitStmt1R(Op.RETURN_OBJECT, 0);
return m;
}
private DexMethodVisitor superVisitDexMethod(int accessFlags, Method method) {
return super.visitMethod(accessFlags, method);
}
};
}
use of com.googlecode.d2j.node.DexMethodNode in project dex2jar by pxb1988.
the class Dex2jar method doTranslate.
private void doTranslate(final Path dist) throws IOException {
DexFileNode fileNode = new DexFileNode();
try {
reader.accept(fileNode, readerConfig | DexFileReader.IGNORE_READ_EXCEPTION);
} catch (Exception ex) {
exceptionHandler.handleFileException(ex);
}
ClassVisitorFactory cvf = new ClassVisitorFactory() {
@Override
public ClassVisitor create(final String name) {
return new ClassVisitor(Opcodes.ASM4, new ClassWriter(ClassWriter.COMPUTE_MAXS)) {
@Override
public void visitEnd() {
super.visitEnd();
ClassWriter cw = (ClassWriter) super.cv;
byte[] data;
try {
// FIXME handle 'java.lang.RuntimeException: Method code too large!'
data = cw.toByteArray();
} catch (Exception ex) {
System.err.println(String.format("ASM fail to generate .class file: %s", name));
exceptionHandler.handleFileException(ex);
return;
}
try {
Path dist1 = dist.resolve(name + ".class");
Path parent = dist1.getParent();
if (parent != null && !Files.exists(parent)) {
Files.createDirectories(parent);
}
Files.write(dist1, data);
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
};
}
};
new ExDex2Asm(exceptionHandler) {
public void convertCode(DexMethodNode methodNode, MethodVisitor mv) {
if ((readerConfig & DexFileReader.SKIP_CODE) != 0 && methodNode.method.getName().equals("<clinit>")) {
// also skip clinit
return;
}
super.convertCode(methodNode, mv);
}
@Override
public void optimize(IrMethod irMethod) {
T_cleanLabel.transform(irMethod);
if (0 != (v3Config & V3.TOPOLOGICAL_SORT)) {
// T_topologicalSort.transform(irMethod);
}
T_deadCode.transform(irMethod);
T_removeLocal.transform(irMethod);
T_removeConst.transform(irMethod);
T_zero.transform(irMethod);
if (T_npe.transformReportChanged(irMethod)) {
T_deadCode.transform(irMethod);
T_removeLocal.transform(irMethod);
T_removeConst.transform(irMethod);
}
T_new.transform(irMethod);
T_fillArray.transform(irMethod);
T_agg.transform(irMethod);
T_multiArray.transform(irMethod);
T_voidInvoke.transform(irMethod);
if (0 != (v3Config & V3.PRINT_IR)) {
int i = 0;
for (Stmt p : irMethod.stmts) {
if (p.st == Stmt.ST.LABEL) {
LabelStmt labelStmt = (LabelStmt) p;
labelStmt.displayName = "L" + i++;
}
}
System.out.println(irMethod);
}
T_type.transform(irMethod);
T_unssa.transform(irMethod);
T_ir2jRegAssign.transform(irMethod);
T_trimEx.transform(irMethod);
}
@Override
public void ir2j(IrMethod irMethod, MethodVisitor mv) {
new IR2JConverter(0 != (V3.OPTIMIZE_SYNCHRONIZED & v3Config)).convert(irMethod, mv);
}
}.convertDex(fileNode, cvf);
}
use of com.googlecode.d2j.node.DexMethodNode in project dex2jar by pxb1988.
the class ExDex2Asm method convertCode.
@Override
public void convertCode(DexMethodNode methodNode, MethodVisitor mv) {
if (!AsmBridge.isMethodWriter(mv)) {
throw new RuntimeException("We use a MethodWriter tricky here!");
}
MethodNode mn = new MethodNode(Opcodes.ASM4, methodNode.access, methodNode.method.getName(), methodNode.method.getDesc(), null, null);
try {
super.convertCode(methodNode, mn);
} catch (Exception ex) {
if (exceptionHandler == null) {
throw new DexException(ex, "fail convert code for %s", methodNode.method);
} else {
mn.instructions.clear();
mn.tryCatchBlocks.clear();
exceptionHandler.handleMethodTranslateException(methodNode.method, methodNode, mn, ex);
}
}
// code convert ok, copy to MethodWriter and check for Size
mn.accept(mv);
try {
AsmBridge.sizeOfMethodWriter(mv);
} catch (Exception ex) {
mn.instructions.clear();
mn.tryCatchBlocks.clear();
exceptionHandler.handleMethodTranslateException(methodNode.method, methodNode, mn, ex);
AsmBridge.replaceMethodWriter(mv, mn);
}
}
Aggregations