Example #1
0
 /// <summary>
 ///     Puts the Runtime[In]Visible[Type]Annotations attributes containing the given annotations and
 ///     all their <i>predecessors</i> (see
 ///     <see cref="previousAnnotation" />
 ///     in the given ByteVector.
 ///     Annotations are put in the same order they have been visited.
 /// </summary>
 /// <param name="symbolTable">
 ///     where the constants used in the AnnotationWriter instances are stored.
 /// </param>
 /// <param name="lastRuntimeVisibleAnnotation">
 ///     The last runtime visible annotation of a field, method or
 ///     class. The previous ones can be accessed with the
 ///     <see cref="previousAnnotation" />
 ///     field. May be
 ///     <literal>null</literal>
 ///     .
 /// </param>
 /// <param name="lastRuntimeInvisibleAnnotation">
 ///     The last runtime invisible annotation of this a field,
 ///     method or class. The previous ones can be accessed with the
 ///     <see cref="previousAnnotation" />
 ///     field. May be
 ///     <literal>null</literal>
 ///     .
 /// </param>
 /// <param name="lastRuntimeVisibleTypeAnnotation">
 ///     The last runtime visible type annotation of this a
 ///     field, method or class. The previous ones can be accessed with the
 ///     <see cref="previousAnnotation" />
 ///     field. May be
 ///     <literal>null</literal>
 ///     .
 /// </param>
 /// <param name="lastRuntimeInvisibleTypeAnnotation">
 ///     The last runtime invisible type annotation of a
 ///     field, method or class field. The previous ones can be accessed with the
 ///     <see cref="previousAnnotation" />
 ///     field. May be
 ///     <literal>null</literal>
 ///     .
 /// </param>
 /// <param name="output">where the attributes must be put.</param>
 internal static void PutAnnotations(SymbolTable symbolTable, AnnotationWriter lastRuntimeVisibleAnnotation
                                     , AnnotationWriter lastRuntimeInvisibleAnnotation, AnnotationWriter lastRuntimeVisibleTypeAnnotation
                                     , AnnotationWriter lastRuntimeInvisibleTypeAnnotation, ByteVector output)
 {
     if (lastRuntimeVisibleAnnotation != null)
     {
         lastRuntimeVisibleAnnotation.PutAnnotations(symbolTable.AddConstantUtf8(Constants
                                                                                 .Runtime_Visible_Annotations), output);
     }
     if (lastRuntimeInvisibleAnnotation != null)
     {
         lastRuntimeInvisibleAnnotation.PutAnnotations(symbolTable.AddConstantUtf8(Constants
                                                                                   .Runtime_Invisible_Annotations), output);
     }
     if (lastRuntimeVisibleTypeAnnotation != null)
     {
         lastRuntimeVisibleTypeAnnotation.PutAnnotations(symbolTable.AddConstantUtf8(Constants
                                                                                     .Runtime_Visible_Type_Annotations), output);
     }
     if (lastRuntimeInvisibleTypeAnnotation != null)
     {
         lastRuntimeInvisibleTypeAnnotation.PutAnnotations(symbolTable.AddConstantUtf8(Constants
                                                                                       .Runtime_Invisible_Type_Annotations), output);
     }
 }
Example #2
0
        /// <summary>
        ///     Returns the total size in bytes of all the attributes that correspond to the given field,
        ///     method or class access flags and signature.
        /// </summary>
        /// <remarks>
        ///     Returns the total size in bytes of all the attributes that correspond to the given field,
        ///     method or class access flags and signature. This size includes the 6 header bytes
        ///     (attribute_name_index and attribute_length) per attribute. Also adds the attribute type names
        ///     to the constant pool.
        /// </remarks>
        /// <param name="symbolTable">
        ///     where the constants used in the attributes must be stored.
        /// </param>
        /// <param name="accessFlags">some field, method or class access flags.</param>
        /// <param name="signatureIndex">
        ///     the constant pool index of a field, method of class signature.
        /// </param>
        /// <returns>
        ///     the size of all the attributes in bytes. This size includes the size of the attribute
        ///     headers.
        /// </returns>
        internal static int ComputeAttributesSize(SymbolTable symbolTable, AccessFlags accessFlags
                                                  , int signatureIndex)
        {
            var size = 0;

            // Before Java 1.5, synthetic fields are represented with a Synthetic attribute.
            if (accessFlags.HasFlagFast(AccessFlags.Synthetic) && symbolTable.GetMajorVersion
                    () < OpcodesConstants.V1_5)
            {
                // Synthetic attributes always use 6 bytes.
                symbolTable.AddConstantUtf8(Constants.Synthetic);
                size += 6;
            }

            if (signatureIndex != 0)
            {
                // Signature attributes always use 8 bytes.
                symbolTable.AddConstantUtf8(Constants.Signature);
                size += 8;
            }

            // ACC_DEPRECATED is ASM specific, the ClassFile format uses a Deprecated attribute instead.
            if (accessFlags.HasFlagFast(AccessFlags.Deprecated))
            {
                // Deprecated attributes always use 6 bytes.
                symbolTable.AddConstantUtf8(Constants.Deprecated);
                size += 6;
            }

            return(size);
        }
Example #3
0
 /// <summary>
 ///     Constructs a new
 ///     <see cref="RecordComponentWriter" />
 ///     .
 /// </summary>
 /// <param name="symbolTable">
 ///     where the constants used in this RecordComponentWriter must be stored.
 /// </param>
 /// <param name="accessFlags">
 ///     the record component access flags, only synthetic and/or deprecated.
 /// </param>
 /// <param name="name">the record component name.</param>
 /// <param name="descriptor">
 ///     the record component descriptor (see
 ///     <see cref="Type" />
 ///     ).
 /// </param>
 /// <param name="signature">
 ///     the record component signature. May be
 ///     <literal>null</literal>
 ///     .
 /// </param>
 internal RecordComponentWriter(SymbolTable symbolTable, AccessFlags accessFlags, string name
                                , string descriptor, string signature)
     : base(VisitorAsmApiVersion.Asm7)
 {
     // Note: fields are ordered as in the component_info structure, and those related to attributes
     // are ordered as in Section TODO of the JVMS.
     // The field accessFlag doesn't exist in the component_info structure but is used to carry
     // ACC_DEPRECATED which is represented by an attribute in the structure and as an access flag by
     // ASM.
     /* latest api = */
     this.symbolTable = symbolTable;
     this.accessFlags = accessFlags;
     nameIndex        = symbolTable.AddConstantUtf8(name);
     descriptorIndex  = symbolTable.AddConstantUtf8(descriptor);
     if (signature != null)
     {
         signatureIndex = symbolTable.AddConstantUtf8(signature);
     }
 }
Example #4
0
 /// <summary>
 ///     Puts all the attributes that correspond to the given field, method or class access flags and
 ///     signature, in the given byte vector.
 /// </summary>
 /// <remarks>
 ///     Puts all the attributes that correspond to the given field, method or class access flags and
 ///     signature, in the given byte vector. This includes the 6 header bytes (attribute_name_index and
 ///     attribute_length) per attribute.
 /// </remarks>
 /// <param name="symbolTable">
 ///     where the constants used in the attributes must be stored.
 /// </param>
 /// <param name="accessFlags">some field, method or class access flags.</param>
 /// <param name="signatureIndex">
 ///     the constant pool index of a field, method of class signature.
 /// </param>
 /// <param name="output">where the attributes must be written.</param>
 internal static void PutAttributes(SymbolTable symbolTable, AccessFlags accessFlags, int
                                    signatureIndex, ByteVector output)
 {
     // Before Java 1.5, synthetic fields are represented with a Synthetic attribute.
     if (accessFlags.HasFlagFast(AccessFlags.Synthetic) && symbolTable.GetMajorVersion
             () < OpcodesConstants.V1_5)
     {
         output.PutShort(symbolTable.AddConstantUtf8(Constants.Synthetic)).PutInt(0);
     }
     if (signatureIndex != 0)
     {
         output.PutShort(symbolTable.AddConstantUtf8(Constants.Signature)).PutInt(2).PutShort
             (signatureIndex);
     }
     if (accessFlags.HasFlagFast(AccessFlags.Deprecated))
     {
         output.PutShort(symbolTable.AddConstantUtf8(Constants.Deprecated)).PutInt(0);
     }
 }
Example #5
0
        /// <summary>
        ///     Creates a new
        ///     <see cref="AnnotationWriter" />
        ///     using named values.
        /// </summary>
        /// <param name="symbolTable">
        ///     where the constants used in this AnnotationWriter must be stored.
        /// </param>
        /// <param name="descriptor">the class descriptor of the annotation class.</param>
        /// <param name="previousAnnotation">
        ///     the previously visited annotation of the
        ///     Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or
        ///     <literal>null</literal>
        ///     in other cases (e.g. nested or array annotations).
        /// </param>
        /// <returns>
        ///     a new
        ///     <see cref="AnnotationWriter" />
        ///     for the given annotation descriptor.
        /// </returns>
        internal static AnnotationWriter Create(SymbolTable symbolTable, string descriptor
                                                , AnnotationWriter previousAnnotation)
        {
            // Create a ByteVector to hold an 'annotation' JVMS structure.
            // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.
            var annotation = new ByteVector();

            // Write type_index and reserve space for num_element_value_pairs.
            annotation.PutShort(symbolTable.AddConstantUtf8(descriptor)).PutShort(0);
            return(new AnnotationWriter(symbolTable, true, annotation, previousAnnotation));
        }
Example #6
0
        // Nothing to do.
        // -----------------------------------------------------------------------------------------------
        // Utility methods
        // -----------------------------------------------------------------------------------------------
        /// <summary>
        ///     Returns the size of the field_info JVMS structure generated by this FieldWriter.
        /// </summary>
        /// <remarks>
        ///     Returns the size of the field_info JVMS structure generated by this FieldWriter. Also adds the
        ///     names of the attributes of this field in the constant pool.
        /// </remarks>
        /// <returns>the size in bytes of the field_info JVMS structure.</returns>
        internal int ComputeFieldInfoSize()
        {
            // The access_flags, name_index, descriptor_index and attributes_count fields use 8 bytes.
            var size = 8;

            // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
            if (constantValueIndex != 0)
            {
                // ConstantValue attributes always use 8 bytes.
                symbolTable.AddConstantUtf8(Constants.Constant_Value);
                size += 8;
            }

            size += Attribute.ComputeAttributesSize(symbolTable, accessFlags, signatureIndex);
            size += AnnotationWriter.ComputeAnnotationsSize(lastRuntimeVisibleAnnotation, lastRuntimeInvisibleAnnotation
                                                            , lastRuntimeVisibleTypeAnnotation, lastRuntimeInvisibleTypeAnnotation);
            if (firstAttribute != null)
            {
                size += firstAttribute.ComputeAttributesSize(symbolTable);
            }
            return(size);
        }
Example #7
0
 /// <summary>
 ///     Constructs a new
 ///     <see cref="FieldWriter" />
 ///     .
 /// </summary>
 /// <param name="symbolTable">
 ///     where the constants used in this FieldWriter must be stored.
 /// </param>
 /// <param name="access">
 ///     the field's access flags (see
 ///     <see cref="Opcodes" />
 ///     ).
 /// </param>
 /// <param name="name">the field's name.</param>
 /// <param name="descriptor">
 ///     the field's descriptor (see
 ///     <see cref="Type" />
 ///     ).
 /// </param>
 /// <param name="signature">
 ///     the field's signature. May be
 ///     <literal>null</literal>
 ///     .
 /// </param>
 /// <param name="constantValue">
 ///     the field's constant value. May be
 ///     <literal>null</literal>
 ///     .
 /// </param>
 internal FieldWriter(SymbolTable symbolTable, AccessFlags access, string name, string descriptor
                      , string signature, object constantValue)
     : base(VisitorAsmApiVersion.Asm7)
 {
     // Note: fields are ordered as in the field_info structure, and those related to attributes are
     // ordered as in Section 4.7 of the JVMS.
     // -----------------------------------------------------------------------------------------------
     // Constructor
     // -----------------------------------------------------------------------------------------------
     /* latest api = */
     this.symbolTable = symbolTable;
     accessFlags      = access;
     nameIndex        = symbolTable.AddConstantUtf8(name);
     descriptorIndex  = symbolTable.AddConstantUtf8(descriptor);
     if (signature != null)
     {
         signatureIndex = symbolTable.AddConstantUtf8(signature);
     }
     if (constantValue != null)
     {
         constantValueIndex = symbolTable.AddConstant(constantValue).index;
     }
 }
Example #8
0
        /* useNamedValues = */
        /// <summary>
        ///     Creates a new
        ///     <see cref="AnnotationWriter" />
        ///     using named values.
        /// </summary>
        /// <param name="symbolTable">
        ///     where the constants used in this AnnotationWriter must be stored.
        /// </param>
        /// <param name="typeRef">
        ///     a reference to the annotated type. The sort of this type reference must be
        ///     <see cref="TypeReference.Class_Type_Parameter" />
        ///     ,
        ///     <see cref="TypeReference.Class_Type_Parameter_Bound" />
        ///     or
        ///     <see cref="TypeReference.Class_Extends" />
        ///     . See
        ///     <see cref="TypeReference" />
        ///     .
        /// </param>
        /// <param name="typePath">
        ///     the path to the annotated type argument, wildcard bound, array element type, or
        ///     static inner type within 'typeRef'. May be
        ///     <literal>null</literal>
        ///     if the annotation targets
        ///     'typeRef' as a whole.
        /// </param>
        /// <param name="descriptor">the class descriptor of the annotation class.</param>
        /// <param name="previousAnnotation">
        ///     the previously visited annotation of the
        ///     Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or
        ///     <literal>null</literal>
        ///     in other cases (e.g. nested or array annotations).
        /// </param>
        /// <returns>
        ///     a new
        ///     <see cref="AnnotationWriter" />
        ///     for the given type annotation reference and descriptor.
        /// </returns>
        internal static AnnotationWriter Create(SymbolTable symbolTable, int typeRef, TypePath
                                                typePath, string descriptor, AnnotationWriter previousAnnotation)
        {
            // Create a ByteVector to hold a 'type_annotation' JVMS structure.
            // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.
            var typeAnnotation = new ByteVector();

            // Write target_type, target_info, and target_path.
            TypeReference.PutTarget(typeRef, typeAnnotation);
            TypePath.Put(typePath, typeAnnotation);
            // Write type_index and reserve space for num_element_value_pairs.
            typeAnnotation.PutShort(symbolTable.AddConstantUtf8(descriptor)).PutShort(0);
            return(new AnnotationWriter(symbolTable, true, typeAnnotation, previousAnnotation
                                        ));
        }
Example #9
0
        /// <summary>
        ///     Returns the total size in bytes of all the attributes in the attribute list that begins with
        ///     this attribute.
        /// </summary>
        /// <remarks>
        ///     Returns the total size in bytes of all the attributes in the attribute list that begins with
        ///     this attribute. This size includes the 6 header bytes (attribute_name_index and
        ///     attribute_length) per attribute. Also adds the attribute type names to the constant pool.
        /// </remarks>
        /// <param name="symbolTable">
        ///     where the constants used in the attributes must be stored.
        /// </param>
        /// <param name="code">
        ///     the bytecode of the method corresponding to these Code attributes, or
        ///     <literal>null</literal>
        ///     if they are not Code attributes. Corresponds to the 'code' field of the Code
        ///     attribute.
        /// </param>
        /// <param name="codeLength">
        ///     the length of the bytecode of the method corresponding to these code
        ///     attributes, or 0 if they are not Code attributes. Corresponds to the 'code_length' field of
        ///     the Code attribute.
        /// </param>
        /// <param name="maxStack">
        ///     the maximum stack size of the method corresponding to these Code attributes, or
        ///     -1 if they are not Code attributes.
        /// </param>
        /// <param name="maxLocals">
        ///     the maximum number of local variables of the method corresponding to these
        ///     Code attributes, or -1 if they are not Code attribute.
        /// </param>
        /// <returns>
        ///     the size of all the attributes in this attribute list. This size includes the size of
        ///     the attribute headers.
        /// </returns>
        internal int ComputeAttributesSize(SymbolTable symbolTable, byte[] code, int codeLength
                                           , int maxStack, int maxLocals)
        {
            var classWriter = symbolTable.classWriter;
            var size        = 0;
            var attribute   = this;

            while (attribute != null)
            {
                symbolTable.AddConstantUtf8(attribute.type);
                size     += 6 + attribute.Write(classWriter, code, codeLength, maxStack, maxLocals).length;
                attribute = attribute.nextAttribute;
            }

            return(size);
        }
Example #10
0
        /// <summary>
        ///     Puts all the attributes of the attribute list that begins with this attribute, in the given
        ///     byte vector.
        /// </summary>
        /// <remarks>
        ///     Puts all the attributes of the attribute list that begins with this attribute, in the given
        ///     byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per
        ///     attribute.
        /// </remarks>
        /// <param name="symbolTable">
        ///     where the constants used in the attributes must be stored.
        /// </param>
        /// <param name="code">
        ///     the bytecode of the method corresponding to these Code attributes, or
        ///     <literal>null</literal>
        ///     if they are not Code attributes. Corresponds to the 'code' field of the Code
        ///     attribute.
        /// </param>
        /// <param name="codeLength">
        ///     the length of the bytecode of the method corresponding to these code
        ///     attributes, or 0 if they are not Code attributes. Corresponds to the 'code_length' field of
        ///     the Code attribute.
        /// </param>
        /// <param name="maxStack">
        ///     the maximum stack size of the method corresponding to these Code attributes, or
        ///     -1 if they are not Code attributes.
        /// </param>
        /// <param name="maxLocals">
        ///     the maximum number of local variables of the method corresponding to these
        ///     Code attributes, or -1 if they are not Code attribute.
        /// </param>
        /// <param name="output">where the attributes must be written.</param>
        internal void PutAttributes(SymbolTable symbolTable, byte[] code, int codeLength,
                                    int maxStack, int maxLocals, ByteVector output)
        {
            var classWriter = symbolTable.classWriter;
            var attribute   = this;

            while (attribute != null)
            {
                var attributeContent = attribute.Write(classWriter, code, codeLength, maxStack
                                                       , maxLocals);
                // Put attribute_name_index and attribute_length.
                output.PutShort(symbolTable.AddConstantUtf8(attribute.type)).PutInt(attributeContent
                                                                                    .length);
                output.PutByteArray(attributeContent.data, 0, attributeContent.length);
                attribute = attribute.nextAttribute;
            }
        }
Example #11
0
 /* useNamedValues = */
 // -----------------------------------------------------------------------------------------------
 // Implementation of the AnnotationVisitor abstract class
 // -----------------------------------------------------------------------------------------------
 public override void Visit(string name, object value)
 {
     // Case of an element_value with a const_value_index, class_info_index or array_index field.
     // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
     ++numElementValuePairs;
     if (useNamedValues)
     {
         annotation.PutShort(symbolTable.AddConstantUtf8(name));
     }
     if (value is string)
     {
         annotation.Put12('s', symbolTable.AddConstantUtf8((string)value));
     }
     else if (value is byte)
     {
         annotation.Put12('B', symbolTable.AddConstantInteger((byte)value).index);
     }
     else if (value is bool)
     {
         var booleanValue = (bool)value ? 1 : 0;
         annotation.Put12('Z', symbolTable.AddConstantInteger(booleanValue).index);
     }
     else if (value is char)
     {
         annotation.Put12('C', symbolTable.AddConstantInteger((char)value).index);
     }
     else if (value is short)
     {
         annotation.Put12('S', symbolTable.AddConstantInteger((short)value).index);
     }
     else if (value is Type)
     {
         annotation.Put12('c', symbolTable.AddConstantUtf8(((Type)value).GetDescriptor()));
     }
     else if (value is byte[])
     {
         var byteArray = (byte[])value;
         annotation.Put12('[', byteArray.Length);
         foreach (var byteValue in byteArray)
         {
             annotation.Put12('B', symbolTable.AddConstantInteger(byteValue).index);
         }
     }
     else if (value is bool[])
     {
         var booleanArray = (bool[])value;
         annotation.Put12('[', booleanArray.Length);
         foreach (var booleanValue in booleanArray)
         {
             annotation.Put12('Z', symbolTable.AddConstantInteger(booleanValue ? 1 : 0).index);
         }
     }
     else if (value is short[])
     {
         var shortArray = (short[])value;
         annotation.Put12('[', shortArray.Length);
         foreach (var shortValue in shortArray)
         {
             annotation.Put12('S', symbolTable.AddConstantInteger(shortValue).index);
         }
     }
     else if (value is char[])
     {
         var charArray = (char[])value;
         annotation.Put12('[', charArray.Length);
         foreach (var charValue in charArray)
         {
             annotation.Put12('C', symbolTable.AddConstantInteger(charValue).index);
         }
     }
     else if (value is int[])
     {
         var intArray = (int[])value;
         annotation.Put12('[', intArray.Length);
         foreach (var intValue in intArray)
         {
             annotation.Put12('I', symbolTable.AddConstantInteger(intValue).index);
         }
     }
     else if (value is long[])
     {
         var longArray = (long[])value;
         annotation.Put12('[', longArray.Length);
         foreach (var longValue in longArray)
         {
             annotation.Put12('J', symbolTable.AddConstantLong(longValue).index);
         }
     }
     else if (value is float[])
     {
         var floatArray = (float[])value;
         annotation.Put12('[', floatArray.Length);
         foreach (var floatValue in floatArray)
         {
             annotation.Put12('F', symbolTable.AddConstantFloat(floatValue).index);
         }
     }
     else if (value is double[])
     {
         var doubleArray = (double[])value;
         annotation.Put12('[', doubleArray.Length);
         foreach (var doubleValue in doubleArray)
         {
             annotation.Put12('D', symbolTable.AddConstantDouble(doubleValue).index);
         }
     }
     else
     {
         var symbol = symbolTable.AddConstant(value);
         annotation.Put12(".s.IFJDCS"[symbol.tag], symbol.index);
     }
 }
Example #12
0
 public override void VisitRequire(string module, AccessFlags access, string version)
 {
     requires.PutShort(symbolTable.AddConstantModule(module).index).PutShort((int)access).PutShort
         (version == null ? 0 : symbolTable.AddConstantUtf8(version));
     requiresCount++;
 }