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