InstructionMethodItem.java revision f7d6d5fadec6276246194a55b6aefe4815b50ace
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.dexlib2.ReferenceType; 36import org.jf.dexlib2.VerificationError; 37import org.jf.dexlib2.dexbacked.DexBackedDexFile.InvalidItemIndex; 38import org.jf.dexlib2.iface.instruction.*; 39import org.jf.dexlib2.iface.instruction.formats.Instruction20bc; 40import org.jf.dexlib2.iface.instruction.formats.UnknownInstruction; 41import org.jf.dexlib2.iface.reference.Reference; 42import org.jf.util.IndentingWriter; 43 44import javax.annotation.Nonnull; 45import java.io.IOException; 46 47public class InstructionMethodItem<T extends Instruction> extends MethodItem { 48 @Nonnull protected final MethodDefinition methodDef; 49 @Nonnull protected final T instruction; 50 51 public InstructionMethodItem(@Nonnull MethodDefinition methodDef, int codeAddress, @Nonnull T instruction) { 52 super(codeAddress); 53 this.methodDef = methodDef; 54 this.instruction = instruction; 55 } 56 57 public double getSortOrder() { 58 //instructions should appear after everything except an "end try" label and .catch directive 59 return 100; 60 } 61 62 @Override 63 public boolean writeTo(IndentingWriter writer) throws IOException { 64 boolean invalidReference = false; 65 if (instruction instanceof ReferenceInstruction) { 66 try { 67 Reference reference = ((ReferenceInstruction)instruction).getReference(); 68 } catch (InvalidItemIndex ex) { 69 invalidReference = true; 70 71 writer.write("#invalid "); 72 writer.write(ReferenceType.toString(instruction.getOpcode().referenceType)); 73 writer.write(" index: "); 74 writer.printSignedIntAsDec(ex.getInvalidIndex()); 75 writer.write("\n#"); 76 } 77 } 78 79 switch (instruction.getOpcode().format) { 80 case Format10t: 81 writeOpcode(writer); 82 writer.write(' '); 83 writeTargetLabel(writer); 84 return true; 85 case Format10x: 86 if (instruction instanceof UnknownInstruction) { 87 writer.write("#unknown opcode: 0x"); 88 writer.printUnsignedLongAsHex(((UnknownInstruction)instruction).getOriginalOpcode()); 89 writer.write('\n'); 90 } 91 writeOpcode(writer); 92 return true; 93 case Format11n: 94 writeOpcode(writer); 95 writer.write(' '); 96 writeFirstRegister(writer); 97 writer.write(", "); 98 writeLiteral(writer); 99 return true; 100 case Format11x: 101 writeOpcode(writer); 102 writer.write(' '); 103 writeFirstRegister(writer); 104 return true; 105 case Format12x: 106 writeOpcode(writer); 107 writer.write(' '); 108 writeFirstRegister(writer); 109 writer.write(", "); 110 writeSecondRegister(writer); 111 return true; 112 case Format20bc: 113 writeOpcode(writer); 114 writer.write(' '); 115 writeVerificationErrorType(writer); 116 writer.write(", "); 117 writeReference(writer); 118 return true; 119 case Format20t: 120 case Format30t: 121 writeOpcode(writer); 122 writer.write(' '); 123 writeTargetLabel(writer); 124 return true; 125 case Format21c: 126 case Format31c: 127 writeOpcode(writer); 128 writer.write(' '); 129 writeFirstRegister(writer); 130 writer.write(", "); 131 writeReference(writer); 132 return true; 133 case Format21ih: 134 case Format21lh: 135 case Format21s: 136 case Format31i: 137 case Format51l: 138 writeOpcode(writer); 139 writer.write(' '); 140 writeFirstRegister(writer); 141 writer.write(", "); 142 writeLiteral(writer); 143 return true; 144 case Format21t: 145 case Format31t: 146 writeOpcode(writer); 147 writer.write(' '); 148 writeFirstRegister(writer); 149 writer.write(", "); 150 writeTargetLabel(writer); 151 return true; 152 case Format22b: 153 case Format22s: 154 writeOpcode(writer); 155 writer.write(' '); 156 writeFirstRegister(writer); 157 writer.write(", "); 158 writeSecondRegister(writer); 159 writer.write(", "); 160 writeLiteral(writer); 161 return true; 162 case Format22c: 163 writeOpcode(writer); 164 writer.write(' '); 165 writeFirstRegister(writer); 166 writer.write(", "); 167 writeSecondRegister(writer); 168 writer.write(", "); 169 writeReference(writer); 170 return true; 171 case Format22cs: 172 writeOpcode(writer); 173 writer.write(' '); 174 writeFirstRegister(writer); 175 writer.write(", "); 176 writeSecondRegister(writer); 177 writer.write(", "); 178 writeFieldOffset(writer); 179 return true; 180 case Format22t: 181 writeOpcode(writer); 182 writer.write(' '); 183 writeFirstRegister(writer); 184 writer.write(", "); 185 writeSecondRegister(writer); 186 writer.write(", "); 187 writeTargetLabel(writer); 188 return true; 189 case Format22x: 190 case Format32x: 191 writeOpcode(writer); 192 writer.write(' '); 193 writeFirstRegister(writer); 194 writer.write(", "); 195 writeSecondRegister(writer); 196 return true; 197 case Format23x: 198 writeOpcode(writer); 199 writer.write(' '); 200 writeFirstRegister(writer); 201 writer.write(", "); 202 writeSecondRegister(writer); 203 writer.write(", "); 204 writeThirdRegister(writer); 205 return true; 206 case Format35c: 207 writeOpcode(writer); 208 writer.write(' '); 209 writeInvokeRegisters(writer); 210 writer.write(", "); 211 writeReference(writer); 212 return true; 213 case Format35mi: 214 writeOpcode(writer); 215 writer.write(' '); 216 writeInvokeRegisters(writer); 217 writer.write(", "); 218 writeInlineIndex(writer); 219 return true; 220 case Format35ms: 221 writeOpcode(writer); 222 writer.write(' '); 223 writeInvokeRegisters(writer); 224 writer.write(", "); 225 writeVtableIndex(writer); 226 return true; 227 case Format3rc: 228 writeOpcode(writer); 229 writer.write(' '); 230 writeInvokeRangeRegisters(writer); 231 writer.write(", "); 232 writeReference(writer); 233 return true; 234 case Format3rmi: 235 writeOpcode(writer); 236 writer.write(' '); 237 writeInvokeRangeRegisters(writer); 238 writer.write(", "); 239 writeInlineIndex(writer); 240 return true; 241 case Format3rms: 242 writeOpcode(writer); 243 writer.write(' '); 244 writeInvokeRangeRegisters(writer); 245 writer.write(", "); 246 writeVtableIndex(writer); 247 return true; 248 } 249 assert false; 250 return false; 251 } 252 253 protected void writeOpcode(IndentingWriter writer) throws IOException { 254 writer.write(instruction.getOpcode().name); 255 } 256 257 protected void writeTargetLabel(IndentingWriter writer) throws IOException { 258 //this method is overridden by OffsetInstructionMethodItem, and should only be called for the formats that 259 //have a target 260 throw new RuntimeException(); 261 } 262 263 protected void writeRegister(IndentingWriter writer, int registerNumber) throws IOException { 264 methodDef.registerFormatter.writeTo(writer, registerNumber); 265 } 266 267 protected void writeFirstRegister(IndentingWriter writer) throws IOException { 268 writeRegister(writer, ((OneRegisterInstruction)instruction).getRegisterA()); 269 } 270 271 protected void writeSecondRegister(IndentingWriter writer) throws IOException { 272 writeRegister(writer, ((TwoRegisterInstruction)instruction).getRegisterB()); 273 } 274 275 protected void writeThirdRegister(IndentingWriter writer) throws IOException { 276 writeRegister(writer, ((ThreeRegisterInstruction) instruction).getRegisterC()); 277 } 278 279 protected void writeInvokeRegisters(IndentingWriter writer) throws IOException { 280 FiveRegisterInstruction instruction = (FiveRegisterInstruction)this.instruction; 281 final int regCount = instruction.getRegisterCount(); 282 283 writer.write('{'); 284 switch (regCount) { 285 case 1: 286 writeRegister(writer, instruction.getRegisterC()); 287 break; 288 case 2: 289 writeRegister(writer, instruction.getRegisterC()); 290 writer.write(", "); 291 writeRegister(writer, instruction.getRegisterD()); 292 break; 293 case 3: 294 writeRegister(writer, instruction.getRegisterC()); 295 writer.write(", "); 296 writeRegister(writer, instruction.getRegisterD()); 297 writer.write(", "); 298 writeRegister(writer, instruction.getRegisterE()); 299 break; 300 case 4: 301 writeRegister(writer, instruction.getRegisterC()); 302 writer.write(", "); 303 writeRegister(writer, instruction.getRegisterD()); 304 writer.write(", "); 305 writeRegister(writer, instruction.getRegisterE()); 306 writer.write(", "); 307 writeRegister(writer, instruction.getRegisterF()); 308 break; 309 case 5: 310 writeRegister(writer, instruction.getRegisterC()); 311 writer.write(", "); 312 writeRegister(writer, instruction.getRegisterD()); 313 writer.write(", "); 314 writeRegister(writer, instruction.getRegisterE()); 315 writer.write(", "); 316 writeRegister(writer, instruction.getRegisterF()); 317 writer.write(", "); 318 writeRegister(writer, instruction.getRegisterG()); 319 break; 320 } 321 writer.write('}'); 322 } 323 324 protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException { 325 RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction; 326 327 int regCount = instruction.getRegisterCount(); 328 if (regCount == 0) { 329 writer.write("{}"); 330 } else { 331 int startRegister = instruction.getStartRegister(); 332 methodDef.registerFormatter.writeRegisterRange(writer, startRegister, startRegister+regCount-1); 333 } 334 } 335 336 protected void writeLiteral(IndentingWriter writer) throws IOException { 337 LongRenderer.writeSignedIntOrLongTo(writer, ((WideLiteralInstruction)instruction).getWideLiteral()); 338 } 339 340 341 protected void writeFieldOffset(IndentingWriter writer) throws IOException { 342 writer.write("field@0x"); 343 writer.printUnsignedLongAsHex(((FieldOffsetInstruction)instruction).getFieldOffset()); 344 } 345 346 protected void writeInlineIndex(IndentingWriter writer) throws IOException { 347 writer.write("inline@"); 348 writer.printSignedIntAsDec(((InlineIndexInstruction)instruction).getInlineIndex()); 349 } 350 351 protected void writeVtableIndex(IndentingWriter writer) throws IOException { 352 writer.write("vtable@"); 353 writer.printSignedIntAsDec(((VtableIndexInstruction)instruction).getVtableIndex()); 354 } 355 356 protected void writeReference(IndentingWriter writer) throws IOException { 357 try { 358 ReferenceFormatter.writeReference(writer, instruction.getOpcode().referenceType, 359 ((ReferenceInstruction)instruction).getReference()); 360 } catch (InvalidItemIndex ex) { 361 writer.write(ReferenceType.toString(instruction.getOpcode().referenceType)); 362 writer.write("@"); 363 writer.printSignedIntAsDec(ex.getInvalidIndex()); 364 } 365 } 366 367 protected void writeVerificationErrorType(IndentingWriter writer) throws IOException { 368 int verificationError = ((Instruction20bc)instruction).getVerificationError(); 369 writer.write(VerificationError.getVerificationErrorName(verificationError)); 370 } 371} 372