@@ -15,9 +15,12 @@ readonly struct ModuleHandle
1515[Flags ]
1616enum ModuleFlags
1717{
18- Tenured = 0x 00000001 , // Set once we know for sure the Module will not be freed until the appdomain itself exits
19- EditAndContinue = 0x 00000008 , // Edit and Continue is enabled for this module
20- ReflectionEmit = 0x 00000040 , // Reflection.Emit was used to create this module
18+ Tenured = 0x 1 , // Set once we know for sure the Module will not be freed until the appdomain itself exits
19+ JitOptimizationDisabled = 0x 2 , // Cached flag: JIT optimizations are disabled
20+ EditAndContinue = 0x 8 , // Edit and Continue is enabled for this module
21+ ReflectionEmit = 0x 40 , // Reflection.Emit was used to create this module
22+ ProfDisableOptimizations = 0x 80 , // Profiler disabled JIT optimizations
23+ EncCapable = 0x 200 , // Cached flag: module is Edit and Continue capable
2124 }
2225
2326[Flags ]
@@ -90,6 +93,31 @@ TargetPointer GetObjectHandle(TargetPointer loaderAllocatorPointer);
9093TargetPointer GetILHeader (ModuleHandle handle , uint token );
9194TargetPointer GetDynamicIL (ModuleHandle handle , uint token );
9295IReadOnlyDictionary < string , TargetPointer > GetLoaderAllocatorHeaps (TargetPointer loaderAllocatorPointer );
96+
97+ DebuggerAssemblyControlFlags GetDebuggerInfoBits (ModuleHandle handle );
98+ void SetDebuggerInfoBits (ModuleHandle handle , DebuggerAssemblyControlFlags newBits );
99+ ```
100+
101+ The ` DebuggerAssemblyControlFlags ` enum is defined as:
102+ ``` csharp
103+ [Flags ]
104+ enum DebuggerAssemblyControlFlags : uint
105+ {
106+ DACF_NONE = 0x 00 ,
107+ DACF_ALLOW_JIT_OPTS = 0x 02 ,
108+ DACF_ENC_ENABLED = 0x 08 ,
109+ DACF_CONTROL_FLAGS_MASK = 0x 2E ,
110+ }
111+ ```
112+
113+ The ` ClrModifiableAssemblies ` enum (from ` EEConfig::ModifiableAssemblies ` ) is defined as:
114+ ``` csharp
115+ enum ClrModifiableAssemblies : uint
116+ {
117+ Unset = 0 ,
118+ None = 1 ,
119+ Debug = 2 ,
120+ }
93121```
94122
95123## Version 1
@@ -173,6 +201,7 @@ IReadOnlyDictionary<string, TargetPointer> GetLoaderAllocatorHeaps(TargetPointer
173201| ` DynamicILBlobTable ` | ` EntrySize ` | Size of each table entry |
174202| ` DynamicILBlobTable ` | ` EntryMethodToken ` | Offset of each entry method token from entry address |
175203| ` DynamicILBlobTable ` | ` EntryIL ` | Offset of each entry IL from entry address |
204+ | ` EEConfig ` | ` ModifiableAssemblies ` | Controls Edit and Continue support (ClrModifiableAssemblies enum) |
176205
177206
178207
@@ -181,6 +210,7 @@ IReadOnlyDictionary<string, TargetPointer> GetLoaderAllocatorHeaps(TargetPointer
181210| --- | --- | --- |
182211| ` AppDomain ` | TargetPointer | Pointer to the global AppDomain |
183212| ` SystemDomain ` | TargetPointer | Pointer to the global SystemDomain |
213+ | ` EEConfig ` | TargetPointer | Pointer to the global EEConfig (runtime configuration) |
184214
185215
186216### Contract Constants:
@@ -189,6 +219,9 @@ IReadOnlyDictionary<string, TargetPointer> GetLoaderAllocatorHeaps(TargetPointer
189219| ` ASSEMBLY_NOTIFYFLAGS_PROFILER_NOTIFIED ` | uint | Flag in Assembly NotifyFlags indicating the Assembly will notify profilers. | ` 0x1 ` |
190220| ` DefaultDomainFriendlyName ` | string | Friendly name returned when ` AppDomain.FriendlyName ` is null (matches native ` DEFAULT_DOMAIN_FRIENDLY_NAME ` ) | ` "DefaultDomain" ` |
191221| ` MaxWebcilSections ` | ushort | Maximum number of COFF sections supported in a Webcil image (must stay in sync with native ` WEBCIL_MAX_SECTIONS ` ) | ` 16 ` |
222+ | ` DebuggerInfoMask ` | uint | Mask for the debugger info bits within the Module's transient flags | ` 0x0000FC00 ` |
223+ | ` DebuggerInfoShift ` | int | Bit shift for the debugger info bits within the Module's transient flags | ` 10 ` |
224+ | ` DEBUGGER_ALLOW_JIT_OPTS_PRIV ` | uint | Debugger allows JIT optimizations (shifted in transient flags) | ` 0x00000800 ` |
192225
193226Contracts used:
194227| Contract Name |
@@ -817,6 +850,36 @@ TargetPointer GetDynamicIL(ModuleHandle handle, uint token)
817850 Data .DynamicILBlobEntry blobEntry = shashContract .LookupSHash (shash , token );
818851 return /* blob entry IL address */
819852}
853+
854+ DebuggerAssemblyControlFlags GetDebuggerInfoBits (ModuleHandle handle )
855+ {
856+ uint flags = // read Module::Flags at handle.Address + Flags offset
857+ return (DebuggerAssemblyControlFlags )((flags & DebuggerInfoMask ) >> DebuggerInfoShift );
858+ }
859+
860+ void SetDebuggerInfoBits (ModuleHandle handle , DebuggerAssemblyControlFlags newBits )
861+ {
862+ uint currentFlags = // read Module::Flags at handle.Address + Flags offset
863+ uint debuggerInfoBitsMask = DebuggerInfoMask >> DebuggerInfoShift ;
864+ uint updated = (currentFlags & ~ DebuggerInfoMask ) | (((uint )newBits & debuggerInfoBitsMask ) << DebuggerInfoShift );
865+
866+ bool jitOptDisabled = (updated & DEBUGGER_ALLOW_JIT_OPTS_PRIV ) == 0 || (updated & PROF_DISABLE_OPTIMIZATIONS ) != 0 ;
867+ // Set or clear IS_JIT_OPTIMIZATION_DISABLED accordingly.
868+
869+ if ((updated & IS_ENC_CAPABLE ) != 0 )
870+ {
871+ ClrModifiableAssemblies modifiable = // read EEConfig::ModifiableAssemblies from g_pConfig
872+ if (modifiable != None )
873+ {
874+ bool encRequested = (newBits & DACF_ENC_ENABLED ) != 0 ;
875+ bool setEnC = encRequested || (modifiable == Debug && jitOptDisabled );
876+ if (setEnC )
877+ updated |= IS_EDIT_AND_CONTINUE ;
878+ }
879+ }
880+
881+ // Write updated flags back to handle.Address + Flags offset
882+ }
820883```
821884
822885### DacEnumerableHash (EETypeHashTable and InstMethodHashTable)
0 commit comments