22.1 Bitmasks and Flags This section explains the various flags and bitmasks used in the various metadata tables. 22.1.1 Values for AssemblyHashAlgorithm Algorithm | Value |
|---|
None | 0x0000 | Reserved (MD5) | 0x8003 | SHA1 | 0x8004 | ANNOTATION For more information on the SHA1 hash algorithm, see Partition II, section 6.2.1.1. |
22.1.2 Values for AssemblyFlags Flag | Value | Description |
|---|
PublicKey | 0x0001 | The assembly reference holds the full (unhashed) public key. | SideBySideCompatible | 0x0000 | The assembly is side by side compatible. | <reserved> | 0x0030 | Reserved: both bits shall be zero. | Retargetable | 0x0100 | The implementation of this assembly used at runtime is not expected to match the version seen at compile time. (See the text following this table.) | EnableJITcompileTracking | 0x8000 | Reserved (a conforming implementation of the CLI may ignore this setting on read; some implementations might use this bit to indicate that a CIL-to-native-code compiler should generate CIL-to-native-code map). | DisableJITcompileOptimizer | 0x4000 | Reserved (a conforming implementation of the CLI may ignore this setting on read; some implementations might use this bit to indicate that a CIL-to-native-code compiler should not generate optimized code). | In portable programs, the Retargetable (0x100) bit shall be set on all references to assemblies specified in this standard. ANNOTATION For more information on the originator's public key, see Partition II, section 6.2.1.3. |
22.1.3 Values for Culture ar-SA | ar-IQ | ar-EG | ar-LY | ar-DZ | ar-MA | ar-TN | ar-OM | ar-YE | ar-SY | ar-JO | ar-LB | ar-KW | ar-AE | ar-BH | ar-QA | bg-BG | ca-ES | zh-TW | zh-CN | zh-HK | zh-SG | zh-MO | cs-CZ | da-DK | de-DE | de-CH | de-AT | de-LU | de-LI | el-GR | en-US | en-GB | en-AU | en-CA | en-NZ | en-IE | en-ZA | en-JM | en-CB | en-BZ | en-TT | en-ZW | en-PH | es-ES-Ts | es-MX | es-ES-Is | es-GT | es-CR | es-PA | es-DO | es-VE | es-CO | es-PE | es-AR | es-EC | es-CL | es-UY | es-PY | es-BO | es-SV | es-HN | es-NI | es-PR | Fi-FI | fr-FR | fr-BE | fr-CA | Fr-CH | fr-LU | fr-MC | he-IL | hu-HU | is-IS | it-IT | it-CH | Ja-JP | ko-KR | nl-NL | nl-BE | nb-NO | nn-NO | pl-PL | pt-BR | pt-PT | ro-RO | ru-RU | hr-HR | Lt-sr-SP | Cy-sr-SP | sk-SK | sq-AL | sv-SE | sv-FI | th-TH | tr-TR | ur-PK | id-ID | uk-UA | be-BY | sl-SI | et-EE | lv-LV | lt-LT | fa-IR | vi-VN | hy-AM | Lt-az-AZ | Cy-az-AZ | eu-ES | mk-MK | af-ZA | ka-GE | fo-FO | hi-IN | ms-MY | ms-BN | kk-KZ | ky-KZ | sw-KE | Lt-uz-UZ | Cy-uz-UZ | tt-TA | pa-IN | gu-IN | ta-IN | te-IN | kn-IN | mr-IN | sa-IN | mn-MN | gl-ES | kok-IN | syr-SY | div-MV | | Note on RFC 1766 Locale names: a typical string would be "en-US". The first part ("en" in the example) uses ISO 639 characters ("Latin-alphabet characters in lowercase. No diacritical marks of modified characters are used"). The second part ("US" in the example) uses ISO 3166 characters (similar to ISO 639, but uppercase). In other words, the familiar ASCII characters a z and A Z, respectively. However, while RFC 1766 recommends the first part is lowercase, the second part uppercase, it allows mixed case. Therefore, the validation rule checks only that Culture is one of the strings in the list above but the check is totally case-blind where case-blind is the familiar fold on values less than U+0080. ANNOTATION For more information on the culture, see Partition II, section 6.2.1.2. |
22.1.4 Flags for Events (EventAttributes) Flag | Value | Description |
|---|
SpecialName | 0x0200 | Event is special. | RTSpecialName | 0x0400 | CLI provides "special" behavior, depending upon the name of the event. | ANNOTATION The SpecialName attribute is also used for properties, and compilers can designate any name they choose as SpecialName. RTSpecialName is used for certain other names that require special treatment by the VES. For more information on designating names as special, to either the compiler or the runtime, see Partition II, section 9.1.6, and Partition I, sections 8.11.3 and 8.11.4. |
22.1.5 Flags for Fields (FieldAttributes) Flag | Value | Description |
|---|
FieldAccessMask | 0x0007 | | CompilerControlled | 0x0000 | Member not referenceable. | Private | 0x0001 | Accessible only by the parent type. | FamANDAssem | 0x0002 | Accessible by subtypes only in this Assembly. | Assembly | 0x0003 | Accessibly by anyone in the Assembly. | Family | 0x0004 | Accessible only by type and subtypes. | FamORAssem | 0x0005 | Accessibly by subtypes anywhere, plus anyone in assembly. | Public | 0x0006 | Accessibly by anyone who has visibility to this scope field contract attributes. | Static | 0x0010 | Defined on type, else per instance. | InitOnly | 0x0020 | Field may only be initialized, not written to after init. | Literal | 0x0040 | Value is compile-time constant. | NotSerialized | 0x0080 | Field does not have to be serialized when type is remoted. | SpecialName | 0x0200 | Field is special. | Interop Attributes | PInvokeImpl | 0x2000 | Implementation is forwarded through PInvoke. | Additional Flags | RTSpecialName | 0x0400 | CLI provides "special" behavior, depending upon the name of the field. | HasFieldMarshal | 0x1000 | Field has marshalling information. | HasDefault | 0x8000 | Field has default. | HasFieldRVA | 0x0100 | Field has RVA. | ANNOTATION For more information on NotSerialized, see Partition II, sections 9.1.6 and 15.1.2. For more information on the accessibility options, see Partition II, section 8 and its subsections. |
22.1.6 Flags for Files (FileAttributes) Flag | Value | Description |
|---|
ContainsMetaData | 0x0000 | This is not a resource file. | ContainsNoMetaData | 0x0001 | This is a resource file or other non-metadata-containing file. | 22.1.7 Flags for ImplMap (PInvokeAttributes) Flag | Value | Description |
|---|
NoMangle | 0x0001 | PInvoke is to use the member name as specified. | Character Set | CharSetMask | 0x0006 | This is a resource file or other non-metadata-containing file. | CharSetNotSpec | 0x0000 | | CharSetAnsi | 0x0002 | | CharSetUnicode | 0x0004 | | CharSetAuto | 0x0006 | | SupportsLastError | 0x0040 | Information about target function. Not relevant for fields. | Calling Convention | CallConvMask | 0x0700 | | CallConvWinapi | 0x0100 | | CallConvCdecl | 0x0200 | | CallConvStdcall | 0x0300 | | CallConvThiscall | 0x0400 | | CallConvFastcall | 0x0500 | | ANNOTATION For more information on character sets, see Partition II, section 9.1.5. For more information on calling conventions, see Partition II, section 14.3. |
22.1.8 Flags for ManifestResource (ManifestResourceAttributes) Flag | Value | Description |
|---|
VisibilityMask | 0x0007 | | Public | 0x0001 | The Resource is exported from the Assembly. | Private | 0x0002 | The Resource is private to the Assembly. | ANNOTATION For more information on visibility, see Partition II, section 8 and its subsections. |
22.1.9 Flags for Methods (MethodAttributes) Flag | Value | Description |
|---|
MemberAccessMask | 0x0007 | | CompilerControlled | 0x0000 | Member not referenceable. | Private | 0x0001 | Accessible only by the parent type. | FamANDAssem | 0x0002 | Accessible by subtypes only in this Assembly. | Assem | 0x0003 | Accessibly by anyone in the Assembly. | Family | 0x0004 | Accessible only by type and subtypes. | FamORAssem | 0x0005 | Accessibly by subtypes anywhere, plus anyone in assembly. | Public | 0x0006 | Accessibly by anyone who has visibility to this scope. | Static | 0x0010 | Defined on type, else per instance. | Final | 0x0020 | Method may not be overridden. | Virtual | 0x0040 | Method is virtual. | HideBySig | 0x0080 | Method hides by name+sig, else just by name. | VtableLayoutMask | 0x0100 | Use this mask to retrieve vtable attributes. | ReuseSlot | 0x0000 | Method reuses existing slot in vtable. | NewSlot | 0x0100 | Method always gets a new slot in the vtable. | Abstract | 0x0400 | Method does not provide an implementation. | SpecialName | 0x0800 | Method is special. | Interop Attributes | PInvokeImpl | 0x2000 | Implementation is forwarded through PInvoke. | UnmanagedExport | 0x0008 | Reserved: shall be zero for conforming implementations. | Additional Flags | RTSpecialName | 0x1000 | CLI provides "special" behavior, depending upon the name of the method. | HasSecurity | 0x4000 | Method has security associate with it. | RequireSecObject | 0x8000 | Method calls another method containing security code. | ANNOTATION For more information on the accessibility options and hiding, see Partition II, section 8 and its subsections. For information on overriding (the NewSlot flag), see Partition II, section 9.3.1. |
ANNOTATION Implementation-Specific (Microsoft): UnmanagedExport indicates a managed method exported via thunk to unmanaged code. |
22.1.10 Flags for Methods (MethodImplAttributes) Flag | Value | Description |
|---|
CodeTypeMask | 0x0003 | | IL | 0x0000 | Method impl is CIL. | Native | 0x0001 | Method impl is native. | OPTIL | 0x0002 | Reserved: shall be zero in conforming implementations. | Runtime | 0x0003 | Method impl is provided by the runtime. | ManagedMask | 0x0004 | Flags specifying whether the code is managed or unmanaged. | Unmanaged | 0x0004 | Method impl is unmanaged, otherwise managed. | Managed | 0x0000 | Method impl is managed. | Implementation Info and Interop | ForwardRef | 0x0010 | Indicates method is defined; used primarily in merge scenarios. | PreserveSig | 0x0080 | Reserved: conforming implementations may ignore. | InternalCall | 0x1000 | Reserved: shall be zero in conforming implementations. | Synchronized | 0x0020 | Method is single-threaded through the body. | NoInlining | 0x0008 | Method may not be inlined. | MaxMethodImplVal | 0xffff | Range check value. | ANNOTATION Implementation-Specific (Microsoft): The PreserveSig method signature is not to be mangled to do HRESULT conversion. |
22.1.11 Flags for MethodSemantics (MethodSemanticsAttributes) Flag | Value | Description |
|---|
Setter | 0x0001 | Setter for property | Getter | 0x0002 | Getter for property | Other | 0x0004 | Other method for property or event | AddOn | 0x0008 | AddOn method for event | RemoveOn | 0x0010 | RemoveOn method for event | Fire | 0x0020 | Fire method for event | ANNOTATION For more information on properties and events, see Partition II, sections 16 and 17. |
22.1.12 Flags for Params (ParamAttributes) Flag | Value | Description |
|---|
In | 0x0001 | Param is [In]. | Out | 0x0002 | Param is [Out]. | Optional | 0x0010 | Param is optional. | HasDefault | 0x1000 | Param has default value. | HasFieldMarshal | 0x2000 | Param has FieldMarshal. | Unused | 0xcfe0 | Reserved: shall be zero in a conforming implementation. | 22.1.13 Flags for Properties (PropertyAttributes) Flag | Value | Description |
|---|
SpecialName | 0x0200 | Property is special. | RTSpecialName | 0x0400 | Runtime (metadata internal APIs) should check name encoding. | HasDefault | 0x1000 | Property has default. | Unused | 0xe9ff | Reserved: shall be zero in a conforming implementation. | 22.1.14 Flags for Types (TypeAttributes) Flag | Value | Description |
|---|
Visibility Attributes | VisibilityMask | 0x00000007 | Use this mask to retrieve visibility information. | NotPublic | 0x00000000 | Class has no public scope. | Public | 0x00000001 | Class has public scope. | NestedPublic | 0x00000002 | Class is nested with public visibility. | NestedPrivate | 0x00000003 | Class is nested with private visibility. | NestedFamily | 0x00000004 | Class is nested with family visibility. | NestedAssembly | 0x00000005 | Class is nested with assembly visibility. | NestedFamANDAssem | 0x00000006 | Class is nested with family and assembly visibility. | NestedFamORAssem | 0x00000007 | Class is nested with family or assembly visibility. | Class Layout Attributes | LayoutMask | 0x00000018 | Use this mask to retrieve class layout information. | AutoLayout | 0x00000000 | Class fields are auto-laid out. | SequentialLayout | 0x00000008 | Class fields are laid out sequentially. | ExplicitLayout | 0x00000010 | Layout is supplied explicitly. | Class Semantics Attributes | ClassSemanticsMask | 0x00000020 | Use this mask to retrieve class semantics information. | Class | 0x00000000 | Type is a class. | Interface | 0x00000020 | Type is an interface. | Special Semantics in Addition to Class Semantics | Abstract | 0x00000080 | Class is abstract. | Sealed | 0x00000100 | Class cannot be extended. | SpecialName | 0x00000400 | Class name is special. | Implementation Attributes | Import | 0x00001000 | Class/Interface is imported. | Serializable | 0x00002000 | Class is serializable. | String Formatting Attributes | StringFormatMask | 0x00030000 | Use this mask to retrieve string information for native interop. | AnsiClass | 0x00000000 | LPSTR is interpreted as ANSI. | UnicodeClass | 0x00010000 | LPSTR is interpreted as Unicode. | AutoClass | 0x00020000 | LPSTR is interpreted automatically. | Class Initialization Attributes | BeforeFieldInit | 0x00100000 | Initialize the class before first static field access. | Additional Flags | RTSpecialName | 0x00000800 | CLI provides "special" behavior, depending upon the name of the Type. | HasSecurity | 0x00040000 | Type has security associated with it. | 22.1.15 Element Types Used in Signatures The following table lists the values for ELEMENT_TYPE constants. These are used extensively in metadata signature blobs see Partition II, section 22.2. ANNOTATION For more information on element types, see Partition II, sections 21.9 and 21.10. |
ANNOTATION Implementation-Specific (Microsoft): These values are defined in the file inc\CorHdr.h in the Microsoft .NET SDK. |
Name | Value | Remarks |
|---|
ELEMENT_TYPE_END | 0x00 | Marks end of a list. | ELEMENT_TYPE_VOID | 0x01 | | ELEMENT_TYPE_BOOLEAN | 0x02 | | ELEMENT_TYPE_CHAR | 0x03 | | ELEMENT_TYPE_I1 | 0x04 | | ELEMENT_TYPE_U1 | 0x05 | | ELEMENT_TYPE_I2 | 0x06 | | ELEMENT_TYPE_U2 | 0x07 | | ELEMENT_TYPE_I4 | 0x08 | | ELEMENT_TYPE_U4 | 0x09 | | ELEMENT_TYPE_I8 | 0x0a | | ELEMENT_TYPE_U8 | 0x0b | | ELEMENT_TYPE_R4 | 0x0c | | ELEMENT_TYPE_R8 | 0x0d | | ELEMENT_TYPE_STRING | 0x0e | | ELEMENT_TYPE_PTR | 0x0f | Followed by <type> token. | ELEMENT_TYPE_BYREF | 0x10 | Followed by <type> token. | ELEMENT_TYPE_VALUETYPE | 0x11 | Followed by TypeDef or TypeRef token. | ELEMENT_TYPE_CLASS | 0x12 | Followed by TypeDef or TypeRef token. | ELEMENT_TYPE_ARRAY | 0x14 | <type> <rank> <boundsCount> <bound1> … <loCount> <lo1> … | ELEMENT_TYPE_TYPEDBYREF | 0x16 | | ELEMENT_TYPE_I | 0x18 | System.IntPtr. | ELEMENT_TYPE_U | 0x19 | System.UIntPtr. | ELEMENT_TYPE_FNPTR | 0x1b | Followed by full method signature. | ELEMENT_TYPE_OBJECT | 0x1c | System.Object. | ELEMENT_TYPE_SZARRAY | 0x1d | Single-dim array with 0 lower bound. | ELEMENT_TYPE_CMOD_REQD | 0x1f | Required modifier: followed by a TypeDef or TypeRef token. | ELEMENT_TYPE_CMOD_OPT | 0x20 | Optional modifier: followed by a TypeDef or TypeRef token. | ELEMENT_TYPE_INTERNAL | 0x21 | Implemented within the CLI. | ELEMENT_TYPE_MODIFIER | 0x40 | OR'd with following element types. | ELEMENT_TYPE_SENTINEL | 0x41 | Sentinel for varargs method signature. | ELEMENT_TYPE_PINNED | 0x45 | Denotes a local variable that points at a pinned object. | 22.2 Blobs and Signatures The word "signature" is conventionally used to describe the type info for a function or method that is, the type of each of its parameters, and the type of its return value. Within metadata, the word "signature" is also used to describe the type info for fields, properties, and local variables. Each Signature is stored as a (counted) byte array in the Blob heap. There are six kinds of Signatures, as follows: The value of the leading byte of a Signature "blob" indicates what kind of Signature it is. This section defines the binary "blob" format for each kind of Signature. Note that Signatures are compressed before being stored into the Blob heap (described below) by compressing the integers embedded in the signature. The maximum encodable integer is 29 bits long, 0x1FFFFFFF. The compression algorithm used is as follows (bit 0 is the least significant bit): If the value lies between 0 (0x00) and 127 (0x7F), inclusive, encode as a 1-byte integer (bit #7 is clear, value held in bits #6 through #0). If the value lies between 28 (0x80) and 214 1 (0x3FFF), inclusive, encode as a 2-byte integer with bit #15 set, bit #14 clear (value held in bits #13 through #0). Otherwise, encode as a 4-byte integer, with bit #31 set, bit #30 set, bit #29 clear (value held in bits #28 through #0). A null string should be represented with the reserved single-byte 0xFF, and no following data. NOTE The table below shows several examples. The first column gives a value, expressed in familiar (C-like) hex notation. The second column shows the corresponding, compressed result, as it would appear in a PE file, with successive bytes of the result lying at successively higher byte offsets within the file. (This is the opposite order from how regular binary integers are laid out in a PE file.) Original Value | Compressed Representation |
|---|
0x03 | 03 | 0x7F | 7F (7 bits set) | 0x80 | 8080 | 0x2E57 | AE57 | 0x3FFF | BFFF | 0x4000 | C000 4000 | 0x1FFF FFFF | DFFF FFFF | Thus, the most significant bits (the first ones encountered in a PE file) of a "compressed" field, can reveal whether it occupies 1, 2, or 4 bytes, as well as its value. For this to work, the "compressed" value, as explained above, is stored in big-endian order with the most significant byte at the smallest offset within the file. ANNOTATION As you will note, the "compressions" above do not always reduce the size of the values. This type of compression allows smaller values to be stored in fewer than 4 bytes, because statistically, more small positive or negative numbers are used than larger values. Integers near zero use only 1 byte instead of 4, and slightly larger values use 2 bytes instead of 4. |
Signatures make extensive use of constant values called ELEMENT_TYPE_xxx see Partition II, section 22.1.15. In particular, signatures include two modifiers called: ELEMENT_TYPE_BYREF this element is a managed pointer [see the annotation to Partition I, section 8.9.2]. This modifier can only occur in the definition of Param (Partition II, section 22.2.10) or RetType (Partition II, section 22.2.11). It shall not occur within the definition of a Field (Partition II, section 22.2.4). ELEMENT_TYPE_PTR this element is an unmanaged pointer (see Partition I [section 8.9.2]). This modifier can occur in the definition of Param (Partition II, section 22.2.10) or RetType (Partition II, section 22.2.11) or Field (Partition II, section 22.2.4). ANNOTATION For a field, the signature would be the type of the field. For a method, it would be the return type, the number of parameters, all of the parameter types, etc. |
22.2.1 MethodDefSig A MethodDefSig is indexed by the Method.Signature column. It captures the signature of a method or global function. The syntax chart for a MethodDefSig is:  This chart uses the following abbreviations (see Partition II, section 14.3): HASTHIS = 0x20, used to encode the keyword instance in the calling convention EXPLICITTHIS = 0x40, used to encode the keyword explicit in the calling convention DEFAULT = 0x0, used to encode the keyword default in the calling convention VARARG = 0x5, used to encode the keyword vararg in the calling convention ANNOTATION Implementation-Specific (Microsoft): The above names are defined in the file inc\CorHdr.h as part of the Microsoft .NET SDK, using a prefix of IMAGE_CEE_ CS_CALLCONV_. |
The first byte of the Signature holds bits for HASTHIS, EXPLICITTHIS, and calling convention DEFAULT or VARARG. These are OR'd together. ParamCount is an integer that holds the number of parameters (0 or more). It can be any number between 0 and 0x1FFFFFFF. The compiler compresses it too (see Partition II, Metadata Validation [section 3]) before storing into the "blob" (ParamCount counts just the method parameters it does not include the method's return type). The RetType item describes the type of the method's return value (see Partition II, section 22.2.11). The Param item describes the type of each of the method's parameters. There shall be ParamCount instances of the Param item (see Partition II, section 22.2.10). 22.2.2 MethodRefSig A MethodRefSig is indexed by the MemberRef.Signature column. This provides the call-site Signature for a method. Normally, this call-site Signature shall match exactly the Signature specified in the definition of the target method. For example, if a method Foo is defined that takes two uint32's and returns void; then any call site shall index a signature that takes exactly two uint32's and returns void. In this case, the syntax chart for a MethodRefSig is identical with that for a MethodDefSig see Partition II, section 22.2.1. The Signature at a call site differs from that at its definition, only for a method with the VARARG calling convention. In this case, the call-site Signature is extended to include info about the extra VARARG arguments (for example, corresponding to the "..." in C syntax). The syntax chart for this case is:  This chart uses the following abbreviations (see Partition II, section 14.3): HASTHIS = 0x20, used to encode the keyword instance in the calling convention EXPLICITTHIS = 0x40, used to encode the keyword explicit in the calling convention DEFAULT = 0x0, used to encode the keyword default in the calling convention VARARG = 0x5, used to encode the keyword vararg in the calling convention SENTINEL = 0x41 (see Partition II, section 22.1.15), used to encode "..." in the parameter list ANNOTATION Implementation-Specific (Microsoft): The above names are defined in the file inc\CorHdr.h as part of the SDK, using a prefix of IMAGE_CEE_CS_CALLCONV_. |
The first byte of the Signature holds bits for HASTHIS, EXPLICITTHIS, and calling convention DEFAULT, VARARG, C, STDCALL, THISCALL, or FASTCALL. These are OR'd together. ParamCount is an integer that holds the number of parameters (0 or more). It can be any number between 0 and 0x1FFFFFFF. The compiler compresses it too (see Partition II, Metadata Validation [section 3]) before storing into the "blob" (ParamCount counts just the method parameters it does not include the method's return type). The RetType item describes the type of the method's return value (see Partition II, section 22.2.11). The Param item describes the type of each of the method's parameters. There shall be ParamCount instances of the Param item (see Partition II, section 22.2.10). The Param item describes the type of each of the method's parameters. There shall be ParamCount instances of the Param item. This starts just like the MethodDefSig for a VARARG method (see Partition II, section 22.2.1). But then a SENTINEL token is appended, followed by extra Param items to describe the extra VARARG arguments. Note that the ParamCount item shall indicate the total number of Param items in the Signature before and after the SENTINEL byte (0x41). In the unusual case that a call site supplies no extra arguments, the signature shall not include a SENTINEL (this is the route shown by the lower arrow that bypasses SENTINEL and goes to the end of the MethodRefSig definition). 22.2.3 StandAloneMethodSig A StandAloneMethodSig is indexed by the StandAloneSig.Signature column. It is typically created as preparation for executing a calli instruction. It is similar to a MethodRefSig, in that it represents a call-site signature, but its calling convention may specify an unmanaged target (the calli instruction invokes either managed or unmanaged code). Its syntax chart is:  This chart uses the following abbreviations (see Partition II, section 14.3): HASTHIS for 0x20 EXPLICITTHIS for 0x40 DEFAULT for 0x0 VARARG for 0x5 C for 0x1 STDCALL for 0x2 THISCALL for 0x3 FASTCALL for 0x4 SENTINEL for 0x41 (see Partition II, section 22.1.15 and Partition II, section 14.3) ANNOTATION Implementation-Specific (Microsoft): The above names are defined in the file inc\CorHdr.h as part of the Microsoft .NET SDK, using a prefix of IMAGE_CEE_CS_ CALLCONV_. |
The first byte of the Signature holds bits for HASTHIS, EXPLICITTHIS, and calling convention DEFAULT, VARARG, C, STDCALL, THISCALL, or FASTCALL. These are OR'd together. ParamCount is an integer that holds the number of parameters (0 or more). It can be any number between 0 and 0x1FFFFFFF. The compiler compresses it too (see Partition II, Metadata Validation [section 3]) before storing into the "blob" (ParamCount counts just the method parameters it does not include the method's return type). The RetType item describes the type of the method's return value (see Partition II, section 22.2.11). The Param item describes the type of each of the method's parameters. There shall be ParamCount instances of the Param item (see Partition II, section 22.2.10). This is the most complex of the various method signatures. Two separate charts have been combined into one in this diagram, using shading to distinguish between them. Thus, for the following calling conventions: DEFAULT (managed), STDCALL, THISCALL, and FASTCALL (unmanaged), the signature ends just before the SENTINEL item (these are all non-vararg signatures). However, for the managed and unmanaged vararg calling conventions: VARARG (managed) and C (unmanaged), the signature can include the SENTINEL and final Param items (they are not required, however). These options are indicated by the shading of boxes in the syntax chart. 22.2.4 FieldSig A FieldSig is indexed by the Field.Signature column or by the MemberRef.Signature column (in the case where it specifies a reference to a field, not a method, of course). The Signature captures the field's definition. The field may be a static or instance field in a class, or it may be a global variable. The syntax chart for a FieldSig looks like this:  This chart uses the following abbreviations: FIELD for 0x6 ANNOTATION Implementation-Specific (Microsoft): The above name is defined in the file inc\CorHdr.h as part of the Microsoft .NET SDK, using a prefix of IMAGE_CEE_CS_ CALLCONV_FIELD. |
CustomMod is defined in Partition II, section 22.2.7. Type is defined in Partition II, section 22.2.12. 22.2.5 PropertySig A PropertySig is indexed by the Property.Type column. It captures the type information for a Property essentially, the signature of its getter method: How many parameters are supplied to its getter method The base type of the Property the type returned by its getter method Type information for each parameter in the getter method that is, the index parameters Note that the signatures of the getter and setter are related precisely as follows: The types of a getter's paramCount parameters are exactly the same as the first paramCount parameters of the setter. The return type of a getter is exactly the same as the type of the last parameter supplied to the setter. The syntax chart for a PropertySig looks like this:  This chart uses the following abbreviations: PROPERTY for 0x8 ANNOTATION Implementation-Specific (Microsoft): The above name is defined in the file inc\CorHdr.h as part of the Microsoft .NET SDK, using a prefix of IMAGE_CEE_CS_ CALLCONV_PROPERTY. |
Type specifies the type returned by the getter method for this property. Type is defined in Partition II, section 22.2.12. Param is defined in Partition II, section 22.2.10. ParamCount is an integer that holds the number of index parameters in the getter methods (0 or more) (see Partition II, section 22.2.1). (ParamCount counts just the method parameters it does not include the method's base type of the Property.) 22.2.6 LocalVarSig A LocalVarSig is indexed by the StandAloneSig.Signature column. It captures the type of all the local variables in a method. Its syntax chart is:  This chart uses the following abbreviations: LOCAL_SIG for 0x7, used for the .locals directive (see Partition II, section 14.4.1.3) ANNOTATION Implementation-Specific (Microsoft): The above name is defined in the file inc\CorHdr.h as part of the Microsoft .NET SDK, using a prefix of IMAGE_CEE_CS_ CALLCONV_LOCAL_SIG. |
BYREF for ELEMENT_TYPE_BYREF (see Partition II, section 22.1.15) Constraint is defined in Partition II, section 22.2.9. Type is defined in Partition II, section 22.2.12. Count is an unsigned integer that holds the number of local variables. It can be any number between 1 and 0xFFFE. There shall be Count instances of the Type in the LocalVarSig. 22.2.7 CustomMod The CustomMod (custom modifier) item in Signatures has a syntax chart like this:  This chart uses the following abbreviations: CMOD_OPT | for | LEMENT_TYPE_CMOD_OPT (see Partition II, section 22.1.15) | CMOD_REQD | for | ELEMENT_TYPE_CMOD_REQD (see Partition II, section 22.1.15) | The CMOD_OPT or CMOD_REQD value is compressed (see Partition II, section 22.2). The CMOD_OPT or CMOD_REQD is followed by a metadata token that indexes a row in the TypeDef table or the TypeRef table. However, these tokens are encoded and compressed see Partition II, section 22.2.8 for details. If the custom modifier is tagged CMOD_OPT, then any importing compiler can freely ignore it entirely. Conversely, if the custom modifier is tagged CMOD_REQD, any importing compiler shall "understand|" the semantic implied by this custom modifier in order to reference the surrounding Signature. ANNOTATION Implementation-Specific (Microsoft): A typical use for a custom modifier is for Visual C++ .NET to denote a method parameter as const. It does this using a CMOD_OPT, followed by a TypeRef to Microsoft.VisualC.IsConstModifier (defined in Microsoft.VisualC.DLL). Visual C++ .NET also uses a custom modifier (embedded within a RetType see Partition II, section 22.2.11) to mark the native calling convention of a function. Of course, if that routine is implemented as managed code, this info is not used. But if it turns out to be implemented as unmanaged code, it becomes crucial that automatically generated thunks marshal the arguments correctly. This technique is used in IJW ("It Just Works") scenarios. Strictly speaking, such a custom modifier does not apply only to the RetType; it really applies to the whole function. In these cases, the TypeRef following the CMOD_OPT is to one of CallConvCdecl, CallConvStdcall, CallConvThiscall, or CallConvFastcall. |
22.2.8 TypeDef or Ref Encoded These items are compact ways to store a TypeDef or TypeRef token in a Signature (see Partition II, section 22.2.12). Consider a regular TypeRef token, such as 0x01000012. The top byte of 0x01 indicates that this is a TypeRef token (see Partition V for a list of the supported metadata token types). The lower 3 bytes (0x000012) index row number 0x12 in the TypeRef table. The encoded version of this TypeRef token is made up as follows: Encode the table that this token indexes as the least significant 2 bits. The bit values to use are 0, 1, and 2, specifying the target table is the TypeDef, TypeRef, or TypeSpec table, respectively. Shift the 3-byte row index (0x000012 in this example) left by 2 bits, and OR into the 2-bit encoding from step 1. Compress the resulting value (see Partition II, section 22.2). This example yields the following encoded value: a) encoded = value for TypeRef table = 0x01 (from 1. above) b) encoded = ( 0x000012 << 2 ) | 0x01 = 0x48 | 0x01 = 0x49 c) encoded = Compress (0x49) = 0x49 So, instead of the original, regular TypeRef token value of 0x01000012, requiring 4 bytes of space in the Signature "blob," this TypeRef token is encoded as a single byte. 22.2.9 Constraint The Constraint item in Signatures currently has only one possible value ELEMENT_TYPE_PINNED (see Partition II, section 22.1.15), which specifies that the target type is pinned in the runtime heap, and will not be moved by the actions of garbage collection. A Constraint can only be applied within a LocalVarSig (not a FieldSig). The Type of the local variable shall either be a reference type (in other words, it points to the actual variable for example, an Object or a String); or it shall include the BYREF item. The reason is that local variables are allocated on the runtime stack they are never allocated from the runtime heap; so unless the local variable points at an object allocated in the GC heap, pinning makes no sense. 22.2.10 Param The Param (parameter) item in Signatures has this syntax chart:  This chart uses the following abbreviations: BYREF | for | 0x10 (see Partition II, section 22.1.15) | TYPEDBYREF | for | 0x16 (see Partition II, section 22.1.15) | CustomMod is defined in Partition II, section 22.2.7. Type is defined in Partition II, section 22.2.12. 22.2.11 RetType The RetType (return type) item in Signatures has this syntax chart:  RetType is identical to Param except for one extra possibility, that it can include the type VOID. This chart uses the following abbreviations: BYREF | for | ELEMENT_TYPE_BYREF (see Partition II, section 22.1.15) | TYPEDBYREF | for | ELEMENT_TYPE_TYPEDBYREF (see Partition II, section 22.1.15) | VOID | for | ELEMENT_TYPE_VOID (see Partition II, section 22.1.15) | 22.2.12 Type Type is encoded in signatures as follows (I1 is an abbreviation for ELEMENT_TYPE_I1, etc.; see Partition II, section 22.1.15): Type ::= BOOLEAN | CHAR | I1 | U1 | I2 | U2 | I4 | U4 | I8 | U8 | R4 | R8 | I | U | | VALUETYPE TypeDefOrRefEncoded | CLASS TypeDefOrRefEncoded | STRING | OBJECT | PTR CustomMod* VOID | PTR CustomMod* Type | FNPTR MethodDefSig | FNPTR MethodRefSig | ARRAY Type ArrayShape (general array, see Partition II, section 22.2.13) | SZARRAY CustomMod* Type (single-dimensional, zero-based array--i.e., vector) 22.2.13 ArrayShape An ArrayShape has the following syntax chart:  Rank is an integer (stored in compressed form; see Partition II, section 22.2) that specifies the number of dimensions in the array (shall be 1 or more). NumSizes is a compressed integer that says how many dimensions have specified sizes (it shall be 0 or more). Size is a compressed integer specifying the size of that dimension the sequence starts at the first dimension, and goes on for a total of NumSizes items. Similarly, NumLoBounds is a compressed integer that says how many dimensions have specified lower bounds (it shall be 0 or more). And LoBound is a compressed integer specifying the lower bound of that dimension the sequence starts at the first dimension and goes on for a total of NumLoBounds items. None of the dimensions in these two sequences can be skipped, but the number of specified dimensions can be less than Rank. Here are a few examples, all for element type int32: | | Type | Rank | NumSizes | Size | NumLoBounds | LoBound |
|---|
| | | | | | | | [0...2] | I4 | 1 | 1 | 3 | 0 | | [,,,,,,] | I4 | 7 | 0 | | 0 | | [0...3, 0...2,,,,] | I4 | 6 | 2 | 4 3 | 2 | 0 0 | [1...2, 6...8] | I4 | 2 | 2 | 2 3 | 2 | 1 6 | [5, 3...5, , ] | I4 | 4 | 2 | 5 3 | 2 | 0 3 | NOTE Definitions can nest, since the Type may itself be an array. 22.2.14 TypeSpec The signature in the Blob heap indexed by a TypeSpec token has the following format: TypeSpecBlob :== PTR CustomMod* VOID | PTR CustomMod* Type | FNPTR MethodDefSig | FNPTR MethodRefSig | ARRAY Type ArrayShape | SZARRAY CustomMod* Type For compactness, the ELEMENT_TYPE_ prefixes have been omitted from this list. So, for example, PTR is shorthand for ELEMENT_TYPE_PTR (see Partition II, section 22.1.15). Note that a TypeSpecBlob does not begin with a calling-convention byte, so it differs from the various other signatures that are stored into metadata. 22.2.15 Short-Form Signatures The general specification for signatures leaves some leeway in how to encode certain items. For example, it appears legal to encode a String as either Long-form: ELEMENT_TYPE_CLASS, TypeRef-to-System.String Short-form: ELEMENT_TYPE_STRING Only the short form is valid. The following table shows which short forms should be used in place of each long-form item. (As usual, for compactness, the ELEMENT_TYPE_ prefixes have been omitted here so VALUETYPE is short for ELEMENT_TYPE_VALUETYPE.) Long Form | Short Form |
|---|
Prefix | TypeRef to: | |
|---|
CLASS | System.String | STRING | CLASS | System.Object | OBJECT | VALUETYPE | System.Void | VOID | VALUETYPE | System.Boolean | BOOLEAN | VALUETYPE | System.Char | CHAR | VALUETYPE | System.Byte | U1 | VALUETYPE | System.Sbyte | I1 | VALUETYPE | System.Int16 | I2 | VALUETYPE | System.UInt16 | U2 | VALUETYPE | System.Int32 | I4 | VALUETYPE | System.UInt32 | U4 | VALUETYPE | System.Int64 | I8 | VALUETYPE | System.UInt64 | U8 | VALUETYPE | System.IntPtr | I | VALUETYPE | System.UIntPtr | U | VALUETYPE | System.TypedReference | TYPEDBYREF | NOTE Arrays shall be encoded in signatures using one of ELEMENT_TYPE_ARRAY or ELEMENT_TYPE_SZARRAY. There is no long form involving a TypeRef to System.Array. 22.3 Custom Attributes A Custom Attribute has the following syntax chart:  All binary values are stored in little-endian format (except PackedLen items used only as counts for the number of bytes to follow in a UTF8 string). If there are no fields, parameters, or properties specified, the entire attribute may be represented as an empty blob. CustomAttrib starts with a Prolog an unsigned int16, with value 0x0001. Next comes a description of the fixed arguments for the constructor method. Their number and type is found by examining that constructor's MethodDef; this info is not repeated in the CustomAttrib itself. As the syntax chart shows, there can be zero or more FixedArgs. (Note that VARARG constructor methods are not allowed in the definition of Custom Attributes.) Next is a description of the optional "named" fields and properties. This starts with NumNamed an unsigned int16 giving the number of "named" properties or fields that follow. Note that NumNamed shall always be present. If its value is zero, there are no "named" properties or fields to follow (and of course, in this case, the CustomAttrib shall end immediately after NumNamed). In the case where NumNamed is non-zero, it is followed by NumNamed repeats of NamedArgs.  The format for each FixedArg depends upon whether that argument is single, or an SZARRAY this is shown in the upper and lower paths, respectively, of the syntax chart [above]. So each FixedArg is either a single Elem, or NumElem repeats of Elem. (SZARRAY is the single byte 0x1d and denotes a vector a single-dimension array with a lower bound of zero.) NumElem is an unsigned int32 specifying the number of elements in the SZARRAY, or 0xFFFFFFFF to indicate that the value is null.  An Elem takes one of three forms: If the parameter kind is simple (bool, char, float32, float64, int8, int16, int32, int64, unsigned int8, unsigned int16, unsigned int32, or unsigned int64) then the "blob" contains its binary value (Val). This pattern is also used if the parameter kind is an enum simply store the value of the enum's underlying integer type. If the parameter kind is string or type, then the blob contains a SerString a PackedLen count of bytes, followed by the UTF8 characters. A type is stored as a string giving the full name of that type. Where the actual argument value is null, it shall be encoded as the single byte 0xFF. For parameters, fields, or properties whose formal (static) type is System.Object, the blob contains the actual type's FieldOrPropType (see below), followed by the representation of the actual parameter. (Note: it is not possible to pass a value of null in this case.) Val is the binary value for a simple type. A bool is a single byte with value 0 (false) or 1 (true); char is a two-byte unicode character; and the others have their obvious meaning.  A NamedArg is simply a FixedArg (discussed above) preceded by information to identify which field or property it represents. FIELD is the single byte 0x53. PROPERTY is the single byte 0x54. If the parameter kind is a boxed simple value type (bool, char, float32, float64, int8, int16, int32, int64, unsigned int8, unsigned int16, unsigned int32, or unsigned int64), then FieldOrPropType is immediately preceded by a byte containing the value 0x51. The FieldOrPropType shall be exactly one of: ELEMENT_TYPE_BOOLEAN, ELEMENT_TYPE_CHAR, ELEMENT_TYPE_I1, ELEMENT_TYPE_U1, ELEMENT_TYPE_I2, ELEMENT_TYPE_U2, ELEMENT_TYPE_I4, ELEMENT_TYPE_U4, ELEMENT_TYPE_I8, ELEMENT_TYPE_U8, ELEMENT_TYPE_R4, ELEMENT_TYPE_R8, ELEMENT_TYPE_STRING, or the constant 0x50 (for an argument of type Type). A single-dimensional, zero-based array is specified as a single byte 0x1D followed by the FieldOrPropType of the element type. (See Partition II, section 22.1.15.) The FieldOrPropName is the name of the field or property, stored as a SerString (defined above). The SerString used to encode an argument of type Type includes the full type name, followed optionally by the assembly where it is defined, its version, culture, and public key token. If the assembly name is omitted, the CLI looks first in this assembly, and then the assembly named mscorlib. For example, consider the Type string "Ozzy.OutBack.Kangaroo+Wallaby, MyAssembly" for a class "Wallaby" nested within class "Ozzy.OutBack.Kangaroo", defined in the assembly "MyAssembly". 22.4 Marshalling Descriptors A marshalling descriptor is like a signature it's a "blob" of binary data. It describes how a field or parameter (which, as usual, covers the method return, as parameter number 0) should be marshalled when calling to or from unmanaged code via PInvoke dispatch. The ilasm syntax marshal can be used to create a marshalling descriptor, as can the pseudo custom attribute MarshalAsAttribute see Partition II, section 20.2.1.) Note that a conforming implementation of the CLI need only support marshalling of the types specified earlier see Partition II, section 14.5.5. Marshalling descriptors make use of constants named NATIVE_TYPE_xxx. Their names and values are listed in the following table: Name | Value |
|---|
NATIVE_TYPE_BOOLEAN | 0x02 | NATIVE_TYPE_I1 | 0x03 | NATIVE_TYPE_U1 | 0x04 | NATIVE_TYPE_I2 | 0x05 | NATIVE_TYPE_U2 | 0x06 | NATIVE_TYPE_I4 | 0x07 | NATIVE_TYPE_U4 | 0x08 | NATIVE_TYPE_I8 | 0x09 | NATIVE_TYPE_U8 | 0x0a | NATIVE_TYPE_R4 | 0x0b | NATIVE_TYPE_R8 | 0x0c | NATIVE_TYPE_LPSTR | 0x14 | NATIVE_TYPE_INT | 0x1f | NATIVE_TYPE_UINT | 0x20 | NATIVE_TYPE_FUNC | 0x26 | NATIVE_TYPE_ARRAY | 0x2a | ANNOTATION Implementation-Specific (Microsoft): The Microsoft implementation supports a richer set of types to describe marshalling between Windows native types and COM. These additional options are listed in the following table: |
Name | Value | Remarks |
|---|
NATIVE_TYPE_CURRENCY | 0x0f | | NATIVE_TYPE_BSTR | 0x13 | | NATIVE_TYPE_LPWSTR | 0x15 | | NATIVE_TYPE_LPTSTR | 0x16 | | NATIVE_TYPE_FIXEDSYSSTRING | 0x17 | | NATIVE_TYPE_IUNKNOWN | 0x19 | | NATIVE_TYPE_IDISPATCH | 0x1a | | NATIVE_TYPE_STRUCT | 0x1b | | NATIVE_TYPE_INTF | 0x1c | | NATIVE_TYPE_SAFEARRAY | 0x1d | | NATIVE_TYPE_FIXEDARRAY | 0x1e | | NATIVE_TYPE_BYVALSTR | 0x22 | | NATIVE_TYPE_ANSIBSTR | 0x23 | | NATIVE_TYPE_TBSTR | 0x24 | Selects BSTR or ANSIBSTR depending on platform. | NATIVE_TYPE_VARIANTBOOL | 0x25 | 2-byte Boolean value: false = 0; true = 1. | NATIVE_TYPE_ASANY | 0x28 | | NATIVE_TYPE_LPSTRUCT | 0x2b | | NATIVE_TYPE_CUSTOMMARSHALER | 0x2c | Custom marshaller native type. Shall be followed by a string in the format: "Native type name/0Custom marshaler type name/0Optional cookie/0" OR "{Native type GUID}/0Custom marshaler type name/0Optional cookie/0" | NATIVE_TYPE_ERROR | 0x2d | This native type coupled with ELEMENT_TYPE_I4 will map to VT_HRESULT. | NATIVE_TYPE_MAX | 0X50 | Used to indicate "no info." | The "blob" has the following format: MarshalSpec ::= NativeInstrinsic | ARRAY ArrayElemType ParamNum ElemMult NumElem ANNOTATION Implementation-Specific (Microsoft): The Microsoft implementation supports a wider range of options: MarshalSpec ::= NativeIntrinsic | ARRAY ArrayElemType ParamNum ElemMult NumElem | CUSTOMMARSHALLER Guid UnmanagedType ManagedType Cookie | FIXEDARRAY NumElem ArrayElemType | SAFEARRAY SafeArrayElemType |
NativeInstrinsic ::= BOOLEAN | I1 | U1 | I2 | U2 | I4 | U4 | I8 | U8 | R4 | R8 | CURRENCY | BSTR | LPSTR | LPWSTR | LPTSTR | INT | UINT | FUNC | LPVOID For compactness, the NATIVE_TYPE_ prefixes have been omitted in the above lists. So, for example, ARRAY is shorthand for NATIVE_TYPE_ARRAY. ANNOTATION Implementation-Specific (Microsoft): NativeIntrinsic ::= … | FIXEDSYSSTRING | STRUCT | INTF | FIXEDARRAY | BYVALSTR | ANSIBSTR | | TBSTR | VARIANTBOOL | ASANY | LPSTRUCT | ERROR Guid is a counted-UTF8 string e.g., "{90883F05-3D28-11D2-8F17-00A0C9A6186D}" it shall include leading "{" and trailing "}" and be exactly 38 characters long. UnmanagedType is a counted-UTF8 string e.g., "Point". ManagedType is a counted-UTF8 string e.g., "System.Util.MyGeometry" it shall be the fully qualified name (namespace and name) of a managed Type defined within the current Assembly (that Type shall implement ICustomMarshaller, and provides a "to" and "from" marshalling method). Cookie is a counted-UTF8 string e.g., "123" an empty string is allowed. |
NumElem is an integer (compressed as described in Partition II, section 22.2) that specifies how many elements are in the array. ArrayElemType :== NativeInstrinsic | BOOLEAN | I1 | U1 | I2 | U2 | I4 | U4 | I8 | U8 | R4 | R8 | LPSTR | INT | UINT | FUNC | LPVOID ANNOTATION Implementation-Specific (Microsoft): ArrayElemType ::= … | BSTR | LPWSTR | LPTSTR | FIXEDSYSSTRING | STRUCT | INTF | BYVALSTR | ANSIBSTR | TBSTR | VARIANTBOOL | ASANY | LPSTRUCT | ERROR | MAX The value MAX is used to indicate "no info." The following information and table are specific to the Microsoft implementation of the CLI: SafeArrayElemType ::= I2 | I4 | R4 | R8 | CY | DATE | BSTR | DISPATCH | | ERROR | BOOL | VARIANT | UNKNOWN | DECIMAL | I1 | UI1 | UI2 | UI4 | INT | UINT where each is prefixed by VT_. The values for the VT_xxx constants are given in the following table: Constant | Value |
|---|
VT_I2 | = 2, | VT_I4 | = 3, | VT_R4 | = 4, | VT_R8 | = 5, | VT_CY | = 6, | VT_DATE | = 7, | VT_BSTR | = 8, | VT_DISPATCH | = 9, | VT_ERROR | = 10, | VT_BOOL | = 11, | VT_VARIANT | = 12, | VT_UNKNOWN | = 13, | VT_DECIMAL | = 14, | VT_I1 | = 16, | VT_UI1 | = 17, | VT_UI2 | = 18, | VT_UI4 | = 19, | VT_INT | = 22, | VT_UINT | = 23, |
|
ParamNum is an integer (compressed as described in Partition II, section 22.2) specifying the parameter in the method call that provides the number of elements in the array see below. ElemMult is an integer compressed as described in Partition II, section 22.2 (says by whatfactor to multiply see below). NOTE For example, in the method declaration: Foo (int ar1[], int size1, byte ar2[], int size2) The ar1 parameter might own a row in the FieldMarshal table, which indexes a MarshalSpec in the Blob heap with the format: ARRAY MAX 2 1 0 This says the parameter is marshalled to a NATIVE_TYPE_ARRAY. There is no additional info about the type of each element (signified by that NATIVE_TYPE_MAX). The value of ParamNum is 2, which indicates that parameter number 2 in the method (the one called "size1") will specify the number of elements in the actual array let's suppose its value on a particular call is 42. The value of ElemMult is 1. The value of NumElem is 0. The calculated total size, in bytes, of the array is given by the formula: if ParamNum == 0 SizeInBytes = NumElem * sizeof (elem) else SizeInBytes = ( @ParamNum * ElemMult + NumElem ) * sizeof (elem) endif The syntax "@ParamNum" is used here to denote the value passed in for parameter number ParamNum it would be 42 in this example. The size of each element is calculated from the metadata for the ar1 parameter in Foo's signature an ELEMENT_TYPE_I4 (see Partition II, section 22.1.15) of size 4 bytes. |