Skip to content

Commit d1d6526

Browse files
authored
feature/EnC-tables (#23)
1 parent 79788d2 commit d1d6526

File tree

14 files changed

+881
-22
lines changed

14 files changed

+881
-22
lines changed

src/metadata/loader/context.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ use crate::{
7373
tables::{
7474
AssemblyOsRc, AssemblyProcessorRc, AssemblyRc, AssemblyRefMap, AssemblyRefOsMap,
7575
AssemblyRefProcessorMap, ClassLayoutMap, CodedIndex, ConstantMap, CustomAttributeMap,
76-
DeclSecurityMap, EventMap, EventMapEntryMap, EventPtrMap, FieldLayoutMap, FieldMap,
77-
FieldMarshalMap, FieldPtrMap, FieldRVAMap, FileMap, GenericParamConstraintMap,
78-
GenericParamMap, InterfaceImplMap, MemberRefMap, MethodImplMap, MethodPtrMap,
79-
MethodSemanticsMap, MethodSpecMap, ModuleRc, ModuleRefMap, NestedClassMap, ParamMap,
80-
ParamPtrMap, PropertyMap, PropertyMapEntryMap, PropertyPtrMap, StandAloneSigMap,
81-
TableId, TypeSpecMap,
76+
DeclSecurityMap, EncLogMap, EncMapMap, EventMap, EventMapEntryMap, EventPtrMap,
77+
FieldLayoutMap, FieldMap, FieldMarshalMap, FieldPtrMap, FieldRVAMap, FileMap,
78+
GenericParamConstraintMap, GenericParamMap, InterfaceImplMap, MemberRefMap,
79+
MethodImplMap, MethodPtrMap, MethodSemanticsMap, MethodSpecMap, ModuleRc, ModuleRefMap,
80+
NestedClassMap, ParamMap, ParamPtrMap, PropertyMap, PropertyMapEntryMap,
81+
PropertyPtrMap, StandAloneSigMap, TableId, TypeSpecMap,
8282
},
8383
typesystem::{CilTypeReference, TypeRegistry},
8484
},
@@ -207,6 +207,12 @@ pub(crate) struct LoaderContext<'a> {
207207
/// Field relative virtual addresses for initialized data.
208208
pub field_rva: FieldRVAMap,
209209

210+
// === Edit-and-Continue Tables ===
211+
/// Edit-and-Continue log entries tracking debugging modifications.
212+
pub enc_log: EncLogMap,
213+
/// Edit-and-Continue token mapping for debugging scenarios.
214+
pub enc_map: EncMapMap,
215+
210216
// === Parameter and Generic Tables ===
211217
/// Parameter definitions for methods.
212218
pub param: ParamMap,

src/metadata/loader/data.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ impl<'a> CilObjectData<'a> {
298298
field_layout: SkipMap::default(),
299299
field_marshal: SkipMap::default(),
300300
field_rva: SkipMap::default(),
301+
enc_log: SkipMap::default(),
302+
enc_map: SkipMap::default(),
301303
param: SkipMap::default(),
302304
param_ptr: SkipMap::default(),
303305
generic_param: SkipMap::default(),

src/metadata/loader/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub(crate) use data::CilObjectData;
3939

4040
/// Static registry of all metadata table loaders.
4141
///
42-
/// This array contains references to all 43 metadata table loaders that are part of the .NET metadata
42+
/// This array contains references to all 45 metadata table loaders that are part of the .NET metadata
4343
/// specification. Each loader is responsible for processing a specific metadata table type and declaring
4444
/// its dependencies on other tables.
4545
///
@@ -75,7 +75,7 @@ pub(crate) use data::CilObjectData;
7575
/// 2. Add the loader to this array
7676
/// 3. Update any loaders that depend on the new table
7777
/// 4. Test that the dependency graph remains acyclic
78-
static LOADERS: [&'static dyn MetadataLoader; 43] = [
78+
static LOADERS: [&'static dyn MetadataLoader; 45] = [
7979
&crate::metadata::tables::AssemblyLoader,
8080
&crate::metadata::tables::AssemblyOsLoader,
8181
&crate::metadata::tables::AssemblyProcessorLoader,
@@ -86,6 +86,8 @@ static LOADERS: [&'static dyn MetadataLoader; 43] = [
8686
&crate::metadata::tables::ConstantLoader,
8787
&crate::metadata::tables::CustomAttributeLoader,
8888
&crate::metadata::tables::DeclSecurityLoader,
89+
&crate::metadata::tables::EncLogLoader,
90+
&crate::metadata::tables::EncMapLoader,
8991
&crate::metadata::tables::EventLoader,
9092
&crate::metadata::tables::EventMapLoader,
9193
&crate::metadata::tables::EventPtrLoader,

src/metadata/streams/tablesheader.rs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,14 @@ use crate::{
307307
metadata::tables::{
308308
AssemblyOsRaw, AssemblyProcessorRaw, AssemblyRaw, AssemblyRefOsRaw,
309309
AssemblyRefProcessorRaw, AssemblyRefRaw, ClassLayoutRaw, ConstantRaw, CustomAttributeRaw,
310-
DeclSecurityRaw, EventMapRaw, EventPtrRaw, EventRaw, ExportedTypeRaw, FieldLayoutRaw,
311-
FieldMarshalRaw, FieldPtrRaw, FieldRaw, FieldRvaRaw, FileRaw, GenericParamConstraintRaw,
312-
GenericParamRaw, ImplMapRaw, InterfaceImplRaw, ManifestResourceRaw, MemberRefRaw,
313-
MetadataTable, MethodDefRaw, MethodImplRaw, MethodPtrRaw, MethodSemanticsRaw,
314-
MethodSpecRaw, ModuleRaw, ModuleRefRaw, NestedClassRaw, ParamPtrRaw, ParamRaw,
315-
PropertyMapRaw, PropertyPtrRaw, PropertyRaw, RowDefinition, StandAloneSigRaw, TableData,
316-
TableId, TableInfo, TableInfoRef, TypeDefRaw, TypeRefRaw, TypeSpecRaw,
310+
DeclSecurityRaw, EncLogRaw, EncMapRaw, EventMapRaw, EventPtrRaw, EventRaw, ExportedTypeRaw,
311+
FieldLayoutRaw, FieldMarshalRaw, FieldPtrRaw, FieldRaw, FieldRvaRaw, FileRaw,
312+
GenericParamConstraintRaw, GenericParamRaw, ImplMapRaw, InterfaceImplRaw,
313+
ManifestResourceRaw, MemberRefRaw, MetadataTable, MethodDefRaw, MethodImplRaw,
314+
MethodPtrRaw, MethodSemanticsRaw, MethodSpecRaw, ModuleRaw, ModuleRefRaw, NestedClassRaw,
315+
ParamPtrRaw, ParamRaw, PropertyMapRaw, PropertyPtrRaw, PropertyRaw, RowDefinition,
316+
StandAloneSigRaw, TableData, TableId, TableInfo, TableInfoRef, TypeDefRaw, TypeRefRaw,
317+
TypeSpecRaw,
317318
},
318319
Error::OutOfBounds,
319320
Result,
@@ -1234,6 +1235,12 @@ impl<'a> TablesHeader<'a> {
12341235
TableData::DeclSecurity(table) => unsafe {
12351236
Some(&*std::ptr::from_ref(table).cast::<MetadataTable<T>>())
12361237
},
1238+
TableData::EncLog(table) => unsafe {
1239+
Some(&*std::ptr::from_ref(table).cast::<MetadataTable<T>>())
1240+
},
1241+
TableData::EncMap(table) => unsafe {
1242+
Some(&*std::ptr::from_ref(table).cast::<MetadataTable<T>>())
1243+
},
12371244
TableData::ClassLayout(table) => unsafe {
12381245
Some(&*std::ptr::from_ref(table).cast::<MetadataTable<T>>())
12391246
},
@@ -1439,6 +1446,18 @@ impl<'a> TablesHeader<'a> {
14391446

14401447
TableData::DeclSecurity(table)
14411448
}
1449+
TableId::EncLog => {
1450+
let table = MetadataTable::<EncLogRaw>::new(data, t_info.rows, self.info.clone())?;
1451+
*current_offset += table.size() as usize;
1452+
1453+
TableData::EncLog(table)
1454+
}
1455+
TableId::EncMap => {
1456+
let table = MetadataTable::<EncMapRaw>::new(data, t_info.rows, self.info.clone())?;
1457+
*current_offset += table.size() as usize;
1458+
1459+
TableData::EncMap(table)
1460+
}
14421461
TableId::ClassLayout => {
14431462
let table =
14441463
MetadataTable::<ClassLayoutRaw>::new(data, t_info.rows, self.info.clone())?;
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//! EncLog table loader implementation
2+
//!
3+
//! Provides the [`crate::metadata::tables::enclog::loader::EncLogLoader`] implementation for loading Edit-and-Continue log entries
4+
//! from the ECMA-335 EncLog table (0x1E). This loader processes debugging metadata that tracks
5+
//! modifications made during Edit-and-Continue debugging sessions.
6+
//!
7+
//! # Table Structure
8+
//!
9+
//! The EncLog table contains Edit-and-Continue operation tracking information:
10+
//! - **Token**: Metadata token identifying the affected element
11+
//! - **FuncCode**: Operation code (create=0, update=1, delete=2)
12+
//!
13+
//! # Usage Context
14+
//!
15+
//! This table is only present in assemblies that have been modified during debugging
16+
//! sessions using Edit-and-Continue functionality. It enables the runtime to understand
17+
//! what metadata elements have been added, modified, or removed during debugging.
18+
//!
19+
//! # Reference
20+
//! - [ECMA-335 II.22.12](https://ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf) - EncLog table specification
21+
22+
use crate::{
23+
metadata::{
24+
loader::{LoaderContext, MetadataLoader},
25+
tables::{EncLogRaw, TableId},
26+
},
27+
Result,
28+
};
29+
30+
/// Loader for the EncLog metadata table
31+
///
32+
/// Implements [`crate::metadata::loader::MetadataLoader`] to process the EncLog table (0x1E)
33+
/// which contains Edit-and-Continue log entries that track metadata modifications made during
34+
/// debugging sessions. This table records all changes to help the runtime understand what
35+
/// has been modified during active debugging.
36+
pub(crate) struct EncLogLoader;
37+
38+
impl MetadataLoader for EncLogLoader {
39+
/// Load Edit-and-Continue log entries from the EncLog table
40+
///
41+
/// Processes EncLog table rows (if present) and stores the Edit-and-Continue operation
42+
/// information in the loader context. The EncLog table is optional and only present
43+
/// in assemblies that have been modified during debugging sessions.
44+
///
45+
/// # Arguments
46+
/// * `context` - Loader context containing metadata tables and storage collections
47+
///
48+
/// # Returns
49+
/// * `Ok(())` - EncLog entries successfully loaded or table not present
50+
/// * `Err(`[`crate::Error`]`)` - Malformed data or processing error
51+
fn load(&self, context: &LoaderContext) -> Result<()> {
52+
if let Some(header) = context.meta {
53+
if let Some(table) = header.table::<EncLogRaw>(TableId::EncLog) {
54+
table.par_iter().try_for_each(|row| {
55+
let owned = row.to_owned()?;
56+
57+
context.enc_log.insert(row.token, owned);
58+
Ok(())
59+
})?;
60+
}
61+
}
62+
Ok(())
63+
}
64+
65+
/// Returns the table identifier for the EncLog table
66+
///
67+
/// # Returns
68+
/// [`crate::metadata::tables::TableId::EncLog`] (0x1E)
69+
fn table_id(&self) -> TableId {
70+
TableId::EncLog
71+
}
72+
73+
/// Returns the list of table dependencies
74+
///
75+
/// The EncLog table has no dependencies on other metadata tables or heaps,
76+
/// as it contains only metadata tokens and operation codes.
77+
///
78+
/// # Returns
79+
/// Empty slice - no table dependencies
80+
fn dependencies(&self) -> &'static [TableId] {
81+
&[]
82+
}
83+
}

src/metadata/tables/enclog/mod.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//! EncLog table module
2+
//!
3+
//! Provides complete support for the ECMA-335 EncLog metadata table (0x1E), which contains
4+
//! Edit-and-Continue log entries that track modifications made during debugging sessions.
5+
//! This module includes raw table access, collection types, and edit operation support.
6+
//!
7+
//! # Components
8+
//!
9+
//! - [`crate::metadata::tables::enclog::EncLogRaw`]: Raw table structure (no heap resolution needed)
10+
//! - [`crate::metadata::tables::enclog::EncLog`]: Type alias to Raw since all data is self-contained
11+
//! - [`crate::metadata::tables::enclog::loader::EncLogLoader`]: Internal loader for processing EncLog table data
12+
//! - Type aliases for efficient collections and reference management
13+
//!
14+
//! # EncLog Table Structure
15+
//!
16+
//! The EncLog table contains Edit-and-Continue operation records:
17+
//! - **Token**: Metadata token identifying the affected element (4 bytes)
18+
//! - **FuncCode**: Operation code (create/update/delete) (4 bytes)
19+
//!
20+
//! # Edit-and-Continue Support
21+
//!
22+
//! This table supports .NET's Edit-and-Continue debugging feature, which allows developers
23+
//! to modify source code while the program is paused in the debugger. The EncLog table
24+
//! tracks all metadata changes made during these edit sessions, enabling the runtime to
25+
//! understand what elements have been modified, added, or removed.
26+
//!
27+
//! # Table Characteristics
28+
//!
29+
//! - **Optional**: Not all assemblies contain EncLog tables
30+
//! - **Debugging-specific**: Primarily used during active debugging sessions
31+
//! - **Self-contained**: Contains only primitive values, no heap references
32+
//! - **Sequential**: Entries are typically ordered by edit session timestamp
33+
//!
34+
//! # Reference
35+
//! - [ECMA-335 II.22.12](https://ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf) - EncLog table specification
36+
37+
use crossbeam_skiplist::SkipMap;
38+
use std::sync::Arc;
39+
40+
use crate::metadata::token::Token;
41+
42+
mod loader;
43+
mod raw;
44+
45+
pub(crate) use loader::*;
46+
pub use raw::*;
47+
48+
/// A map that holds the mapping of [`crate::metadata::token::Token`] to parsed [`crate::metadata::tables::enclog::EncLog`]
49+
///
50+
/// Thread-safe concurrent map using skip list data structure for efficient lookups
51+
/// and insertions. Used to cache resolved EncLog entries by their metadata tokens.
52+
pub type EncLogMap = SkipMap<Token, EncLogRc>;
53+
54+
/// A vector that holds a list of [`crate::metadata::tables::enclog::EncLog`] references
55+
///
56+
/// Thread-safe append-only vector for storing EncLog collections. Uses atomic operations
57+
/// for lock-free concurrent access and is optimized for scenarios with frequent reads.
58+
pub type EncLogList = Arc<boxcar::Vec<EncLogRc>>;
59+
60+
/// A reference-counted pointer to an [`crate::metadata::tables::enclog::EncLog`]
61+
///
62+
/// Provides shared ownership and automatic memory management for EncLog instances.
63+
/// Multiple references can safely point to the same EncLog data across threads.
64+
pub type EncLogRc = Arc<EncLog>;
65+
66+
/// Edit-and-Continue log entry for tracking debugging session modifications
67+
///
68+
/// Type alias to [`crate::metadata::tables::enclog::EncLogRaw`] since the EncLog table contains only primitive values
69+
/// that don't require heap resolution. All data in the raw structure is immediately usable.
70+
///
71+
/// The EncLog table records all metadata changes made during Edit-and-Continue debugging sessions,
72+
/// enabling the runtime to understand what elements have been modified, added, or removed during
73+
/// active debugging.
74+
///
75+
/// # Data Model
76+
///
77+
/// Unlike other metadata tables that reference string or blob heaps, EncLog contains
78+
/// only integer values (tokens and operation codes), making the "raw" and "owned"
79+
/// representations identical.
80+
///
81+
/// # Reference
82+
/// - [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)
83+
pub type EncLog = EncLogRaw;

0 commit comments

Comments
 (0)