use of com.googlecode.dex2jar.ir.stmt.LabelStmt in project dex2jar by pxb1988.
the class ExceptionHandlerTrim method transform.
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public void transform(IrMethod irMethod) {
List<Trap> trips = irMethod.traps;
irMethod.traps = new ArrayList();
LabelAndLocalMapper map = new LabelAndLocalMapper() {
@Override
public LabelStmt map(LabelStmt label) {
return label;
}
};
for (Trap trap : trips) {
Trap ntrap = trap.clone(map);
int status = 0;
for (Stmt p = trap.start.getNext(); p != trap.end; p = p.getNext()) {
if (!Cfg.notThrow(p)) {
if (status == 0) {
Stmt pre = p.getPre();
if (pre == null || pre.st != ST.LABEL) {
pre = Stmts.nLabel();
irMethod.stmts.insertBefore(p, pre);
}
ntrap.start = (LabelStmt) pre;
status = 1;
} else if (status == 1) {
// continue;
}
} else if (status == 1) {
Stmt pre = p.getPre();
if (pre == null || pre.st != ST.LABEL) {
pre = Stmts.nLabel();
irMethod.stmts.insertBefore(p, pre);
}
ntrap.end = (LabelStmt) pre;
irMethod.traps.add(ntrap);
status = 0;
ntrap = trap.clone(map);
}
}
if (status == 1) {
ntrap.end = trap.end;
irMethod.traps.add(ntrap);
status = 0;
}
}
}
use of com.googlecode.dex2jar.ir.stmt.LabelStmt in project dex2jar by pxb1988.
the class NewTransformer method makeSureUsedBeforeConstructor.
void makeSureUsedBeforeConstructor(IrMethod method, final Map<Local, TObject> init, final int size) {
Cfg.createCFG(method);
Cfg.dfs(method.stmts, new Cfg.FrameVisitor<Vx[]>() {
boolean keepFrame = false;
Vx[] tmp = new Vx[size];
StmtTraveler stmtTraveler = new StmtTraveler() {
Stmt current;
@Override
public Stmt travel(Stmt stmt) {
this.current = stmt;
if (stmt.et == ET.E2) {
if (stmt.getOp1().vt == LOCAL) {
Local op1 = (Local) stmt.getOp1();
if (stmt.getOp2().vt == LOCAL) {
Local op2 = (Local) stmt.getOp2();
tmp[op1._ls_index] = tmp[op2._ls_index];
return stmt;
} else if (stmt.getOp2().vt == NEW) {
tmp[op1._ls_index] = new Vx(init.get(op1), false);
return stmt;
} else {
travel(stmt.getOp2());
tmp[op1._ls_index] = IGNORED;
return stmt;
}
}
}
if (stmt.st == LABEL) {
LabelStmt labelStmt = (LabelStmt) stmt;
if (labelStmt.phis != null) {
for (AssignStmt phi : labelStmt.phis) {
Local local = (Local) phi.getOp1();
tmp[local._ls_index] = IGNORED;
}
}
return stmt;
}
return super.travel(stmt);
}
@Override
public Value travel(Value op) {
if (op.vt == INVOKE_SPECIAL) {
if (op.getOps().length >= 1) {
InvokeExpr ie = (InvokeExpr) op;
if ("<init>".equals(ie.name)) {
Value thiz = op.getOps()[0];
if (thiz.vt == LOCAL) {
Local local = (Local) thiz;
Vx vx = tmp[local._ls_index];
TObject object = vx.obj;
if (object != null) {
if (object.invokeStmt != null) {
object.useBeforeInit = true;
} else {
vx.init = true;
object.invokeStmt = current;
for (int i = 0; i < tmp.length; i++) {
Vx s = tmp[i];
if (s != null && s.obj == object) {
tmp[i] = IGNORED;
}
}
keepFrame = true;
}
}
}
}
}
}
op = super.travel(op);
if (op.vt == LOCAL) {
use((Local) op);
}
return op;
}
};
@Override
public Vx[] merge(Vx[] srcFrame, Vx[] distFrame, Stmt src, Stmt dist) {
if (distFrame == null) {
distFrame = new Vx[size];
System.arraycopy(srcFrame, 0, distFrame, 0, size);
} else {
for (int i = 0; i < size; i++) {
Vx s = srcFrame[i];
Vx d = distFrame[i];
if (s != null) {
if (d == null) {
distFrame[i] = s;
} else {
if (s != d) {
TObject obj = s.obj;
if (obj != null) {
obj.useBeforeInit = true;
}
obj = d.obj;
if (obj != null) {
obj.useBeforeInit = true;
}
}
}
}
}
}
if (dist.st == LABEL) {
List<AssignStmt> phis = ((LabelStmt) dist).phis;
if (phis != null && phis.size() > 0) {
for (AssignStmt phi : phis) {
for (Value value : phi.getOp2().getOps()) {
Local local = (Local) value;
int i = local._ls_index;
Vx s = srcFrame[i];
Vx d = distFrame[i];
if (d != null) {
if (!d.init) {
TObject obj = d.obj;
if (obj != null) {
obj.useBeforeInit = true;
}
}
} else if (s != null) {
if (!s.init) {
TObject obj = s.obj;
if (obj != null) {
obj.useBeforeInit = true;
}
}
}
}
}
}
}
return distFrame;
}
@Override
public Vx[] initFirstFrame(Stmt first) {
return new Vx[size];
}
@Override
public Vx[] exec(Vx[] frame, Stmt stmt) {
keepFrame = false;
System.arraycopy(frame, 0, tmp, 0, size);
stmtTraveler.travel(stmt);
if (stmt._cfg_froms.size() > 1) {
keepFrame = true;
}
if (!keepFrame) {
stmt.frame = null;
}
return tmp;
}
void use(Local local) {
Vx vx = tmp[local._ls_index];
if (!vx.init) {
TObject object = vx.obj;
if (object != null) {
object.useBeforeInit = true;
}
tmp[local._ls_index] = IGNORED;
}
}
});
for (Iterator<Map.Entry<Local, TObject>> iterator = init.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry<Local, TObject> e = iterator.next();
boolean keep = true;
TObject obj = e.getValue();
if (obj.useBeforeInit) {
keep = false;
}
if (obj.invokeStmt == null) {
keep = false;
}
if (!keep) {
iterator.remove();
}
}
}
use of com.googlecode.dex2jar.ir.stmt.LabelStmt 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.LabelStmt 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.stmt.LabelStmt 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