Search in sources :

Example 16 with BuilderInstruction10x

use of org.jf.dexlib2.builder.instruction.BuilderInstruction10x in project smali by JesusFreke.

the class PayloadAlignmentTest method testPayloadAlignmentRemoveNopWithReferent.

@Test
public void testPayloadAlignmentRemoveNopWithReferent() {
    MethodImplementationBuilder implBuilder = new MethodImplementationBuilder(10);
    Label label = implBuilder.getLabel("array_payload");
    implBuilder.addInstruction(new BuilderInstruction31t(Opcode.FILL_ARRAY_DATA, 0, label));
    implBuilder.addInstruction(new BuilderInstruction12x(Opcode.MOVE, 0, 0));
    implBuilder.addInstruction(new BuilderInstruction12x(Opcode.MOVE, 0, 0));
    implBuilder.addInstruction(new BuilderInstruction12x(Opcode.MOVE, 0, 0));
    implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    implBuilder.addLabel("array_payload");
    implBuilder.addInstruction(new BuilderArrayPayload(4, null));
    List<Instruction> instructions = Lists.newArrayList(implBuilder.getMethodImplementation().getInstructions());
    checkInstructions(instructions, new Opcode[] { Opcode.FILL_ARRAY_DATA, Opcode.MOVE, Opcode.MOVE, Opcode.MOVE, Opcode.ARRAY_PAYLOAD });
    Instruction31t referent = (Instruction31t) instructions.get(0);
    Assert.assertEquals(6, referent.getCodeOffset());
}
Also used : OffsetInstruction(org.jf.dexlib2.iface.instruction.OffsetInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) Instruction31t(org.jf.dexlib2.iface.instruction.formats.Instruction31t) Test(org.junit.Test)

Example 17 with BuilderInstruction10x

use of org.jf.dexlib2.builder.instruction.BuilderInstruction10x in project smali by JesusFreke.

the class PayloadAlignmentTest method testPayloadAlignmentRemoveNop.

@Test
public void testPayloadAlignmentRemoveNop() {
    MethodImplementationBuilder implBuilder = new MethodImplementationBuilder(10);
    implBuilder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    implBuilder.addInstruction(new BuilderArrayPayload(4, null));
    List<? extends Instruction> instructions = Lists.newArrayList(implBuilder.getMethodImplementation().getInstructions());
    Assert.assertEquals(instructions.size(), 1);
    Instruction instruction = instructions.get(0);
    Assert.assertEquals(instruction.getOpcode(), Opcode.ARRAY_PAYLOAD);
}
Also used : OffsetInstruction(org.jf.dexlib2.iface.instruction.OffsetInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) Test(org.junit.Test)

Example 18 with BuilderInstruction10x

use of org.jf.dexlib2.builder.instruction.BuilderInstruction10x in project smali by JesusFreke.

the class MutableMethodImplementationTest method testNewLabelByAddress.

@Test
public void testNewLabelByAddress() {
    MethodImplementationBuilder builder = new MethodImplementationBuilder(10);
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction32x(Opcode.MOVE_16, 0, 0));
    MutableMethodImplementation mutableMethodImplementation = new MutableMethodImplementation(builder.getMethodImplementation());
    mutableMethodImplementation.addCatch(mutableMethodImplementation.newLabelForAddress(0), mutableMethodImplementation.newLabelForAddress(8), mutableMethodImplementation.newLabelForAddress(1));
    Assert.assertEquals(0, mutableMethodImplementation.getTryBlocks().get(0).getStartCodeAddress());
    Assert.assertEquals(8, mutableMethodImplementation.getTryBlocks().get(0).getCodeUnitCount());
    Assert.assertEquals(1, mutableMethodImplementation.getTryBlocks().get(0).getExceptionHandlers().get(0).getHandlerCodeAddress());
}
Also used : BuilderInstruction10x(org.jf.dexlib2.builder.instruction.BuilderInstruction10x) BuilderInstruction32x(org.jf.dexlib2.builder.instruction.BuilderInstruction32x) Test(org.junit.Test)

Example 19 with BuilderInstruction10x

use of org.jf.dexlib2.builder.instruction.BuilderInstruction10x in project smali by JesusFreke.

the class MutableMethodImplementationTest method testTryEndAtEndOfMethod.

@Test
public void testTryEndAtEndOfMethod() {
    MethodImplementationBuilder builder = new MethodImplementationBuilder(10);
    Label startLabel = builder.addLabel("start");
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
    builder.addInstruction(new BuilderInstruction32x(Opcode.MOVE_16, 0, 0));
    Label endLabel = builder.addLabel("end");
    builder.addCatch(startLabel, endLabel, startLabel);
    MethodImplementation methodImplementation = builder.getMethodImplementation();
    Assert.assertEquals(0, methodImplementation.getTryBlocks().get(0).getStartCodeAddress());
    Assert.assertEquals(8, methodImplementation.getTryBlocks().get(0).getCodeUnitCount());
    methodImplementation = new MutableMethodImplementation(methodImplementation);
    Assert.assertEquals(0, methodImplementation.getTryBlocks().get(0).getStartCodeAddress());
    Assert.assertEquals(8, methodImplementation.getTryBlocks().get(0).getCodeUnitCount());
}
Also used : MethodImplementation(org.jf.dexlib2.iface.MethodImplementation) BuilderInstruction10x(org.jf.dexlib2.builder.instruction.BuilderInstruction10x) BuilderInstruction32x(org.jf.dexlib2.builder.instruction.BuilderInstruction32x) Test(org.junit.Test)

Example 20 with BuilderInstruction10x

use of org.jf.dexlib2.builder.instruction.BuilderInstruction10x in project tinker by Tencent.

the class BuilderMutableMethodImplementation method fixInstructions.

private void fixInstructions() {
    HashSet<MethodLocation> payloadLocations = Sets.newHashSet();
    for (MethodLocation location : instructionList) {
        BuilderInstruction instruction = location.instruction;
        if (instruction != null) {
            switch(instruction.getOpcode()) {
                case SPARSE_SWITCH:
                case PACKED_SWITCH:
                    {
                        MethodLocation targetLocation = ((BuilderOffsetInstruction) instruction).getTarget().getLocation();
                        BuilderInstruction targetInstruction = targetLocation.instruction;
                        if (targetInstruction == null) {
                            throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d points to the end of the method.", location.codeAddress, location.index));
                        }
                        if (targetInstruction.getOpcode() == Opcode.NOP) {
                            targetInstruction = getFirstNonNop(targetLocation.index + 1);
                        }
                        if (targetInstruction == null || !(targetInstruction instanceof BuilderSwitchPayload)) {
                            throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d does not refer to a payload instruction.", location.codeAddress, location.index));
                        }
                        if ((instruction.opcode == Opcode.PACKED_SWITCH && targetInstruction.getOpcode() != Opcode.PACKED_SWITCH_PAYLOAD) || (instruction.opcode == Opcode.SPARSE_SWITCH && targetInstruction.getOpcode() != Opcode.SPARSE_SWITCH_PAYLOAD)) {
                            throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d refers to the wrong type of payload instruction.", location.codeAddress, location.index));
                        }
                        if (!payloadLocations.add(targetLocation)) {
                            throw new IllegalStateException("Multiple switch instructions refer to the same payload. " + "This is not currently supported. Please file a bug :)");
                        }
                        ((BuilderSwitchPayload) targetInstruction).referrer = location;
                        break;
                    }
                default:
                    {
                        break;
                    }
            }
        }
    }
    boolean madeChanges;
    do {
        madeChanges = false;
        for (int index = 0; index < instructionList.size(); index++) {
            MethodLocation location = instructionList.get(index);
            BuilderInstruction instruction = location.instruction;
            if (instruction != null) {
                switch(instruction.getOpcode()) {
                    case GOTO:
                        {
                            int offset = ((BuilderOffsetInstruction) instruction).internalGetCodeOffset();
                            if (offset < Byte.MIN_VALUE || offset > Byte.MAX_VALUE) {
                                BuilderOffsetInstruction replacement;
                                if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
                                    replacement = new BuilderInstruction30t(Opcode.GOTO_32, ((BuilderOffsetInstruction) instruction).getTarget());
                                } else {
                                    replacement = new BuilderInstruction20t(Opcode.GOTO_16, ((BuilderOffsetInstruction) instruction).getTarget());
                                }
                                replaceInstruction(location.index, replacement);
                                madeChanges = true;
                            }
                            break;
                        }
                    case GOTO_16:
                        {
                            int offset = ((BuilderOffsetInstruction) instruction).internalGetCodeOffset();
                            if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
                                BuilderOffsetInstruction replacement = new BuilderInstruction30t(Opcode.GOTO_32, ((BuilderOffsetInstruction) instruction).getTarget());
                                replaceInstruction(location.index, replacement);
                                madeChanges = true;
                            }
                            break;
                        }
                    case SPARSE_SWITCH_PAYLOAD:
                    case PACKED_SWITCH_PAYLOAD:
                        if (((BuilderSwitchPayload) instruction).referrer == null) {
                            // if the switch payload isn't referenced, just remove it
                            removeInstruction(index);
                            index--;
                            madeChanges = true;
                            break;
                        }
                    // intentional fall-through
                    case ARRAY_PAYLOAD:
                        {
                            if ((location.codeAddress & 0x01) != 0) {
                                int previousIndex = location.index - 1;
                                MethodLocation previousLocation = instructionList.get(previousIndex);
                                Instruction previousInstruction = previousLocation.instruction;
                                assert previousInstruction != null;
                                if (previousInstruction.getOpcode() == Opcode.NOP) {
                                    removeInstruction(previousIndex);
                                    index--;
                                } else {
                                    addInstruction(location.index, new BuilderInstruction10x(Opcode.NOP));
                                    index++;
                                }
                                madeChanges = true;
                            }
                            break;
                        }
                    default:
                        {
                            break;
                        }
                }
            }
        }
    } while (madeChanges);
    fixInstructions = false;
}
Also used : BuilderInstruction10x(org.jf.dexlib2.builder.instruction.BuilderInstruction10x) BuilderInstruction20t(org.jf.dexlib2.builder.instruction.BuilderInstruction20t) BuilderInstruction30t(org.jf.dexlib2.builder.instruction.BuilderInstruction30t) Instruction(org.jf.dexlib2.iface.instruction.Instruction)

Aggregations

Test (org.junit.Test)19 BuilderInstruction10x (org.jf.dexlib2.builder.instruction.BuilderInstruction10x)16 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)12 MethodImplementationBuilder (org.jf.dexlib2.builder.MethodImplementationBuilder)7 BuilderInstruction21t (org.jf.dexlib2.builder.instruction.BuilderInstruction21t)6 BuilderInstruction22c (org.jf.dexlib2.builder.instruction.BuilderInstruction22c)6 ClassDef (org.jf.dexlib2.iface.ClassDef)6 DexFile (org.jf.dexlib2.iface.DexFile)6 Method (org.jf.dexlib2.iface.Method)6 ImmutableClassDef (org.jf.dexlib2.immutable.ImmutableClassDef)6 ImmutableDexFile (org.jf.dexlib2.immutable.ImmutableDexFile)6 ImmutableMethod (org.jf.dexlib2.immutable.ImmutableMethod)6 ImmutableMethodParameter (org.jf.dexlib2.immutable.ImmutableMethodParameter)6 ImmutableTypeReference (org.jf.dexlib2.immutable.reference.ImmutableTypeReference)6 Instruction (org.jf.dexlib2.iface.instruction.Instruction)5 BuilderInstruction10t (org.jf.dexlib2.builder.instruction.BuilderInstruction10t)4 OffsetInstruction (org.jf.dexlib2.iface.instruction.OffsetInstruction)4 BuilderInstruction20t (org.jf.dexlib2.builder.instruction.BuilderInstruction20t)3 BuilderInstruction32x (org.jf.dexlib2.builder.instruction.BuilderInstruction32x)3 BuilderInstruction12x (org.jf.dexlib2.builder.instruction.BuilderInstruction12x)2