InstructionMethodItem.java revision a8e05220c14778d93c97911044ff5124aadbd77c
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.dexlib.Code.Format.UnknownInstruction; 35import org.jf.dexlib2.ReferenceType; 36import org.jf.dexlib2.iface.instruction.*; 37import org.jf.util.IndentingWriter; 38import org.jf.baksmali.Renderers.LongRenderer; 39 40import javax.annotation.Nonnull; 41import java.io.IOException; 42 43public class InstructionMethodItem<T extends Instruction> extends MethodItem { 44 @Nonnull protected final MethodDefinition methodDef; 45 @Nonnull protected final T instruction; 46 47 public InstructionMethodItem(@Nonnull MethodDefinition methodDef, int codeAddress, @Nonnull T instruction) { 48 super(codeAddress); 49 this.methodDef = methodDef; 50 this.instruction = instruction; 51 } 52 53 public double getSortOrder() { 54 //instructions should appear after everything except an "end try" label and .catch directive 55 return 100; 56 } 57 58 @Override 59 public boolean writeTo(IndentingWriter writer) throws IOException { 60 switch (instruction.getOpcode().format) { 61 case Format10t: 62 writeOpcode(writer); 63 writer.write(' '); 64 writeTargetLabel(writer); 65 return true; 66 case Format10x: 67 if (instruction instanceof UnknownInstruction) { 68 writer.write("#unknown opcode: 0x"); 69 writer.printUnsignedLongAsHex(((UnknownInstruction) instruction).getOriginalOpcode() & 0xFFFF); 70 writer.write('\n'); 71 } 72 writeOpcode(writer); 73 return true; 74 case Format11n: 75 writeOpcode(writer); 76 writer.write(' '); 77 writeFirstRegister(writer); 78 writer.write(", "); 79 writeLiteral(writer); 80 return true; 81 case Format11x: 82 writeOpcode(writer); 83 writer.write(' '); 84 writeFirstRegister(writer); 85 return true; 86 case Format12x: 87 writeOpcode(writer); 88 writer.write(' '); 89 writeFirstRegister(writer); 90 writer.write(", "); 91 writeSecondRegister(writer); 92 return true; 93 //TODO: uncomment 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 //TODO: uncomment 154 /*case Format22cs: 155 writeOpcode(writer); 156 writer.write(' '); 157 writeFirstRegister(writer); 158 writer.write(", "); 159 writeSecondRegister(writer); 160 writer.write(", "); 161 writeFieldOffset(writer); 162 return true;*/ 163 case Format22t: 164 writeOpcode(writer); 165 writer.write(' '); 166 writeFirstRegister(writer); 167 writer.write(", "); 168 writeSecondRegister(writer); 169 writer.write(", "); 170 writeTargetLabel(writer); 171 return true; 172 case Format22x: 173 case Format32x: 174 writeOpcode(writer); 175 writer.write(' '); 176 writeFirstRegister(writer); 177 writer.write(", "); 178 writeSecondRegister(writer); 179 return true; 180 case Format23x: 181 writeOpcode(writer); 182 writer.write(' '); 183 writeFirstRegister(writer); 184 writer.write(", "); 185 writeSecondRegister(writer); 186 writer.write(", "); 187 writeThirdRegister(writer); 188 return true; 189 case Format35c: 190 writeOpcode(writer); 191 writer.write(' '); 192 writeInvokeRegisters(writer); 193 writer.write(", "); 194 writeReference(writer); 195 return true; 196 //TODO: uncomment 197 /*case Format35mi: 198 writeOpcode(writer); 199 writer.write(' '); 200 writeInvokeRegisters(writer); 201 writer.write(", "); 202 writeInlineIndex(writer); 203 return true; 204 case Format35ms: 205 writeOpcode(writer); 206 writer.write(' '); 207 writeInvokeRegisters(writer); 208 writer.write(", "); 209 writeVtableIndex(writer); 210 return true;*/ 211 case Format3rc: 212 writeOpcode(writer); 213 writer.write(' '); 214 writeInvokeRangeRegisters(writer); 215 writer.write(", "); 216 writeReference(writer); 217 return true; 218 //TODO: uncomment 219 /*case Format3rmi: 220 writeOpcode(writer); 221 writer.write(' '); 222 writeInvokeRangeRegisters(writer); 223 writer.write(", "); 224 writeInlineIndex(writer); 225 return true; 226 case Format3rms: 227 writeOpcode(writer); 228 writer.write(' '); 229 writeInvokeRangeRegisters(writer); 230 writer.write(", "); 231 writeVtableIndex(writer); 232 return true;*/ 233 } 234 assert false; 235 return false; 236 } 237 238 protected void writeOpcode(IndentingWriter writer) throws IOException { 239 writer.write(instruction.getOpcode().name); 240 } 241 242 protected void writeTargetLabel(IndentingWriter writer) throws IOException { 243 //this method is overrided by OffsetInstructionMethodItem, and should only be called for the formats that 244 //have a target 245 throw new RuntimeException(); 246 } 247 248 protected void writeRegister(IndentingWriter writer, int registerNumber) throws IOException { 249 methodDef.registerFormatter.writeTo(writer, registerNumber); 250 } 251 252 protected void writeFirstRegister(IndentingWriter writer) throws IOException { 253 writeRegister(writer, ((OneRegisterInstruction)instruction).getRegisterA()); 254 } 255 256 protected void writeSecondRegister(IndentingWriter writer) throws IOException { 257 writeRegister(writer, ((TwoRegisterInstruction)instruction).getRegisterB()); 258 } 259 260 protected void writeThirdRegister(IndentingWriter writer) throws IOException { 261 writeRegister(writer, ((ThreeRegisterInstruction) instruction).getRegisterC()); 262 } 263 264 protected void writeInvokeRegisters(IndentingWriter writer) throws IOException { 265 FiveRegisterInstruction instruction = (FiveRegisterInstruction)this.instruction; 266 final int regCount = instruction.getRegisterCount(); 267 268 writer.write('{'); 269 switch (regCount) { 270 case 1: 271 writeRegister(writer, instruction.getRegisterC()); 272 break; 273 case 2: 274 writeRegister(writer, instruction.getRegisterC()); 275 writer.write(", "); 276 writeRegister(writer, instruction.getRegisterD()); 277 break; 278 case 3: 279 writeRegister(writer, instruction.getRegisterC()); 280 writer.write(", "); 281 writeRegister(writer, instruction.getRegisterD()); 282 writer.write(", "); 283 writeRegister(writer, instruction.getRegisterE()); 284 break; 285 case 4: 286 writeRegister(writer, instruction.getRegisterC()); 287 writer.write(", "); 288 writeRegister(writer, instruction.getRegisterD()); 289 writer.write(", "); 290 writeRegister(writer, instruction.getRegisterE()); 291 writer.write(", "); 292 writeRegister(writer, instruction.getRegisterF()); 293 break; 294 case 5: 295 writeRegister(writer, instruction.getRegisterC()); 296 writer.write(", "); 297 writeRegister(writer, instruction.getRegisterD()); 298 writer.write(", "); 299 writeRegister(writer, instruction.getRegisterE()); 300 writer.write(", "); 301 writeRegister(writer, instruction.getRegisterF()); 302 writer.write(", "); 303 writeRegister(writer, instruction.getRegisterG()); 304 break; 305 } 306 writer.write('}'); 307 } 308 309 protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException { 310 RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction; 311 312 int regCount = instruction.getRegisterCount(); 313 if (regCount == 0) { 314 writer.write("{}"); 315 } else { 316 int startRegister = instruction.getStartRegister(); 317 methodDef.registerFormatter.writeRegisterRange(writer, startRegister, startRegister+regCount-1); 318 } 319 } 320 321 protected void writeLiteral(IndentingWriter writer) throws IOException { 322 LongRenderer.writeSignedIntOrLongTo(writer, ((WideLiteralInstruction)instruction).getWideLiteral()); 323 } 324 325 //TODO: uncomment 326 /*protected void writeFieldOffset(IndentingWriter writer) throws IOException { 327 writer.write("field@0x"); 328 writer.printUnsignedLongAsHex(((OdexedFieldAccess) instruction).getFieldOffset()); 329 } 330 331 protected void writeInlineIndex(IndentingWriter writer) throws IOException { 332 writer.write("inline@0x"); 333 writer.printUnsignedLongAsHex(((OdexedInvokeInline) instruction).getInlineIndex()); 334 } 335 336 protected void writeVtableIndex(IndentingWriter writer) throws IOException { 337 writer.write("vtable@0x"); 338 writer.printUnsignedLongAsHex(((OdexedInvokeVirtual) instruction).getVtableIndex()); 339 }*/ 340 341 protected void writeReference(IndentingWriter writer) throws IOException { 342 ReferenceFormatter.writeReference(writer, instruction.getOpcode().referenceType, 343 ((ReferenceInstruction)instruction).getReference()); 344 } 345 346 //TODO: uncomment 347 /*protected void writeVerificationErrorType(IndentingWriter writer) throws IOException { 348 VerificationErrorType validationErrorType = ((Instruction20bc)instruction).getValidationErrorType(); 349 writer.write(validationErrorType.getName()); 350 }*/ 351} 352