Skip to content

Releases: lordmilko/ClrDebug

ClrDebug 0.3.3

22 Apr 05:43
Compare
Choose a tag to compare

ClrDebug 0.3.3 contains a variety of improvements, bug fixes and breaking changes, split across the following feature areas:

ICorDebug

  • Add RaiseOnAnyEvent method to CorDebugManagedCallback to allow invoking OnAnyEvent from an overridden HandleEvent method, without needing to call the base HandleEvent implementation
  • Fix bufsize being a required parameter on CorDebugProcess.SetUnmanagedBreakpoint
  • Fix memberRef not being an mdMemberRef on CorDebugObjectValue.GetVirtualMethod/GetVirtualMethodAndType
  • Fix UnsignedValueHelpers crashing when trying to compare ClrDebug's custom numeric types
  • Fix various ICorDebugType/ICorDebugValue parameters in ICorDebugClass/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 with DEBUG_BREAK
  • Add missing DbgEng struct types
  • Fix DbgEng interface wrappers failing (RPC_E_INVALIDMETHOD) when using proxy interfaces returned from DebugConnect
  • Fix IDebugClient.OutputServers incorrectly being called OutputServer
  • Add DebugSymbols GetScope<T>, SetScope<T>, GetScopeEx<T> and SetScopeEx<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 an IntPtr rather than a byte[] for pbData
  • Add an extension method for DiaAddressMap that takes an IMAGE_SECTION_HEADER[]
  • Add IDiaDataSource2/IDiaDataSource3
  • Fix DiaStackWalkFrame.GetRegisterValue/PutRegisterValue not using CV_HREG_e
  • Fix DiaSymbol.Function not returning a bool
  • Fix DiaSymbol.Value crashing when a VARIANT contains a fake BSTR, as the CLR doesn't understand the custom free logic that is required
  • Add DiaSession.As<T>() extension method
  • Show FileName as ToString() of DiaInjectedSource, DiaInputAssemblyFile and DiaSourceFile
  • Remove DiaStackWalkFrame and DiaStackWalkHelper wrappers, as these type is expected to be implemented by user code

Misc

  • Clear Current when enumerator types can no longer MoveNext
  • 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 with MethodImplOptions.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 an UnmanagedType.U2 instead of a UnmanagedType.U1 for the function name
  • Rename enum MEM_FLAGS to MEM_TYPE_FLAGS

ClrDebug 0.3.2

02 Jan 03:41
Compare
Choose a tag to compare

Bugfixes

  • Fix string marshalling on DIA interfaces not working when using a version of DIA that uses fake BSTR strings

    When using DIA, you must now set ClrDebug.Extensions.DiaStringsUseComHeap to either true or false 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 and DUMP_HEADER64 marshalling issues

  • Fix the DebuggerDisplay on certain structs sometimes throwing a NullReferenceException when attempting to display a null interface

ClrDebug 0.3.1

22 Dec 09:23
Compare
Choose a tag to compare

Improvements

  • Greatly enhance DbgEng XmlDocs on enum types

  • Expose WINDBG_EXTENSION_APIS from WinDbgExtensionAPI 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 and ISOSDacInterface13

  • Fix callback event handlers not being marked as event

  • Add NTSTATUS HRESULT_FROM_NT values to HRESULT

  • 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 to Marshal.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 own ClrDebug.InAttribute and ClrDebug.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, and System.Runtime.InteropServices.OutAttribute now is allowed again - but only on arrays! As such, due to all [Out] array methods now being decorated with a fake ClrDebug.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 using DiaSourceAlt or the DIA inside DbgHelp) the CLR will crash when it attempts to call SysFreeString. The next release will provide a mechanism to support both real and fake BSTR values that are emitted from DIA

ClrDebug 0.3.0

15 Nov 23:58
Compare
Choose a tag to compare

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 same ComWrappers instance. Source generated COM uses an internal StrategyBasedComWrappers.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 an out interface parameters: such interfaces will be System.__ComObject instances, which are completely incompatible with the ComWrappers infrastructure. Interfaces should instead be marshalled as out IntPtr and then manually wrapped using GetObjectForIUnknown<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 between CorDebugValue types
  • Add all HRESULT types defined in corerror.h
  • Make CorDebugObjectValue non-abstract
  • Add DebuggerDisplay on CorDebugValue 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 via MetaDataGetDispenser() method in the CLR
  • Throw exceptions regarding the current thread being STA in the default CorDebug constructor, rather than in CLRCreateInstance()
  • 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 using CORDB_ADDRESS instead of CLRDATA_ADDRESS
  • Fix DebuggerDisplay in various DEBUG_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 use Marshal.GetDelegateForFunctionPointer safely cross-platform anyway
  • Renamed STARTUPINFO to STARTUPINFOW
  • Renamed SymTag to SymTagEnum
  • Use char[] instead of StringBuilder on all COM interfaces
  • Use IntPtr instead of ICorDebug on DbgShim 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

31 Mar 23:59
Compare
Choose a tag to compare
  • 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 to DacpFieldDescData.TokenOfType
  • Add CorRuntimeHost.EnumDomains<T> extension method for enumerating AppDomains as either an _AppDomain or AppDomain

ClrDebug 0.2.0

11 Feb 23:49
Compare
Choose a tag to compare
  • 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 than CLRDataTarget / 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

12 Jan 01:07
Compare
Choose a tag to compare

Initial release