InstructionMethodItem.java revision db7795ffaa2d8804d84623a79d406f8c8686c1b8
1/* 2 * [The "BSD licence"] 3 * Copyright (c) 2010 Ben Gruver (JesusFreke) 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29package org.jf.baksmali.Adaptors.Format; 30 31import org.jf.baksmali.Adaptors.MethodDefinition; 32import org.jf.baksmali.Adaptors.MethodItem; 33import org.jf.baksmali.Adaptors.ReferenceFormatter; 34import org.jf.baksmali.Renderers.LongRenderer; 35import org.jf.dexlib.Code.Format.UnknownInstruction; 36import org.jf.dexlib2.VerificationError; 37import org.jf.dexlib2.iface.instruction.*; 38import org.jf.dexlib2.iface.instruction.formats.Instruction20bc; 39import org.jf.util.IndentingWriter; 40 41import javax.annotation.Nonnull; 42import java.io.IOException; 43 44public class InstructionMethodItem<T extends Instruction> extends MethodItem { 45 @Nonnull protected final MethodDefinition methodDef; 46 @Nonnull protected final T instruction; 47 48 public InstructionMethodItem(@Nonnull MethodDefinition methodDef, int codeAddress, @Nonnull T instruction) { 49 super(codeAddress); 50 this.methodDef = methodDef; 51 this.instruction = instruction; 52 } 53 54 public double getSortOrder() { 55 //instructions should appear after everything except an "end try" label and .catch directive 56 return 100; 57 } 58 59 @Override 60 public boolean writeTo(IndentingWriter writer) throws IOException { 61 switch (instruction.getOpcode().format) { 62 case Format10t: 63 writeOpcode(writer); 64 writer.write(' '); 65 writeTargetLabel(writer); 66 return true; 67 case Format10x: 68 if (instruction instanceof UnknownInstruction) { 69 writer.write("#unknown opcode: 0x"); 70 writer.printUnsignedLongAsHex(((UnknownInstruction) instruction).getOriginalOpcode() & 0xFFFF); 71 writer.write('\n'); 72 } 73 writeOpcode(writer); 74 return true; 75 case Format11n: 76 writeOpcode(writer); 77 writer.write(' '); 78 writeFirstRegister(writer); 79 writer.write(", "); 80 writeLiteral(writer); 81 return true; 82 case Format11x: 83 writeOpcode(writer); 84 writer.write(' '); 85 writeFirstRegister(writer); 86 return true; 87 case Format12x: 88 writeOpcode(writer); 89 writer.write(' '); 90 writeFirstRegister(writer); 91 writer.write(", "); 92 writeSecondRegister(writer); 93 return true; 94 case Format20bc: 95 writeOpcode(writer); 96 writer.write(' '); 97 writeVerificationErrorType(writer); 98 writer.write(", "); 99 writeReference(writer); 100 return true; 101 case Format20t: 102 case Format30t: 103 writeOpcode(writer); 104 writer.write(' '); 105 writeTargetLabel(writer); 106 return true; 107 case Format21c: 108 case Format31c: 109 writeOpcode(writer); 110 writer.write(' '); 111 writeFirstRegister(writer); 112 writer.write(", "); 113 writeReference(writer); 114 return true; 115 case Format21ih: 116 case Format21lh: 117 case Format21s: 118 case Format31i: 119 case Format51l: 120 writeOpcode(writer); 121 writer.write(' '); 122 writeFirstRegister(writer); 123 writer.write(", "); 124 writeLiteral(writer); 125 return true; 126 case Format21t: 127 case Format31t: 128 writeOpcode(writer); 129 writer.write(' '); 130 writeFirstRegister(writer); 131 writer.write(", "); 132 writeTargetLabel(writer); 133 return true; 134 case Format22b: 135 case Format22s: 136 writeOpcode(writer); 137 writer.write(' '); 138 writeFirstRegister(writer); 139 writer.write(", "); 140 writeSecondRegister(writer); 141 writer.write(", "); 142 writeLiteral(writer); 143 return true; 144 case Format22c: 145 writeOpcode(writer); 146 writer.write(' '); 147 writeFirstRegister(writer); 148 writer.write(", "); 149 writeSecondRegister(writer); 150 writer.write(", "); 151 writeReference(writer); 152 return true; 153 case Format22cs: 154 writeOpcode(writer); 155 writer.write(' '); 156 writeFirstRegister(writer); 157 writer.write(", "); 158 writeSecondRegister(writer); 159 writer.write(", "); 160 writeFieldOffset(writer); 161 return true; 162 case Format22t: 163 writeOpcode(writer); 164 writer.write(' '); 165 writeFirstRegister(writer); 166 writer.write(", "); 167 writeSecondRegister(writer); 168 writer.write(", "); 169 writeTargetLabel(writer); 170 return true; 171 case Format22x: 172 case Format32x: 173 writeOpcode(writer); 174 writer.write(' '); 175 writeFirstRegister(writer); 176 writer.write(", "); 177 writeSecondRegister(writer); 178 return true; 179 case Format23x: 180 writeOpcode(writer); 181 writer.write(' '); 182 writeFirstRegister(writer); 183 writer.write(", "); 184 writeSecondRegister(writer); 185 writer.write(", "); 186 writeThirdRegister(writer); 187 return true; 188 case Format35c: 189 writeOpcode(writer); 190 writer.write(' '); 191 writeInvokeRegisters(writer); 192 writer.write(", "); 193 writeReference(writer); 194 return true; 195 case Format35mi: 196 writeOpcode(writer); 197 writer.write(' '); 198 writeInvokeRegisters(writer); 199 writer.write(", "); 200 writeInlineIndex(writer); 201 return true; 202 case Format35ms: 203 writeOpcode(writer); 204 writer.write(' '); 205 writeInvokeRegisters(writer); 206 writer.write(", "); 207 writeVtableIndex(writer); 208 return true; 209 case Format3rc: 210 writeOpcode(writer); 211 writer.write(' '); 212 writeInvokeRangeRegisters(writer); 213 writer.write(", "); 214 writeReference(writer); 215 return true; 216 case Format3rmi: 217 writeOpcode(writer); 218 writer.write(' '); 219 writeInvokeRangeRegisters(writer); 220 writer.write(", "); 221 writeInlineIndex(writer); 222 return true; 223 case Format3rms: 224 writeOpcode(writer); 225 writer.write(' '); 226 writeInvokeRangeRegisters(writer); 227 writer.write(", "); 228 writeVtableIndex(writer); 229 return true; 230 } 231 assert false; 232 return false; 233 } 234 235 protected void writeOpcode(IndentingWriter writer) throws IOException { 236 writer.write(instruction.getOpcode().name); 237 } 238 239 protected void writeTargetLabel(IndentingWriter writer) throws IOException { 240 //this method is overridden by OffsetInstructionMethodItem, and should only be called for the formats that 241 //have a target 242 throw new RuntimeException(); 243 } 244 245 protected void writeRegister(IndentingWriter writer, int registerNumber) throws IOException { 246 methodDef.registerFormatter.writeTo(writer, registerNumber); 247 } 248 249 protected void writeFirstRegister(IndentingWriter writer) throws IOException { 250 writeRegister(writer, ((OneRegisterInstruction)instruction).getRegisterA()); 251 } 252 253 protected void writeSecondRegister(IndentingWriter writer) throws IOException { 254 writeRegister(writer, ((TwoRegisterInstruction)instruction).getRegisterB()); 255 } 256 257 protected void writeThirdRegister(IndentingWriter writer) throws IOException { 258 writeRegister(writer, ((ThreeRegisterInstruction) instruction).getRegisterC()); 259 } 260 261 protected void writeInvokeRegisters(IndentingWriter writer) throws IOException { 262 FiveRegisterInstruction instruction = (FiveRegisterInstruction)this.instruction; 263 final int regCount = instruction.getRegisterCount(); 264 265 writer.write('{'); 266 switch (regCount) { 267 case 1: 268 writeRegister(writer, instruction.getRegisterC()); 269 break; 270 case 2: 271 writeRegister(writer, instruction.getRegisterC()); 272 writer.write(", "); 273 writeRegister(writer, instruction.getRegisterD()); 274 break; 275 case 3: 276 writeRegister(writer, instruction.getRegisterC()); 277 writer.write(", "); 278 writeRegister(writer, instruction.getRegisterD()); 279 writer.write(", "); 280 writeRegister(writer, instruction.getRegisterE()); 281 break; 282 case 4: 283 writeRegister(writer, instruction.getRegisterC()); 284 writer.write(", "); 285 writeRegister(writer, instruction.getRegisterD()); 286 writer.write(", "); 287 writeRegister(writer, instruction.getRegisterE()); 288 writer.write(", "); 289 writeRegister(writer, instruction.getRegisterF()); 290 break; 291 case 5: 292 writeRegister(writer, instruction.getRegisterC()); 293 writer.write(", "); 294 writeRegister(writer, instruction.getRegisterD()); 295 writer.write(", "); 296 writeRegister(writer, instruction.getRegisterE()); 297 writer.write(", "); 298 writeRegister(writer, instruction.getRegisterF()); 299 writer.write(", "); 300 writeRegister(writer, instruction.getRegisterG()); 301 break; 302 } 303 writer.write('}'); 304 } 305 306 protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException { 307 RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction; 308 309 int regCount = instruction.getRegisterCount(); 310 if (regCount == 0) { 311 writer.write("{}"); 312 } else { 313 int startRegister = instruction.getStartRegister(); 314 methodDef.registerFormatter.writeRegisterRange(writer, startRegister, startRegister+regCount-1); 315 } 316 } 317 318 protected void writeLiteral(IndentingWriter writer) throws IOException { 319 LongRenderer.writeSignedIntOrLongTo(writer, ((WideLiteralInstruction)instruction).getWideLiteral()); 320 } 321 322 323 protected void writeFieldOffset(IndentingWriter writer) throws IOException { 324 writer.write("field@0x"); 325 writer.printUnsignedLongAsHex(((FieldOffsetInstruction)instruction).getFieldOffset()); 326 } 327 328 protected void writeInlineIndex(IndentingWriter writer) throws IOException { 329 writer.write("inline@"); 330 writer.printSignedIntAsDec(((InlineIndexInstruction)instruction).getInlineIndex()); 331 } 332 333 protected void writeVtableIndex(IndentingWriter writer) throws IOException { 334 writer.write("vtable@"); 335 writer.printSignedIntAsDec(((VtableIndexInstruction)instruction).getVtableIndex()); 336 } 337 338 protected void writeReference(IndentingWriter writer) throws IOException { 339 ReferenceFormatter.writeReference(writer, instruction.getOpcode().referenceType, 340 ((ReferenceInstruction)instruction).getReference()); 341 } 342 343 protected void writeVerificationErrorType(IndentingWriter writer) throws IOException { 344 int verificationError = ((Instruction20bc)instruction).getVerificationError(); 345 writer.write(VerificationError.getVerificationErrorName(verificationError)); 346 } 347} 348