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