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