use of com.googlecode.dex2jar.ir.expr.Local in project dex2jar by pxb1988.
the class Dex2IrAdapter method visitRegister.
@Override
public void visitRegister(int total) {
Local[] locals = new Local[total];
this.locals = locals;
this.tmpLocal = new Local(total);
for (int i = 0; i < locals.length; i++) {
locals[i] = new Local(i);
}
int nextReg = total - countParameterRegisters(method, isStatic);
int nextReg0 = nextReg;
if (!isStatic) {
// is not static
x(Stmts.nIdentity(locals[nextReg], Exprs.nThisRef(method.getOwner())));
nextReg++;
}
String[] args = method.getParameterTypes();
for (int i = 0; i < args.length; i++) {
String t = args[i];
x(Stmts.nIdentity(locals[nextReg], Exprs.nParameterRef(t, i)));
nextReg++;
if (t.equals("J") || t.equals("D")) {
nextReg++;
}
}
// simple fix for issue 219, init all tmp register to 0 at the start of insn.
for (int i = 0; i < nextReg0; i++) {
x(Stmts.nAssign(locals[i], nInt(0)));
}
x(Stmts.nAssign(tmpLocal, nInt(0)));
}
use of com.googlecode.dex2jar.ir.expr.Local in project dex2jar by pxb1988.
the class NpeTransformer method replace.
private void replace(final IrMethod m, final Stmt p) {
StmtTraveler traveler = new StmtTraveler() {
@Override
public Value travel(Value op) {
switch(op.vt) {
case INVOKE_VIRTUAL:
case INVOKE_SPECIAL:
case INVOKE_INTERFACE:
{
Value[] ops = op.getOps();
if (isNull(ops[0])) {
for (int i = 1; i < ops.length; i++) {
travel(ops[i]);
}
throw NPE;
}
}
break;
case ARRAY:
{
if (isNull(op.getOp1())) {
travel(op.getOp2());
throw NPE;
}
}
break;
case FIELD:
{
if (isNull(op.getOp())) {
throw NPE;
}
}
break;
case IDIV:
if (op.getOp2().vt == Value.VT.CONSTANT) {
Constant constant = (Constant) op.getOp2();
if (((Number) constant.value).intValue() == 0) {
travel(op.getOp1());
throw DIVE;
}
}
break;
case LDIV:
if (op.getOp2().vt == Value.VT.CONSTANT) {
Constant constant = (Constant) op.getOp2();
if (((Number) constant.value).longValue() == 0) {
travel(op.getOp1());
throw DIVE;
}
}
break;
case NEW_ARRAY:
if (op.getOp().vt == Value.VT.CONSTANT) {
Constant constant = (Constant) op.getOp();
if (((Number) constant.value).intValue() < 0) {
throw NEGATIVE_ARRAY_SIZE;
}
}
break;
case NEW_MUTI_ARRAY:
for (Value size : op.getOps()) {
if (size.vt == Value.VT.CONSTANT) {
Constant constant = (Constant) size;
if (((Number) constant.value).intValue() < 0) {
throw NEGATIVE_ARRAY_SIZE;
} else {
travel(size);
}
}
}
break;
default:
}
Value sop = super.travel(op);
if (sop.vt == Value.VT.LOCAL || sop.vt == Value.VT.CONSTANT) {
return sop;
} else {
Local local = new Local();
m.locals.add(local);
m.stmts.insertBefore(p, Stmts.nAssign(local, sop));
return local;
}
}
};
try {
switch(p.et) {
case E0:
// impossible
break;
case E1:
traveler.travel(p.getOp());
break;
case E2:
if (p.st == Stmt.ST.ASSIGN) {
switch(p.getOp1().vt) {
case ARRAY:
traveler.travel(p.getOp1().getOp1());
traveler.travel(p.getOp1().getOp2());
traveler.travel(p.getOp2());
break;
case FIELD:
traveler.travel(p.getOp1().getOp());
traveler.travel(p.getOp2());
break;
case STATIC_FIELD:
case LOCAL:
traveler.travel(p.getOp2());
break;
default:
}
} else if (p.st == Stmt.ST.FILL_ARRAY_DATA) {
if (isNull(p.getOp1())) {
throw NPE;
} else {
traveler.travel(p.getOp1());
}
}
break;
case En:
}
} catch (MustThrowException e) {
if (e == NPE) {
m.stmts.insertBefore(p, Stmts.nThrow(Exprs.nInvokeNew(new Value[0], new String[0], "Ljava/lang/NullPointerException;")));
} else if (e == DIVE) {
m.stmts.insertBefore(p, Stmts.nThrow(Exprs.nInvokeNew(new Value[] { Exprs.nString("divide by zero") }, new String[] { "Ljava/lang/String;" }, "Ljava/lang/ArithmeticException;")));
} else if (e == NEGATIVE_ARRAY_SIZE) {
m.stmts.insertBefore(p, Stmts.nThrow(Exprs.nInvokeNew(new Value[0], new String[0], "Ljava/lang/NegativeArraySizeException;")));
}
}
}
use of com.googlecode.dex2jar.ir.expr.Local in project dex2jar by pxb1988.
the class RemoveConstantFromSSA method transformReportChanged.
@Override
public boolean transformReportChanged(IrMethod method) {
boolean changed = false;
List<AssignStmt> assignStmtList = new ArrayList<>();
Map<Local, Object> cstMap = new HashMap<>();
for (Stmt p = method.stmts.getFirst(); p != null; p = p.getNext()) {
if (p.st == Stmt.ST.ASSIGN) {
AssignStmt as = (AssignStmt) p;
if (as.getOp1().vt == Value.VT.LOCAL) {
if (as.getOp2().vt == Value.VT.CONSTANT) {
assignStmtList.add(as);
cstMap.put((Local) as.getOp1(), ((Constant) as.getOp2()).value);
} else if (as.getOp2().vt == Value.VT.LOCAL) {
cstMap.put((Local) as.getOp1(), as.getOp2());
}
}
}
}
if (assignStmtList.size() == 0) {
return false;
}
RemoveLocalFromSSA.fixReplace(cstMap);
final Map<Local, Value> toReplace = new HashMap<>();
Set<Value> usedInPhi = new HashSet<>();
List<LabelStmt> phiLabels = method.phiLabels;
if (phiLabels != null) {
boolean loopAgain = true;
while (loopAgain) {
loopAgain = false;
usedInPhi.clear();
for (Iterator<LabelStmt> it = phiLabels.iterator(); it.hasNext(); ) {
LabelStmt labelStmt = it.next();
if (labelStmt.phis != null) {
for (Iterator<AssignStmt> it2 = labelStmt.phis.iterator(); it2.hasNext(); ) {
AssignStmt phi = it2.next();
Value[] vs = phi.getOp2().getOps();
Object sameCst = null;
boolean allEqual = true;
for (Value p : vs) {
Object cst = cstMap.get(p);
if (cst == null) {
allEqual = false;
break;
}
if (sameCst == null) {
sameCst = cst;
} else if (!sameCst.equals(cst)) {
allEqual = false;
break;
}
}
if (allEqual) {
// all are same constant
cstMap.put((Local) phi.getOp1(), sameCst);
if (sameCst instanceof Local) {
phi.setOp2((Value) sameCst);
} else {
phi.setOp2(Exprs.nConstant(sameCst));
assignStmtList.add(phi);
}
it2.remove();
method.stmts.insertAfter(labelStmt, phi);
changed = true;
// loop again
loopAgain = true;
} else {
usedInPhi.addAll(Arrays.asList(phi.getOp2().getOps()));
}
}
if (labelStmt.phis.size() == 0) {
it.remove();
}
}
}
}
}
for (Iterator<AssignStmt> it = assignStmtList.iterator(); it.hasNext(); ) {
AssignStmt as = it.next();
if (!usedInPhi.contains(as.getOp1())) {
it.remove();
method.stmts.remove(as);
method.locals.remove(as.getOp1());
changed = true;
}
toReplace.put((Local) as.getOp1(), as.getOp2());
}
Cfg.travelMod(method.stmts, new Cfg.TravelCallBack() {
@Override
public Value onAssign(Local v, AssignStmt as) {
return v;
}
@Override
public Value onUse(Local v) {
Value n = toReplace.get(v);
return n == null ? v : n.clone();
}
}, false);
return changed;
}
use of com.googlecode.dex2jar.ir.expr.Local in project dex2jar by pxb1988.
the class RemoveLocalFromSSA method collectPhiObjects.
private Map<Local, PhiObject> collectPhiObjects(List<LabelStmt> phiLabels) {
Map<Local, PhiObject> phis;
phis = new HashMap<>();
for (LabelStmt labelStmt : phiLabels) {
for (AssignStmt as : labelStmt.phis) {
Local local = (Local) as.getOp1();
PhiObject child = getOrCreate(phis, local);
child.isInitByPhi = true;
for (Value op : as.getOp2().getOps()) {
if (op == local) {
continue;
}
PhiObject parent = getOrCreate(phis, (Local) op);
linkPhiObject(parent, child);
}
}
}
return phis;
}
use of com.googlecode.dex2jar.ir.expr.Local in project dex2jar by pxb1988.
the class RemoveLocalFromSSA method transformReportChanged.
@Override
public boolean transformReportChanged(IrMethod method) {
boolean irChanged = false;
List<AssignStmt> assignStmtList = new ArrayList<>();
List<LabelStmt> phiLabels = method.phiLabels;
for (Stmt p = method.stmts.getFirst(); p != null; p = p.getNext()) {
if (p.st == Stmt.ST.ASSIGN) {
AssignStmt as = (AssignStmt) p;
if (as.getOp1().vt == Value.VT.LOCAL && as.getOp2().vt == Value.VT.LOCAL) {
assignStmtList.add(as);
}
}
}
final Map<Local, Local> toReplace = new HashMap<>();
Set<Value> set = new HashSet<>();
boolean changed = true;
while (changed) {
changed = false;
if (removeLoopFromPhi(phiLabels, toReplace)) {
fixReplace(toReplace);
replacePhi(phiLabels, toReplace, set);
}
while (simplePhi(phiLabels, toReplace, set)) {
// remove a = phi(b)
fixReplace(toReplace);
replacePhi(phiLabels, toReplace, set);
}
while (simpleAssign(phiLabels, assignStmtList, toReplace, method.stmts)) {
// remove a=b
fixReplace(toReplace);
replaceAssign(assignStmtList, toReplace);
changed = true;
irChanged = true;
}
replacePhi(phiLabels, toReplace, set);
}
for (Local local : toReplace.keySet()) {
method.locals.remove(local);
irChanged = true;
}
if (toReplace.size() > 0) {
Cfg.travelMod(method.stmts, new Cfg.TravelCallBack() {
@Override
public Value onAssign(Local v, AssignStmt as) {
return v;
}
@Override
public Value onUse(Local v) {
Local n = toReplace.get(v);
return n == null ? v : n;
}
}, true);
}
return irChanged;
}
Aggregations