| 1 21 package proguard.classfile.editor; 22 23 import proguard.classfile.instruction.*; 24 import proguard.classfile.instruction.visitor.InstructionVisitor; 25 import proguard.classfile.attribute.visitor.AttributeVisitor; 26 import proguard.classfile.attribute.CodeAttribute; 27 import proguard.classfile.*; 28 import proguard.classfile.util.SimplifiedVisitor; 29 30 38 public class InstructionWriter 39 extends SimplifiedVisitor 40 implements InstructionVisitor, 41 AttributeVisitor 42 { 43 private int codeLength; 44 45 private CodeAttributeEditor codeAttributeEditor; 46 47 48 52 public void reset(int codeLength) 53 { 54 this.codeLength = codeLength; 55 56 if (codeAttributeEditor != null) 58 { 59 codeAttributeEditor.reset(codeLength); 60 } 61 } 62 63 64 66 public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) 67 { 68 simpleInstruction.write(codeAttribute, offset); 71 } 72 73 74 public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 75 { 76 try 77 { 78 constantInstruction.write(codeAttribute, offset); 80 } 81 catch (IllegalArgumentException exception) 82 { 83 Instruction replacementInstruction = 85 new ConstantInstruction(constantInstruction.opcode, 86 constantInstruction.constantIndex, 87 constantInstruction.constant).shrink(); 88 89 replaceInstruction(offset, replacementInstruction); 90 91 constantInstruction.constantIndex = 0; 93 constantInstruction.constant = 0; 94 constantInstruction.write(codeAttribute, offset); 95 } 96 } 97 98 99 public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) 100 { 101 try 102 { 103 variableInstruction.write(codeAttribute, offset); 105 } 106 catch (IllegalArgumentException exception) 107 { 108 Instruction replacementInstruction = 110 new VariableInstruction(variableInstruction.opcode, 111 variableInstruction.variableIndex, 112 variableInstruction.constant).shrink(); 113 114 replaceInstruction(offset, replacementInstruction); 115 116 variableInstruction.variableIndex = 0; 118 variableInstruction.constant = 0; 119 variableInstruction.write(codeAttribute, offset); 120 } 121 } 122 123 124 public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) 125 { 126 try 127 { 128 branchInstruction.write(codeAttribute, offset); 130 } 131 catch (IllegalArgumentException exception) 132 { 133 Instruction replacementInstruction = 135 new BranchInstruction(InstructionConstants.OP_GOTO_W, 136 branchInstruction.branchOffset); 137 138 switch (branchInstruction.opcode) 140 { 141 default: 142 { 143 replacementInstruction = 145 new BranchInstruction(branchInstruction.opcode, 146 branchInstruction.branchOffset).shrink(); 147 148 break; 149 } 150 151 case InstructionConstants.OP_IFEQ: 153 case InstructionConstants.OP_IFNE: 154 case InstructionConstants.OP_IFLT: 155 case InstructionConstants.OP_IFGE: 156 case InstructionConstants.OP_IFGT: 157 case InstructionConstants.OP_IFLE: 158 case InstructionConstants.OP_IFICMPEQ: 159 case InstructionConstants.OP_IFICMPNE: 160 case InstructionConstants.OP_IFICMPLT: 161 case InstructionConstants.OP_IFICMPGE: 162 case InstructionConstants.OP_IFICMPGT: 163 case InstructionConstants.OP_IFICMPLE: 164 case InstructionConstants.OP_IFACMPEQ: 165 case InstructionConstants.OP_IFACMPNE: 166 { 167 Instruction complementaryConditionalBranch = 169 new BranchInstruction((byte)(((branchInstruction.opcode+1) ^ 1) - 1), 170 (1+2) + (1+4)); 171 172 insertBeforeInstruction(offset, complementaryConditionalBranch); 173 174 break; 176 } 177 178 case InstructionConstants.OP_IFNULL: 179 case InstructionConstants.OP_IFNONNULL: 180 { 181 Instruction complementaryConditionalBranch = 183 new BranchInstruction((byte)(branchInstruction.opcode ^ 1), 184 (1+2) + (1+4)); 185 186 insertBeforeInstruction(offset, complementaryConditionalBranch); 187 188 break; 190 } 191 } 192 193 replaceInstruction(offset, replacementInstruction); 194 195 branchInstruction.branchOffset = 0; 197 branchInstruction.write(codeAttribute, offset); 198 } 199 } 200 201 202 public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction) 203 { 204 switchInstruction.write(codeAttribute, offset); 207 } 208 209 210 212 public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 213 { 214 if (codeAttributeEditor != null) 216 { 217 codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute); 219 220 codeAttributeEditor = null; 222 } 223 } 224 225 226 228 232 private void insertBeforeInstruction(int instructionOffset, Instruction instruction) 233 { 234 ensureCodeAttributeEditor(); 235 236 codeAttributeEditor.insertBeforeInstruction(instructionOffset, instruction); 238 } 239 240 241 245 private void replaceInstruction(int instructionOffset, Instruction instruction) 246 { 247 ensureCodeAttributeEditor(); 248 249 codeAttributeEditor.replaceInstruction(instructionOffset, instruction); 251 } 252 253 254 258 private void insertAfterInstruction(int instructionOffset, Instruction instruction) 259 { 260 ensureCodeAttributeEditor(); 261 262 codeAttributeEditor.insertAfterInstruction(instructionOffset, instruction); 264 } 265 266 267 270 private void ensureCodeAttributeEditor() 271 { 272 if (codeAttributeEditor == null) 273 { 274 codeAttributeEditor = new CodeAttributeEditor(); 275 codeAttributeEditor.reset(codeLength); 276 } 277 } 278 } 279 | Popular Tags |