InstructionMethodItem.java revision 4af666e4a6dbcff1a68ebc3bc64fe813decb5920
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.MethodItem; 32import org.jf.baksmali.Adaptors.ReferenceFormatter; 33import org.jf.baksmali.Adaptors.RegisterFormatter; 34import org.jf.dexlib.Code.Format.Instruction20bc; 35import org.jf.dexlib.Code.Format.UnknownInstruction; 36import org.jf.util.IndentingWriter; 37import org.jf.baksmali.Renderers.LongRenderer; 38import org.jf.dexlib.Code.*; 39import org.jf.dexlib.CodeItem; 40import org.jf.dexlib.Item; 41 42import java.io.IOException; 43 44public class InstructionMethodItem<T extends Instruction> extends MethodItem { 45 protected final CodeItem codeItem; 46 protected final T instruction; 47 48 public InstructionMethodItem(CodeItem codeItem, int codeAddress, T instruction) { 49 super(codeAddress); 50 this.codeItem = codeItem; 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.getFormat()) { 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 Format21h: 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.opcode.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 RegisterFormatter.writeTo(writer, codeItem, registerNumber); 246 } 247 248 protected void writeFirstRegister(IndentingWriter writer) throws IOException { 249 writeRegister(writer, ((SingleRegisterInstruction)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.getRegCount(); 263 264 writer.write('{'); 265 switch (regCount) { 266 case 1: 267 writeRegister(writer, instruction.getRegisterD()); 268 break; 269 case 2: 270 writeRegister(writer, instruction.getRegisterD()); 271 writer.write(", "); 272 writeRegister(writer, instruction.getRegisterE()); 273 break; 274 case 3: 275 writeRegister(writer, instruction.getRegisterD()); 276 writer.write(", "); 277 writeRegister(writer, instruction.getRegisterE()); 278 writer.write(", "); 279 writeRegister(writer, instruction.getRegisterF()); 280 break; 281 case 4: 282 writeRegister(writer, instruction.getRegisterD()); 283 writer.write(", "); 284 writeRegister(writer, instruction.getRegisterE()); 285 writer.write(", "); 286 writeRegister(writer, instruction.getRegisterF()); 287 writer.write(", "); 288 writeRegister(writer, instruction.getRegisterG()); 289 break; 290 case 5: 291 writeRegister(writer, instruction.getRegisterD()); 292 writer.write(", "); 293 writeRegister(writer, instruction.getRegisterE()); 294 writer.write(", "); 295 writeRegister(writer, instruction.getRegisterF()); 296 writer.write(", "); 297 writeRegister(writer, instruction.getRegisterG()); 298 writer.write(", "); 299 writeRegister(writer, instruction.getRegisterA()); 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.getRegCount(); 309 if (regCount == 0) { 310 writer.write("{}"); 311 } else { 312 int startRegister = instruction.getStartRegister(); 313 RegisterFormatter.writeRegisterRange(writer, codeItem, startRegister, startRegister+regCount-1); 314 } 315 } 316 317 protected void writeLiteral(IndentingWriter writer) throws IOException { 318 LongRenderer.writeSignedIntOrLongTo(writer, ((LiteralInstruction)instruction).getLiteral()); 319 } 320 321 protected void writeFieldOffset(IndentingWriter writer) throws IOException { 322 writer.write("field@0x"); 323 writer.printUnsignedLongAsHex(((OdexedFieldAccess) instruction).getFieldOffset()); 324 } 325 326 protected void writeInlineIndex(IndentingWriter writer) throws IOException { 327 writer.write("inline@0x"); 328 writer.printUnsignedLongAsHex(((OdexedInvokeInline) instruction).getInlineIndex()); 329 } 330 331 protected void writeVtableIndex(IndentingWriter writer) throws IOException { 332 writer.write("vtable@0x"); 333 writer.printUnsignedLongAsHex(((OdexedInvokeVirtual) instruction).getVtableIndex()); 334 } 335 336 protected void writeReference(IndentingWriter writer) throws IOException { 337 Item item = ((InstructionWithReference)instruction).getReferencedItem(); 338 ReferenceFormatter.writeReference(writer, item); 339 } 340 341 protected void writeVerificationErrorType(IndentingWriter writer) throws IOException { 342 VerificationErrorType validationErrorType = ((Instruction20bc)instruction).getValidationErrorType(); 343 writer.write(validationErrorType.getName()); 344 } 345} 346