1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 package proguard.classfile.attribute; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.visitor.*; 25 import proguard.classfile.instruction.*; 26 import proguard.classfile.instruction.visitor.InstructionVisitor; 27 28 /** 29 * This Attribute represents a code attribute. 30 * 31 * @author Eric Lafortune 32 */ 33 public class CodeAttribute extends Attribute 34 { 35 public int u2maxStack; 36 public int u2maxLocals; 37 public int u4codeLength; 38 public byte[] code; 39 public int u2exceptionTableLength; 40 public ExceptionInfo[] exceptionTable; 41 public int u2attributesCount; 42 public Attribute[] attributes; 43 44 45 /** 46 * Creates an uninitialized CodeAttribute. 47 */ CodeAttribute()48 public CodeAttribute() 49 { 50 } 51 52 53 /** 54 * Creates an initialized CodeAttribute. 55 */ CodeAttribute(int u2attributeNameIndex, int u2maxStack, int u2maxLocals, int u4codeLength, byte[] code, int u2exceptionTableLength, ExceptionInfo[] exceptionTable, int u2attributesCount, Attribute[] attributes)56 public CodeAttribute(int u2attributeNameIndex, 57 int u2maxStack, 58 int u2maxLocals, 59 int u4codeLength, 60 byte[] code, 61 int u2exceptionTableLength, 62 ExceptionInfo[] exceptionTable, 63 int u2attributesCount, 64 Attribute[] attributes) 65 { 66 super(u2attributeNameIndex); 67 68 this.u2maxStack = u2maxStack; 69 this.u2maxLocals = u2maxLocals; 70 this.u4codeLength = u4codeLength; 71 this.code = code; 72 this.u2exceptionTableLength = u2exceptionTableLength; 73 this.exceptionTable = exceptionTable; 74 this.u2attributesCount = u2attributesCount; 75 this.attributes = attributes; 76 } 77 78 79 /** 80 * Returns the (first) attribute with the given name. 81 */ getAttribute(Clazz clazz, String name)82 public Attribute getAttribute(Clazz clazz, String name) 83 { 84 for (int index = 0; index < u2attributesCount; index++) 85 { 86 Attribute attribute = attributes[index]; 87 if (attribute.getAttributeName(clazz).equals(name)) 88 { 89 return attribute; 90 } 91 } 92 93 return null; 94 } 95 96 97 // Implementations for Attribute. 98 accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)99 public void accept(Clazz clazz, Method method, AttributeVisitor attributeVisitor) 100 { 101 attributeVisitor.visitCodeAttribute(clazz, method, this); 102 } 103 104 105 /** 106 * Applies the given instruction visitor to all instructions. 107 */ instructionsAccept(Clazz clazz, Method method, InstructionVisitor instructionVisitor)108 public void instructionsAccept(Clazz clazz, Method method, InstructionVisitor instructionVisitor) 109 { 110 instructionsAccept(clazz, method, 0, u4codeLength, instructionVisitor); 111 } 112 113 114 /** 115 * Applies the given instruction visitor to the instruction at the specified 116 * offset. 117 */ instructionAccept(Clazz clazz, Method method, int offset, InstructionVisitor instructionVisitor)118 public void instructionAccept(Clazz clazz, Method method, int offset, InstructionVisitor instructionVisitor) 119 { 120 Instruction instruction = InstructionFactory.create(code, offset); 121 instruction.accept(clazz, method, this, offset, instructionVisitor); 122 } 123 124 125 /** 126 * Applies the given instruction visitor to all instructions in the 127 * specified range of offsets. 128 */ instructionsAccept(Clazz clazz, Method method, int startOffset, int endOffset, InstructionVisitor instructionVisitor)129 public void instructionsAccept(Clazz clazz, Method method, int startOffset, int endOffset, InstructionVisitor instructionVisitor) 130 { 131 int offset = startOffset; 132 133 while (offset < endOffset) 134 { 135 // Note that the instruction is only volatile. 136 Instruction instruction = InstructionFactory.create(code, offset); 137 int instructionLength = instruction.length(offset); 138 instruction.accept(clazz, method, this, offset, instructionVisitor); 139 offset += instructionLength; 140 } 141 } 142 143 144 /** 145 * Applies the given exception visitor to all exceptions. 146 */ exceptionsAccept(Clazz clazz, Method method, ExceptionInfoVisitor exceptionInfoVisitor)147 public void exceptionsAccept(Clazz clazz, Method method, ExceptionInfoVisitor exceptionInfoVisitor) 148 { 149 for (int index = 0; index < u2exceptionTableLength; index++) 150 { 151 // We don't need double dispatching here, since there is only one 152 // type of ExceptionInfo. 153 exceptionInfoVisitor.visitExceptionInfo(clazz, method, this, exceptionTable[index]); 154 } 155 } 156 157 158 /** 159 * Applies the given exception visitor to all exceptions that are applicable 160 * to the instruction at the specified offset. 161 */ exceptionsAccept(Clazz clazz, Method method, int offset, ExceptionInfoVisitor exceptionInfoVisitor)162 public void exceptionsAccept(Clazz clazz, Method method, int offset, ExceptionInfoVisitor exceptionInfoVisitor) 163 { 164 for (int index = 0; index < u2exceptionTableLength; index++) 165 { 166 ExceptionInfo exceptionInfo = exceptionTable[index]; 167 if (exceptionInfo.isApplicable(offset)) 168 { 169 exceptionInfoVisitor.visitExceptionInfo(clazz, method, this, exceptionInfo); 170 } 171 } 172 } 173 174 175 /** 176 * Applies the given exception visitor to all exceptions that are applicable 177 * to any of the instructions in the specified range of offsets. 178 */ exceptionsAccept(Clazz clazz, Method method, int startOffset, int endOffset, ExceptionInfoVisitor exceptionInfoVisitor)179 public void exceptionsAccept(Clazz clazz, Method method, int startOffset, int endOffset, ExceptionInfoVisitor exceptionInfoVisitor) 180 { 181 for (int index = 0; index < u2exceptionTableLength; index++) 182 { 183 ExceptionInfo exceptionInfo = exceptionTable[index]; 184 if (exceptionInfo.isApplicable(startOffset, endOffset)) 185 { 186 exceptionInfoVisitor.visitExceptionInfo(clazz, method, this, exceptionInfo); 187 } 188 } 189 } 190 191 192 /** 193 * Applies the given attribute visitor to all attributes. 194 */ attributesAccept(Clazz clazz, Method method, AttributeVisitor attributeVisitor)195 public void attributesAccept(Clazz clazz, Method method, AttributeVisitor attributeVisitor) 196 { 197 for (int index = 0; index < u2attributesCount; index++) 198 { 199 attributes[index].accept(clazz, method, this, attributeVisitor); 200 } 201 } 202 } 203