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