Search in sources :

Example 1 with BasicBlock

use of com.android.dx.rop.code.BasicBlock in project buck by facebook.

the class StdCatchBuilder method build.

/**
     * Builds and returns the catch table for a given method.
     *
     * @param method {@code non-null;} method to build the list for
     * @param order {@code non-null;} block output order
     * @param addresses {@code non-null;} address objects for each block
     * @return {@code non-null;} the constructed table
     */
public static CatchTable build(RopMethod method, int[] order, BlockAddresses addresses) {
    int len = order.length;
    BasicBlockList blocks = method.getBlocks();
    ArrayList<CatchTable.Entry> resultList = new ArrayList<CatchTable.Entry>(len);
    CatchHandlerList currentHandlers = CatchHandlerList.EMPTY;
    BasicBlock currentStartBlock = null;
    BasicBlock currentEndBlock = null;
    for (int i = 0; i < len; i++) {
        BasicBlock block = blocks.labelToBlock(order[i]);
        if (!block.canThrow()) {
            /*
                 * There is no need to concern ourselves with the
                 * placement of blocks that can't throw with respect
                 * to the blocks that *can* throw.
                 */
            continue;
        }
        CatchHandlerList handlers = handlersFor(block, addresses);
        if (currentHandlers.size() == 0) {
            // This is the start of a new catch range.
            currentStartBlock = block;
            currentEndBlock = block;
            currentHandlers = handlers;
            continue;
        }
        if (currentHandlers.equals(handlers) && rangeIsValid(currentStartBlock, block, addresses)) {
            /*
                 * The block we are looking at now has the same handlers
                 * as the block that started the currently open catch
                 * range, and adding it to the currently open range won't
                 * cause it to be too long.
                 */
            currentEndBlock = block;
            continue;
        }
        /*
             * The block we are looking at now has incompatible handlers,
             * so we need to finish off the last entry and start a new
             * one. Note: We only emit an entry if it has associated handlers.
             */
        if (currentHandlers.size() != 0) {
            CatchTable.Entry entry = makeEntry(currentStartBlock, currentEndBlock, currentHandlers, addresses);
            resultList.add(entry);
        }
        currentStartBlock = block;
        currentEndBlock = block;
        currentHandlers = handlers;
    }
    if (currentHandlers.size() != 0) {
        // Emit an entry for the range that was left hanging.
        CatchTable.Entry entry = makeEntry(currentStartBlock, currentEndBlock, currentHandlers, addresses);
        resultList.add(entry);
    }
    // Construct the final result.
    int resultSz = resultList.size();
    if (resultSz == 0) {
        return CatchTable.EMPTY;
    }
    CatchTable result = new CatchTable(resultSz);
    for (int i = 0; i < resultSz; i++) {
        result.set(i, resultList.get(i));
    }
    result.setImmutable();
    return result;
}
Also used : ArrayList(java.util.ArrayList) BasicBlock(com.android.dx.rop.code.BasicBlock) BasicBlockList(com.android.dx.rop.code.BasicBlockList)

Example 2 with BasicBlock

use of com.android.dx.rop.code.BasicBlock in project buck by facebook.

the class BlockAddresses method setupArrays.

/**
     * Sets up the address arrays.
     */
private void setupArrays(RopMethod method) {
    BasicBlockList blocks = method.getBlocks();
    int sz = blocks.size();
    for (int i = 0; i < sz; i++) {
        BasicBlock one = blocks.get(i);
        int label = one.getLabel();
        Insn insn = one.getInsns().get(0);
        starts[label] = new CodeAddress(insn.getPosition());
        SourcePosition pos = one.getLastInsn().getPosition();
        lasts[label] = new CodeAddress(pos);
        ends[label] = new CodeAddress(pos);
    }
}
Also used : Insn(com.android.dx.rop.code.Insn) SourcePosition(com.android.dx.rop.code.SourcePosition) BasicBlock(com.android.dx.rop.code.BasicBlock) BasicBlockList(com.android.dx.rop.code.BasicBlockList)

Example 3 with BasicBlock

use of com.android.dx.rop.code.BasicBlock in project buck by facebook.

the class SsaBasicBlock method newFromRop.

/**
     * Creates a new SSA basic block from a ROP form basic block.
     *
     * @param rmeth original method
     * @param basicBlockIndex index this block will have
     * @param parent method of this block predecessor set will be
     * updated
     * @return new instance
     */
public static SsaBasicBlock newFromRop(RopMethod rmeth, int basicBlockIndex, final SsaMethod parent) {
    BasicBlockList ropBlocks = rmeth.getBlocks();
    BasicBlock bb = ropBlocks.get(basicBlockIndex);
    SsaBasicBlock result = new SsaBasicBlock(basicBlockIndex, bb.getLabel(), parent);
    InsnList ropInsns = bb.getInsns();
    result.insns.ensureCapacity(ropInsns.size());
    for (int i = 0, sz = ropInsns.size(); i < sz; i++) {
        result.insns.add(new NormalSsaInsn(ropInsns.get(i), result));
    }
    result.predecessors = SsaMethod.bitSetFromLabelList(ropBlocks, rmeth.labelToPredecessors(bb.getLabel()));
    result.successors = SsaMethod.bitSetFromLabelList(ropBlocks, bb.getSuccessors());
    result.successorList = SsaMethod.indexListFromLabelList(ropBlocks, bb.getSuccessors());
    if (result.successorList.size() != 0) {
        int primarySuccessor = bb.getPrimarySuccessor();
        result.primarySuccessor = (primarySuccessor < 0) ? -1 : ropBlocks.indexOfLabel(primarySuccessor);
    }
    return result;
}
Also used : BasicBlock(com.android.dx.rop.code.BasicBlock) InsnList(com.android.dx.rop.code.InsnList) BasicBlockList(com.android.dx.rop.code.BasicBlockList)

Example 4 with BasicBlock

use of com.android.dx.rop.code.BasicBlock in project buck by facebook.

the class Ropper method inlineSubroutines.

/**
     * Inlines any subroutine calls.
     */
private void inlineSubroutines() {
    final IntList reachableSubroutineCallerLabels = new IntList(4);
    /*
         * Compile a list of all subroutine calls reachable
         * through the normal (non-subroutine) flow.  We do this first, since
         * we'll be affecting the call flow as we go.
         *
         * Start at label 0 --  the param assignment block has nothing for us
         */
    forEachNonSubBlockDepthFirst(0, new BasicBlock.Visitor() {

        public void visitBlock(BasicBlock b) {
            if (isSubroutineCaller(b)) {
                reachableSubroutineCallerLabels.add(b.getLabel());
            }
        }
    });
    /*
         * Convert the resultSubroutines list, indexed by block index,
         * to a label-to-subroutines mapping used by the inliner.
         */
    int largestAllocedLabel = getAvailableLabel();
    ArrayList<IntList> labelToSubroutines = new ArrayList<IntList>(largestAllocedLabel);
    for (int i = 0; i < largestAllocedLabel; i++) {
        labelToSubroutines.add(null);
    }
    for (int i = 0; i < result.size(); i++) {
        BasicBlock b = result.get(i);
        if (b == null) {
            continue;
        }
        IntList subroutineList = resultSubroutines.get(i);
        labelToSubroutines.set(b.getLabel(), subroutineList);
    }
    /*
         * Inline all reachable subroutines.
         * Inner subroutines will be inlined as they are encountered.
         */
    int sz = reachableSubroutineCallerLabels.size();
    for (int i = 0; i < sz; i++) {
        int label = reachableSubroutineCallerLabels.get(i);
        new SubroutineInliner(new LabelAllocator(getAvailableLabel()), labelToSubroutines).inlineSubroutineCalledFrom(labelToBlock(label));
    }
    // Now find the blocks that aren't reachable and remove them
    deleteUnreachableBlocks();
}
Also used : BasicBlock(com.android.dx.rop.code.BasicBlock) ArrayList(java.util.ArrayList) IntList(com.android.dx.util.IntList)

Example 5 with BasicBlock

use of com.android.dx.rop.code.BasicBlock in project buck by facebook.

the class DotDumper method endParsingMember.

public void endParsingMember(ByteArray bytes, int offset, String name, String descriptor, Member member) {
    if (!(member instanceof Method)) {
        return;
    }
    if (!shouldDumpMethod(name)) {
        return;
    }
    ConcreteMethod meth = new ConcreteMethod((Method) member, classFile, true, true);
    TranslationAdvice advice = DexTranslationAdvice.THE_ONE;
    RopMethod rmeth = Ropper.convert(meth, advice, classFile.getMethods());
    if (optimize) {
        boolean isStatic = AccessFlags.isStatic(meth.getAccessFlags());
        rmeth = Optimizer.optimize(rmeth, BaseDumper.computeParamWidth(meth, isStatic), isStatic, true, advice);
    }
    System.out.println("digraph " + name + "{");
    System.out.println("\tfirst -> n" + Hex.u2(rmeth.getFirstLabel()) + ";");
    BasicBlockList blocks = rmeth.getBlocks();
    int sz = blocks.size();
    for (int i = 0; i < sz; i++) {
        BasicBlock bb = blocks.get(i);
        int label = bb.getLabel();
        IntList successors = bb.getSuccessors();
        if (successors.size() == 0) {
            System.out.println("\tn" + Hex.u2(label) + " -> returns;");
        } else if (successors.size() == 1) {
            System.out.println("\tn" + Hex.u2(label) + " -> n" + Hex.u2(successors.get(0)) + ";");
        } else {
            System.out.print("\tn" + Hex.u2(label) + " -> {");
            for (int j = 0; j < successors.size(); j++) {
                int successor = successors.get(j);
                if (successor != bb.getPrimarySuccessor()) {
                    System.out.print(" n" + Hex.u2(successor) + " ");
                }
            }
            System.out.println("};");
            System.out.println("\tn" + Hex.u2(label) + " -> n" + Hex.u2(bb.getPrimarySuccessor()) + " [label=\"primary\"];");
        }
    }
    System.out.println("}");
}
Also used : RopMethod(com.android.dx.rop.code.RopMethod) ConcreteMethod(com.android.dx.cf.code.ConcreteMethod) BasicBlock(com.android.dx.rop.code.BasicBlock) DexTranslationAdvice(com.android.dx.rop.code.DexTranslationAdvice) TranslationAdvice(com.android.dx.rop.code.TranslationAdvice) ConcreteMethod(com.android.dx.cf.code.ConcreteMethod) RopMethod(com.android.dx.rop.code.RopMethod) Method(com.android.dx.cf.iface.Method) BasicBlockList(com.android.dx.rop.code.BasicBlockList) IntList(com.android.dx.util.IntList)

Aggregations

BasicBlock (com.android.dx.rop.code.BasicBlock)20 IntList (com.android.dx.util.IntList)11 BasicBlockList (com.android.dx.rop.code.BasicBlockList)8 Insn (com.android.dx.rop.code.Insn)7 InsnList (com.android.dx.rop.code.InsnList)7 SourcePosition (com.android.dx.rop.code.SourcePosition)6 PlainCstInsn (com.android.dx.rop.code.PlainCstInsn)5 PlainInsn (com.android.dx.rop.code.PlainInsn)5 ThrowingCstInsn (com.android.dx.rop.code.ThrowingCstInsn)5 ThrowingInsn (com.android.dx.rop.code.ThrowingInsn)5 RegisterSpec (com.android.dx.rop.code.RegisterSpec)3 RopMethod (com.android.dx.rop.code.RopMethod)3 CstType (com.android.dx.rop.cst.CstType)3 TypeList (com.android.dx.rop.type.TypeList)3 DexTranslationAdvice (com.android.dx.rop.code.DexTranslationAdvice)2 TranslationAdvice (com.android.dx.rop.code.TranslationAdvice)2 StdTypeList (com.android.dx.rop.type.StdTypeList)2 Type (com.android.dx.rop.type.Type)2 ArrayList (java.util.ArrayList)2 BytecodeArray (com.android.dx.cf.code.BytecodeArray)1