InstructionMethodItem.java revision a9ce1cf3ecff57b00c14bf86b2c688823c918a05
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 case Format41c: 110 writeOpcode(writer); 111 writer.write(' '); 112 writeFirstRegister(writer); 113 writer.write(", "); 114 writeReference(writer); 115 return true; 116 case Format21h: 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 case Format52c: 146 writeOpcode(writer); 147 writer.write(' '); 148 writeFirstRegister(writer); 149 writer.write(", "); 150 writeSecondRegister(writer); 151 writer.write(", "); 152 writeReference(writer); 153 return true; 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 case Format35mi: 197 writeOpcode(writer); 198 writer.write(' '); 199 writeInvokeRegisters(writer); 200 writer.write(", "); 201 writeInlineIndex(writer); 202 return true; 203 case Format35ms: 204 writeOpcode(writer); 205 writer.write(' '); 206 writeInvokeRegisters(writer); 207 writer.write(", "); 208 writeVtableIndex(writer); 209 return true; 210 case Format3rc: 211 case Format5rc: 212 writeOpcode(writer); 213 writer.write(' '); 214 writeInvokeRangeRegisters(writer); 215 writer.write(", "); 216 writeReference(writer); 217 return true; 218 case Format3rmi: 219 writeOpcode(writer); 220 writer.write(' '); 221 writeInvokeRangeRegisters(writer); 222 writer.write(", "); 223 writeInlineIndex(writer); 224 return true; 225 case Format3rms: 226 writeOpcode(writer); 227 writer.write(' '); 228 writeInvokeRangeRegisters(writer); 229 writer.write(", "); 230 writeVtableIndex(writer); 231 return true; 232 } 233 assert false; 234 return false; 235 } 236 237 protected void writeOpcode(IndentingWriter writer) throws IOException { 238 writer.write(instruction.opcode.name); 239 } 240 241 protected void writeTargetLabel(IndentingWriter writer) throws IOException { 242 //this method is overrided by OffsetInstructionMethodItem, and should only be called for the formats that 243 //have a target 244 throw new RuntimeException(); 245 } 246 247 protected void writeRegister(IndentingWriter writer, int registerNumber) throws IOException { 248 RegisterFormatter.writeTo(writer, codeItem, registerNumber); 249 } 250 251 protected void writeFirstRegister(IndentingWriter writer) throws IOException { 252 writeRegister(writer, ((SingleRegisterInstruction)instruction).getRegisterA()); 253 } 254 255 protected void writeSecondRegister(IndentingWriter writer) throws IOException { 256 writeRegister(writer, ((TwoRegisterInstruction)instruction).getRegisterB()); 257 } 258 259 protected void writeThirdRegister(IndentingWriter writer) throws IOException { 260 writeRegister(writer, ((ThreeRegisterInstruction)instruction).getRegisterC()); 261 } 262 263 protected void writeInvokeRegisters(IndentingWriter writer) throws IOException { 264 FiveRegisterInstruction instruction = (FiveRegisterInstruction)this.instruction; 265 final int regCount = instruction.getRegCount(); 266 267 writer.write('{'); 268 switch (regCount) { 269 case 1: 270 writeRegister(writer, instruction.getRegisterD()); 271 break; 272 case 2: 273 writeRegister(writer, instruction.getRegisterD()); 274 writer.write(", "); 275 writeRegister(writer, instruction.getRegisterE()); 276 break; 277 case 3: 278 writeRegister(writer, instruction.getRegisterD()); 279 writer.write(", "); 280 writeRegister(writer, instruction.getRegisterE()); 281 writer.write(", "); 282 writeRegister(writer, instruction.getRegisterF()); 283 break; 284 case 4: 285 writeRegister(writer, instruction.getRegisterD()); 286 writer.write(", "); 287 writeRegister(writer, instruction.getRegisterE()); 288 writer.write(", "); 289 writeRegister(writer, instruction.getRegisterF()); 290 writer.write(", "); 291 writeRegister(writer, instruction.getRegisterG()); 292 break; 293 case 5: 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 writer.write(", "); 302 writeRegister(writer, instruction.getRegisterA()); 303 break; 304 } 305 writer.write('}'); 306 } 307 308 protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException { 309 RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction; 310 311 int regCount = instruction.getRegCount(); 312 if (regCount == 0) { 313 writer.write("{}"); 314 } else { 315 int startRegister = instruction.getStartRegister(); 316 RegisterFormatter.writeRegisterRange(writer, codeItem, startRegister, startRegister+regCount-1); 317 } 318 } 319 320 protected void writeLiteral(IndentingWriter writer) throws IOException { 321 LongRenderer.writeSignedIntOrLongTo(writer, ((LiteralInstruction)instruction).getLiteral()); 322 } 323 324 protected void writeFieldOffset(IndentingWriter writer) throws IOException { 325 writer.write("field@0x"); 326 writer.printUnsignedLongAsHex(((OdexedFieldAccess) instruction).getFieldOffset()); 327 } 328 329 protected void writeInlineIndex(IndentingWriter writer) throws IOException { 330 writer.write("inline@0x"); 331 writer.printUnsignedLongAsHex(((OdexedInvokeInline) instruction).getInlineIndex()); 332 } 333 334 protected void writeVtableIndex(IndentingWriter writer) throws IOException { 335 writer.write("vtable@0x"); 336 writer.printUnsignedLongAsHex(((OdexedInvokeVirtual) instruction).getVtableIndex()); 337 } 338 339 protected void writeReference(IndentingWriter writer) throws IOException { 340 Item item = ((InstructionWithReference)instruction).getReferencedItem(); 341 ReferenceFormatter.writeReference(writer, item); 342 } 343 344 protected void writeVerificationErrorType(IndentingWriter writer) throws IOException { 345 VerificationErrorType validationErrorType = ((Instruction20bc)instruction).getValidationErrorType(); 346 writer.write(validationErrorType.getName()); 347 } 348} 349