PreInstructionRegisterInfoMethodItem.java revision 754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0
1/* 2 * [The "BSD licence"] 3 * Copyright (c) 2010 Ben Gruver 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; 30 31import org.jf.util.IndentingWriter; 32import org.jf.baksmali.baksmali; 33import org.jf.baksmali.main; 34import org.jf.dexlib.ClassDataItem; 35import org.jf.dexlib.Code.Analysis.AnalyzedInstruction; 36import org.jf.dexlib.Code.Analysis.MethodAnalyzer; 37import org.jf.dexlib.Code.Analysis.RegisterType; 38import org.jf.dexlib.Code.*; 39import org.jf.dexlib.Util.AccessFlags; 40 41import java.io.IOException; 42import java.util.BitSet; 43 44//TODO: uncomment 45/*public class PreInstructionRegisterInfoMethodItem extends MethodItem { 46 private final AnalyzedInstruction analyzedInstruction; 47 private final MethodAnalyzer methodAnalyzer; 48 49 public PreInstructionRegisterInfoMethodItem(AnalyzedInstruction analyzedInstruction, MethodAnalyzer methodAnalyzer, 50 int codeAddress) { 51 super(codeAddress); 52 this.analyzedInstruction = analyzedInstruction; 53 this.methodAnalyzer = methodAnalyzer; 54 } 55 56 @Override 57 public double getSortOrder() { 58 return 99.9; 59 } 60 61 @Override 62 public boolean writeTo(IndentingWriter writer) throws IOException { 63 int registerInfo = baksmali.registerInfo; 64 int registerCount = analyzedInstruction.getRegisterCount(); 65 BitSet registers = new BitSet(registerCount); 66 67 if ((registerInfo & main.ALL) != 0) { 68 registers.set(0, registerCount); 69 } else { 70 if ((registerInfo & main.ALLPRE) != 0) { 71 registers.set(0, registerCount); 72 } else { 73 if ((registerInfo & main.ARGS) != 0) { 74 addArgsRegs(registers); 75 } 76 if ((registerInfo & main.MERGE) != 0) { 77 addMergeRegs(registers, registerCount); 78 } else if ((registerInfo & main.FULLMERGE) != 0 && 79 (analyzedInstruction.isBeginningInstruction())) { 80 addParamRegs(registers, registerCount); 81 } 82 } 83 } 84 85 boolean printedSomething = false; 86 if ((registerInfo & main.FULLMERGE) != 0) { 87 printedSomething = writeFullMergeRegs(writer, registers, registerCount); 88 } 89 90 printedSomething |= writeRegisterInfo(writer, registers, printedSomething); 91 92 return printedSomething; 93 } 94 95 private void addArgsRegs(BitSet registers) { 96 if (analyzedInstruction.getInstruction() instanceof RegisterRangeInstruction) { 97 RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.getInstruction(); 98 99 registers.set(instruction.getStartRegister(), 100 instruction.getStartRegister() + instruction.getRegCount()); 101 } else if (analyzedInstruction.getInstruction() instanceof FiveRegisterInstruction) { 102 FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.getInstruction(); 103 int regCount = instruction.getRegCount(); 104 switch (regCount) { 105 case 5: 106 registers.set(instruction.getRegisterA()); 107 //fall through 108 case 4: 109 registers.set(instruction.getRegisterG()); 110 //fall through 111 case 3: 112 registers.set(instruction.getRegisterF()); 113 //fall through 114 case 2: 115 registers.set(instruction.getRegisterE()); 116 //fall through 117 case 1: 118 registers.set(instruction.getRegisterD()); 119 } 120 } else if (analyzedInstruction.getInstruction() instanceof ThreeRegisterInstruction) { 121 ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.getInstruction(); 122 registers.set(instruction.getRegisterA()); 123 registers.set(instruction.getRegisterB()); 124 registers.set(instruction.getRegisterC()); 125 } else if (analyzedInstruction.getInstruction() instanceof TwoRegisterInstruction) { 126 TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.getInstruction(); 127 registers.set(instruction.getRegisterA()); 128 registers.set(instruction.getRegisterB()); 129 } else if (analyzedInstruction.getInstruction() instanceof SingleRegisterInstruction) { 130 SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.getInstruction(); 131 registers.set(instruction.getRegisterA()); 132 } 133 } 134 135 private void addMergeRegs(BitSet registers, int registerCount) { 136 if (analyzedInstruction.isBeginningInstruction()) { 137 addParamRegs(registers, registerCount); 138 } 139 140 if (analyzedInstruction.getPredecessorCount() <= 1) { 141 //in the common case of an instruction that only has a single predecessor which is the previous 142 //instruction, the pre-instruction registers will always match the previous instruction's 143 //post-instruction registers 144 return; 145 } 146 147 for (int registerNum=0; registerNum<registerCount; registerNum++) { 148 RegisterType mergedRegisterType = analyzedInstruction.getPreInstructionRegisterType(registerNum); 149 150 for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) { 151 if (predecessor.getPostInstructionRegisterType(registerNum) != mergedRegisterType) { 152 registers.set(registerNum); 153 continue; 154 } 155 } 156 } 157 } 158 159 private void addParamRegs(BitSet registers, int registerCount) { 160 ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod(); 161 int parameterRegisterCount = encodedMethod.method.getPrototype().getParameterRegisterCount(); 162 if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) { 163 parameterRegisterCount++; 164 } 165 166 registers.set(registerCount-parameterRegisterCount, registerCount); 167 } 168 169 private boolean writeFullMergeRegs(IndentingWriter writer, BitSet registers, int registerCount) 170 throws IOException { 171 if (analyzedInstruction.getPredecessorCount() <= 1) { 172 return false; 173 } 174 175 ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod(); 176 177 boolean firstRegister = true; 178 179 for (int registerNum=0; registerNum<registerCount; registerNum++) { 180 RegisterType mergedRegisterType = analyzedInstruction.getPreInstructionRegisterType(registerNum); 181 boolean addRegister = false; 182 183 for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) { 184 RegisterType predecessorRegisterType = predecessor.getPostInstructionRegisterType(registerNum); 185 if (predecessorRegisterType.category != RegisterType.Category.Unknown && 186 predecessorRegisterType != mergedRegisterType) { 187 188 addRegister = true; 189 break; 190 } 191 } 192 193 if (!addRegister) { 194 continue; 195 } 196 197 if (firstRegister) { 198 firstRegister = false; 199 } else { 200 writer.write('\n'); 201 } 202 203 writer.write('#'); 204 RegisterFormatter.writeTo(writer, encodedMethod.codeItem, registerNum); 205 writer.write('='); 206 analyzedInstruction.getPreInstructionRegisterType(registerNum).writeTo(writer); 207 writer.write(":merge{"); 208 209 boolean first = true; 210 211 for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) { 212 RegisterType predecessorRegisterType = predecessor.getPostInstructionRegisterType(registerNum); 213 214 if (!first) { 215 writer.write(','); 216 } 217 218 if (predecessor.getInstructionIndex() == -1) { 219 //the fake "StartOfMethod" instruction 220 writer.write("Start:"); 221 } else { 222 writer.write("0x"); 223 writer.printUnsignedLongAsHex(methodAnalyzer.getInstructionAddress(predecessor)); 224 writer.write(':'); 225 } 226 predecessorRegisterType.writeTo(writer); 227 228 first = false; 229 } 230 writer.write('}'); 231 232 registers.clear(registerNum); 233 } 234 return !firstRegister; 235 } 236 237 private boolean writeRegisterInfo(IndentingWriter writer, BitSet registers, 238 boolean addNewline) throws IOException { 239 ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod(); 240 241 int registerNum = registers.nextSetBit(0); 242 if (registerNum < 0) { 243 return false; 244 } 245 246 if (addNewline) { 247 writer.write('\n'); 248 } 249 writer.write('#'); 250 for (; registerNum >= 0; registerNum = registers.nextSetBit(registerNum + 1)) { 251 252 RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(registerNum); 253 254 RegisterFormatter.writeTo(writer, encodedMethod.codeItem, registerNum); 255 writer.write('='); 256 257 if (registerType == null) { 258 writer.write("null"); 259 } else { 260 registerType.writeTo(writer); 261 } 262 writer.write(';'); 263 } 264 return true; 265 } 266}*/ 267