Search in sources :

Example 1 with CstType

use of com.taobao.android.dx.rop.cst.CstType in project atlas by alibaba.

the class RopperMachine method run.

/** {@inheritDoc} */
@Override
public void run(Frame frame, int offset, int opcode) {
    /*
         * This is the stack pointer after the opcode's arguments have been
         * popped.
         */
    int stackPointer = maxLocals + frame.getStack().size();
    // The sources have to be retrieved before super.run() gets called.
    RegisterSpecList sources = getSources(opcode, stackPointer);
    int sourceCount = sources.size();
    super.run(frame, offset, opcode);
    SourcePosition pos = method.makeSourcePosistion(offset);
    RegisterSpec localTarget = getLocalTarget(opcode == ByteOps.ISTORE);
    int destCount = resultCount();
    RegisterSpec dest;
    if (destCount == 0) {
        dest = null;
        switch(opcode) {
            case ByteOps.POP:
            case ByteOps.POP2:
                {
                    // These simply don't appear in the rop form.
                    return;
                }
        }
    } else if (localTarget != null) {
        dest = localTarget;
    } else if (destCount == 1) {
        dest = RegisterSpec.make(stackPointer, result(0));
    } else {
        /*
             * This clause only ever applies to the stack manipulation
             * ops that have results (that is, dup* and swap but not
             * pop*).
             *
             * What we do is first move all the source registers into
             * the "temporary stack" area defined for the method, and
             * then move stuff back down onto the main "stack" in the
             * arrangement specified by the stack op pattern.
             *
             * Note: This code ends up emitting a lot of what will
             * turn out to be superfluous moves (e.g., moving back and
             * forth to the same local when doing a dup); however,
             * that makes this code a bit easier (and goodness knows
             * it doesn't need any extra complexity), and all the SSA
             * stuff is going to want to deal with this sort of
             * superfluous assignment anyway, so it should be a wash
             * in the end.
             */
        int scratchAt = ropper.getFirstTempStackReg();
        RegisterSpec[] scratchRegs = new RegisterSpec[sourceCount];
        for (int i = 0; i < sourceCount; i++) {
            RegisterSpec src = sources.get(i);
            TypeBearer type = src.getTypeBearer();
            RegisterSpec scratch = src.withReg(scratchAt);
            insns.add(new PlainInsn(Rops.opMove(type), pos, scratch, src));
            scratchRegs[i] = scratch;
            scratchAt += src.getCategory();
        }
        for (int pattern = getAuxInt(); pattern != 0; pattern >>= 4) {
            int which = (pattern & 0x0f) - 1;
            RegisterSpec scratch = scratchRegs[which];
            TypeBearer type = scratch.getTypeBearer();
            insns.add(new PlainInsn(Rops.opMove(type), pos, scratch.withReg(stackPointer), scratch));
            stackPointer += type.getType().getCategory();
        }
        return;
    }
    TypeBearer destType = (dest != null) ? dest : Type.VOID;
    Constant cst = getAuxCst();
    int ropOpcode;
    Rop rop;
    Insn insn;
    if (opcode == ByteOps.MULTIANEWARRAY) {
        blockCanThrow = true;
        // Add the extra instructions for handling multianewarray.
        extraBlockCount = 6;
        /*
             * Add an array constructor for the int[] containing all the
             * dimensions.
             */
        RegisterSpec dimsReg = RegisterSpec.make(dest.getNextReg(), Type.INT_ARRAY);
        rop = Rops.opFilledNewArray(Type.INT_ARRAY, sourceCount);
        insn = new ThrowingCstInsn(rop, pos, sources, catches, CstType.INT_ARRAY);
        insns.add(insn);
        // Add a move-result for the new-filled-array
        rop = Rops.opMoveResult(Type.INT_ARRAY);
        insn = new PlainInsn(rop, pos, dimsReg, RegisterSpecList.EMPTY);
        insns.add(insn);
        /*
             * Add a const-class instruction for the specified array
             * class.
             */
        /*
             * Remove as many dimensions from the originally specified
             * class as are given in the explicit list of dimensions,
             * so as to pass the right component class to the standard
             * Java library array constructor.
             */
        Type componentType = ((CstType) cst).getClassType();
        for (int i = 0; i < sourceCount; i++) {
            componentType = componentType.getComponentType();
        }
        RegisterSpec classReg = RegisterSpec.make(dest.getReg(), Type.CLASS);
        if (componentType.isPrimitive()) {
            /*
                 * The component type is primitive (e.g., int as opposed
                 * to Integer), so we have to fetch the corresponding
                 * TYPE class.
                 */
            CstFieldRef typeField = CstFieldRef.forPrimitiveType(componentType);
            insn = new ThrowingCstInsn(Rops.GET_STATIC_OBJECT, pos, RegisterSpecList.EMPTY, catches, typeField);
        } else {
            /*
                 * The component type is an object type, so just make a
                 * normal class reference.
                 */
            insn = new ThrowingCstInsn(Rops.CONST_OBJECT, pos, RegisterSpecList.EMPTY, catches, new CstType(componentType));
        }
        insns.add(insn);
        // Add a move-result-pseudo for the get-static or const
        rop = Rops.opMoveResultPseudo(classReg.getType());
        insn = new PlainInsn(rop, pos, classReg, RegisterSpecList.EMPTY);
        insns.add(insn);
        /*
             * Add a call to the "multianewarray method," that is,
             * Array.newInstance(class, dims). Note: The result type
             * of newInstance() is Object, which is why the last
             * instruction in this sequence is a cast to the right
             * type for the original instruction.
             */
        RegisterSpec objectReg = RegisterSpec.make(dest.getReg(), Type.OBJECT);
        insn = new ThrowingCstInsn(Rops.opInvokeStatic(MULTIANEWARRAY_METHOD.getPrototype()), pos, RegisterSpecList.make(classReg, dimsReg), catches, MULTIANEWARRAY_METHOD);
        insns.add(insn);
        // Add a move-result.
        rop = Rops.opMoveResult(MULTIANEWARRAY_METHOD.getPrototype().getReturnType());
        insn = new PlainInsn(rop, pos, objectReg, RegisterSpecList.EMPTY);
        insns.add(insn);
        /*
             * And finally, set up for the remainder of this method to
             * add an appropriate cast.
             */
        opcode = ByteOps.CHECKCAST;
        sources = RegisterSpecList.make(objectReg);
    } else if (opcode == ByteOps.JSR) {
        // JSR has no Rop instruction
        hasJsr = true;
        return;
    } else if (opcode == ByteOps.RET) {
        try {
            returnAddress = (ReturnAddress) arg(0);
        } catch (ClassCastException ex) {
            throw new RuntimeException("Argument to RET was not a ReturnAddress", ex);
        }
        // RET has no Rop instruction.
        return;
    }
    ropOpcode = jopToRopOpcode(opcode, cst);
    rop = Rops.ropFor(ropOpcode, destType, sources, cst);
    Insn moveResult = null;
    if (dest != null && rop.isCallLike()) {
        /*
             * We're going to want to have a move-result in the next
             * basic block.
             */
        extraBlockCount++;
        moveResult = new PlainInsn(Rops.opMoveResult(((CstMethodRef) cst).getPrototype().getReturnType()), pos, dest, RegisterSpecList.EMPTY);
        dest = null;
    } else if (dest != null && rop.canThrow()) {
        /*
             * We're going to want to have a move-result-pseudo in the
             * next basic block.
             */
        extraBlockCount++;
        moveResult = new PlainInsn(Rops.opMoveResultPseudo(dest.getTypeBearer()), pos, dest, RegisterSpecList.EMPTY);
        dest = null;
    }
    if (ropOpcode == RegOps.NEW_ARRAY) {
        /*
             * In the original bytecode, this was either a primitive
             * array constructor "newarray" or an object array
             * constructor "anewarray". In the former case, there is
             * no explicit constant, and in the latter, the constant
             * is for the element type and not the array type. The rop
             * instruction form for both of these is supposed to be
             * the resulting array type, so we initialize / alter
             * "cst" here, accordingly. Conveniently enough, the rop
             * opcode already gets constructed with the proper array
             * type.
             */
        cst = CstType.intern(rop.getResult());
    } else if ((cst == null) && (sourceCount == 2)) {
        TypeBearer firstType = sources.get(0).getTypeBearer();
        TypeBearer lastType = sources.get(1).getTypeBearer();
        if ((lastType.isConstant() || firstType.isConstant()) && advice.hasConstantOperation(rop, sources.get(0), sources.get(1))) {
            if (lastType.isConstant()) {
                /*
                     * The target architecture has an instruction that can
                     * build in the constant found in the second argument,
                     * so pull it out of the sources and just use it as a
                     * constant here.
                     */
                cst = (Constant) lastType;
                sources = sources.withoutLast();
                // For subtraction, change to addition and invert constant
                if (rop.getOpcode() == RegOps.SUB) {
                    ropOpcode = RegOps.ADD;
                    CstInteger cstInt = (CstInteger) lastType;
                    cst = CstInteger.make(-cstInt.getValue());
                }
            } else {
                /*
                     * The target architecture has an instruction that can
                     * build in the constant found in the first argument,
                     * so pull it out of the sources and just use it as a
                     * constant here.
                     */
                cst = (Constant) firstType;
                sources = sources.withoutFirst();
            }
            rop = Rops.ropFor(ropOpcode, destType, sources, cst);
        }
    }
    SwitchList cases = getAuxCases();
    ArrayList<Constant> initValues = getInitValues();
    boolean canThrow = rop.canThrow();
    blockCanThrow |= canThrow;
    if (cases != null) {
        if (cases.size() == 0) {
            // It's a default-only switch statement. It can happen!
            insn = new PlainInsn(Rops.GOTO, pos, null, RegisterSpecList.EMPTY);
            primarySuccessorIndex = 0;
        } else {
            IntList values = cases.getValues();
            insn = new SwitchInsn(rop, pos, dest, sources, values);
            primarySuccessorIndex = values.size();
        }
    } else if (ropOpcode == RegOps.RETURN) {
        /*
             * Returns get turned into the combination of a move (if
             * non-void and if the return doesn't already mention
             * register 0) and a goto (to the return block).
             */
        if (sources.size() != 0) {
            RegisterSpec source = sources.get(0);
            TypeBearer type = source.getTypeBearer();
            if (source.getReg() != 0) {
                insns.add(new PlainInsn(Rops.opMove(type), pos, RegisterSpec.make(0, type), source));
            }
        }
        insn = new PlainInsn(Rops.GOTO, pos, null, RegisterSpecList.EMPTY);
        primarySuccessorIndex = 0;
        updateReturnOp(rop, pos);
        returns = true;
    } else if (cst != null) {
        if (canThrow) {
            insn = new ThrowingCstInsn(rop, pos, sources, catches, cst);
            catchesUsed = true;
            primarySuccessorIndex = catches.size();
        } else {
            insn = new PlainCstInsn(rop, pos, dest, sources, cst);
        }
    } else if (canThrow) {
        insn = new ThrowingInsn(rop, pos, sources, catches);
        catchesUsed = true;
        if (opcode == ByteOps.ATHROW) {
            /*
                 * The op athrow is the only one where it's possible
                 * to have non-empty successors and yet not have a
                 * primary successor.
                 */
            primarySuccessorIndex = -1;
        } else {
            primarySuccessorIndex = catches.size();
        }
    } else {
        insn = new PlainInsn(rop, pos, dest, sources);
    }
    insns.add(insn);
    if (moveResult != null) {
        insns.add(moveResult);
    }
    /*
         * If initValues is non-null, it means that the parser has
         * seen a group of compatible constant initialization
         * bytecodes that are applied to the current newarray. The
         * action we take here is to convert these initialization
         * bytecodes into a single fill-array-data ROP which lays out
         * all the constant values in a table.
         */
    if (initValues != null) {
        extraBlockCount++;
        insn = new FillArrayDataInsn(Rops.FILL_ARRAY_DATA, pos, RegisterSpecList.make(moveResult.getResult()), initValues, cst);
        insns.add(insn);
    }
}
Also used : Insn(com.taobao.android.dx.rop.code.Insn) PlainCstInsn(com.taobao.android.dx.rop.code.PlainCstInsn) SwitchInsn(com.taobao.android.dx.rop.code.SwitchInsn) PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) ThrowingInsn(com.taobao.android.dx.rop.code.ThrowingInsn) ThrowingCstInsn(com.taobao.android.dx.rop.code.ThrowingCstInsn) FillArrayDataInsn(com.taobao.android.dx.rop.code.FillArrayDataInsn) ThrowingCstInsn(com.taobao.android.dx.rop.code.ThrowingCstInsn) Constant(com.taobao.android.dx.rop.cst.Constant) ThrowingInsn(com.taobao.android.dx.rop.code.ThrowingInsn) RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList) CstInteger(com.taobao.android.dx.rop.cst.CstInteger) SourcePosition(com.taobao.android.dx.rop.code.SourcePosition) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec) FillArrayDataInsn(com.taobao.android.dx.rop.code.FillArrayDataInsn) CstFieldRef(com.taobao.android.dx.rop.cst.CstFieldRef) CstMethodRef(com.taobao.android.dx.rop.cst.CstMethodRef) SwitchInsn(com.taobao.android.dx.rop.code.SwitchInsn) IntList(com.taobao.android.dx.util.IntList) PlainCstInsn(com.taobao.android.dx.rop.code.PlainCstInsn) PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) Rop(com.taobao.android.dx.rop.code.Rop) CstType(com.taobao.android.dx.rop.cst.CstType) Type(com.taobao.android.dx.rop.type.Type) CstType(com.taobao.android.dx.rop.cst.CstType) TypeBearer(com.taobao.android.dx.rop.type.TypeBearer)

Example 2 with CstType

use of com.taobao.android.dx.rop.cst.CstType in project atlas by alibaba.

the class BytecodeArray method parseNewarray.

/**
     * Helper to deal with {@code newarray}.
     *
     * @param offset the offset to the {@code newarray} opcode itself
     * @param visitor {@code non-null;} visitor to use
     * @return instruction length, in bytes
     */
private int parseNewarray(int offset, Visitor visitor) {
    int value = bytes.getUnsignedByte(offset + 1);
    CstType type;
    switch(value) {
        case ByteOps.NEWARRAY_BOOLEAN:
            {
                type = CstType.BOOLEAN_ARRAY;
                break;
            }
        case ByteOps.NEWARRAY_CHAR:
            {
                type = CstType.CHAR_ARRAY;
                break;
            }
        case ByteOps.NEWARRAY_DOUBLE:
            {
                type = CstType.DOUBLE_ARRAY;
                break;
            }
        case ByteOps.NEWARRAY_FLOAT:
            {
                type = CstType.FLOAT_ARRAY;
                break;
            }
        case ByteOps.NEWARRAY_BYTE:
            {
                type = CstType.BYTE_ARRAY;
                break;
            }
        case ByteOps.NEWARRAY_SHORT:
            {
                type = CstType.SHORT_ARRAY;
                break;
            }
        case ByteOps.NEWARRAY_INT:
            {
                type = CstType.INT_ARRAY;
                break;
            }
        case ByteOps.NEWARRAY_LONG:
            {
                type = CstType.LONG_ARRAY;
                break;
            }
        default:
            {
                throw new SimException("bad newarray code " + Hex.u1(value));
            }
    }
    // Revisit the previous bytecode to find out the length of the array
    int previousOffset = visitor.getPreviousOffset();
    ConstantParserVisitor constantVisitor = new ConstantParserVisitor();
    int arrayLength = 0;
    /*
         * For visitors that don't record the previous offset, -1 will be
         * seen here
         */
    if (previousOffset >= 0) {
        parseInstruction(previousOffset, constantVisitor);
        if (constantVisitor.cst instanceof CstInteger && constantVisitor.length + previousOffset == offset) {
            arrayLength = constantVisitor.value;
        }
    }
    /*
         * Try to match the array initialization idiom. For example, if the
         * subsequent code is initializing an int array, we are expecting the
         * following pattern repeatedly:
         *  dup
         *  push index
         *  push value
         *  *astore
         *
         * where the index value will be incrimented sequentially from 0 up.
         */
    int nInit = 0;
    int curOffset = offset + 2;
    int lastOffset = curOffset;
    ArrayList<Constant> initVals = new ArrayList<Constant>();
    if (arrayLength != 0) {
        while (true) {
            boolean punt = false;
            // First, check if the next bytecode is dup.
            int nextByte = bytes.getUnsignedByte(curOffset++);
            if (nextByte != ByteOps.DUP)
                break;
            /*
                 * Next, check if the expected array index is pushed to
                 * the stack.
                 */
            parseInstruction(curOffset, constantVisitor);
            if (constantVisitor.length == 0 || !(constantVisitor.cst instanceof CstInteger) || constantVisitor.value != nInit)
                break;
            // Next, fetch the init value and record it.
            curOffset += constantVisitor.length;
            /*
                 * Next, find out what kind of constant is pushed onto
                 * the stack.
                 */
            parseInstruction(curOffset, constantVisitor);
            if (constantVisitor.length == 0 || !(constantVisitor.cst instanceof CstLiteralBits))
                break;
            curOffset += constantVisitor.length;
            initVals.add(constantVisitor.cst);
            nextByte = bytes.getUnsignedByte(curOffset++);
            // Now, check if the value is stored to the array properly.
            switch(value) {
                case ByteOps.NEWARRAY_BYTE:
                case ByteOps.NEWARRAY_BOOLEAN:
                    {
                        if (nextByte != ByteOps.BASTORE) {
                            punt = true;
                        }
                        break;
                    }
                case ByteOps.NEWARRAY_CHAR:
                    {
                        if (nextByte != ByteOps.CASTORE) {
                            punt = true;
                        }
                        break;
                    }
                case ByteOps.NEWARRAY_DOUBLE:
                    {
                        if (nextByte != ByteOps.DASTORE) {
                            punt = true;
                        }
                        break;
                    }
                case ByteOps.NEWARRAY_FLOAT:
                    {
                        if (nextByte != ByteOps.FASTORE) {
                            punt = true;
                        }
                        break;
                    }
                case ByteOps.NEWARRAY_SHORT:
                    {
                        if (nextByte != ByteOps.SASTORE) {
                            punt = true;
                        }
                        break;
                    }
                case ByteOps.NEWARRAY_INT:
                    {
                        if (nextByte != ByteOps.IASTORE) {
                            punt = true;
                        }
                        break;
                    }
                case ByteOps.NEWARRAY_LONG:
                    {
                        if (nextByte != ByteOps.LASTORE) {
                            punt = true;
                        }
                        break;
                    }
                default:
                    punt = true;
                    break;
            }
            if (punt) {
                break;
            }
            lastOffset = curOffset;
            nInit++;
        }
    }
    /*
         * For singleton arrays it is still more economical to
         * generate the aput.
         */
    if (nInit < 2 || nInit != arrayLength) {
        visitor.visitNewarray(offset, 2, type, null);
        return 2;
    } else {
        visitor.visitNewarray(offset, lastOffset - offset, type, initVals);
        return lastOffset - offset;
    }
}
Also used : CstLiteralBits(com.taobao.android.dx.rop.cst.CstLiteralBits) CstInteger(com.taobao.android.dx.rop.cst.CstInteger) Constant(com.taobao.android.dx.rop.cst.Constant) CstType(com.taobao.android.dx.rop.cst.CstType) ArrayList(java.util.ArrayList)

Example 3 with CstType

use of com.taobao.android.dx.rop.cst.CstType in project atlas by alibaba.

the class CfTranslator method processMethods.

/**
     * Processes the methods of the given class.
     *
     * @param cf {@code non-null;} class being translated
     * @param cfOptions {@code non-null;} options for class translation
     * @param dexOptions {@code non-null;} options for dex output
     * @param out {@code non-null;} output class
     * @param dexFile {@code non-null;} dex output
     */
private static void processMethods(DirectClassFile cf, CfOptions cfOptions, DexOptions dexOptions, OptimizerOptions optimizerOptions, ClassDefItem out, DexFile dexFile) {
    CstType thisClass = cf.getThisClass();
    MethodList methods = cf.getMethods();
    int sz = methods.size();
    for (int i = 0; i < sz; i++) {
        Method one = methods.get(i);
        try {
            CstMethodRef meth = new CstMethodRef(thisClass, one.getNat());
            int accessFlags = one.getAccessFlags();
            boolean isStatic = AccessFlags.isStatic(accessFlags);
            boolean isPrivate = AccessFlags.isPrivate(accessFlags);
            boolean isNative = AccessFlags.isNative(accessFlags);
            boolean isAbstract = AccessFlags.isAbstract(accessFlags);
            boolean isConstructor = meth.isInstanceInit() || meth.isClassInit();
            DalvCode code;
            if (isNative || isAbstract) {
                // There's no code for native or abstract methods.
                code = null;
            } else {
                ConcreteMethod concrete = new ConcreteMethod(one, cf, (cfOptions.positionInfo != PositionList.NONE), cfOptions.localInfo);
                TranslationAdvice advice;
                advice = DexTranslationAdvice.THE_ONE;
                RopMethod rmeth = Ropper.convert(concrete, advice, methods);
                RopMethod nonOptRmeth = null;
                int paramSize;
                paramSize = meth.getParameterWordCount(isStatic);
                String canonicalName = thisClass.getClassType().getDescriptor() + "." + one.getName().getString();
                if (cfOptions.optimize && optimizerOptions.shouldOptimize(canonicalName)) {
                    if (DEBUG) {
                        System.err.println("Optimizing " + canonicalName);
                    }
                    nonOptRmeth = rmeth;
                    rmeth = new Optimizer().optimize(rmeth, paramSize, isStatic, cfOptions.localInfo, advice);
                    if (DEBUG) {
                        OptimizerOptions.compareOptimizerStep(nonOptRmeth, paramSize, isStatic, cfOptions, advice, rmeth);
                    }
                    if (cfOptions.statistics) {
                        cfOptions.codeStatistics.updateRopStatistics(nonOptRmeth, rmeth);
                    }
                }
                LocalVariableInfo locals = null;
                if (cfOptions.localInfo) {
                    locals = LocalVariableExtractor.extract(rmeth);
                }
                code = RopTranslator.translate(rmeth, cfOptions.positionInfo, locals, paramSize, dexOptions);
                if (cfOptions.statistics && nonOptRmeth != null) {
                    updateDexStatistics(cfOptions, dexOptions, rmeth, nonOptRmeth, locals, paramSize, concrete.getCode().size());
                }
            }
            // Preserve the synchronized flag as its "declared" variant...
            if (AccessFlags.isSynchronized(accessFlags)) {
                accessFlags |= AccessFlags.ACC_DECLARED_SYNCHRONIZED;
                /*
                     * ...but only native methods are actually allowed to be
                     * synchronized.
                     */
                if (!isNative) {
                    accessFlags &= ~AccessFlags.ACC_SYNCHRONIZED;
                }
            }
            if (isConstructor) {
                accessFlags |= AccessFlags.ACC_CONSTRUCTOR;
            }
            TypeList exceptions = AttributeTranslator.getExceptions(one);
            EncodedMethod mi = new EncodedMethod(meth, accessFlags, code, exceptions);
            if (meth.isInstanceInit() || meth.isClassInit() || isStatic || isPrivate) {
                out.addDirectMethod(mi);
            } else {
                out.addVirtualMethod(mi);
            }
            Annotations annotations = AttributeTranslator.getMethodAnnotations(one);
            if (annotations.size() != 0) {
                if (list.contains(meth.toString())) {
                    System.out.println(meth.toString());
                } else {
                    list.add(meth.toString());
                }
                out.addMethodAnnotations(meth, annotations, dexFile);
            }
            AnnotationsList list = AttributeTranslator.getParameterAnnotations(one);
            if (list.size() != 0) {
                out.addParameterAnnotations(meth, list, dexFile);
            }
            dexFile.getMethodIds().intern(meth);
        } catch (RuntimeException ex) {
            String msg = "...while processing " + one.getName().toHuman() + " " + one.getDescriptor().toHuman();
            throw ExceptionWithContext.withContext(ex, msg);
        }
    }
}
Also used : DalvCode(com.taobao.android.dx.dex.code.DalvCode) RopMethod(com.taobao.android.dx.rop.code.RopMethod) Optimizer(com.taobao.android.dx.ssa.Optimizer) AnnotationsList(com.taobao.android.dx.rop.annotation.AnnotationsList) MethodList(com.taobao.android.dx.cf.iface.MethodList) TranslationAdvice(com.taobao.android.dx.rop.code.TranslationAdvice) DexTranslationAdvice(com.taobao.android.dx.rop.code.DexTranslationAdvice) Method(com.taobao.android.dx.cf.iface.Method) ConcreteMethod(com.taobao.android.dx.cf.code.ConcreteMethod) RopMethod(com.taobao.android.dx.rop.code.RopMethod) EncodedMethod(com.taobao.android.dx.dex.file.EncodedMethod) CstString(com.taobao.android.dx.rop.cst.CstString) CstMethodRef(com.taobao.android.dx.rop.cst.CstMethodRef) LocalVariableInfo(com.taobao.android.dx.rop.code.LocalVariableInfo) Annotations(com.taobao.android.dx.rop.annotation.Annotations) EncodedMethod(com.taobao.android.dx.dex.file.EncodedMethod) CstType(com.taobao.android.dx.rop.cst.CstType) ConcreteMethod(com.taobao.android.dx.cf.code.ConcreteMethod) TypeList(com.taobao.android.dx.rop.type.TypeList)

Example 4 with CstType

use of com.taobao.android.dx.rop.cst.CstType in project atlas by alibaba.

the class CfTranslator method translate0.

/**
     * Performs the main act of translation. This method is separated
     * from {@link #translate} just to keep things a bit simpler in
     * terms of exception handling.
     *
     * @param cf {@code non-null;} the class file
     * @param bytes {@code non-null;} contents of the file
     * @param cfOptions options for class translation
     * @param dexOptions options for dex output
     * @param dexFile {@code non-null;} dex output
     * @param optimizerOptions options for the optimizer
     * @return {@code non-null;} the translated class
     */
private static ClassDefItem translate0(DirectClassFile cf, byte[] bytes, CfOptions cfOptions, DexOptions dexOptions, OptimizerOptions optimizerOptions, DexFile dexFile) {
    optimizerOptions.loadOptimizeLists(cfOptions.optimizeListFile, cfOptions.dontOptimizeListFile);
    // Build up a class to output.
    CstType thisClass = cf.getThisClass();
    int classAccessFlags = cf.getAccessFlags() & ~AccessFlags.ACC_SUPER;
    CstString sourceFile = (cfOptions.positionInfo == PositionList.NONE) ? null : cf.getSourceFile();
    ClassDefItem out = new ClassDefItem(thisClass, classAccessFlags, cf.getSuperclass(), cf.getInterfaces(), sourceFile);
    Annotations classAnnotations = AttributeTranslator.getClassAnnotations(cf, cfOptions);
    if (classAnnotations.size() != 0) {
        out.setClassAnnotations(classAnnotations, dexFile);
    }
    FieldIdsSection fieldIdsSection = dexFile.getFieldIds();
    MethodIdsSection methodIdsSection = dexFile.getMethodIds();
    processFields(cf, out, dexFile);
    processMethods(cf, cfOptions, dexOptions, optimizerOptions, out, dexFile);
    // intern constant pool method, field and type references
    ConstantPool constantPool = cf.getConstantPool();
    int constantPoolSize = constantPool.size();
    for (int i = 0; i < constantPoolSize; i++) {
        Constant constant = constantPool.getOrNull(i);
        if (constant instanceof CstMethodRef) {
            methodIdsSection.intern((CstBaseMethodRef) constant);
        } else if (constant instanceof CstInterfaceMethodRef) {
            methodIdsSection.intern(((CstInterfaceMethodRef) constant).toMethodRef());
        } else if (constant instanceof CstFieldRef) {
            fieldIdsSection.intern((CstFieldRef) constant);
        } else if (constant instanceof CstEnumRef) {
            fieldIdsSection.intern(((CstEnumRef) constant).getFieldRef());
        }
    }
    return out;
}
Also used : Constant(com.taobao.android.dx.rop.cst.Constant) TypedConstant(com.taobao.android.dx.rop.cst.TypedConstant) CstString(com.taobao.android.dx.rop.cst.CstString) CstFieldRef(com.taobao.android.dx.rop.cst.CstFieldRef) CstEnumRef(com.taobao.android.dx.rop.cst.CstEnumRef) FieldIdsSection(com.taobao.android.dx.dex.file.FieldIdsSection) MethodIdsSection(com.taobao.android.dx.dex.file.MethodIdsSection) CstMethodRef(com.taobao.android.dx.rop.cst.CstMethodRef) Annotations(com.taobao.android.dx.rop.annotation.Annotations) ClassDefItem(com.taobao.android.dx.dex.file.ClassDefItem) ConstantPool(com.taobao.android.dx.rop.cst.ConstantPool) CstType(com.taobao.android.dx.rop.cst.CstType) CstInterfaceMethodRef(com.taobao.android.dx.rop.cst.CstInterfaceMethodRef)

Example 5 with CstType

use of com.taobao.android.dx.rop.cst.CstType in project atlas by alibaba.

the class BlockDumper method regularDump.

/**
     * Does a regular basic block dump.
     *
     * @param meth {@code non-null;} method data to dump
     */
private void regularDump(ConcreteMethod meth) {
    BytecodeArray code = meth.getCode();
    ByteArray bytes = code.getBytes();
    ByteBlockList list = BasicBlocker.identifyBlocks(meth);
    int sz = list.size();
    CodeObserver codeObserver = new CodeObserver(bytes, BlockDumper.this);
    // Reset the dump cursor to the start of the bytecode.
    setAt(bytes, 0);
    suppressDump = false;
    int byteAt = 0;
    for (int i = 0; i < sz; i++) {
        ByteBlock bb = list.get(i);
        int start = bb.getStart();
        int end = bb.getEnd();
        if (byteAt < start) {
            parsed(bytes, byteAt, start - byteAt, "dead code " + Hex.u2(byteAt) + ".." + Hex.u2(start));
        }
        parsed(bytes, start, 0, "block " + Hex.u2(bb.getLabel()) + ": " + Hex.u2(start) + ".." + Hex.u2(end));
        changeIndent(1);
        int len;
        for (int j = start; j < end; j += len) {
            len = code.parseInstruction(j, codeObserver);
            codeObserver.setPreviousOffset(j);
        }
        IntList successors = bb.getSuccessors();
        int ssz = successors.size();
        if (ssz == 0) {
            parsed(bytes, end, 0, "returns");
        } else {
            for (int j = 0; j < ssz; j++) {
                int succ = successors.get(j);
                parsed(bytes, end, 0, "next " + Hex.u2(succ));
            }
        }
        ByteCatchList catches = bb.getCatches();
        int csz = catches.size();
        for (int j = 0; j < csz; j++) {
            ByteCatchList.Item one = catches.get(j);
            CstType exceptionClass = one.getExceptionClass();
            parsed(bytes, end, 0, "catch " + ((exceptionClass == CstType.OBJECT) ? "<any>" : exceptionClass.toHuman()) + " -> " + Hex.u2(one.getHandlerPc()));
        }
        changeIndent(-1);
        byteAt = end;
    }
    int end = bytes.size();
    if (byteAt < end) {
        parsed(bytes, byteAt, end - byteAt, "dead code " + Hex.u2(byteAt) + ".." + Hex.u2(end));
    }
    suppressDump = true;
}
Also used : BytecodeArray(com.taobao.android.dx.cf.code.BytecodeArray) ByteCatchList(com.taobao.android.dx.cf.code.ByteCatchList) ByteBlock(com.taobao.android.dx.cf.code.ByteBlock) CstType(com.taobao.android.dx.rop.cst.CstType) ByteArray(com.taobao.android.dx.util.ByteArray) CodeObserver(com.taobao.android.dx.cf.direct.CodeObserver) ByteBlockList(com.taobao.android.dx.cf.code.ByteBlockList) IntList(com.taobao.android.dx.util.IntList)

Aggregations

CstType (com.taobao.android.dx.rop.cst.CstType)36 CstString (com.taobao.android.dx.rop.cst.CstString)14 Constant (com.taobao.android.dx.rop.cst.Constant)12 Type (com.taobao.android.dx.rop.type.Type)9 CstFieldRef (com.taobao.android.dx.rop.cst.CstFieldRef)7 CstMethodRef (com.taobao.android.dx.rop.cst.CstMethodRef)6 CstInsn (com.taobao.android.dx.dex.code.CstInsn)5 Annotations (com.taobao.android.dx.rop.annotation.Annotations)5 RegisterSpec (com.taobao.android.dx.rop.code.RegisterSpec)5 RegisterSpecList (com.taobao.android.dx.rop.code.RegisterSpecList)5 Annotation (com.taobao.android.dx.rop.annotation.Annotation)4 CstNat (com.taobao.android.dx.rop.cst.CstNat)4 IntList (com.taobao.android.dx.util.IntList)4 AttEnclosingMethod (com.taobao.android.dx.cf.attrib.AttEnclosingMethod)3 NameValuePair (com.taobao.android.dx.rop.annotation.NameValuePair)3 ConstantPool (com.taobao.android.dx.rop.cst.ConstantPool)3 TypeList (com.taobao.android.dx.rop.type.TypeList)3 ByteArray (com.taobao.android.dx.util.ByteArray)3 AttInnerClasses (com.taobao.android.dx.cf.attrib.AttInnerClasses)2 AttRuntimeInvisibleAnnotations (com.taobao.android.dx.cf.attrib.AttRuntimeInvisibleAnnotations)2