@Override protected BuilderInstruction getRealInsn0(LabelAssigner assigner) { return new BuilderInstruction10x(opc); } }
@Nonnull private BuilderInstruction10x newBuilderInstruction10x(@Nonnull Instruction10x instruction) { return new BuilderInstruction10x( instruction.getOpcode()); }
BuilderInstruction replacement; if (nextAddresses.contains(address)) { replacement = new BuilderInstruction10x(Opcode.NOP); } else { BuilderOffsetInstruction original = (BuilderOffsetInstruction) manipulator.getInstruction(address);
index--; } else { addInstruction(location.index, new BuilderInstruction10x(Opcode.NOP)); index++;
@Test public void addingManyNopsAfterGotoModifiesStateCorrectly() { int nops_to_insert = 127; Object[][] expected = new Object[3 + nops_to_insert][]; expected[0] = new Object[] { 0, Opcode.GOTO_16, new Object[][][] { { { 2 + 1 + 127, Opcode.RETURN_VOID } } } }; // No children, no node pile, these nops are dead code and never get executed expected[1] = new Object[] { 2, Opcode.NOP, new Object[0][0][0] }; for (int i = 0; i < nops_to_insert; i++) { int index = i + 2; expected[index] = new Object[] { index + 1, Opcode.NOP, new Object[0][0][0] }; } expected[129] = new Object[] { 130, Opcode.RETURN_VOID, new Object[1][0][0] }; manipulator = OptimizerTester.getGraphManipulator(CLASS_NAME, "hasGotoAndOneNop()V"); // Adding 126 bytes (nop) between goto and target offset causes dexlib to "fix" goto into goto/16 for (int i = 0; i < nops_to_insert - 1; i++) { manipulator.addInstruction(1, new BuilderInstruction10x(Opcode.NOP)); } // Addresses 0 and 1 are now goto/16, need to insert at 2 manipulator.addInstruction(2, new BuilderInstruction10x(Opcode.NOP)); test(expected, manipulator); }
public final void insn_format10x() throws RecognitionException { CommonTree INSTRUCTION_FORMAT10x116=null; try { // smaliTreeWalker.g:818:3: ( ^( I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x ) ) // smaliTreeWalker.g:819:5: ^( I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x ) { match(input,I_STATEMENT_FORMAT10x,FOLLOW_I_STATEMENT_FORMAT10x_in_insn_format10x2244); match(input, Token.DOWN, null); INSTRUCTION_FORMAT10x116=(CommonTree)match(input,INSTRUCTION_FORMAT10x,FOLLOW_INSTRUCTION_FORMAT10x_in_insn_format10x2246); match(input, Token.UP, null); Opcode opcode = opcodes.getOpcodeByName((INSTRUCTION_FORMAT10x116!=null?INSTRUCTION_FORMAT10x116.getText():null)); method_stack.peek().methodBuilder.addInstruction(new BuilderInstruction10x(opcode)); } } catch (RecognitionException re) { reportError(re); recover(input,re); } finally { // do for sure before leaving } } // $ANTLR end "insn_format10x"
@Test public void addingThenRemovingManyNopsAfterGotoModifiesStateCorrectly() { Object[][] expected = new Object[3][]; expected[0] = new Object[] { 0, Opcode.GOTO_16, new Object[][][] { { { 3, Opcode.RETURN_VOID } } } }; expected[1] = new Object[] { 2, Opcode.NOP, new Object[0][0][0] }; expected[2] = new Object[] { 3, Opcode.RETURN_VOID, new Object[1][0][0] }; int nops_to_insert = 127; manipulator = OptimizerTester.getGraphManipulator(CLASS_NAME, "hasGotoAndOneNop()V"); // Adding 126 bytes (nop) between goto and target offset causes dexlib to "fix" goto into goto/16 for (int i = 0; i < nops_to_insert - 1; i++) { manipulator.addInstruction(1, new BuilderInstruction10x(Opcode.NOP)); } // Addresses 0 and 1 are now goto/16, need to insert at 2 manipulator.addInstruction(2, new BuilderInstruction10x(Opcode.NOP)); List<Integer> removeList = new LinkedList<Integer>(); // for (int removeAddress = 2, i = 0; i < nops_to_insert; removeAddress++, i++) { for (int i = 1; i < nops_to_insert; i++) { int removeAddress = i + 2; removeList.add(removeAddress); } manipulator.removeInstructions(removeList); manipulator.removeInstruction(2); test(expected, manipulator); }
@Test public void addingInstructionModifiesStateCorrectly() { //@formatter:off Object[][] expected = new Object[][] { { 0, Opcode.NOP, new Object[][][] { { { 1, Opcode.CONST_4 } } } }, { 1, Opcode.CONST_4, new Object[][][] { { { 2, Opcode.CONST_4 } } } }, { 2, Opcode.CONST_4, new Object[][][] { { { 3, Opcode.CONST_4 } } } }, { 3, Opcode.CONST_4, new Object[][][] { { { 4, Opcode.CONST_4 } } } }, { 4, Opcode.CONST_4, new Object[][][] { { { 5, Opcode.CONST_4 } } } }, { 5, Opcode.CONST_4, new Object[][][] { { { 6, Opcode.RETURN_VOID } } } }, { 6, Opcode.RETURN_VOID, new Object[1][0][0] }, }; //@formatter:on manipulator = OptimizerTester.getGraphManipulator(CLASS_NAME, "verySimple()V"); BuilderInstruction addition = new BuilderInstruction10x(Opcode.NOP); manipulator.addInstruction(0, addition); test(expected, manipulator); testHeritage(manipulator, 0); testHeritage(manipulator, 1); }
@Test public void addingInstructionThatCausesNopPaddingToBeAddedModifiesStateCorrectly() { //@formatter:off Object[][] expected = new Object[][] { { 0, Opcode.CONST_16, new Object[][][] { { { 2, Opcode.NEW_ARRAY } } } }, { 2, Opcode.NEW_ARRAY, new Object[][][] { { { 4, Opcode.NOP } } } }, { 4, Opcode.NOP, new Object[][][] { { { 5, Opcode.FILL_ARRAY_DATA } } } }, { 5, Opcode.FILL_ARRAY_DATA, new Object[][][] { { { 0xa, Opcode.ARRAY_PAYLOAD } } } }, { 8, Opcode.RETURN_VOID, new Object[1][0][0] }, { 9, Opcode.NOP, new Object[0][0][0] }, { 0xa, Opcode.ARRAY_PAYLOAD, new Object[][][] { { { 8, Opcode.RETURN_VOID } }, } }, }; //@formatter:on manipulator = OptimizerTester.getGraphManipulator(CLASS_NAME, "hasNoNopPadding()V"); BuilderInstruction addition = new BuilderInstruction10x(Opcode.NOP); manipulator.addInstruction(4, addition); test(expected, manipulator); testHeritage(manipulator, 2); testHeritage(manipulator, 4); testHeritage(manipulator, 5); }
@Nonnull private BuilderInstruction10x newBuilderInstruction10x(@Nonnull Instruction10x instruction) { return new BuilderInstruction10x( instruction.getOpcode()); }
@Nonnull private BuilderInstruction10x newBuilderInstruction10x(@Nonnull Instruction10x instruction) { return new BuilderInstruction10x( instruction.getOpcode()); }
@Nonnull private BuilderInstruction10x newBuilderInstruction10x(@Nonnull Instruction10x instruction) { return new BuilderInstruction10x( instruction.getOpcode()); }
@Nonnull private BuilderInstruction10x newBuilderInstruction10x(@Nonnull Instruction10x instruction) { return new BuilderInstruction10x( instruction.getOpcode()); }
@Test public void testFixGotoToGoto16() { MethodImplementationBuilder builder = new MethodImplementationBuilder(1); Label gotoTarget = builder.getLabel("gotoTarget"); builder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, gotoTarget)); for (int i=0; i<500; i++) { builder.addInstruction(new BuilderInstruction10x(Opcode.NOP)); } builder.addLabel("gotoTarget"); builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); MethodImplementation impl = builder.getMethodImplementation(); List<? extends Instruction> instructions = Lists.newArrayList(impl.getInstructions()); Assert.assertEquals(502, instructions.size()); Assert.assertEquals(Opcode.GOTO_16, instructions.get(0).getOpcode()); Assert.assertEquals(502, ((OffsetInstruction)instructions.get(0)).getCodeOffset()); }
@Test public void testFixGotoToGoto32() { MethodImplementationBuilder builder = new MethodImplementationBuilder(1); Label gotoTarget = builder.getLabel("gotoTarget"); builder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, gotoTarget)); for (int i=0; i<70000; i++) { builder.addInstruction(new BuilderInstruction10x(Opcode.NOP)); } builder.addLabel("gotoTarget"); builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); MethodImplementation impl = builder.getMethodImplementation(); List<? extends Instruction> instructions = Lists.newArrayList(impl.getInstructions()); Assert.assertEquals(70002, instructions.size()); Assert.assertEquals(Opcode.GOTO_32, instructions.get(0).getOpcode()); Assert.assertEquals(70003, ((OffsetInstruction)instructions.get(0)).getCodeOffset()); }
@Test public void testFixGoto16ToGoto32() { MethodImplementationBuilder builder = new MethodImplementationBuilder(1); Label gotoTarget = builder.getLabel("gotoTarget"); builder.addInstruction(new BuilderInstruction20t(Opcode.GOTO_16, gotoTarget)); for (int i=0; i<70000; i++) { builder.addInstruction(new BuilderInstruction10x(Opcode.NOP)); } builder.addLabel("gotoTarget"); builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); MethodImplementation impl = builder.getMethodImplementation(); List<? extends Instruction> instructions = Lists.newArrayList(impl.getInstructions()); Assert.assertEquals(70002, instructions.size()); Assert.assertEquals(Opcode.GOTO_32, instructions.get(0).getOpcode()); Assert.assertEquals(70003, ((OffsetInstruction)instructions.get(0)).getCodeOffset()); }
@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); }
@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()); }
@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()); }
@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()); }