Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions src/metadata/loader/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ use crate::{
tables::{
AssemblyOsRc, AssemblyProcessorRc, AssemblyRc, AssemblyRefMap, AssemblyRefOsMap,
AssemblyRefProcessorMap, ClassLayoutMap, CodedIndex, ConstantMap, CustomAttributeMap,
DeclSecurityMap, EventMap, EventMapEntryMap, EventPtrMap, FieldLayoutMap, FieldMap,
FieldMarshalMap, FieldPtrMap, FieldRVAMap, FileMap, GenericParamConstraintMap,
GenericParamMap, InterfaceImplMap, MemberRefMap, MethodImplMap, MethodPtrMap,
MethodSemanticsMap, MethodSpecMap, ModuleRc, ModuleRefMap, NestedClassMap, ParamMap,
ParamPtrMap, PropertyMap, PropertyMapEntryMap, PropertyPtrMap, StandAloneSigMap,
TableId, TypeSpecMap,
DeclSecurityMap, EncLogMap, EncMapMap, EventMap, EventMapEntryMap, EventPtrMap,
FieldLayoutMap, FieldMap, FieldMarshalMap, FieldPtrMap, FieldRVAMap, FileMap,
GenericParamConstraintMap, GenericParamMap, InterfaceImplMap, MemberRefMap,
MethodImplMap, MethodPtrMap, MethodSemanticsMap, MethodSpecMap, ModuleRc, ModuleRefMap,
NestedClassMap, ParamMap, ParamPtrMap, PropertyMap, PropertyMapEntryMap,
PropertyPtrMap, StandAloneSigMap, TableId, TypeSpecMap,
},
typesystem::{CilTypeReference, TypeRegistry},
},
Expand Down Expand Up @@ -207,6 +207,12 @@ pub(crate) struct LoaderContext<'a> {
/// Field relative virtual addresses for initialized data.
pub field_rva: FieldRVAMap,

// === Edit-and-Continue Tables ===
/// Edit-and-Continue log entries tracking debugging modifications.
pub enc_log: EncLogMap,
/// Edit-and-Continue token mapping for debugging scenarios.
pub enc_map: EncMapMap,

// === Parameter and Generic Tables ===
/// Parameter definitions for methods.
pub param: ParamMap,
Expand Down
2 changes: 2 additions & 0 deletions src/metadata/loader/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@ impl<'a> CilObjectData<'a> {
field_layout: SkipMap::default(),
field_marshal: SkipMap::default(),
field_rva: SkipMap::default(),
enc_log: SkipMap::default(),
enc_map: SkipMap::default(),
param: SkipMap::default(),
param_ptr: SkipMap::default(),
generic_param: SkipMap::default(),
Expand Down
6 changes: 4 additions & 2 deletions src/metadata/loader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub(crate) use data::CilObjectData;

/// Static registry of all metadata table loaders.
///
/// This array contains references to all 43 metadata table loaders that are part of the .NET metadata
/// This array contains references to all 45 metadata table loaders that are part of the .NET metadata
/// specification. Each loader is responsible for processing a specific metadata table type and declaring
/// its dependencies on other tables.
///
Expand Down Expand Up @@ -75,7 +75,7 @@ pub(crate) use data::CilObjectData;
/// 2. Add the loader to this array
/// 3. Update any loaders that depend on the new table
/// 4. Test that the dependency graph remains acyclic
static LOADERS: [&'static dyn MetadataLoader; 43] = [
static LOADERS: [&'static dyn MetadataLoader; 45] = [
&crate::metadata::tables::AssemblyLoader,
&crate::metadata::tables::AssemblyOsLoader,
&crate::metadata::tables::AssemblyProcessorLoader,
Expand All @@ -86,6 +86,8 @@ static LOADERS: [&'static dyn MetadataLoader; 43] = [
&crate::metadata::tables::ConstantLoader,
&crate::metadata::tables::CustomAttributeLoader,
&crate::metadata::tables::DeclSecurityLoader,
&crate::metadata::tables::EncLogLoader,
&crate::metadata::tables::EncMapLoader,
&crate::metadata::tables::EventLoader,
&crate::metadata::tables::EventMapLoader,
&crate::metadata::tables::EventPtrLoader,
Expand Down
33 changes: 26 additions & 7 deletions src/metadata/streams/tablesheader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,14 @@
metadata::tables::{
AssemblyOsRaw, AssemblyProcessorRaw, AssemblyRaw, AssemblyRefOsRaw,
AssemblyRefProcessorRaw, AssemblyRefRaw, ClassLayoutRaw, ConstantRaw, CustomAttributeRaw,
DeclSecurityRaw, EventMapRaw, EventPtrRaw, EventRaw, ExportedTypeRaw, FieldLayoutRaw,
FieldMarshalRaw, FieldPtrRaw, FieldRaw, FieldRvaRaw, FileRaw, GenericParamConstraintRaw,
GenericParamRaw, ImplMapRaw, InterfaceImplRaw, ManifestResourceRaw, MemberRefRaw,
MetadataTable, MethodDefRaw, MethodImplRaw, MethodPtrRaw, MethodSemanticsRaw,
MethodSpecRaw, ModuleRaw, ModuleRefRaw, NestedClassRaw, ParamPtrRaw, ParamRaw,
PropertyMapRaw, PropertyPtrRaw, PropertyRaw, RowDefinition, StandAloneSigRaw, TableData,
TableId, TableInfo, TableInfoRef, TypeDefRaw, TypeRefRaw, TypeSpecRaw,
DeclSecurityRaw, EncLogRaw, EncMapRaw, EventMapRaw, EventPtrRaw, EventRaw, ExportedTypeRaw,
FieldLayoutRaw, FieldMarshalRaw, FieldPtrRaw, FieldRaw, FieldRvaRaw, FileRaw,
GenericParamConstraintRaw, GenericParamRaw, ImplMapRaw, InterfaceImplRaw,
ManifestResourceRaw, MemberRefRaw, MetadataTable, MethodDefRaw, MethodImplRaw,
MethodPtrRaw, MethodSemanticsRaw, MethodSpecRaw, ModuleRaw, ModuleRefRaw, NestedClassRaw,
ParamPtrRaw, ParamRaw, PropertyMapRaw, PropertyPtrRaw, PropertyRaw, RowDefinition,
StandAloneSigRaw, TableData, TableId, TableInfo, TableInfoRef, TypeDefRaw, TypeRefRaw,
TypeSpecRaw,
},
Error::OutOfBounds,
Result,
Expand Down Expand Up @@ -1234,6 +1235,12 @@
TableData::DeclSecurity(table) => unsafe {
Some(&*std::ptr::from_ref(table).cast::<MetadataTable<T>>())
},
TableData::EncLog(table) => unsafe {
Some(&*std::ptr::from_ref(table).cast::<MetadataTable<T>>())

Check warning on line 1239 in src/metadata/streams/tablesheader.rs

View check run for this annotation

Codecov / codecov/patch

src/metadata/streams/tablesheader.rs#L1238-L1239

Added lines #L1238 - L1239 were not covered by tests
},
TableData::EncMap(table) => unsafe {
Some(&*std::ptr::from_ref(table).cast::<MetadataTable<T>>())

Check warning on line 1242 in src/metadata/streams/tablesheader.rs

View check run for this annotation

Codecov / codecov/patch

src/metadata/streams/tablesheader.rs#L1241-L1242

Added lines #L1241 - L1242 were not covered by tests
},
TableData::ClassLayout(table) => unsafe {
Some(&*std::ptr::from_ref(table).cast::<MetadataTable<T>>())
},
Expand Down Expand Up @@ -1439,6 +1446,18 @@

TableData::DeclSecurity(table)
}
TableId::EncLog => {
let table = MetadataTable::<EncLogRaw>::new(data, t_info.rows, self.info.clone())?;
*current_offset += table.size() as usize;

TableData::EncLog(table)

Check warning on line 1453 in src/metadata/streams/tablesheader.rs

View check run for this annotation

Codecov / codecov/patch

src/metadata/streams/tablesheader.rs#L1450-L1453

Added lines #L1450 - L1453 were not covered by tests
}
TableId::EncMap => {
let table = MetadataTable::<EncMapRaw>::new(data, t_info.rows, self.info.clone())?;
*current_offset += table.size() as usize;

TableData::EncMap(table)

Check warning on line 1459 in src/metadata/streams/tablesheader.rs

View check run for this annotation

Codecov / codecov/patch

src/metadata/streams/tablesheader.rs#L1456-L1459

Added lines #L1456 - L1459 were not covered by tests
}
TableId::ClassLayout => {
let table =
MetadataTable::<ClassLayoutRaw>::new(data, t_info.rows, self.info.clone())?;
Expand Down
83 changes: 83 additions & 0 deletions src/metadata/tables/enclog/loader.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//! EncLog table loader implementation
//!
//! Provides the [`crate::metadata::tables::enclog::loader::EncLogLoader`] implementation for loading Edit-and-Continue log entries
//! from the ECMA-335 EncLog table (0x1E). This loader processes debugging metadata that tracks
//! modifications made during Edit-and-Continue debugging sessions.
//!
//! # Table Structure
//!
//! The EncLog table contains Edit-and-Continue operation tracking information:
//! - **Token**: Metadata token identifying the affected element
//! - **FuncCode**: Operation code (create=0, update=1, delete=2)
//!
//! # Usage Context
//!
//! This table is only present in assemblies that have been modified during debugging
//! sessions using Edit-and-Continue functionality. It enables the runtime to understand
//! what metadata elements have been added, modified, or removed during debugging.
//!
//! # Reference
//! - [ECMA-335 II.22.12](https://ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf) - EncLog table specification

use crate::{
metadata::{
loader::{LoaderContext, MetadataLoader},
tables::{EncLogRaw, TableId},
},
Result,
};

/// Loader for the EncLog metadata table
///
/// Implements [`crate::metadata::loader::MetadataLoader`] to process the EncLog table (0x1E)
/// which contains Edit-and-Continue log entries that track metadata modifications made during
/// debugging sessions. This table records all changes to help the runtime understand what
/// has been modified during active debugging.
pub(crate) struct EncLogLoader;

impl MetadataLoader for EncLogLoader {
/// Load Edit-and-Continue log entries from the EncLog table
///
/// Processes EncLog table rows (if present) and stores the Edit-and-Continue operation
/// information in the loader context. The EncLog table is optional and only present
/// in assemblies that have been modified during debugging sessions.
///
/// # Arguments
/// * `context` - Loader context containing metadata tables and storage collections
///
/// # Returns
/// * `Ok(())` - EncLog entries successfully loaded or table not present
/// * `Err(`[`crate::Error`]`)` - Malformed data or processing error
fn load(&self, context: &LoaderContext) -> Result<()> {
if let Some(header) = context.meta {
if let Some(table) = header.table::<EncLogRaw>(TableId::EncLog) {
table.par_iter().try_for_each(|row| {
let owned = row.to_owned()?;

Check warning on line 55 in src/metadata/tables/enclog/loader.rs

View check run for this annotation

Codecov / codecov/patch

src/metadata/tables/enclog/loader.rs#L54-L55

Added lines #L54 - L55 were not covered by tests

context.enc_log.insert(row.token, owned);
Ok(())
})?;

Check warning on line 59 in src/metadata/tables/enclog/loader.rs

View check run for this annotation

Codecov / codecov/patch

src/metadata/tables/enclog/loader.rs#L57-L59

Added lines #L57 - L59 were not covered by tests
}
}

Check warning on line 61 in src/metadata/tables/enclog/loader.rs

View check run for this annotation

Codecov / codecov/patch

src/metadata/tables/enclog/loader.rs#L61

Added line #L61 was not covered by tests
Ok(())
}

/// Returns the table identifier for the EncLog table
///
/// # Returns
/// [`crate::metadata::tables::TableId::EncLog`] (0x1E)
fn table_id(&self) -> TableId {
TableId::EncLog
}

/// Returns the list of table dependencies
///
/// The EncLog table has no dependencies on other metadata tables or heaps,
/// as it contains only metadata tokens and operation codes.
///
/// # Returns
/// Empty slice - no table dependencies
fn dependencies(&self) -> &'static [TableId] {
&[]
}
}
83 changes: 83 additions & 0 deletions src/metadata/tables/enclog/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//! EncLog table module
//!
//! Provides complete support for the ECMA-335 EncLog metadata table (0x1E), which contains
//! Edit-and-Continue log entries that track modifications made during debugging sessions.
//! This module includes raw table access, collection types, and edit operation support.
//!
//! # Components
//!
//! - [`crate::metadata::tables::enclog::EncLogRaw`]: Raw table structure (no heap resolution needed)
//! - [`crate::metadata::tables::enclog::EncLog`]: Type alias to Raw since all data is self-contained
//! - [`crate::metadata::tables::enclog::loader::EncLogLoader`]: Internal loader for processing EncLog table data
//! - Type aliases for efficient collections and reference management
//!
//! # EncLog Table Structure
//!
//! The EncLog table contains Edit-and-Continue operation records:
//! - **Token**: Metadata token identifying the affected element (4 bytes)
//! - **FuncCode**: Operation code (create/update/delete) (4 bytes)
//!
//! # Edit-and-Continue Support
//!
//! This table supports .NET's Edit-and-Continue debugging feature, which allows developers
//! to modify source code while the program is paused in the debugger. The EncLog table
//! tracks all metadata changes made during these edit sessions, enabling the runtime to
//! understand what elements have been modified, added, or removed.
//!
//! # Table Characteristics
//!
//! - **Optional**: Not all assemblies contain EncLog tables
//! - **Debugging-specific**: Primarily used during active debugging sessions
//! - **Self-contained**: Contains only primitive values, no heap references
//! - **Sequential**: Entries are typically ordered by edit session timestamp
//!
//! # Reference
//! - [ECMA-335 II.22.12](https://ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf) - EncLog table specification

use crossbeam_skiplist::SkipMap;
use std::sync::Arc;

use crate::metadata::token::Token;

mod loader;
mod raw;

pub(crate) use loader::*;
pub use raw::*;

/// A map that holds the mapping of [`crate::metadata::token::Token`] to parsed [`crate::metadata::tables::enclog::EncLog`]
///
/// Thread-safe concurrent map using skip list data structure for efficient lookups
/// and insertions. Used to cache resolved EncLog entries by their metadata tokens.
pub type EncLogMap = SkipMap<Token, EncLogRc>;

/// A vector that holds a list of [`crate::metadata::tables::enclog::EncLog`] references
///
/// Thread-safe append-only vector for storing EncLog collections. Uses atomic operations
/// for lock-free concurrent access and is optimized for scenarios with frequent reads.
pub type EncLogList = Arc<boxcar::Vec<EncLogRc>>;

/// A reference-counted pointer to an [`crate::metadata::tables::enclog::EncLog`]
///
/// Provides shared ownership and automatic memory management for EncLog instances.
/// Multiple references can safely point to the same EncLog data across threads.
pub type EncLogRc = Arc<EncLog>;

/// Edit-and-Continue log entry for tracking debugging session modifications
///
/// Type alias to [`crate::metadata::tables::enclog::EncLogRaw`] since the EncLog table contains only primitive values
/// that don't require heap resolution. All data in the raw structure is immediately usable.
///
/// The EncLog table records all metadata changes made during Edit-and-Continue debugging sessions,
/// enabling the runtime to understand what elements have been modified, added, or removed during
/// active debugging.
///
/// # Data Model
///
/// Unlike other metadata tables that reference string or blob heaps, EncLog contains
/// only integer values (tokens and operation codes), making the "raw" and "owned"
/// representations identical.
///
/// # Reference
/// - [ECMA-335 II.22.12](https://ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf) - EncLog table specification (Table ID = 0x1E)
pub type EncLog = EncLogRaw;
Loading
Loading