use of com.googlecode.d2j.reader.Op in project dex2jar by pxb1988.
the class AntlrSmaliUtil method acceptCode.
private static void acceptCode(SmaliParser.SMethodContext ctx, final M m, DexMethodVisitor dexMethodVisitor) {
if (ctx == null || dexMethodVisitor == null) {
return;
}
final DexCodeVisitor dexCodeVisitor = dexMethodVisitor.visitCode();
if (dexCodeVisitor == null) {
return;
}
final SmaliCodeVisitor scv = new SmaliCodeVisitor(dexCodeVisitor);
final DexDebugVisitor dexDebugVisitor = scv.visitDebug();
final List<SmaliParser.SInstructionContext> instructionContexts = ctx.sInstruction();
final SmaliBaseVisitor v = new SmaliBaseVisitor() {
@Override
public Object visitFregisters(SmaliParser.FregistersContext ctx) {
return null;
}
@Override
public Object visitFlocals(SmaliParser.FlocalsContext ctx) {
return null;
}
@Override
public Object visitFline(SmaliParser.FlineContext ctx) {
if (dexDebugVisitor != null) {
DexLabel dexLabel = new DexLabel();
scv.visitLabel(dexLabel);
dexDebugVisitor.visitLineNumber(Utils.parseInt(ctx.line.getText()), dexLabel);
}
return null;
}
@Override
public Object visitFend(SmaliParser.FendContext ctx) {
if (dexDebugVisitor != null) {
DexLabel dexLabel = new DexLabel();
scv.visitLabel(dexLabel);
int reg = m.pareReg(ctx.r.getText());
dexDebugVisitor.visitEndLocal(reg, dexLabel);
}
return null;
}
@Override
public Object visitFlocal(SmaliParser.FlocalContext ctx) {
if (dexDebugVisitor != null) {
DexLabel dexLabel = new DexLabel();
scv.visitLabel(dexLabel);
int reg = m.pareReg(ctx.r.getText());
String name;
String type;
if (ctx.v1 != null) {
Field fld = parseFieldAndUnescape("Lt;", ctx.v1.getText());
name = fld.getName();
type = fld.getType();
} else if (ctx.v2 != null) {
String txt = ctx.v2.getText();
int i = findString(txt, 1, txt.length(), '\"');
name = unescapeStr(txt.substring(0, i + 1));
type = unEscapeId(txt.substring(i + 2));
} else {
if (ctx.name2 != null) {
name = unescapeStr(ctx.name2.getText());
} else {
name = unEscapeId(ctx.name1.getText());
}
type = unEscapeId(ctx.type.getText());
}
String sig = ctx.sig == null ? null : unescapeStr(ctx.sig.getText());
dexDebugVisitor.visitStartLocal(reg, dexLabel, name, type, sig);
}
return null;
}
@Override
public Object visitFrestart(SmaliParser.FrestartContext ctx) {
if (dexDebugVisitor != null) {
DexLabel dexLabel = new DexLabel();
scv.visitLabel(dexLabel);
int reg = m.pareReg(ctx.r.getText());
dexDebugVisitor.visitRestartLocal(reg, dexLabel);
}
return null;
}
@Override
public Object visitFprologue(SmaliParser.FprologueContext ctx) {
if (dexDebugVisitor != null) {
DexLabel dexLabel = new DexLabel();
scv.visitLabel(dexLabel);
dexDebugVisitor.visitPrologue(dexLabel);
}
return null;
}
Map<String, DexLabel> labelMap = new HashMap<>();
@Override
public Object visitSLabel(SmaliParser.SLabelContext ctx) {
scv.visitLabel(getLabel(ctx.label.getText()));
return null;
}
@Override
public Object visitFspareswitch(SmaliParser.FspareswitchContext ctx) {
List<TerminalNode> ints = ctx.INT();
List<TerminalNode> ts = ctx.LABEL();
int[] cases = new int[ts.size()];
DexLabel[] labels = new DexLabel[ts.size()];
for (int i = 0; i < ts.size(); i++) {
cases[i] = parseInt(ints.get(i).getSymbol().getText());
labels[i] = getLabel(ts.get(i).getSymbol().getText());
}
scv.dSparseSwitch(cases, labels);
return null;
}
@Override
public Object visitFarraydata(SmaliParser.FarraydataContext ctx) {
int size = parseInt(ctx.size.getText());
List<SmaliParser.SBaseValueContext> ts = ctx.sBaseValue();
byte[] ps = new byte[ts.size()];
for (int i = 0; i < ts.size(); i++) {
ps[i] = ((Number) parseBaseValue(ts.get(i))).byteValue();
}
scv.dArrayData(size, ps);
return null;
}
Op getOp(Token t) {
return Utils.getOp(t.getText());
}
@Override
public Object visitF0x(SmaliParser.F0xContext ctx) {
scv.visitStmt0R(getOp(ctx.op));
return null;
}
@Override
public Object visitF0t(SmaliParser.F0tContext ctx) {
scv.visitJumpStmt(getOp(ctx.op), 0, 0, getLabel(ctx.target.getText()));
return null;
}
@Override
public Object visitF1x(SmaliParser.F1xContext ctx) {
scv.visitStmt1R(getOp(ctx.op), m.pareReg(ctx.r1.getText()));
return null;
}
@Override
public Object visitFconst(SmaliParser.FconstContext ctx) {
Op op = getOp(ctx.op);
int r = m.pareReg(ctx.r1.getText());
Token cst = ctx.cst;
switch(op) {
case CONST_STRING:
case CONST_STRING_JUMBO:
scv.visitConstStmt(op, r, unescapeStr(cst.getText()));
break;
case CONST_CLASS:
scv.visitConstStmt(op, r, new DexType(unEscapeId(cst.getText())));
break;
case CHECK_CAST:
case NEW_INSTANCE:
scv.visitTypeStmt(op, r, 0, unEscapeId(cst.getText()));
break;
case CONST_WIDE:
scv.visitConstStmt(op, r, cst.getType() == SmaliLexer.INT ? ((long) parseInt(cst.getText())) : parseLong(cst.getText()));
break;
case CONST_WIDE_16:
{
long v;
if (cst.getType() == SmaliLexer.LONG) {
v = parseLong(cst.getText());
} else {
v = (short) parseInt(cst.getText());
}
scv.visitConstStmt(op, r, v);
}
break;
case CONST_WIDE_32:
{
long v;
if (cst.getType() == SmaliLexer.LONG) {
v = parseLong(cst.getText());
} else {
v = parseInt(cst.getText());
}
scv.visitConstStmt(op, r, v);
}
break;
case CONST_WIDE_HIGH16:
{
long v;
if (cst.getType() == SmaliLexer.LONG) {
v = parseLong(cst.getText());
} else {
v = (short) parseInt(cst.getText());
v <<= 48;
}
scv.visitConstStmt(op, r, v);
}
break;
case CONST:
case CONST_4:
case CONST_16:
{
int v = parseInt(cst.getText());
scv.visitConstStmt(op, r, v);
}
break;
case CONST_HIGH16:
{
int v = parseInt(cst.getText());
v <<= 16;
scv.visitConstStmt(op, r, v);
}
break;
default:
throw new RuntimeException();
}
return null;
}
@Override
public Object visitFf1c(SmaliParser.Ff1cContext ctx) {
int r = m.pareReg(ctx.r1.getText());
Field field = parseFieldAndUnescape(ctx.fld.getText());
scv.visitFieldStmt(getOp(ctx.op), r, 0, field);
return null;
}
@Override
public Object visitFt2c(SmaliParser.Ft2cContext ctx) {
int r1 = m.pareReg(ctx.r1.getText());
int r2 = m.pareReg(ctx.r2.getText());
scv.visitTypeStmt(getOp(ctx.op), r1, r2, unEscapeId(ctx.type.getText()));
return null;
}
@Override
public Object visitFf2c(SmaliParser.Ff2cContext ctx) {
int r1 = m.pareReg(ctx.r1.getText());
int r2 = m.pareReg(ctx.r2.getText());
scv.visitFieldStmt(getOp(ctx.op), r1, r2, parseFieldAndUnescape(ctx.fld.getText()));
return null;
}
@Override
public Object visitF2x(SmaliParser.F2xContext ctx) {
int r1 = m.pareReg(ctx.r1.getText());
int r2 = m.pareReg(ctx.r2.getText());
scv.visitStmt2R(getOp(ctx.op), r1, r2);
return null;
}
@Override
public Object visitF3x(SmaliParser.F3xContext ctx) {
int r1 = m.pareReg(ctx.r1.getText());
int r2 = m.pareReg(ctx.r2.getText());
int r3 = m.pareReg(ctx.r3.getText());
scv.visitStmt3R(getOp(ctx.op), r1, r2, r3);
return null;
}
@Override
public Object visitFt5c(SmaliParser.Ft5cContext ctx) {
Op op = getOp(ctx.op);
List<TerminalNode> ts = ctx.REGISTER();
int[] rs = new int[ts.size()];
for (int i = 0; i < ts.size(); i++) {
rs[i] = m.pareReg(ts.get(i).getSymbol().getText());
}
scv.visitFilledNewArrayStmt(op, rs, unEscapeId(ctx.type.getText()));
return null;
}
@Override
public Object visitFm5c(SmaliParser.Fm5cContext ctx) {
Op op = getOp(ctx.op);
List<TerminalNode> ts = ctx.REGISTER();
int[] rs = new int[ts.size()];
for (int i = 0; i < ts.size(); i++) {
rs[i] = m.pareReg(ts.get(i).getSymbol().getText());
}
scv.visitMethodStmt(op, rs, parseMethodAndUnescape(ctx.method.getText()));
return null;
}
@Override
public Object visitFmrc(SmaliParser.FmrcContext ctx) {
if (ctx.rstart != null) {
int start = m.pareReg(ctx.rstart.getText());
int end = m.pareReg(ctx.rend.getText());
int size = end - start + 1;
int[] rs = new int[size];
for (int i = 0; i < size; i++) {
rs[i] = start + i;
}
scv.visitMethodStmt(getOp(ctx.op), rs, parseMethodAndUnescape(ctx.method.getText()));
} else {
scv.visitMethodStmt(getOp(ctx.op), new int[0], parseMethodAndUnescape(ctx.method.getText()));
}
return null;
}
@Override
public Object visitFtrc(SmaliParser.FtrcContext ctx) {
if (ctx.rstart != null) {
int start = m.pareReg(ctx.rstart.getText());
int end = m.pareReg(ctx.rend.getText());
int size = end - start + 1;
int[] rs = new int[size];
for (int i = 0; i < size; i++) {
rs[i] = start + i;
}
scv.visitFilledNewArrayStmt(getOp(ctx.op), rs, unEscapeId(ctx.type.getText()));
} else {
scv.visitFilledNewArrayStmt(getOp(ctx.op), new int[0], unEscapeId(ctx.type.getText()));
}
return null;
}
@Override
public Object visitF31t(SmaliParser.F31tContext ctx) {
scv.visitF31tStmt(getOp(ctx.op), m.pareReg(ctx.r1.getText()), getLabel(ctx.label.getText()));
return null;
}
@Override
public Object visitF1t(SmaliParser.F1tContext ctx) {
scv.visitJumpStmt(getOp(ctx.op), m.pareReg(ctx.r1.getText()), 0, getLabel(ctx.label.getText()));
return null;
}
@Override
public Object visitF2t(SmaliParser.F2tContext ctx) {
scv.visitJumpStmt(getOp(ctx.op), m.pareReg(ctx.r1.getText()), m.pareReg(ctx.r2.getText()), getLabel(ctx.label.getText()));
return null;
}
@Override
public Object visitF2sb(SmaliParser.F2sbContext ctx) {
scv.visitStmt2R1N(getOp(ctx.op), m.pareReg(ctx.r1.getText()), m.pareReg(ctx.r2.getText()), parseInt(ctx.lit.getText()));
return null;
}
@Override
public Object visitFpackageswitch(SmaliParser.FpackageswitchContext ctx) {
int start = parseInt(ctx.start.getText());
List<TerminalNode> ts = ctx.LABEL();
DexLabel[] labels = new DexLabel[ts.size()];
for (int i = 0; i < ts.size(); i++) {
labels[i] = getLabel(ts.get(i).getSymbol().getText());
}
scv.dPackedSwitch(start, labels);
return null;
}
@Override
public Object visitFcache(SmaliParser.FcacheContext ctx) {
scv.visitTryCatch(getLabel(ctx.start.getText()), getLabel(ctx.end.getText()), new DexLabel[] { getLabel(ctx.handle.getText()) }, new String[] { unEscapeId(ctx.type.getText()) });
return null;
}
@Override
public Object visitFcacheall(SmaliParser.FcacheallContext ctx) {
scv.visitTryCatch(getLabel(ctx.start.getText()), getLabel(ctx.end.getText()), new DexLabel[] { getLabel(ctx.handle.getText()) }, new String[] { null });
return null;
}
DexLabel getLabel(String name) {
DexLabel dexLabel = labelMap.get(name);
if (dexLabel == null) {
dexLabel = new DexLabel();
labelMap.put(name, dexLabel);
}
return dexLabel;
}
@Override
public Object visitFepiogue(SmaliParser.FepiogueContext ctx) {
if (dexDebugVisitor != null) {
DexLabel dexLabel = new DexLabel();
scv.visitLabel(dexLabel);
dexDebugVisitor.visitEpiogue(dexLabel);
}
return null;
}
};
scv.visitRegister(m.total);
if (dexDebugVisitor != null) {
for (int i = 0; i < m.paramNames.length; i++) {
String name = m.paramNames[i];
if (name != null) {
dexDebugVisitor.visitParameterName(i, name);
}
}
}
for (SmaliParser.SInstructionContext instructionContext : instructionContexts) {
ParserRuleContext parserRuleContext = (ParserRuleContext) instructionContext.getChild(0);
parserRuleContext.accept(v);
}
scv.visitEnd();
}
use of com.googlecode.d2j.reader.Op in project dex2jar by pxb1988.
the class BaksmaliDumper method baksmaliCode.
public void baksmaliCode(DexMethodNode methodNode, DexCodeNode codeNode, Out out) {
final List<DexLabel> allLabel = new ArrayList<>();
final Set<DexLabel> usedLabel = new HashSet<>();
codeNode.accept(new DexCodeVisitor() {
@Override
public void visitJumpStmt(Op op, int a, int b, DexLabel label) {
usedLabel.add(label);
}
@Override
public void visitPackedSwitchStmt(Op op, int aA, int first_case, DexLabel[] labels) {
usedLabel.addAll(Arrays.asList(labels));
}
@Override
public void visitTryCatch(DexLabel start, DexLabel end, DexLabel[] handler, String[] type) {
usedLabel.add(start);
usedLabel.add(end);
usedLabel.addAll(Arrays.asList(handler));
}
@Override
public void visitLabel(DexLabel label) {
allLabel.add(label);
}
@Override
public void visitSparseSwitchStmt(Op op, int ra, int[] cases, DexLabel[] labels) {
usedLabel.addAll(Arrays.asList(labels));
}
});
Map<DexLabel, List<DexDebugNode.DexDebugOpNode>> debugLabelMap = new HashMap<>();
if (codeNode.debugNode != null) {
DexDebugNode debugNode = codeNode.debugNode;
for (DexDebugNode.DexDebugOpNode opNode : debugNode.debugNodes) {
List<DexDebugNode.DexDebugOpNode> list = debugLabelMap.get(opNode.label);
if (list == null) {
list = new ArrayList<>(3);
debugLabelMap.put(opNode.label, list);
}
list.add(opNode);
}
}
int nextLabelNumber = 0;
for (DexLabel label : allLabel) {
if (usedLabel.contains(label)) {
label.displayName = "L" + nextLabelNumber++;
}
}
int inRegs = Utils.methodIns(methodNode.method, (methodNode.access & ACC_STATIC) != 0);
DexCodeVisitor dexCodeVisitor = new BaksmaliCodeDumper(out, useParameterRegisters, useLocals, nextLabelNumber, codeNode.totalRegister - inRegs, usedLabel, debugLabelMap);
accept(out, codeNode, dexCodeVisitor);
dexCodeVisitor.visitEnd();
}
use of com.googlecode.d2j.reader.Op in project dex2jar by pxb1988.
the class DexWeaverCmd method doCommandLine.
@Override
protected void doCommandLine() throws Exception {
if (remainingArgs.length == 0) {
throw new HelpException("no odex");
}
final Map<String, Method> map = new HashMap<>();
for (String ln : Files.readAllLines(config, StandardCharsets.UTF_8)) {
if (ln.startsWith("#") || ln.length() == 0) {
continue;
}
String[] x = ln.split("=");
map.put(x[0], parseMethod(x[1]));
}
DexFileWriter out = new DexFileWriter();
DexFileVisitor fv = new DexFileVisitor(out) {
@Override
public DexClassVisitor visit(int access_flags, String className, String superClass, String[] interfaceNames) {
DexClassVisitor dcv = super.visit(access_flags, className, superClass, interfaceNames);
if (dcv != null) {
return new DexClassVisitor(dcv) {
@Override
public DexMethodVisitor visitMethod(int accessFlags, Method method) {
DexMethodVisitor dmv = super.visitMethod(accessFlags, method);
if (dmv != null) {
return new DexMethodVisitor(dmv) {
@Override
public DexCodeVisitor visitCode() {
DexCodeVisitor code = super.visitCode();
if (code != null) {
return new DexCodeVisitor(code) {
@Override
public void visitMethodStmt(Op op, int[] args, Method method) {
Method replaceTo = map.get(method.toString());
if (replaceTo != null) {
switch(op) {
case INVOKE_DIRECT:
case INVOKE_INTERFACE:
case INVOKE_STATIC:
case INVOKE_SUPER:
case INVOKE_VIRTUAL:
super.visitMethodStmt(Op.INVOKE_STATIC, args, replaceTo);
break;
case INVOKE_DIRECT_RANGE:
case INVOKE_INTERFACE_RANGE:
case INVOKE_STATIC_RANGE:
case INVOKE_SUPER_RANGE:
case INVOKE_VIRTUAL_RANGE:
super.visitMethodStmt(Op.INVOKE_STATIC_RANGE, args, replaceTo);
break;
default:
}
} else {
super.visitMethodStmt(op, args, method);
}
}
};
}
return code;
}
};
}
return dmv;
}
};
}
return dcv;
}
@Override
public void visitEnd() {
}
};
for (String f : remainingArgs) {
byte[] data = ZipUtil.readDex(new File(f).toPath());
DexFileReader r = new DexFileReader(data);
r.accept(fv);
}
if (stub != null) {
byte[] data = ZipUtil.readDex(stub);
DexFileReader r = new DexFileReader(data);
r.accept(new DexFileVisitor(out) {
@Override
public void visitEnd() {
}
});
}
out.visitEnd();
byte[] data = out.toByteArray();
Files.write(output, data);
}
use of com.googlecode.d2j.reader.Op in project dex2jar by pxb1988.
the class Dex2IRConverter method buildInterpreter.
private DvmInterpreter<DvmValue> buildInterpreter() {
return new DvmInterpreter<DvmValue>() {
DvmValue b(com.googlecode.dex2jar.ir.expr.Value value) {
Local local = newLocal();
emit(Stmts.nAssign(local, value));
return new DvmValue(local);
}
@Override
public DvmValue newOperation(DexStmtNode insn) {
switch(insn.op) {
case CONST:
case CONST_16:
case CONST_4:
case CONST_HIGH16:
return b(nInt((Integer) ((ConstStmtNode) insn).value));
case CONST_WIDE:
case CONST_WIDE_16:
case CONST_WIDE_32:
case CONST_WIDE_HIGH16:
return b(nLong((Long) ((ConstStmtNode) insn).value));
case CONST_CLASS:
return b(nType(((DexType) ((ConstStmtNode) insn).value).desc));
case CONST_STRING:
case CONST_STRING_JUMBO:
return b(nString((String) ((ConstStmtNode) insn).value));
case SGET:
case SGET_BOOLEAN:
case SGET_BYTE:
case SGET_CHAR:
case SGET_OBJECT:
case SGET_SHORT:
case SGET_WIDE:
Field field = ((FieldStmtNode) insn).field;
return b(nStaticField(field.getOwner(), field.getName(), field.getType()));
case NEW_INSTANCE:
return b(nNew(((TypeStmtNode) insn).type));
default:
}
return null;
}
@Override
public DvmValue copyOperation(DexStmtNode insn, DvmValue value) {
if (value == null) {
emitNotFindOperand(insn);
return b(nInt(0));
}
return b(getLocal(value));
}
@Override
public DvmValue unaryOperation(DexStmtNode insn, DvmValue value) {
if (value == null) {
emitNotFindOperand(insn);
return b(nInt(0));
}
Local local = getLocal(value);
switch(insn.op) {
case NOT_INT:
return b(nNot(local, "I"));
case NOT_LONG:
return b(nNot(local, "J"));
case NEG_DOUBLE:
return b(nNeg(local, "D"));
case NEG_FLOAT:
return b(nNeg(local, "F"));
case NEG_INT:
return b(nNeg(local, "I"));
case NEG_LONG:
return b(nNeg(local, "J"));
case INT_TO_BYTE:
return b(nCast(local, "I", "B"));
case INT_TO_CHAR:
return b(nCast(local, "I", "C"));
case INT_TO_DOUBLE:
return b(nCast(local, "I", "D"));
case INT_TO_FLOAT:
return b(nCast(local, "I", "F"));
case INT_TO_LONG:
return b(nCast(local, "I", "J"));
case INT_TO_SHORT:
return b(nCast(local, "I", "S"));
case FLOAT_TO_DOUBLE:
return b(nCast(local, "F", "D"));
case FLOAT_TO_INT:
return b(nCast(local, "F", "I"));
case FLOAT_TO_LONG:
return b(nCast(local, "F", "J"));
case DOUBLE_TO_FLOAT:
return b(nCast(local, "D", "F"));
case DOUBLE_TO_INT:
return b(nCast(local, "D", "I"));
case DOUBLE_TO_LONG:
return b(nCast(local, "D", "J"));
case LONG_TO_DOUBLE:
return b(nCast(local, "J", "D"));
case LONG_TO_FLOAT:
return b(nCast(local, "J", "F"));
case LONG_TO_INT:
return b(nCast(local, "J", "I"));
case ARRAY_LENGTH:
return b(nLength(local));
case IF_EQZ:
emit(nIf(Exprs.nEq(local, nInt(0), TypeClass.ZIL.name), getLabel(((JumpStmtNode) insn).label)));
return null;
case IF_GEZ:
emit(nIf(Exprs.nGe(local, nInt(0), "I"), getLabel(((JumpStmtNode) insn).label)));
return null;
case IF_GTZ:
emit(nIf(Exprs.nGt(local, nInt(0), "I"), getLabel(((JumpStmtNode) insn).label)));
return null;
case IF_LEZ:
emit(nIf(Exprs.nLe(local, nInt(0), "I"), getLabel(((JumpStmtNode) insn).label)));
return null;
case IF_LTZ:
emit(nIf(Exprs.nLt(local, nInt(0), "I"), getLabel(((JumpStmtNode) insn).label)));
return null;
case IF_NEZ:
emit(nIf(Exprs.nNe(local, nInt(0), TypeClass.ZIL.name), getLabel(((JumpStmtNode) insn).label)));
return null;
case PACKED_SWITCH:
case SPARSE_SWITCH:
DexLabel[] labels = ((BaseSwitchStmtNode) insn).labels;
LabelStmt[] lss = new LabelStmt[labels.length];
for (int i = 0; i < labels.length; i++) {
lss[i] = getLabel(labels[i]);
}
LabelStmt d = new LabelStmt();
if (insn.op == Op.PACKED_SWITCH) {
emit(nTableSwitch(local, ((PackedSwitchStmtNode) insn).first_case, lss, d));
} else {
emit(nLookupSwitch(local, ((SparseSwitchStmtNode) insn).cases, lss, d));
}
emit(d);
return null;
case SPUT:
case SPUT_BOOLEAN:
case SPUT_BYTE:
case SPUT_CHAR:
case SPUT_OBJECT:
case SPUT_SHORT:
case SPUT_WIDE:
{
Field field = ((FieldStmtNode) insn).field;
emit(nAssign(nStaticField(field.getOwner(), field.getName(), field.getType()), local));
return null;
}
case IGET:
case IGET_BOOLEAN:
case IGET_BYTE:
case IGET_CHAR:
case IGET_OBJECT:
case IGET_SHORT:
case IGET_WIDE:
{
Field field = ((FieldStmtNode) insn).field;
return b(nField(local, field.getOwner(), field.getName(), field.getType()));
}
case INSTANCE_OF:
return b(nInstanceOf(local, ((TypeStmtNode) insn).type));
case NEW_ARRAY:
return b(nNewArray(((TypeStmtNode) insn).type.substring(1), local));
case CHECK_CAST:
return b(nCheckCast(local, ((TypeStmtNode) insn).type));
case MONITOR_ENTER:
emit(nLock(local));
return null;
case MONITOR_EXIT:
emit(nUnLock(local));
return null;
case THROW:
emit(nThrow(local));
return null;
case ADD_INT_LIT16:
case ADD_INT_LIT8:
return b(nAdd(local, nInt(((Stmt2R1NNode) insn).content), "I"));
case RSUB_INT_LIT8:
case //
RSUB_INT:
return b(nSub(nInt(((Stmt2R1NNode) insn).content), local, "I"));
case MUL_INT_LIT8:
case MUL_INT_LIT16:
return b(nMul(local, nInt(((Stmt2R1NNode) insn).content), "I"));
case DIV_INT_LIT16:
case DIV_INT_LIT8:
return b(nDiv(local, nInt(((Stmt2R1NNode) insn).content), "I"));
case REM_INT_LIT16:
case REM_INT_LIT8:
return b(nRem(local, nInt(((Stmt2R1NNode) insn).content), "I"));
case AND_INT_LIT16:
case AND_INT_LIT8:
return b(nAnd(local, nInt(((Stmt2R1NNode) insn).content), ((Stmt2R1NNode) insn).content < 0 || ((Stmt2R1NNode) insn).content > 1 ? "I" : TypeClass.ZI.name));
case OR_INT_LIT16:
case OR_INT_LIT8:
return b(nOr(local, nInt(((Stmt2R1NNode) insn).content), ((Stmt2R1NNode) insn).content < 0 || ((Stmt2R1NNode) insn).content > 1 ? "I" : TypeClass.ZI.name));
case XOR_INT_LIT16:
case XOR_INT_LIT8:
return b(nXor(local, nInt(((Stmt2R1NNode) insn).content), ((Stmt2R1NNode) insn).content < 0 || ((Stmt2R1NNode) insn).content > 1 ? "I" : TypeClass.ZI.name));
case SHL_INT_LIT8:
return b(nShl(local, nInt(((Stmt2R1NNode) insn).content), "I"));
case SHR_INT_LIT8:
return b(nShr(local, nInt(((Stmt2R1NNode) insn).content), "I"));
case USHR_INT_LIT8:
return b(nUshr(local, nInt(((Stmt2R1NNode) insn).content), "I"));
case FILL_ARRAY_DATA:
emit(nFillArrayData(local, nArrayValue(((FillArrayDataStmtNode) insn).array)));
return null;
}
throw new RuntimeException();
}
@Override
public DvmValue binaryOperation(DexStmtNode insn, DvmValue value1, DvmValue value2) {
if (value1 == null || value2 == null) {
emitNotFindOperand(insn);
return b(nInt(0));
}
Local local1 = getLocal(value1);
Local local2 = getLocal(value2);
switch(insn.op) {
case AGET:
return b(nArray(local1, local2, TypeClass.IF.name));
case AGET_BOOLEAN:
return b(nArray(local1, local2, "Z"));
case AGET_BYTE:
return b(nArray(local1, local2, "B"));
case AGET_CHAR:
return b(nArray(local1, local2, "C"));
case AGET_OBJECT:
return b(nArray(local1, local2, "L"));
case AGET_SHORT:
return b(nArray(local1, local2, "S"));
case AGET_WIDE:
return b(nArray(local1, local2, TypeClass.JD.name));
case CMP_LONG:
return b(nLCmp(local1, local2));
case CMPG_DOUBLE:
return b(nDCmpg(local1, local2));
case CMPG_FLOAT:
return b(nFCmpg(local1, local2));
case CMPL_DOUBLE:
return b(nDCmpl(local1, local2));
case CMPL_FLOAT:
return b(nFCmpl(local1, local2));
case ADD_DOUBLE:
return b(nAdd(local1, local2, "D"));
case ADD_FLOAT:
return b(nAdd(local1, local2, "F"));
case ADD_INT:
return b(nAdd(local1, local2, "I"));
case ADD_LONG:
return b(nAdd(local1, local2, "J"));
case SUB_DOUBLE:
return b(nSub(local1, local2, "D"));
case SUB_FLOAT:
return b(nSub(local1, local2, "F"));
case SUB_INT:
return b(nSub(local1, local2, "I"));
case SUB_LONG:
return b(nSub(local1, local2, "J"));
case MUL_DOUBLE:
return b(nMul(local1, local2, "D"));
case MUL_FLOAT:
return b(nMul(local1, local2, "F"));
case MUL_INT:
return b(nMul(local1, local2, "I"));
case MUL_LONG:
return b(nMul(local1, local2, "J"));
case DIV_DOUBLE:
return b(nDiv(local1, local2, "D"));
case DIV_FLOAT:
return b(nDiv(local1, local2, "F"));
case DIV_INT:
return b(nDiv(local1, local2, "I"));
case DIV_LONG:
return b(nDiv(local1, local2, "J"));
case REM_DOUBLE:
return b(nRem(local1, local2, "D"));
case REM_FLOAT:
return b(nRem(local1, local2, "F"));
case REM_INT:
return b(nRem(local1, local2, "I"));
case REM_LONG:
return b(nRem(local1, local2, "J"));
case AND_INT:
return b(nAnd(local1, local2, TypeClass.ZI.name));
case AND_LONG:
return b(nAnd(local1, local2, "J"));
case OR_INT:
return b(nOr(local1, local2, TypeClass.ZI.name));
case OR_LONG:
return b(nOr(local1, local2, "J"));
case XOR_INT:
return b(nXor(local1, local2, TypeClass.ZI.name));
case XOR_LONG:
return b(nXor(local1, local2, "J"));
case SHL_INT:
return b(nShl(local1, local2, "I"));
case SHL_LONG:
return b(nShl(local1, local2, "J"));
case SHR_INT:
return b(nShr(local1, local2, "I"));
case SHR_LONG:
return b(nShr(local1, local2, "J"));
case USHR_INT:
return b(nUshr(local1, local2, "I"));
case USHR_LONG:
return b(nUshr(local1, local2, "J"));
case IF_EQ:
emit(nIf(Exprs.nEq(local1, local2, TypeClass.ZIL.name), getLabel(((JumpStmtNode) insn).label)));
return null;
case IF_GE:
emit(nIf(Exprs.nGe(local1, local2, "I"), getLabel(((JumpStmtNode) insn).label)));
return null;
case IF_GT:
emit(nIf(Exprs.nGt(local1, local2, "I"), getLabel(((JumpStmtNode) insn).label)));
return null;
case IF_LE:
emit(nIf(Exprs.nLe(local1, local2, "I"), getLabel(((JumpStmtNode) insn).label)));
return null;
case IF_LT:
emit(nIf(Exprs.nLt(local1, local2, "I"), getLabel(((JumpStmtNode) insn).label)));
return null;
case IF_NE:
emit(nIf(Exprs.nNe(local1, local2, TypeClass.ZIL.name), getLabel(((JumpStmtNode) insn).label)));
return null;
case IPUT:
case IPUT_BOOLEAN:
case IPUT_BYTE:
case IPUT_CHAR:
case IPUT_OBJECT:
case IPUT_SHORT:
case IPUT_WIDE:
Field field = ((FieldStmtNode) insn).field;
emit(nAssign(nField(local1, field.getOwner(), field.getName(), field.getType()), local2));
return null;
case ADD_DOUBLE_2ADDR:
return b(nAdd(local1, local2, "D"));
case ADD_FLOAT_2ADDR:
return b(nAdd(local1, local2, "F"));
case ADD_INT_2ADDR:
return b(nAdd(local1, local2, "I"));
case ADD_LONG_2ADDR:
return b(nAdd(local1, local2, "J"));
case SUB_DOUBLE_2ADDR:
return b(nSub(local1, local2, "D"));
case SUB_FLOAT_2ADDR:
return b(nSub(local1, local2, "F"));
case SUB_INT_2ADDR:
return b(nSub(local1, local2, "I"));
case SUB_LONG_2ADDR:
return b(nSub(local1, local2, "J"));
case MUL_DOUBLE_2ADDR:
return b(nMul(local1, local2, "D"));
case MUL_FLOAT_2ADDR:
return b(nMul(local1, local2, "F"));
case MUL_INT_2ADDR:
return b(nMul(local1, local2, "I"));
case MUL_LONG_2ADDR:
return b(nMul(local1, local2, "J"));
case DIV_DOUBLE_2ADDR:
return b(nDiv(local1, local2, "D"));
case DIV_FLOAT_2ADDR:
return b(nDiv(local1, local2, "F"));
case DIV_INT_2ADDR:
return b(nDiv(local1, local2, "I"));
case DIV_LONG_2ADDR:
return b(nDiv(local1, local2, "J"));
case REM_DOUBLE_2ADDR:
return b(nRem(local1, local2, "D"));
case REM_FLOAT_2ADDR:
return b(nRem(local1, local2, "F"));
case REM_INT_2ADDR:
return b(nRem(local1, local2, "I"));
case REM_LONG_2ADDR:
return b(nRem(local1, local2, "J"));
case AND_INT_2ADDR:
return b(nAnd(local1, local2, TypeClass.ZI.name));
case AND_LONG_2ADDR:
return b(nAnd(local1, local2, "J"));
case OR_INT_2ADDR:
return b(nOr(local1, local2, TypeClass.ZI.name));
case OR_LONG_2ADDR:
return b(nOr(local1, local2, "J"));
case XOR_INT_2ADDR:
return b(nXor(local1, local2, TypeClass.ZI.name));
case XOR_LONG_2ADDR:
return b(nXor(local1, local2, "J"));
case SHL_INT_2ADDR:
return b(nShl(local1, local2, "I"));
case SHL_LONG_2ADDR:
return b(nShl(local1, local2, "J"));
case SHR_INT_2ADDR:
return b(nShr(local1, local2, "I"));
case SHR_LONG_2ADDR:
return b(nShr(local1, local2, "J"));
case USHR_INT_2ADDR:
return b(nUshr(local1, local2, "I"));
case USHR_LONG_2ADDR:
return b(nUshr(local1, local2, "J"));
}
throw new RuntimeException();
}
@Override
public DvmValue ternaryOperation(DexStmtNode insn, DvmValue value1, DvmValue value2, DvmValue value3) {
if (value1 == null || value2 == null || value3 == null) {
emitNotFindOperand(insn);
return b(nInt(0));
}
Local localArray = getLocal(value1);
Local localIndex = getLocal(value2);
Local localValue = getLocal(value3);
switch(insn.op) {
case APUT:
emit(nAssign(nArray(localArray, localIndex, TypeClass.IF.name), localValue));
break;
case APUT_BOOLEAN:
emit(nAssign(nArray(localArray, localIndex, "Z"), localValue));
break;
case APUT_BYTE:
emit(nAssign(nArray(localArray, localIndex, "B"), localValue));
break;
case APUT_CHAR:
emit(nAssign(nArray(localArray, localIndex, "C"), localValue));
break;
case APUT_OBJECT:
emit(nAssign(nArray(localArray, localIndex, "L"), localValue));
break;
case APUT_SHORT:
emit(nAssign(nArray(localArray, localIndex, "S"), localValue));
break;
case APUT_WIDE:
emit(nAssign(nArray(localArray, localIndex, TypeClass.JD.name), localValue));
break;
}
return null;
}
@Override
public DvmValue naryOperation(DexStmtNode insn, List<? extends DvmValue> values) {
for (DvmValue v : values) {
if (v == null) {
emitNotFindOperand(insn);
return b(nInt(0));
}
}
switch(insn.op) {
case FILLED_NEW_ARRAY:
case FILLED_NEW_ARRAY_RANGE:
DvmValue value = new DvmValue();
FilledNewArrayStmtNode filledNewArrayStmtNode = (FilledNewArrayStmtNode) insn;
String type = filledNewArrayStmtNode.type;
String elem = type.substring(1);
emit(nAssign(getLocal(value), nNewArray(elem, nInt(values.size()))));
for (int i = 0; i < values.size(); i++) {
emit(nAssign(nArray(getLocal(value), nInt(i), elem), getLocal(values.get(i))));
}
return value;
default:
Op op = insn.op;
Method method = ((MethodStmtNode) insn).method;
Value[] vs = new Value[values.size()];
for (int i = 0; i < vs.length; i++) {
vs[i] = getLocal(values.get(i));
}
Value invoke = null;
switch(op) {
case INVOKE_VIRTUAL_RANGE:
case INVOKE_VIRTUAL:
invoke = nInvokeVirtual(vs, method.getOwner(), method.getName(), method.getParameterTypes(), method.getReturnType());
break;
case INVOKE_SUPER_RANGE:
case INVOKE_DIRECT_RANGE:
case INVOKE_SUPER:
case INVOKE_DIRECT:
invoke = nInvokeSpecial(vs, method.getOwner(), method.getName(), method.getParameterTypes(), method.getReturnType());
break;
case INVOKE_STATIC_RANGE:
case INVOKE_STATIC:
invoke = nInvokeStatic(vs, method.getOwner(), method.getName(), method.getParameterTypes(), method.getReturnType());
break;
case INVOKE_INTERFACE_RANGE:
case INVOKE_INTERFACE:
invoke = nInvokeInterface(vs, method.getOwner(), method.getName(), method.getParameterTypes(), method.getReturnType());
break;
default:
throw new RuntimeException();
}
if ("V".equals(method.getReturnType())) {
emit(nVoidInvoke(invoke));
return null;
} else {
return b(invoke);
}
}
}
void emitNotFindOperand(DexStmtNode insn) {
String msg;
switch(insn.op) {
case MOVE_RESULT:
case MOVE_RESULT_OBJECT:
case MOVE_RESULT_WIDE:
msg = "can't get operand(s) for " + insn.op + ", wrong position ?";
break;
default:
msg = "can't get operand(s) for " + insn.op + ", out-of-range or not initialized ?";
break;
}
System.err.println("WARN: " + msg);
emit(nThrow(nInvokeNew(new Value[] { nString("d2j: " + msg) }, new String[] { "Ljava/lang/String;" }, "Ljava/lang/VerifyError;")));
}
@Override
public void returnOperation(DexStmtNode insn, DvmValue value) {
if (value == null) {
emitNotFindOperand(insn);
return;
}
emit(nReturn(getLocal(value)));
}
};
}
use of com.googlecode.d2j.reader.Op 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));
}
}
Aggregations