001// ASM: a very small and fast Java bytecode manipulation framework 002// Copyright (c) 2000-2011 INRIA, France Telecom 003// All rights reserved. 004// 005// Redistribution and use in source and binary forms, with or without 006// modification, are permitted provided that the following conditions 007// are met: 008// 1. Redistributions of source code must retain the above copyright 009// notice, this list of conditions and the following disclaimer. 010// 2. Redistributions in binary form must reproduce the above copyright 011// notice, this list of conditions and the following disclaimer in the 012// documentation and/or other materials provided with the distribution. 013// 3. Neither the name of the copyright holders nor the names of its 014// contributors may be used to endorse or promote products derived from 015// this software without specific prior written permission. 016// 017// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 018// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 019// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 020// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 021// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 022// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 023// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 024// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 025// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 026// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 027// THE POSSIBILITY OF SUCH DAMAGE. 028package io.ebean.enhance.asm; 029 030/** 031 * A non standard class, field, method or Code attribute, as defined in the Java Virtual Machine 032 * Specification (JVMS). 033 * 034 * @see <a href= "https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7">JVMS 035 * 4.7</a> 036 * @see <a href= "https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.3">JVMS 037 * 4.7.3</a> 038 * @author Eric Bruneton 039 * @author Eugene Kuleshov 040 */ 041public class Attribute { 042 043 /** The type of this attribute, also called its name in the JVMS. */ 044 public final String type; 045 046 /** 047 * The raw content of this attribute, as returned by {@link 048 * #write(ClassWriter,byte[],int,int,int)}. The 6 header bytes of the attribute 049 * (attribute_name_index and attribute_length) are <i>not</i> included. 050 */ 051 private ByteVector cachedContent; 052 053 /** 054 * The next attribute in this attribute list (Attribute instances can be linked via this field to 055 * store a list of class, field, method or Code attributes). May be {@literal null}. 056 */ 057 Attribute nextAttribute; 058 059 /** 060 * Constructs a new empty attribute. 061 * 062 * @param type the type of the attribute. 063 */ 064 protected Attribute(final String type) { 065 this.type = type; 066 } 067 068 /** 069 * Returns {@literal true} if this type of attribute is unknown. This means that the attribute 070 * content can't be parsed to extract constant pool references, labels, etc. Instead, the 071 * attribute content is read as an opaque byte array, and written back as is. This can lead to 072 * invalid attributes, if the content actually contains constant pool references, labels, or other 073 * symbolic references that need to be updated when there are changes to the constant pool, the 074 * method bytecode, etc. The default implementation of this method always returns {@literal true}. 075 * 076 * @return {@literal true} if this type of attribute is unknown. 077 */ 078 public boolean isUnknown() { 079 return true; 080 } 081 082 /** 083 * Returns {@literal true} if this type of attribute is a Code attribute. 084 * 085 * @return {@literal true} if this type of attribute is a Code attribute. 086 */ 087 public boolean isCodeAttribute() { 088 return false; 089 } 090 091 /** 092 * Returns the labels corresponding to this attribute. 093 * 094 * @return the labels corresponding to this attribute, or {@literal null} if this attribute is not 095 * a Code attribute that contains labels. 096 * @deprecated no longer used by ASM. 097 */ 098 @Deprecated 099 protected Label[] getLabels() { 100 return new Label[0]; 101 } 102 103 /** 104 * Reads a {@link #type} attribute. This method must return a <i>new</i> {@link Attribute} object, 105 * of type {@link #type}, corresponding to the 'length' bytes starting at 'offset', in the given 106 * ClassReader. 107 * 108 * @param classReader the class that contains the attribute to be read. 109 * @param offset index of the first byte of the attribute's content in {@link ClassReader}. The 6 110 * attribute header bytes (attribute_name_index and attribute_length) are not taken into 111 * account here. 112 * @param length the length of the attribute's content (excluding the 6 attribute header bytes). 113 * @param charBuffer the buffer to be used to call the ClassReader methods requiring a 114 * 'charBuffer' parameter. 115 * @param codeAttributeOffset index of the first byte of content of the enclosing Code attribute 116 * in {@link ClassReader}, or -1 if the attribute to be read is not a Code attribute. The 6 117 * attribute header bytes (attribute_name_index and attribute_length) are not taken into 118 * account here. 119 * @param labels the labels of the method's code, or {@literal null} if the attribute to be read 120 * is not a Code attribute. Labels defined in the attribute must be created and added to this 121 * array, if not already present, by calling the {@link #readLabel} method (do not create 122 * {@link Label} instances directly). 123 * @return a <i>new</i> {@link Attribute} object corresponding to the specified bytes. 124 */ 125 protected Attribute read( 126 final ClassReader classReader, 127 final int offset, 128 final int length, 129 final char[] charBuffer, 130 final int codeAttributeOffset, 131 final Label[] labels) { 132 Attribute attribute = new Attribute(type); 133 attribute.cachedContent = new ByteVector(classReader.readBytes(offset, length)); 134 return attribute; 135 } 136 137 /** 138 * Reads an attribute with the same {@link #type} as the given attribute. This method returns a 139 * new {@link Attribute} object, corresponding to the 'length' bytes starting at 'offset', in the 140 * given ClassReader. 141 * 142 * @param attribute The attribute prototype that is used for reading. 143 * @param classReader the class that contains the attribute to be read. 144 * @param offset index of the first byte of the attribute's content in {@link ClassReader}. The 6 145 * attribute header bytes (attribute_name_index and attribute_length) are not taken into 146 * account here. 147 * @param length the length of the attribute's content (excluding the 6 attribute header bytes). 148 * @param charBuffer the buffer to be used to call the ClassReader methods requiring a 149 * 'charBuffer' parameter. 150 * @param codeAttributeOffset index of the first byte of content of the enclosing Code attribute 151 * in {@link ClassReader}, or -1 if the attribute to be read is not a Code attribute. The 6 152 * attribute header bytes (attribute_name_index and attribute_length) are not taken into 153 * account here. 154 * @param labels the labels of the method's code, or {@literal null} if the attribute to be read 155 * is not a Code attribute. Labels defined in the attribute are added to this array, if not 156 * already present. 157 * @return a new {@link Attribute} object corresponding to the specified bytes. 158 */ 159 public static Attribute read( 160 final Attribute attribute, 161 final ClassReader classReader, 162 final int offset, 163 final int length, 164 final char[] charBuffer, 165 final int codeAttributeOffset, 166 final Label[] labels) { 167 return attribute.read(classReader, offset, length, charBuffer, codeAttributeOffset, labels); 168 } 169 170 /** 171 * Returns the label corresponding to the given bytecode offset by calling {@link 172 * ClassReader#readLabel}. This creates and adds the label to the given array if it is not already 173 * present. Note that this created label may be a {@link Label} subclass instance, if the given 174 * ClassReader overrides {@link ClassReader#readLabel}. Hence {@link #read(ClassReader, int, int, 175 * char[], int, Label[])} must not manually create {@link Label} instances. 176 * 177 * @param bytecodeOffset a bytecode offset in a method. 178 * @param labels the already created labels, indexed by their offset. If a label already exists 179 * for bytecodeOffset this method does not create a new one. Otherwise it stores the new label 180 * in this array. 181 * @return a label for the given bytecode offset. 182 */ 183 public static Label readLabel( 184 final ClassReader classReader, final int bytecodeOffset, final Label[] labels) { 185 return classReader.readLabel(bytecodeOffset, labels); 186 } 187 188 /** 189 * Calls {@link #write(ClassWriter,byte[],int,int,int)} if it has not already been called and 190 * returns its result or its (cached) previous result. 191 * 192 * @param classWriter the class to which this attribute must be added. This parameter can be used 193 * to add the items that corresponds to this attribute to the constant pool of this class. 194 * @param code the bytecode of the method corresponding to this Code attribute, or {@literal null} 195 * if this attribute is not a Code attribute. Corresponds to the 'code' field of the Code 196 * attribute. 197 * @param codeLength the length of the bytecode of the method corresponding to this code 198 * attribute, or 0 if this attribute is not a Code attribute. Corresponds to the 'code_length' 199 * field of the Code attribute. 200 * @param maxStack the maximum stack size of the method corresponding to this Code attribute, or 201 * -1 if this attribute is not a Code attribute. 202 * @param maxLocals the maximum number of local variables of the method corresponding to this code 203 * attribute, or -1 if this attribute is not a Code attribute. 204 * @return the byte array form of this attribute. 205 */ 206 private ByteVector maybeWrite( 207 final ClassWriter classWriter, 208 final byte[] code, 209 final int codeLength, 210 final int maxStack, 211 final int maxLocals) { 212 if (cachedContent == null) { 213 cachedContent = write(classWriter, code, codeLength, maxStack, maxLocals); 214 } 215 return cachedContent; 216 } 217 218 /** 219 * Returns the byte array form of the content of this attribute. The 6 header bytes 220 * (attribute_name_index and attribute_length) must <i>not</i> be added in the returned 221 * ByteVector. 222 * 223 * <p>This method is only invoked once to compute the binary form of this attribute. Subsequent 224 * changes to the attribute after it was written for the first time will not be considered. 225 * 226 * @param classWriter the class to which this attribute must be added. This parameter can be used 227 * to add the items that corresponds to this attribute to the constant pool of this class. 228 * @param code the bytecode of the method corresponding to this Code attribute, or {@literal null} 229 * if this attribute is not a Code attribute. Corresponds to the 'code' field of the Code 230 * attribute. 231 * @param codeLength the length of the bytecode of the method corresponding to this code 232 * attribute, or 0 if this attribute is not a Code attribute. Corresponds to the 'code_length' 233 * field of the Code attribute. 234 * @param maxStack the maximum stack size of the method corresponding to this Code attribute, or 235 * -1 if this attribute is not a Code attribute. 236 * @param maxLocals the maximum number of local variables of the method corresponding to this code 237 * attribute, or -1 if this attribute is not a Code attribute. 238 * @return the byte array form of this attribute. 239 */ 240 protected ByteVector write( 241 final ClassWriter classWriter, 242 final byte[] code, 243 final int codeLength, 244 final int maxStack, 245 final int maxLocals) { 246 return cachedContent; 247 } 248 249 /** 250 * Returns the byte array form of the content of the given attribute. The 6 header bytes 251 * (attribute_name_index and attribute_length) are <i>not</i> added in the returned byte array. 252 * 253 * @param attribute The attribute that should be written. 254 * @param classWriter the class to which this attribute must be added. This parameter can be used 255 * to add the items that corresponds to this attribute to the constant pool of this class. 256 * @param code the bytecode of the method corresponding to this Code attribute, or {@literal null} 257 * if this attribute is not a Code attribute. Corresponds to the 'code' field of the Code 258 * attribute. 259 * @param codeLength the length of the bytecode of the method corresponding to this code 260 * attribute, or 0 if this attribute is not a Code attribute. Corresponds to the 'code_length' 261 * field of the Code attribute. 262 * @param maxStack the maximum stack size of the method corresponding to this Code attribute, or 263 * -1 if this attribute is not a Code attribute. 264 * @param maxLocals the maximum number of local variables of the method corresponding to this code 265 * attribute, or -1 if this attribute is not a Code attribute. 266 * @return the byte array form of this attribute. 267 */ 268 public static byte[] write( 269 final Attribute attribute, 270 final ClassWriter classWriter, 271 final byte[] code, 272 final int codeLength, 273 final int maxStack, 274 final int maxLocals) { 275 ByteVector content = attribute.maybeWrite(classWriter, code, codeLength, maxStack, maxLocals); 276 byte[] result = new byte[content.length]; 277 System.arraycopy(content.data, 0, result, 0, content.length); 278 return result; 279 } 280 281 /** 282 * Returns the number of attributes of the attribute list that begins with this attribute. 283 * 284 * @return the number of attributes of the attribute list that begins with this attribute. 285 */ 286 final int getAttributeCount() { 287 int count = 0; 288 Attribute attribute = this; 289 while (attribute != null) { 290 count += 1; 291 attribute = attribute.nextAttribute; 292 } 293 return count; 294 } 295 296 /** 297 * Returns the total size in bytes of all the attributes in the attribute list that begins with 298 * this attribute. This size includes the 6 header bytes (attribute_name_index and 299 * attribute_length) per attribute. Also adds the attribute type names to the constant pool. 300 * 301 * @param symbolTable where the constants used in the attributes must be stored. 302 * @return the size of all the attributes in this attribute list. This size includes the size of 303 * the attribute headers. 304 */ 305 final int computeAttributesSize(final SymbolTable symbolTable) { 306 final byte[] code = null; 307 final int codeLength = 0; 308 final int maxStack = -1; 309 final int maxLocals = -1; 310 return computeAttributesSize(symbolTable, code, codeLength, maxStack, maxLocals); 311 } 312 313 /** 314 * Returns the total size in bytes of all the attributes in the attribute list that begins with 315 * this attribute. This size includes the 6 header bytes (attribute_name_index and 316 * attribute_length) per attribute. Also adds the attribute type names to the constant pool. 317 * 318 * @param symbolTable where the constants used in the attributes must be stored. 319 * @param code the bytecode of the method corresponding to these Code attributes, or {@literal 320 * null} if they are not Code attributes. Corresponds to the 'code' field of the Code 321 * attribute. 322 * @param codeLength the length of the bytecode of the method corresponding to these code 323 * attributes, or 0 if they are not Code attributes. Corresponds to the 'code_length' field of 324 * the Code attribute. 325 * @param maxStack the maximum stack size of the method corresponding to these Code attributes, or 326 * -1 if they are not Code attributes. 327 * @param maxLocals the maximum number of local variables of the method corresponding to these 328 * Code attributes, or -1 if they are not Code attribute. 329 * @return the size of all the attributes in this attribute list. This size includes the size of 330 * the attribute headers. 331 */ 332 final int computeAttributesSize( 333 final SymbolTable symbolTable, 334 final byte[] code, 335 final int codeLength, 336 final int maxStack, 337 final int maxLocals) { 338 final ClassWriter classWriter = symbolTable.classWriter; 339 int size = 0; 340 Attribute attribute = this; 341 while (attribute != null) { 342 symbolTable.addConstantUtf8(attribute.type); 343 size += 6 + attribute.maybeWrite(classWriter, code, codeLength, maxStack, maxLocals).length; 344 attribute = attribute.nextAttribute; 345 } 346 return size; 347 } 348 349 /** 350 * Returns the total size in bytes of all the attributes that correspond to the given field, 351 * method or class access flags and signature. This size includes the 6 header bytes 352 * (attribute_name_index and attribute_length) per attribute. Also adds the attribute type names 353 * to the constant pool. 354 * 355 * @param symbolTable where the constants used in the attributes must be stored. 356 * @param accessFlags some field, method or class access flags. 357 * @param signatureIndex the constant pool index of a field, method of class signature. 358 * @return the size of all the attributes in bytes. This size includes the size of the attribute 359 * headers. 360 */ 361 static int computeAttributesSize( 362 final SymbolTable symbolTable, final int accessFlags, final int signatureIndex) { 363 int size = 0; 364 // Before Java 1.5, synthetic fields are represented with a Synthetic attribute. 365 if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 366 && symbolTable.getMajorVersion() < Opcodes.V1_5) { 367 // Synthetic attributes always use 6 bytes. 368 symbolTable.addConstantUtf8(Constants.SYNTHETIC); 369 size += 6; 370 } 371 if (signatureIndex != 0) { 372 // Signature attributes always use 8 bytes. 373 symbolTable.addConstantUtf8(Constants.SIGNATURE); 374 size += 8; 375 } 376 // ACC_DEPRECATED is ASM specific, the ClassFile format uses a Deprecated attribute instead. 377 if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) { 378 // Deprecated attributes always use 6 bytes. 379 symbolTable.addConstantUtf8(Constants.DEPRECATED); 380 size += 6; 381 } 382 return size; 383 } 384 385 /** 386 * Puts all the attributes of the attribute list that begins with this attribute, in the given 387 * byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per 388 * attribute. 389 * 390 * @param symbolTable where the constants used in the attributes must be stored. 391 * @param output where the attributes must be written. 392 */ 393 final void putAttributes(final SymbolTable symbolTable, final ByteVector output) { 394 final byte[] code = null; 395 final int codeLength = 0; 396 final int maxStack = -1; 397 final int maxLocals = -1; 398 putAttributes(symbolTable, code, codeLength, maxStack, maxLocals, output); 399 } 400 401 /** 402 * Puts all the attributes of the attribute list that begins with this attribute, in the given 403 * byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per 404 * attribute. 405 * 406 * @param symbolTable where the constants used in the attributes must be stored. 407 * @param code the bytecode of the method corresponding to these Code attributes, or {@literal 408 * null} if they are not Code attributes. Corresponds to the 'code' field of the Code 409 * attribute. 410 * @param codeLength the length of the bytecode of the method corresponding to these code 411 * attributes, or 0 if they are not Code attributes. Corresponds to the 'code_length' field of 412 * the Code attribute. 413 * @param maxStack the maximum stack size of the method corresponding to these Code attributes, or 414 * -1 if they are not Code attributes. 415 * @param maxLocals the maximum number of local variables of the method corresponding to these 416 * Code attributes, or -1 if they are not Code attribute. 417 * @param output where the attributes must be written. 418 */ 419 final void putAttributes( 420 final SymbolTable symbolTable, 421 final byte[] code, 422 final int codeLength, 423 final int maxStack, 424 final int maxLocals, 425 final ByteVector output) { 426 final ClassWriter classWriter = symbolTable.classWriter; 427 Attribute attribute = this; 428 while (attribute != null) { 429 ByteVector attributeContent = 430 attribute.maybeWrite(classWriter, code, codeLength, maxStack, maxLocals); 431 // Put attribute_name_index and attribute_length. 432 output.putShort(symbolTable.addConstantUtf8(attribute.type)).putInt(attributeContent.length); 433 output.putByteArray(attributeContent.data, 0, attributeContent.length); 434 attribute = attribute.nextAttribute; 435 } 436 } 437 438 /** 439 * Puts all the attributes that correspond to the given field, method or class access flags and 440 * signature, in the given byte vector. This includes the 6 header bytes (attribute_name_index and 441 * attribute_length) per attribute. 442 * 443 * @param symbolTable where the constants used in the attributes must be stored. 444 * @param accessFlags some field, method or class access flags. 445 * @param signatureIndex the constant pool index of a field, method of class signature. 446 * @param output where the attributes must be written. 447 */ 448 static void putAttributes( 449 final SymbolTable symbolTable, 450 final int accessFlags, 451 final int signatureIndex, 452 final ByteVector output) { 453 // Before Java 1.5, synthetic fields are represented with a Synthetic attribute. 454 if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 455 && symbolTable.getMajorVersion() < Opcodes.V1_5) { 456 output.putShort(symbolTable.addConstantUtf8(Constants.SYNTHETIC)).putInt(0); 457 } 458 if (signatureIndex != 0) { 459 output 460 .putShort(symbolTable.addConstantUtf8(Constants.SIGNATURE)) 461 .putInt(2) 462 .putShort(signatureIndex); 463 } 464 if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) { 465 output.putShort(symbolTable.addConstantUtf8(Constants.DEPRECATED)).putInt(0); 466 } 467 } 468 469 /** A set of attribute prototypes (attributes with the same type are considered equal). */ 470 static final class Set { 471 472 private static final int SIZE_INCREMENT = 6; 473 474 private int size; 475 private Attribute[] data = new Attribute[SIZE_INCREMENT]; 476 477 void addAttributes(final Attribute attributeList) { 478 Attribute attribute = attributeList; 479 while (attribute != null) { 480 if (!contains(attribute)) { 481 add(attribute); 482 } 483 attribute = attribute.nextAttribute; 484 } 485 } 486 487 Attribute[] toArray() { 488 Attribute[] result = new Attribute[size]; 489 System.arraycopy(data, 0, result, 0, size); 490 return result; 491 } 492 493 private boolean contains(final Attribute attribute) { 494 for (int i = 0; i < size; ++i) { 495 if (data[i].type.equals(attribute.type)) { 496 return true; 497 } 498 } 499 return false; 500 } 501 502 private void add(final Attribute attribute) { 503 if (size >= data.length) { 504 Attribute[] newData = new Attribute[data.length + SIZE_INCREMENT]; 505 System.arraycopy(data, 0, newData, 0, size); 506 data = newData; 507 } 508 data[size++] = attribute; 509 } 510 } 511}