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