Struct CilObject
pub struct CilObject { /* private fields */ }Expand description
The self-referencing struct.
Implementations§
§impl CilObject
impl CilObject
pub fn from_file(file: &Path) -> Result<Self>
pub fn from_file(file: &Path) -> Result<Self>
Creates a new CilObject by loading and parsing a .NET assembly from disk.
This method handles the complete loading process including file I/O, PE header validation, and metadata parsing. The file is memory-mapped for efficient access to large assemblies.
§Arguments
file- Path to the .NET assembly file (.dll, .exe, or .netmodule)
§Returns
Returns a fully parsed CilObject or an error if:
- The file cannot be opened or read
- The file is not a valid PE format
- The PE file is not a valid .NET assembly
- Metadata streams are corrupted or invalid
§Examples
use dotscope::CilObject;
use std::path::Path;
let assembly = CilObject::from_file(Path::new("tests/samples/WindowsBase.dll"))?;
println!("Loaded assembly: {}", assembly.assembly().unwrap().name);§Errors
Returns an error if the file cannot be read or parsed as a valid .NET assembly.
pub fn from_file_with_validation(
file: &Path,
validation_config: ValidationConfig,
) -> Result<Self>
pub fn from_file_with_validation( file: &Path, validation_config: ValidationConfig, ) -> Result<Self>
Creates a new CilObject by parsing a .NET assembly from a file with custom validation configuration.
This method allows you to control which validation checks are performed during loading. Use this when you need to balance performance vs. validation coverage.
§Arguments
file- Path to the .NET assembly filevalidation_config- Configuration specifying which validation checks to perform
§Examples
use dotscope::{CilObject, ValidationConfig};
use std::path::Path;
// Load with minimal validation for maximum performance
let assembly = CilObject::from_file_with_validation(
Path::new("tests/samples/WindowsBase.dll"),
ValidationConfig::minimal()
)?;
// Load with production validation for balance of safety and performance
let assembly = CilObject::from_file_with_validation(
Path::new("tests/samples/WindowsBase.dll"),
ValidationConfig::production()
)?;§Errors
Returns an error if the file cannot be read, parsed as a valid .NET assembly, or if validation checks fail.
pub fn from_mem(data: Vec<u8>) -> Result<Self>
pub fn from_mem(data: Vec<u8>) -> Result<Self>
Creates a new CilObject by parsing a .NET assembly from a memory buffer.
This method is useful for analyzing assemblies that are already loaded in memory, downloaded from network sources, or embedded as resources. The data is copied internally to ensure proper lifetime management.
§Arguments
data- Raw bytes of the .NET assembly in PE format
§Returns
Returns a fully parsed CilObject or an error if:
- The data is not a valid PE format
- The PE data is not a valid .NET assembly
- Metadata streams are corrupted or invalid
- Memory allocation fails during processing
§Examples
use dotscope::CilObject;
// Load assembly from network or embedded resource
//let assembly_bytes = download_assembly().await?;
//let assembly = CilObject::from_mem(assembly_bytes)?;
// Or from file for comparison
let file_data = std::fs::read("tests/samples/WindowsBase.dll")?;
let assembly = CilObject::from_mem(file_data)?;§Errors
Returns an error if the memory buffer cannot be parsed as a valid .NET assembly.
pub fn from_mem_with_validation(
data: Vec<u8>,
validation_config: ValidationConfig,
) -> Result<Self>
pub fn from_mem_with_validation( data: Vec<u8>, validation_config: ValidationConfig, ) -> Result<Self>
Creates a new CilObject by parsing a .NET assembly from a memory buffer with custom validation configuration.
This method allows you to control which validation checks are performed during loading. Use this when you need to balance performance vs. validation coverage.
§Arguments
data- Raw bytes of the .NET assembly in PE formatvalidation_config- Configuration specifying which validation checks to perform
§Examples
use dotscope::{CilObject, ValidationConfig};
let file_data = std::fs::read("tests/samples/WindowsBase.dll")?;
// Load with production validation settings
let assembly = CilObject::from_mem_with_validation(
file_data.clone(),
ValidationConfig::production()
)?;§Errors
Returns an error if the memory buffer cannot be parsed as a valid .NET assembly or if validation checks fail.
pub fn cor20header(&self) -> &Cor20Header
pub fn cor20header(&self) -> &Cor20Header
Returns the COR20 header containing .NET-specific PE information.
The COR20 header (also known as CLI header) contains essential information about the .NET assembly including metadata directory location, entry point, and runtime flags. This header is always present in valid .NET assemblies.
§Returns
Reference to the parsed Cor20Header structure containing:
- Metadata directory RVA and size
- Entry point token (for executables)
- Runtime flags (
IL_ONLY,32BIT_REQUIRED, etc.) - Resources and strong name signature locations
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
let header = assembly.cor20header();
println!("Metadata RVA: 0x{:X}", header.meta_data_rva);
println!("Runtime flags: {:?}", header.flags);pub fn metadata_root(&self) -> &Root
pub fn metadata_root(&self) -> &Root
Returns the metadata root header containing stream directory information.
The metadata root is the entry point to the .NET metadata system, containing the version signature, stream count, and directory of all metadata streams (#~, #Strings, #US, #GUID, #Blob). This structure is always present and provides the foundation for accessing all assembly metadata.
§Returns
Reference to the parsed Root structure containing:
- Metadata format version and signature
- Stream directory with names, offsets, and sizes
- Framework version string
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
let root = assembly.metadata_root();
println!("Metadata version: {}", root.version);
println!("Number of streams: {}", root.stream_headers.len());
for stream in &root.stream_headers {
println!("Stream: {} at offset 0x{:X}", stream.name, stream.offset);
}pub fn tables(&self) -> Option<&TablesHeader<'_>>
pub fn tables(&self) -> Option<&TablesHeader<'_>>
Returns the metadata tables header from the #~ or #- stream.
The tables header contains all metadata tables defined by ECMA-335, including Type definitions, Method definitions, Field definitions, Assembly references, and many others. This is the core of .NET metadata and provides structured access to all assembly information.
§Returns
Some(&TablesHeader)if the #~ stream is present (compressed metadata)Noneif no tables stream is found (invalid or malformed assembly)
The TablesHeader provides access to:
- All metadata table row counts and data
- String, GUID, and Blob heap indices
- Schema version and heap size information
§Examples
use dotscope::{CilObject, metadata::tables::{TypeDefRaw, TableId}};
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
if let Some(tables) = assembly.tables() {
println!("Schema version: {}.{}", tables.major_version, tables.minor_version);
// Access individual tables
if let Some(typedef_table) = &tables.table::<TypeDefRaw>(TableId::TypeDef) {
println!("Number of types: {}", typedef_table.row_count());
}
}pub fn strings(&self) -> Option<&Strings<'_>>
pub fn strings(&self) -> Option<&Strings<'_>>
Returns the strings heap from the #Strings stream.
The strings heap contains null-terminated UTF-8 strings used throughout the metadata tables for names of types, members, parameters, and other identifiers. String references in tables are indices into this heap.
§Returns
Some(&Strings)if the #Strings stream is presentNoneif the stream is missing (malformed assembly)
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
if let Some(strings) = assembly.strings() {
// Look up string by index (from metadata table)
if let Ok(name) = strings.get(0x123) {
println!("String at index 0x123: {}", name);
}
}pub fn userstrings(&self) -> Option<&UserStrings<'_>>
pub fn userstrings(&self) -> Option<&UserStrings<'_>>
Returns the user strings heap from the #US stream.
The user strings heap contains length-prefixed Unicode strings that appear
as string literals in CIL code (e.g., from C# string literals). These are
accessed via the ldstr instruction and are distinct from metadata strings.
§Returns
Some(&UserStrings)if the #US stream is presentNoneif the stream is missing (assembly has no string literals)
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
if let Some(user_strings) = assembly.userstrings() {
// Look up user string by token (from ldstr instruction)
if let Ok(literal) = user_strings.get(0x70000001) {
println!("String literal: {}", literal.to_string().unwrap());
}
}pub fn guids(&self) -> Option<&Guid<'_>>
pub fn guids(&self) -> Option<&Guid<'_>>
Returns the GUID heap from the #GUID stream.
The GUID heap contains 16-byte GUIDs referenced by metadata tables, typically used for type library IDs, interface IDs, and other unique identifiers in COM interop scenarios.
§Returns
Some(&Guid)if the #GUID stream is presentNoneif the stream is missing (assembly has no GUID references)
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
if let Some(guids) = assembly.guids() {
// Look up GUID by index (from metadata table)
if let Ok(guid) = guids.get(1) {
println!("GUID: {}", guid);
}
}pub fn blob(&self) -> Option<&Blob<'_>>
pub fn blob(&self) -> Option<&Blob<'_>>
Returns the blob heap from the #Blob stream.
The blob heap contains variable-length binary data referenced by metadata tables, including type signatures, method signatures, field signatures, custom attribute values, and marshalling information.
§Returns
Some(&Blob)if the #Blob stream is presentNoneif the stream is missing (malformed assembly)
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
if let Some(blob) = assembly.blob() {
// Look up blob by index (from metadata table)
if let Ok(signature) = blob.get(0x456) {
println!("Signature bytes: {:02X?}", signature);
}
}pub fn refs_assembly(&self) -> &AssemblyRefMap
pub fn refs_assembly(&self) -> &AssemblyRefMap
Returns all assembly references used by this assembly.
Assembly references represent external .NET assemblies that this assembly
depends on, including version information, public key tokens, and culture
settings. These correspond to entries in the AssemblyRef metadata table.
§Returns
Reference to the AssemblyRefMap containing all external assembly dependencies.
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
let refs = assembly.refs_assembly();
for entry in refs.iter() {
let (token, assembly_ref) = (entry.key(), entry.value());
println!("Dependency: {} v{}.{}.{}.{}",
assembly_ref.name,
assembly_ref.major_version,
assembly_ref.minor_version,
assembly_ref.build_number,
assembly_ref.revision_number
);
}pub fn refs_module(&self) -> &ModuleRefMap
pub fn refs_module(&self) -> &ModuleRefMap
Returns all module references used by this assembly.
Module references represent external unmanaged modules (native DLLs)
that this assembly imports functions from via P/Invoke declarations.
These correspond to entries in the ModuleRef metadata table.
§Returns
Reference to the ModuleRefMap containing all external module dependencies.
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
let refs = assembly.refs_module();
for entry in refs.iter() {
let (token, module_ref) = (entry.key(), entry.value());
println!("Native module: {}", module_ref.name);
}pub fn refs_members(&self) -> &MemberRefMap
pub fn refs_members(&self) -> &MemberRefMap
Returns all member references used by this assembly.
Member references represent external type members (methods, fields, properties)
from other assemblies that are referenced by this assembly’s code.
These correspond to entries in the MemberRef metadata table.
§Returns
Reference to the MemberRefMap containing all external member references.
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
let refs = assembly.refs_members();
for entry in refs.iter() {
let (token, member_ref) = (entry.key(), entry.value());
println!("External member: {}", member_ref.name);
}pub fn module(&self) -> Option<&ModuleRc>
pub fn module(&self) -> Option<&ModuleRc>
Returns the primary module information for this assembly.
The module represents the main file of the assembly, containing the module’s name, MVID (Module Version Identifier), and generation ID. Multi-file assemblies can have additional modules, but there’s always one primary module.
§Returns
Some(&ModuleRc)if module information is presentNoneif no module table entry exists (malformed assembly)
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
if let Some(module) = assembly.module() {
println!("Module name: {}", module.name);
println!("Module GUID: {}", module.mvid);
}pub fn assembly(&self) -> Option<&AssemblyRc>
pub fn assembly(&self) -> Option<&AssemblyRc>
Returns the assembly metadata for this .NET assembly.
The assembly metadata contains the assembly’s identity including name, version, culture, public key information, and security attributes. This corresponds to the Assembly metadata table entry.
§Returns
Some(&AssemblyRc)if assembly metadata is presentNoneif this is a module-only file (no Assembly table entry)
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
if let Some(assembly_info) = assembly.assembly() {
println!("Assembly: {}", assembly_info.name);
println!("Version: {}.{}.{}.{}",
assembly_info.major_version,
assembly_info.minor_version,
assembly_info.build_number,
assembly_info.revision_number
);
}pub fn assembly_os(&self) -> Option<&AssemblyOsRc>
pub fn assembly_os(&self) -> Option<&AssemblyOsRc>
Returns assembly OS information if present.
The AssemblyOS table contains operating system identification information
for the assembly. This table is rarely used in modern .NET assemblies
and is primarily for legacy compatibility.
§Returns
Some(&AssemblyOsRc)if OS information is presentNoneif noAssemblyOStable entry exists (typical for most assemblies)
pub fn assembly_processor(&self) -> Option<&AssemblyProcessorRc>
pub fn assembly_processor(&self) -> Option<&AssemblyProcessorRc>
Returns assembly processor information if present.
The AssemblyProcessor table contains processor architecture identification
information for the assembly. This table is rarely used in modern .NET
assemblies and is primarily for legacy compatibility.
§Returns
Some(&AssemblyProcessorRc)if processor information is presentNoneif noAssemblyProcessortable entry exists (typical for most assemblies)
pub fn imports(&self) -> &Imports
pub fn imports(&self) -> &Imports
Returns the imports container with all P/Invoke and COM import information.
The imports container provides access to all external function imports
including P/Invoke declarations, COM method imports, and related
marshalling information. This data comes from ImplMap and related tables.
§Returns
Reference to the Imports container with all import declarations.
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
let imports = assembly.imports();
for entry in imports.iter() {
let (token, import) = (entry.key(), entry.value());
println!("Import: {}.{} from {:?}", import.namespace, import.name, import.source_id);
}pub fn exports(&self) -> &Exports
pub fn exports(&self) -> &Exports
Returns the exports container with all exported function information.
The exports container provides access to all functions that this assembly exports for use by other assemblies or native code. This includes both managed exports and any native exports in mixed-mode assemblies.
§Returns
Reference to the Exports container with all export declarations.
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
let exports = assembly.exports();
for entry in exports.iter() {
let (token, export) = (entry.key(), entry.value());
println!("Export: {} at offset 0x{:X} - Token 0x{:X}", export.name, export.offset, token.value());
}pub fn methods(&self) -> &MethodMap
pub fn methods(&self) -> &MethodMap
Returns the methods container with all method definitions and metadata.
The methods container provides access to all methods defined in this assembly,
including their signatures, IL code, exception handlers, and related metadata.
This integrates data from MethodDef, Param, and other method-related tables.
§Returns
Reference to the MethodMap containing all method definitions.
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
let methods = assembly.methods();
for entry in methods.iter() {
let (token, method) = (entry.key(), entry.value());
println!("Method: {} (Token: 0x{:08X})", method.name, token.value());
if let Some(rva) = method.rva {
println!(" RVA: 0x{:X}", rva);
}
}pub fn method_specs(&self) -> &MethodSpecMap
pub fn method_specs(&self) -> &MethodSpecMap
Returns the method specifications container with all generic method instantiations.
The method specifications container provides access to all generic method instantiations
defined in this assembly. MethodSpec entries represent calls to generic methods with
specific type arguments, enabling IL instructions to reference these instantiations.
§Returns
Reference to the MethodSpecMap containing all method specifications.
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
let method_specs = assembly.method_specs();
for entry in method_specs.iter() {
let (token, method_spec) = (entry.key(), entry.value());
println!("MethodSpec: Token 0x{:08X}", token.value());
println!(" Generic args count: {}", method_spec.generic_args.count());
}pub fn resources(&self) -> &Resources
pub fn resources(&self) -> &Resources
Returns the resources container with all embedded and linked resources.
The resources container provides access to all resources associated with this assembly, including embedded resources, linked files, and resource metadata. This includes both .NET resources and Win32 resources.
§Returns
Reference to the Resources container with all resource information.
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
let resources = assembly.resources();
for entry in resources.iter() {
let (name, resource) = (entry.key(), entry.value());
println!("Resource: {} (Size: {}, Offset: 0x{:X})", name, resource.data_offset, resource.data_size);
}pub fn types(&self) -> &TypeRegistry
pub fn types(&self) -> &TypeRegistry
Returns the type registry containing all type definitions and references.
The type registry provides centralized access to all types defined in and
referenced by this assembly. This includes TypeDef entries (types defined
in this assembly), TypeRef entries (types referenced from other assemblies),
TypeSpec entries (instantiated generic types), and primitive types.
§Returns
Reference to the TypeRegistry containing all type information.
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
let types = assembly.types();
println!("Total types: {}", types.len());
// Get all types
for type_info in types.all_types() {
println!("Type: {}.{} (Token: 0x{:08X})",
type_info.namespace, type_info.name, type_info.token.value());
}
// Look up specific types
let string_types = types.get_by_name("String");
for string_type in string_types {
println!("Found String type in namespace: {}", string_type.namespace);
}pub fn file(&self) -> &Arc<File>
pub fn file(&self) -> &Arc<File>
Returns the underlying file representation of this assembly.
The file object provides access to the raw PE file data, headers, and file-level operations such as RVA-to-offset conversion, section access, and memory-mapped or buffered file I/O. This is useful for low-level analysis or when you need direct access to the PE file structure.
§Returns
Reference to the Arc<File> containing the PE file representation.
§Examples
use dotscope::CilObject;
let assembly = CilObject::from_file("tests/samples/WindowsBase.dll".as_ref())?;
let file = assembly.file();
// Access file-level information
println!("File size: {} bytes", file.data().len());
// Access PE headers
let dos_header = file.header_dos();
let nt_headers = file.header();
println!("PE signature: 0x{:X}", nt_headers.signature);
// Convert RVA to file offset
let (clr_rva, _) = file.clr();
let offset = file.rva_to_offset(clr_rva)?;
println!("CLR header at file offset: 0x{:X}", offset);pub fn validate(&self, config: ValidationConfig) -> Result<()>
pub fn validate(&self, config: ValidationConfig) -> Result<()>
Performs comprehensive validation on the loaded assembly.
This method allows you to validate an already-loaded assembly with specific validation settings. This is useful when you want to perform additional validation after loading, or when you loaded with minimal validation initially.
§Arguments
config- Validation configuration specifying which validations to perform
§Returns
Returns Ok(()) if all validations pass, or an error describing
any validation failures found.
§Examples
use dotscope::{CilObject, ValidationConfig};
use std::path::Path;
// Load assembly with minimal validation for speed
let assembly = CilObject::from_file_with_validation(
Path::new("tests/samples/WindowsBase.dll"),
ValidationConfig::minimal()
)?;
// Later, perform comprehensive validation
assembly.validate(ValidationConfig::comprehensive())?;§Errors
Returns validation errors found during analysis, such as:
- Circular type nesting
- Field layout overlaps
- Invalid generic constraints
- Type system inconsistencies
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for CilObject
impl !RefUnwindSafe for CilObject
impl Send for CilObject
impl Sync for CilObject
impl Unpin for CilObject
impl !UnwindSafe for CilObject
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more