Search in sources :

Example 1 with Instruction3rc

use of org.jf.dexlib2.iface.instruction.formats.Instruction3rc in project atlas by alibaba.

the class InsTructionsReIClassDef method reInstructions.

@Override
protected Iterable<? extends Instruction> reInstructions(Iterable<? extends Instruction> instructions) {
    final List<Instruction> reinstructions = new ArrayList<Instruction>();
    for (final Instruction instruction : instructions) {
        if (instruction instanceof ReferenceInstruction) {
            Opcode opcode = instruction.getOpcode();
            if (opcode.referenceType == ReferenceType.METHOD) {
                boolean isBasic = false;
                MethodReference methodReference = null;
                try {
                    methodReference = (MethodReference) ((ReferenceInstruction) instruction).getReference();
                    if (methodReference.getDefiningClass().contains("Ljava/lang") || methodReference.getDefiningClass().startsWith("Ljava/util/") || methodReference.getDefiningClass().startsWith("[Ljava/lang")) {
                        reinstructions.add(ImmutableInstruction.of(instruction));
                        continue;
                    }
                    String returnType = methodReference.getReturnType();
                    boolean isArray = false;
                    if (returnType.startsWith("[")) {
                        isArray = true;
                    }
                    String methodName = methodReference.getName();
                    if (methodName.equals("InitBundleInfoByVersionIfNeed")) {
                        System.out.println("InitBundleInfoByVersionIfNeed");
                    }
                    if (basicType.containsKey(returnType)) {
                        isBasic = true;
                    }
                    List<? extends CharSequence> paramTypes = methodReference.getParameterTypes();
                    List<CharSequence> dalvikParamTypes = new ArrayList<CharSequence>();
                    List<CharSequence> newParamTypes = new ArrayList<CharSequence>();
                    for (CharSequence charSequence : paramTypes) {
                        if (basicType.containsKey(charSequence.toString())) {
                            newParamTypes.add(charSequence);
                            dalvikParamTypes.add(basicType.get(charSequence.toString()));
                            continue;
                        }
                        boolean isArray1 = charSequence.toString().startsWith("[");
                        dalvikParamTypes.add(DefineUtils.getDalvikClassName(charSequence.toString()) + (isArray ? "[]" : ""));
                        newParamTypes.add(DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(charSequence.toString())).className, isArray1));
                    }
                    final ImmutableMethodReference immutableReference = new ImmutableMethodReference(DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(methodReference.getDefiningClass())).className, false), classProcessor.methodProcess(DefineUtils.getDalvikClassName(methodReference.getDefiningClass()), methodReference.getName(), isBasic ? basicType.get(methodReference.getReturnType()) : DefineUtils.getDalvikClassName(methodReference.getReturnType()) + (isArray ? "[]" : ""), StringUtils.join(dalvikParamTypes.toArray(), ",")).methodName, newParamTypes, isBasic ? returnType : DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(methodReference.getReturnType())).className, methodReference.getReturnType().startsWith("[")));
                    if (instruction instanceof Instruction3rc) {
                        reinstructions.add(new ImmutableInstruction3rc(instruction.getOpcode(), ((Instruction3rc) instruction).getStartRegister(), ((Instruction3rc) instruction).getRegisterCount(), immutableReference));
                    } else if (instruction instanceof Instruction20bc) {
                        reinstructions.add(new ImmutableInstruction20bc(instruction.getOpcode(), ((Instruction20bc) instruction).getVerificationError(), immutableReference));
                    } else if (instruction instanceof Instruction21c) {
                        reinstructions.add(new ImmutableInstruction21c(instruction.getOpcode(), ((Instruction21c) instruction).getRegisterA(), immutableReference));
                    } else if (instruction instanceof Instruction22c) {
                        reinstructions.add(new ImmutableInstruction22c(instruction.getOpcode(), ((Instruction22c) instruction).getRegisterA(), ((Instruction22c) instruction).getRegisterB(), immutableReference));
                    } else if (instruction instanceof Instruction31c) {
                        reinstructions.add(new ImmutableInstruction31c(instruction.getOpcode(), ((Instruction31c) instruction).getRegisterA(), immutableReference));
                    } else if (instruction instanceof Instruction35c) {
                        reinstructions.add(new ImmutableInstruction35c(instruction.getOpcode(), ((Instruction35c) instruction).getRegisterCount(), ((Instruction35c) instruction).getRegisterC(), ((Instruction35c) instruction).getRegisterD(), ((Instruction35c) instruction).getRegisterE(), ((Instruction35c) instruction).getRegisterF(), ((Instruction35c) instruction).getRegisterG(), immutableReference));
                    }
                } catch (Exception e) {
                }
            } else if (opcode.referenceType == ReferenceType.FIELD) {
                FieldReference fieldReference = null;
                boolean isBasic = false;
                boolean isBasicArray = false;
                fieldReference = (FieldReference) ((ReferenceInstruction) instruction).getReference();
                if (fieldReference.getDefiningClass().startsWith("Ljava/lang/") || fieldReference.getDefiningClass().startsWith("Ljava/util/") || fieldReference.getDefiningClass().startsWith("[Ljava/lang/")) {
                    reinstructions.add(ImmutableInstruction.of(instruction));
                    continue;
                }
                if (basicType.containsKey(fieldReference.getType())) {
                    isBasic = true;
                }
                final ImmutableFieldReference immutableFieldReference = new ImmutableFieldReference(DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(fieldReference.getDefiningClass())).className, false), classProcessor.filedProcess(DefineUtils.getDalvikClassName(fieldReference.getDefiningClass()), isBasic ? basicType.get(fieldReference.getType()) : DefineUtils.getDalvikClassName(fieldReference.getType()), fieldReference.getName()).fieldName, isBasic ? fieldReference.getType() : DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(fieldReference.getType())).className, fieldReference.getType().startsWith("[")));
                if (instruction instanceof Instruction3rc) {
                    reinstructions.add(new ImmutableInstruction3rc(instruction.getOpcode(), ((Instruction3rc) instruction).getStartRegister(), ((Instruction3rc) instruction).getRegisterCount(), immutableFieldReference));
                } else if (instruction instanceof Instruction20bc) {
                    reinstructions.add(new ImmutableInstruction20bc(instruction.getOpcode(), ((Instruction20bc) instruction).getVerificationError(), immutableFieldReference));
                } else if (instruction instanceof Instruction21c) {
                    reinstructions.add(new ImmutableInstruction21c(instruction.getOpcode(), ((Instruction21c) instruction).getRegisterA(), immutableFieldReference));
                } else if (instruction instanceof Instruction22c) {
                    reinstructions.add(new ImmutableInstruction22c(instruction.getOpcode(), ((Instruction22c) instruction).getRegisterA(), ((Instruction22c) instruction).getRegisterB(), immutableFieldReference));
                } else if (instruction instanceof Instruction31c) {
                    reinstructions.add(new ImmutableInstruction31c(instruction.getOpcode(), ((Instruction31c) instruction).getRegisterA(), immutableFieldReference));
                } else if (instruction instanceof Instruction35c) {
                    reinstructions.add(new ImmutableInstruction35c(instruction.getOpcode(), ((Instruction35c) instruction).getRegisterCount(), ((Instruction35c) instruction).getRegisterC(), ((Instruction35c) instruction).getRegisterD(), ((Instruction35c) instruction).getRegisterE(), ((Instruction35c) instruction).getRegisterF(), ((Instruction35c) instruction).getRegisterG(), immutableFieldReference));
                }
            } else if (opcode.referenceType == ReferenceType.TYPE) {
                TypeReference typeReference = (TypeReference) ((ReferenceInstruction) instruction).getReference();
                String type = typeReference.getType();
                if (!basicType.containsKey(type) && !type.startsWith("Ljava/lang") && !type.startsWith("Ljava/util/") && !type.startsWith("[Ljava/lang")) {
                    type = DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(type)).className, type.startsWith("["));
                }
                ImmutableTypeReference immutableTypeReference = new ImmutableTypeReference(type);
                if (instruction instanceof Instruction3rc) {
                    reinstructions.add(new ImmutableInstruction3rc(instruction.getOpcode(), ((Instruction3rc) instruction).getStartRegister(), ((Instruction3rc) instruction).getRegisterCount(), immutableTypeReference));
                } else if (instruction instanceof Instruction20bc) {
                    reinstructions.add(new ImmutableInstruction20bc(instruction.getOpcode(), ((Instruction20bc) instruction).getVerificationError(), immutableTypeReference));
                } else if (instruction instanceof Instruction21c) {
                    reinstructions.add(new ImmutableInstruction21c(instruction.getOpcode(), ((Instruction21c) instruction).getRegisterA(), immutableTypeReference));
                } else if (instruction instanceof Instruction22c) {
                    reinstructions.add(new ImmutableInstruction22c(instruction.getOpcode(), ((Instruction22c) instruction).getRegisterA(), ((Instruction22c) instruction).getRegisterB(), immutableTypeReference));
                } else if (instruction instanceof Instruction31c) {
                    reinstructions.add(new ImmutableInstruction31c(instruction.getOpcode(), ((Instruction31c) instruction).getRegisterA(), immutableTypeReference));
                } else if (instruction instanceof Instruction35c) {
                    reinstructions.add(new ImmutableInstruction35c(instruction.getOpcode(), ((Instruction35c) instruction).getRegisterCount(), ((Instruction35c) instruction).getRegisterC(), ((Instruction35c) instruction).getRegisterD(), ((Instruction35c) instruction).getRegisterE(), ((Instruction35c) instruction).getRegisterF(), ((Instruction35c) instruction).getRegisterG(), immutableTypeReference));
                }
            } else if (opcode.referenceType == ReferenceType.STRING) {
                StringReference stringReference = (StringReference) ((ReferenceInstruction) instruction).getReference();
                String type = stringReference.getString();
                //                    if (!basicType.contains(type) && !type.startsWith("[Ljava/lang")) {
                //                        type = DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(type)).className);
                //                    }
                ImmutableStringReference immutableStringReference = new ImmutableStringReference(type);
                if (instruction instanceof Instruction3rc) {
                    reinstructions.add(new ImmutableInstruction3rc(instruction.getOpcode(), ((Instruction3rc) instruction).getStartRegister(), ((Instruction3rc) instruction).getRegisterCount(), immutableStringReference));
                } else if (instruction instanceof Instruction20bc) {
                    reinstructions.add(new ImmutableInstruction20bc(instruction.getOpcode(), ((Instruction20bc) instruction).getVerificationError(), immutableStringReference));
                } else if (instruction instanceof Instruction21c) {
                    reinstructions.add(new ImmutableInstruction21c(instruction.getOpcode(), ((Instruction21c) instruction).getRegisterA(), immutableStringReference));
                } else if (instruction instanceof Instruction22c) {
                    reinstructions.add(new ImmutableInstruction22c(instruction.getOpcode(), ((Instruction22c) instruction).getRegisterA(), ((Instruction22c) instruction).getRegisterB(), immutableStringReference));
                } else if (instruction instanceof Instruction31c) {
                    reinstructions.add(new ImmutableInstruction31c(instruction.getOpcode(), ((Instruction31c) instruction).getRegisterA(), immutableStringReference));
                } else if (instruction instanceof Instruction35c) {
                    reinstructions.add(new ImmutableInstruction35c(instruction.getOpcode(), ((Instruction35c) instruction).getRegisterCount(), ((Instruction35c) instruction).getRegisterC(), ((Instruction35c) instruction).getRegisterD(), ((Instruction35c) instruction).getRegisterE(), ((Instruction35c) instruction).getRegisterF(), ((Instruction35c) instruction).getRegisterG(), immutableStringReference));
                }
            } else {
                reinstructions.add(ImmutableInstruction.of(instruction));
            }
        } else {
            reinstructions.add(ImmutableInstruction.of(instruction));
        }
    }
    return new Iterable<Instruction>() {

        @Override
        public Iterator<Instruction> iterator() {
            return reinstructions.iterator();
        }
    };
}
Also used : ImmutableInstruction31c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction31c) Instruction31c(org.jf.dexlib2.iface.instruction.formats.Instruction31c) ImmutableInstruction21c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction21c) Instruction21c(org.jf.dexlib2.iface.instruction.formats.Instruction21c) Instruction35c(org.jf.dexlib2.iface.instruction.formats.Instruction35c) ImmutableInstruction35c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction35c) ArrayList(java.util.ArrayList) ImmutableFieldReference(org.jf.dexlib2.immutable.reference.ImmutableFieldReference) ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) Opcode(org.jf.dexlib2.Opcode) ImmutableInstruction(org.jf.dexlib2.immutable.instruction.ImmutableInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) ImmutableInstruction35c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction35c) ImmutableInstruction21c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction21c) ImmutableInstruction31c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction31c) TypeReference(org.jf.dexlib2.iface.reference.TypeReference) ImmutableTypeReference(org.jf.dexlib2.immutable.reference.ImmutableTypeReference) ImmutableTypeReference(org.jf.dexlib2.immutable.reference.ImmutableTypeReference) Instruction3rc(org.jf.dexlib2.iface.instruction.formats.Instruction3rc) ImmutableInstruction3rc(org.jf.dexlib2.immutable.instruction.ImmutableInstruction3rc) Instruction22c(org.jf.dexlib2.iface.instruction.formats.Instruction22c) ImmutableInstruction22c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction22c) FieldReference(org.jf.dexlib2.iface.reference.FieldReference) ImmutableFieldReference(org.jf.dexlib2.immutable.reference.ImmutableFieldReference) ImmutableMethodReference(org.jf.dexlib2.immutable.reference.ImmutableMethodReference) ImmutableStringReference(org.jf.dexlib2.immutable.reference.ImmutableStringReference) ImmutableStringReference(org.jf.dexlib2.immutable.reference.ImmutableStringReference) StringReference(org.jf.dexlib2.iface.reference.StringReference) ImmutableInstruction20bc(org.jf.dexlib2.immutable.instruction.ImmutableInstruction20bc) ImmutableInstruction20bc(org.jf.dexlib2.immutable.instruction.ImmutableInstruction20bc) Instruction20bc(org.jf.dexlib2.iface.instruction.formats.Instruction20bc) ImmutableInstruction22c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction22c) ImmutableInstruction3rc(org.jf.dexlib2.immutable.instruction.ImmutableInstruction3rc) ImmutableMethodReference(org.jf.dexlib2.immutable.reference.ImmutableMethodReference) MethodReference(org.jf.dexlib2.iface.reference.MethodReference)

Example 2 with Instruction3rc

use of org.jf.dexlib2.iface.instruction.formats.Instruction3rc in project smali by JesusFreke.

the class CodeItem method makeAnnotator.

@Nonnull
public static SectionAnnotator makeAnnotator(@Nonnull DexAnnotator annotator, @Nonnull MapItem mapItem) {
    return new SectionAnnotator(annotator, mapItem) {

        private SectionAnnotator debugInfoAnnotator = null;

        @Override
        public void annotateSection(@Nonnull AnnotatedBytes out) {
            debugInfoAnnotator = annotator.getAnnotator(ItemType.DEBUG_INFO_ITEM);
            super.annotateSection(out);
        }

        @Nonnull
        @Override
        public String getItemName() {
            return "code_item";
        }

        @Override
        public int getItemAlignment() {
            return 4;
        }

        @Override
        public void annotateItem(@Nonnull AnnotatedBytes out, int itemIndex, @Nullable String itemIdentity) {
            try {
                DexReader reader = dexFile.readerAt(out.getCursor());
                int registers = reader.readUshort();
                out.annotate(2, "registers_size = %d", registers);
                int inSize = reader.readUshort();
                out.annotate(2, "ins_size = %d", inSize);
                int outSize = reader.readUshort();
                out.annotate(2, "outs_size = %d", outSize);
                int triesCount = reader.readUshort();
                out.annotate(2, "tries_size = %d", triesCount);
                int debugInfoOffset = reader.readInt();
                out.annotate(4, "debug_info_off = 0x%x", debugInfoOffset);
                if (debugInfoOffset > 0) {
                    addDebugInfoIdentity(debugInfoOffset, itemIdentity);
                }
                int instructionSize = reader.readSmallUint();
                out.annotate(4, "insns_size = 0x%x", instructionSize);
                out.annotate(0, "instructions:");
                out.indent();
                out.setLimit(out.getCursor(), out.getCursor() + instructionSize * 2);
                int end = reader.getOffset() + instructionSize * 2;
                try {
                    while (reader.getOffset() < end) {
                        Instruction instruction = DexBackedInstruction.readFrom(reader);
                        // if we read past the end of the instruction list
                        if (reader.getOffset() > end) {
                            out.annotateTo(end, "truncated instruction");
                            reader.setOffset(end);
                        } else {
                            switch(instruction.getOpcode().format) {
                                case Format10x:
                                    annotateInstruction10x(out, instruction);
                                    break;
                                case Format35c:
                                    annotateInstruction35c(out, (Instruction35c) instruction);
                                    break;
                                case Format3rc:
                                    annotateInstruction3rc(out, (Instruction3rc) instruction);
                                    break;
                                case ArrayPayload:
                                    annotateArrayPayload(out, (ArrayPayload) instruction);
                                    break;
                                case PackedSwitchPayload:
                                    annotatePackedSwitchPayload(out, (PackedSwitchPayload) instruction);
                                    break;
                                case SparseSwitchPayload:
                                    annotateSparseSwitchPayload(out, (SparseSwitchPayload) instruction);
                                    break;
                                default:
                                    annotateDefaultInstruction(out, instruction);
                                    break;
                            }
                        }
                        assert reader.getOffset() == out.getCursor();
                    }
                } catch (ExceptionWithContext ex) {
                    ex.printStackTrace(System.err);
                    out.annotate(0, "annotation error: %s", ex.getMessage());
                    out.moveTo(end);
                    reader.setOffset(end);
                } finally {
                    out.clearLimit();
                    out.deindent();
                }
                if (triesCount > 0) {
                    if ((reader.getOffset() % 4) != 0) {
                        reader.readUshort();
                        out.annotate(2, "padding");
                    }
                    out.annotate(0, "try_items:");
                    out.indent();
                    try {
                        for (int i = 0; i < triesCount; i++) {
                            out.annotate(0, "try_item[%d]:", i);
                            out.indent();
                            try {
                                int startAddr = reader.readSmallUint();
                                out.annotate(4, "start_addr = 0x%x", startAddr);
                                int instructionCount = reader.readUshort();
                                out.annotate(2, "insn_count = 0x%x", instructionCount);
                                int handlerOffset = reader.readUshort();
                                out.annotate(2, "handler_off = 0x%x", handlerOffset);
                            } finally {
                                out.deindent();
                            }
                        }
                    } finally {
                        out.deindent();
                    }
                    int handlerListCount = reader.readSmallUleb128();
                    out.annotate(0, "encoded_catch_handler_list:");
                    out.annotateTo(reader.getOffset(), "size = %d", handlerListCount);
                    out.indent();
                    try {
                        for (int i = 0; i < handlerListCount; i++) {
                            out.annotate(0, "encoded_catch_handler[%d]", i);
                            out.indent();
                            try {
                                int handlerCount = reader.readSleb128();
                                out.annotateTo(reader.getOffset(), "size = %d", handlerCount);
                                boolean hasCatchAll = handlerCount <= 0;
                                handlerCount = Math.abs(handlerCount);
                                if (handlerCount != 0) {
                                    out.annotate(0, "handlers:");
                                    out.indent();
                                    try {
                                        for (int j = 0; j < handlerCount; j++) {
                                            out.annotate(0, "encoded_type_addr_pair[%d]", i);
                                            out.indent();
                                            try {
                                                int typeIndex = reader.readSmallUleb128();
                                                out.annotateTo(reader.getOffset(), TypeIdItem.getReferenceAnnotation(dexFile, typeIndex));
                                                int handlerAddress = reader.readSmallUleb128();
                                                out.annotateTo(reader.getOffset(), "addr = 0x%x", handlerAddress);
                                            } finally {
                                                out.deindent();
                                            }
                                        }
                                    } finally {
                                        out.deindent();
                                    }
                                }
                                if (hasCatchAll) {
                                    int catchAllAddress = reader.readSmallUleb128();
                                    out.annotateTo(reader.getOffset(), "catch_all_addr = 0x%x", catchAllAddress);
                                }
                            } finally {
                                out.deindent();
                            }
                        }
                    } finally {
                        out.deindent();
                    }
                }
            } catch (ExceptionWithContext ex) {
                out.annotate(0, "annotation error: %s", ex.getMessage());
            }
        }

        private String formatRegister(int registerNum) {
            return String.format("v%d", registerNum);
        }

        private void annotateInstruction10x(@Nonnull AnnotatedBytes out, @Nonnull Instruction instruction) {
            out.annotate(2, instruction.getOpcode().name);
        }

        private void annotateInstruction35c(@Nonnull AnnotatedBytes out, @Nonnull Instruction35c instruction) {
            List<String> args = Lists.newArrayList();
            int registerCount = instruction.getRegisterCount();
            if (registerCount == 1) {
                args.add(formatRegister(instruction.getRegisterC()));
            } else if (registerCount == 2) {
                args.add(formatRegister(instruction.getRegisterC()));
                args.add(formatRegister(instruction.getRegisterD()));
            } else if (registerCount == 3) {
                args.add(formatRegister(instruction.getRegisterC()));
                args.add(formatRegister(instruction.getRegisterD()));
                args.add(formatRegister(instruction.getRegisterE()));
            } else if (registerCount == 4) {
                args.add(formatRegister(instruction.getRegisterC()));
                args.add(formatRegister(instruction.getRegisterD()));
                args.add(formatRegister(instruction.getRegisterE()));
                args.add(formatRegister(instruction.getRegisterF()));
            } else if (registerCount == 5) {
                args.add(formatRegister(instruction.getRegisterC()));
                args.add(formatRegister(instruction.getRegisterD()));
                args.add(formatRegister(instruction.getRegisterE()));
                args.add(formatRegister(instruction.getRegisterF()));
                args.add(formatRegister(instruction.getRegisterG()));
            }
            String reference = ReferenceUtil.getReferenceString(instruction.getReference());
            out.annotate(6, String.format("%s {%s}, %s", instruction.getOpcode().name, Joiner.on(", ").join(args), reference));
        }

        private void annotateInstruction3rc(@Nonnull AnnotatedBytes out, @Nonnull Instruction3rc instruction) {
            int startRegister = instruction.getStartRegister();
            int endRegister = startRegister + instruction.getRegisterCount() - 1;
            String reference = ReferenceUtil.getReferenceString(instruction.getReference());
            out.annotate(6, String.format("%s {%s .. %s}, %s", instruction.getOpcode().name, formatRegister(startRegister), formatRegister(endRegister), reference));
        }

        private void annotateDefaultInstruction(@Nonnull AnnotatedBytes out, @Nonnull Instruction instruction) {
            List<String> args = Lists.newArrayList();
            if (instruction instanceof OneRegisterInstruction) {
                args.add(formatRegister(((OneRegisterInstruction) instruction).getRegisterA()));
                if (instruction instanceof TwoRegisterInstruction) {
                    args.add(formatRegister(((TwoRegisterInstruction) instruction).getRegisterB()));
                    if (instruction instanceof ThreeRegisterInstruction) {
                        args.add(formatRegister(((ThreeRegisterInstruction) instruction).getRegisterC()));
                    }
                }
            } else if (instruction instanceof VerificationErrorInstruction) {
                String verificationError = VerificationError.getVerificationErrorName(((VerificationErrorInstruction) instruction).getVerificationError());
                if (verificationError != null) {
                    args.add(verificationError);
                } else {
                    args.add("invalid verification error type");
                }
            }
            if (instruction instanceof ReferenceInstruction) {
                args.add(ReferenceUtil.getReferenceString(((ReferenceInstruction) instruction).getReference()));
            } else if (instruction instanceof OffsetInstruction) {
                int offset = ((OffsetInstruction) instruction).getCodeOffset();
                String sign = offset >= 0 ? "+" : "-";
                args.add(String.format("%s0x%x", sign, Math.abs(offset)));
            } else if (instruction instanceof NarrowLiteralInstruction) {
                int value = ((NarrowLiteralInstruction) instruction).getNarrowLiteral();
                if (NumberUtils.isLikelyFloat(value)) {
                    args.add(String.format("%d # %f", value, Float.intBitsToFloat(value)));
                } else {
                    args.add(String.format("%d", value));
                }
            } else if (instruction instanceof WideLiteralInstruction) {
                long value = ((WideLiteralInstruction) instruction).getWideLiteral();
                if (NumberUtils.isLikelyDouble(value)) {
                    args.add(String.format("%d # %f", value, Double.longBitsToDouble(value)));
                } else {
                    args.add(String.format("%d", value));
                }
            } else if (instruction instanceof FieldOffsetInstruction) {
                int fieldOffset = ((FieldOffsetInstruction) instruction).getFieldOffset();
                args.add(String.format("field@0x%x", fieldOffset));
            } else if (instruction instanceof VtableIndexInstruction) {
                int vtableIndex = ((VtableIndexInstruction) instruction).getVtableIndex();
                args.add(String.format("vtable@%d", vtableIndex));
            } else if (instruction instanceof InlineIndexInstruction) {
                int inlineIndex = ((InlineIndexInstruction) instruction).getInlineIndex();
                args.add(String.format("inline@%d", inlineIndex));
            }
            out.annotate(instruction.getCodeUnits() * 2, "%s %s", instruction.getOpcode().name, Joiner.on(", ").join(args));
        }

        private void annotateArrayPayload(@Nonnull AnnotatedBytes out, @Nonnull ArrayPayload instruction) {
            List<Number> elements = instruction.getArrayElements();
            int elementWidth = instruction.getElementWidth();
            out.annotate(2, instruction.getOpcode().name);
            out.indent();
            out.annotate(2, "element_width = %d", elementWidth);
            out.annotate(4, "size = %d", elements.size());
            out.annotate(0, "elements:");
            out.indent();
            for (int i = 0; i < elements.size(); i++) {
                if (elementWidth == 8) {
                    long value = elements.get(i).longValue();
                    if (NumberUtils.isLikelyDouble(value)) {
                        out.annotate(elementWidth, "element[%d] = %d # %f", i, value, Double.longBitsToDouble(value));
                    } else {
                        out.annotate(elementWidth, "element[%d] = %d", i, value);
                    }
                } else {
                    int value = elements.get(i).intValue();
                    if (NumberUtils.isLikelyFloat(value)) {
                        out.annotate(elementWidth, "element[%d] = %d # %f", i, value, Float.intBitsToFloat(value));
                    } else {
                        out.annotate(elementWidth, "element[%d] = %d", i, value);
                    }
                }
            }
            if (out.getCursor() % 2 != 0) {
                out.annotate(1, "padding");
            }
            out.deindent();
            out.deindent();
        }

        private void annotatePackedSwitchPayload(@Nonnull AnnotatedBytes out, @Nonnull PackedSwitchPayload instruction) {
            List<? extends SwitchElement> elements = instruction.getSwitchElements();
            out.annotate(2, instruction.getOpcode().name);
            out.indent();
            out.annotate(2, "size = %d", elements.size());
            if (elements.size() == 0) {
                out.annotate(4, "first_key");
            } else {
                out.annotate(4, "first_key = %d", elements.get(0).getKey());
                out.annotate(0, "targets:");
                out.indent();
                for (int i = 0; i < elements.size(); i++) {
                    out.annotate(4, "target[%d] = %d", i, elements.get(i).getOffset());
                }
                out.deindent();
            }
            out.deindent();
        }

        private void annotateSparseSwitchPayload(@Nonnull AnnotatedBytes out, @Nonnull SparseSwitchPayload instruction) {
            List<? extends SwitchElement> elements = instruction.getSwitchElements();
            out.annotate(2, instruction.getOpcode().name);
            out.indent();
            out.annotate(2, "size = %d", elements.size());
            if (elements.size() > 0) {
                out.annotate(0, "keys:");
                out.indent();
                for (int i = 0; i < elements.size(); i++) {
                    out.annotate(4, "key[%d] = %d", i, elements.get(i).getKey());
                }
                out.deindent();
                out.annotate(0, "targets:");
                out.indent();
                for (int i = 0; i < elements.size(); i++) {
                    out.annotate(4, "target[%d] = %d", i, elements.get(i).getOffset());
                }
                out.deindent();
            }
            out.deindent();
        }

        private void addDebugInfoIdentity(int debugInfoOffset, String methodString) {
            if (debugInfoAnnotator != null) {
                debugInfoAnnotator.setItemIdentity(debugInfoOffset, methodString);
            }
        }
    };
}
Also used : DexReader(org.jf.dexlib2.dexbacked.DexReader) DexBackedInstruction(org.jf.dexlib2.dexbacked.instruction.DexBackedInstruction) ExceptionWithContext(org.jf.util.ExceptionWithContext) Nonnull(javax.annotation.Nonnull) AnnotatedBytes(org.jf.dexlib2.util.AnnotatedBytes) Nullable(javax.annotation.Nullable) Nonnull(javax.annotation.Nonnull)

Example 3 with Instruction3rc

use of org.jf.dexlib2.iface.instruction.formats.Instruction3rc in project smali by JesusFreke.

the class MethodAnalyzer method analyzeExecuteInlineRange.

private void analyzeExecuteInlineRange(@Nonnull AnalyzedInstruction analyzedInstruction) {
    if (inlineResolver == null) {
        throw new AnalysisException("Cannot analyze an odexed instruction unless we are deodexing");
    }
    Instruction3rmi instruction = (Instruction3rmi) analyzedInstruction.instruction;
    Method resolvedMethod = inlineResolver.resolveExecuteInline(analyzedInstruction);
    Opcode deodexedOpcode;
    int acccessFlags = resolvedMethod.getAccessFlags();
    if (AccessFlags.STATIC.isSet(acccessFlags)) {
        deodexedOpcode = Opcode.INVOKE_STATIC_RANGE;
    } else if (AccessFlags.PRIVATE.isSet(acccessFlags)) {
        deodexedOpcode = Opcode.INVOKE_DIRECT_RANGE;
    } else {
        deodexedOpcode = Opcode.INVOKE_VIRTUAL_RANGE;
    }
    Instruction3rc deodexedInstruction = new ImmutableInstruction3rc(deodexedOpcode, instruction.getStartRegister(), instruction.getRegisterCount(), resolvedMethod);
    analyzedInstruction.setDeodexedInstruction(deodexedInstruction);
    analyzeInstruction(analyzedInstruction);
}
Also used : Opcode(org.jf.dexlib2.Opcode)

Example 4 with Instruction3rc

use of org.jf.dexlib2.iface.instruction.formats.Instruction3rc in project smali by JesusFreke.

the class MethodAnalyzer method analyzeInvokeVirtual.

private boolean analyzeInvokeVirtual(@Nonnull AnalyzedInstruction analyzedInstruction, boolean isRange) {
    MethodReference targetMethod;
    if (!normalizeVirtualMethods) {
        return true;
    }
    if (isRange) {
        Instruction3rc instruction = (Instruction3rc) analyzedInstruction.instruction;
        targetMethod = (MethodReference) instruction.getReference();
    } else {
        Instruction35c instruction = (Instruction35c) analyzedInstruction.instruction;
        targetMethod = (MethodReference) instruction.getReference();
    }
    MethodReference replacementMethod = normalizeMethodReference(targetMethod);
    if (replacementMethod == null || replacementMethod.equals(targetMethod)) {
        return true;
    }
    Instruction deodexedInstruction;
    if (isRange) {
        Instruction3rc instruction = (Instruction3rc) analyzedInstruction.instruction;
        deodexedInstruction = new ImmutableInstruction3rc(instruction.getOpcode(), instruction.getStartRegister(), instruction.getRegisterCount(), replacementMethod);
    } else {
        Instruction35c instruction = (Instruction35c) analyzedInstruction.instruction;
        deodexedInstruction = new ImmutableInstruction35c(instruction.getOpcode(), instruction.getRegisterCount(), instruction.getRegisterC(), instruction.getRegisterD(), instruction.getRegisterE(), instruction.getRegisterF(), instruction.getRegisterG(), replacementMethod);
    }
    analyzedInstruction.setDeodexedInstruction(deodexedInstruction);
    return true;
}
Also used : BaseMethodReference(org.jf.dexlib2.base.reference.BaseMethodReference) ImmutableMethodReference(org.jf.dexlib2.immutable.reference.ImmutableMethodReference) MethodReference(org.jf.dexlib2.iface.reference.MethodReference)

Example 5 with Instruction3rc

use of org.jf.dexlib2.iface.instruction.formats.Instruction3rc in project smali by JesusFreke.

the class DexWriter method writeCodeItem.

private int writeCodeItem(@Nonnull DexDataWriter writer, @Nonnull ByteArrayOutputStream ehBuf, @Nonnull MethodKey methodKey, @Nonnull List<? extends TryBlock<? extends ExceptionHandler>> tryBlocks, @Nullable Iterable<? extends Instruction> instructions, int debugItemOffset) throws IOException {
    if (instructions == null && debugItemOffset == NO_OFFSET) {
        return -1;
    }
    numCodeItemItems++;
    writer.align();
    int codeItemOffset = writer.getPosition();
    writer.writeUshort(classSection.getRegisterCount(methodKey));
    boolean isStatic = AccessFlags.STATIC.isSet(classSection.getMethodAccessFlags(methodKey));
    Collection<? extends TypeKey> parameters = typeListSection.getTypes(protoSection.getParameters(methodSection.getPrototype(methodKey)));
    writer.writeUshort(MethodUtil.getParameterRegisterCount(parameters, isStatic));
    if (instructions != null) {
        tryBlocks = TryListBuilder.massageTryBlocks(tryBlocks);
        int outParamCount = 0;
        int codeUnitCount = 0;
        for (Instruction instruction : instructions) {
            codeUnitCount += instruction.getCodeUnits();
            if (instruction.getOpcode().referenceType == ReferenceType.METHOD) {
                ReferenceInstruction refInsn = (ReferenceInstruction) instruction;
                MethodReference methodRef = (MethodReference) refInsn.getReference();
                int paramCount = MethodUtil.getParameterRegisterCount(methodRef, InstructionUtil.isInvokeStatic(instruction.getOpcode()));
                if (paramCount > outParamCount) {
                    outParamCount = paramCount;
                }
            }
        }
        writer.writeUshort(outParamCount);
        writer.writeUshort(tryBlocks.size());
        writer.writeInt(debugItemOffset);
        InstructionWriter instructionWriter = InstructionWriter.makeInstructionWriter(opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection);
        writer.writeInt(codeUnitCount);
        int codeOffset = 0;
        for (Instruction instruction : instructions) {
            try {
                switch(instruction.getOpcode().format) {
                    case Format10t:
                        instructionWriter.write((Instruction10t) instruction);
                        break;
                    case Format10x:
                        instructionWriter.write((Instruction10x) instruction);
                        break;
                    case Format11n:
                        instructionWriter.write((Instruction11n) instruction);
                        break;
                    case Format11x:
                        instructionWriter.write((Instruction11x) instruction);
                        break;
                    case Format12x:
                        instructionWriter.write((Instruction12x) instruction);
                        break;
                    case Format20bc:
                        instructionWriter.write((Instruction20bc) instruction);
                        break;
                    case Format20t:
                        instructionWriter.write((Instruction20t) instruction);
                        break;
                    case Format21c:
                        instructionWriter.write((Instruction21c) instruction);
                        break;
                    case Format21ih:
                        instructionWriter.write((Instruction21ih) instruction);
                        break;
                    case Format21lh:
                        instructionWriter.write((Instruction21lh) instruction);
                        break;
                    case Format21s:
                        instructionWriter.write((Instruction21s) instruction);
                        break;
                    case Format21t:
                        instructionWriter.write((Instruction21t) instruction);
                        break;
                    case Format22b:
                        instructionWriter.write((Instruction22b) instruction);
                        break;
                    case Format22c:
                        instructionWriter.write((Instruction22c) instruction);
                        break;
                    case Format22s:
                        instructionWriter.write((Instruction22s) instruction);
                        break;
                    case Format22t:
                        instructionWriter.write((Instruction22t) instruction);
                        break;
                    case Format22x:
                        instructionWriter.write((Instruction22x) instruction);
                        break;
                    case Format23x:
                        instructionWriter.write((Instruction23x) instruction);
                        break;
                    case Format30t:
                        instructionWriter.write((Instruction30t) instruction);
                        break;
                    case Format31c:
                        instructionWriter.write((Instruction31c) instruction);
                        break;
                    case Format31i:
                        instructionWriter.write((Instruction31i) instruction);
                        break;
                    case Format31t:
                        instructionWriter.write((Instruction31t) instruction);
                        break;
                    case Format32x:
                        instructionWriter.write((Instruction32x) instruction);
                        break;
                    case Format35c:
                        instructionWriter.write((Instruction35c) instruction);
                        break;
                    case Format3rc:
                        instructionWriter.write((Instruction3rc) instruction);
                        break;
                    case Format45cc:
                        instructionWriter.write((Instruction45cc) instruction);
                        break;
                    case Format4rcc:
                        instructionWriter.write((Instruction4rcc) instruction);
                        break;
                    case Format51l:
                        instructionWriter.write((Instruction51l) instruction);
                        break;
                    case ArrayPayload:
                        instructionWriter.write((ArrayPayload) instruction);
                        break;
                    case PackedSwitchPayload:
                        instructionWriter.write((PackedSwitchPayload) instruction);
                        break;
                    case SparseSwitchPayload:
                        instructionWriter.write((SparseSwitchPayload) instruction);
                        break;
                    default:
                        throw new ExceptionWithContext("Unsupported instruction format: %s", instruction.getOpcode().format);
                }
            } catch (RuntimeException ex) {
                throw new ExceptionWithContext(ex, "Error while writing instruction at code offset 0x%x", codeOffset);
            }
            codeOffset += instruction.getCodeUnits();
        }
        if (tryBlocks.size() > 0) {
            writer.align();
            // filter out unique lists of exception handlers
            Map<List<? extends ExceptionHandler>, Integer> exceptionHandlerOffsetMap = Maps.newHashMap();
            for (TryBlock<? extends ExceptionHandler> tryBlock : tryBlocks) {
                exceptionHandlerOffsetMap.put(tryBlock.getExceptionHandlers(), 0);
            }
            DexDataWriter.writeUleb128(ehBuf, exceptionHandlerOffsetMap.size());
            for (TryBlock<? extends ExceptionHandler> tryBlock : tryBlocks) {
                int startAddress = tryBlock.getStartCodeAddress();
                int endAddress = startAddress + tryBlock.getCodeUnitCount();
                int tbCodeUnitCount = endAddress - startAddress;
                writer.writeInt(startAddress);
                writer.writeUshort(tbCodeUnitCount);
                if (tryBlock.getExceptionHandlers().size() == 0) {
                    throw new ExceptionWithContext("No exception handlers for the try block!");
                }
                Integer offset = exceptionHandlerOffsetMap.get(tryBlock.getExceptionHandlers());
                if (offset != 0) {
                    // exception handler has already been written out, just use it
                    writer.writeUshort(offset);
                } else {
                    // if offset has not been set yet, we are about to write out a new exception handler
                    offset = ehBuf.size();
                    writer.writeUshort(offset);
                    exceptionHandlerOffsetMap.put(tryBlock.getExceptionHandlers(), offset);
                    // check if the last exception handler is a catch-all and adjust the size accordingly
                    int ehSize = tryBlock.getExceptionHandlers().size();
                    ExceptionHandler ehLast = tryBlock.getExceptionHandlers().get(ehSize - 1);
                    if (ehLast.getExceptionType() == null) {
                        ehSize = ehSize * (-1) + 1;
                    }
                    // now let's layout the exception handlers, assuming that catch-all is always last
                    DexDataWriter.writeSleb128(ehBuf, ehSize);
                    for (ExceptionHandler eh : tryBlock.getExceptionHandlers()) {
                        TypeKey exceptionTypeKey = classSection.getExceptionType(eh);
                        int codeAddress = eh.getHandlerCodeAddress();
                        if (exceptionTypeKey != null) {
                            //regular exception handling
                            DexDataWriter.writeUleb128(ehBuf, typeSection.getItemIndex(exceptionTypeKey));
                            DexDataWriter.writeUleb128(ehBuf, codeAddress);
                        } else {
                            //catch-all
                            DexDataWriter.writeUleb128(ehBuf, codeAddress);
                        }
                    }
                }
            }
            if (ehBuf.size() > 0) {
                ehBuf.writeTo(writer);
                ehBuf.reset();
            }
        }
    } else {
        // no instructions, all we have is the debug item offset
        writer.writeUshort(0);
        writer.writeUshort(0);
        writer.writeInt(debugItemOffset);
        writer.writeInt(0);
    }
    return codeItemOffset;
}
Also used : ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) OneRegisterInstruction(org.jf.dexlib2.iface.instruction.OneRegisterInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) ExceptionHandler(org.jf.dexlib2.iface.ExceptionHandler) ExceptionWithContext(org.jf.util.ExceptionWithContext)

Aggregations

Opcode (org.jf.dexlib2.Opcode)2 Instruction (org.jf.dexlib2.iface.instruction.Instruction)2 ReferenceInstruction (org.jf.dexlib2.iface.instruction.ReferenceInstruction)2 MethodReference (org.jf.dexlib2.iface.reference.MethodReference)2 StringReference (org.jf.dexlib2.iface.reference.StringReference)2 ImmutableMethodReference (org.jf.dexlib2.immutable.reference.ImmutableMethodReference)2 ExceptionWithContext (org.jf.util.ExceptionWithContext)2 ArrayList (java.util.ArrayList)1 Nonnull (javax.annotation.Nonnull)1 Nullable (javax.annotation.Nullable)1 BaseMethodReference (org.jf.dexlib2.base.reference.BaseMethodReference)1 DexReader (org.jf.dexlib2.dexbacked.DexReader)1 DexBackedInstruction (org.jf.dexlib2.dexbacked.instruction.DexBackedInstruction)1 ExceptionHandler (org.jf.dexlib2.iface.ExceptionHandler)1 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)1 OneRegisterInstruction (org.jf.dexlib2.iface.instruction.OneRegisterInstruction)1 Instruction20bc (org.jf.dexlib2.iface.instruction.formats.Instruction20bc)1 Instruction21c (org.jf.dexlib2.iface.instruction.formats.Instruction21c)1 Instruction22c (org.jf.dexlib2.iface.instruction.formats.Instruction22c)1 Instruction31c (org.jf.dexlib2.iface.instruction.formats.Instruction31c)1