1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/* 2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification 3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of Java bytecode. 4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 52270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) 6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it 8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free 9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option) 10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version. 11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT 13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details. 16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along 18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc., 19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard.classfile.editor; 22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*; 24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.*; 252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.classfile.attribute.annotation.*; 262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.classfile.attribute.annotation.target.*; 272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.classfile.attribute.annotation.target.visitor.*; 282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.classfile.attribute.annotation.visitor.TypeAnnotationVisitor; 29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.preverification.*; 30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.preverification.visitor.*; 31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.visitor.*; 32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.*; 33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.visitor.InstructionVisitor; 34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.SimplifiedVisitor; 35b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport proguard.util.ArrayUtil; 36b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 37b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport java.util.Arrays; 38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/** 40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This AttributeVisitor accumulates specified changes to code, and then applies 41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * these accumulated changes to the code attributes that it visits. 42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune 44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class CodeAttributeEditor 46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends SimplifiedVisitor 47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements AttributeVisitor, 48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionVisitor, 49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ExceptionInfoVisitor, 50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato StackMapFrameVisitor, 51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato VerificationTypeVisitor, 52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato LineNumberInfoVisitor, 53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato LocalVariableInfoVisitor, 542270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom LocalVariableTypeInfoVisitor, 552270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom TypeAnnotationVisitor, 562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom TargetInfoVisitor, 572270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom LocalVariableTargetElementVisitor 58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{ 59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //* 60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private static final boolean DEBUG = false; 61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /*/ 62b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public static boolean DEBUG = false; 63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //*/ 64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 65b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 66b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private final boolean updateFrameSizes; 67b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private final boolean shrinkInstructions; 68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private int codeLength; 70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean modified; 71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean simple; 72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /*private*/public Instruction[] preInsertions = new Instruction[ClassConstants.TYPICAL_CODE_LENGTH]; 74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /*private*/public Instruction[] replacements = new Instruction[ClassConstants.TYPICAL_CODE_LENGTH]; 75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /*private*/public Instruction[] postInsertions = new Instruction[ClassConstants.TYPICAL_CODE_LENGTH]; 76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /*private*/public boolean[] deleted = new boolean[ClassConstants.TYPICAL_CODE_LENGTH]; 77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 78b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private int[] newInstructionOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH]; 79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private int newOffset; 80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean lengthIncreased; 81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private int expectedStackMapFrameOffset; 83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final StackSizeUpdater stackSizeUpdater = new StackSizeUpdater(); 85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final VariableSizeUpdater variableSizeUpdater = new VariableSizeUpdater(); 86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final InstructionWriter instructionWriter = new InstructionWriter(); 87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 89b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 90b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Creates a new CodeAttributeEditor that automatically updates frame 91b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * sizes and shrinks instructions. 92b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public CodeAttributeEditor() 94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 95b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang this(true, true); 96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 99b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 100b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Creates a new CodeAttributeEditor. 101b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * @param updateFrameSizes specifies whether frame sizes of edited code 102b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * should be updated. 103b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * @param shrinkInstructions specifies whether added instructions should 104b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * automatically be shrunk before being written. 105b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 106b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public CodeAttributeEditor(boolean updateFrameSizes, 107b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang boolean shrinkInstructions) 108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 109b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang this.updateFrameSizes = updateFrameSizes; 110b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang this.shrinkInstructions = shrinkInstructions; 111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Resets the accumulated code changes. 116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param codeLength the length of the code that will be edited next. 117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void reset(int codeLength) 119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Try to reuse the previous arrays. 121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (preInsertions.length < codeLength) 122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato preInsertions = new Instruction[codeLength]; 124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replacements = new Instruction[codeLength]; 125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato postInsertions = new Instruction[codeLength]; 126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato deleted = new boolean[codeLength]; 127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else 129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 130b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang Arrays.fill(preInsertions, 0, codeLength, null); 131b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang Arrays.fill(replacements, 0, codeLength, null); 132b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang Arrays.fill(postInsertions, 0, codeLength, null); 133b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang Arrays.fill(deleted, 0, codeLength, false); 134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 136b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang this.codeLength = codeLength; 137b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato modified = false; 139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato simple = true; 140b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 141b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 142b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 143b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 144b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Extends the size of the accumulated code changes. 145b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * @param codeLength the length of the code that will be edited next. 146b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 147b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public void extend(int codeLength) 148b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 149b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Try to reuse the previous arrays. 150b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (preInsertions.length < codeLength) 151b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 152b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang preInsertions = (Instruction[])ArrayUtil.extendArray(preInsertions, codeLength); 153b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang replacements = (Instruction[])ArrayUtil.extendArray(replacements, codeLength); 154b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang postInsertions = (Instruction[])ArrayUtil.extendArray(postInsertions, codeLength); 155b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang deleted = ArrayUtil.extendArray(deleted, codeLength); 156b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 157b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang else 158b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 159b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang Arrays.fill(preInsertions, this.codeLength, codeLength, null); 160b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang Arrays.fill(replacements, this.codeLength, codeLength, null); 161b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang Arrays.fill(postInsertions, this.codeLength, codeLength, null); 162b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang Arrays.fill(deleted, this.codeLength, codeLength, false); 163b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 165b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang this.codeLength = codeLength; 166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Remembers to place the given instruction right before the instruction 171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * at the given offset. 172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instructionOffset the offset of the instruction. 173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instruction the new instruction. 174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void insertBeforeInstruction(int instructionOffset, Instruction instruction) 176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (instructionOffset < 0 || 178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionOffset >= codeLength) 179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]"); 181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 183b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang preInsertions[instructionOffset] = shrinkInstructions ? 184b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang instruction.shrink() : 185b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang instruction; 186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato modified = true; 188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato simple = false; 189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Remembers to place the given instructions right before the instruction 194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * at the given offset. 195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instructionOffset the offset of the instruction. 196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instructions the new instructions. 197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void insertBeforeInstruction(int instructionOffset, Instruction[] instructions) 199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (instructionOffset < 0 || 201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionOffset >= codeLength) 202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]"); 204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 206b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang CompositeInstruction instruction = 207b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang new CompositeInstruction(instructions); 208b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 209b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang preInsertions[instructionOffset] = shrinkInstructions ? 210b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang instruction.shrink() : 211b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang instruction; 212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato modified = true; 214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato simple = false; 215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Remembers to replace the instruction at the given offset by the given 220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * instruction. 221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instructionOffset the offset of the instruction to be replaced. 222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instruction the new instruction. 223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void replaceInstruction(int instructionOffset, Instruction instruction) 225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (instructionOffset < 0 || 227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionOffset >= codeLength) 228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]"); 230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 232b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang replacements[instructionOffset] = shrinkInstructions ? 233b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang instruction.shrink() : 234b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang instruction; 235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato modified = true; 237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Remembers to replace the instruction at the given offset by the given 242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * instructions. 243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instructionOffset the offset of the instruction to be replaced. 244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instructions the new instructions. 245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void replaceInstruction(int instructionOffset, Instruction[] instructions) 247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (instructionOffset < 0 || 249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionOffset >= codeLength) 250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]"); 252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 254b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang CompositeInstruction instruction = 255b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang new CompositeInstruction(instructions); 256b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 257b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang replacements[instructionOffset] = shrinkInstructions ? 258b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang instruction.shrink() : 259b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang instruction; 260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato modified = true; 262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Remembers to place the given instruction right after the instruction 267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * at the given offset. 268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instructionOffset the offset of the instruction. 269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instruction the new instruction. 270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void insertAfterInstruction(int instructionOffset, Instruction instruction) 272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (instructionOffset < 0 || 274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionOffset >= codeLength) 275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]"); 277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 279b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang postInsertions[instructionOffset] = shrinkInstructions ? 280b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang instruction.shrink() : 281b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang instruction; 282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato modified = true; 284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato simple = false; 285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Remembers to place the given instructions right after the instruction 290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * at the given offset. 291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instructionOffset the offset of the instruction. 292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instructions the new instructions. 293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void insertAfterInstruction(int instructionOffset, Instruction[] instructions) 295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (instructionOffset < 0 || 297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionOffset >= codeLength) 298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]"); 300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 302b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang CompositeInstruction instruction = 303b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang new CompositeInstruction(instructions); 304b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 305b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang postInsertions[instructionOffset] = shrinkInstructions ? 306b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang instruction.shrink() : 307b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang instruction; 308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato modified = true; 310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato simple = false; 311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Remembers to delete the instruction at the given offset. 316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instructionOffset the offset of the instruction to be deleted. 317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void deleteInstruction(int instructionOffset) 319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (instructionOffset < 0 || 321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionOffset >= codeLength) 322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]"); 324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 325b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 326b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato deleted[instructionOffset] = true; 327b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 328b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato modified = true; 329b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato simple = false; 330b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 331b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 332b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 333b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 334b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Remembers not to delete the instruction at the given offset. 335b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instructionOffset the offset of the instruction not to be deleted. 336b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 337b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void undeleteInstruction(int instructionOffset) 338b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 339b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (instructionOffset < 0 || 340b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionOffset >= codeLength) 341b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 342b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]"); 343b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 344b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 345b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato deleted[instructionOffset] = false; 346b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 347b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 348b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 349b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 350b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Clears all modifications of the instruction at the given offset. 351b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * @param instructionOffset the offset of the instruction to be deleted. 352b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 353b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public void clearModifications(int instructionOffset) 354b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 355b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (instructionOffset < 0 || 356b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang instructionOffset >= codeLength) 357b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 358b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]"); 359b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 360b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 361b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang preInsertions[instructionOffset] = null; 362b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang replacements[instructionOffset] = null; 363b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang postInsertions[instructionOffset] = null; 364b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang deleted[instructionOffset] = false; 365b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 366b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 367b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 368b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 369b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Returns whether the code has been modified in any way. 370b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 371b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public boolean isModified() 372b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 373b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang return modified; 374b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 375b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 376b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 377b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 378b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns whether the instruction at the given offset has been modified 379b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * in any way. 380b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 381b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public boolean isModified(int instructionOffset) 382b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 383b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return preInsertions[instructionOffset] != null || 384b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replacements[instructionOffset] != null || 385b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato postInsertions[instructionOffset] != null || 386b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato deleted[instructionOffset]; 387b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 388b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 389b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 390b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for AttributeVisitor. 391b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 392b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} 393b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 394b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 395b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 396b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 397b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// DEBUG = 398b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// clazz.getName().equals("abc/Def") && 399b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// method.getName(clazz).equals("abc"); 400b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 401b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // TODO: Remove this when the code has stabilized. 402b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Catch any unexpected exceptions from the actual visiting method. 403b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato try 404b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 405b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Process the code. 406b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato visitCodeAttribute0(clazz, method, codeAttribute); 407b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 408b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato catch (RuntimeException ex) 409b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 410b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println("Unexpected error while editing code:"); 411b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println(" Class = ["+clazz.getName()+"]"); 412b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]"); 413b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")"); 414b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 415b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw ex; 416b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 417b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 418b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 419b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 420b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute) 421b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 422b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Do we have to update the code? 423b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (modified) 424b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 425b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (DEBUG) 426b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 427b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang System.out.println("CodeAttributeEditor: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)); 428b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 429b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 430b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Can we perform a faster simple replacement of instructions? 431b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (canPerformSimpleReplacements(codeAttribute)) 432b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 433b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (DEBUG) 434b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 435b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang System.out.println(" Simple editing"); 436b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 437b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 438b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Simply overwrite the instructions. 439b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang performSimpleReplacements(codeAttribute); 440b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 441b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang else 442b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 443b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (DEBUG) 444b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 445b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang System.out.println(" Full editing"); 446b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 447b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 448b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Move and remap the instructions. 449b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang codeAttribute.u4codeLength = 450b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang updateInstructions(clazz, method, codeAttribute); 451b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 452b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the exception table. 453b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang codeAttribute.exceptionsAccept(clazz, method, this); 454b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 455b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Remove exceptions with empty code blocks. 456b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang codeAttribute.u2exceptionTableLength = 457b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang removeEmptyExceptions(codeAttribute.exceptionTable, 458b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang codeAttribute.u2exceptionTableLength); 4599f606f95f03a75961498803e24bee6799a7c0885Ying Wang 460b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the line number table and the local variable tables. 461b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang codeAttribute.attributesAccept(clazz, method, this); 462b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 463b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 464b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Make sure instructions are widened if necessary. 465b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionWriter.visitCodeAttribute(clazz, method, codeAttribute); 466b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 467b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 468b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the maximum stack size and local variable frame size. 469b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (updateFrameSizes) 470b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 471b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute); 472b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato variableSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute); 473b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 474b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 475b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 476b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 477b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) 478b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 479b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update all stack map entries. 480b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato expectedStackMapFrameOffset = -1; 481b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this); 482b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 483b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 484b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 485b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) 486b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 487b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update all stack map table entries. 488b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato expectedStackMapFrameOffset = 0; 489b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this); 490b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 491b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 492b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 493b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) 494b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 495b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update all line number table entries. 496b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this); 497b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 498b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Remove line numbers with empty code blocks. 499b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato lineNumberTableAttribute.u2lineNumberTableLength = 500b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato removeEmptyLineNumbers(lineNumberTableAttribute.lineNumberTable, 501b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato lineNumberTableAttribute.u2lineNumberTableLength, 502b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttribute.u4codeLength); 503b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 504b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 505b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 506b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) 507b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 508b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update all local variable table entries. 509b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 510b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 511b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 512b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 513b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) 514b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 515b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update all local variable table entries. 516b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); 517b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 518b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 519b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 5202270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute) 5212270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 5222270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this); 5232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 5242270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 5252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 526b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 527b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Checks if it is possible to modifies the given code without having to 528b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * update any offsets. 529b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param codeAttribute the code to be changed. 530b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @return the new code length. 531b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 532b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean canPerformSimpleReplacements(CodeAttribute codeAttribute) 533b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 534b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (!simple) 535b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 536b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return false; 537b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 538b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 539b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato byte[] code = codeAttribute.code; 540b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int codeLength = codeAttribute.u4codeLength; 541b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 542b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Go over all replacement instructions. 543b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int offset = 0; offset < codeLength; offset++) 544b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 545b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Check if the replacement instruction, if any, has a different 546b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // length than the original instruction. 547b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = replacements[offset]; 548b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (replacementInstruction != null && 549b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replacementInstruction.length(offset) != 550b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionFactory.create(code, offset).length(offset)) 551b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 552b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return false; 553b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 554b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 555b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 556b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return true; 557b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 558b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 559b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 560b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 561b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Modifies the given code without updating any offsets. 562b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param codeAttribute the code to be changed. 563b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 564b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void performSimpleReplacements(CodeAttribute codeAttribute) 565b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 566b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int codeLength = codeAttribute.u4codeLength; 567b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 568b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Go over all replacement instructions. 569b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int offset = 0; offset < codeLength; offset++) 570b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 571b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Overwrite the original instruction with the replacement 572b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // instruction if any. 573b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = replacements[offset]; 574b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (replacementInstruction != null) 575b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 576b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replacementInstruction.write(codeAttribute, offset); 577b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 578b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) 579b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 580b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang System.out.println(" Replaced "+replacementInstruction.toString(offset)); 581b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 582b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 583b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 584b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 585b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 586b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 587b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 588b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Modifies the given code based on the previously specified changes. 589b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param clazz the class file of the code to be changed. 590b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param method the method of the code to be changed. 591b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param codeAttribute the code to be changed. 592b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @return the new code length. 593b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 594b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private int updateInstructions(Clazz clazz, 595b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Method method, 596b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato CodeAttribute codeAttribute) 597b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 598b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato byte[] oldCode = codeAttribute.code; 599b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int oldLength = codeAttribute.u4codeLength; 600b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 601b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Make sure there is a sufficiently large instruction offset map. 602b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (newInstructionOffsets.length < oldLength + 1) 603b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 604b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang newInstructionOffsets = new int[oldLength + 1]; 605b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 606b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 607b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Fill out the instruction offset map. 608b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int newLength = mapInstructions(oldCode, 609b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato oldLength); 610b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 611b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Create a new code array if necessary. 612b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (lengthIncreased) 613b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 614b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttribute.code = new byte[newLength]; 615b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 616b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 617b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Prepare for possible widening of instructions. 618b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionWriter.reset(newLength); 619b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 620b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Move the instructions into the new code array. 621b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato moveInstructions(clazz, 622b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato method, 623b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttribute, 624b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato oldCode, 625b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato oldLength); 626b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 627b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // We can return the new length. 628b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return newLength; 629b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 630b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 631b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 632b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 633b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Fills out the instruction offset map for the given code block. 634b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param oldCode the instructions to be moved. 635b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param oldLength the code length. 636b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @return the new code length. 637b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 638b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private int mapInstructions(byte[] oldCode, int oldLength) 639b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 640b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Start mapping instructions at the beginning. 641b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset = 0; 642b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato lengthIncreased = false; 643b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 644b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int oldOffset = 0; 645b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato do 646b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 647b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Get the next instruction. 648b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction = InstructionFactory.create(oldCode, oldOffset); 649b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 650b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Compute the mapping of the instruction. 651b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato mapInstruction(oldOffset, instruction); 652b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 653b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato oldOffset += instruction.length(oldOffset); 654b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 655b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (newOffset > oldOffset) 656b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 657b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato lengthIncreased = true; 658b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 659b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 660b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato while (oldOffset < oldLength); 661b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 662b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Also add an entry for the first offset after the code. 663b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang newInstructionOffsets[oldOffset] = newOffset; 664b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 665b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return newOffset; 666b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 667b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 668b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 669b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 670b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Fills out the instruction offset map for the given instruction. 671b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param oldOffset the instruction's old offset. 672b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instruction the instruction to be moved. 673b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 674b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void mapInstruction(int oldOffset, 675b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction) 676b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 677b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang newInstructionOffsets[oldOffset] = newOffset; 678b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 679b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Account for the pre-inserted instruction, if any. 680b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction preInstruction = preInsertions[oldOffset]; 681b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (preInstruction != null) 682b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 683b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset += preInstruction.length(newOffset); 684b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 685b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 686b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Account for the replacement instruction, or for the current 687b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // instruction, if it shouldn't be deleted. 688b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = replacements[oldOffset]; 689b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (replacementInstruction != null) 690b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 691b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset += replacementInstruction.length(newOffset); 692b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 693b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else if (!deleted[oldOffset]) 694b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 695b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Note that the instruction's length may change at its new offset, 696b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // e.g. if it is a switch instruction. 697b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset += instruction.length(newOffset); 698b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 699b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 700b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Account for the post-inserted instruction, if any. 701b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction postInstruction = postInsertions[oldOffset]; 702b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (postInstruction != null) 703b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 704b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset += postInstruction.length(newOffset); 705b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 706b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 707b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 708b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 709b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 710b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Moves the given code block to the new offsets. 711b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param clazz the class file of the code to be changed. 712b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param method the method of the code to be changed. 713b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param codeAttribute the code to be changed. 714b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param oldCode the original code to be moved. 715b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param oldLength the original code length. 716b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 717b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void moveInstructions(Clazz clazz, 718b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Method method, 719b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato CodeAttribute codeAttribute, 720b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato byte[] oldCode, 721b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int oldLength) 722b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 723b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Start writing instructions at the beginning. 724b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset = 0; 725b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 726b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int oldOffset = 0; 727b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato do 728b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 729b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Get the next instruction. 730b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction = InstructionFactory.create(oldCode, oldOffset); 731b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 732b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Move the instruction to its new offset. 733b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato moveInstruction(clazz, 734b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato method, 735b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttribute, 736b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato oldOffset, 737b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction); 738b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 739b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato oldOffset += instruction.length(oldOffset); 740b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 741b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato while (oldOffset < oldLength); 742b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 743b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 744b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 745b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 746b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Moves the given instruction to its new offset. 747b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param clazz the class file of the code to be changed. 748b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param method the method of the code to be changed. 749b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param codeAttribute the code to be changed. 750b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param oldOffset the original instruction offset. 751b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param instruction the original instruction. 752b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 753b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void moveInstruction(Clazz clazz, 754b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Method method, 755b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato CodeAttribute codeAttribute, 756b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int oldOffset, 757b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction) 758b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 759b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update and insert the pre-inserted instruction, if any. 760b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction preInstruction = preInsertions[oldOffset]; 761b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (preInstruction != null) 762b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 763b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) 764b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 765b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang System.out.println(" Pre-inserted ["+oldOffset+"] -> "+preInstruction.toString(newOffset)); 766b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 767b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 768b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the instruction. 769b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato preInstruction.accept(clazz, method, codeAttribute, oldOffset, this); 770b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 771b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 772b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update and insert the replacement instruction, or the current 773b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // instruction, if it shouldn't be deleted. 774b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = replacements[oldOffset]; 775b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (replacementInstruction != null) 776b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 777b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) 778b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 779b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang System.out.println(" Replaced ["+oldOffset+"] -> "+replacementInstruction.toString(newOffset)); 780b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 781b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 782b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the instruction. 783b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replacementInstruction.accept(clazz, method, codeAttribute, oldOffset, this); 784b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 785b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else if (!deleted[oldOffset]) 786b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 787b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) 788b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 789b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang System.out.println(" Copied ["+oldOffset+"] -> "+instruction.toString(newOffset)); 790b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 791b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 792b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the instruction. 793b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction.accept(clazz, method, codeAttribute, oldOffset, this); 794b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 795b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 796b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update and insert the post-inserted instruction, if any. 797b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction postInstruction = postInsertions[oldOffset]; 798b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (postInstruction != null) 799b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 800b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) 801b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 802b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang System.out.println(" Post-inserted ["+oldOffset+"] -> "+postInstruction.toString(newOffset)); 803b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 804b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 805b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the instruction. 806b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato postInstruction.accept(clazz, method, codeAttribute, oldOffset, this); 807b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 808b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 809b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 810b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 811b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for InstructionVisitor. 812b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 813b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) 814b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 815b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Write out the instruction. 816b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionWriter.visitSimpleInstruction(clazz, 817b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato method, 818b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttribute, 819b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset, 820b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato simpleInstruction); 821b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 822b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset += simpleInstruction.length(newOffset); 823b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 824b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 825b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 826b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 827b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 828b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Write out the instruction. 829b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionWriter.visitConstantInstruction(clazz, 830b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato method, 831b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttribute, 832b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset, 833b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato constantInstruction); 834b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 835b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset += constantInstruction.length(newOffset); 836b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 837b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 838b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 839b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) 840b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 841b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Write out the instruction. 842b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionWriter.visitVariableInstruction(clazz, 843b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato method, 844b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttribute, 845b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset, 846b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato variableInstruction); 847b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 848b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset += variableInstruction.length(newOffset); 849b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 850b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 851b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 852b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) 853b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 8542270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Update the branch offset, relative to the precise new offset. 8552270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom branchInstruction.branchOffset = 8562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newBranchOffset(offset, branchInstruction.branchOffset, newOffset); 857b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 858b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Write out the instruction. 859b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionWriter.visitBranchInstruction(clazz, 860b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato method, 861b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttribute, 862b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset, 863b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato branchInstruction); 864b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 865b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset += branchInstruction.length(newOffset); 866b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 867b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 868b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 869b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction) 870b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 8712270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Update the default jump offset, relative to the precise new offset. 8722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom tableSwitchInstruction.defaultOffset = 8732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newBranchOffset(offset, tableSwitchInstruction.defaultOffset, newOffset); 874b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 8752270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Update the jump offsets, relative to the precise new offset. 876b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang newJumpOffsets(offset, 8772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom tableSwitchInstruction.jumpOffsets, 8782270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newOffset); 879b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 880b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Write out the instruction. 881b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionWriter.visitTableSwitchInstruction(clazz, 882b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato method, 883b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttribute, 884b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset, 885b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato tableSwitchInstruction); 886b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 887b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset += tableSwitchInstruction.length(newOffset); 888b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 889b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 890b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 891b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction) 892b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 8932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Update the default jump offset, relative to the precise new offset. 8942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom lookUpSwitchInstruction.defaultOffset = 8952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newBranchOffset(offset, lookUpSwitchInstruction.defaultOffset, newOffset); 896b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 8972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Update the jump offsets, relative to the precise new offset. 898b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang newJumpOffsets(offset, 8992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom lookUpSwitchInstruction.jumpOffsets, 9002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newOffset); 901b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 902b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Write out the instruction. 903b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructionWriter.visitLookUpSwitchInstruction(clazz, 904b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato method, 905b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttribute, 906b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset, 907b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato lookUpSwitchInstruction); 908b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 909b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset += lookUpSwitchInstruction.length(newOffset); 910b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 911b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 912b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 913b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for ExceptionInfoVisitor. 914b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 915b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) 916b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 9172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Update the code offsets. Note that the instruction offset map also 9182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // has an entry for the first offset after the code, for u2endPC. 919b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang exceptionInfo.u2startPC = newInstructionOffset(exceptionInfo.u2startPC); 920b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang exceptionInfo.u2endPC = newInstructionOffset(exceptionInfo.u2endPC); 921b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang exceptionInfo.u2handlerPC = newInstructionOffset(exceptionInfo.u2handlerPC); 922b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 923b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 924b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 925b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for StackMapFrameVisitor. 926b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 927b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) 928b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 929b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the stack map frame offset. 930b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang int stackMapFrameOffset = newInstructionOffset(offset); 931b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 932b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offsetDelta = stackMapFrameOffset; 933b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 934b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Compute the offset delta if the frame is part of a stack map frame 935b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // table (for JDK 6.0) instead of a stack map (for Java Micro Edition). 936b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (expectedStackMapFrameOffset >= 0) 937b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 938b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offsetDelta -= expectedStackMapFrameOffset; 939b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 940b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato expectedStackMapFrameOffset = stackMapFrameOffset + 1; 941b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 942b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 943b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato stackMapFrame.u2offsetDelta = offsetDelta; 944b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 945b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 946b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 947b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame) 948b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 949b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the stack map frame offset. 950b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato visitAnyStackMapFrame(clazz, method, codeAttribute, offset, sameOneFrame); 951b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 952b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the verification type offset. 953b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this); 954b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 955b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 956b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 957b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame) 958b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 959b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the stack map frame offset. 960b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato visitAnyStackMapFrame(clazz, method, codeAttribute, offset, moreZeroFrame); 961b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 962b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the verification type offsets. 963b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this); 964b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 965b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 966b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 967b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame) 968b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 969b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the stack map frame offset. 970b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato visitAnyStackMapFrame(clazz, method, codeAttribute, offset, fullFrame); 971b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 972b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the verification type offsets. 973b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this); 974b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato fullFrame.stackAccept(clazz, method, codeAttribute, offset, this); 975b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 976b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 977b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 978b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for VerificationTypeVisitor. 979b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 980b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {} 981b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 982b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 983b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType) 984b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 985b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the offset of the 'new' instruction. 986b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang uninitializedType.u2newInstructionOffset = newInstructionOffset(uninitializedType.u2newInstructionOffset); 987b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 988b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 989b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 990b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for LineNumberInfoVisitor. 991b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 992b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo) 993b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 994b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the code offset. 995b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang lineNumberInfo.u2startPC = newInstructionOffset(lineNumberInfo.u2startPC); 996b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 997b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 998b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 999b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for LocalVariableInfoVisitor. 1000b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1001b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) 1002b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1003b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the code offset and length. 10042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Be careful to update the length first. 10052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom localVariableInfo.u2length = newBranchOffset(localVariableInfo.u2startPC, localVariableInfo.u2length); 10062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom localVariableInfo.u2startPC = newInstructionOffset(localVariableInfo.u2startPC); 1007b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1008b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1009b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1010b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for LocalVariableTypeInfoVisitor. 1011b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1012b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) 1013b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1014b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the code offset and length. 10152270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Be careful to update the length first. 10162270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom localVariableTypeInfo.u2length = newBranchOffset(localVariableTypeInfo.u2startPC, localVariableTypeInfo.u2length); 10172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom localVariableTypeInfo.u2startPC = newInstructionOffset(localVariableTypeInfo.u2startPC); 10182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 10192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10202270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10212270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Implementations for TypeAnnotationVisitor. 10222270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation) 10242270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 10252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Update all local variable targets. 10262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom typeAnnotation.targetInfoAccept(clazz, this); 10272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 10282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Implementations for TargetInfoVisitor. 10312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10322270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom public void visitAnyTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfo targetInfo) {} 10332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1034b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 10352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo) 10362270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 10372270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Update the offsets of the variables. 10382270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this); 10392270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 10402270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10412270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10422270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo) 10432270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 10442270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Update the offset. 10452270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom offsetTargetInfo.u2offset = newInstructionOffset(offsetTargetInfo.u2offset); 10462270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 10472270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10482270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10492270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Implementations for LocalVariableTargetElementVisitor. 10502270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10512270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement) 10522270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 10532270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Update the variable start offset and length. 10542270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Be careful to update the length first. 10552270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom localVariableTargetElement.u2length = newBranchOffset(localVariableTargetElement.u2startPC, localVariableTargetElement.u2length); 10562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom localVariableTargetElement.u2startPC = newInstructionOffset(localVariableTargetElement.u2startPC); 1057b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1058b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1059b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1060b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Small utility methods. 1061b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1062b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 10632270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Updates the given jump offsets for the instruction at the given offset, 10642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * relative to the given new offset. 1065b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 10662270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private void newJumpOffsets(int oldInstructionOffset, 10672270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int[] oldJumpOffsets, 10682270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int newInstructionOffset) 1069b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1070b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang for (int index = 0; index < oldJumpOffsets.length; index++) 1071b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 10722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom oldJumpOffsets[index] = newBranchOffset(oldInstructionOffset, 10732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom oldJumpOffsets[index], 10742270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newInstructionOffset); 1075b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1076b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1077b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1078b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1079b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 1080b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Computes the new branch offset for the instruction at the given offset 10812270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * with the given branch offset, relative to the new instruction (block) 10822270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * offset. 10832270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom */ 10842270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private int newBranchOffset(int oldInstructionOffset, 10852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int oldBranchOffset) 10862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 10872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom return newInstructionOffset(oldInstructionOffset + oldBranchOffset) - 10882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newInstructionOffset(oldInstructionOffset); 10892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 10902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10922270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom /** 10932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Computes the new branch offset for the instruction at the given offset 10942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * with the given branch offset, relative to the given new offset. 1095b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 10962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private int newBranchOffset(int oldInstructionOffset, 10972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int oldBranchOffset, 10982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int newInstructionOffset) 1099b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 11002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom return newInstructionOffset(oldInstructionOffset + oldBranchOffset) - 11012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newInstructionOffset; 1102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 11062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Computes the new instruction offset for the instruction at the given 11072270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * offset. 1108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 1109b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private int newInstructionOffset(int oldInstructionOffset) 1110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1111b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (oldInstructionOffset < 0 || 1112b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang oldInstructionOffset > codeLength) 1113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1114b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang throw new IllegalArgumentException("Invalid instruction offset ["+oldInstructionOffset+"] in code with length ["+codeLength+"]"); 1115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1117b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang return newInstructionOffsets[oldInstructionOffset]; 1118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 1122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns the given list of exceptions, without the ones that have empty 1123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * code blocks. 1124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 1125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private int removeEmptyExceptions(ExceptionInfo[] exceptionInfos, 1126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int exceptionInfoCount) 1127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Overwrite all empty exceptions. 1129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int newIndex = 0; 1130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int index = 0; index < exceptionInfoCount; index++) 1131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ExceptionInfo exceptionInfo = exceptionInfos[index]; 1133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (exceptionInfo.u2startPC < exceptionInfo.u2endPC) 1134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato exceptionInfos[newIndex++] = exceptionInfo; 1136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return newIndex; 1140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 1144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns the given list of line numbers, without the ones that have empty 1145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * code blocks or that exceed the code size. 1146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 1147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private int removeEmptyLineNumbers(LineNumberInfo[] lineNumberInfos, 1148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int lineNumberInfoCount, 1149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int codeLength) 1150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Overwrite all empty line number entries. 1152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int newIndex = 0; 1153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int index = 0; index < lineNumberInfoCount; index++) 1154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato LineNumberInfo lineNumberInfo = lineNumberInfos[index]; 1156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int startPC = lineNumberInfo.u2startPC; 1157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (startPC < codeLength && 1158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (index == 0 || startPC > lineNumberInfos[index-1].u2startPC)) 1159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato lineNumberInfos[newIndex++] = lineNumberInfo; 1161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return newIndex; 1165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 11689f606f95f03a75961498803e24bee6799a7c0885Ying Wang /** 1169b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * This instruction is a composite of other instructions, for local use 1170b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * inside the editor class only. 11719f606f95f03a75961498803e24bee6799a7c0885Ying Wang */ 1172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private class CompositeInstruction 1173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato extends Instruction 1174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private Instruction[] instructions; 1176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private CompositeInstruction(Instruction[] instructions) 1179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.instructions = instructions; 1181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for Instruction. 1185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public Instruction shrink() 1187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int index = 0; index < instructions.length; index++) 1189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instructions[index] = instructions[index].shrink(); 1191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return this; 1194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void write(byte[] code, int offset) 1198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int index = 0; index < instructions.length; index++) 1200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction = instructions[index]; 1202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction.write(code, offset); 1204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset += instruction.length(offset); 1206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato protected void readInfo(byte[] code, int offset) 1211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw new UnsupportedOperationException("Can't read composite instruction"); 1213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato protected void writeInfo(byte[] code, int offset) 1217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw new UnsupportedOperationException("Can't write composite instruction"); 1219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public int length(int offset) 1223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int newOffset = offset; 1225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int index = 0; index < instructions.length; index++) 1227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato newOffset += instructions[index].length(newOffset); 1229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return newOffset - offset; 1232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor) 1236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (instructionVisitor != CodeAttributeEditor.this) 1238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw new UnsupportedOperationException("Unexpected visitor ["+instructionVisitor+"]"); 1240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int index = 0; index < instructions.length; index++) 1243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction = instructions[index]; 1245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction.accept(clazz, method, codeAttribute, offset, CodeAttributeEditor.this); 1247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset += instruction.length(offset); 1249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for Object. 1254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public String toString() 1256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato StringBuffer stringBuffer = new StringBuffer(); 1258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int index = 0; index < instructions.length; index++) 1260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato stringBuffer.append(instructions[index].toString()).append("; "); 1262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return stringBuffer.toString(); 1265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato} 1268