Search in sources :

Example 11 with AssignStmt

use of com.googlecode.dex2jar.ir.stmt.AssignStmt 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();
        }
    }
}
Also used : LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Stmt(com.googlecode.dex2jar.ir.stmt.Stmt) StmtTraveler(com.googlecode.dex2jar.ir.StmtTraveler)

Example 12 with AssignStmt

use of com.googlecode.dex2jar.ir.stmt.AssignStmt 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;
}
Also used : LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) HashMap(java.util.HashMap) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) ArrayList(java.util.ArrayList) Local(com.googlecode.dex2jar.ir.expr.Local) LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Stmt(com.googlecode.dex2jar.ir.stmt.Stmt) Value(com.googlecode.dex2jar.ir.expr.Value) HashSet(java.util.HashSet)

Example 13 with AssignStmt

use of com.googlecode.dex2jar.ir.stmt.AssignStmt 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;
}
Also used : LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Value(com.googlecode.dex2jar.ir.expr.Value) Local(com.googlecode.dex2jar.ir.expr.Local)

Example 14 with AssignStmt

use of com.googlecode.dex2jar.ir.stmt.AssignStmt 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;
}
Also used : LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Local(com.googlecode.dex2jar.ir.expr.Local) LabelStmt(com.googlecode.dex2jar.ir.stmt.LabelStmt) AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Stmt(com.googlecode.dex2jar.ir.stmt.Stmt) Value(com.googlecode.dex2jar.ir.expr.Value)

Example 15 with AssignStmt

use of com.googlecode.dex2jar.ir.stmt.AssignStmt in project dex2jar by pxb1988.

the class RemoveLocalFromSSA method replaceAssign.

static <T extends Value> void replaceAssign(List<AssignStmt> assignStmtList, Map<Local, T> toReplace) {
    for (AssignStmt as : assignStmtList) {
        Value right = as.getOp2();
        T to = toReplace.get(right);
        if (to != null) {
            as.setOp2(to);
        }
    }
}
Also used : AssignStmt(com.googlecode.dex2jar.ir.stmt.AssignStmt) Value(com.googlecode.dex2jar.ir.expr.Value)

Aggregations

AssignStmt (com.googlecode.dex2jar.ir.stmt.AssignStmt)22 LabelStmt (com.googlecode.dex2jar.ir.stmt.LabelStmt)18 Stmt (com.googlecode.dex2jar.ir.stmt.Stmt)13 Local (com.googlecode.dex2jar.ir.expr.Local)12 Value (com.googlecode.dex2jar.ir.expr.Value)11 ArrayList (java.util.ArrayList)6 JumpStmt (com.googlecode.dex2jar.ir.stmt.JumpStmt)4 StmtList (com.googlecode.dex2jar.ir.stmt.StmtList)3 Cfg (com.googlecode.dex2jar.ir.ts.Cfg)3 List (java.util.List)3 StmtTraveler (com.googlecode.dex2jar.ir.StmtTraveler)2 PhiExpr (com.googlecode.dex2jar.ir.expr.PhiExpr)2 HashSet (java.util.HashSet)2 Trap (com.googlecode.dex2jar.ir.Trap)1 Constant (com.googlecode.dex2jar.ir.expr.Constant)1 UnopStmt (com.googlecode.dex2jar.ir.stmt.UnopStmt)1 AnalyzeValue (com.googlecode.dex2jar.ir.ts.an.AnalyzeValue)1 HashMap (java.util.HashMap)1 Test (org.junit.Test)1