use of com.googlecode.dex2jar.ir.stmt.Stmt in project dex2jar by pxb1988.
the class NpeTransformer method transformReportChanged.
@Override
public boolean transformReportChanged(IrMethod method) {
boolean changed = false;
if (method.locals.size() == 0) {
return false;
}
StmtSearcher st = new StmtSearcher() {
@Override
public void travel(Stmt stmt) {
if (stmt.st == Stmt.ST.FILL_ARRAY_DATA) {
if (isNull(stmt.getOp1())) {
throw NPE;
}
}
super.travel(stmt);
}
@Override
public void travel(Value op) {
switch(op.vt) {
case INVOKE_VIRTUAL:
case INVOKE_SPECIAL:
case INVOKE_INTERFACE:
{
if (isNull(op.getOps()[0])) {
throw NPE;
}
}
break;
case ARRAY:
{
if (isNull(op.getOp1())) {
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) {
throw DIVE;
}
}
break;
case LDIV:
if (op.getOp2().vt == Value.VT.CONSTANT) {
Constant constant = (Constant) op.getOp2();
if (((Number) constant.value).longValue() == 0) {
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;
}
}
}
break;
default:
}
}
};
for (Stmt p = method.stmts.getFirst(); p != null; ) {
try {
st.travel(p);
p = p.getNext();
} catch (MustThrowException e) {
replace(method, p);
Stmt q = p.getNext();
method.stmts.remove(p);
changed = true;
p = q;
}
}
return changed;
}
use of com.googlecode.dex2jar.ir.stmt.Stmt 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.stmt.Stmt 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;
}
use of com.googlecode.dex2jar.ir.stmt.Stmt in project dex2jar by pxb1988.
the class AggTransformer method transformReportChanged.
@Override
public boolean transformReportChanged(IrMethod method) {
boolean changed = false;
Set<Stmt> locationSensitiveStmts = new HashSet<>();
// 1. merge location Insensitive stmts
changed = simpleMergeLocals(method, changed, locationSensitiveStmts);
if (locationSensitiveStmts.size() == 0) {
return changed;
}
ReplaceX replaceX = new ReplaceX();
Queue<Stmt> q = new UniqueQueue<>();
q.addAll(locationSensitiveStmts);
// 2. merge location sensitive stmts
while (!q.isEmpty()) {
Stmt stmt = q.poll();
Local local = (Local) stmt.getOp1();
Stmt next = stmt.getNext();
switch(next.st) {
case LABEL:
case GOTO:
case IDENTITY:
case FILL_ARRAY_DATA:
case NOP:
case RETURN_VOID:
continue;
default:
}
try {
localCanExecFirst(local, next);
// impossible here
throw new RuntimeException();
} catch (MergeResult e) {
if (e == SUCCESS) {
replaceX.local = local;
replaceX.replaceWith = stmt.getOp2();
method.locals.remove(local);
method.stmts.remove(stmt);
Cfg.travelMod(next, replaceX, false);
Stmt pre = next.getPre();
if (pre != null && locationSensitiveStmts.contains(pre)) {
q.add(pre);
}
}
}
}
return changed;
}
use of com.googlecode.dex2jar.ir.stmt.Stmt in project dex2jar by pxb1988.
the class ArrayNullPointerTransformer method transform.
@Override
public void transform(IrMethod irMethod) {
for (Stmt p = irMethod.stmts.getFirst(); p != null; ) {
if (arrayNPE(p)) {
Stmt q = p.getNext();
replaceNPE(irMethod.stmts, irMethod.locals, p);
p = q;
continue;
}
p = p.getNext();
}
}
Aggregations