1/* 2 * Copyright 2013, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32package org.jf.dexlib2.builder; 33 34import com.google.common.collect.Lists; 35import junit.framework.Assert; 36import org.jf.dexlib2.Opcode; 37import org.jf.dexlib2.builder.instruction.BuilderInstruction10t; 38import org.jf.dexlib2.builder.instruction.BuilderInstruction10x; 39import org.jf.dexlib2.iface.ExceptionHandler; 40import org.jf.dexlib2.iface.MethodImplementation; 41import org.jf.dexlib2.iface.TryBlock; 42import org.jf.dexlib2.iface.debug.DebugItem; 43import org.jf.dexlib2.iface.debug.LineNumber; 44import org.jf.dexlib2.iface.instruction.Instruction; 45import org.jf.dexlib2.iface.instruction.OffsetInstruction; 46import org.junit.Test; 47 48import java.util.List; 49 50public class FixOffsetsTest { 51 @Test 52 public void testFixOffsets() { 53 MethodImplementationBuilder builder = new MethodImplementationBuilder(1); 54 55 Label firstGotoTarget = builder.getLabel("firstGotoTarget"); 56 builder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, firstGotoTarget)); 57 58 builder.addLineNumber(1); 59 60 for (int i=0; i<250; i++) { 61 builder.addInstruction(new BuilderInstruction10x(Opcode.NOP)); 62 } 63 64 builder.addLabel("tryStart"); 65 66 builder.addLineNumber(2); 67 68 for (int i=0; i<250; i++) { 69 builder.addInstruction(new BuilderInstruction10x(Opcode.NOP)); 70 } 71 72 builder.addLineNumber(3); 73 74 Label secondGotoTarget = builder.getLabel("secondGotoTarget"); 75 builder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, secondGotoTarget)); 76 77 78 builder.addLineNumber(4); 79 builder.addLabel("handler"); 80 81 for (int i=0; i<500; i++) { 82 builder.addInstruction(new BuilderInstruction10x(Opcode.NOP)); 83 } 84 85 builder.addLineNumber(5); 86 87 builder.addLabel("tryEnd"); 88 89 builder.addLabel("firstGotoTarget"); 90 builder.addLabel("secondGotoTarget"); 91 builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); 92 93 Label tryStart = builder.getLabel("tryStart"); 94 Label tryEnd = builder.getLabel("tryEnd"); 95 Label handler = builder.getLabel("handler"); 96 97 builder.addCatch(tryStart, tryEnd, handler); 98 99 MethodImplementation impl = builder.getMethodImplementation(); 100 101 List<? extends Instruction> instructions = Lists.newArrayList(impl.getInstructions()); 102 Assert.assertEquals(1003, instructions.size()); 103 104 Assert.assertEquals(Opcode.GOTO_16, instructions.get(0).getOpcode()); 105 Assert.assertEquals(1004, ((OffsetInstruction)instructions.get(0)).getCodeOffset()); 106 107 Assert.assertEquals(Opcode.GOTO_16, instructions.get(501).getOpcode()); 108 Assert.assertEquals(502, ((OffsetInstruction)instructions.get(501)).getCodeOffset()); 109 110 List<? extends TryBlock<? extends ExceptionHandler>> exceptionHandlers = impl.getTryBlocks(); 111 112 Assert.assertEquals(1, exceptionHandlers.size()); 113 Assert.assertEquals(252, exceptionHandlers.get(0).getStartCodeAddress()); 114 Assert.assertEquals(752, exceptionHandlers.get(0).getCodeUnitCount()); 115 116 Assert.assertEquals(1, exceptionHandlers.get(0).getExceptionHandlers().size()); 117 118 ExceptionHandler exceptionHandler = exceptionHandlers.get(0).getExceptionHandlers().get(0); 119 Assert.assertEquals(504, exceptionHandler.getHandlerCodeAddress()); 120 121 List<DebugItem> debugItems = Lists.newArrayList(impl.getDebugItems()); 122 123 Assert.assertEquals(5, debugItems.size()); 124 125 Assert.assertEquals(1, ((LineNumber)debugItems.get(0)).getLineNumber()); 126 Assert.assertEquals(2, debugItems.get(0).getCodeAddress()); 127 128 Assert.assertEquals(2, ((LineNumber)debugItems.get(1)).getLineNumber()); 129 Assert.assertEquals(252, debugItems.get(1).getCodeAddress()); 130 131 Assert.assertEquals(3, ((LineNumber)debugItems.get(2)).getLineNumber()); 132 Assert.assertEquals(502, debugItems.get(2).getCodeAddress()); 133 134 Assert.assertEquals(4, ((LineNumber)debugItems.get(3)).getLineNumber()); 135 Assert.assertEquals(504, debugItems.get(3).getCodeAddress()); 136 137 Assert.assertEquals(5, ((LineNumber)debugItems.get(4)).getLineNumber()); 138 Assert.assertEquals(1004, debugItems.get(4).getCodeAddress()); 139 } 140} 141