Module signatures
Expand description
Implementation of method and type signatures Method and type signature parsing for .NET metadata according to ECMA-335.
This module provides comprehensive parsing of .NET metadata signatures, which encode type information, method parameters, generic constraints, and calling conventions in a compact binary format. Signatures are fundamental to the .NET type system and are used throughout assembly metadata to describe types, methods, and their relationships.
§.NET Signature System Overview
The .NET metadata format defines signatures as binary-encoded type descriptions that provide complete type information for methods, fields, properties, and local variables. These signatures enable the CLR to understand type relationships, perform type checking, and support generic type instantiation.
§Signature Categories
The .NET metadata format defines several signature types, each serving specific purposes:
§Method Signatures
- Purpose: Describe method parameter types, return types, and calling conventions
- Usage: Method definitions, method references, and method specifications
- Features: Support for instance methods, static methods, generic methods, and varargs
- Calling Conventions: Default, varargs, C calling convention, stdcall, fastcall
§Field Signatures
- Purpose: Describe field type information and custom modifiers
- Usage: Field definitions and field references
- Features: Support for custom modifiers (modreq/modopt), array types, and generic types
- Modifiers: Required and optional custom modifiers for advanced type scenarios
§Property Signatures
- Purpose: Describe property type and indexer parameter information
- Usage: Property definitions with getter/setter methods
- Features: Support for indexed properties, instance properties, and generic property types
- Indexers: Multi-dimensional indexers with complex parameter types
§Local Variable Signatures
- Purpose: Describe local variable types within method bodies
- Usage: Method body metadata for JIT compilation and debugging
- Features: Support for pinned variables, byref variables, and complex local types
- Memory Management: Pinned locals for interop scenarios and unsafe code
§Type Specification Signatures
- Purpose: Define generic type instantiations and complex type references
- Usage: Generic type instantiations like
List<int>orDictionary<string, object> - Features: Nested generic types, generic method instantiations, and type constraints
- Instantiation: Runtime type creation from generic type definitions
§Method Specification Signatures
- Purpose: Provide type arguments for generic method instantiations
- Usage: Generic method calls with specific type arguments
- Features: Multiple type arguments, nested generic types, and method constraints
- Resolution: Runtime method resolution for generic method calls
§Binary Encoding Format
Signatures use a compressed binary encoding optimized for space efficiency while maintaining complete type information. The encoding follows ECMA-335 specifications and includes several key characteristics:
§Encoding Characteristics
- Calling Conventions: Encoded as single-byte prefixes (0x00-0x0F range)
- Parameter Counts: Use compressed integer encoding for space efficiency
- Type References: Element type tokens and metadata table references
- Generic Parameters: Positional indices into generic parameter lists
- Custom Modifiers: Inline encoding with type information for advanced scenarios
§Compression Techniques
- Compressed Integers: Variable-length encoding for counts and indices
- Element Types: Single-byte encoding for primitive types (int32, string, etc.)
- Token Compression: Compressed encoding for metadata table references
- Recursive Encoding: Nested type information for complex generic types
§Common Usage Patterns
§Basic Method Signature Analysis
use dotscope::metadata::signatures::parse_method_signature;
// Parse a simple method signature: void Method()
let signature_data = &[0x00, 0x00, 0x01]; // DEFAULT, 0 params, VOID return
let method_sig = parse_method_signature(signature_data)?;
println!("Method has {} parameters", method_sig.params.len());
println!("Return type: {:?}", method_sig.return_type.base);
println!("Has 'this' parameter: {}", method_sig.has_this);
println!("Generic parameter count: {}", method_sig.param_count_generic);§Generic Method Signature Analysis
use dotscope::metadata::signatures::{parse_method_signature, TypeSignature};
// Parse generic method: T Method<T>(T item)
let signature_data = &[
0x30, // HASTHIS | GENERIC
0x01, // 1 generic parameter
0x01, // 1 method parameter
0x13, 0x00, // GenericParam(0) - return type
0x13, 0x00, // GenericParam(0) - parameter type
];
let method_sig = parse_method_signature(signature_data)?;
if method_sig.param_count_generic > 0 {
println!("Generic method with {} type parameters", method_sig.param_count_generic);
}
// Check if return type is a generic parameter
if let TypeSignature::GenericParamType(index) = method_sig.return_type.base {
println!("Return type is generic parameter {}", index);
}§Field Type Analysis
use dotscope::metadata::signatures::{parse_field_signature, TypeSignature};
// Parse array field signature: string[] field
let signature_data = &[0x06, 0x1D, 0x0E]; // FIELD, SZARRAY, String
let field_sig = parse_field_signature(signature_data)?;
match &field_sig.base {
TypeSignature::SzArray(element_type) => {
println!("Array field with element type: {:?}", element_type.base);
},
TypeSignature::String => {
println!("String field");
},
TypeSignature::I4 => {
println!("Integer field");
},
_ => {
println!("Other field type: {:?}", field_sig.base);
}
}
if !field_sig.modifiers.is_empty() {
println!("Field has {} custom modifiers", field_sig.modifiers.len());
}§Local Variable Analysis
use dotscope::metadata::signatures::parse_local_var_signature;
// Parse locals: int a; ref string b; pinned byte* c;
let signature_data = &[
0x07, // LOCAL_SIG
0x03, // 3 variables
0x08, // I4 (int)
0x10, 0x0E, // BYREF String (ref string)
0x45, 0x0F, // PINNED PTR (pinned byte*)
];
let locals_sig = parse_local_var_signature(signature_data)?;
for (i, local) in locals_sig.locals.iter().enumerate() {
println!("Local {}: {:?}", i, local.base);
if local.is_byref {
println!(" -> Passed by reference");
}
if local.is_pinned {
println!(" -> Pinned in memory (for interop)");
}
}§Generic Type Instantiation Analysis
use dotscope::metadata::signatures::{parse_type_spec_signature, TypeSignature};
// Parse List<int> type specification
let signature_data = &[
0x15, // GENERICINST
0x12, 0x49, // Class token reference
0x01, // 1 type argument
0x08, // I4 (int)
];
let type_spec = parse_type_spec_signature(signature_data)?;
if let TypeSignature::GenericInst(class_type, args) = &type_spec.base {
println!("Generic type instantiation:");
println!(" Base type: {:?}", class_type);
println!(" Type arguments: {} types", args.len());
for (i, arg) in args.iter().enumerate() {
println!(" [{}]: {:?}", i, arg);
}
}§Advanced Features
§Custom Modifiers (modreq/modopt)
Custom modifiers provide additional type information for advanced scenarios:
- modreq: Required modifiers that affect type identity and compatibility
- modopt: Optional modifiers that provide hints but don’t affect compatibility
- Usage: C++/CLI interop, volatile fields, const fields, and custom type constraints
§Calling Conventions
Different calling conventions are supported for platform interop:
- DEFAULT: Standard managed calling convention
- VARARG: Variable argument lists (params arrays)
- C: C-style calling convention for P/Invoke
- STDCALL: Windows standard calling convention
- FASTCALL: Fast calling convention for performance-critical code
§Memory Layout Specifications
Signatures include information for memory management:
- Pinned Variables: Fixed memory location for interop scenarios
- ByRef Parameters: Reference semantics for value types
- Pointer Types: Unsafe pointer types for low-level operations
- Array Bounds: Multi-dimensional array layout information
§Thread Safety
All parsing functions in this module are thread-safe:
- Stateless parsing functions can be called concurrently
- Parsed signature structures are immutable and shareable
- No global state or shared mutable data
§Error Handling
Parsing can fail for several reasons:
- Malformed Data: Invalid signature encoding or truncated data
- Unsupported Features: Unknown element types or calling conventions
- Version Incompatibility: Signatures from newer .NET versions
- Corrupted Metadata: Damaged assembly files or invalid token references
§ECMA-335 Compliance
This implementation follows ECMA-335 6th Edition specifications:
- Partition II, Section 23.2: Blobs and signature encoding formats
- Partition II, Section 23.1: Metadata validation and well-formedness rules
- Partition I, Section 8: Type system fundamentals and signature semantics
- Partition III, Section 1.6: Calling conventions and method signatures
The implementation handles all standard signature types and element types defined in the specification, including legacy formats for backward compatibility.
Modules§
- CALLING_
CONVENTION - Calling convention flags as defined in ECMA-335 II.23.2.1 for method signature encoding.
- SIGNATURE_
HEADER - Signature marker bytes as defined in ECMA-335 II.23.2.
Structs§
- Custom
Modifier - Represents a custom modifier with its required/optional flag and type reference.
- Field
Signature Builder - Builder for constructing field signatures with fluent API.
- Local
Variable Signature Builder - Builder for constructing local variable signatures with fluent API.
- Method
Signature Builder - Builder for constructing method signatures with fluent API.
- Property
Signature Builder - Builder for constructing property signatures with fluent API.
- Signature
Array - Multi-dimensional array signature with bounds and dimension information.
- Signature
Field - Field signature with type information and custom modifiers.
- Signature
Local Variable - Individual local variable declaration with type and attributes.
- Signature
Local Variables - Local variable signature collection for method bodies.
- Signature
Method - Method signature with calling conventions, parameters, and return types.
- Signature
Method Spec - Method specification signature for generic method instantiations.
- Signature
Parameter - Method parameter signature with modifiers and reference semantics.
- Signature
Parser - Binary signature parser for all .NET metadata signature types according to ECMA-335.
- Signature
Pointer - Unmanaged pointer signature with custom modifiers.
- Signature
Property - Property signature with indexer support and custom modifiers.
- Signature
SzArray - Single-dimensional array signature with custom modifiers.
- Signature
Type Spec - Type specification signature for complex and generic types.
- Type
Spec Signature Builder - Builder for constructing type specification signatures with fluent API.
Enums§
- Type
Signature - Complete .NET type signature representation supporting all ECMA-335 type encodings.
Functions§
- encode_
field_ signature - Encodes a field signature into binary format according to ECMA-335.
- encode_
local_ var_ signature - Encodes a local variable signature into binary format according to ECMA-335.
- encode_
method_ signature - Encodes a method signature into binary format according to ECMA-335.
- encode_
property_ signature - Encodes a property signature into binary format according to ECMA-335.
- encode_
typespec_ signature - Encodes a type specification signature into binary format according to ECMA-335.
- parse_
field_ signature - Parse a field signature from binary signature data.
- parse_
local_ var_ signature - Parse a local variable signature from binary signature data.
- parse_
method_ signature - Parse a method signature from binary signature data.
- parse_
method_ spec_ signature - Parse a method specification signature from binary signature data.
- parse_
property_ signature - Parse a property signature from binary signature data.
- parse_
type_ spec_ signature - Parse a type specification signature from binary signature data.
Type Aliases§
- Custom
Modifiers - A collection of custom modifiers applied to a type or type component.