Search in sources :

Example 1 with Instruction21c

use of org.jf.dexlib2.iface.instruction.formats.Instruction21c 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 Instruction21c

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

the class ImplicitReferenceTest method testImplicitFieldReference.

@Test
public void testImplicitFieldReference() throws RecognitionException, IOException {
    ClassDef classDef = SmaliTestUtils.compileSmali("" + ".class public LHelloWorld;\n" + ".super Ljava/lang/Object;\n" + ".method public static main([Ljava/lang/String;)V\n" + "    .registers 1\n" + "    sget-object v0, someField:I\n" + "    sget-object v0, V:I\n" + "    sget-object v0, I:I\n" + "    return-void\n" + ".end method");
    Method mainMethod = null;
    for (Method method : classDef.getMethods()) {
        if (method.getName().equals("main")) {
            mainMethod = method;
        }
    }
    Assert.assertNotNull(mainMethod);
    MethodImplementation methodImpl = mainMethod.getImplementation();
    Assert.assertNotNull(methodImpl);
    List<Instruction> instructions = Lists.newArrayList(methodImpl.getInstructions());
    Instruction21c instruction = (Instruction21c) instructions.get(0);
    Assert.assertNotNull(instruction);
    Assert.assertEquals(Opcode.SGET_OBJECT, instruction.getOpcode());
    FieldReference field = (FieldReference) instruction.getReference();
    Assert.assertEquals(classDef.getType(), field.getDefiningClass());
    Assert.assertEquals("someField", field.getName());
    instruction = (Instruction21c) instructions.get(1);
    Assert.assertNotNull(instruction);
    Assert.assertEquals(Opcode.SGET_OBJECT, instruction.getOpcode());
    field = (FieldReference) instruction.getReference();
    Assert.assertEquals(classDef.getType(), field.getDefiningClass());
    Assert.assertEquals("V", field.getName());
    instruction = (Instruction21c) instructions.get(2);
    Assert.assertNotNull(instruction);
    Assert.assertEquals(Opcode.SGET_OBJECT, instruction.getOpcode());
    field = (FieldReference) instruction.getReference();
    Assert.assertEquals(classDef.getType(), field.getDefiningClass());
    Assert.assertEquals("I", field.getName());
}
Also used : MethodImplementation(org.jf.dexlib2.iface.MethodImplementation) Instruction21c(org.jf.dexlib2.iface.instruction.formats.Instruction21c) ClassDef(org.jf.dexlib2.iface.ClassDef) FieldReference(org.jf.dexlib2.iface.reference.FieldReference) Method(org.jf.dexlib2.iface.Method) Instruction(org.jf.dexlib2.iface.instruction.Instruction) Test(org.junit.Test)

Example 3 with Instruction21c

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

the class JumboStringConversionTest method testJumboStringConversion_NonMethodBuilder.

@Test
public void testJumboStringConversion_NonMethodBuilder() throws IOException {
    DexBuilder dexBuilder = new DexBuilder(Opcodes.getDefault());
    final List<Instruction> instructions = Lists.newArrayList();
    for (int i = 0; i < 66000; i++) {
        final StringReference ref = dexBuilder.internStringReference(String.format("%08d", i));
        instructions.add(new Instruction21c() {

            @Override
            public int getRegisterA() {
                return 0;
            }

            @Nonnull
            @Override
            public Reference getReference() {
                return ref;
            }

            @Override
            public int getReferenceType() {
                return ReferenceType.STRING;
            }

            @Override
            public Opcode getOpcode() {
                return Opcode.CONST_STRING;
            }

            @Override
            public int getCodeUnits() {
                return getOpcode().format.size / 2;
            }
        });
    }
    instructions.add(new ImmutableInstruction10x(Opcode.RETURN_VOID));
    MethodImplementation methodImpl = new MethodImplementation() {

        @Override
        public int getRegisterCount() {
            return 1;
        }

        @Nonnull
        @Override
        public Iterable<? extends Instruction> getInstructions() {
            return instructions;
        }

        @Nonnull
        @Override
        public List<? extends TryBlock<? extends ExceptionHandler>> getTryBlocks() {
            return ImmutableList.of();
        }

        @Nonnull
        @Override
        public Iterable<? extends DebugItem> getDebugItems() {
            return ImmutableList.of();
        }
    };
    dexBuilder.internClassDef("Ltest;", 0, "Ljava/lang/Object;", null, null, ImmutableSet.<Annotation>of(), null, ImmutableList.of(dexBuilder.internMethod("Ltest;", "test", null, "V", 0, ImmutableSet.<Annotation>of(), methodImpl)));
    MemoryDataStore dexStore = new MemoryDataStore();
    dexBuilder.writeTo(dexStore);
    DexBackedDexFile dexFile = new DexBackedDexFile(Opcodes.getDefault(), dexStore.getData());
    ClassDef classDef = Iterables.getFirst(dexFile.getClasses(), null);
    Assert.assertNotNull(classDef);
    Method method = Iterables.getFirst(classDef.getMethods(), null);
    Assert.assertNotNull(method);
    MethodImplementation impl = method.getImplementation();
    Assert.assertNotNull(impl);
    List<? extends Instruction> actualInstructions = Lists.newArrayList(impl.getInstructions());
    Assert.assertEquals(66001, actualInstructions.size());
    for (int i = 0; i < 65536; i++) {
        Assert.assertEquals(Opcode.CONST_STRING, actualInstructions.get(i).getOpcode());
        Assert.assertEquals(String.format("%08d", i), ((StringReference) ((ReferenceInstruction) actualInstructions.get(i)).getReference()).getString());
    }
    for (int i = 65536; i < 66000; i++) {
        Assert.assertEquals(Opcode.CONST_STRING_JUMBO, actualInstructions.get(i).getOpcode());
        Assert.assertEquals(String.format("%08d", i), ((StringReference) ((ReferenceInstruction) actualInstructions.get(i)).getReference()).getString());
    }
    Assert.assertEquals(Opcode.RETURN_VOID, actualInstructions.get(66000).getOpcode());
}
Also used : BuilderInstruction21c(org.jf.dexlib2.builder.instruction.BuilderInstruction21c) Instruction21c(org.jf.dexlib2.iface.instruction.formats.Instruction21c) DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) Nonnull(javax.annotation.Nonnull) Reference(org.jf.dexlib2.iface.reference.Reference) StringReference(org.jf.dexlib2.iface.reference.StringReference) MemoryDataStore(org.jf.dexlib2.writer.io.MemoryDataStore) Opcode(org.jf.dexlib2.Opcode) ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) StringReference(org.jf.dexlib2.iface.reference.StringReference) ImmutableInstruction10x(org.jf.dexlib2.immutable.instruction.ImmutableInstruction10x) DexBuilder(org.jf.dexlib2.writer.builder.DexBuilder) Test(org.junit.Test)

Example 4 with Instruction21c

use of org.jf.dexlib2.iface.instruction.formats.Instruction21c 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)

Example 5 with Instruction21c

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

the class SmalideaMethodTest method testSmalideaMethod.

public void testSmalideaMethod() {
    String text = ".class public Lmy/pkg/blah; .super Ljava/lang/Object;\n" + ".method public someMethodName(I)I\n" + "    .registers 4\n" + "    .param p1, \"edge\"    # I\n" + "    goto :here  #0: 10t\n" + "    :here\n" + "    return-void  #1: 21c\n" + "    const/4 v0, 1234 #2: 11n\n" + "    monitor-enter v1, #3: 11x\n" + "    move v1, v0 #4: 12x\n" + "    goto/16 :here #5: 20t\n" + "    sget v0, La/b/c;->blah:I #6: 21c\n" + "    const/high16 v0, 0x12340000 #7: 21ih\n" + "    const-wide/high16 v0, 0x1234000000000000L #8: 21lh\n" + "    const-wide/16 v0, 1234 #9: 21s\n" + "    if-eqz v0, :here #10: 21t\n" + "    add-int/lit8 v0, v1, 123 #11: 22b\n" + "    iget v1, v2, Labc;->blort:Z #12: 22c\n" + "    add-int/lit16 v0, v1, 1234 #13: 22s\n" + "    if-eq v0, v1, :here #14: 22t\n" + "    move/from16 v0, v1 #15: 22x\n" + "    cmpl-float v0, v1, v2 #16: 23x\n" + "    goto/32 :here #17: 30t\n" + "    const-string/jumbo v0, \"abcd\" #18: 31c\n" + "    const v0, 1234 #19: 31i\n" + "    move/16 v0, v1 #20: 32x\n" + "    invoke-virtual {v0, v1, v2, v3, v4}, Lblah;->blort(IIII)I #21: 35c\n" + "    invoke-virtual/range {v0..v4}, Lblah;->blort(IIII)I #22: 3rc\n" + "    const-wide v0, 0x1234567890L #23: 51i\n" + ".end method";
    SmaliFile file = (SmaliFile) myFixture.addFileToProject("my/pkg/blah.smali", text);
    SmaliClass smaliClass = file.getPsiClass();
    SmaliMethod smaliMethod = smaliClass.getMethods()[0];
    SmalideaMethod method = new SmalideaMethod(smaliMethod);
    Assert.assertEquals("Lmy/pkg/blah;", method.getDefiningClass());
    Assert.assertEquals("someMethodName", method.getName());
    Assert.assertEquals("I", method.getReturnType());
    List<? extends CharSequence> parameterTypes = method.getParameterTypes();
    Assert.assertEquals(1, parameterTypes.size());
    Assert.assertEquals("I", parameterTypes.get(0));
    List<? extends MethodParameter> parameters = method.getParameters();
    Assert.assertEquals(1, parameters.size());
    Assert.assertEquals("I", parameters.get(0).getType());
    Assert.assertEquals("edge", parameters.get(0).getName());
    Assert.assertEquals(AccessFlags.PUBLIC.getValue(), method.getAccessFlags());
    MethodImplementation impl = method.getImplementation();
    Assert.assertNotNull(impl);
    Assert.assertEquals(4, impl.getRegisterCount());
    List<? extends Instruction> instructions = Lists.newArrayList(impl.getInstructions());
    {
        Instruction10t instruction = (Instruction10t) instructions.get(0);
        Assert.assertEquals(Opcode.GOTO, instruction.getOpcode());
        Assert.assertEquals(1, instruction.getCodeOffset());
    }
    {
        Instruction10x instruction = (Instruction10x) instructions.get(1);
        Assert.assertEquals(Opcode.RETURN_VOID, instruction.getOpcode());
    }
    {
        Instruction11n instruction = (Instruction11n) instructions.get(2);
        Assert.assertEquals(Opcode.CONST_4, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals(1234, instruction.getNarrowLiteral());
    }
    {
        Instruction11x instruction = (Instruction11x) instructions.get(3);
        Assert.assertEquals(Opcode.MONITOR_ENTER, instruction.getOpcode());
        Assert.assertEquals(1, instruction.getRegisterA());
    }
    {
        Instruction12x instruction = (Instruction12x) instructions.get(4);
        Assert.assertEquals(Opcode.MOVE, instruction.getOpcode());
        Assert.assertEquals(1, instruction.getRegisterA());
        Assert.assertEquals(0, instruction.getRegisterB());
    }
    {
        Instruction20t instruction = (Instruction20t) instructions.get(5);
        Assert.assertEquals(Opcode.GOTO_16, instruction.getOpcode());
        Assert.assertEquals(-4, instruction.getCodeOffset());
    }
    {
        Instruction21c instruction = (Instruction21c) instructions.get(6);
        Assert.assertEquals(Opcode.SGET, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals("La/b/c;->blah:I", ReferenceUtil.getFieldDescriptor((FieldReference) instruction.getReference()));
    }
    {
        Instruction21ih instruction = (Instruction21ih) instructions.get(7);
        Assert.assertEquals(Opcode.CONST_HIGH16, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals(0x1234, instruction.getHatLiteral());
        Assert.assertEquals(0x12340000, instruction.getNarrowLiteral());
        Assert.assertEquals(0x12340000, instruction.getWideLiteral());
    }
    {
        Instruction21lh instruction = (Instruction21lh) instructions.get(8);
        Assert.assertEquals(Opcode.CONST_WIDE_HIGH16, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals(0x1234, instruction.getHatLiteral());
        Assert.assertEquals(0x1234000000000000L, instruction.getWideLiteral());
    }
    {
        Instruction21s instruction = (Instruction21s) instructions.get(9);
        Assert.assertEquals(Opcode.CONST_WIDE_16, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals(1234, instruction.getWideLiteral());
    }
    {
        Instruction21t instruction = (Instruction21t) instructions.get(10);
        Assert.assertEquals(Opcode.IF_EQZ, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals(-14, instruction.getCodeOffset());
    }
    {
        Instruction22b instruction = (Instruction22b) instructions.get(11);
        Assert.assertEquals(Opcode.ADD_INT_LIT8, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals(1, instruction.getRegisterB());
        Assert.assertEquals(123, instruction.getNarrowLiteral());
    }
    {
        Instruction22c instruction = (Instruction22c) instructions.get(12);
        Assert.assertEquals(Opcode.IGET, instruction.getOpcode());
        Assert.assertEquals(1, instruction.getRegisterA());
        Assert.assertEquals(2, instruction.getRegisterB());
        Assert.assertEquals("Labc;->blort:Z", ReferenceUtil.getFieldDescriptor((FieldReference) instruction.getReference()));
    }
    {
        Instruction22s instruction = (Instruction22s) instructions.get(13);
        Assert.assertEquals(Opcode.ADD_INT_LIT16, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals(1, instruction.getRegisterB());
        Assert.assertEquals(1234, instruction.getNarrowLiteral());
    }
    {
        Instruction22t instruction = (Instruction22t) instructions.get(14);
        Assert.assertEquals(Opcode.IF_EQ, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals(1, instruction.getRegisterB());
        Assert.assertEquals(-22, instruction.getCodeOffset());
    }
    {
        Instruction22x instruction = (Instruction22x) instructions.get(15);
        Assert.assertEquals(Opcode.MOVE_FROM16, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals(1, instruction.getRegisterB());
    }
    {
        Instruction23x instruction = (Instruction23x) instructions.get(16);
        Assert.assertEquals(Opcode.CMPL_FLOAT, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals(1, instruction.getRegisterB());
        Assert.assertEquals(2, instruction.getRegisterC());
    }
    {
        Instruction30t instruction = (Instruction30t) instructions.get(17);
        Assert.assertEquals(Opcode.GOTO_32, instruction.getOpcode());
        Assert.assertEquals(-28, instruction.getCodeOffset());
    }
    {
        Instruction31c instruction = (Instruction31c) instructions.get(18);
        Assert.assertEquals(Opcode.CONST_STRING_JUMBO, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals("abcd", ((StringReference) instruction.getReference()).getString());
    }
    {
        Instruction31i instruction = (Instruction31i) instructions.get(19);
        Assert.assertEquals(Opcode.CONST, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals(1234, instruction.getNarrowLiteral());
    }
    {
        Instruction32x instruction = (Instruction32x) instructions.get(20);
        Assert.assertEquals(Opcode.MOVE_16, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals(1, instruction.getRegisterB());
    }
    {
        Instruction35c instruction = (Instruction35c) instructions.get(21);
        Assert.assertEquals(Opcode.INVOKE_VIRTUAL, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterC());
        Assert.assertEquals(1, instruction.getRegisterD());
        Assert.assertEquals(2, instruction.getRegisterE());
        Assert.assertEquals(3, instruction.getRegisterF());
        Assert.assertEquals(4, instruction.getRegisterG());
        Assert.assertEquals("Lblah;->blort(IIII)I", ReferenceUtil.getReferenceString(instruction.getReference()));
    }
    {
        Instruction3rc instruction = (Instruction3rc) instructions.get(22);
        Assert.assertEquals(Opcode.INVOKE_VIRTUAL_RANGE, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getStartRegister());
        Assert.assertEquals(5, instruction.getRegisterCount());
        Assert.assertEquals("Lblah;->blort(IIII)I", ReferenceUtil.getReferenceString(instruction.getReference()));
    }
    {
        Instruction51l instruction = (Instruction51l) instructions.get(23);
        Assert.assertEquals(Opcode.CONST_WIDE, instruction.getOpcode());
        Assert.assertEquals(0, instruction.getRegisterA());
        Assert.assertEquals(0x1234567890L, instruction.getWideLiteral());
    }
}
Also used : SmaliFile(org.jf.smalidea.psi.impl.SmaliFile) MethodImplementation(org.jf.dexlib2.iface.MethodImplementation) SmaliClass(org.jf.smalidea.psi.impl.SmaliClass) SmaliMethod(org.jf.smalidea.psi.impl.SmaliMethod) StringReference(org.jf.dexlib2.iface.reference.StringReference)

Aggregations

Instruction (org.jf.dexlib2.iface.instruction.Instruction)4 ReferenceInstruction (org.jf.dexlib2.iface.instruction.ReferenceInstruction)3 Instruction21c (org.jf.dexlib2.iface.instruction.formats.Instruction21c)3 StringReference (org.jf.dexlib2.iface.reference.StringReference)3 Opcode (org.jf.dexlib2.Opcode)2 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)2 FieldReference (org.jf.dexlib2.iface.reference.FieldReference)2 Test (org.junit.Test)2 ArrayList (java.util.ArrayList)1 Nonnull (javax.annotation.Nonnull)1 BuilderInstruction21c (org.jf.dexlib2.builder.instruction.BuilderInstruction21c)1 DexBackedDexFile (org.jf.dexlib2.dexbacked.DexBackedDexFile)1 ClassDef (org.jf.dexlib2.iface.ClassDef)1 ExceptionHandler (org.jf.dexlib2.iface.ExceptionHandler)1 Method (org.jf.dexlib2.iface.Method)1 OneRegisterInstruction (org.jf.dexlib2.iface.instruction.OneRegisterInstruction)1 Instruction20bc (org.jf.dexlib2.iface.instruction.formats.Instruction20bc)1 Instruction22c (org.jf.dexlib2.iface.instruction.formats.Instruction22c)1 Instruction31c (org.jf.dexlib2.iface.instruction.formats.Instruction31c)1 Instruction35c (org.jf.dexlib2.iface.instruction.formats.Instruction35c)1