1 /* 2 * Copyright 2012, 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 32 package org.jf.dexlib2.dexbacked.instruction; 33 34 import org.jf.dexlib2.Opcode; 35 import org.jf.dexlib2.dexbacked.DexBackedDexFile; 36 import org.jf.dexlib2.dexbacked.DexReader; 37 import org.jf.dexlib2.iface.instruction.Instruction; 38 import org.jf.util.ExceptionWithContext; 39 40 import javax.annotation.Nonnull; 41 import javax.annotation.Nullable; 42 43 public abstract class DexBackedInstruction implements Instruction { 44 @Nonnull public final DexBackedDexFile dexFile; 45 @Nonnull public final Opcode opcode; 46 public final int instructionStart; 47 48 public DexBackedInstruction(@Nonnull DexBackedDexFile dexFile, 49 @Nonnull Opcode opcode, 50 int instructionStart) { 51 this.dexFile = dexFile; 52 this.opcode = opcode; 53 this.instructionStart = instructionStart; 54 } 55 56 @Nonnull public Opcode getOpcode() { return opcode; } 57 @Override public int getCodeUnits() { return opcode.format.size / 2; } 58 59 @Nonnull 60 public static Instruction readFrom(@Nonnull DexReader reader) { 61 int opcodeValue = reader.peekUbyte(); 62 63 if (opcodeValue == 0) { 64 opcodeValue = reader.peekUshort(); 65 } 66 67 Opcode opcode = reader.dexBuf.getOpcodes().getOpcodeByValue(opcodeValue); 68 69 Instruction instruction = buildInstruction(reader.dexBuf, opcode, reader.getOffset()); 70 reader.moveRelative(instruction.getCodeUnits()*2); 71 return instruction; 72 } 73 74 private static DexBackedInstruction buildInstruction(@Nonnull DexBackedDexFile dexFile, @Nullable Opcode opcode, 75 int instructionStartOffset) { 76 if (opcode == null) { 77 return new DexBackedUnknownInstruction(dexFile, instructionStartOffset); 78 } 79 switch (opcode.format) { 80 case Format10t: 81 return new DexBackedInstruction10t(dexFile, opcode, instructionStartOffset); 82 case Format10x: 83 return new DexBackedInstruction10x(dexFile, opcode, instructionStartOffset); 84 case Format11n: 85 return new DexBackedInstruction11n(dexFile, opcode, instructionStartOffset); 86 case Format11x: 87 return new DexBackedInstruction11x(dexFile, opcode, instructionStartOffset); 88 case Format12x: 89 return new DexBackedInstruction12x(dexFile, opcode, instructionStartOffset); 90 case Format20bc: 91 return new DexBackedInstruction20bc(dexFile, opcode, instructionStartOffset); 92 case Format20t: 93 return new DexBackedInstruction20t(dexFile, opcode, instructionStartOffset); 94 case Format21c: 95 return new DexBackedInstruction21c(dexFile, opcode, instructionStartOffset); 96 case Format21ih: 97 return new DexBackedInstruction21ih(dexFile, opcode, instructionStartOffset); 98 case Format21lh: 99 return new DexBackedInstruction21lh(dexFile, opcode, instructionStartOffset); 100 case Format21s: 101 return new DexBackedInstruction21s(dexFile, opcode, instructionStartOffset); 102 case Format21t: 103 return new DexBackedInstruction21t(dexFile, opcode, instructionStartOffset); 104 case Format22b: 105 return new DexBackedInstruction22b(dexFile, opcode, instructionStartOffset); 106 case Format22c: 107 return new DexBackedInstruction22c(dexFile, opcode, instructionStartOffset); 108 case Format22cs: 109 return new DexBackedInstruction22cs(dexFile, opcode, instructionStartOffset); 110 case Format22s: 111 return new DexBackedInstruction22s(dexFile, opcode, instructionStartOffset); 112 case Format22t: 113 return new DexBackedInstruction22t(dexFile, opcode, instructionStartOffset); 114 case Format22x: 115 return new DexBackedInstruction22x(dexFile, opcode, instructionStartOffset); 116 case Format23x: 117 return new DexBackedInstruction23x(dexFile, opcode, instructionStartOffset); 118 case Format30t: 119 return new DexBackedInstruction30t(dexFile, opcode, instructionStartOffset); 120 case Format31c: 121 return new DexBackedInstruction31c(dexFile, opcode, instructionStartOffset); 122 case Format31i: 123 return new DexBackedInstruction31i(dexFile, opcode, instructionStartOffset); 124 case Format31t: 125 return new DexBackedInstruction31t(dexFile, opcode, instructionStartOffset); 126 case Format32x: 127 return new DexBackedInstruction32x(dexFile, opcode, instructionStartOffset); 128 case Format35c: 129 return new DexBackedInstruction35c(dexFile, opcode, instructionStartOffset); 130 case Format35ms: 131 return new DexBackedInstruction35ms(dexFile, opcode, instructionStartOffset); 132 case Format35mi: 133 return new DexBackedInstruction35mi(dexFile, opcode, instructionStartOffset); 134 case Format3rc: 135 return new DexBackedInstruction3rc(dexFile, opcode, instructionStartOffset); 136 case Format3rmi: 137 return new DexBackedInstruction3rmi(dexFile, opcode, instructionStartOffset); 138 case Format3rms: 139 return new DexBackedInstruction3rms(dexFile, opcode, instructionStartOffset); 140 case Format45cc: 141 return new DexBackedInstruction45cc(dexFile, opcode, instructionStartOffset); 142 case Format4rcc: 143 return new DexBackedInstruction4rcc(dexFile, opcode, instructionStartOffset); 144 case Format51l: 145 return new DexBackedInstruction51l(dexFile, opcode, instructionStartOffset); 146 case PackedSwitchPayload: 147 return new DexBackedPackedSwitchPayload(dexFile, instructionStartOffset); 148 case SparseSwitchPayload: 149 return new DexBackedSparseSwitchPayload(dexFile, instructionStartOffset); 150 case ArrayPayload: 151 return new DexBackedArrayPayload(dexFile, instructionStartOffset); 152 default: 153 throw new ExceptionWithContext("Unexpected opcode format: %s", opcode.format.toString()); 154 } 155 } 156 } 157