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