Releases: lordmilko/ClrDebug
ClrDebug 0.3.3
ClrDebug 0.3.3 contains a variety of improvements, bug fixes and breaking changes, split across the following feature areas:
ICorDebug
- Add
RaiseOnAnyEvent
method toCorDebugManagedCallback
to allow invokingOnAnyEvent
from an overriddenHandleEvent
method, without needing to call the baseHandleEvent
implementation - Fix
bufsize
being a required parameter onCorDebugProcess.SetUnmanagedBreakpoint
- Fix
memberRef
not being anmdMemberRef
onCorDebugObjectValue.GetVirtualMethod
/GetVirtualMethodAndType
- Fix
UnsignedValueHelpers
crashing when trying to compare ClrDebug's custom numeric types - Fix various
ICorDebugType
/ICorDebugValue
parameters inICorDebugClass
/ICorDebugEval
not being marshalled correctly (Fix #13) - Fix
CorDebugStringValue.GetString
requiring a manual array (Fix #14)
DbgEng
- Add DbgEng's new model/service interface types
- Add missing DebugClient related interface types
- Implement comprehensive
Dispose
method on DebugClient. Disposes and clears all sub-RCW members to prepare for unloading DbgEng - Remove
DEBUG_BREAKPOINT_ACCESS_TYPE
, which is redundant withDEBUG_BREAK
- Add missing DbgEng struct types
- Fix DbgEng interface wrappers failing (
RPC_E_INVALIDMETHOD
) when using proxy interfaces returned fromDebugConnect
- Fix
IDebugClient.OutputServers
incorrectly being calledOutputServer
- Add
DebugSymbols GetScope<T>
,SetScope<T>
,GetScopeEx<T>
andSetScopeEx<T>
extension methods - Add
CorDebugProcess.WriteMemory
extension methods
DIA
- Fix
DiaEnumStackFrames
not being an enumerator - Fix
DiaStringMarshaller
not properly creating a fake BSTR properly, and failing to marshal strings when a DIA method is being intercepted in a detour hook - Change
DiaAddressMap.SetImageHeaders
to take anIntPtr
rather than abyte[]
forpbData
- Add an extension method for
DiaAddressMap
that takes anIMAGE_SECTION_HEADER[]
- Add
IDiaDataSource2
/IDiaDataSource3
- Fix
DiaStackWalkFrame.GetRegisterValue
/PutRegisterValue
not usingCV_HREG_e
- Fix
DiaSymbol.Function
not returning abool
- Fix
DiaSymbol.Value
crashing when aVARIANT
contains a fake BSTR, as the CLR doesn't understand the custom free logic that is required - Add
DiaSession.As<T>()
extension method - Show F
ileName
asToString()
ofDiaInjectedSource
,DiaInputAssemblyFile
andDiaSourceFile
- Remove
DiaStackWalkFrame
andDiaStackWalkHelper
wrappers, as these type is expected to be implemented by user code
Misc
- Clear
Current
when enumerator types can no longerMoveNext
- Add extension methods for CLR macros that perform common checks on enum values (e.g.
IsTdPublic
) - Work around a bug in the the CLR's implementation of
ICLRDataProcess.GetRuntimeNameByAddress
- Fix
CorpubPublishClass
not being decorated withMethodImplOptions.InternalCall
- Add missing values from
CorAssemblyFlags
,CorMethodImpl
- Use
X86_CONTEXT_FLAGS
enum type in X86/AMD64 CONTEXT types - Add CLR related PE header types
- Add Ready2Run PE header types
- Add
DllGetClassObject
extension method - Don't free strings owned by the CLR emitted from various
IMetaDataTables
methods in .NET 8 - Fix
ISOSDacInterface.GetJitHelperFunctionName
incorrectly using anUnmanagedType.U2
instead of aUnmanagedType.U1
for the function name - Rename enum
MEM_FLAGS
toMEM_TYPE_FLAGS
ClrDebug 0.3.2
Bugfixes
-
Fix string marshalling on DIA interfaces not working when using a version of DIA that uses fake
BSTR
stringsWhen using DIA, you must now set
ClrDebug.Extensions.DiaStringsUseComHeap
to eithertrue
orfalse
so that ClrDebug knows how to marshal strings from the DIA implementation you are using. Attempting to marshal strings from DIA interfaces without setting this property will throw an exception that explains how to use the property. -
Fix
[Out]
arrays not working in source generated COM -
Fix
DUMP_HEADER32
andDUMP_HEADER64
marshalling issues -
Fix the
DebuggerDisplay
on certain structs sometimes throwing aNullReferenceException
when attempting to display anull
interface
ClrDebug 0.3.1
Improvements
-
Greatly enhance DbgEng XmlDocs on enum types
-
Expose
WINDBG_EXTENSION_APIS
fromWinDbgExtensionAPI
wrapper -
Display a better error message when an throwing a
DebugException
with an unknown HRESULT -
Allow specifying wrapper types to generic extension methods that are used to retrieve IUnknown instances
e.g. instead of
new MetaDataImport(corDebugModule.GetMetaDataInterface<IMetaDataImport>())
you can now do
corDebugModule.GetMetaDataInterface<MetaDataImport>()
-
Add
ISOSDacInterface12
andISOSDacInterface13
-
Fix callback event handlers not being marked as
event
-
Add
NTSTATUS
HRESULT_FROM_NT
values toHRESULT
-
Add
DebugAdvanced
GetThreadContext
/SetThreadContext
generic extension methods
Bugfixes
- Return null from
New()
wrapper methods when a null input object is specified (i.e.CorDebugValue.New(null)
) - Check whether raw COM objects are null prior attempting to wrap them
- Work around a bug in
ISOSDacInterface.GetFrameName
misreporting the length of the returned string in .NET Framework - Fix
LARGE_INTEGER
/ULARGE_INTEGER
breaking the alignment of other structs - Fix several extension methods not calling
Marshal.DestroyStructure
after a previous call toMarshal.StructureToPtr
Known Issues
- Due to the breaking change in .NET 8's source generated COM that you're not allowed to decorate COM method parameters with
[In]
and[Out]
, ClrDebug defines its ownClrDebug.InAttribute
andClrDebug.OutAttribute
attributes to make the .NET 8 compiler ignore these attributes. However, after realizing blacklisting these attributes completely was a mistake, Microsoft partially reversed course on this decision, andSystem.Runtime.InteropServices.OutAttribute
now is allowed again - but only on arrays! As such, due to all[Out]
array methods now being decorated with a fakeClrDebug.OutAttribute
, any methods that output non-blittable arrays (meaning any array consisting of interfaces, strings or structs that require complex marshalling) will fail to fill their managed output buffer. This only affects the .NET 8 version of ClrDebug, and will be fixed in the next release - DIA supports two different mechanisms of allocating strings. If a fake
BSTR
is returned from DIA (as occurs when usingDiaSourceAlt
or the DIA insideDbgHelp
) the CLR will crash when it attempts to callSysFreeString
. The next release will provide a mechanism to support both real and fakeBSTR
values that are emitted from DIA
ClrDebug 0.3.0
New Features
-
ClrDebug is now cross-platform/NativeAOT compatible! 🎉
-
When targeting .NET 8 or above, ClrDebug will used source generated COM for marshalling between native and managed code
-
Types your program declares that implement COM interfaces (e.g. a custom
ClassFactory : IClassFactory
) must be decorated with[GeneratedComClass]
in order for source generated COM to generate the required native vtable -
To simplify converting between RCWs/CCWs, ClrDebug provides a series of cross-platform methods that you can take advantage of
using static ClrDebug.Extensions; //Retrieve an RCW from a given pointer cast to a specified type T GetObjectForIUnknown<T>(IntPtr pUnk); //Retrieve an RCW from a given pointer object GetObjectForIUnknown(IntPtr pUnk); //Retrieve an IUnknown CCW for a given managed object IntPtr GetIUnknownForObject(object o);
ClrDebug caches its own
StrategyBasedComWrappers
singleton to use for these methods internally, so that you don't have to waste allocations each time you want to do a manual RCW/CCW conversion -
⚠️ Watch out when comparing the equivalence of source generated COM RCWs!⚠️ I believe RCWs are only considered equivalent when they were created by the sameComWrappers
instance. Source generated COM uses an internalStrategyBasedComWrappers.Instance
singleton, which means that any objects you marshal yourself may not be considered equivalent to objects marshalled by the runtime, even if both objects have the same underlying native pointer! In addition, you should ensure that you do not declare P/Invoke functions that emit anout interface
parameters: such interfaces will beSystem.__ComObject
instances, which are completely incompatible with theComWrappers
infrastructure. Interfaces should instead be marshalled asout IntPtr
and then manually wrapped usingGetObjectForIUnknown<T>()
as listed above -
Types in the
ClrDebug.CoClass
namespace are currently not available in the .NET 8 version of ClrDebug -
Due to the specialized custom marshalling required by DbgEng's invalid COM implementation, interfaces defined under the
ClrDebug.DbgEng
namespace do not use source generated COM and are not NativeAOT compatible
-
-
Add
hostfxr
API -
Add
CoreCLR
API -
Add DIA types
General Enhancements
- Add
As<T>
extension methods for converting betweenCorDebugValue
types - Add all
HRESULT
types defined incorerror.h
- Make
CorDebugObjectValue
non-abstract - Add
DebuggerDisplay
onCorDebugValue
types to show the possible interfaces that the underlying COM object supports - Add
ICLRRuntimeHost2
+ICLRRuntimeHost4
- Add
CLRDataCreateInstanceInterfaces
overload that takes a module handle - Add
MetaDataDispenserEx
constructor accepting a CLR module handle - Implement support for retrieving
MetaDataDispenser
viaMetaDataGetDispenser()
method in the CLR - Throw exceptions regarding the current thread being STA in the default
CorDebug
constructor, rather than inCLRCreateInstance()
- Cache
PSTARTUP_CALLBACK
delegates in DbgShim to prevent callbacks from being garbage collected while waiting for callback to occur - Support .NET Core/cross-platform DAC libraries in
Extensions.CLRDataCreateInstanceInterfaces()
Bugfixes
- Fix mathematical operators against negative numbers yielding incorrect results
- Fix
ICLRDataTarget
extensions incorrectly usingCORDB_ADDRESS
instead ofCLRDATA_ADDRESS
- Fix
DebuggerDisplay
in variousDEBUG_EVENT
structs
Breaking Changes
ClrDebug does not guarantee any backwards compatibility with each release, and solely prioritizes maintaining correctness against the native type definitions it attempts to model. The following is a list of notable breaking changes to consider when updating to this release
- Removed
DbgShim.GetDelegate
- The
DbgShim
class is now cross-platform compatible, and you can't useMarshal.GetDelegateForFunctionPointer
safely cross-platform anyway
- The
- Renamed
STARTUPINFO
toSTARTUPINFOW
- Renamed
SymTag
toSymTagEnum
- Use
char[]
instead ofStringBuilder
on all COM interfaces - Use
IntPtr
instead ofICorDebug
onDbgShim
delegate types for NativeAOT/cross-platform compatibility- To reduce the friction of these native compatible interfaces, DbgShim now defines several managed-friendly delegates + extension methods to simplifying calling these methods
ClrDebug 0.2.1
- Add additional mathematical/boolean operators on numeric wrapper types
- Improve numeric wrapper type implicit conversions
- Fix numeric types returning incorrect values in 32-bit processes
- Add
ICLRRuntimeLocator
- Add
CorElementType.Max
- Rename
DacpFieldDescData.TypeToken
toDacpFieldDescData.TokenOfType
- Add
CorRuntimeHost.EnumDomains<T>
extension method for enumerating AppDomains as either an_AppDomain
orAppDomain
ClrDebug 0.2.0
-
Add
As<T>
extension methods for easily casting an underlying interface between various wrapper types it supports// Get an XCLRDataProcess from somewhere XCLRDataProcess clrDataProcess = GetXCLRDataProcess(); // Cast the underlying mscordacwks!ClrDataAccess to ISOSDacInterface and wrap as SOSDacInterface SOSDacInterface sosDacInterface = clrDataProcess.As<SOSDacInterface>();
-
Fix various method parameters / struct members not having the correct type
-
Fix various
GetContext
extension methods not freeing their buffer properly -
Target
ICLRDataTarget
/ICorDebugDataTarget
on extension methods rather thanCLRDataTarget
/CorDebugDataTarget
-
Add unmanaged profiling API types. Note that in order to write a profiler in .NET you must
- Use NativeAOT (which hosts its own minimal runtime/GC)
- Use .NET's native
ComWrappers
API (not to be confused with my ComWrapper library) for generating RCWs/CCWs (as this dynamic infrastructure is not included in NativeAOT). See this issue for more information on the status of using COM in NativeAOT. Ostensibly, in the future Microsoft will include a source generator that automatically generates RCW/CCW code for you.
ClrDebug 0.1.0
Initial release