From b36964b06251036260e42e977bd1ca26b5b74978 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Tue, 24 Feb 2026 08:51:11 -0500 Subject: [PATCH 1/3] Convert IDacDbiInterface methods to return HRESULT Change all 119 non-HRESULT virtual methods in IDacDbiInterface to return HRESULT. Methods that previously returned values (BOOL, VMPTR_*, ULONG, etc.) now take an additional OUT parameter. void methods simply change their return type to HRESULT. This is the interface declaration change for Approach E: eliminating C++ exceptions crossing the DAC/DBI DSO boundary on Android. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/coreclr/debug/inc/dacdbiinterface.h | 465 ++++++------------------ 1 file changed, 119 insertions(+), 346 deletions(-) diff --git a/src/coreclr/debug/inc/dacdbiinterface.h b/src/coreclr/debug/inc/dacdbiinterface.h index 9cf4c4d6172dc1..c989a9c9869128 100644 --- a/src/coreclr/debug/inc/dacdbiinterface.h +++ b/src/coreclr/debug/inc/dacdbiinterface.h @@ -219,8 +219,7 @@ class IDacDbiInterface // consistency failures exceptions (this is independent from asserts - there are legitimate // scenarios for all 4 combinations). // - virtual - void DacSetTargetConsistencyChecks(bool fEnableAsserts) = 0; + virtual HRESULT DacSetTargetConsistencyChecks(bool fEnableAsserts) = 0; // // Destroy the interface object. The client should call this when it's done @@ -232,8 +231,7 @@ class IDacDbiInterface // Notes: // The client should not call anything else on this interface after Destroy. // - virtual - void Destroy() = 0; + virtual HRESULT Destroy() = 0; //----------------------------------------------------------------------------- // General purpose target inspection functions @@ -253,8 +251,7 @@ class IDacDbiInterface // If the left-side is started up, then data is ready. (Although data may be temporarily inconsistent, // see DataSafe). We may still get a Startup Exception in these cases, but it can be ignored. // - virtual - BOOL IsLeftSideInitialized() = 0; + virtual HRESULT IsLeftSideInitialized(OUT BOOL * pResult) = 0; // @@ -273,8 +270,7 @@ class IDacDbiInterface // An AppDomainId is unique for the lifetime of the VM. // This is the inverse function of GetAppDomainId(). // - virtual - VMPTR_AppDomain GetAppDomainFromId(ULONG appdomainId) = 0; + virtual HRESULT GetAppDomainFromId(ULONG appdomainId, OUT VMPTR_AppDomain * pRetVal) = 0; // @@ -289,8 +285,7 @@ class IDacDbiInterface // Notes: // An AppDomainId is unique for the lifetime of the VM. It is non-zero. // - virtual - ULONG GetAppDomainId(VMPTR_AppDomain vmAppDomain) = 0; + virtual HRESULT GetAppDomainId(VMPTR_AppDomain vmAppDomain, OUT ULONG * pRetVal) = 0; // // Get the managed AppDomain object for an AppDomain. @@ -306,11 +301,9 @@ class IDacDbiInterface // The AppDomain managed object is lazily constructed on the AppDomain the first time // it is requested. It may be NULL. // - virtual - VMPTR_OBJECTHANDLE GetAppDomainObject(VMPTR_AppDomain vmAppDomain) = 0; + virtual HRESULT GetAppDomainObject(VMPTR_AppDomain vmAppDomain, OUT VMPTR_OBJECTHANDLE * pRetVal) = 0; - virtual - void GetAssemblyFromDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Assembly * vmAssembly) = 0; + virtual HRESULT GetAssemblyFromDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Assembly * vmAssembly) = 0; // // Determines whether the runtime security system has assigned full-trust to this assembly. @@ -326,8 +319,7 @@ class IDacDbiInterface // Of course trusted malicious code in the process could always cause this API to lie. However, // an assembly loaded without full-trust should have no way of causing this API to return true. // - virtual - BOOL IsAssemblyFullyTrusted(VMPTR_DomainAssembly vmDomainAssembly) = 0; + virtual HRESULT IsAssemblyFullyTrusted(VMPTR_DomainAssembly vmDomainAssembly, OUT BOOL * pResult) = 0; // @@ -346,10 +338,7 @@ class IDacDbiInterface // so callers should be prepared to listen for name-change events and requery. // AD names are specified by the user. // - virtual - void GetAppDomainFullName( - VMPTR_AppDomain vmAppDomain, - IStringHolder * pStrName) = 0; + virtual HRESULT GetAppDomainFullName(VMPTR_AppDomain vmAppDomain, IStringHolder * pStrName) = 0; // @@ -406,8 +395,7 @@ class IDacDbiInterface // relationship to the filename, and it's not necessarily the metadata name. // Do not use the simple name for anything other than as a pretty string to give the an end user. // - virtual - void GetModuleSimpleName(VMPTR_Module vmModule, IStringHolder * pStrFilename) = 0; + virtual HRESULT GetModuleSimpleName(VMPTR_Module vmModule, IStringHolder * pStrFilename) = 0; // @@ -434,9 +422,7 @@ class IDacDbiInterface // which will not be saved to disk) there is no filename. In that case this API // returns an empty string. // - virtual - BOOL GetAssemblyPath(VMPTR_Assembly vmAssembly, - IStringHolder * pStrFilename) = 0; + virtual HRESULT GetAssemblyPath(VMPTR_Assembly vmAssembly, IStringHolder * pStrFilename, OUT BOOL * pResult) = 0; // get a type def resolved across modules @@ -445,9 +431,7 @@ class IDacDbiInterface // output: pTargetRefInfo - domain file and type def from the referenced type (this may // come from a module other than the referencing module) // Note: throws - virtual - void ResolveTypeReference(const TypeRefData * pTypeRefInfo, - TypeRefData * pTargetRefInfo) = 0; + virtual HRESULT ResolveTypeReference(const TypeRefData * pTypeRefInfo, TypeRefData * pTargetRefInfo) = 0; // // Get the full path and file name to the module (if any). // @@ -473,9 +457,7 @@ class IDacDbiInterface // We intentionally don't use the function name "GetModuleFileName" here because // winbase #defines that token (along with many others) to have an A or W suffix. // - virtual - BOOL GetModulePath(VMPTR_Module vmModule, - IStringHolder * pStrFilename) = 0; + virtual HRESULT GetModulePath(VMPTR_Module vmModule, IStringHolder * pStrFilename, OUT BOOL * pResult) = 0; // Get the metadata for the target module // @@ -510,8 +492,7 @@ class IDacDbiInterface // scenario with missing memory. Client should use alternative metadata location techniques (such as // an ImagePath to locate the original image and then pulling metadata from that file). // - virtual - void GetMetadata(VMPTR_Module vmModule, OUT TargetBuffer * pTargetBuffer) = 0; + virtual HRESULT GetMetadata(VMPTR_Module vmModule, OUT TargetBuffer * pTargetBuffer) = 0; // Definitions for possible symbol formats @@ -549,8 +530,7 @@ class IDacDbiInterface // - hosted modules where the host (such as SQL) store the PDB. // // In all cases, this can commonly fail. Executable code does not need to have a PDB. - virtual - void GetSymbolsBuffer(VMPTR_Module vmModule, OUT TargetBuffer * pTargetBuffer, OUT SymbolFormat * pSymbolFormat) = 0; + virtual HRESULT GetSymbolsBuffer(VMPTR_Module vmModule, OUT TargetBuffer * pTargetBuffer, OUT SymbolFormat * pSymbolFormat) = 0; // // Get properties for a module @@ -562,8 +542,7 @@ class IDacDbiInterface // Notes: // See definition of DomainAssemblyInfo for more details about what properties // this gives back. - virtual - void GetModuleData(VMPTR_Module vmModule, OUT ModuleInfo * pData) = 0; + virtual HRESULT GetModuleData(VMPTR_Module vmModule, OUT ModuleInfo * pData) = 0; // @@ -576,11 +555,9 @@ class IDacDbiInterface // Notes: // See definition of DomainAssemblyInfo for more details about what properties // this gives back. - virtual - void GetDomainAssemblyData(VMPTR_DomainAssembly vmDomainAssembly, OUT DomainAssemblyInfo * pData) = 0; + virtual HRESULT GetDomainAssemblyData(VMPTR_DomainAssembly vmDomainAssembly, OUT DomainAssemblyInfo * pData) = 0; - virtual - void GetModuleForDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Module * pModule) = 0; + virtual HRESULT GetModuleForDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Module * pModule) = 0; //......................................................................... // These methods were the methods that DBI was calling from IXClrData in V2. @@ -618,8 +595,7 @@ class IDacDbiInterface // This is provided for V3 compatibility to support Interop-debugging. // This should eventually be deprecated. // - virtual - AddressType GetAddressType(CORDB_ADDRESS address) = 0; + virtual HRESULT GetAddressType(CORDB_ADDRESS address, OUT AddressType * pRetVal) = 0; // @@ -637,8 +613,7 @@ class IDacDbiInterface // This yields true if the address is claimed by a CLR stub manager, or if the IP is in mscorwks. // Conceptually, This should eventually be merged with GetAddressType(). // - virtual - BOOL IsTransitionStub(CORDB_ADDRESS address) = 0; + virtual HRESULT IsTransitionStub(CORDB_ADDRESS address, OUT BOOL * pResult) = 0; //......................................................................... // Get the values of the JIT Optimization and EnC flags. @@ -657,11 +632,7 @@ class IDacDbiInterface // ICorDebugCode2::GetCompilerFlags. //......................................................................... - virtual - void GetCompilerFlags( - VMPTR_DomainAssembly vmDomainAssembly, - OUT BOOL * pfAllowJITOpts, - OUT BOOL * pfEnableEnC) = 0; + virtual HRESULT GetCompilerFlags(VMPTR_DomainAssembly vmDomainAssembly, OUT BOOL * pfAllowJITOpts, OUT BOOL * pfEnableEnC) = 0; //......................................................................... // Set the values of the JIT optimization and EnC flags. @@ -710,9 +681,7 @@ class IDacDbiInterface // See enumeration rules for details. // typedef void (*FP_APPDOMAIN_ENUMERATION_CALLBACK)(VMPTR_AppDomain vmAppDomain, CALLBACK_DATA pUserData); - virtual - void EnumerateAppDomains(FP_APPDOMAIN_ENUMERATION_CALLBACK fpCallback, - CALLBACK_DATA pUserData) = 0; + virtual HRESULT EnumerateAppDomains(FP_APPDOMAIN_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData) = 0; // @@ -741,10 +710,7 @@ class IDacDbiInterface // typedef void (*FP_ASSEMBLY_ENUMERATION_CALLBACK)(VMPTR_DomainAssembly vmDomainAssembly, CALLBACK_DATA pUserData); - virtual - void EnumerateAssembliesInAppDomain(VMPTR_AppDomain vmAppDomain, - FP_ASSEMBLY_ENUMERATION_CALLBACK fpCallback, - CALLBACK_DATA pUserData) = 0; + virtual HRESULT EnumerateAssembliesInAppDomain(VMPTR_AppDomain vmAppDomain, FP_ASSEMBLY_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData) = 0; @@ -773,11 +739,7 @@ class IDacDbiInterface // - Resource modules (which have no code or metadata) // - Inspection-only modules. These are viewed as pure data from the debugger's perspective. // - virtual - void EnumerateModulesInAssembly( - VMPTR_DomainAssembly vmAssembly, - FP_MODULE_ENUMERATION_CALLBACK fpCallback, - CALLBACK_DATA pUserData) = 0; + virtual HRESULT EnumerateModulesInAssembly(VMPTR_DomainAssembly vmAssembly, FP_MODULE_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData) = 0; @@ -800,8 +762,7 @@ class IDacDbiInterface // // This is also like a precursor to "AsyncBreakAllOtherThreads" // - virtual - void RequestSyncAtEvent() = 0; + virtual HRESULT RequestSyncAtEvent() = 0; // Sets a flag inside LS.Debugger that indicates that // 1. all "first chance exception" events should not be sent to the debugger @@ -831,8 +792,7 @@ class IDacDbiInterface // This doesn't do anything else (eg, no fake events). // // @dbgtodo- still an open Feature-Crew decision how this is exposed publicly. - virtual - void MarkDebuggerAttachPending() = 0; + virtual HRESULT MarkDebuggerAttachPending() = 0; // // Notify the debuggee that a debugger is attached / detached. @@ -849,8 +809,7 @@ class IDacDbiInterface // This lets the V3 codepaths invade the LS to subscribe to events. // // @dbgtodo- still an open Feature-Crew decision how this is exposed publicly. - virtual - void MarkDebuggerAttached(BOOL fAttached) = 0; + virtual HRESULT MarkDebuggerAttached(BOOL fAttached) = 0; @@ -895,16 +854,7 @@ class IDacDbiInterface // stackwalker that the GC uses. It must be in cooperative mode, and push a Frame on the // frame chain to protect the managed frames it hijacked from before it goes to preemptive mode. - virtual - void Hijack( - VMPTR_Thread vmThread, - ULONG32 dwThreadId, - const EXCEPTION_RECORD * pRecord, - T_CONTEXT * pOriginalContext, - ULONG32 cbSizeContext, - EHijackReason::EHijackReason reason, - void * pUserData, - CORDB_ADDRESS * pRemoteContextAddr) = 0; + virtual HRESULT Hijack(VMPTR_Thread vmThread, ULONG32 dwThreadId, const EXCEPTION_RECORD * pRecord, T_CONTEXT * pOriginalContext, ULONG32 cbSizeContext, EHijackReason::EHijackReason reason, void * pUserData, CORDB_ADDRESS * pRemoteContextAddr) = 0; // @@ -949,8 +899,7 @@ class IDacDbiInterface // Callback invoked for each thread. typedef void (*FP_THREAD_ENUMERATION_CALLBACK)(VMPTR_Thread vmThread, CALLBACK_DATA pUserData); - virtual - void EnumerateThreads(FP_THREAD_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData) = 0; + virtual HRESULT EnumerateThreads(FP_THREAD_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData) = 0; // Check if the thread is dead @@ -1005,8 +954,7 @@ class IDacDbiInterface // Whether a thread is dead can be inferred from the ICorDebug API. However, we have this // on DacDbi to ensure that this definition is consistent with the other DacDbi methods, // especially the enumeration and discovery rules. - virtual - bool IsThreadMarkedDead(VMPTR_Thread vmThread) = 0; + virtual HRESULT IsThreadMarkedDead(VMPTR_Thread vmThread, OUT bool * pResult) = 0; // @@ -1020,8 +968,7 @@ class IDacDbiInterface // // @dbgtodo- this should go away in V3. This is useless on a dump. - virtual - HANDLE GetThreadHandle(VMPTR_Thread vmThread) = 0; + virtual HRESULT GetThreadHandle(VMPTR_Thread vmThread, OUT HANDLE * pRetVal) = 0; // // Return the object handle for the managed Thread object corresponding to the specified thread. @@ -1035,8 +982,7 @@ class IDacDbiInterface // for the specified thread yet. // - virtual - VMPTR_OBJECTHANDLE GetThreadObject(VMPTR_Thread vmThread) = 0; + virtual HRESULT GetThreadObject(VMPTR_Thread vmThread, OUT VMPTR_OBJECTHANDLE * pRetVal) = 0; // // Get the allocation info corresponding to the specified thread. @@ -1046,8 +992,7 @@ class IDacDbiInterface // threadAllocInfo - the allocated bytes from SOH and UOH so far on this thread // - virtual - void GetThreadAllocInfo(VMPTR_Thread vmThread, DacThreadAllocInfo* threadAllocInfo) = 0; + virtual HRESULT GetThreadAllocInfo(VMPTR_Thread vmThread, DacThreadAllocInfo* threadAllocInfo) = 0; // // Set and reset the TSNC_DebuggerUserSuspend bit on the state of the specified thread @@ -1058,9 +1003,7 @@ class IDacDbiInterface // debugState - the desired CorDebugThreadState // - virtual - void SetDebugState(VMPTR_Thread vmThread, - CorDebugThreadState debugState) = 0; + virtual HRESULT SetDebugState(VMPTR_Thread vmThread, CorDebugThreadState debugState) = 0; // // Returns TRUE if this thread has an unhandled exception @@ -1071,8 +1014,7 @@ class IDacDbiInterface // Return Value // TRUE iff this thread has an unhandled exception // - virtual - BOOL HasUnhandledException(VMPTR_Thread vmThread) = 0; + virtual HRESULT HasUnhandledException(VMPTR_Thread vmThread, OUT BOOL * pResult) = 0; // // Return the user state of the specified thread. Most of the state are derived from @@ -1086,8 +1028,7 @@ class IDacDbiInterface // the user state of the specified thread // - virtual - CorDebugUserState GetUserState(VMPTR_Thread vmThread) = 0; + virtual HRESULT GetUserState(VMPTR_Thread vmThread, OUT CorDebugUserState * pRetVal) = 0; // @@ -1105,8 +1046,7 @@ class IDacDbiInterface // Return Value: // the user state of the specified thread // - virtual - CorDebugUserState GetPartialUserState(VMPTR_Thread vmThread) = 0; + virtual HRESULT GetPartialUserState(VMPTR_Thread vmThread, OUT CorDebugUserState * pRetVal) = 0; // @@ -1119,8 +1059,7 @@ class IDacDbiInterface // the connection ID of the specified thread // - virtual - CONNID GetConnectionID(VMPTR_Thread vmThread) = 0; + virtual HRESULT GetConnectionID(VMPTR_Thread vmThread, OUT CONNID * pRetVal) = 0; // // Return the task ID of the specified thread. @@ -1132,8 +1071,7 @@ class IDacDbiInterface // the task ID of the specified thread // - virtual - TASKID GetTaskID(VMPTR_Thread vmThread) = 0; + virtual HRESULT GetTaskID(VMPTR_Thread vmThread, OUT TASKID * pRetVal) = 0; // // Return the OS thread ID of the specified thread @@ -1145,8 +1083,7 @@ class IDacDbiInterface // the OS thread ID of the specified thread. Returns 0 if not scheduled. // - virtual - DWORD TryGetVolatileOSThreadID(VMPTR_Thread vmThread) = 0; + virtual HRESULT TryGetVolatileOSThreadID(VMPTR_Thread vmThread, OUT DWORD * pRetVal) = 0; // // Return the unique thread ID of the specified thread. The value used for the thread ID changes @@ -1163,8 +1100,7 @@ class IDacDbiInterface // Returns a stable and unique thread ID for the lifetime of the specified managed thread. // - virtual - DWORD GetUniqueThreadID(VMPTR_Thread vmThread) = 0; + virtual HRESULT GetUniqueThreadID(VMPTR_Thread vmThread, OUT DWORD * pRetVal) = 0; // // Return the object handle to the managed Exception object of the current exception @@ -1179,8 +1115,7 @@ class IDacDbiInterface // is an unmanaged thread which has entered and exited the runtime. // - virtual - VMPTR_OBJECTHANDLE GetCurrentException(VMPTR_Thread vmThread) = 0; + virtual HRESULT GetCurrentException(VMPTR_Thread vmThread, OUT VMPTR_OBJECTHANDLE * pRetVal) = 0; // // Return the object handle to the managed object for a given CCW pointer. @@ -1192,8 +1127,7 @@ class IDacDbiInterface // This function returns the object handle to the managed object for a given CCW pointer. // - virtual - VMPTR_OBJECTHANDLE GetObjectForCCW(CORDB_ADDRESS ccwPtr) = 0; + virtual HRESULT GetObjectForCCW(CORDB_ADDRESS ccwPtr, OUT VMPTR_OBJECTHANDLE * pRetVal) = 0; // // Return the object handle to the managed CustomNotification object of the current notification @@ -1207,8 +1141,7 @@ class IDacDbiInterface // The return value may be NULL if there is no current notification. // - virtual - VMPTR_OBJECTHANDLE GetCurrentCustomDebuggerNotification(VMPTR_Thread vmThread) = 0; + virtual HRESULT GetCurrentCustomDebuggerNotification(VMPTR_Thread vmThread, OUT VMPTR_OBJECTHANDLE * pRetVal) = 0; // @@ -1221,8 +1154,7 @@ class IDacDbiInterface // This function throws if the current appdomain is NULL for whatever reason. // - virtual - VMPTR_AppDomain GetCurrentAppDomain() = 0; + virtual HRESULT GetCurrentAppDomain(OUT VMPTR_AppDomain * pRetVal) = 0; // @@ -1245,8 +1177,7 @@ class IDacDbiInterface // // The debugger can't duplicate this policy with 100% accuracy, and // so we need DAC to lookup the assembly that was actually loaded. - virtual - VMPTR_DomainAssembly ResolveAssembly(VMPTR_DomainAssembly vmScope, mdToken tkAssemblyRef) = 0; + virtual HRESULT ResolveAssembly(VMPTR_DomainAssembly vmScope, mdToken tkAssemblyRef, OUT VMPTR_DomainAssembly * pRetVal) = 0; //----------------------------------------------------------------------------- // Interface for initializing the native/IL sequence points and native var info @@ -1268,12 +1199,7 @@ class IDacDbiInterface // Notes: //----------------------------------------------------------------------------- - virtual - void GetNativeCodeSequencePointsAndVarInfo(VMPTR_MethodDesc vmMethodDesc, - CORDB_ADDRESS startAddress, - BOOL fCodeAvailable, - OUT NativeVarData * pNativeVarData, - OUT SequencePoints * pSequencePoints) = 0; + virtual HRESULT GetNativeCodeSequencePointsAndVarInfo(VMPTR_MethodDesc vmMethodDesc, CORDB_ADDRESS startAddress, BOOL fCodeAvailable, OUT NativeVarData * pNativeVarData, OUT SequencePoints * pSequencePoints) = 0; // // Return the filter CONTEXT on the LS. Once we move entirely over to the new managed pipeline @@ -1290,8 +1216,7 @@ class IDacDbiInterface // we don't have a filter CONTEXT on the LS anymore. // - virtual - VMPTR_CONTEXT GetManagedStoppedContext(VMPTR_Thread vmThread) = 0; + virtual HRESULT GetManagedStoppedContext(VMPTR_Thread vmThread, OUT VMPTR_CONTEXT * pRetVal) = 0; typedef enum { @@ -1323,14 +1248,10 @@ class IDacDbiInterface // This is a special case that violates the 'no state' tenant. // - virtual - void CreateStackWalk(VMPTR_Thread vmThread, - DT_CONTEXT * pInternalContextBuffer, - OUT StackWalkHandle * ppSFIHandle) = 0; + virtual HRESULT CreateStackWalk(VMPTR_Thread vmThread, DT_CONTEXT * pInternalContextBuffer, OUT StackWalkHandle * ppSFIHandle) = 0; // Delete the stackwalk object created from CreateStackWalk. - virtual - void DeleteStackWalk(StackWalkHandle ppSFIHandle) = 0; + virtual HRESULT DeleteStackWalk(StackWalkHandle ppSFIHandle) = 0; // // Get the CONTEXT of the current frame where the stackwalker is stopped at. @@ -1340,9 +1261,7 @@ class IDacDbiInterface // pContext - OUT: the CONTEXT to be filled out. The context control flags are ignored. // - virtual - void GetStackWalkCurrentContext(StackWalkHandle pSFIHandle, - DT_CONTEXT * pContext) = 0; + virtual HRESULT GetStackWalkCurrentContext(StackWalkHandle pSFIHandle, DT_CONTEXT * pContext) = 0; // // Set the stackwalker to the given CONTEXT. The CorDebugSetContextFlag indicates whether @@ -1356,11 +1275,7 @@ class IDacDbiInterface // pContext - the specified CONTEXT. This may make correctional adjustments to the context's IP. // - virtual - void SetStackWalkCurrentContext(VMPTR_Thread vmThread, - StackWalkHandle pSFIHandle, - CorDebugSetContextFlag flag, - DT_CONTEXT * pContext) = 0; + virtual HRESULT SetStackWalkCurrentContext(VMPTR_Thread vmThread, StackWalkHandle pSFIHandle, CorDebugSetContextFlag flag, DT_CONTEXT * pContext) = 0; // // Unwind the stackwalker to the next frame. The next frame could be any actual stack frame, @@ -1376,8 +1291,7 @@ class IDacDbiInterface // Throw on error. // - virtual - BOOL UnwindStackWalkFrame(StackWalkHandle pSFIHandle) = 0; + virtual HRESULT UnwindStackWalkFrame(StackWalkHandle pSFIHandle, OUT BOOL * pResult) = 0; // // Check whether the specified CONTEXT is valid. The only check we perform right now is whether the @@ -1411,9 +1325,7 @@ class IDacDbiInterface // Return the type of the current frame // - virtual - FrameType GetStackWalkCurrentFrameInfo(StackWalkHandle pSFIHandle, - OPTIONAL DebuggerIPCE_STRData * pFrameData) = 0; + virtual HRESULT GetStackWalkCurrentFrameInfo(StackWalkHandle pSFIHandle, OPTIONAL DebuggerIPCE_STRData * pFrameData, OUT FrameType * pRetVal) = 0; // // Return the number of internal frames on the specified thread. @@ -1435,8 +1347,7 @@ class IDacDbiInterface // out how many interesting internal frames there are. // - virtual - ULONG32 GetCountOfInternalFrames(VMPTR_Thread vmThread) = 0; + virtual HRESULT GetCountOfInternalFrames(VMPTR_Thread vmThread, OUT ULONG32 * pRetVal) = 0; // // Enumerate the internal frames on the specified thread and invoke the provided callback on each of @@ -1454,10 +1365,7 @@ class IDacDbiInterface typedef void (*FP_INTERNAL_FRAME_ENUMERATION_CALLBACK)(const DebuggerIPCE_STRData * pFrameData, CALLBACK_DATA pUserData); - virtual - void EnumerateInternalFrames(VMPTR_Thread vmThread, - FP_INTERNAL_FRAME_ENUMERATION_CALLBACK fpCallback, - CALLBACK_DATA pUserData) = 0; + virtual HRESULT EnumerateInternalFrames(VMPTR_Thread vmThread, FP_INTERNAL_FRAME_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData) = 0; // // Given the FramePointer of the parent frame and the FramePointer of the current frame, @@ -1476,8 +1384,7 @@ class IDacDbiInterface // ask the ExInfo to do it. // - virtual - BOOL IsMatchingParentFrame(FramePointer fpToCheck, FramePointer fpParent) = 0; + virtual HRESULT IsMatchingParentFrame(FramePointer fpToCheck, FramePointer fpParent, OUT BOOL * pResult) = 0; // // Return the stack parameter size of a given method. This is necessary on x86 for unwinding. @@ -1493,8 +1400,7 @@ class IDacDbiInterface // The callee stack parameter size is constant throughout a method. // - virtual - ULONG32 GetStackParameterSize(CORDB_ADDRESS controlPC) = 0; + virtual HRESULT GetStackParameterSize(CORDB_ADDRESS controlPC, OUT ULONG32 * pRetVal) = 0; // // Return the FramePointer of the current frame where the stackwalker is stopped at. @@ -1518,8 +1424,7 @@ class IDacDbiInterface // The FramePointer of an explicit frame is just the stack address of the explicit frame. // - virtual - FramePointer GetFramePointer(StackWalkHandle pSFIHandle) = 0; + virtual HRESULT GetFramePointer(StackWalkHandle pSFIHandle, OUT FramePointer * pRetVal) = 0; // // Check whether the specified CONTEXT is the CONTEXT of the leaf frame. This function doesn't care @@ -1537,9 +1442,7 @@ class IDacDbiInterface // This will be deprecated in V3. // - virtual - BOOL IsLeafFrame(VMPTR_Thread vmThread, - const DT_CONTEXT * pContext) = 0; + virtual HRESULT IsLeafFrame(VMPTR_Thread vmThread, const DT_CONTEXT * pContext, OUT BOOL * pResult) = 0; // Get the context for a particular thread of the target process. // Arguments: @@ -1547,8 +1450,7 @@ class IDacDbiInterface // output: pContextBuffer - the address of the CONTEXT to be initialized. // The memory for this belongs to the caller. It must not be NULL. // Note: throws - virtual - void GetContext(VMPTR_Thread vmThread, DT_CONTEXT * pContextBuffer) = 0; + virtual HRESULT GetContext(VMPTR_Thread vmThread, DT_CONTEXT * pContextBuffer) = 0; // // This is a simple helper function to convert a CONTEXT to a DebuggerREGDISPLAY. We need to do this @@ -1563,10 +1465,7 @@ class IDacDbiInterface // unwinding. // - virtual - void ConvertContextToDebuggerRegDisplay(const DT_CONTEXT * pInContext, - DebuggerREGDISPLAY * pOutDRD, - BOOL fActive) = 0; + virtual HRESULT ConvertContextToDebuggerRegDisplay(const DT_CONTEXT * pInContext, DebuggerREGDISPLAY * pOutDRD, BOOL fActive) = 0; typedef enum { @@ -1588,8 +1487,7 @@ class IDacDbiInterface // Return kLCGMethod if the method is an LCG method. // - virtual - DynamicMethodType IsDiagnosticsHiddenOrLCGMethod(VMPTR_MethodDesc vmMethodDesc) = 0; + virtual HRESULT IsDiagnosticsHiddenOrLCGMethod(VMPTR_MethodDesc vmMethodDesc, OUT DynamicMethodType * pRetVal) = 0; // // Return a TargetBuffer for the raw vararg signature. @@ -1618,9 +1516,7 @@ class IDacDbiInterface // in mscordbi.dll. // - virtual - TargetBuffer GetVarArgSig(CORDB_ADDRESS VASigCookieAddr, - OUT CORDB_ADDRESS * pArgBase) = 0; + virtual HRESULT GetVarArgSig(CORDB_ADDRESS VASigCookieAddr, OUT CORDB_ADDRESS * pArgBase, OUT TargetBuffer * pRetVal) = 0; // // Indicates if the specified type requires 8-byte alignment. @@ -1632,8 +1528,7 @@ class IDacDbiInterface // TRUE if the type requires 8-byte alignment. // - virtual - BOOL RequiresAlign8(VMPTR_TypeHandle thExact) = 0; + virtual HRESULT RequiresAlign8(VMPTR_TypeHandle thExact, OUT BOOL * pResult) = 0; // // Resolve the raw generics token to the real generics type token. The resolution is based on the @@ -1662,9 +1557,7 @@ class IDacDbiInterface // However, we don't want the RS to know all this logic. // - virtual - GENERICS_TYPE_TOKEN ResolveExactGenericArgsToken(DWORD dwExactGenericArgsTokenIndex, - GENERICS_TYPE_TOKEN rawToken) = 0; + virtual HRESULT ResolveExactGenericArgsToken(DWORD dwExactGenericArgsTokenIndex, GENERICS_TYPE_TOKEN rawToken, OUT GENERICS_TYPE_TOKEN * pRetVal) = 0; //----------------------------------------------------------------------------- // Functions to get information about code objects @@ -1681,11 +1574,7 @@ class IDacDbiInterface // Output (required): // codeInfo - start address and size of the IL // pLocalSigToken - signature token for the method - virtual - void GetILCodeAndSig(VMPTR_DomainAssembly vmDomainAssembly, - mdToken functionToken, - OUT TargetBuffer * pCodeInfo, - OUT mdToken * pLocalSigToken) = 0; + virtual HRESULT GetILCodeAndSig(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, OUT TargetBuffer * pCodeInfo, OUT mdToken * pLocalSigToken) = 0; // Gets information about a native code blob: // it's method desc, whether it's an instantiated generic, its EnC version number @@ -1701,10 +1590,7 @@ class IDacDbiInterface // is unavailable for any reason, the output parameter will also be // invalid (i.e., pCodeInfo->IsValid is false). - virtual - void GetNativeCodeInfo(VMPTR_DomainAssembly vmDomainAssembly, - mdToken functionToken, - OUT NativeCodeFunctionData * pCodeInfo) = 0; + virtual HRESULT GetNativeCodeInfo(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, OUT NativeCodeFunctionData * pCodeInfo) = 0; // Gets information about a native code blob: // it's method desc, whether it's an instantiated generic, its EnC version number @@ -1722,11 +1608,7 @@ class IDacDbiInterface // pVmModule - module containing metadata for the method // pFunctionToken - metadata token for the function - virtual - void GetNativeCodeInfoForAddr(CORDB_ADDRESS codeAddress, - NativeCodeFunctionData * pCodeInfo, - VMPTR_Module * pVmModule, - mdToken * pFunctionToken) = 0; + virtual HRESULT GetNativeCodeInfoForAddr(CORDB_ADDRESS codeAddress, NativeCodeFunctionData * pCodeInfo, VMPTR_Module * pVmModule, mdToken * pFunctionToken) = 0; //----------------------------------------------------------------------------- // Functions to get information about types @@ -1740,8 +1622,7 @@ class IDacDbiInterface // Return: // TRUE iff the type is a ValueType - virtual - BOOL IsValueType (VMPTR_TypeHandle th) = 0; + virtual HRESULT IsValueType(VMPTR_TypeHandle th, OUT BOOL * pResult) = 0; // Determine if a type has generic parameters // @@ -1751,8 +1632,7 @@ class IDacDbiInterface // Return: // TRUE iff the type has generic parameters - virtual - BOOL HasTypeParams (VMPTR_TypeHandle th) = 0; + virtual HRESULT HasTypeParams(VMPTR_TypeHandle th, OUT BOOL * pResult) = 0; // Get type information for a class // @@ -1763,10 +1643,7 @@ class IDacDbiInterface // pData - structure containing information about the class and its // fields - virtual - void GetClassInfo (VMPTR_AppDomain vmAppDomain, - VMPTR_TypeHandle thExact, - ClassInfo * pData) = 0; + virtual HRESULT GetClassInfo(VMPTR_AppDomain vmAppDomain, VMPTR_TypeHandle thExact, ClassInfo * pData) = 0; // get field information and object size for an instantiated generic // @@ -1779,12 +1656,7 @@ class IDacDbiInterface // contents. Allocated and initialized by this function. // pObjectSize - size of the instantiated object // - virtual - void GetInstantiationFieldInfo (VMPTR_DomainAssembly vmDomainAssembly, - VMPTR_TypeHandle vmThExact, - VMPTR_TypeHandle vmThApprox, - OUT DacDbiArrayList * pFieldList, - OUT SIZE_T * pObjectSize) = 0; + virtual HRESULT GetInstantiationFieldInfo(VMPTR_DomainAssembly vmDomainAssembly, VMPTR_TypeHandle vmThExact, VMPTR_TypeHandle vmThApprox, OUT DacDbiArrayList * pFieldList, OUT SIZE_T * pObjectSize) = 0; // use a type handle to get the information needed to create the corresponding RS CordbType instance // @@ -1795,24 +1667,12 @@ class IDacDbiInterface // vmTypeHandle - type handle for the type // output: pTypeInfo - holds information needed to build the corresponding CordbType // - virtual - void TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, - VMPTR_AppDomain vmAppDomain, - VMPTR_TypeHandle vmTypeHandle, - DebuggerIPCE_ExpandedTypeData * pTypeInfo) = 0; + virtual HRESULT TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, VMPTR_AppDomain vmAppDomain, VMPTR_TypeHandle vmTypeHandle, DebuggerIPCE_ExpandedTypeData * pTypeInfo) = 0; - virtual - void GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed, - VMPTR_AppDomain vmAppDomain, - CORDB_ADDRESS addr, - OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo) = 0; + virtual HRESULT GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed, VMPTR_AppDomain vmAppDomain, CORDB_ADDRESS addr, OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo) = 0; - virtual - void GetObjectExpandedTypeInfoFromID(AreValueTypesBoxed boxed, - VMPTR_AppDomain vmAppDomain, - COR_TYPEID id, - OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo) = 0; + virtual HRESULT GetObjectExpandedTypeInfoFromID(AreValueTypesBoxed boxed, VMPTR_AppDomain vmAppDomain, COR_TYPEID id, OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo) = 0; // Get type handle for a TypeDef token, if one exists. For generics this returns the open type. @@ -1826,9 +1686,7 @@ class IDacDbiInterface // // Return value: the type handle if it exists or throws CORDBG_E_CLASS_NOT_LOADED if it isn't loaded // - virtual - VMPTR_TypeHandle GetTypeHandle(VMPTR_Module vmModule, - mdTypeDef metadataToken) = 0; + virtual HRESULT GetTypeHandle(VMPTR_Module vmModule, mdTypeDef metadataToken, OUT VMPTR_TypeHandle * pRetVal) = 0; // Get the approximate type handle for an instantiated type. This may be identical to the exact type handle, // but if we have code sharing for generics, it may differ in that it may have canonical type parameters. @@ -1840,8 +1698,7 @@ class IDacDbiInterface // and the number of entries in the list. Allocated and initialized by the caller. // Return value: the approximate type handle // - virtual - VMPTR_TypeHandle GetApproxTypeHandle(TypeInfoList * pTypeData) = 0; + virtual HRESULT GetApproxTypeHandle(TypeInfoList * pTypeData, OUT VMPTR_TypeHandle * pRetVal) = 0; // Get the exact type handle from type data. // Arguments: @@ -1881,12 +1738,7 @@ class IDacDbiInterface // The caller is responsible for releasing it. // - virtual - void GetMethodDescParams(VMPTR_AppDomain vmAppDomain, - VMPTR_MethodDesc vmMethodDesc, - GENERICS_TYPE_TOKEN genericsToken, - OUT UINT32 * pcGenericClassTypeParams, - OUT TypeParamsList * pGenericTypeParams) = 0; + virtual HRESULT GetMethodDescParams(VMPTR_AppDomain vmAppDomain, VMPTR_MethodDesc vmMethodDesc, GENERICS_TYPE_TOKEN genericsToken, OUT UINT32 * pcGenericClassTypeParams, OUT TypeParamsList * pGenericTypeParams) = 0; // Get the target field address of a thread local static. // Arguments: @@ -1901,9 +1753,7 @@ class IDacDbiInterface // This is an inspection only method and can not allocate the static storage. // Field storage is constant once allocated, so this value can be cached. - virtual - CORDB_ADDRESS GetThreadStaticAddress(VMPTR_FieldDesc vmField, - VMPTR_Thread vmRuntimeThread) = 0; + virtual HRESULT GetThreadStaticAddress(VMPTR_FieldDesc vmField, VMPTR_Thread vmRuntimeThread, OUT CORDB_ADDRESS * pRetVal) = 0; // Get the target field address of a collectible types static. // Arguments: @@ -1919,9 +1769,7 @@ class IDacDbiInterface // Field storage is not constant once allocated so this value can not be cached // across a Continue - virtual - CORDB_ADDRESS GetCollectibleTypeStaticAddress(VMPTR_FieldDesc vmField, - VMPTR_AppDomain vmAppDomain) = 0; + virtual HRESULT GetCollectibleTypeStaticAddress(VMPTR_FieldDesc vmField, VMPTR_AppDomain vmAppDomain, OUT CORDB_ADDRESS * pRetVal) = 0; // Get information about a field added with Edit And Continue. // Arguments: @@ -1934,10 +1782,7 @@ class IDacDbiInterface // an indication of the type: whether it's a class or value type // output: pFieldData - information about the EnC added field // pfStatic - flag to indicate whether the field is static - virtual - void GetEnCHangingFieldInfo(const EnCHangingFieldInfo * pEnCFieldInfo, - OUT FieldData * pFieldData, - OUT BOOL * pfStatic) = 0; + virtual HRESULT GetEnCHangingFieldInfo(const EnCHangingFieldInfo * pEnCFieldInfo, OUT FieldData * pFieldData, OUT BOOL * pfStatic) = 0; // GetTypeHandleParams gets the necessary data for a type handle, i.e. its @@ -1954,10 +1799,7 @@ class IDacDbiInterface // heap in this function. // This will not fail except for OOM - virtual - void GetTypeHandleParams(VMPTR_AppDomain vmAppDomain, - VMPTR_TypeHandle vmTypeHandle, - OUT TypeParamsList * pParams) = 0; + virtual HRESULT GetTypeHandleParams(VMPTR_AppDomain vmAppDomain, VMPTR_TypeHandle vmTypeHandle, OUT TypeParamsList * pParams) = 0; // GetSimpleType // gets the metadata token and domain file corresponding to a simple type @@ -1973,60 +1815,35 @@ class IDacDbiInterface // If the type has been loaded, vmDomainAssembly will be non-null unless the target is somehow corrupted. // In that case, we will throw CORDBG_E_TARGET_INCONSISTENT. - virtual - void GetSimpleType(VMPTR_AppDomain vmAppDomain, - CorElementType simpleType, - OUT mdTypeDef * pMetadataToken, - OUT VMPTR_Module * pVmModule, - OUT VMPTR_DomainAssembly * pVmDomainAssembly) = 0; + virtual HRESULT GetSimpleType(VMPTR_AppDomain vmAppDomain, CorElementType simpleType, OUT mdTypeDef * pMetadataToken, OUT VMPTR_Module * pVmModule, OUT VMPTR_DomainAssembly * pVmDomainAssembly) = 0; // for the specified object returns TRUE if the object derives from System.Exception - virtual - BOOL IsExceptionObject(VMPTR_Object vmObject) = 0; + virtual HRESULT IsExceptionObject(VMPTR_Object vmObject, OUT BOOL * pResult) = 0; // gets the list of raw stack frames for the specified exception object - virtual - void GetStackFramesFromException(VMPTR_Object vmObject, DacDbiArrayList& dacStackFrames) = 0; + virtual HRESULT GetStackFramesFromException(VMPTR_Object vmObject, DacDbiArrayList& dacStackFrames) = 0; // Returns true if the argument is a runtime callable wrapper - virtual - BOOL IsRcw(VMPTR_Object vmObject) = 0; + virtual HRESULT IsRcw(VMPTR_Object vmObject, OUT BOOL * pResult) = 0; // retrieves the list of COM interfaces implemented by vmObject, as it is known at // the time of the call (the list may change as new interface types become available // in the runtime) - virtual - void GetRcwCachedInterfaceTypes( - VMPTR_Object vmObject, - VMPTR_AppDomain vmAppDomain, - BOOL bIInspectableOnly, - OUT DacDbiArrayList * pDacInterfaces) = 0; + virtual HRESULT GetRcwCachedInterfaceTypes(VMPTR_Object vmObject, VMPTR_AppDomain vmAppDomain, BOOL bIInspectableOnly, OUT DacDbiArrayList * pDacInterfaces) = 0; // retrieves the list of interfaces pointers implemented by vmObject, as it is known at // the time of the call (the list may change as new interface types become available // in the runtime) - virtual - void GetRcwCachedInterfacePointers( - VMPTR_Object vmObject, - BOOL bIInspectableOnly, - OUT DacDbiArrayList * pDacItfPtrs) = 0; + virtual HRESULT GetRcwCachedInterfacePointers(VMPTR_Object vmObject, BOOL bIInspectableOnly, OUT DacDbiArrayList * pDacItfPtrs) = 0; // retrieves a list of interface types corresponding to the passed in // list of IIDs. the interface types are retrieved from an app domain // IID / Type cache, that is updated as new types are loaded. will // have NULL entries corresponding to unknown IIDs in "iids" - virtual - void GetCachedWinRTTypesForIIDs( - VMPTR_AppDomain vmAppDomain, - DacDbiArrayList & iids, - OUT DacDbiArrayList * pTypes) = 0; + virtual HRESULT GetCachedWinRTTypesForIIDs(VMPTR_AppDomain vmAppDomain, DacDbiArrayList & iids, OUT DacDbiArrayList * pTypes) = 0; // retrieves the whole app domain cache of IID / Type mappings. - virtual - void GetCachedWinRTTypes( - VMPTR_AppDomain vmAppDomain, - OUT DacDbiArrayList * piids, - OUT DacDbiArrayList * pTypes) = 0; + virtual HRESULT GetCachedWinRTTypes(VMPTR_AppDomain vmAppDomain, OUT DacDbiArrayList * piids, OUT DacDbiArrayList * pTypes) = 0; // ---------------------------------------------------------------------------- @@ -2040,10 +1857,7 @@ class IDacDbiInterface // vmAppDomain - AppDomain for the type of the object referenced // output: pObjectData - information about the object referenced by pTypedByRef // Note: Throws - virtual - void GetTypedByRefInfo(CORDB_ADDRESS pTypedByRef, - VMPTR_AppDomain vmAppDomain, - DebuggerIPCE_ObjectData * pObjectData) = 0; + virtual HRESULT GetTypedByRefInfo(CORDB_ADDRESS pTypedByRef, VMPTR_AppDomain vmAppDomain, DebuggerIPCE_ObjectData * pObjectData) = 0; // Get the string length and offset to string base for a string object // Arguments: @@ -2051,8 +1865,7 @@ class IDacDbiInterface // output: pObjectData - fills in the string fields stringInfo.offsetToStringBase and // stringInfo.length // Note: throws - virtual - void GetStringData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData) = 0; + virtual HRESULT GetStringData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData) = 0; // Get information for an array type referent of an objRef, including rank, upper and lower bounds, // element size and type, and the number of elements. @@ -2066,8 +1879,7 @@ class IDacDbiInterface // arrayInfo.rank, // arrayInfo.elementSize, // Note: throws - virtual - void GetArrayData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData) = 0; + virtual HRESULT GetArrayData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData) = 0; // Get information about an object for which we have a reference, including the object size and // type information. @@ -2078,11 +1890,7 @@ class IDacDbiInterface // vmAppDomain - the appdomain to which the object belong // output: pObjectData - fills in the size and type information fields // Note: throws - virtual - void GetBasicObjectInfo(CORDB_ADDRESS objectAddress, - CorElementType type, - VMPTR_AppDomain vmAppDomain, - DebuggerIPCE_ObjectData * pObjectData) = 0; + virtual HRESULT GetBasicObjectInfo(CORDB_ADDRESS objectAddress, CorElementType type, VMPTR_AppDomain vmAppDomain, DebuggerIPCE_ObjectData * pObjectData) = 0; // -------------------------------------------------------------------------------------------- #ifdef TEST_DATA_CONSISTENCY @@ -2097,8 +1905,7 @@ class IDacDbiInterface // Notes: // Throws // For this code to run, the environment variable TestDataConsistency must be set to 1. - virtual - void TestCrst(VMPTR_Crst vmCrst) = 0; + virtual HRESULT TestCrst(VMPTR_Crst vmCrst) = 0; // Determine whether a crst is held by the left side. When the DAC is executing VM code that takes a // lock, we want to know whether the LS already holds that lock. If it does, we will assume the locked @@ -2112,8 +1919,7 @@ class IDacDbiInterface // Throws // For this code to run, the environment variable TestDataConsistency must be set to 1. - virtual - void TestRWLock(VMPTR_SimpleRWLock vmRWLock) = 0; + virtual HRESULT TestRWLock(VMPTR_SimpleRWLock vmRWLock) = 0; #endif // -------------------------------------------------------------------------------------------- // Get the address of the Debugger control block on the helper thread. The debugger control block @@ -2122,8 +1928,7 @@ class IDacDbiInterface // Arguments: none // Return Value: The remote address of the Debugger control block allocated on the helper thread // if it has been successfully allocated or NULL otherwise. - virtual - CORDB_ADDRESS GetDebuggerControlBlockAddress() = 0; + virtual HRESULT GetDebuggerControlBlockAddress(OUT CORDB_ADDRESS * pRetVal) = 0; // Creates a VMPTR of an Object. The Object is found by dereferencing ptr // as though it is a target address to an OBJECTREF. This is similar to @@ -2140,8 +1945,7 @@ class IDacDbiInterface // This function will throw if given a NULL or otherwise invalid pointer, // but if given a valid address to an invalid pointer, it will produce // a VMPTR_Object which points to invalid memory. - virtual - VMPTR_Object GetObjectFromRefPtr(CORDB_ADDRESS ptr) = 0; + virtual HRESULT GetObjectFromRefPtr(CORDB_ADDRESS ptr, OUT VMPTR_Object * pRetVal) = 0; // Creates a VMPTR of an Object. The Object is assumed to be at the target // address supplied by ptr @@ -2156,8 +1960,7 @@ class IDacDbiInterface // The VMPTR this produces can be deconstructed by GetObjectContents. // This will produce a VMPTR_Object regardless of whether the pointer is // valid or not. - virtual - VMPTR_Object GetObject(CORDB_ADDRESS ptr) = 0; + virtual HRESULT GetObject(CORDB_ADDRESS ptr, OUT VMPTR_Object * pRetVal) = 0; // Sets state in the native binder. // @@ -2221,8 +2024,7 @@ class IDacDbiInterface // This will produce a VMPTR_OBJECTHANDLE regardless of whether handle is // valid. // Ideally we'd be using only strongly-typed variables on the RS, and then this would be unnecessary - virtual - VMPTR_OBJECTHANDLE GetVmObjectHandle(CORDB_ADDRESS handleAddress) = 0; + virtual HRESULT GetVmObjectHandle(CORDB_ADDRESS handleAddress, OUT VMPTR_OBJECTHANDLE * pRetVal) = 0; // Validate that the VMPTR_OBJECTHANDLE refers to a legitimate managed object // @@ -2232,8 +2034,7 @@ class IDacDbiInterface // Return value: // TRUE if the object appears to be valid (its a heuristic), FALSE if it definately is not valid // - virtual - BOOL IsVmObjectHandleValid(VMPTR_OBJECTHANDLE vmHandle) = 0; + virtual HRESULT IsVmObjectHandleValid(VMPTR_OBJECTHANDLE vmHandle, OUT BOOL * pResult) = 0; // indicates if the specified module is a WinRT module // @@ -2256,8 +2057,7 @@ class IDacDbiInterface // The app domain id of the object of interest // // This may throw if the object handle is corrupt (it doesn't refer to a managed object) - virtual - ULONG GetAppDomainIdFromVmObjectHandle(VMPTR_OBJECTHANDLE vmHandle) = 0; + virtual HRESULT GetAppDomainIdFromVmObjectHandle(VMPTR_OBJECTHANDLE vmHandle, OUT ULONG * pRetVal) = 0; // Get the target address from a VMPTR_OBJECTHANDLE, i.e., the handle address @@ -2265,8 +2065,7 @@ class IDacDbiInterface // vmHandle - (input) the VMPTR_OBJECTHANDLE from which we need the target address // Return value: the target address from the VMPTR_OBJECTHANDLE // - virtual - CORDB_ADDRESS GetHandleAddressFromVmHandle(VMPTR_OBJECTHANDLE vmHandle) = 0; + virtual HRESULT GetHandleAddressFromVmHandle(VMPTR_OBJECTHANDLE vmHandle, OUT CORDB_ADDRESS * pRetVal) = 0; // Given a VMPTR to an Object return the target address // @@ -2281,8 +2080,7 @@ class IDacDbiInterface // providing the address stored in the returned TargetBuffer. This has // undefined behavior for invalid VMPTR_Objects. - virtual - TargetBuffer GetObjectContents(VMPTR_Object obj) = 0; + virtual HRESULT GetObjectContents(VMPTR_Object obj, OUT TargetBuffer * pRetVal) = 0; // // Returns the thread which owns the monitor lock on an object and the acquisition @@ -2298,8 +2096,7 @@ class IDacDbiInterface // pAcquisitionCount - the number of times the lock would need to be released in // order for it to be unowned // - virtual - MonitorLockInfo GetThreadOwningMonitorLock(VMPTR_Object vmObject) = 0; + virtual HRESULT GetThreadOwningMonitorLock(VMPTR_Object vmObject, OUT MonitorLockInfo * pRetVal) = 0; // // Enumerate all threads waiting on the monitor event for an object @@ -2313,10 +2110,7 @@ class IDacDbiInterface // Returns on success. Throws on error. // // - virtual - void EnumerateMonitorEventWaitList(VMPTR_Object vmObject, - FP_THREAD_ENUMERATION_CALLBACK fpCallback, - CALLBACK_DATA pUserData) = 0; + virtual HRESULT EnumerateMonitorEventWaitList(VMPTR_Object vmObject, FP_THREAD_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData) = 0; // // Returns the managed debugging flags for the process (a combination @@ -2325,17 +2119,11 @@ class IDacDbiInterface // event (if one exists) is caused by a Debugger.Launch(). This is // important b/c Debugger.Launch calls should *NOT* cause the debugger // to terminate the process when the attach is canceled. - virtual - CLR_DEBUGGING_PROCESS_FLAGS GetAttachStateFlags() = 0; + virtual HRESULT GetAttachStateFlags(OUT CLR_DEBUGGING_PROCESS_FLAGS * pRetVal) = 0; - virtual - bool GetMetaDataFileInfoFromPEFile(VMPTR_PEAssembly vmPEAssembly, - DWORD & dwTimeStamp, - DWORD & dwImageSize, - IStringHolder* pStrFilename) = 0; + virtual HRESULT GetMetaDataFileInfoFromPEFile(VMPTR_PEAssembly vmPEAssembly, DWORD & dwTimeStamp, DWORD & dwImageSize, IStringHolder* pStrFilename, OUT bool * pResult) = 0; - virtual - bool IsThreadSuspendedOrHijacked(VMPTR_Thread vmThread) = 0; + virtual HRESULT IsThreadSuspendedOrHijacked(VMPTR_Thread vmThread, OUT bool * pResult) = 0; typedef void* * HeapWalkHandle; @@ -2343,8 +2131,7 @@ class IDacDbiInterface // Returns true if it is safe to walk the heap. If this function returns false, // you could still create a heap walk and attempt to walk it, but there's no // telling how much of the heap will be available. - virtual - bool AreGCStructuresValid() = 0; + virtual HRESULT AreGCStructuresValid(OUT bool * pResult) = 0; // Creates a HeapWalkHandle which can be used to walk the managed heap with the // WalkHeap function. Note if this function completes successfully you will need @@ -2361,8 +2148,7 @@ class IDacDbiInterface // Deletes the give HeapWalkHandle. Note you must call this function if // CreateHeapWalk returns success. - virtual - void DeleteHeapWalk(HeapWalkHandle handle) = 0; + virtual HRESULT DeleteHeapWalk(HeapWalkHandle handle) = 0; // Walks the heap using the given heap walk handle, enumerating objects // on the managed heap. Note that walking the heap requires that the GC @@ -2395,13 +2181,9 @@ class IDacDbiInterface virtual HRESULT GetHeapSegments(OUT DacDbiArrayList * pSegments) = 0; - virtual - bool IsValidObject(CORDB_ADDRESS obj) = 0; + virtual HRESULT IsValidObject(CORDB_ADDRESS obj, OUT bool * pResult) = 0; - virtual - bool GetAppDomainForObject(CORDB_ADDRESS obj, OUT VMPTR_AppDomain * pApp, - OUT VMPTR_Module * pModule, - OUT VMPTR_DomainAssembly * pDomainAssembly) = 0; + virtual HRESULT GetAppDomainForObject(CORDB_ADDRESS obj, OUT VMPTR_AppDomain * pApp, OUT VMPTR_Module * pModule, OUT VMPTR_DomainAssembly * pDomainAssembly, OUT bool * pResult) = 0; // Reference Walking. @@ -2424,8 +2206,7 @@ class IDacDbiInterface // handle - in - the handle of the reference walk to delete // Excecptions: // Does not throw, but does not catch exceptions either. - virtual - void DeleteRefWalk(RefWalkHandle handle) = 0; + virtual HRESULT DeleteRefWalk(RefWalkHandle handle) = 0; // Enumerates GC references in the process based on the parameters passed to CreateRefWalk. // Parameters: @@ -2451,8 +2232,7 @@ class IDacDbiInterface virtual HRESULT GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT * pLayout) = 0; - virtual - void GetGCHeapInformation(OUT COR_HEAPINFO * pHeapInfo) = 0; + virtual HRESULT GetGCHeapInformation(OUT COR_HEAPINFO * pHeapInfo) = 0; // If a PEAssembly has an RW capable IMDInternalImport, this returns the address of the MDInternalRW // object which implements it. @@ -2682,8 +2462,7 @@ class IDacDbiInterface // Arguments: // vmObject - pointer to runtime object to query for. // - virtual - BOOL IsDelegate(VMPTR_Object vmObject) = 0; + virtual HRESULT IsDelegate(VMPTR_Object vmObject, OUT BOOL * pResult) = 0; // Returns the delegate type virtual @@ -2709,8 +2488,7 @@ class IDacDbiInterface virtual HRESULT IsModuleMapped(VMPTR_Module pModule, OUT BOOL *isModuleMapped) = 0; - virtual - bool MetadataUpdatesApplied() = 0; + virtual HRESULT MetadataUpdatesApplied(OUT bool * pResult) = 0; virtual HRESULT GetDomainAssemblyFromModule(VMPTR_Module vmModule, OUT VMPTR_DomainAssembly *pVmDomainAssembly) = 0; @@ -2722,12 +2500,7 @@ class IDacDbiInterface OUT CORDB_ADDRESS* pNextContinuation, OUT UINT32* pState) = 0; - virtual - void GetAsyncLocals( - VMPTR_MethodDesc vmMethod, - CORDB_ADDRESS codeAddr, - UINT32 state, - OUT DacDbiArrayList* pAsyncLocals) = 0; + virtual HRESULT GetAsyncLocals(VMPTR_MethodDesc vmMethod, CORDB_ADDRESS codeAddr, UINT32 state, OUT DacDbiArrayList* pAsyncLocals) = 0; virtual HRESULT GetGenericArgTokenIndex( From 2b797975784627dad3b3e08173240f6a0b2d487b Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Tue, 24 Feb 2026 08:52:37 -0500 Subject: [PATCH 2/3] Update DacDbiInterfaceImpl declarations to match HRESULT interface Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/coreclr/debug/daccess/dacdbiimpl.h | 351 +++++++++---------------- 1 file changed, 124 insertions(+), 227 deletions(-) diff --git a/src/coreclr/debug/daccess/dacdbiimpl.h b/src/coreclr/debug/daccess/dacdbiimpl.h index 99de4ffd483414..43524cd22377aa 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.h +++ b/src/coreclr/debug/daccess/dacdbiimpl.h @@ -65,11 +65,11 @@ class DacDbiInterfaceImpl : HRESULT FlushCache(); // enable or disable DAC target consistency checks - void DacSetTargetConsistencyChecks(bool fEnableAsserts); + HRESULT DacSetTargetConsistencyChecks(bool fEnableAsserts); // Destroy the interface object. The client should call this when it's done // with the IDacDbiInterface to free up any resources. - void Destroy(); + HRESULT Destroy(); IAllocator * GetAllocator() { @@ -78,27 +78,25 @@ class DacDbiInterfaceImpl : // Is Left-side started up? - BOOL IsLeftSideInitialized(); + HRESULT IsLeftSideInitialized(OUT BOOL * pResult); // Get an LS Appdomain via an AppDomain unique ID. // Fails if the AD is not found or if the ID is invalid. - VMPTR_AppDomain GetAppDomainFromId(ULONG appdomainId); + HRESULT GetAppDomainFromId(ULONG appdomainId, OUT VMPTR_AppDomain * pRetVal); // Get the AppDomain ID for an AppDomain. - ULONG GetAppDomainId(VMPTR_AppDomain vmAppDomain); + HRESULT GetAppDomainId(VMPTR_AppDomain vmAppDomain, OUT ULONG * pRetVal); // Get the managed AppDomain object for an AppDomain. - VMPTR_OBJECTHANDLE GetAppDomainObject(VMPTR_AppDomain vmAppDomain); + HRESULT GetAppDomainObject(VMPTR_AppDomain vmAppDomain, OUT VMPTR_OBJECTHANDLE * pRetVal); // Get the full AD friendly name for the appdomain. - void GetAppDomainFullName( - VMPTR_AppDomain vmAppDomain, - IStringHolder * pStrName); + HRESULT GetAppDomainFullName(VMPTR_AppDomain vmAppDomain, IStringHolder * pStrName); // Get the values of the JIT Optimization and EnC flags. - void GetCompilerFlags (VMPTR_DomainAssembly vmDomainAssembly, - BOOL * pfAllowJITOpts, - BOOL * pfEnableEnC); + HRESULT GetCompilerFlags(VMPTR_DomainAssembly vmDomainAssembly, + OUT BOOL * pfAllowJITOpts, + OUT BOOL * pfEnableEnC); // Helper function for SetCompilerFlags to set EnC status bool CanSetEnCBits(Module * pModule); @@ -110,18 +108,14 @@ class DacDbiInterfaceImpl : // Initialize the native/IL sequence points and native var info for a function. - void GetNativeCodeSequencePointsAndVarInfo(VMPTR_MethodDesc vmMethodDesc, - CORDB_ADDRESS startAddr, - BOOL fCodeAvailable, - NativeVarData * pNativeVarData, - SequencePoints * pSequencePoints); + HRESULT GetNativeCodeSequencePointsAndVarInfo(VMPTR_MethodDesc vmMethodDesc, CORDB_ADDRESS startAddress, BOOL fCodeAvailable, OUT NativeVarData * pNativeVarData, OUT SequencePoints * pSequencePoints); - bool IsThreadSuspendedOrHijacked(VMPTR_Thread vmThread); + HRESULT IsThreadSuspendedOrHijacked(VMPTR_Thread vmThread, OUT bool * pResult); - bool AreGCStructuresValid(); + HRESULT AreGCStructuresValid(OUT bool * pResult); HRESULT CreateHeapWalk(HeapWalkHandle *pHandle); - void DeleteHeapWalk(HeapWalkHandle handle); + HRESULT DeleteHeapWalk(HeapWalkHandle handle); HRESULT WalkHeap(HeapWalkHandle handle, ULONG count, @@ -131,14 +125,14 @@ class DacDbiInterfaceImpl : HRESULT GetHeapSegments(OUT DacDbiArrayList *pSegments); - bool IsValidObject(CORDB_ADDRESS obj); + HRESULT IsValidObject(CORDB_ADDRESS obj, OUT bool * pResult); - bool GetAppDomainForObject(CORDB_ADDRESS obj, OUT VMPTR_AppDomain * pApp, OUT VMPTR_Module *pModule, OUT VMPTR_DomainAssembly *mod); + HRESULT GetAppDomainForObject(CORDB_ADDRESS obj, OUT VMPTR_AppDomain * pApp, OUT VMPTR_Module * pModule, OUT VMPTR_DomainAssembly * pDomainAssembly, OUT bool * pResult); HRESULT CreateRefWalk(RefWalkHandle * pHandle, BOOL walkStacks, BOOL walkFQ, UINT32 handleWalkMask); - void DeleteRefWalk(RefWalkHandle handle); + HRESULT DeleteRefWalk(RefWalkHandle handle); HRESULT WalkRefs(RefWalkHandle handle, ULONG count, OUT DacGcReference * objects, OUT ULONG *pFetched); HRESULT GetTypeID(CORDB_ADDRESS obj, COR_TYPEID *pID); @@ -148,7 +142,7 @@ class DacDbiInterfaceImpl : HRESULT GetObjectFields(COR_TYPEID id, ULONG32 celt, COR_FIELD *layout, ULONG32 *pceltFetched); HRESULT GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT *pLayout); HRESULT GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT *pLayout); - void GetGCHeapInformation(COR_HEAPINFO * pHeapInfo); + HRESULT GetGCHeapInformation(OUT COR_HEAPINFO * pHeapInfo); HRESULT GetPEFileMDInternalRW(VMPTR_PEAssembly vmPEAssembly, OUT TADDR* pAddrMDInternalRW); HRESULT GetReJitInfo(VMPTR_Module vmModule, mdMethodDef methodTk, OUT VMPTR_ReJitInfo* pReJitInfo); #ifdef FEATURE_CODE_VERSIONING @@ -169,10 +163,7 @@ class DacDbiInterfaceImpl : OUT PCODE *pDiagnosticIP, OUT CORDB_ADDRESS *pNextContinuation, OUT UINT32 *pState); - void GetAsyncLocals(VMPTR_MethodDesc vmMethod, - CORDB_ADDRESS codeAddr, - UINT32 state, - DacDbiArrayList * pAsyncLocals); + HRESULT GetAsyncLocals(VMPTR_MethodDesc vmMethod, CORDB_ADDRESS codeAddr, UINT32 state, OUT DacDbiArrayList* pAsyncLocals); HRESULT GetGenericArgTokenIndex(VMPTR_MethodDesc vmMethod, OUT UINT32* pIndex); private: @@ -224,10 +215,7 @@ class DacDbiInterfaceImpl : // a module and a token. The info will come from a MethodDesc, if // one exists or from metadata. // - void GetILCodeAndSig(VMPTR_DomainAssembly vmDomainAssembly, - mdToken functionToken, - TargetBuffer * pCodeInfo, - mdToken * pLocalSigToken); + HRESULT GetILCodeAndSig(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, OUT TargetBuffer * pCodeInfo, OUT mdToken * pLocalSigToken); // Gets the following information about the native code blob for a function, if the native // code is available: @@ -235,9 +223,7 @@ class DacDbiInterfaceImpl : // whether it's an instantiated generic // its EnC version number // hot and cold region information. - void GetNativeCodeInfo(VMPTR_DomainAssembly vmDomainAssembly, - mdToken functionToken, - NativeCodeFunctionData * pCodeInfo); + HRESULT GetNativeCodeInfo(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, OUT NativeCodeFunctionData * pCodeInfo); // Gets the following information about the native code blob for a function // its method desc @@ -246,10 +232,7 @@ class DacDbiInterfaceImpl : // hot and cold region information // its module // its metadata token. - void GetNativeCodeInfoForAddr(CORDB_ADDRESS codeAddress, - NativeCodeFunctionData * pCodeInfo, - VMPTR_Module * pVmModule, - mdToken * pFunctionToken); + HRESULT GetNativeCodeInfoForAddr(CORDB_ADDRESS codeAddress, NativeCodeFunctionData * pCodeInfo, VMPTR_Module * pVmModule, mdToken * pFunctionToken); private: // Get start addresses and sizes for hot and cold regions for a native code blob @@ -258,51 +241,35 @@ class DacDbiInterfaceImpl : public: // Determine if a type is a ValueType - BOOL IsValueType (VMPTR_TypeHandle th); + HRESULT IsValueType(VMPTR_TypeHandle th, OUT BOOL * pResult); // Determine if a type has generic parameters - BOOL HasTypeParams (VMPTR_TypeHandle th); + HRESULT HasTypeParams(VMPTR_TypeHandle th, OUT BOOL * pResult); // Get type information for a class - void GetClassInfo (VMPTR_AppDomain vmAppDomain, - VMPTR_TypeHandle thExact, - ClassInfo * pData); + HRESULT GetClassInfo(VMPTR_AppDomain vmAppDomain, VMPTR_TypeHandle thExact, ClassInfo * pData); // get field information and object size for an instantiated generic type - void GetInstantiationFieldInfo (VMPTR_DomainAssembly vmDomainAssembly, - VMPTR_TypeHandle vmThExact, - VMPTR_TypeHandle vmThApprox, - DacDbiArrayList * pFieldList, - SIZE_T * pObjectSize); + HRESULT GetInstantiationFieldInfo(VMPTR_DomainAssembly vmDomainAssembly, VMPTR_TypeHandle vmThExact, VMPTR_TypeHandle vmThApprox, OUT DacDbiArrayList * pFieldList, OUT SIZE_T * pObjectSize); - void GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed, - VMPTR_AppDomain vmAppDomain, - CORDB_ADDRESS addr, - DebuggerIPCE_ExpandedTypeData *pTypeInfo); + HRESULT GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed, VMPTR_AppDomain vmAppDomain, CORDB_ADDRESS addr, OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo); - void GetObjectExpandedTypeInfoFromID(AreValueTypesBoxed boxed, - VMPTR_AppDomain vmAppDomain, - COR_TYPEID id, - DebuggerIPCE_ExpandedTypeData *pTypeInfo); + HRESULT GetObjectExpandedTypeInfoFromID(AreValueTypesBoxed boxed, VMPTR_AppDomain vmAppDomain, COR_TYPEID id, OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo); // @dbgtodo Microsoft inspection: change DebuggerIPCE_ExpandedTypeData to DacDbiStructures type hierarchy // once ICorDebugType and ICorDebugClass are DACized // use a type handle to get the information needed to create the corresponding RS CordbType instance - void TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, - VMPTR_AppDomain vmAppDomain, - VMPTR_TypeHandle vmTypeHandle, - DebuggerIPCE_ExpandedTypeData * pTypeInfo); + HRESULT TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, VMPTR_AppDomain vmAppDomain, VMPTR_TypeHandle vmTypeHandle, DebuggerIPCE_ExpandedTypeData * pTypeInfo); // Get type handle for a TypeDef token, if one exists. For generics this returns the open type. - VMPTR_TypeHandle GetTypeHandle(VMPTR_Module vmModule, - mdTypeDef metadataToken); + HRESULT GetTypeHandle(VMPTR_Module vmModule, mdTypeDef metadataToken, OUT VMPTR_TypeHandle * pRetVal); // Get the approximate type handle for an instantiated type. This may be identical to the exact type handle, // but if we have code sharing for generics,it may differ in that it may have canonical type parameters. - VMPTR_TypeHandle GetApproxTypeHandle(TypeInfoList * pTypeData); + HRESULT GetApproxTypeHandle(TypeInfoList * pTypeData, OUT VMPTR_TypeHandle * pRetVal); // Get the exact type handle from type data HRESULT GetExactTypeHandle(DebuggerIPCE_ExpandedTypeData * pTypeData, @@ -311,50 +278,36 @@ class DacDbiInterfaceImpl : // Retrieve the generic type params for a given MethodDesc. This function is specifically // for stackwalking because it requires the generic type token on the stack. - void GetMethodDescParams(VMPTR_AppDomain vmAppDomain, - VMPTR_MethodDesc vmMethodDesc, - GENERICS_TYPE_TOKEN genericsToken, - UINT32 * pcGenericClassTypeParams, - TypeParamsList * pGenericTypeParams); + HRESULT GetMethodDescParams(VMPTR_AppDomain vmAppDomain, VMPTR_MethodDesc vmMethodDesc, GENERICS_TYPE_TOKEN genericsToken, OUT UINT32 * pcGenericClassTypeParams, OUT TypeParamsList * pGenericTypeParams); // Get the target field address of a context or thread local static. - CORDB_ADDRESS GetThreadStaticAddress(VMPTR_FieldDesc vmField, - VMPTR_Thread vmRuntimeThread); + HRESULT GetThreadStaticAddress(VMPTR_FieldDesc vmField, VMPTR_Thread vmRuntimeThread, OUT CORDB_ADDRESS * pRetVal); // Get the target field address of a collectible types static. - CORDB_ADDRESS GetCollectibleTypeStaticAddress(VMPTR_FieldDesc vmField, - VMPTR_AppDomain vmAppDomain); + HRESULT GetCollectibleTypeStaticAddress(VMPTR_FieldDesc vmField, VMPTR_AppDomain vmAppDomain, OUT CORDB_ADDRESS * pRetVal); // Get information about a field added with Edit And Continue. - void GetEnCHangingFieldInfo(const EnCHangingFieldInfo * pEnCFieldInfo, - FieldData * pFieldData, - BOOL * pfStatic); + HRESULT GetEnCHangingFieldInfo(const EnCHangingFieldInfo * pEnCFieldInfo, OUT FieldData * pFieldData, OUT BOOL * pfStatic); // GetTypeHandleParams gets the necessary data for a type handle, i.e. its // type parameters, e.g. "String" and "List" from the type handle // for "Dict>", and sends it back to the right side. // This should not fail except for OOM - void GetTypeHandleParams(VMPTR_AppDomain vmAppDomain, - VMPTR_TypeHandle vmTypeHandle, - TypeParamsList * pParams); + HRESULT GetTypeHandleParams(VMPTR_AppDomain vmAppDomain, VMPTR_TypeHandle vmTypeHandle, OUT TypeParamsList * pParams); // DacDbi API: GetSimpleType // gets the metadata token and domain file corresponding to a simple type - void GetSimpleType(VMPTR_AppDomain vmAppDomain, - CorElementType simpleType, - mdTypeDef * pMetadataToken, - VMPTR_Module * pVmModule, - VMPTR_DomainAssembly * pVmDomainAssembly); + HRESULT GetSimpleType(VMPTR_AppDomain vmAppDomain, CorElementType simpleType, OUT mdTypeDef * pMetadataToken, OUT VMPTR_Module * pVmModule, OUT VMPTR_DomainAssembly * pVmDomainAssembly); - BOOL IsExceptionObject(VMPTR_Object vmObject); + HRESULT IsExceptionObject(VMPTR_Object vmObject, OUT BOOL * pResult); - void GetStackFramesFromException(VMPTR_Object vmObject, DacDbiArrayList& dacStackFrames); + HRESULT GetStackFramesFromException(VMPTR_Object vmObject, DacDbiArrayList& dacStackFrames); // Returns true if the argument is a runtime callable wrapper - BOOL IsRcw(VMPTR_Object vmObject); + HRESULT IsRcw(VMPTR_Object vmObject, OUT BOOL * pResult); - BOOL IsDelegate(VMPTR_Object vmObject); + HRESULT IsDelegate(VMPTR_Object vmObject, OUT BOOL * pResult); HRESULT GetDelegateType(VMPTR_Object delegateObject, DelegateType *delegateType); @@ -374,39 +327,26 @@ class DacDbiInterfaceImpl : HRESULT IsModuleMapped(VMPTR_Module pModule, OUT BOOL *isModuleMapped); - bool MetadataUpdatesApplied(); + HRESULT MetadataUpdatesApplied(OUT bool * pResult); // retrieves the list of COM interfaces implemented by vmObject, as it is known at // the time of the call (the list may change as new interface types become available // in the runtime) - void GetRcwCachedInterfaceTypes( - VMPTR_Object vmObject, - VMPTR_AppDomain vmAppDomain, - BOOL bIInspectableOnly, - OUT DacDbiArrayList * pDacInterfaces); + HRESULT GetRcwCachedInterfaceTypes(VMPTR_Object vmObject, VMPTR_AppDomain vmAppDomain, BOOL bIInspectableOnly, OUT DacDbiArrayList * pDacInterfaces); // retrieves the list of interfaces pointers implemented by vmObject, as it is known at // the time of the call (the list may change as new interface types become available // in the runtime) - void GetRcwCachedInterfacePointers( - VMPTR_Object vmObject, - BOOL bIInspectableOnly, - OUT DacDbiArrayList * pDacItfPtrs); + HRESULT GetRcwCachedInterfacePointers(VMPTR_Object vmObject, BOOL bIInspectableOnly, OUT DacDbiArrayList * pDacItfPtrs); // retrieves a list of interface types corresponding to the passed in // list of IIDs. the interface types are retrieved from an app domain // IID / Type cache, that is updated as new types are loaded. will // have NULL entries corresponding to unknown IIDs in "iids" - void GetCachedWinRTTypesForIIDs( - VMPTR_AppDomain vmAppDomain, - DacDbiArrayList & iids, - OUT DacDbiArrayList * pTypes); + HRESULT GetCachedWinRTTypesForIIDs(VMPTR_AppDomain vmAppDomain, DacDbiArrayList & iids, OUT DacDbiArrayList * pTypes); // retrieves the whole app domain cache of IID / Type mappings. - void GetCachedWinRTTypes( - VMPTR_AppDomain vmAppDomain, - OUT DacDbiArrayList * pGuids, - OUT DacDbiArrayList * pTypes); + HRESULT GetCachedWinRTTypes(VMPTR_AppDomain vmAppDomain, OUT DacDbiArrayList * piids, OUT DacDbiArrayList * pTypes); private: // Helper to enumerate all possible memory ranges help by a loader allocator. @@ -428,7 +368,7 @@ class DacDbiInterfaceImpl : TADDR funcIp, OUT VMPTR_MethodDesc *ppMD); - BOOL IsExceptionObject(MethodTable* pMT); + HRESULT IsExceptionObject(VMPTR_Object vmObject, OUT BOOL * pResult); // Get the approximate and exact type handles for a type void GetTypeHandles(VMPTR_TypeHandle vmThExact, @@ -644,32 +584,25 @@ class DacDbiInterfaceImpl : public: // Get object information for a TypedByRef object. Initializes the objRef and typedByRefType fields of // pObjectData (type info for the referent). - void GetTypedByRefInfo(CORDB_ADDRESS pTypedByRef, - VMPTR_AppDomain vmAppDomain, - DebuggerIPCE_ObjectData * pObjectData); + HRESULT GetTypedByRefInfo(CORDB_ADDRESS pTypedByRef, VMPTR_AppDomain vmAppDomain, DebuggerIPCE_ObjectData * pObjectData); // Get the string length and offset to string base for a string object - void GetStringData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData); + HRESULT GetStringData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData); // Get information for an array type referent of an objRef, including rank, upper and lower bounds, // element size and type, and the number of elements. - void GetArrayData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData); + HRESULT GetArrayData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData); // Get information about an object for which we have a reference, including the object size and // type information. - void GetBasicObjectInfo(CORDB_ADDRESS objectAddress, - CorElementType type, - VMPTR_AppDomain vmAppDomain, - DebuggerIPCE_ObjectData * pObjectData); + HRESULT GetBasicObjectInfo(CORDB_ADDRESS objectAddress, CorElementType type, VMPTR_AppDomain vmAppDomain, DebuggerIPCE_ObjectData * pObjectData); // Returns the thread which owns the monitor lock on an object and the acquisition count - MonitorLockInfo GetThreadOwningMonitorLock(VMPTR_Object vmObject); + HRESULT GetThreadOwningMonitorLock(VMPTR_Object vmObject, OUT MonitorLockInfo * pRetVal); // Enumerate all threads waiting on the monitor event for an object - void EnumerateMonitorEventWaitList(VMPTR_Object vmObject, - FP_THREAD_ENUMERATION_CALLBACK fpCallback, - CALLBACK_DATA pUserData); + HRESULT EnumerateMonitorEventWaitList(VMPTR_Object vmObject, FP_THREAD_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData); private: // Helper function for CheckRef. Sanity check an object. @@ -694,8 +627,8 @@ class DacDbiInterfaceImpl : #ifdef TEST_DATA_CONSISTENCY public: - void TestCrst(VMPTR_Crst vmCrst); - void TestRWLock(VMPTR_SimpleRWLock vmRWLock); + HRESULT TestCrst(VMPTR_Crst vmCrst); + HRESULT TestRWLock(VMPTR_SimpleRWLock vmRWLock); #endif // ============================================================================ @@ -707,232 +640,199 @@ class DacDbiInterfaceImpl : public: // Get the full path and file name to the assembly's manifest module. - BOOL GetAssemblyPath(VMPTR_Assembly vmAssembly, - IStringHolder * pStrFilename); + HRESULT GetAssemblyPath(VMPTR_Assembly vmAssembly, IStringHolder * pStrFilename, OUT BOOL * pResult); - void GetAssemblyFromDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, VMPTR_Assembly *vmAssembly); + HRESULT GetAssemblyFromDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Assembly * vmAssembly); // Determines whether the runtime security system has assigned full-trust to this assembly. - BOOL IsAssemblyFullyTrusted(VMPTR_DomainAssembly vmDomainAssembly); + HRESULT IsAssemblyFullyTrusted(VMPTR_DomainAssembly vmDomainAssembly, OUT BOOL * pResult); // get a type def resolved across modules - void ResolveTypeReference(const TypeRefData * pTypeRefInfo, - TypeRefData * pTargetRefInfo); + HRESULT ResolveTypeReference(const TypeRefData * pTypeRefInfo, TypeRefData * pTargetRefInfo); // Get the full path and file name to the module (if any). - BOOL GetModulePath(VMPTR_Module vmModule, - IStringHolder * pStrFilename); + HRESULT GetModulePath(VMPTR_Module vmModule, IStringHolder * pStrFilename, OUT BOOL * pResult); // Implementation of IDacDbiInterface::GetModuleSimpleName - void GetModuleSimpleName(VMPTR_Module vmModule, IStringHolder * pStrFilename); + HRESULT GetModuleSimpleName(VMPTR_Module vmModule, IStringHolder * pStrFilename); // Implementation of IDacDbiInterface::GetMetadata - void GetMetadata(VMPTR_Module vmModule, TargetBuffer * pTargetBuffer); + HRESULT GetMetadata(VMPTR_Module vmModule, OUT TargetBuffer * pTargetBuffer); // Implementation of IDacDbiInterface::GetSymbolsBuffer - void GetSymbolsBuffer(VMPTR_Module vmModule, TargetBuffer * pTargetBuffer, SymbolFormat * pSymbolFormat); + HRESULT GetSymbolsBuffer(VMPTR_Module vmModule, OUT TargetBuffer * pTargetBuffer, OUT SymbolFormat * pSymbolFormat); // Gets properties for a module - void GetModuleData(VMPTR_Module vmModule, ModuleInfo * pData); + HRESULT GetModuleData(VMPTR_Module vmModule, OUT ModuleInfo * pData); // Gets properties for a domain assembly - void GetDomainAssemblyData(VMPTR_DomainAssembly vmDomainAssembly, DomainAssemblyInfo * pData); + HRESULT GetDomainAssemblyData(VMPTR_DomainAssembly vmDomainAssembly, OUT DomainAssemblyInfo * pData); - void GetModuleForDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Module * pModule); + HRESULT GetModuleForDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Module * pModule); // Yields true if the address is a CLR stub. - BOOL IsTransitionStub(CORDB_ADDRESS address); + HRESULT IsTransitionStub(CORDB_ADDRESS address, OUT BOOL * pResult); // Get the "type" of address. - AddressType GetAddressType(CORDB_ADDRESS address); + HRESULT GetAddressType(CORDB_ADDRESS address, OUT AddressType * pRetVal); // Enumerate the appdomains - void EnumerateAppDomains(FP_APPDOMAIN_ENUMERATION_CALLBACK fpCallback, - void * pUserData); + HRESULT EnumerateAppDomains(FP_APPDOMAIN_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData); // Enumerate the assemblies in the appdomain. - void EnumerateAssembliesInAppDomain(VMPTR_AppDomain vmAppDomain, - FP_ASSEMBLY_ENUMERATION_CALLBACK fpCallback, - void * pUserData); + HRESULT EnumerateAssembliesInAppDomain(VMPTR_AppDomain vmAppDomain, FP_ASSEMBLY_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData); // Enumerate the moduels in the given assembly. - void EnumerateModulesInAssembly( - VMPTR_DomainAssembly vmAssembly, - FP_MODULE_ENUMERATION_CALLBACK fpCallback, - void * pUserData - ); + HRESULT EnumerateModulesInAssembly(VMPTR_DomainAssembly vmAssembly, FP_MODULE_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData); // When stopped at an event, request a synchronization. - void RequestSyncAtEvent(); + HRESULT RequestSyncAtEvent(); //sets flag Debugger::m_sendExceptionsOutsideOfJMC on the LS HRESULT SetSendExceptionsOutsideOfJMC(BOOL sendExceptionsOutsideOfJMC); // Notify the debuggee that a debugger attach is pending. - void MarkDebuggerAttachPending(); + HRESULT MarkDebuggerAttachPending(); // Notify the debuggee that a debugger is attached. - void MarkDebuggerAttached(BOOL fAttached); + HRESULT MarkDebuggerAttached(BOOL fAttached); // Enumerate connections in the process. void EnumerateConnections(FP_CONNECTION_CALLBACK fpCallback, void * pUserData); - void EnumerateThreads(FP_THREAD_ENUMERATION_CALLBACK fpCallback, void * pUserData); + HRESULT EnumerateThreads(FP_THREAD_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData); - bool IsThreadMarkedDead(VMPTR_Thread vmThread); + HRESULT IsThreadMarkedDead(VMPTR_Thread vmThread, OUT bool * pResult); // Return the handle of the specified thread. - HANDLE GetThreadHandle(VMPTR_Thread vmThread); + HRESULT GetThreadHandle(VMPTR_Thread vmThread, OUT HANDLE * pRetVal); // Return the object handle for the managed Thread object corresponding to the specified thread. - VMPTR_OBJECTHANDLE GetThreadObject(VMPTR_Thread vmThread); + HRESULT GetThreadObject(VMPTR_Thread vmThread, OUT VMPTR_OBJECTHANDLE * pRetVal); // Get the alocated bytes for this thread. - void GetThreadAllocInfo(VMPTR_Thread vmThread, DacThreadAllocInfo* threadAllocInfo); + HRESULT GetThreadAllocInfo(VMPTR_Thread vmThread, DacThreadAllocInfo* threadAllocInfo); // Set and reset the TSNC_DebuggerUserSuspend bit on the state of the specified thread // according to the CorDebugThreadState. - void SetDebugState(VMPTR_Thread vmThread, - CorDebugThreadState debugState); + HRESULT SetDebugState(VMPTR_Thread vmThread, CorDebugThreadState debugState); // Returns TRUE if there is a current exception which is unhandled - BOOL HasUnhandledException(VMPTR_Thread vmThread); + HRESULT HasUnhandledException(VMPTR_Thread vmThread, OUT BOOL * pResult); // Return the user state of the specified thread. - CorDebugUserState GetUserState(VMPTR_Thread vmThread); + HRESULT GetUserState(VMPTR_Thread vmThread, OUT CorDebugUserState * pRetVal); // Returns the user state of the specified thread except for USER_UNSAFE_POINT. - CorDebugUserState GetPartialUserState(VMPTR_Thread vmThread); + HRESULT GetPartialUserState(VMPTR_Thread vmThread, OUT CorDebugUserState * pRetVal); // Return the connection ID of the specified thread. - CONNID GetConnectionID(VMPTR_Thread vmThread); + HRESULT GetConnectionID(VMPTR_Thread vmThread, OUT CONNID * pRetVal); // Return the task ID of the specified thread. - TASKID GetTaskID(VMPTR_Thread vmThread); + HRESULT GetTaskID(VMPTR_Thread vmThread, OUT TASKID * pRetVal); // Return the OS thread ID of the specified thread - DWORD TryGetVolatileOSThreadID(VMPTR_Thread vmThread); + HRESULT TryGetVolatileOSThreadID(VMPTR_Thread vmThread, OUT DWORD * pRetVal); // Return the unique thread ID of the specified thread. - DWORD GetUniqueThreadID(VMPTR_Thread vmThread); + HRESULT GetUniqueThreadID(VMPTR_Thread vmThread, OUT DWORD * pRetVal); // Return the object handle to the managed Exception object of the current exception // on the specified thread. The return value could be NULL if there is no current exception. - VMPTR_OBJECTHANDLE GetCurrentException(VMPTR_Thread vmThread); + HRESULT GetCurrentException(VMPTR_Thread vmThread, OUT VMPTR_OBJECTHANDLE * pRetVal); // Return the object handle to the managed object for a given CCW pointer. - VMPTR_OBJECTHANDLE GetObjectForCCW(CORDB_ADDRESS ccwPtr); + HRESULT GetObjectForCCW(CORDB_ADDRESS ccwPtr, OUT VMPTR_OBJECTHANDLE * pRetVal); // Return the object handle to the managed CustomNotification object of the current notification // on the specified thread. The return value could be NULL if there is no current notification. // This will return non-null if and only if we are currently inside a CustomNotification Callback // (or a dump was generated while in this callback) - VMPTR_OBJECTHANDLE GetCurrentCustomDebuggerNotification(VMPTR_Thread vmThread); + HRESULT GetCurrentCustomDebuggerNotification(VMPTR_Thread vmThread, OUT VMPTR_OBJECTHANDLE * pRetVal); // Return the current appdomain - VMPTR_AppDomain GetCurrentAppDomain(); + HRESULT GetCurrentAppDomain(OUT VMPTR_AppDomain * pRetVal); // Given an assembly ref token and metadata scope (via the DomainAssembly), resolve the assembly. - VMPTR_DomainAssembly ResolveAssembly(VMPTR_DomainAssembly vmScope, mdToken tkAssemblyRef); + HRESULT ResolveAssembly(VMPTR_DomainAssembly vmScope, mdToken tkAssemblyRef, OUT VMPTR_DomainAssembly * pRetVal); // Hijack the thread - void Hijack( - VMPTR_Thread vmThread, - ULONG32 dwThreadId, - const EXCEPTION_RECORD * pRecord, - T_CONTEXT * pOriginalContext, - ULONG32 cbSizeContext, - EHijackReason::EHijackReason reason, - void * pUserData, - CORDB_ADDRESS * pRemoteContextAddr); + HRESULT Hijack(VMPTR_Thread vmThread, ULONG32 dwThreadId, const EXCEPTION_RECORD * pRecord, T_CONTEXT * pOriginalContext, ULONG32 cbSizeContext, EHijackReason::EHijackReason reason, void * pUserData, CORDB_ADDRESS * pRemoteContextAddr); // Return the filter CONTEXT on the LS. - VMPTR_CONTEXT GetManagedStoppedContext(VMPTR_Thread vmThread); + HRESULT GetManagedStoppedContext(VMPTR_Thread vmThread, OUT VMPTR_CONTEXT * pRetVal); // Create and return a stackwalker on the specified thread. - void CreateStackWalk(VMPTR_Thread vmThread, - DT_CONTEXT * pInternalContextBuffer, - StackWalkHandle * ppSFIHandle); + HRESULT CreateStackWalk(VMPTR_Thread vmThread, DT_CONTEXT * pInternalContextBuffer, OUT StackWalkHandle * ppSFIHandle); // Delete the stackwalk object - void DeleteStackWalk(StackWalkHandle ppSFIHandle); + HRESULT DeleteStackWalk(StackWalkHandle ppSFIHandle); // Get the CONTEXT of the current frame at which the stackwalker is stopped. - void GetStackWalkCurrentContext(StackWalkHandle pSFIHandle, - DT_CONTEXT * pContext); + HRESULT GetStackWalkCurrentContext(StackWalkHandle pSFIHandle, DT_CONTEXT * pContext); - void GetStackWalkCurrentContext(StackFrameIterator * pIter, DT_CONTEXT * pContext); + HRESULT GetStackWalkCurrentContext(StackWalkHandle pSFIHandle, DT_CONTEXT * pContext); // Set the stackwalker to the specified CONTEXT. - void SetStackWalkCurrentContext(VMPTR_Thread vmThread, - StackWalkHandle pSFIHandle, - CorDebugSetContextFlag flag, - DT_CONTEXT * pContext); + HRESULT SetStackWalkCurrentContext(VMPTR_Thread vmThread, StackWalkHandle pSFIHandle, CorDebugSetContextFlag flag, DT_CONTEXT * pContext); // Unwind the stackwalker to the next frame. - BOOL UnwindStackWalkFrame(StackWalkHandle pSFIHandle); + HRESULT UnwindStackWalkFrame(StackWalkHandle pSFIHandle, OUT BOOL * pResult); HRESULT CheckContext(VMPTR_Thread vmThread, const DT_CONTEXT * pContext); // Retrieve information about the current frame from the stackwalker. - FrameType GetStackWalkCurrentFrameInfo(StackWalkHandle pSFIHandle, - DebuggerIPCE_STRData * pFrameData); + HRESULT GetStackWalkCurrentFrameInfo(StackWalkHandle pSFIHandle, OPTIONAL DebuggerIPCE_STRData * pFrameData, OUT FrameType * pRetVal); // Return the number of internal frames on the specified thread. - ULONG32 GetCountOfInternalFrames(VMPTR_Thread vmThread); + HRESULT GetCountOfInternalFrames(VMPTR_Thread vmThread, OUT ULONG32 * pRetVal); // Enumerate the internal frames on the specified thread and invoke the provided callback on each of them. - void EnumerateInternalFrames(VMPTR_Thread vmThread, - FP_INTERNAL_FRAME_ENUMERATION_CALLBACK fpCallback, - void * pUserData); + HRESULT EnumerateInternalFrames(VMPTR_Thread vmThread, FP_INTERNAL_FRAME_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData); // Given the FramePointer of the parent frame and the FramePointer of the current frame, // check if the current frame is the parent frame. - BOOL IsMatchingParentFrame(FramePointer fpToCheck, FramePointer fpParent); + HRESULT IsMatchingParentFrame(FramePointer fpToCheck, FramePointer fpParent, OUT BOOL * pResult); // Return the stack parameter size of the given method. - ULONG32 GetStackParameterSize(CORDB_ADDRESS controlPC); + HRESULT GetStackParameterSize(CORDB_ADDRESS controlPC, OUT ULONG32 * pRetVal); // Return the FramePointer of the current frame at which the stackwalker is stopped. - FramePointer GetFramePointer(StackWalkHandle pSFIHandle); + HRESULT GetFramePointer(StackWalkHandle pSFIHandle, OUT FramePointer * pRetVal); FramePointer GetFramePointerWorker(StackFrameIterator * pIter); // Return TRUE if the specified CONTEXT is the CONTEXT of the leaf frame. // @dbgtodo filter CONTEXT - Currently we check for the filter CONTEXT first. - BOOL IsLeafFrame(VMPTR_Thread vmThread, - const DT_CONTEXT * pContext); + HRESULT IsLeafFrame(VMPTR_Thread vmThread, const DT_CONTEXT * pContext, OUT BOOL * pResult); // DacDbi API: Get the context for a particular thread of the target process - void GetContext(VMPTR_Thread vmThread, DT_CONTEXT * pContextBuffer); + HRESULT GetContext(VMPTR_Thread vmThread, DT_CONTEXT * pContextBuffer); // This is a simple helper function to convert a CONTEXT to a DebuggerREGDISPLAY. We need to do this // inside DDI because the RS has no notion of REGDISPLAY. - void ConvertContextToDebuggerRegDisplay(const DT_CONTEXT * pInContext, - DebuggerREGDISPLAY * pOutDRD, - BOOL fActive); + HRESULT ConvertContextToDebuggerRegDisplay(const DT_CONTEXT * pInContext, DebuggerREGDISPLAY * pOutDRD, BOOL fActive); // Check if the given method is a DiagnosticHidden or an LCG method. - DynamicMethodType IsDiagnosticsHiddenOrLCGMethod(VMPTR_MethodDesc vmMethodDesc); + HRESULT IsDiagnosticsHiddenOrLCGMethod(VMPTR_MethodDesc vmMethodDesc, OUT DynamicMethodType * pRetVal); // Return a TargetBuffer for the raw vararg signature. - TargetBuffer GetVarArgSig(CORDB_ADDRESS VASigCookieAddr, - CORDB_ADDRESS * pArgBase); + HRESULT GetVarArgSig(CORDB_ADDRESS VASigCookieAddr, OUT CORDB_ADDRESS * pArgBase, OUT TargetBuffer * pRetVal); // returns TRUE if the type requires 8-byte alignment - BOOL RequiresAlign8(VMPTR_TypeHandle thExact); + HRESULT RequiresAlign8(VMPTR_TypeHandle thExact, OUT BOOL * pResult); // Resolve the raw generics token to the real generics type token. The resolution is based on the // given index. - GENERICS_TYPE_TOKEN ResolveExactGenericArgsToken(DWORD dwExactGenericArgsTokenIndex, - GENERICS_TYPE_TOKEN rawToken); + HRESULT ResolveExactGenericArgsToken(DWORD dwExactGenericArgsTokenIndex, GENERICS_TYPE_TOKEN rawToken, OUT GENERICS_TYPE_TOKEN * pRetVal); // Returns a bitfield reflecting the managed debugging state at the time of // the jit attach. - CLR_DEBUGGING_PROCESS_FLAGS GetAttachStateFlags(); + HRESULT GetAttachStateFlags(OUT CLR_DEBUGGING_PROCESS_FLAGS * pRetVal); protected: // This class used to be stateless, but we are relaxing the requirements @@ -989,10 +889,10 @@ class DacDbiInterfaceImpl : // Get the address of the Debugger control block on the helper thread. Returns // NULL if the control block has not been successfully allocated - CORDB_ADDRESS GetDebuggerControlBlockAddress(); + HRESULT GetDebuggerControlBlockAddress(OUT CORDB_ADDRESS * pRetVal); // Creates a VMPTR of an Object from a target address - VMPTR_Object GetObject(CORDB_ADDRESS ptr); + HRESULT GetObject(CORDB_ADDRESS ptr, OUT VMPTR_Object * pRetVal); // sets state in the native binder HRESULT EnableNGENPolicy(CorDebugNGENPolicy ePolicy); @@ -1005,25 +905,25 @@ class DacDbiInterfaceImpl : HRESULT GetNGENCompilerFlags(DWORD *pdwFlags); // Creates a VMPTR of an Object from a target address pointing to an OBJECTREF - VMPTR_Object GetObjectFromRefPtr(CORDB_ADDRESS ptr); + HRESULT GetObjectFromRefPtr(CORDB_ADDRESS ptr, OUT VMPTR_Object * pRetVal); // Get the target address from a VMPTR_OBJECTHANDLE, i.e., the handle address - CORDB_ADDRESS GetHandleAddressFromVmHandle(VMPTR_OBJECTHANDLE vmHandle); + HRESULT GetHandleAddressFromVmHandle(VMPTR_OBJECTHANDLE vmHandle, OUT CORDB_ADDRESS * pRetVal); // Gets the target address of an VMPTR of an Object - TargetBuffer GetObjectContents(VMPTR_Object vmObj); + HRESULT GetObjectContents(VMPTR_Object obj, OUT TargetBuffer * pRetVal); // Create a VMPTR_OBJECTHANDLE from a CORDB_ADDRESS pointing to an object handle - VMPTR_OBJECTHANDLE GetVmObjectHandle(CORDB_ADDRESS handleAddress); + HRESULT GetVmObjectHandle(CORDB_ADDRESS handleAddress, OUT VMPTR_OBJECTHANDLE * pRetVal); // Validate that the VMPTR_OBJECTHANDLE refers to a legitimate managed object - BOOL IsVmObjectHandleValid(VMPTR_OBJECTHANDLE vmHandle); + HRESULT IsVmObjectHandleValid(VMPTR_OBJECTHANDLE vmHandle, OUT BOOL * pResult); // if the specified module is a WinRT module then isWinRT will equal TRUE HRESULT IsWinRTModule(VMPTR_Module vmModule, BOOL& isWinRT); // Determines the app domain id for the object referred to by a given VMPTR_OBJECTHANDLE - ULONG GetAppDomainIdFromVmObjectHandle(VMPTR_OBJECTHANDLE vmHandle); + HRESULT GetAppDomainIdFromVmObjectHandle(VMPTR_OBJECTHANDLE vmHandle, OUT ULONG * pRetVal); private: bool IsThreadMarkedDeadWorker(Thread * pThread); @@ -1045,7 +945,7 @@ class DacDbiInterfaceImpl : DebuggerIPCE_JITFuncData * pJITFuncData); // Return the stack parameter size of the given method. - ULONG32 GetStackParameterSize(EECodeInfo * pCodeInfo); + HRESULT GetStackParameterSize(CORDB_ADDRESS controlPC, OUT ULONG32 * pRetVal); typedef enum { @@ -1102,10 +1002,7 @@ class DacDbiInterfaceImpl : public: // API for picking up the info needed for a debugger to look up an image from its search path. - bool GetMetaDataFileInfoFromPEFile(VMPTR_PEAssembly vmPEAssembly, - DWORD &dwTimeStamp, - DWORD &dwSize, - IStringHolder* pStrFilename); + HRESULT GetMetaDataFileInfoFromPEFile(VMPTR_PEAssembly vmPEAssembly, DWORD & dwTimeStamp, DWORD & dwImageSize, IStringHolder* pStrFilename, OUT bool * pResult); }; From e4f089d04c3658542a3d011723c40c133094fdd3 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Tue, 24 Feb 2026 08:57:07 -0500 Subject: [PATCH 3/3] Wrap DAC implementation bodies with EX_TRY/EX_CATCH_HRESULT Convert all 122 IDacDbiInterface method implementations to catch exceptions and return HRESULT. Value-returning methods now write results through OUT parameters. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/coreclr/debug/daccess/dacdbiimpl.cpp | 4132 ++++++++++------- src/coreclr/debug/daccess/dacdbiimpl.h | 10 +- src/coreclr/debug/daccess/dacdbiimpllocks.cpp | 22 +- .../debug/daccess/dacdbiimplstackwalk.cpp | 766 +-- src/coreclr/debug/di/divalue.cpp | 66 +- src/coreclr/debug/di/module.cpp | 48 +- src/coreclr/debug/di/process.cpp | 107 +- src/coreclr/debug/di/rsappdomain.cpp | 24 +- src/coreclr/debug/di/rsassembly.cpp | 10 +- src/coreclr/debug/di/rsclass.cpp | 26 +- src/coreclr/debug/di/rsfunction.cpp | 8 +- src/coreclr/debug/di/rsstackwalk.cpp | 37 +- src/coreclr/debug/di/rsthread.cpp | 122 +- src/coreclr/debug/di/rstype.cpp | 30 +- src/coreclr/debug/di/valuehome.cpp | 4 +- 15 files changed, 3136 insertions(+), 2276 deletions(-) diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index facd30daac6bdf..c598a8090c4e5f 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -436,12 +436,18 @@ interface IMDInternalImport* DacDbiInterfaceImpl::GetMDImport( //----------------------------------------------------------------------------- // Destroy the connection, freeing up any resources. -void DacDbiInterfaceImpl::Destroy() +HRESULT DacDbiInterfaceImpl::Destroy() { - m_pAllocator = NULL; + HRESULT hr = S_OK; + EX_TRY + { + m_pAllocator = NULL; - this->Release(); - // Memory is deleted, don't access this object any more + this->Release(); + // Memory is deleted, don't access this object any more + } + EX_CATCH_HRESULT(hr); + return hr; } // Check whether the version of the DBI matches the version of the runtime. @@ -483,165 +489,225 @@ HRESULT DacDbiInterfaceImpl::FlushCache() } // enable or disable DAC target consistency checks -void DacDbiInterfaceImpl::DacSetTargetConsistencyChecks(bool fEnableAsserts) +HRESULT DacDbiInterfaceImpl::DacSetTargetConsistencyChecks(bool fEnableAsserts) { - // forward on to our ClrDataAccess base class - ClrDataAccess::SetTargetConsistencyChecks(fEnableAsserts); + HRESULT hr = S_OK; + EX_TRY + { + // forward on to our ClrDataAccess base class + ClrDataAccess::SetTargetConsistencyChecks(fEnableAsserts); + } + EX_CATCH_HRESULT(hr); + return hr; } // Query if Left-side is started up? -BOOL DacDbiInterfaceImpl::IsLeftSideInitialized() +HRESULT DacDbiInterfaceImpl::IsLeftSideInitialized(OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - if (g_pDebugger != NULL) + HRESULT hr = S_OK; + EX_TRY { - // This check is "safe". - // The initialize order in the left-side is: - // 1) g_pDebugger is an RVA based global initialized to NULL when the module is loaded. - // 2) Allocate a "Debugger" object. - // 3) run the ctor, which will set m_fLeftSideInitialized = FALSE. - // 4) assign the object to g_pDebugger. - // 5) later, LS initialization code will assign g_pDebugger->m_fLeftSideInitialized = TRUE. - // - // The memory write in #5 is atomic. There is no window where we're reading uninitialized data. - return (g_pDebugger->m_fLeftSideInitialized != 0); + if (g_pDebugger != NULL) + { + // This check is "safe". + // The initialize order in the left-side is: + // 1) g_pDebugger is an RVA based global initialized to NULL when the module is loaded. + // 2) Allocate a "Debugger" object. + // 3) run the ctor, which will set m_fLeftSideInitialized = FALSE. + // 4) assign the object to g_pDebugger. + // 5) later, LS initialization code will assign g_pDebugger->m_fLeftSideInitialized = TRUE. + // + // The memory write in #5 is atomic. There is no window where we're reading uninitialized data. + + *pResult = (g_pDebugger->m_fLeftSideInitialized != 0); + } + else + { + *pResult = FALSE; + } } - - return FALSE; + EX_CATCH_HRESULT(hr); + return hr; } // Determines if a given address is a CLR stub. -BOOL DacDbiInterfaceImpl::IsTransitionStub(CORDB_ADDRESS address) +HRESULT DacDbiInterfaceImpl::IsTransitionStub(CORDB_ADDRESS address, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - BOOL fIsStub = FALSE; + HRESULT hr = S_OK; + EX_TRY + { -#if defined(TARGET_UNIX) - // Currently IsIPInModule() is not implemented in the PAL. Rather than skipping the check, we should - // either E_NOTIMPL this API or implement IsIPInModule() in the PAL. Since ICDProcess::IsTransitionStub() - // is only called by VS in mixed-mode debugging scenarios, and mixed-mode debugging is not supported on - // POSIX systems, there is really no incentive to implement this API at this point. - ThrowHR(E_NOTIMPL); + BOOL fIsStub = FALSE; -#else // !TARGET_UNIX + #if defined(TARGET_UNIX) + // Currently IsIPInModule() is not implemented in the PAL. Rather than skipping the check, we should + // either E_NOTIMPL this API or implement IsIPInModule() in the PAL. Since ICDProcess::IsTransitionStub() + // is only called by VS in mixed-mode debugging scenarios, and mixed-mode debugging is not supported on + // POSIX systems, there is really no incentive to implement this API at this point. + ThrowHR(E_NOTIMPL); - TADDR ip = (TADDR)address; + #else // !TARGET_UNIX - if (ip == NULL) - { - fIsStub = FALSE; - } - else - { - fIsStub = StubManager::IsStub(ip); - } + TADDR ip = (TADDR)address; - // If it's in Mscorwks, count that as a stub too. - if (fIsStub == FALSE) - { - fIsStub = IsIPInModule(m_globalBase, ip); - } + if (ip == NULL) + { + fIsStub = FALSE; + } + else + { + fIsStub = StubManager::IsStub(ip); + } + + // If it's in Mscorwks, count that as a stub too. + if (fIsStub == FALSE) + { + fIsStub = IsIPInModule(m_globalBase, ip); + } -#endif // TARGET_UNIX + #endif // TARGET_UNIX - return fIsStub; + *pResult = fIsStub; + } + EX_CATCH_HRESULT(hr); + return hr; } // Gets the type of 'address'. -IDacDbiInterface::AddressType DacDbiInterfaceImpl::GetAddressType(CORDB_ADDRESS address) +HRESULT DacDbiInterfaceImpl::GetAddressType(CORDB_ADDRESS address, OUT AddressType * pRetVal) { DD_ENTER_MAY_THROW; - TADDR taAddr = CORDB_ADDRESS_TO_TADDR(address); - if (IsPossibleCodeAddress(taAddr) == S_OK) + HRESULT hr = S_OK; + EX_TRY { - if (ExecutionManager::IsManagedCode(taAddr)) + TADDR taAddr = CORDB_ADDRESS_TO_TADDR(address); + + if (IsPossibleCodeAddress(taAddr) == S_OK) { - return kAddressManagedMethod; + if (ExecutionManager::IsManagedCode(taAddr)) + { + *pRetVal = kAddressManagedMethod; + } + else if (StubManager::IsStub(taAddr)) + { + *pRetVal = kAddressRuntimeUnmanagedStub; + } + else + { + *pRetVal = kAddressUnrecognized; + } } - - if (StubManager::IsStub(taAddr)) + else { - return kAddressRuntimeUnmanagedStub; + *pRetVal = kAddressUnrecognized; } } - - return kAddressUnrecognized; + EX_CATCH_HRESULT(hr); + return hr; } // Get a VM appdomain pointer that matches the appdomain ID -VMPTR_AppDomain DacDbiInterfaceImpl::GetAppDomainFromId(ULONG appdomainId) +HRESULT DacDbiInterfaceImpl::GetAppDomainFromId(ULONG appdomainId, OUT VMPTR_AppDomain * pRetVal) { DD_ENTER_MAY_THROW; - VMPTR_AppDomain vmAppDomain; + HRESULT hr = S_OK; + EX_TRY + { + + VMPTR_AppDomain vmAppDomain; - // @dbgtodo dac support - We would like to wean ourselves off the IXClrData interfaces. - IXCLRDataProcess * pDAC = this; - ReleaseHolder pDacAppDomain; + // @dbgtodo dac support - We would like to wean ourselves off the IXClrData interfaces. + IXCLRDataProcess * pDAC = this; + ReleaseHolder pDacAppDomain; - HRESULT hrStatus = pDAC->GetAppDomainByUniqueID(appdomainId, &pDacAppDomain); - IfFailThrow(hrStatus); + HRESULT hrStatus = pDAC->GetAppDomainByUniqueID(appdomainId, &pDacAppDomain); + IfFailThrow(hrStatus); - IXCLRDataAppDomain * pIAppDomain = pDacAppDomain; - AppDomain * pAppDomain = (static_cast (pIAppDomain))->GetAppDomain(); - SIMPLIFYING_ASSUMPTION(pAppDomain != NULL); - if (pAppDomain == NULL) - { - ThrowHR(E_FAIL); // corrupted left-side? - } + IXCLRDataAppDomain * pIAppDomain = pDacAppDomain; + AppDomain * pAppDomain = (static_cast (pIAppDomain))->GetAppDomain(); + SIMPLIFYING_ASSUMPTION(pAppDomain != NULL); + if (pAppDomain == NULL) + { + ThrowHR(E_FAIL); // corrupted left-side? + } - TADDR addrAppDomain = PTR_HOST_TO_TADDR(pAppDomain); - vmAppDomain.SetDacTargetPtr(addrAppDomain); + TADDR addrAppDomain = PTR_HOST_TO_TADDR(pAppDomain); + vmAppDomain.SetDacTargetPtr(addrAppDomain); - return vmAppDomain; + *pRetVal = vmAppDomain; + } + EX_CATCH_HRESULT(hr); + return hr; } // Get the AppDomain ID for an AppDomain. -ULONG DacDbiInterfaceImpl::GetAppDomainId(VMPTR_AppDomain vmAppDomain) +HRESULT DacDbiInterfaceImpl::GetAppDomainId(VMPTR_AppDomain vmAppDomain, OUT ULONG * pRetVal) { DD_ENTER_MAY_THROW; - if (vmAppDomain.IsNull()) - { - return 0; - } - else + HRESULT hr = S_OK; + EX_TRY { - AppDomain * pAppDomain = vmAppDomain.GetDacPtr(); - return DefaultADID; + + if (vmAppDomain.IsNull()) + { + *pRetVal = 0; + } + else + { + AppDomain * pAppDomain = vmAppDomain.GetDacPtr(); + *pRetVal = DefaultADID; + } } + EX_CATCH_HRESULT(hr); + return hr; } // Get the managed AppDomain object for an AppDomain. -VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetAppDomainObject(VMPTR_AppDomain vmAppDomain) +HRESULT DacDbiInterfaceImpl::GetAppDomainObject(VMPTR_AppDomain vmAppDomain, OUT VMPTR_OBJECTHANDLE * pRetVal) { DD_ENTER_MAY_THROW; - AppDomain* pAppDomain = vmAppDomain.GetDacPtr(); - OBJECTHANDLE hAppDomainManagedObject = pAppDomain->GetRawExposedObjectHandleForDebugger(); - VMPTR_OBJECTHANDLE vmObj = VMPTR_OBJECTHANDLE::NullPtr(); - vmObj.SetDacTargetPtr(hAppDomainManagedObject); - return vmObj; + HRESULT hr = S_OK; + EX_TRY + { + + AppDomain* pAppDomain = vmAppDomain.GetDacPtr(); + OBJECTHANDLE hAppDomainManagedObject = pAppDomain->GetRawExposedObjectHandleForDebugger(); + VMPTR_OBJECTHANDLE vmObj = VMPTR_OBJECTHANDLE::NullPtr(); + vmObj.SetDacTargetPtr(hAppDomainManagedObject); + *pRetVal = vmObj; + } + EX_CATCH_HRESULT(hr); + return hr; } // Get the full AD friendly name for the given EE AppDomain. -void DacDbiInterfaceImpl::GetAppDomainFullName( - VMPTR_AppDomain vmAppDomain, - IStringHolder * pStrName ) +HRESULT DacDbiInterfaceImpl::GetAppDomainFullName(VMPTR_AppDomain vmAppDomain, IStringHolder * pStrName) { DD_ENTER_MAY_THROW; - AppDomain * pAppDomain = vmAppDomain.GetDacPtr(); - // Get the AppDomain name from the VM without changing anything - IfFailThrow(pStrName->AssignCopy(pAppDomain->GetFriendlyName())); + HRESULT hr = S_OK; + EX_TRY + { + AppDomain * pAppDomain = vmAppDomain.GetDacPtr(); + + // Get the AppDomain name from the VM without changing anything + IfFailThrow(pStrName->AssignCopy(pAppDomain->GetFriendlyName())); + } + EX_CATCH_HRESULT(hr); + return hr; } //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -649,27 +715,31 @@ void DacDbiInterfaceImpl::GetAppDomainFullName( //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Get the values of the JIT Optimization and EnC flags. -void DacDbiInterfaceImpl::GetCompilerFlags ( - VMPTR_DomainAssembly vmDomainAssembly, - BOOL *pfAllowJITOpts, - BOOL *pfEnableEnC) +HRESULT DacDbiInterfaceImpl::GetCompilerFlags(VMPTR_DomainAssembly vmDomainAssembly, OUT BOOL * pfAllowJITOpts, OUT BOOL * pfEnableEnC) { DD_ENTER_MAY_THROW; - DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); - - if (pDomainAssembly == NULL) + HRESULT hr = S_OK; + EX_TRY { - ThrowHR(E_FAIL); - } - // Get the underlying module - none of this is AppDomain specific - Module * pModule = pDomainAssembly->GetAssembly()->GetModule(); - *pfAllowJITOpts = !pModule->AreJITOptimizationsDisabled(); - *pfEnableEnC = pModule->IsEditAndContinueEnabled(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + + if (pDomainAssembly == NULL) + { + ThrowHR(E_FAIL); + } + + // Get the underlying module - none of this is AppDomain specific + Module * pModule = pDomainAssembly->GetAssembly()->GetModule(); + *pfAllowJITOpts = !pModule->AreJITOptimizationsDisabled(); + *pfEnableEnC = pModule->IsEditAndContinueEnabled(); -} //GetCompilerFlags + } + EX_CATCH_HRESULT(hr); + return hr; +} //----------------------------------------------------------------------------- // Helper function for SetCompilerFlags to set EnC status. @@ -760,27 +830,30 @@ HRESULT DacDbiInterfaceImpl::SetCompilerFlags(VMPTR_DomainAssembly vmDomainAssem //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Initialize the native/IL sequence points and native var info for a function. -void DacDbiInterfaceImpl::GetNativeCodeSequencePointsAndVarInfo(VMPTR_MethodDesc vmMethodDesc, - CORDB_ADDRESS startAddr, - BOOL fCodeAvailable, - NativeVarData * pNativeVarData, - SequencePoints * pSequencePoints) +HRESULT DacDbiInterfaceImpl::GetNativeCodeSequencePointsAndVarInfo(VMPTR_MethodDesc vmMethodDesc, CORDB_ADDRESS startAddress, BOOL fCodeAvailable, OUT NativeVarData * pNativeVarData, OUT SequencePoints * pSequencePoints) { DD_ENTER_MAY_THROW; - _ASSERTE(!vmMethodDesc.IsNull()); + HRESULT hr = S_OK; + EX_TRY + { + + _ASSERTE(!vmMethodDesc.IsNull()); - MethodDesc * pMD = vmMethodDesc.GetDacPtr(); + MethodDesc * pMD = vmMethodDesc.GetDacPtr(); - _ASSERTE(fCodeAvailable != 0); + _ASSERTE(fCodeAvailable != 0); - // get information about the locations of arguments and local variables - GetNativeVarData(pMD, startAddr, GetArgCount(pMD), pNativeVarData); + // get information about the locations of arguments and local variables + GetNativeVarData(pMD, startAddress, GetArgCount(pMD), pNativeVarData); - // get the sequence points - GetSequencePoints(pMD, startAddr, pSequencePoints); + // get the sequence points + GetSequencePoints(pMD, startAddress, pSequencePoints); -} // GetNativeCodeSequencePointsAndVarInfo + } + EX_CATCH_HRESULT(hr); + return hr; +} //----------------------------------------------------------------------------- // Get the number of fixed arguments to a function, i.e., the explicit args and the "this" pointer. @@ -946,61 +1019,65 @@ void DacDbiInterfaceImpl::GetSequencePoints(MethodDesc * pMethodDesc, // a module and a token. The info will come from a MethodDesc, if // one exists or from metadata. // -void DacDbiInterfaceImpl::GetILCodeAndSig(VMPTR_DomainAssembly vmDomainAssembly, - mdToken functionToken, - TargetBuffer * pCodeInfo, - mdToken * pLocalSigToken) +HRESULT DacDbiInterfaceImpl::GetILCodeAndSig(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, OUT TargetBuffer * pCodeInfo, OUT mdToken * pLocalSigToken) { DD_ENTER_MAY_THROW; - DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); - Module * pModule = pDomainAssembly->GetAssembly()->GetModule(); - RVA methodRVA = 0; - DWORD implFlags; + HRESULT hr = S_OK; + EX_TRY + { - // preinitialize out params - pCodeInfo->Clear(); - *pLocalSigToken = mdSignatureNil; + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetAssembly()->GetModule(); + RVA methodRVA = 0; + DWORD implFlags; - // Get the RVA and impl flags for this method. - IfFailThrow(pModule->GetMDImport()->GetMethodImplProps(functionToken, - &methodRVA, - &implFlags)); + // preinitialize out params + pCodeInfo->Clear(); + *pLocalSigToken = mdSignatureNil; - MethodDesc* pMethodDesc = - FindLoadedMethodRefOrDef(pModule, functionToken); + // Get the RVA and impl flags for this method. + IfFailThrow(pModule->GetMDImport()->GetMethodImplProps(functionToken, + &methodRVA, + &implFlags)); - // If the RVA is 0 or it's native, then the method is not IL - if (methodRVA == 0) - { - LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: Function is not IL - methodRVA == NULL!\n")); - // return (CORDBG_E_FUNCTION_NOT_IL); - // Sanity check this.... + MethodDesc* pMethodDesc = + FindLoadedMethodRefOrDef(pModule, functionToken); - if(!pMethodDesc || !pMethodDesc->IsIL()) - { - LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: And the MD agrees..\n")); - ThrowHR(CORDBG_E_FUNCTION_NOT_IL); - } - else + // If the RVA is 0 or it's native, then the method is not IL + if (methodRVA == 0) { - LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: But the MD says it's IL..\n")); - } + LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: Function is not IL - methodRVA == NULL!\n")); + // return (CORDBG_E_FUNCTION_NOT_IL); + // Sanity check this.... + + if(!pMethodDesc || !pMethodDesc->IsIL()) + { + LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: And the MD agrees..\n")); + ThrowHR(CORDBG_E_FUNCTION_NOT_IL); + } + else + { + LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: But the MD says it's IL..\n")); + } - if (pMethodDesc != NULL && pMethodDesc->GetRVA() == 0) + if (pMethodDesc != NULL && pMethodDesc->GetRVA() == 0) + { + LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: Actually, MD says RVA is 0 too - keep going...!\n")); + } + } + if (IsMiNative(implFlags)) { - LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: Actually, MD says RVA is 0 too - keep going...!\n")); + LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: Function is not IL - IsMiNative!\n")); + ThrowHR(CORDBG_E_FUNCTION_NOT_IL); } - } - if (IsMiNative(implFlags)) - { - LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: Function is not IL - IsMiNative!\n")); - ThrowHR(CORDBG_E_FUNCTION_NOT_IL); - } - *pLocalSigToken = GetILCodeAndSigHelper(pModule, pMethodDesc, functionToken, methodRVA, pCodeInfo); + *pLocalSigToken = GetILCodeAndSigHelper(pModule, pMethodDesc, functionToken, methodRVA, pCodeInfo); -} // GetILCodeAndSig + } + EX_CATCH_HRESULT(hr); + return hr; +} #ifdef _MSC_VER #pragma optimize("", on) @@ -1089,32 +1166,40 @@ mdSignature DacDbiInterfaceImpl::GetILCodeAndSigHelper(Module * pModule, } -bool DacDbiInterfaceImpl::GetMetaDataFileInfoFromPEFile(VMPTR_PEAssembly vmPEAssembly, - DWORD &dwTimeStamp, - DWORD &dwSize, - IStringHolder* pStrFilename) +HRESULT DacDbiInterfaceImpl::GetMetaDataFileInfoFromPEFile(VMPTR_PEAssembly vmPEAssembly, DWORD & dwTimeStamp, DWORD & dwImageSize, IStringHolder* pStrFilename, OUT bool * pResult) { DD_ENTER_MAY_THROW; - DWORD dwDataSize; - DWORD dwRvaHint; - PEAssembly * pPEAssembly = vmPEAssembly.GetDacPtr(); - _ASSERTE(pPEAssembly != NULL); - if (pPEAssembly == NULL) - return false; + HRESULT hr = S_OK; + EX_TRY + { - WCHAR wszFilePath[MAX_LONGPATH] = {0}; - DWORD cchFilePath = MAX_LONGPATH; - bool ret = ClrDataAccess::GetMetaDataFileInfoFromPEFile(pPEAssembly, - dwTimeStamp, - dwSize, - dwDataSize, - dwRvaHint, - wszFilePath, - cchFilePath); - - pStrFilename->AssignCopy(wszFilePath); - return ret; + DWORD dwDataSize; + DWORD dwRvaHint; + PEAssembly * pPEAssembly = vmPEAssembly.GetDacPtr(); + _ASSERTE(pPEAssembly != NULL); + if (pPEAssembly == NULL) + { + *pResult = false; + } + else + { + WCHAR wszFilePath[MAX_LONGPATH] = {0}; + DWORD cchFilePath = MAX_LONGPATH; + bool ret = ClrDataAccess::GetMetaDataFileInfoFromPEFile(pPEAssembly, + dwTimeStamp, + dwImageSize, + dwDataSize, + dwRvaHint, + wszFilePath, + cchFilePath); + + pStrFilename->AssignCopy(wszFilePath); + *pResult = ret; + } + } + EX_CATCH_HRESULT(hr); + return hr; } // Get start addresses and sizes for hot and cold regions for a native code blob. @@ -1172,39 +1257,44 @@ void DacDbiInterfaceImpl::GetMethodRegionInfo(MethodDesc * pMethodDe // isn't currently available. In this case, all values in pCodeInfo will be // cleared. -void DacDbiInterfaceImpl::GetNativeCodeInfo(VMPTR_DomainAssembly vmDomainAssembly, - mdToken functionToken, - NativeCodeFunctionData * pCodeInfo) +HRESULT DacDbiInterfaceImpl::GetNativeCodeInfo(VMPTR_DomainAssembly vmDomainAssembly, mdToken functionToken, OUT NativeCodeFunctionData * pCodeInfo) { DD_ENTER_MAY_THROW; - _ASSERTE(pCodeInfo != NULL); + HRESULT hr = S_OK; + EX_TRY + { - // pre-initialize: - pCodeInfo->Clear(); + _ASSERTE(pCodeInfo != NULL); - DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); - Module * pModule = pDomainAssembly->GetAssembly()->GetModule(); + // pre-initialize: + pCodeInfo->Clear(); - MethodDesc* pMethodDesc = FindLoadedMethodRefOrDef(pModule, functionToken); - pCodeInfo->vmNativeCodeMethodDescToken.SetHostPtr(pMethodDesc); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + Module * pModule = pDomainAssembly->GetAssembly()->GetModule(); - // if we are loading a module and trying to bind a previously set breakpoint, we may not have - // a method desc yet, so check for that situation - if(pMethodDesc != NULL) - { - GetMethodRegionInfo(pMethodDesc, pCodeInfo); - if (pCodeInfo->m_rgCodeRegions[kHot].pAddress != (CORDB_ADDRESS)NULL) + MethodDesc* pMethodDesc = FindLoadedMethodRefOrDef(pModule, functionToken); + pCodeInfo->vmNativeCodeMethodDescToken.SetHostPtr(pMethodDesc); + + // if we are loading a module and trying to bind a previously set breakpoint, we may not have + // a method desc yet, so check for that situation + if(pMethodDesc != NULL) { - pCodeInfo->isInstantiatedGeneric = pMethodDesc->HasClassOrMethodInstantiation(); - LookupEnCVersions(pModule, - pCodeInfo->vmNativeCodeMethodDescToken, - functionToken, - pCodeInfo->m_rgCodeRegions[kHot].pAddress, - &(pCodeInfo->encVersion)); + GetMethodRegionInfo(pMethodDesc, pCodeInfo); + if (pCodeInfo->m_rgCodeRegions[kHot].pAddress != (CORDB_ADDRESS)NULL) + { + pCodeInfo->isInstantiatedGeneric = pMethodDesc->HasClassOrMethodInstantiation(); + LookupEnCVersions(pModule, + pCodeInfo->vmNativeCodeMethodDescToken, + functionToken, + pCodeInfo->m_rgCodeRegions[kHot].pAddress, + &(pCodeInfo->encVersion)); + } } } -} // GetNativeCodeInfo + EX_CATCH_HRESULT(hr); + return hr; +} // Gets the following information about a native code blob: // - its method desc @@ -1213,88 +1303,92 @@ void DacDbiInterfaceImpl::GetNativeCodeInfo(VMPTR_DomainAssembly vmDomai // - hot and cold region information // - its module // - its metadata token. -void DacDbiInterfaceImpl::GetNativeCodeInfoForAddr(CORDB_ADDRESS codeAddress, - NativeCodeFunctionData * pCodeInfo, - VMPTR_Module * pVmModule, - mdToken * pFunctionToken) +HRESULT DacDbiInterfaceImpl::GetNativeCodeInfoForAddr(CORDB_ADDRESS codeAddress, NativeCodeFunctionData * pCodeInfo, VMPTR_Module * pVmModule, mdToken * pFunctionToken) { DD_ENTER_MAY_THROW; - _ASSERTE(pCodeInfo != NULL); - - if (codeAddress == (CORDB_ADDRESS)NULL) + HRESULT hr = S_OK; + EX_TRY { - // if the start address is NULL, the code isn't available yet, so just return - _ASSERTE(!pCodeInfo->IsValid()); - return; - } - IJitManager::MethodRegionInfo methodRegionInfo = {(TADDR)NULL, 0, (TADDR)NULL, 0}; - TADDR codeAddr = CORDB_ADDRESS_TO_TADDR(codeAddress); + _ASSERTE(pCodeInfo != NULL); - EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY - { - codeAddr = GetInterpreterCodeFromInterpreterPrecodeIfPresent(codeAddr); - } - EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY; + if (codeAddress == (CORDB_ADDRESS)NULL) + { + // if the start address is NULL, the code isn't available yet, so just return + _ASSERTE(!pCodeInfo->IsValid()); + return S_OK; + } -#ifdef TARGET_ARM - // TADDR should not have the thumb code bit set. - _ASSERTE((codeAddr & THUMB_CODE) == 0); - codeAddr &= ~THUMB_CODE; -#endif + IJitManager::MethodRegionInfo methodRegionInfo = {(TADDR)NULL, 0, (TADDR)NULL, 0}; + TADDR codeAddr = CORDB_ADDRESS_TO_TADDR(codeAddress); - EECodeInfo codeInfo(codeAddr); - _ASSERTE(codeInfo.IsValid()); + EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY + { + codeAddr = GetInterpreterCodeFromInterpreterPrecodeIfPresent(codeAddr); + } + EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY; - TADDR codeStartAddr = codeInfo.GetStartAddress(); + #ifdef TARGET_ARM + // TADDR should not have the thumb code bit set. + _ASSERTE((codeAddr & THUMB_CODE) == 0); + codeAddr &= ~THUMB_CODE; + #endif - // We may not have the memory for the cold code region in a minidump. - // Do not fail stackwalking because of this. - EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY - { - codeInfo.GetMethodRegionInfo(&methodRegionInfo); - } - EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY; + EECodeInfo codeInfo(codeAddr); + _ASSERTE(codeInfo.IsValid()); - // Even if GetMethodRegionInfo() fails to retrieve the cold code region info, - // we should still be able to get the hot code region info. We are counting on this for - // stackwalking to work in dump debugging scenarios. - _ASSERTE(methodRegionInfo.hotStartAddress == codeStartAddr); + TADDR codeStartAddr = codeInfo.GetStartAddress(); - // now get the rest of the region information - pCodeInfo->m_rgCodeRegions[kHot].Init(PCODEToPINSTR(methodRegionInfo.hotStartAddress), - (ULONG)methodRegionInfo.hotSize); - pCodeInfo->m_rgCodeRegions[kCold].Init(PCODEToPINSTR(methodRegionInfo.coldStartAddress), - (ULONG)methodRegionInfo.coldSize); - _ASSERTE(pCodeInfo->IsValid()); + // We may not have the memory for the cold code region in a minidump. + // Do not fail stackwalking because of this. + EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY + { + codeInfo.GetMethodRegionInfo(&methodRegionInfo); + } + EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY; - VMPTR_MethodDesc vmMethodDesc; - vmMethodDesc.SetHostPtr(codeInfo.GetMethodDesc()); - MethodDesc* pMethodDesc = vmMethodDesc.GetDacPtr(); - pCodeInfo->isInstantiatedGeneric = pMethodDesc->HasClassOrMethodInstantiation(); - pCodeInfo->vmNativeCodeMethodDescToken = vmMethodDesc; + // Even if GetMethodRegionInfo() fails to retrieve the cold code region info, + // we should still be able to get the hot code region info. We are counting on this for + // stackwalking to work in dump debugging scenarios. + _ASSERTE(methodRegionInfo.hotStartAddress == codeStartAddr); - SIZE_T unusedLatestEncVersion; - Module * pModule = pMethodDesc->GetModule(); - _ASSERTE(pModule != NULL); - LookupEnCVersions(pModule, - vmMethodDesc, - pMethodDesc->GetMemberDef(), - codeStartAddr, - &unusedLatestEncVersion, //unused by caller - &(pCodeInfo->encVersion)); + // now get the rest of the region information + pCodeInfo->m_rgCodeRegions[kHot].Init(PCODEToPINSTR(methodRegionInfo.hotStartAddress), + (ULONG)methodRegionInfo.hotSize); + pCodeInfo->m_rgCodeRegions[kCold].Init(PCODEToPINSTR(methodRegionInfo.coldStartAddress), + (ULONG)methodRegionInfo.coldSize); + _ASSERTE(pCodeInfo->IsValid()); - if (pVmModule != NULL) - { - pVmModule->SetDacTargetPtr(dac_cast(pModule)); - } + VMPTR_MethodDesc vmMethodDesc; + vmMethodDesc.SetHostPtr(codeInfo.GetMethodDesc()); + MethodDesc* pMethodDesc = vmMethodDesc.GetDacPtr(); + pCodeInfo->isInstantiatedGeneric = pMethodDesc->HasClassOrMethodInstantiation(); + pCodeInfo->vmNativeCodeMethodDescToken = vmMethodDesc; + + SIZE_T unusedLatestEncVersion; + Module * pModule = pMethodDesc->GetModule(); + _ASSERTE(pModule != NULL); + LookupEnCVersions(pModule, + vmMethodDesc, + pMethodDesc->GetMemberDef(), + codeStartAddr, + &unusedLatestEncVersion, //unused by caller + &(pCodeInfo->encVersion)); + + if (pVmModule != NULL) + { + pVmModule->SetDacTargetPtr(dac_cast(pModule)); + } - if (pFunctionToken != NULL) - { - *pFunctionToken = pMethodDesc->GetMemberDef(); + if (pFunctionToken != NULL) + { + *pFunctionToken = pMethodDesc->GetMemberDef(); + } } -} // GetNativeCodeInfo + EX_CATCH_HRESULT(hr); + return hr; +} //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1575,69 +1669,91 @@ void DacDbiInterfaceImpl::CollectFields(TypeHandle thExact, // Determine if a type is a ValueType -BOOL DacDbiInterfaceImpl::IsValueType (VMPTR_TypeHandle vmTypeHandle) +HRESULT DacDbiInterfaceImpl::IsValueType(VMPTR_TypeHandle th, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - TypeHandle th = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr()); - return th.IsValueType(); + HRESULT hr = S_OK; + EX_TRY + { + + TypeHandle typeHandle = TypeHandle::FromPtr(th.GetDacPtr()); + *pResult = typeHandle.IsValueType(); + } + EX_CATCH_HRESULT(hr); + return hr; } // Determine if a type has generic parameters -BOOL DacDbiInterfaceImpl::HasTypeParams (VMPTR_TypeHandle vmTypeHandle) +HRESULT DacDbiInterfaceImpl::HasTypeParams(VMPTR_TypeHandle th, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - TypeHandle th = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr()); - return th.ContainsGenericVariables(); + HRESULT hr = S_OK; + EX_TRY + { + + TypeHandle typeHandle = TypeHandle::FromPtr(th.GetDacPtr()); + *pResult = typeHandle.ContainsGenericVariables(); + } + EX_CATCH_HRESULT(hr); + return hr; } // DacDbi API: Get type information for a class -void DacDbiInterfaceImpl::GetClassInfo(VMPTR_AppDomain vmAppDomain, - VMPTR_TypeHandle vmThExact, - ClassInfo * pData) +HRESULT DacDbiInterfaceImpl::GetClassInfo(VMPTR_AppDomain vmAppDomain, VMPTR_TypeHandle thExact, ClassInfo * pData) { DD_ENTER_MAY_THROW; - AppDomain * pAppDomain = vmAppDomain.GetDacPtr(); + HRESULT hr = S_OK; + EX_TRY + { + + AppDomain * pAppDomain = vmAppDomain.GetDacPtr(); - TypeHandle thExact; - TypeHandle thApprox; + TypeHandle typeHandleExact; + TypeHandle thApprox; - GetTypeHandles(vmThExact, vmThExact, &thExact, &thApprox); + GetTypeHandles(thExact, thExact, &typeHandleExact, &thApprox); - // initialize field count, generic args count, size and value class flag - InitClassData(thApprox, false, pData); + // initialize field count, generic args count, size and value class flag + InitClassData(thApprox, false, pData); - if (pAppDomain != NULL) - CollectFields(thExact, thApprox, pAppDomain, &(pData->m_fieldList)); -} // DacDbiInterfaceImpl::GetClassInfo + if (pAppDomain != NULL) + CollectFields(typeHandleExact, thApprox, pAppDomain, &(pData->m_fieldList)); + } + EX_CATCH_HRESULT(hr); + return hr; +} // DacDbi API: Get field information and object size for an instantiated generic type -void DacDbiInterfaceImpl::GetInstantiationFieldInfo (VMPTR_DomainAssembly vmDomainAssembly, - VMPTR_TypeHandle vmThExact, - VMPTR_TypeHandle vmThApprox, - DacDbiArrayList * pFieldList, - SIZE_T * pObjectSize) +HRESULT DacDbiInterfaceImpl::GetInstantiationFieldInfo(VMPTR_DomainAssembly vmDomainAssembly, VMPTR_TypeHandle vmThExact, VMPTR_TypeHandle vmThApprox, OUT DacDbiArrayList * pFieldList, OUT SIZE_T * pObjectSize) { DD_ENTER_MAY_THROW; - TypeHandle thExact; - TypeHandle thApprox; - - GetTypeHandles(vmThExact, vmThApprox, &thExact, &thApprox); + HRESULT hr = S_OK; + EX_TRY + { - *pObjectSize = thApprox.GetMethodTable()->GetNumInstanceFieldBytes(); + TypeHandle thExact; + TypeHandle thApprox; - pFieldList->Alloc(GetTotalFieldCount(thApprox)); + GetTypeHandles(vmThExact, vmThApprox, &thExact, &thApprox); - CollectFields(thExact, thApprox, AppDomain::GetCurrentDomain(), pFieldList); + *pObjectSize = thApprox.GetMethodTable()->GetNumInstanceFieldBytes(); -} // DacDbiInterfaceImpl::GetInstantiationFieldInfo + pFieldList->Alloc(GetTotalFieldCount(thApprox)); -//----------------------------------------------------------------------------------- -// DacDbiInterfaceImpl::TypeDataWalk member functions -//----------------------------------------------------------------------------------- + CollectFields(thExact, thApprox, AppDomain::GetCurrentDomain(), pFieldList); + + } + EX_CATCH_HRESULT(hr); + return hr; +} + +//----------------------------------------------------------------------------------- +// DacDbiInterfaceImpl::TypeDataWalk member functions +//----------------------------------------------------------------------------------- //----------------------------------------------------------------------------- // TypeDataWalk constructor--initialize the buffer and number of remaining items from input data @@ -2462,38 +2578,50 @@ void DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo(TypeHandle } // DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo -void DacDbiInterfaceImpl::GetObjectExpandedTypeInfoFromID(AreValueTypesBoxed boxed, - VMPTR_AppDomain vmAppDomain, - COR_TYPEID id, - DebuggerIPCE_ExpandedTypeData *pTypeInfo) +HRESULT DacDbiInterfaceImpl::GetObjectExpandedTypeInfoFromID(AreValueTypesBoxed boxed, VMPTR_AppDomain vmAppDomain, COR_TYPEID id, OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo) { DD_ENTER_MAY_THROW; - TypeHandleToExpandedTypeInfoImpl(boxed, vmAppDomain, TypeHandle::FromPtr(TO_TADDR(id.token1)), pTypeInfo); + HRESULT hr = S_OK; + EX_TRY + { + + TypeHandleToExpandedTypeInfoImpl(boxed, vmAppDomain, TypeHandle::FromPtr(TO_TADDR(id.token1)), pTypeInfo); + } + EX_CATCH_HRESULT(hr); + return hr; } -void DacDbiInterfaceImpl::GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed, - VMPTR_AppDomain vmAppDomain, - CORDB_ADDRESS addr, - DebuggerIPCE_ExpandedTypeData *pTypeInfo) +HRESULT DacDbiInterfaceImpl::GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed, VMPTR_AppDomain vmAppDomain, CORDB_ADDRESS addr, OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo) { DD_ENTER_MAY_THROW; - PTR_Object obj(TO_TADDR(addr)); - TypeHandleToExpandedTypeInfoImpl(boxed, vmAppDomain, obj->GetGCSafeTypeHandle(), pTypeInfo); + HRESULT hr = S_OK; + EX_TRY + { + + PTR_Object obj(TO_TADDR(addr)); + TypeHandleToExpandedTypeInfoImpl(boxed, vmAppDomain, obj->GetGCSafeTypeHandle(), pTypeInfo); + } + EX_CATCH_HRESULT(hr); + return hr; } // DacDbi API: use a type handle to get the information needed to create the corresponding RS CordbType instance -void DacDbiInterfaceImpl::TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, - VMPTR_AppDomain vmAppDomain, - VMPTR_TypeHandle vmTypeHandle, - DebuggerIPCE_ExpandedTypeData * pTypeInfo) +HRESULT DacDbiInterfaceImpl::TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, VMPTR_AppDomain vmAppDomain, VMPTR_TypeHandle vmTypeHandle, DebuggerIPCE_ExpandedTypeData * pTypeInfo) { DD_ENTER_MAY_THROW; + HRESULT hr = S_OK; + EX_TRY + { + - TypeHandle typeHandle = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr()); - TypeHandleToExpandedTypeInfoImpl(boxed, vmAppDomain, typeHandle, pTypeInfo); + TypeHandle typeHandle = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr()); + TypeHandleToExpandedTypeInfoImpl(boxed, vmAppDomain, typeHandle, pTypeInfo); + } + EX_CATCH_HRESULT(hr); + return hr; } @@ -2546,52 +2674,65 @@ void DacDbiInterfaceImpl::TypeHandleToExpandedTypeInfoImpl(AreValueTypesBoxed } // DacDbiInterfaceImpl::TypeHandleToExpandedTypeInfo // Get type handle for a TypeDef token, if one exists. For generics this returns the open type. -VMPTR_TypeHandle DacDbiInterfaceImpl::GetTypeHandle(VMPTR_Module vmModule, - mdTypeDef metadataToken) +HRESULT DacDbiInterfaceImpl::GetTypeHandle(VMPTR_Module vmModule, mdTypeDef metadataToken, OUT VMPTR_TypeHandle * pRetVal) { DD_ENTER_MAY_THROW; - Module* pModule = vmModule.GetDacPtr(); - VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr(); - TypeHandle th = ClassLoader::LookupTypeDefOrRefInModule(pModule, metadataToken); - if (th.IsNull()) + HRESULT hr = S_OK; + EX_TRY { - LOG((LF_CORDB, LL_INFO10000, "D::GTH: class isn't loaded.\n")); - ThrowHR(CORDBG_E_CLASS_NOT_LOADED); - } + Module* pModule = vmModule.GetDacPtr(); + VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr(); + + TypeHandle th = ClassLoader::LookupTypeDefOrRefInModule(pModule, metadataToken); + if (th.IsNull()) + { + LOG((LF_CORDB, LL_INFO10000, "D::GTH: class isn't loaded.\n")); + ThrowHR(CORDBG_E_CLASS_NOT_LOADED); + } - vmTypeHandle.SetDacTargetPtr(th.AsTAddr()); - return vmTypeHandle; + vmTypeHandle.SetDacTargetPtr(th.AsTAddr()); + *pRetVal = vmTypeHandle; + } + EX_CATCH_HRESULT(hr); + return hr; } // DacDbi API: GetAndSendApproxTypeHandle finds the type handle for the layout of the instance fields of an // instantiated type if it is available. -VMPTR_TypeHandle DacDbiInterfaceImpl::GetApproxTypeHandle(TypeInfoList * pTypeData) +HRESULT DacDbiInterfaceImpl::GetApproxTypeHandle(TypeInfoList * pTypeData, OUT VMPTR_TypeHandle * pRetVal) { DD_ENTER_MAY_THROW; - LOG((LF_CORDB, LL_INFO10000, "D::GATH: getting info.\n")); + HRESULT hr = S_OK; + EX_TRY + { + LOG((LF_CORDB, LL_INFO10000, "D::GATH: getting info.\n")); - TypeDataWalk walk(&((*pTypeData)[0]), pTypeData->Count()); - TypeHandle typeHandle = walk.ReadLoadedTypeHandle(TypeDataWalk::kGetCanonical); - VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr(); - vmTypeHandle.SetDacTargetPtr(typeHandle.AsTAddr()); - if (!typeHandle.IsNull()) - { + TypeDataWalk walk(&((*pTypeData)[0]), pTypeData->Count()); + TypeHandle typeHandle = walk.ReadLoadedTypeHandle(TypeDataWalk::kGetCanonical); + VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr(); + vmTypeHandle.SetDacTargetPtr(typeHandle.AsTAddr()); - } - else - { - ThrowHR(CORDBG_E_CLASS_NOT_LOADED); - } + if (!typeHandle.IsNull()) + { + vmTypeHandle.SetDacTargetPtr(typeHandle.AsTAddr()); + } + else + { + ThrowHR(CORDBG_E_CLASS_NOT_LOADED); + } - LOG((LF_CORDB, LL_INFO10000, - "D::GATH: sending result, result = 0x%0x8\n", - typeHandle)); - return vmTypeHandle; -} // DacDbiInterfaceImpl::GetApproxTypeHandle + LOG((LF_CORDB, LL_INFO10000, + "D::GATH: sending result, result = 0x%0x8\n", + typeHandle)); + *pRetVal = vmTypeHandle; + } + EX_CATCH_HRESULT(hr); + return hr; +} // DacDbiInterface API: Get the exact type handle from type data HRESULT DacDbiInterfaceImpl::GetExactTypeHandle(DebuggerIPCE_ExpandedTypeData * pTypeData, @@ -2620,106 +2761,108 @@ HRESULT DacDbiInterfaceImpl::GetExactTypeHandle(DebuggerIPCE_ExpandedTypeData * // Retrieve the generic type params for a given MethodDesc. This function is specifically // for stackwalking because it requires the generic type token on the stack. -void DacDbiInterfaceImpl::GetMethodDescParams( - VMPTR_AppDomain vmAppDomain, - VMPTR_MethodDesc vmMethodDesc, - GENERICS_TYPE_TOKEN genericsToken, - UINT32 * pcGenericClassTypeParams, - TypeParamsList * pGenericTypeParams) +HRESULT DacDbiInterfaceImpl::GetMethodDescParams(VMPTR_AppDomain vmAppDomain, VMPTR_MethodDesc vmMethodDesc, GENERICS_TYPE_TOKEN genericsToken, OUT UINT32 * pcGenericClassTypeParams, OUT TypeParamsList * pGenericTypeParams) { DD_ENTER_MAY_THROW; - if (vmAppDomain.IsNull() || vmMethodDesc.IsNull()) + HRESULT hr = S_OK; + EX_TRY { - ThrowHR(E_INVALIDARG); - } - - _ASSERTE((pcGenericClassTypeParams != NULL) && (pGenericTypeParams != NULL)); - - MethodDesc * pMD = vmMethodDesc.GetDacPtr(); - // Retrieve the number of type parameters for the class and - // the number of type parameters for the method itself. - // For example, the method Foo::Bar() has 2 class type parameters and 1 method type parameters. - UINT32 cGenericClassTypeParams = pMD->GetNumGenericClassArgs(); - UINT32 cGenericMethodTypeParams = pMD->GetNumGenericMethodArgs(); - UINT32 cTotalGenericTypeParams = cGenericClassTypeParams + cGenericMethodTypeParams; - - // Set the out parameter. - *pcGenericClassTypeParams = cGenericClassTypeParams; - - TypeHandle thSpecificClass; - MethodDesc * pSpecificMethod = NULL; + if (vmAppDomain.IsNull() || vmMethodDesc.IsNull()) + { + ThrowHR(E_INVALIDARG); + } - // Try to retrieve a more specific MethodDesc and TypeHandle via the generics type token. - // The generics token is not always guaranteed to be available. - // For example, it may be unavailable in prologs and epilogs. - // In dumps, not available can also mean a thrown exception for missing memory. - BOOL fExact = FALSE; - ALLOW_DATATARGET_MISSING_MEMORY( - fExact = Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation( - pMD, - PTR_VOID((TADDR)genericsToken), - &thSpecificClass, - &pSpecificMethod); - ); - if (!fExact || - !thSpecificClass.GetMethodTable()->SanityCheck() || - !pSpecificMethod->GetMethodTable()->SanityCheck()) - { - // Use the canonical MethodTable and MethodDesc if the exact generics token is not available. - thSpecificClass = TypeHandle(pMD->GetMethodTable()); - pSpecificMethod = pMD; - } + _ASSERTE((pcGenericClassTypeParams != NULL) && (pGenericTypeParams != NULL)); + + MethodDesc * pMD = vmMethodDesc.GetDacPtr(); + + // Retrieve the number of type parameters for the class and + // the number of type parameters for the method itself. + // For example, the method Foo::Bar() has 2 class type parameters and 1 method type parameters. + UINT32 cGenericClassTypeParams = pMD->GetNumGenericClassArgs(); + UINT32 cGenericMethodTypeParams = pMD->GetNumGenericMethodArgs(); + UINT32 cTotalGenericTypeParams = cGenericClassTypeParams + cGenericMethodTypeParams; + + // Set the out parameter. + *pcGenericClassTypeParams = cGenericClassTypeParams; + + TypeHandle thSpecificClass; + MethodDesc * pSpecificMethod = NULL; + + // Try to retrieve a more specific MethodDesc and TypeHandle via the generics type token. + // The generics token is not always guaranteed to be available. + // For example, it may be unavailable in prologs and epilogs. + // In dumps, not available can also mean a thrown exception for missing memory. + BOOL fExact = FALSE; + ALLOW_DATATARGET_MISSING_MEMORY( + fExact = Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation( + pMD, + PTR_VOID((TADDR)genericsToken), + &thSpecificClass, + &pSpecificMethod); + ); + if (!fExact || + !thSpecificClass.GetMethodTable()->SanityCheck() || + !pSpecificMethod->GetMethodTable()->SanityCheck()) + { + // Use the canonical MethodTable and MethodDesc if the exact generics token is not available. + thSpecificClass = TypeHandle(pMD->GetMethodTable()); + pSpecificMethod = pMD; + } - // Retrieve the array of class type parameters and the array of method type parameters. - Instantiation classInst = pSpecificMethod->GetExactClassInstantiation(thSpecificClass); - Instantiation methodInst = pSpecificMethod->GetMethodInstantiation(); + // Retrieve the array of class type parameters and the array of method type parameters. + Instantiation classInst = pSpecificMethod->GetExactClassInstantiation(thSpecificClass); + Instantiation methodInst = pSpecificMethod->GetMethodInstantiation(); - _ASSERTE((classInst.IsEmpty()) == (cGenericClassTypeParams == 0)); - _ASSERTE((methodInst.IsEmpty()) == (cGenericMethodTypeParams == 0)); + _ASSERTE((classInst.IsEmpty()) == (cGenericClassTypeParams == 0)); + _ASSERTE((methodInst.IsEmpty()) == (cGenericMethodTypeParams == 0)); - // allocate memory for the return array - pGenericTypeParams->Alloc(cTotalGenericTypeParams); + // allocate memory for the return array + pGenericTypeParams->Alloc(cTotalGenericTypeParams); - for (UINT32 i = 0; i < cTotalGenericTypeParams; i++) - { - // Retrieve the current type parameter depending on the index. - TypeHandle thCurrent; - if (i < cGenericClassTypeParams) - { - thCurrent = classInst[i]; - } - else + for (UINT32 i = 0; i < cTotalGenericTypeParams; i++) { - thCurrent = methodInst[i - cGenericClassTypeParams]; - } + // Retrieve the current type parameter depending on the index. + TypeHandle thCurrent; + if (i < cGenericClassTypeParams) + { + thCurrent = classInst[i]; + } + else + { + thCurrent = methodInst[i - cGenericClassTypeParams]; + } - // There is the possibility that we'll get this far with a dump and not fail, but still - // not be able to get full info for a particular param. - EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER - { - // Fill in the struct using the TypeHandle of the current type parameter if we can. - VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr(); - vmTypeHandle.SetDacTargetPtr(thCurrent.AsTAddr()); - TypeHandleToExpandedTypeInfo(NoValueTypeBoxing, - vmAppDomain, - vmTypeHandle, - &((*pGenericTypeParams)[i])); - } - EX_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER - { - // On failure for a particular type, default it back to System.__Canon. - VMPTR_TypeHandle vmTHCanon = VMPTR_TypeHandle::NullPtr(); - TypeHandle thCanon = TypeHandle(g_pCanonMethodTableClass); - vmTHCanon.SetDacTargetPtr(thCanon.AsTAddr()); - TypeHandleToExpandedTypeInfo(NoValueTypeBoxing, - vmAppDomain, - vmTHCanon, - &((*pGenericTypeParams)[i])); + // There is the possibility that we'll get this far with a dump and not fail, but still + // not be able to get full info for a particular param. + EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER + { + // Fill in the struct using the TypeHandle of the current type parameter if we can. + VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr(); + vmTypeHandle.SetDacTargetPtr(thCurrent.AsTAddr()); + TypeHandleToExpandedTypeInfo(NoValueTypeBoxing, + vmAppDomain, + vmTypeHandle, + &((*pGenericTypeParams)[i])); + } + EX_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER + { + // On failure for a particular type, default it back to System.__Canon. + VMPTR_TypeHandle vmTHCanon = VMPTR_TypeHandle::NullPtr(); + TypeHandle thCanon = TypeHandle(g_pCanonMethodTableClass); + vmTHCanon.SetDacTargetPtr(thCanon.AsTAddr()); + TypeHandleToExpandedTypeInfo(NoValueTypeBoxing, + vmAppDomain, + vmTHCanon, + &((*pGenericTypeParams)[i])); + } + EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER } - EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER } + EX_CATCH_HRESULT(hr); + return hr; } //----------------------------------------------------------------------------- @@ -3030,166 +3173,195 @@ TypeHandle DacDbiInterfaceImpl::ExpandedTypeInfoToTypeHandle(DebuggerIPCE_Expand // // This can commonly fail, in which case, it will return NULL. // ---------------------------------------------------------------------------- -CORDB_ADDRESS DacDbiInterfaceImpl::GetThreadStaticAddress(VMPTR_FieldDesc vmField, - VMPTR_Thread vmRuntimeThread) +HRESULT DacDbiInterfaceImpl::GetThreadStaticAddress(VMPTR_FieldDesc vmField, VMPTR_Thread vmRuntimeThread, OUT CORDB_ADDRESS * pRetVal) { DD_ENTER_MAY_THROW; - Thread * pRuntimeThread = vmRuntimeThread.GetDacPtr(); - PTR_FieldDesc pFieldDesc = vmField.GetDacPtr(); - TADDR fieldAddress = (TADDR)NULL; + HRESULT hr = S_OK; + EX_TRY + { - _ASSERTE(pRuntimeThread != NULL); + Thread * pRuntimeThread = vmRuntimeThread.GetDacPtr(); + PTR_FieldDesc pFieldDesc = vmField.GetDacPtr(); + TADDR fieldAddress = (TADDR)NULL; - // Find out whether the field is thread local and get its address. - if (pFieldDesc->IsThreadStatic()) - { - fieldAddress = pRuntimeThread->GetStaticFieldAddrNoCreate(pFieldDesc); - } - else - { - // In case we have more special cases added later, this will allow us to notice the need to - // update this function. - ThrowHR(E_NOTIMPL); - } - return fieldAddress; + _ASSERTE(pRuntimeThread != NULL); + + // Find out whether the field is thread local and get its address. + if (pFieldDesc->IsThreadStatic()) + { + fieldAddress = pRuntimeThread->GetStaticFieldAddrNoCreate(pFieldDesc); + } + else + { + // In case we have more special cases added later, this will allow us to notice the need to + // update this function. + ThrowHR(E_NOTIMPL); + } + *pRetVal = fieldAddress; -} // DacDbiInterfaceImpl::GetThreadStaticAddress + } + EX_CATCH_HRESULT(hr); + return hr; +} // Get the target field address of a collectible types static. -CORDB_ADDRESS DacDbiInterfaceImpl::GetCollectibleTypeStaticAddress(VMPTR_FieldDesc vmField, - VMPTR_AppDomain vmAppDomain) +HRESULT DacDbiInterfaceImpl::GetCollectibleTypeStaticAddress(VMPTR_FieldDesc vmField, VMPTR_AppDomain vmAppDomain, OUT CORDB_ADDRESS * pRetVal) { DD_ENTER_MAY_THROW; - AppDomain * pAppDomain = vmAppDomain.GetDacPtr(); - PTR_FieldDesc pFieldDesc = vmField.GetDacPtr(); - _ASSERTE(pAppDomain != NULL); - - // - // Verify this field is of the right type - // - if(!pFieldDesc->IsStatic() || - pFieldDesc->IsSpecialStatic()) + HRESULT hr = S_OK; + EX_TRY { - _ASSERTE(!"BUG: Unsupported static field type for collectible types"); - } - // - // Check that the data is available - // - /* TODO: Ideally we should be checking if the class is allocated first, however - we don't appear to be doing this even for non-collectible statics and - we have never seen an issue. - */ + AppDomain * pAppDomain = vmAppDomain.GetDacPtr(); + PTR_FieldDesc pFieldDesc = vmField.GetDacPtr(); + _ASSERTE(pAppDomain != NULL); - // - // Get the address - // - PTR_VOID base = pFieldDesc->GetBase(); - if (base == PTR_NULL) - { - return PTR_HOST_TO_TADDR(NULL); - } + // + // Verify this field is of the right type + // + if(!pFieldDesc->IsStatic() || + pFieldDesc->IsSpecialStatic()) + { + _ASSERTE(!"BUG: Unsupported static field type for collectible types"); + } - // - // Store the result and return - // - PTR_VOID addr = pFieldDesc->GetStaticAddressHandle(base); - return PTR_TO_TADDR(addr); + // + // Check that the data is available + // + /* TODO: Ideally we should be checking if the class is allocated first, however + we don't appear to be doing this even for non-collectible statics and + we have never seen an issue. + */ + + // + // Get the address + // + PTR_VOID base = pFieldDesc->GetBase(); + if (base == PTR_NULL) + { + *pRetVal = PTR_HOST_TO_TADDR(NULL); + } + else + { + // + // Store the result and return + // + PTR_VOID addr = pFieldDesc->GetStaticAddressHandle(base); + *pRetVal = PTR_TO_TADDR(addr); + } -} // DacDbiInterfaceImpl::GetCollectibleTypeStaticAddress + } + EX_CATCH_HRESULT(hr); + return hr; +} // DacDbi API: GetTypeHandleParams // - gets the necessary data for a type handle, i.e. its type parameters, e.g. "String" and "List" from the type handle // for "Dict>", and sends it back to the right side. // - pParams is allocated and initialized by this function // - This should not fail except for OOM -void DacDbiInterfaceImpl::GetTypeHandleParams(VMPTR_AppDomain vmAppDomain, - VMPTR_TypeHandle vmTypeHandle, - TypeParamsList * pParams) +HRESULT DacDbiInterfaceImpl::GetTypeHandleParams(VMPTR_AppDomain vmAppDomain, VMPTR_TypeHandle vmTypeHandle, OUT TypeParamsList * pParams) { DD_ENTER_MAY_THROW - TypeHandle typeHandle = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr()); - LOG((LF_CORDB, LL_INFO10000, "D::GTHP: getting type parameters for 0x%08x 0x%0x8.\n", - vmAppDomain.GetDacPtr(), typeHandle.AsPtr())); + HRESULT hr = S_OK; + EX_TRY + { + + TypeHandle typeHandle = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr()); + LOG((LF_CORDB, LL_INFO10000, "D::GTHP: getting type parameters for 0x%08x 0x%0x8.\n", + vmAppDomain.GetDacPtr(), typeHandle.AsPtr())); - // Find the class given its type handle. - _ASSERTE(pParams->IsEmpty()); - pParams->Alloc(typeHandle.GetNumGenericArgs()); + // Find the class given its type handle. + _ASSERTE(pParams->IsEmpty()); + pParams->Alloc(typeHandle.GetNumGenericArgs()); - // collect type information for each type parameter - for (unsigned int i = 0; i < pParams->Count(); ++i) - { - VMPTR_TypeHandle thInst = VMPTR_TypeHandle::NullPtr(); - thInst.SetDacTargetPtr(typeHandle.GetInstantiation()[i].AsTAddr()); + // collect type information for each type parameter + for (unsigned int i = 0; i < pParams->Count(); ++i) + { + VMPTR_TypeHandle thInst = VMPTR_TypeHandle::NullPtr(); + thInst.SetDacTargetPtr(typeHandle.GetInstantiation()[i].AsTAddr()); - TypeHandleToExpandedTypeInfo(NoValueTypeBoxing, - vmAppDomain, - thInst, - &((*pParams)[i])); - } + TypeHandleToExpandedTypeInfo(NoValueTypeBoxing, + vmAppDomain, + thInst, + &((*pParams)[i])); + } - LOG((LF_CORDB, LL_INFO10000, "D::GTHP: sending result")); -} // DacDbiInterfaceImpl::GetTypeHandleParams + LOG((LF_CORDB, LL_INFO10000, "D::GTHP: sending result")); + } + EX_CATCH_HRESULT(hr); + return hr; +} //----------------------------------------------------------------------------- // DacDbi API: GetSimpleType // gets the metadata token and domain file corresponding to a simple type //----------------------------------------------------------------------------- -void DacDbiInterfaceImpl::GetSimpleType(VMPTR_AppDomain vmAppDomain, - CorElementType simpleType, - mdTypeDef *pMetadataToken, - VMPTR_Module *pVmModule, - VMPTR_DomainAssembly *pVmDomainAssembly) +HRESULT DacDbiInterfaceImpl::GetSimpleType(VMPTR_AppDomain vmAppDomain, CorElementType simpleType, OUT mdTypeDef * pMetadataToken, OUT VMPTR_Module * pVmModule, OUT VMPTR_DomainAssembly * pVmDomainAssembly) { DD_ENTER_MAY_THROW; - AppDomain *pAppDomain = vmAppDomain.GetDacPtr(); - - // if we fail to get either a valid type handle or module, we will want to send back - // a NULL domain file too, so we'll to preinitialize this here. - _ASSERTE(pVmDomainAssembly != NULL); - *pVmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); - // FindLoadedElementType will return NULL if the type hasn't been loaded yet. - TypeHandle typeHandle = FindLoadedElementType(simpleType); - - if (typeHandle.IsNull()) - { - ThrowHR(CORDBG_E_CLASS_NOT_LOADED); - } - else + HRESULT hr = S_OK; + EX_TRY { - _ASSERTE(pMetadataToken != NULL); - *pMetadataToken = typeHandle.GetCl(); - Module * pModule = typeHandle.GetModule(); - if (pModule == NULL) - ThrowHR(CORDBG_E_TARGET_INCONSISTENT); + AppDomain *pAppDomain = vmAppDomain.GetDacPtr(); - pVmModule->SetHostPtr(pModule); + // if we fail to get either a valid type handle or module, we will want to send back + // a NULL domain file too, so we'll to preinitialize this here. + _ASSERTE(pVmDomainAssembly != NULL); + *pVmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); + // FindLoadedElementType will return NULL if the type hasn't been loaded yet. + TypeHandle typeHandle = FindLoadedElementType(simpleType); - if (pAppDomain) + if (typeHandle.IsNull()) + { + ThrowHR(CORDBG_E_CLASS_NOT_LOADED); + } + else { - pVmDomainAssembly->SetHostPtr(pModule->GetDomainAssembly()); - if (pVmDomainAssembly->IsNull()) + _ASSERTE(pMetadataToken != NULL); + *pMetadataToken = typeHandle.GetCl(); + + Module * pModule = typeHandle.GetModule(); + if (pModule == NULL) ThrowHR(CORDBG_E_TARGET_INCONSISTENT); + + pVmModule->SetHostPtr(pModule); + + if (pAppDomain) + { + pVmDomainAssembly->SetHostPtr(pModule->GetDomainAssembly()); + if (pVmDomainAssembly->IsNull()) + ThrowHR(CORDBG_E_TARGET_INCONSISTENT); + } } - } - LOG((LF_CORDB, LL_INFO10000, "D::STI: sending result.\n")); -} // DacDbiInterfaceImpl::GetSimpleType + LOG((LF_CORDB, LL_INFO10000, "D::STI: sending result.\n")); + } + EX_CATCH_HRESULT(hr); + return hr; +} -BOOL DacDbiInterfaceImpl::IsExceptionObject(VMPTR_Object vmObject) +HRESULT DacDbiInterfaceImpl::IsExceptionObject(VMPTR_Object vmObject, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - Object* objPtr = vmObject.GetDacPtr(); - MethodTable* pMT = objPtr->GetMethodTable(); + HRESULT hr = S_OK; + EX_TRY + { + + Object* objPtr = vmObject.GetDacPtr(); + MethodTable* pMT = objPtr->GetMethodTable(); - return IsExceptionObject(pMT); + *pResult = IsExceptionObject(pMT); + } + EX_CATCH_HRESULT(hr); + return hr; } BOOL DacDbiInterfaceImpl::IsExceptionObject(MethodTable* pMT) @@ -3234,15 +3406,26 @@ HRESULT DacDbiInterfaceImpl::GetMethodDescPtrFromIpEx(TADDR funcIp, VMPTR_Method return S_OK; } -BOOL DacDbiInterfaceImpl::IsDelegate(VMPTR_Object vmObject) +HRESULT DacDbiInterfaceImpl::IsDelegate(VMPTR_Object vmObject, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - if (vmObject.IsNull()) - return FALSE; + HRESULT hr = S_OK; + EX_TRY + { - Object *pObj = vmObject.GetDacPtr(); - return pObj->GetGCSafeMethodTable()->IsDelegate(); + if (vmObject.IsNull()) + { + *pResult = FALSE; + } + else + { + Object *pObj = vmObject.GetDacPtr(); + *pResult = pObj->GetGCSafeMethodTable()->IsDelegate(); + } + } + EX_CATCH_HRESULT(hr); + return hr; } @@ -3537,52 +3720,59 @@ HRESULT DacDbiInterfaceImpl::GetLoaderHeapMemoryRanges(DacDbiArrayList& dacStackFrames) +HRESULT DacDbiInterfaceImpl::GetStackFramesFromException(VMPTR_Object vmObject, DacDbiArrayList& dacStackFrames) { DD_ENTER_MAY_THROW; - PTR_Object objPtr = vmObject.GetDacPtr(); + HRESULT hr = S_OK; + EX_TRY + { -#ifdef _DEBUG - // ensure we have an Exception object - MethodTable* pMT = objPtr->GetMethodTable(); - _ASSERTE(IsExceptionObject(pMT)); -#endif + PTR_Object objPtr = vmObject.GetDacPtr(); - OBJECTREF objRef = ObjectToOBJECTREF(objPtr); + #ifdef _DEBUG + // ensure we have an Exception object + MethodTable* pMT = objPtr->GetMethodTable(); + _ASSERTE(IsExceptionObject(pMT)); + #endif - DebugStackTrace::GetStackFramesData stackFramesData; + OBJECTREF objRef = ObjectToOBJECTREF(objPtr); - stackFramesData.pDomain = NULL; - stackFramesData.NumFramesRequested = 0; + DebugStackTrace::GetStackFramesData stackFramesData; - DebugStackTrace::GetStackFramesFromException(&objRef, &stackFramesData); + stackFramesData.pDomain = NULL; + stackFramesData.NumFramesRequested = 0; - INT32 dacStackFramesLength = stackFramesData.cElements; + DebugStackTrace::GetStackFramesFromException(&objRef, &stackFramesData); - if (dacStackFramesLength > 0) - { - dacStackFrames.Alloc(dacStackFramesLength); + INT32 dacStackFramesLength = stackFramesData.cElements; - for (INT32 index = 0; index < dacStackFramesLength; ++index) + if (dacStackFramesLength > 0) { - DebugStackTrace::Element const& currentElement = stackFramesData.pElements[index]; - DacExceptionCallStackData& currentFrame = dacStackFrames[index]; + dacStackFrames.Alloc(dacStackFramesLength); - AppDomain* pDomain = AppDomain::GetCurrentDomain(); - _ASSERTE(pDomain != NULL); + for (INT32 index = 0; index < dacStackFramesLength; ++index) + { + DebugStackTrace::Element const& currentElement = stackFramesData.pElements[index]; + DacExceptionCallStackData& currentFrame = dacStackFrames[index]; + + AppDomain* pDomain = AppDomain::GetCurrentDomain(); + _ASSERTE(pDomain != NULL); - Module* pModule = currentElement.pFunc->GetModule(); - DomainAssembly* pDomainAssembly = pModule->GetDomainAssembly(); - _ASSERTE(pDomainAssembly != NULL); + Module* pModule = currentElement.pFunc->GetModule(); + DomainAssembly* pDomainAssembly = pModule->GetDomainAssembly(); + _ASSERTE(pDomainAssembly != NULL); - currentFrame.vmAppDomain.SetHostPtr(pDomain); - currentFrame.vmDomainAssembly.SetHostPtr(pDomainAssembly); - currentFrame.ip = currentElement.ip; - currentFrame.methodDef = currentElement.pFunc->GetMemberDef(); - currentFrame.isLastForeignExceptionFrame = (currentElement.flags & STEF_LAST_FRAME_FROM_FOREIGN_STACK_TRACE) != 0; + currentFrame.vmAppDomain.SetHostPtr(pDomain); + currentFrame.vmDomainAssembly.SetHostPtr(pDomainAssembly); + currentFrame.ip = currentElement.ip; + currentFrame.methodDef = currentElement.pFunc->GetMemberDef(); + currentFrame.isLastForeignExceptionFrame = (currentElement.flags & STEF_LAST_FRAME_FROM_FOREIGN_STACK_TRACE) != 0; + } } } + EX_CATCH_HRESULT(hr); + return hr; } #ifdef FEATURE_COMINTEROP @@ -3610,74 +3800,96 @@ PTR_RCW GetRcwFromVmptrObject(VMPTR_Object vmObject) #endif -BOOL DacDbiInterfaceImpl::IsRcw(VMPTR_Object vmObject) +HRESULT DacDbiInterfaceImpl::IsRcw(VMPTR_Object vmObject, OUT BOOL * pResult) { #ifdef FEATURE_COMINTEROP DD_ENTER_MAY_THROW; - return GetRcwFromVmptrObject(vmObject) != NULL; + + HRESULT hr = S_OK; + EX_TRY + { + *pResult = GetRcwFromVmptrObject(vmObject) != NULL; + } + EX_CATCH_HRESULT(hr); + return hr; #else - return FALSE; + *pResult = FALSE; + return S_OK; #endif // FEATURE_COMINTEROP - } -void DacDbiInterfaceImpl::GetRcwCachedInterfaceTypes( - VMPTR_Object vmObject, - VMPTR_AppDomain vmAppDomain, - BOOL bIInspectableOnly, - DacDbiArrayList * pDacInterfaces) +HRESULT DacDbiInterfaceImpl::GetRcwCachedInterfaceTypes(VMPTR_Object vmObject, VMPTR_AppDomain vmAppDomain, BOOL bIInspectableOnly, OUT DacDbiArrayList * pDacInterfaces) { - // Legacy WinRT API. - pDacInterfaces->Alloc(0); + HRESULT hr = S_OK; + EX_TRY + { + // Legacy WinRT API. + pDacInterfaces->Alloc(0); + } + EX_CATCH_HRESULT(hr); + return hr; } -void DacDbiInterfaceImpl::GetRcwCachedInterfacePointers( - VMPTR_Object vmObject, - BOOL bIInspectableOnly, - DacDbiArrayList * pDacItfPtrs) +HRESULT DacDbiInterfaceImpl::GetRcwCachedInterfacePointers(VMPTR_Object vmObject, BOOL bIInspectableOnly, OUT DacDbiArrayList * pDacItfPtrs) { #ifdef FEATURE_COMINTEROP DD_ENTER_MAY_THROW; - Object* objPtr = vmObject.GetDacPtr(); - - InlineSArray rgUnks; - - PTR_RCW pRCW = GetRcwFromVmptrObject(vmObject); - if (pRCW != NULL) + HRESULT hr = S_OK; + EX_TRY { - pRCW->GetCachedInterfacePointers(bIInspectableOnly, &rgUnks); - pDacItfPtrs->Alloc(rgUnks.GetCount()); + Object* objPtr = vmObject.GetDacPtr(); - for (COUNT_T i = 0; i < rgUnks.GetCount(); ++i) + InlineSArray rgUnks; + + PTR_RCW pRCW = GetRcwFromVmptrObject(vmObject); + if (pRCW != NULL) { - (*pDacItfPtrs)[i] = (CORDB_ADDRESS)(rgUnks[i]); - } + pRCW->GetCachedInterfacePointers(bIInspectableOnly, &rgUnks); + pDacItfPtrs->Alloc(rgUnks.GetCount()); + + for (COUNT_T i = 0; i < rgUnks.GetCount(); ++i) + { + (*pDacItfPtrs)[i] = (CORDB_ADDRESS)(rgUnks[i]); + } + + } + else + { + pDacItfPtrs->Alloc(0); + } } - else -#endif // FEATURE_COMINTEROP - { - pDacItfPtrs->Alloc(0); - } + EX_CATCH_HRESULT(hr); + return hr; +#else + pDacItfPtrs->Alloc(0); + return S_OK; +#endif // FEATURE_COMINTEROP } -void DacDbiInterfaceImpl::GetCachedWinRTTypesForIIDs( - VMPTR_AppDomain vmAppDomain, - DacDbiArrayList & iids, - OUT DacDbiArrayList * pTypes) +HRESULT DacDbiInterfaceImpl::GetCachedWinRTTypesForIIDs(VMPTR_AppDomain vmAppDomain, DacDbiArrayList & iids, OUT DacDbiArrayList * pTypes) { - pTypes->Alloc(0); + HRESULT hr = S_OK; + EX_TRY + { + pTypes->Alloc(0); + } + EX_CATCH_HRESULT(hr); + return hr; } -void DacDbiInterfaceImpl::GetCachedWinRTTypes( - VMPTR_AppDomain vmAppDomain, - OUT DacDbiArrayList * pGuids, - OUT DacDbiArrayList * pTypes) +HRESULT DacDbiInterfaceImpl::GetCachedWinRTTypes(VMPTR_AppDomain vmAppDomain, OUT DacDbiArrayList * piids, OUT DacDbiArrayList * pTypes) { - pTypes->Alloc(0); + HRESULT hr = S_OK; + EX_TRY + { + pTypes->Alloc(0); + } + EX_CATCH_HRESULT(hr); + return hr; } //----------------------------------------------------------------------------- @@ -3849,171 +4061,226 @@ void DacDbiInterfaceImpl::InitFieldData(const FieldDesc * pFD, // GENERICS: TODO: this method will need to be modified if we ever support EnC on // generic classes. //----------------------------------------------------------------------------- -void DacDbiInterfaceImpl::GetEnCHangingFieldInfo(const EnCHangingFieldInfo * pEnCFieldInfo, - FieldData * pFieldData, - BOOL * pfStatic) +HRESULT DacDbiInterfaceImpl::GetEnCHangingFieldInfo(const EnCHangingFieldInfo * pEnCFieldInfo, OUT FieldData * pFieldData, OUT BOOL * pfStatic) { DD_ENTER_MAY_THROW; - LOG((LF_CORDB, LL_INFO100000, "DDI::IEnCHFI: Obj:0x%x, objType" - ":0x%x, offset:0x%x\n", pEnCFieldInfo->m_pObject, pEnCFieldInfo->m_objectTypeData.elementType, - pEnCFieldInfo->m_offsetToVars)); + HRESULT hr = S_OK; + EX_TRY + { - FieldDesc * pFD = NULL; - PTR_CBYTE pORField = NULL; + LOG((LF_CORDB, LL_INFO100000, "DDI::IEnCHFI: Obj:0x%x, objType" + ":0x%x, offset:0x%x\n", pEnCFieldInfo->m_pObject, pEnCFieldInfo->m_objectTypeData.elementType, + pEnCFieldInfo->m_offsetToVars)); - pFD = GetEnCFieldDesc(pEnCFieldInfo); - _ASSERTE(pFD->IsEnCNew()); // We shouldn't be here if it wasn't added to an - // already loaded class. + FieldDesc * pFD = NULL; + PTR_CBYTE pORField = NULL; -#ifdef FEATURE_METADATA_UPDATER - pORField = GetPtrToEnCField(pFD, pEnCFieldInfo); -#else - _ASSERTE(!"We shouldn't be here: EnC not supported"); -#endif // FEATURE_METADATA_UPDATER + pFD = GetEnCFieldDesc(pEnCFieldInfo); + _ASSERTE(pFD->IsEnCNew()); // We shouldn't be here if it wasn't added to an + // already loaded class. - InitFieldData(pFD, pORField, pEnCFieldInfo, pFieldData); - *pfStatic = (pFD->IsStatic() != 0); + #ifdef FEATURE_METADATA_UPDATER + pORField = GetPtrToEnCField(pFD, pEnCFieldInfo); + #else + _ASSERTE(!"We shouldn't be here: EnC not supported"); + #endif // FEATURE_METADATA_UPDATER -} // DacDbiInterfaceImpl::GetEnCHangingFieldInfo + InitFieldData(pFD, pORField, pEnCFieldInfo, pFieldData); + *pfStatic = (pFD->IsStatic() != 0); + + } + EX_CATCH_HRESULT(hr); + return hr; +} //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void DacDbiInterfaceImpl::GetAssemblyFromDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, VMPTR_Assembly *vmAssembly) +HRESULT DacDbiInterfaceImpl::GetAssemblyFromDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Assembly * vmAssembly) { DD_ENTER_MAY_THROW; - _ASSERTE(vmAssembly != NULL); + HRESULT hr = S_OK; + EX_TRY + { - DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); - vmAssembly->SetHostPtr(pDomainAssembly->GetAssembly()); + _ASSERTE(vmAssembly != NULL); + + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + vmAssembly->SetHostPtr(pDomainAssembly->GetAssembly()); + } + EX_CATCH_HRESULT(hr); + return hr; } // Determines whether the runtime security system has assigned full-trust to this assembly. -BOOL DacDbiInterfaceImpl::IsAssemblyFullyTrusted(VMPTR_DomainAssembly vmDomainAssembly) +HRESULT DacDbiInterfaceImpl::IsAssemblyFullyTrusted(VMPTR_DomainAssembly vmDomainAssembly, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - return TRUE; + HRESULT hr = S_OK; + EX_TRY + { + + *pResult = TRUE; + } + EX_CATCH_HRESULT(hr); + return hr; } // Get the full path and file name to the assembly's manifest module. -BOOL DacDbiInterfaceImpl::GetAssemblyPath( - VMPTR_Assembly vmAssembly, - IStringHolder * pStrFilename) +HRESULT DacDbiInterfaceImpl::GetAssemblyPath(VMPTR_Assembly vmAssembly, IStringHolder * pStrFilename, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - // Get the manifest module for this assembly - Assembly * pAssembly = vmAssembly.GetDacPtr(); - Module * pManifestModule = pAssembly->GetModule(); + HRESULT hr = S_OK; + EX_TRY + { - // Get the path for the manifest module. - // since we no longer support Win9x, we assume all paths will be in unicode format already - const WCHAR * szPath = pManifestModule->GetPath().DacGetRawUnicode(); - HRESULT hrStatus = pStrFilename->AssignCopy(szPath); - IfFailThrow(hrStatus); + // Get the manifest module for this assembly + Assembly * pAssembly = vmAssembly.GetDacPtr(); + Module * pManifestModule = pAssembly->GetModule(); - if(szPath == NULL || *szPath=='\0') - { - // The asembly has no (and will never have a) file name, but we didn't really fail - return FALSE; - } + // Get the path for the manifest module. + // since we no longer support Win9x, we assume all paths will be in unicode format already + const WCHAR * szPath = pManifestModule->GetPath().DacGetRawUnicode(); + HRESULT hrStatus = pStrFilename->AssignCopy(szPath); + IfFailThrow(hrStatus); - return TRUE; + if(szPath == NULL || *szPath=='\0') + { + // The asembly has no (and will never have a) file name, but we didn't really fail + *pResult = FALSE; + } + else + { + *pResult = TRUE; + } + } + EX_CATCH_HRESULT(hr); + return hr; } // DAC/DBI API // Get a resolved type def from a type ref. The type ref may come from a module other than the // referencing module. -void DacDbiInterfaceImpl::ResolveTypeReference(const TypeRefData * pTypeRefInfo, - TypeRefData * pTargetRefInfo) +HRESULT DacDbiInterfaceImpl::ResolveTypeReference(const TypeRefData * pTypeRefInfo, TypeRefData * pTargetRefInfo) { DD_ENTER_MAY_THROW; - DomainAssembly * pDomainAssembly = pTypeRefInfo->vmDomainAssembly.GetDacPtr(); - Module * pReferencingModule = pDomainAssembly->GetAssembly()->GetModule(); - BOOL fSuccess = FALSE; - - // Resolve the type ref - // g_pEEInterface->FindLoadedClass is almost what we want, but it isn't guaranteed to work if - // the typeRef was originally loaded from a different assembly. Also, we need to ensure that - // we can resolve even unloaded types in fully loaded assemblies, so APIs such as - // LoadTypeDefOrRefThrowing aren't acceptable. - - Module * pTargetModule = NULL; - mdTypeDef targetTypeDef = mdTokenNil; - // The loader won't need to trigger a GC or throw because we've told it not to load anything - ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE(); - - fSuccess = ClassLoader::ResolveTokenToTypeDefThrowing(pReferencingModule, - pTypeRefInfo->typeToken, - &pTargetModule, - &targetTypeDef, - Loader::SafeLookup //don't load, no locks/allocations - ); - if (fSuccess) + HRESULT hr = S_OK; + EX_TRY { - _ASSERTE(pTargetModule != NULL); - _ASSERTE( TypeFromToken(targetTypeDef) == mdtTypeDef ); + DomainAssembly * pDomainAssembly = pTypeRefInfo->vmDomainAssembly.GetDacPtr(); + Module * pReferencingModule = pDomainAssembly->GetAssembly()->GetModule(); + BOOL fSuccess = FALSE; + + // Resolve the type ref + // g_pEEInterface->FindLoadedClass is almost what we want, but it isn't guaranteed to work if + // the typeRef was originally loaded from a different assembly. Also, we need to ensure that + // we can resolve even unloaded types in fully loaded assemblies, so APIs such as + // LoadTypeDefOrRefThrowing aren't acceptable. + + Module * pTargetModule = NULL; + mdTypeDef targetTypeDef = mdTokenNil; + + // The loader won't need to trigger a GC or throw because we've told it not to load anything + ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE(); + + fSuccess = ClassLoader::ResolveTokenToTypeDefThrowing(pReferencingModule, + pTypeRefInfo->typeToken, + &pTargetModule, + &targetTypeDef, + Loader::SafeLookup //don't load, no locks/allocations + ); + if (fSuccess) + { + _ASSERTE(pTargetModule != NULL); + _ASSERTE( TypeFromToken(targetTypeDef) == mdtTypeDef ); - pTargetRefInfo->vmDomainAssembly.SetDacTargetPtr(PTR_HOST_TO_TADDR(pTargetModule->GetDomainAssembly())); - pTargetRefInfo->typeToken = targetTypeDef; - } - else - { - // failed - presumably because the target assembly isn't loaded - ThrowHR(CORDBG_E_CLASS_NOT_LOADED); + pTargetRefInfo->vmDomainAssembly.SetDacTargetPtr(PTR_HOST_TO_TADDR(pTargetModule->GetDomainAssembly())); + pTargetRefInfo->typeToken = targetTypeDef; + } + else + { + // failed - presumably because the target assembly isn't loaded + ThrowHR(CORDBG_E_CLASS_NOT_LOADED); + } } -} // DacDbiInterfaceImpl::ResolveTypeReference + EX_CATCH_HRESULT(hr); + return hr; +} // Get the full path and file name to the module (if any). -BOOL DacDbiInterfaceImpl::GetModulePath(VMPTR_Module vmModule, - IStringHolder * pStrFilename) +HRESULT DacDbiInterfaceImpl::GetModulePath(VMPTR_Module vmModule, IStringHolder * pStrFilename, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - Module * pModule = vmModule.GetDacPtr(); - PEAssembly * pPEAssembly = pModule->GetPEAssembly(); - if (pPEAssembly != NULL) + HRESULT hr = S_OK; + EX_TRY { - if( !pPEAssembly->GetPath().IsEmpty() ) + + Module * pModule = vmModule.GetDacPtr(); + PEAssembly * pPEAssembly = pModule->GetPEAssembly(); + if (pPEAssembly != NULL) { - // Module has an on-disk path - const WCHAR * szPath = pPEAssembly->GetPath().DacGetRawUnicode(); - if (szPath == NULL) + if( !pPEAssembly->GetPath().IsEmpty() ) { - szPath = pPEAssembly->GetModuleFileNameHint().DacGetRawUnicode(); + // Module has an on-disk path + const WCHAR * szPath = pPEAssembly->GetPath().DacGetRawUnicode(); if (szPath == NULL) { - goto NoFileName; + szPath = pPEAssembly->GetModuleFileNameHint().DacGetRawUnicode(); + } + if (szPath != NULL) + { + IfFailThrow(pStrFilename->AssignCopy(szPath)); + *pResult = TRUE; + } + else + { + IfFailThrow(pStrFilename->AssignCopy(W(""))); + *pResult = FALSE; } } - IfFailThrow(pStrFilename->AssignCopy(szPath)); - return TRUE; + else + { + IfFailThrow(pStrFilename->AssignCopy(W(""))); + *pResult = FALSE; + } + } + else + { + // no filename + IfFailThrow(pStrFilename->AssignCopy(W(""))); + *pResult = FALSE; } } - -NoFileName: - // no filename - IfFailThrow(pStrFilename->AssignCopy(W(""))); - return FALSE; + EX_CATCH_HRESULT(hr); + return hr; } // Implementation of IDacDbiInterface::GetModuleSimpleName -void DacDbiInterfaceImpl::GetModuleSimpleName(VMPTR_Module vmModule, IStringHolder * pStrFilename) +HRESULT DacDbiInterfaceImpl::GetModuleSimpleName(VMPTR_Module vmModule, IStringHolder * pStrFilename) { DD_ENTER_MAY_THROW; - _ASSERTE(pStrFilename != NULL); + HRESULT hr = S_OK; + EX_TRY + { + + _ASSERTE(pStrFilename != NULL); - Module * pModule = vmModule.GetDacPtr(); - LPCUTF8 szNameUtf8 = pModule->GetSimpleName(); + Module * pModule = vmModule.GetDacPtr(); + LPCUTF8 szNameUtf8 = pModule->GetSimpleName(); - SString convert(SString::Utf8, szNameUtf8); - IfFailThrow(pStrFilename->AssignCopy(convert.GetUnicode())); + SString convert(SString::Utf8, szNameUtf8); + IfFailThrow(pStrFilename->AssignCopy(convert.GetUnicode())); + } + EX_CATCH_HRESULT(hr); + return hr; } HRESULT DacDbiInterfaceImpl::IsModuleMapped(VMPTR_Module pModule, OUT BOOL *isModuleMapped) @@ -4040,14 +4307,21 @@ HRESULT DacDbiInterfaceImpl::IsModuleMapped(VMPTR_Module pModule, OUT BOOL *isMo return hr; } -bool DacDbiInterfaceImpl::MetadataUpdatesApplied() +HRESULT DacDbiInterfaceImpl::MetadataUpdatesApplied(OUT bool * pResult) { DD_ENTER_MAY_THROW; -#ifdef FEATURE_METADATA_UPDATER - return g_metadataUpdatesApplied; -#else - return false; -#endif + + HRESULT hr = S_OK; + EX_TRY + { + #ifdef FEATURE_METADATA_UPDATER + *pResult = g_metadataUpdatesApplied; + #else + *pResult = false; + #endif + } + EX_CATCH_HRESULT(hr); + return hr; } // Helper to initialize a TargetBuffer from a MemoryRange @@ -4104,267 +4378,326 @@ void InitTargetBufferFromTargetSBuffer(PTR_SBuffer pBuffer, TargetBuffer * pTarg // Implementation of IDacDbiInterface::GetMetadata -void DacDbiInterfaceImpl::GetMetadata(VMPTR_Module vmModule, TargetBuffer * pTargetBuffer) +HRESULT DacDbiInterfaceImpl::GetMetadata(VMPTR_Module vmModule, OUT TargetBuffer * pTargetBuffer) { DD_ENTER_MAY_THROW; - pTargetBuffer->Clear(); + HRESULT hr = S_OK; + EX_TRY + { - Module * pModule = vmModule.GetDacPtr(); + pTargetBuffer->Clear(); - // Target should only be asking about modules that are visible to debugger. - _ASSERTE(pModule->IsVisibleToDebugger()); + Module * pModule = vmModule.GetDacPtr(); - // For dynamic modules, metadata is stored as an eagerly-serialized buffer hanging off the Reflection Module. - if (pModule->IsReflectionEmit()) - { - // Here is the fetch. - ReflectionModule * pReflectionModule = pModule->GetReflectionModule(); + // Target should only be asking about modules that are visible to debugger. + _ASSERTE(pModule->IsVisibleToDebugger()); - TADDR metadataBuffer = pReflectionModule->GetDynamicMetadataBuffer(); - CORDB_ADDRESS addr = PTR_TO_CORDB_ADDRESS(metadataBuffer + offsetof(DynamicMetadata, Data)); - pTargetBuffer->Init(addr, dac_cast(metadataBuffer)->Size); - } - else - { - PEAssembly * pPEAssembly = pModule->GetPEAssembly(); + // For dynamic modules, metadata is stored as an eagerly-serialized buffer hanging off the Reflection Module. + if (pModule->IsReflectionEmit()) + { + // Here is the fetch. + ReflectionModule * pReflectionModule = pModule->GetReflectionModule(); - // For non-dynamic modules, metadata is in the pe-image. - COUNT_T size; - CORDB_ADDRESS address = PTR_TO_CORDB_ADDRESS(dac_cast(pPEAssembly->GetLoadedMetadata(&size))); + TADDR metadataBuffer = pReflectionModule->GetDynamicMetadataBuffer(); + CORDB_ADDRESS addr = PTR_TO_CORDB_ADDRESS(metadataBuffer + offsetof(DynamicMetadata, Data)); + pTargetBuffer->Init(addr, dac_cast(metadataBuffer)->Size); + } + else + { + PEAssembly * pPEAssembly = pModule->GetPEAssembly(); - pTargetBuffer->Init(address, (ULONG) size); - } + // For non-dynamic modules, metadata is in the pe-image. + COUNT_T size; + CORDB_ADDRESS address = PTR_TO_CORDB_ADDRESS(dac_cast(pPEAssembly->GetLoadedMetadata(&size))); - if (pTargetBuffer->IsEmpty()) - { - // We never expect this to happen in a well-behaved scenario. But just in case. - ThrowHR(CORDBG_E_MISSING_METADATA); - } + pTargetBuffer->Init(address, (ULONG) size); + } + + if (pTargetBuffer->IsEmpty()) + { + // We never expect this to happen in a well-behaved scenario. But just in case. + ThrowHR(CORDBG_E_MISSING_METADATA); + } + } + EX_CATCH_HRESULT(hr); + return hr; } // Implementation of IDacDbiInterface::GetSymbolsBuffer -void DacDbiInterfaceImpl::GetSymbolsBuffer(VMPTR_Module vmModule, TargetBuffer * pTargetBuffer, SymbolFormat * pSymbolFormat) +HRESULT DacDbiInterfaceImpl::GetSymbolsBuffer(VMPTR_Module vmModule, OUT TargetBuffer * pTargetBuffer, OUT SymbolFormat * pSymbolFormat) { DD_ENTER_MAY_THROW; - pTargetBuffer->Clear(); - *pSymbolFormat = kSymbolFormatNone; + HRESULT hr = S_OK; + EX_TRY + { - Module * pModule = vmModule.GetDacPtr(); + pTargetBuffer->Clear(); + *pSymbolFormat = kSymbolFormatNone; - // Target should only be asking about modules that are visible to debugger. - _ASSERTE(pModule->IsVisibleToDebugger()); + Module * pModule = vmModule.GetDacPtr(); - PTR_CGrowableStream pStream = pModule->GetInMemorySymbolStream(); - if (pStream == NULL) - { - // Common case is to not have PDBs in-memory. - return; - } + // Target should only be asking about modules that are visible to debugger. + _ASSERTE(pModule->IsVisibleToDebugger()); - const MemoryRange m = pStream->GetRawBuffer(); - if (m.Size() == 0) - { - // We may be prepared to store symbols (in some particular format) but none are there yet. - // We treat this the same as not having any symbols above. - return; - } - InitTargetBufferFromMemoryRange(m, pTargetBuffer); + PTR_CGrowableStream pStream = pModule->GetInMemorySymbolStream(); + if (pStream == NULL) + { + // Common case is to not have PDBs in-memory. + return hr; + } - *pSymbolFormat = kSymbolFormatPDB; + const MemoryRange m = pStream->GetRawBuffer(); + if (m.Size() == 0) + { + // We may be prepared to store symbols (in some particular format) but none are there yet. + // We treat this the same as not having any symbols above. + return hr; + } + InitTargetBufferFromMemoryRange(m, pTargetBuffer); + + *pSymbolFormat = kSymbolFormatPDB; + } + EX_CATCH_HRESULT(hr); + return hr; } -void DacDbiInterfaceImpl::GetModuleForDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Module * pModule) +HRESULT DacDbiInterfaceImpl::GetModuleForDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, OUT VMPTR_Module * pModule) { DD_ENTER_MAY_THROW; - _ASSERTE(pModule != NULL); + HRESULT hr = S_OK; + EX_TRY + { - DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); - pModule->SetHostPtr(pDomainAssembly->GetAssembly()->GetModule()); + _ASSERTE(pModule != NULL); + + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + pModule->SetHostPtr(pDomainAssembly->GetAssembly()->GetModule()); + } + EX_CATCH_HRESULT(hr); + return hr; } // Implement IDacDbiInterface::GetDomainAssemblyData -void DacDbiInterfaceImpl::GetDomainAssemblyData(VMPTR_DomainAssembly vmDomainAssembly, DomainAssemblyInfo * pData) +HRESULT DacDbiInterfaceImpl::GetDomainAssemblyData(VMPTR_DomainAssembly vmDomainAssembly, OUT DomainAssemblyInfo * pData) { DD_ENTER_MAY_THROW; - _ASSERTE(pData != NULL); + HRESULT hr = S_OK; + EX_TRY + { + + _ASSERTE(pData != NULL); - ZeroMemory(pData, sizeof(*pData)); + ZeroMemory(pData, sizeof(*pData)); - DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); + DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr(); - // @dbgtodo - is this efficient DAC usage (perhaps a dac-cop rule)? Are we round-tripping the pointer? - pData->vmDomainAssembly.SetHostPtr(pDomainAssembly); - pData->vmAppDomain.SetHostPtr(AppDomain::GetCurrentDomain()); + // @dbgtodo - is this efficient DAC usage (perhaps a dac-cop rule)? Are we round-tripping the pointer? + pData->vmDomainAssembly.SetHostPtr(pDomainAssembly); + pData->vmAppDomain.SetHostPtr(AppDomain::GetCurrentDomain()); + } + EX_CATCH_HRESULT(hr); + return hr; } // Implement IDacDbiInterface::GetModuleData -void DacDbiInterfaceImpl::GetModuleData(VMPTR_Module vmModule, ModuleInfo * pData) +HRESULT DacDbiInterfaceImpl::GetModuleData(VMPTR_Module vmModule, OUT ModuleInfo * pData) { DD_ENTER_MAY_THROW; - _ASSERTE(pData != NULL); + HRESULT hr = S_OK; + EX_TRY + { - ZeroMemory(pData, sizeof(*pData)); + _ASSERTE(pData != NULL); - Module * pModule = vmModule.GetDacPtr(); - PEAssembly * pPEAssembly = pModule->GetPEAssembly(); + ZeroMemory(pData, sizeof(*pData)); - pData->vmPEAssembly.SetHostPtr(pPEAssembly); - pData->vmAssembly.SetHostPtr(pModule->GetAssembly()); + Module * pModule = vmModule.GetDacPtr(); + PEAssembly * pPEAssembly = pModule->GetPEAssembly(); - // Is it dynamic? - BOOL fIsDynamic = pModule->IsReflectionEmit(); - pData->fIsDynamic = fIsDynamic; + pData->vmPEAssembly.SetHostPtr(pPEAssembly); + pData->vmAssembly.SetHostPtr(pModule->GetAssembly()); - // Get PE BaseAddress and Size - // For dynamic modules, these are 0. Else, - pData->pPEBaseAddress = (CORDB_ADDRESS)NULL; - pData->nPESize = 0; + // Is it dynamic? + BOOL fIsDynamic = pModule->IsReflectionEmit(); + pData->fIsDynamic = fIsDynamic; - if (!fIsDynamic) - { - COUNT_T size = 0; - pData->pPEBaseAddress = PTR_TO_TADDR(pPEAssembly->GetDebuggerContents(&size)); - pData->nPESize = (ULONG) size; - } + // Get PE BaseAddress and Size + // For dynamic modules, these are 0. Else, + pData->pPEBaseAddress = (CORDB_ADDRESS)NULL; + pData->nPESize = 0; - // In-memory is determined by whether the module has a filename. - pData->fInMemory = FALSE; - if (pPEAssembly != NULL) - { - pData->fInMemory = pPEAssembly->GetPath().IsEmpty(); + if (!fIsDynamic) + { + COUNT_T size = 0; + pData->pPEBaseAddress = PTR_TO_TADDR(pPEAssembly->GetDebuggerContents(&size)); + pData->nPESize = (ULONG) size; + } + + // In-memory is determined by whether the module has a filename. + pData->fInMemory = FALSE; + if (pPEAssembly != NULL) + { + pData->fInMemory = pPEAssembly->GetPath().IsEmpty(); + } } + EX_CATCH_HRESULT(hr); + return hr; } // Enumerate all AppDomains in the process. -void DacDbiInterfaceImpl::EnumerateAppDomains( - FP_APPDOMAIN_ENUMERATION_CALLBACK fpCallback, - void * pUserData) +HRESULT DacDbiInterfaceImpl::EnumerateAppDomains(FP_APPDOMAIN_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData) { DD_ENTER_MAY_THROW; - _ASSERTE(fpCallback != NULL); + HRESULT hr = S_OK; + EX_TRY + { + + _ASSERTE(fpCallback != NULL); - // It's critical that we don't yield appdomains after the unload event has been sent. - // See code:IDacDbiInterface#Enumeration for details. - AppDomain * pAppDomain = AppDomain::GetCurrentDomain(); + // It's critical that we don't yield appdomains after the unload event has been sent. + // See code:IDacDbiInterface#Enumeration for details. + AppDomain * pAppDomain = AppDomain::GetCurrentDomain(); - VMPTR_AppDomain vmAppDomain = VMPTR_AppDomain::NullPtr(); - vmAppDomain.SetHostPtr(pAppDomain); - fpCallback(vmAppDomain, pUserData); + VMPTR_AppDomain vmAppDomain = VMPTR_AppDomain::NullPtr(); + vmAppDomain.SetHostPtr(pAppDomain); + fpCallback(vmAppDomain, pUserData); + } + EX_CATCH_HRESULT(hr); + return hr; } // Enumerate all Assemblies in an appdomain. -void DacDbiInterfaceImpl::EnumerateAssembliesInAppDomain( - VMPTR_AppDomain vmAppDomain, - FP_ASSEMBLY_ENUMERATION_CALLBACK fpCallback, - void * pUserData -) +HRESULT DacDbiInterfaceImpl::EnumerateAssembliesInAppDomain(VMPTR_AppDomain vmAppDomain, FP_ASSEMBLY_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData) { DD_ENTER_MAY_THROW; - _ASSERTE(fpCallback != NULL); + HRESULT hr = S_OK; + EX_TRY + { - // Iterate through all Assemblies (including shared) in the appdomain. - AppDomain::AssemblyIterator iterator; + _ASSERTE(fpCallback != NULL); - // If the containing appdomain is unloading, then don't enumerate any assemblies - // in the domain. This is to enforce rules at code:IDacDbiInterface#Enumeration. - // See comment in code:DacDbiInterfaceImpl::EnumerateModulesInAssembly code for details. - AppDomain * pAppDomain = vmAppDomain.GetDacPtr(); + // Iterate through all Assemblies (including shared) in the appdomain. + AppDomain::AssemblyIterator iterator; - if (pAppDomain == nullptr) - { - return; - } + // If the containing appdomain is unloading, then don't enumerate any assemblies + // in the domain. This is to enforce rules at code:IDacDbiInterface#Enumeration. + // See comment in code:DacDbiInterfaceImpl::EnumerateModulesInAssembly code for details. + AppDomain * pAppDomain = vmAppDomain.GetDacPtr(); - // Pass the magical flags to the loader enumerator to get all Execution-only assemblies. - iterator = pAppDomain->IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoading | kIncludeLoaded | kIncludeExecution)); - CollectibleAssemblyHolder pAssembly; + if (pAppDomain == nullptr) + { + return hr; + } - while (iterator.Next(pAssembly.This())) - { - VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); - vmDomainAssembly.SetHostPtr(pAssembly->GetDomainAssembly()); + // Pass the magical flags to the loader enumerator to get all Execution-only assemblies. + iterator = pAppDomain->IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoading | kIncludeLoaded | kIncludeExecution)); + CollectibleAssemblyHolder pAssembly; + + while (iterator.Next(pAssembly.This())) + { + VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); + vmDomainAssembly.SetHostPtr(pAssembly->GetDomainAssembly()); - fpCallback(vmDomainAssembly, pUserData); + fpCallback(vmDomainAssembly, pUserData); + } } + EX_CATCH_HRESULT(hr); + return hr; } // Implementation of IDacDbiInterface::EnumerateModulesInAssembly, // Enumerate all the modules (non-resource) in an assembly. -void DacDbiInterfaceImpl::EnumerateModulesInAssembly( - VMPTR_DomainAssembly vmAssembly, - FP_MODULE_ENUMERATION_CALLBACK fpCallback, - void * pUserData) +HRESULT DacDbiInterfaceImpl::EnumerateModulesInAssembly(VMPTR_DomainAssembly vmAssembly, FP_MODULE_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData) { DD_ENTER_MAY_THROW; - _ASSERTE(fpCallback != NULL); + HRESULT hr = S_OK; + EX_TRY + { + + _ASSERTE(fpCallback != NULL); - DomainAssembly * pDomainAssembly = vmAssembly.GetDacPtr(); + DomainAssembly * pDomainAssembly = vmAssembly.GetDacPtr(); - // Debugger isn't notified of Resource / Inspection-only modules. - if (pDomainAssembly->GetAssembly()->GetModule()->IsVisibleToDebugger()) - { - // If domain assembly isn't yet loaded, just return - if (!pDomainAssembly->GetAssembly()->IsLoaded()) - return; + // Debugger isn't notified of Resource / Inspection-only modules. + if (pDomainAssembly->GetAssembly()->GetModule()->IsVisibleToDebugger()) + { + // If domain assembly isn't yet loaded, just return + if (!pDomainAssembly->GetAssembly()->IsLoaded()) + return hr; - VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); - vmDomainAssembly.SetHostPtr(pDomainAssembly); + VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); + vmDomainAssembly.SetHostPtr(pDomainAssembly); - fpCallback(vmDomainAssembly, pUserData); + fpCallback(vmDomainAssembly, pUserData); + } } + EX_CATCH_HRESULT(hr); + return hr; } // Implementation of IDacDbiInterface::ResolveAssembly // Returns NULL if not found. -VMPTR_DomainAssembly DacDbiInterfaceImpl::ResolveAssembly( - VMPTR_DomainAssembly vmScope, - mdToken tkAssemblyRef) +HRESULT DacDbiInterfaceImpl::ResolveAssembly(VMPTR_DomainAssembly vmScope, mdToken tkAssemblyRef, OUT VMPTR_DomainAssembly * pRetVal) { DD_ENTER_MAY_THROW; + HRESULT hr = S_OK; + EX_TRY + { + - DomainAssembly * pDomainAssembly = vmScope.GetDacPtr(); - Module * pModule = pDomainAssembly->GetAssembly()->GetModule(); + DomainAssembly * pDomainAssembly = vmScope.GetDacPtr(); + Module * pModule = pDomainAssembly->GetAssembly()->GetModule(); - VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); + VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); - Assembly * pAssembly = pModule->LookupAssemblyRef(tkAssemblyRef); - if (pAssembly != NULL) - { - DomainAssembly * pDomainAssembly = pAssembly->GetDomainAssembly(); - vmDomainAssembly.SetHostPtr(pDomainAssembly); + Assembly * pAssembly = pModule->LookupAssemblyRef(tkAssemblyRef); + if (pAssembly != NULL) + { + DomainAssembly * pDomainAssembly = pAssembly->GetDomainAssembly(); + vmDomainAssembly.SetHostPtr(pDomainAssembly); + } + *pRetVal = vmDomainAssembly; } - return vmDomainAssembly; + EX_CATCH_HRESULT(hr); + return hr; } // When stopped at an event, request a synchronization. // See DacDbiInterface.h for full comments -void DacDbiInterfaceImpl::RequestSyncAtEvent() +HRESULT DacDbiInterfaceImpl::RequestSyncAtEvent() { DD_ENTER_MAY_THROW; - // To request a sync, we just need to set g_pDebugger->m_RSRequestedSync high. - if (g_pDebugger != NULL) + HRESULT hr = S_OK; + EX_TRY { - TADDR addr = PTR_HOST_MEMBER_TADDR(Debugger, g_pDebugger, m_RSRequestedSync); - BOOL fTrue = TRUE; - SafeWriteStructOrThrow(addr, &fTrue); + // To request a sync, we just need to set g_pDebugger->m_RSRequestedSync high. + if (g_pDebugger != NULL) + { + TADDR addr = PTR_HOST_MEMBER_TADDR(Debugger, g_pDebugger, m_RSRequestedSync); + + BOOL fTrue = TRUE; + SafeWriteStructOrThrow(addr, &fTrue); + } } + EX_CATCH_HRESULT(hr); + return hr; } HRESULT DacDbiInterfaceImpl::SetSendExceptionsOutsideOfJMC(BOOL sendExceptionsOutsideOfJMC) @@ -4386,102 +4719,130 @@ HRESULT DacDbiInterfaceImpl::SetSendExceptionsOutsideOfJMC(BOOL sendExceptionsOu // Notify the debuggee that a debugger attach is pending. // See DacDbiInterface.h for full comments -void DacDbiInterfaceImpl::MarkDebuggerAttachPending() +HRESULT DacDbiInterfaceImpl::MarkDebuggerAttachPending() { DD_ENTER_MAY_THROW; - if (g_pDebugger != NULL) + HRESULT hr = S_OK; + EX_TRY { - DWORD flags = g_CORDebuggerControlFlags; - flags |= DBCF_PENDING_ATTACH; - // Uses special DAC writing. PTR_TO_TADDR doesn't fetch for globals. - // @dbgtodo dac support - the exact mechanism of writing to the target needs to be flushed out, - // especially as it relates to DAC cop and enforcing undac-ized writes. - g_CORDebuggerControlFlags = flags; - } - else - { - // Caller should have guaranteed that the LS is loaded. - // If we're detaching, then don't throw because we don't care. - ThrowHR(CORDBG_E_NOTREADY); + if (g_pDebugger != NULL) + { + DWORD flags = g_CORDebuggerControlFlags; + flags |= DBCF_PENDING_ATTACH; + + // Uses special DAC writing. PTR_TO_TADDR doesn't fetch for globals. + // @dbgtodo dac support - the exact mechanism of writing to the target needs to be flushed out, + // especially as it relates to DAC cop and enforcing undac-ized writes. + g_CORDebuggerControlFlags = flags; + } + else + { + // Caller should have guaranteed that the LS is loaded. + // If we're detaching, then don't throw because we don't care. + ThrowHR(CORDBG_E_NOTREADY); + } } + EX_CATCH_HRESULT(hr); + return hr; } // Notify the debuggee that a debugger is attached. // See DacDbiInterface.h for full comments -void DacDbiInterfaceImpl::MarkDebuggerAttached(BOOL fAttached) +HRESULT DacDbiInterfaceImpl::MarkDebuggerAttached(BOOL fAttached) { DD_ENTER_MAY_THROW; - if (g_pDebugger != NULL) + HRESULT hr = S_OK; + EX_TRY { - // To be attached, we need to set the following - // g_CORDebuggerControlFlags |= DBCF_ATTACHED; - // To detach (if !fAttached), we need to do the opposite. - DWORD flags = g_CORDebuggerControlFlags; - if (fAttached) + if (g_pDebugger != NULL) { - flags |= DBCF_ATTACHED; + // To be attached, we need to set the following + // g_CORDebuggerControlFlags |= DBCF_ATTACHED; + // To detach (if !fAttached), we need to do the opposite. + + DWORD flags = g_CORDebuggerControlFlags; + if (fAttached) + { + flags |= DBCF_ATTACHED; + } + else + { + flags &= ~ (DBCF_ATTACHED | DBCF_PENDING_ATTACH); + } + + // Uses special DAC writing. PTR_TO_TADDR doesn't fetch for globals. + // @dbgtodo dac support - the exact mechanism of writing to the target needs to be flushed out, + // especially as it relates to DAC cop and enforcing undac-ized writes. + g_CORDebuggerControlFlags = flags; } - else + else if (fAttached) { - flags &= ~ (DBCF_ATTACHED | DBCF_PENDING_ATTACH); + // Caller should have guaranteed that the LS is loaded. + // If we're detaching, then don't throw because we don't care. + ThrowHR(CORDBG_E_NOTREADY); } - // Uses special DAC writing. PTR_TO_TADDR doesn't fetch for globals. - // @dbgtodo dac support - the exact mechanism of writing to the target needs to be flushed out, - // especially as it relates to DAC cop and enforcing undac-ized writes. - g_CORDebuggerControlFlags = flags; - } - else if (fAttached) - { - // Caller should have guaranteed that the LS is loaded. - // If we're detaching, then don't throw because we don't care. - ThrowHR(CORDBG_E_NOTREADY); } - + EX_CATCH_HRESULT(hr); + return hr; } // Enumerate all threads in the process. -void DacDbiInterfaceImpl::EnumerateThreads(FP_THREAD_ENUMERATION_CALLBACK fpCallback, void * pUserData) +HRESULT DacDbiInterfaceImpl::EnumerateThreads(FP_THREAD_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData) { DD_ENTER_MAY_THROW; - if (ThreadStore::s_pThreadStore == NULL) + HRESULT hr = S_OK; + EX_TRY { - return; - } - Thread *pThread = ThreadStore::GetThreadList(NULL); + if (ThreadStore::s_pThreadStore == NULL) + { + return hr; + } - while (pThread != NULL) - { + Thread *pThread = ThreadStore::GetThreadList(NULL); - // Don't want to publish threads via enumeration before they're ready to be inspected. - // Use the same window that we used in whidbey. - Thread::ThreadState threadState = pThread->GetSnapshotState(); - if (!((IsThreadMarkedDeadWorker(pThread)) || (threadState & Thread::TS_Unstarted))) + while (pThread != NULL) { - VMPTR_Thread vmThread = VMPTR_Thread::NullPtr(); - vmThread.SetHostPtr(pThread); - fpCallback(vmThread, pUserData); - } - pThread = ThreadStore::GetThreadList(pThread); + // Don't want to publish threads via enumeration before they're ready to be inspected. + // Use the same window that we used in whidbey. + Thread::ThreadState threadState = pThread->GetSnapshotState(); + if (!((IsThreadMarkedDeadWorker(pThread)) || (threadState & Thread::TS_Unstarted))) + { + VMPTR_Thread vmThread = VMPTR_Thread::NullPtr(); + vmThread.SetHostPtr(pThread); + fpCallback(vmThread, pUserData); + } + + pThread = ThreadStore::GetThreadList(pThread); + } } + EX_CATCH_HRESULT(hr); + return hr; } // public implementation of IsThreadMarkedDead -bool DacDbiInterfaceImpl::IsThreadMarkedDead(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::IsThreadMarkedDead(VMPTR_Thread vmThread, OUT bool * pResult) { DD_ENTER_MAY_THROW; - Thread * pThread = vmThread.GetDacPtr(); - return IsThreadMarkedDeadWorker(pThread); + + HRESULT hr = S_OK; + EX_TRY + { + Thread * pThread = vmThread.GetDacPtr(); + *pResult = IsThreadMarkedDeadWorker(pThread); + } + EX_CATCH_HRESULT(hr); + return hr; } // Private worker for IsThreadMarkedDead @@ -4508,231 +4869,322 @@ bool DacDbiInterfaceImpl::IsThreadMarkedDeadWorker(Thread * pThread) // Return the handle of the specified thread. -HANDLE DacDbiInterfaceImpl::GetThreadHandle(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::GetThreadHandle(VMPTR_Thread vmThread, OUT HANDLE * pRetVal) { DD_ENTER_MAY_THROW; - Thread * pThread = vmThread.GetDacPtr(); - return pThread->GetThreadHandle(); + HRESULT hr = S_OK; + EX_TRY + { + + Thread * pThread = vmThread.GetDacPtr(); + *pRetVal = pThread->GetThreadHandle(); + } + EX_CATCH_HRESULT(hr); + return hr; } // Return the object handle for the managed Thread object corresponding to the specified thread. -VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetThreadObject(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::GetThreadObject(VMPTR_Thread vmThread, OUT VMPTR_OBJECTHANDLE * pRetVal) { DD_ENTER_MAY_THROW; - Thread * pThread = vmThread.GetDacPtr(); - Thread::ThreadState threadState = pThread->GetSnapshotState(); - - if ( (threadState & Thread::TS_Dead) || - (threadState & Thread::TS_Unstarted) || - (threadState & Thread::TS_Detached) || - g_fProcessDetach ) - { - ThrowHR(CORDBG_E_BAD_THREAD_STATE); - } - else + HRESULT hr = S_OK; + EX_TRY { - VMPTR_OBJECTHANDLE vmObjHandle = VMPTR_OBJECTHANDLE::NullPtr(); - vmObjHandle.SetDacTargetPtr(pThread->GetExposedObjectHandleForDebugger()); - return vmObjHandle; + + Thread * pThread = vmThread.GetDacPtr(); + Thread::ThreadState threadState = pThread->GetSnapshotState(); + + if ( (threadState & Thread::TS_Dead) || + (threadState & Thread::TS_Unstarted) || + (threadState & Thread::TS_Detached) || + g_fProcessDetach ) + { + ThrowHR(CORDBG_E_BAD_THREAD_STATE); + } + else + { + VMPTR_OBJECTHANDLE vmObjHandle = VMPTR_OBJECTHANDLE::NullPtr(); + vmObjHandle.SetDacTargetPtr(pThread->GetExposedObjectHandleForDebugger()); + *pRetVal = vmObjHandle; + } } + EX_CATCH_HRESULT(hr); + return hr; } -void DacDbiInterfaceImpl::GetThreadAllocInfo(VMPTR_Thread vmThread, - DacThreadAllocInfo* threadAllocInfo) +HRESULT DacDbiInterfaceImpl::GetThreadAllocInfo(VMPTR_Thread vmThread, DacThreadAllocInfo* threadAllocInfo) { DD_ENTER_MAY_THROW; - Thread * pThread = vmThread.GetDacPtr(); - gc_alloc_context* allocContext = pThread->GetAllocContext(); - if (allocContext != nullptr) - { - threadAllocInfo->m_allocBytesSOH = allocContext->alloc_bytes - (allocContext->alloc_limit - allocContext->alloc_ptr); - threadAllocInfo->m_allocBytesUOH = allocContext->alloc_bytes_uoh; - } - else + HRESULT hr = S_OK; + EX_TRY { - threadAllocInfo->m_allocBytesSOH = 0; - threadAllocInfo->m_allocBytesUOH = 0; + + Thread * pThread = vmThread.GetDacPtr(); + gc_alloc_context* allocContext = pThread->GetAllocContext(); + if (allocContext != nullptr) + { + threadAllocInfo->m_allocBytesSOH = allocContext->alloc_bytes - (allocContext->alloc_limit - allocContext->alloc_ptr); + threadAllocInfo->m_allocBytesUOH = allocContext->alloc_bytes_uoh; + } + else + { + threadAllocInfo->m_allocBytesSOH = 0; + threadAllocInfo->m_allocBytesUOH = 0; + } } + EX_CATCH_HRESULT(hr); + return hr; } // Set and reset the TSNC_DebuggerUserSuspend bit on the state of the specified thread // according to the CorDebugThreadState. -void DacDbiInterfaceImpl::SetDebugState(VMPTR_Thread vmThread, - CorDebugThreadState debugState) +HRESULT DacDbiInterfaceImpl::SetDebugState(VMPTR_Thread vmThread, CorDebugThreadState debugState) { DD_ENTER_MAY_THROW; - Thread * pThread = vmThread.GetDacPtr(); - - // update the field on the host copy - if (debugState == THREAD_SUSPEND) - { - pThread->SetThreadStateNC(Thread::TSNC_DebuggerUserSuspend); - } - else if (debugState == THREAD_RUN) - { - pThread->ResetThreadStateNC(Thread::TSNC_DebuggerUserSuspend); - } - else + HRESULT hr = S_OK; + EX_TRY { - ThrowHR(E_INVALIDARG); - } - // update the field on the target copy - TADDR taThreadState = PTR_HOST_MEMBER_TADDR(Thread, pThread, m_StateNC); - SafeWriteStructOrThrow(taThreadState, &(pThread->m_StateNC)); + Thread * pThread = vmThread.GetDacPtr(); + + // update the field on the host copy + if (debugState == THREAD_SUSPEND) + { + pThread->SetThreadStateNC(Thread::TSNC_DebuggerUserSuspend); + } + else if (debugState == THREAD_RUN) + { + pThread->ResetThreadStateNC(Thread::TSNC_DebuggerUserSuspend); + } + else + { + ThrowHR(E_INVALIDARG); + } + + // update the field on the target copy + TADDR taThreadState = PTR_HOST_MEMBER_TADDR(Thread, pThread, m_StateNC); + SafeWriteStructOrThrow(taThreadState, &(pThread->m_StateNC)); + } + EX_CATCH_HRESULT(hr); + return hr; } // Gets the debugger unhandled exception threadstate flag -BOOL DacDbiInterfaceImpl::HasUnhandledException(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::HasUnhandledException(VMPTR_Thread vmThread, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - Thread * pThread = vmThread.GetDacPtr(); - - // some managed exceptions don't have any underlying - // native exception processing going on. They just consist - // of a managed throwable that we have stashed away followed - // by a debugger notification and some form of failfast. - // Everything that comes through EEFatalError is in this category - if(pThread->IsLastThrownObjectUnhandled()) + HRESULT hr = S_OK; + EX_TRY { - return TRUE; - } - // most managed exceptions are just a throwable bound to a - // native exception. In that case this handle will be non-null - OBJECTHANDLE ohException = pThread->GetThrowableAsHandle(); - if (ohException != (OBJECTHANDLE)NULL) - { - // during the UEF we set the unhandled bit, if it is set the exception - // was unhandled - // however if the exception has intercept info then we consider it handled - // again - return pThread->GetExceptionState()->GetFlags()->IsUnhandled() && - !(pThread->GetExceptionState()->GetFlags()->DebuggerInterceptInfo()); - } + Thread * pThread = vmThread.GetDacPtr(); - return FALSE; + // some managed exceptions don't have any underlying + // native exception processing going on. They just consist + // of a managed throwable that we have stashed away followed + // by a debugger notification and some form of failfast. + // Everything that comes through EEFatalError is in this category + if(pThread->IsLastThrownObjectUnhandled()) + { + *pResult = TRUE; + } + else + { + // most managed exceptions are just a throwable bound to a + // native exception. In that case this handle will be non-null + OBJECTHANDLE ohException = pThread->GetThrowableAsHandle(); + if (ohException != (OBJECTHANDLE)NULL) + { + // during the UEF we set the unhandled bit, if it is set the exception + // was unhandled + // however if the exception has intercept info then we consider it handled + // again + *pResult = pThread->GetExceptionState()->GetFlags()->IsUnhandled() && + !(pThread->GetExceptionState()->GetFlags()->DebuggerInterceptInfo()); + } + else + { + *pResult = FALSE; + } + } + } + EX_CATCH_HRESULT(hr); + return hr; } // Return the user state of the specified thread. -CorDebugUserState DacDbiInterfaceImpl::GetUserState(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::GetUserState(VMPTR_Thread vmThread, OUT CorDebugUserState * pRetVal) { DD_ENTER_MAY_THROW; - UINT result = 0; - result = GetPartialUserState(vmThread); - - if (!IsThreadAtGCSafePlace(vmThread)) + HRESULT hr = S_OK; + EX_TRY { - result |= USER_UNSAFE_POINT; - } - return (CorDebugUserState)result; + UINT result = 0; + CorDebugUserState partialState; + IfFailThrow(GetPartialUserState(vmThread, &partialState)); + result = (UINT)partialState; + + if (!IsThreadAtGCSafePlace(vmThread)) + { + result |= USER_UNSAFE_POINT; + } + + *pRetVal = (CorDebugUserState)result; + } + EX_CATCH_HRESULT(hr); + return hr; } // Return the connection ID of the specified thread. -CONNID DacDbiInterfaceImpl::GetConnectionID(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::GetConnectionID(VMPTR_Thread vmThread, OUT CONNID * pRetVal) { DD_ENTER_MAY_THROW; - return INVALID_CONNECTION_ID; + HRESULT hr = S_OK; + EX_TRY + { + + *pRetVal = INVALID_CONNECTION_ID; + } + EX_CATCH_HRESULT(hr); + return hr; } // Return the task ID of the specified thread. -TASKID DacDbiInterfaceImpl::GetTaskID(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::GetTaskID(VMPTR_Thread vmThread, OUT TASKID * pRetVal) { DD_ENTER_MAY_THROW; - return INVALID_TASK_ID; + HRESULT hr = S_OK; + EX_TRY + { + + *pRetVal = INVALID_TASK_ID; + } + EX_CATCH_HRESULT(hr); + return hr; } // Return the OS thread ID of the specified thread -DWORD DacDbiInterfaceImpl::TryGetVolatileOSThreadID(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::TryGetVolatileOSThreadID(VMPTR_Thread vmThread, OUT DWORD * pRetVal) { DD_ENTER_MAY_THROW; - Thread * pThread = vmThread.GetDacPtr(); - _ASSERTE(pThread != NULL); + HRESULT hr = S_OK; + EX_TRY + { - DWORD dwThreadId = pThread->GetOSThreadIdForDebugger(); + Thread * pThread = vmThread.GetDacPtr(); + _ASSERTE(pThread != NULL); - // If the thread ID is a the magical cookie value, then this is really - // a switched out thread and doesn't have an OS tid. In that case, the - // DD contract is to return 0 (a much more sane value) - const DWORD dwSwitchedOutThreadId = SWITCHED_OUT_FIBER_OSID; - if (dwThreadId == dwSwitchedOutThreadId) - { - return 0; + DWORD dwThreadId = pThread->GetOSThreadIdForDebugger(); + + // If the thread ID is a the magical cookie value, then this is really + // a switched out thread and doesn't have an OS tid. In that case, the + // DD contract is to return 0 (a much more sane value) + const DWORD dwSwitchedOutThreadId = SWITCHED_OUT_FIBER_OSID; + if (dwThreadId == dwSwitchedOutThreadId) + { + *pRetVal = 0; + } + else + { + *pRetVal = dwThreadId; + } } - return dwThreadId; + EX_CATCH_HRESULT(hr); + return hr; } // Return the unique thread ID of the specified thread. -DWORD DacDbiInterfaceImpl::GetUniqueThreadID(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::GetUniqueThreadID(VMPTR_Thread vmThread, OUT DWORD * pRetVal) { DD_ENTER_MAY_THROW; - Thread * pThread = vmThread.GetDacPtr(); - _ASSERTE(pThread != NULL); + HRESULT hr = S_OK; + EX_TRY + { - return pThread->GetOSThreadId(); + Thread * pThread = vmThread.GetDacPtr(); + _ASSERTE(pThread != NULL); + + *pRetVal = pThread->GetOSThreadId(); + } + EX_CATCH_HRESULT(hr); + return hr; } // Return the object handle to the managed Exception object of the current exception // on the specified thread. The return value could be NULL if there is no current exception. -VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetCurrentException(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::GetCurrentException(VMPTR_Thread vmThread, OUT VMPTR_OBJECTHANDLE * pRetVal) { DD_ENTER_MAY_THROW; - Thread * pThread = vmThread.GetDacPtr(); + HRESULT hr = S_OK; + EX_TRY + { - // OBJECTHANDLEs are really just TADDRs. - OBJECTHANDLE ohException = pThread->GetThrowableAsHandle(); // ohException can be NULL + Thread * pThread = vmThread.GetDacPtr(); - if (ohException == (OBJECTHANDLE)NULL) - { - if (pThread->IsLastThrownObjectUnhandled()) + // OBJECTHANDLEs are really just TADDRs. + OBJECTHANDLE ohException = pThread->GetThrowableAsHandle(); // ohException can be NULL + + if (ohException == (OBJECTHANDLE)NULL) { - ohException = pThread->LastThrownObjectHandle(); + if (pThread->IsLastThrownObjectUnhandled()) + { + ohException = pThread->LastThrownObjectHandle(); + } } - } - VMPTR_OBJECTHANDLE vmObjHandle; - vmObjHandle.SetDacTargetPtr(ohException); - return vmObjHandle; + VMPTR_OBJECTHANDLE vmObjHandle; + vmObjHandle.SetDacTargetPtr(ohException); + *pRetVal = vmObjHandle; + } + EX_CATCH_HRESULT(hr); + return hr; } // Return the object handle to the managed object for a given CCW pointer. -VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetObjectForCCW(CORDB_ADDRESS ccwPtr) +HRESULT DacDbiInterfaceImpl::GetObjectForCCW(CORDB_ADDRESS ccwPtr, OUT VMPTR_OBJECTHANDLE * pRetVal) { DD_ENTER_MAY_THROW; - OBJECTHANDLE ohCCW = (OBJECTHANDLE)NULL; + HRESULT hr = S_OK; + EX_TRY + { + + OBJECTHANDLE ohCCW = (OBJECTHANDLE)NULL; + + #ifdef FEATURE_COMWRAPPERS + if (DACTryGetComWrappersHandleFromCCW(ccwPtr, &ohCCW) != S_OK) + { + #endif + #ifdef FEATURE_COMINTEROP + ComCallWrapper *pCCW = DACGetCCWFromAddress(ccwPtr); + if (pCCW) + { + ohCCW = pCCW->GetObjectHandle(); + } + #endif + #ifdef FEATURE_COMWRAPPERS + } + #endif -#ifdef FEATURE_COMWRAPPERS - if (DACTryGetComWrappersHandleFromCCW(ccwPtr, &ohCCW) != S_OK) - { -#endif -#ifdef FEATURE_COMINTEROP - ComCallWrapper *pCCW = DACGetCCWFromAddress(ccwPtr); - if (pCCW) - { - ohCCW = pCCW->GetObjectHandle(); + VMPTR_OBJECTHANDLE vmObjHandle; + vmObjHandle.SetDacTargetPtr(ohCCW); + *pRetVal = vmObjHandle; } -#endif -#ifdef FEATURE_COMWRAPPERS - } -#endif - - VMPTR_OBJECTHANDLE vmObjHandle; - vmObjHandle.SetDacTargetPtr(ohCCW); - return vmObjHandle; + EX_CATCH_HRESULT(hr); + return hr; } // Return the object handle to the managed CustomNotification object of the current notification @@ -4743,51 +5195,72 @@ VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetObjectForCCW(CORDB_ADDRESS ccwPtr) // if and only if we are currently inside a CustomNotification Callback (or a dump was generated while in this // callback) // -VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetCurrentCustomDebuggerNotification(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::GetCurrentCustomDebuggerNotification(VMPTR_Thread vmThread, OUT VMPTR_OBJECTHANDLE * pRetVal) { DD_ENTER_MAY_THROW; - Thread * pThread = vmThread.GetDacPtr(); + HRESULT hr = S_OK; + EX_TRY + { - // OBJECTHANDLEs are really just TADDRs. - OBJECTHANDLE ohNotification = pThread->GetThreadCurrNotification(); // ohNotification can be NULL + Thread * pThread = vmThread.GetDacPtr(); - VMPTR_OBJECTHANDLE vmObjHandle; - vmObjHandle.SetDacTargetPtr(ohNotification); - return vmObjHandle; + // OBJECTHANDLEs are really just TADDRs. + OBJECTHANDLE ohNotification = pThread->GetThreadCurrNotification(); // ohNotification can be NULL + + VMPTR_OBJECTHANDLE vmObjHandle; + vmObjHandle.SetDacTargetPtr(ohNotification); + *pRetVal = vmObjHandle; + } + EX_CATCH_HRESULT(hr); + return hr; } // Return the current appdomain. -VMPTR_AppDomain DacDbiInterfaceImpl::GetCurrentAppDomain() +HRESULT DacDbiInterfaceImpl::GetCurrentAppDomain(OUT VMPTR_AppDomain * pRetVal) { DD_ENTER_MAY_THROW; - AppDomain * pAppDomain = AppDomain::GetCurrentDomain(); - VMPTR_AppDomain vmAppDomain = VMPTR_AppDomain::NullPtr(); - vmAppDomain.SetDacTargetPtr(PTR_HOST_TO_TADDR(pAppDomain)); - return vmAppDomain; + HRESULT hr = S_OK; + EX_TRY + { + + AppDomain * pAppDomain = AppDomain::GetCurrentDomain(); + VMPTR_AppDomain vmAppDomain = VMPTR_AppDomain::NullPtr(); + vmAppDomain.SetDacTargetPtr(PTR_HOST_TO_TADDR(pAppDomain)); + *pRetVal = vmAppDomain; + } + EX_CATCH_HRESULT(hr); + return hr; } // Returns a bitfield reflecting the managed debugging state at the time of // the jit attach. -CLR_DEBUGGING_PROCESS_FLAGS DacDbiInterfaceImpl::GetAttachStateFlags() +HRESULT DacDbiInterfaceImpl::GetAttachStateFlags(OUT CLR_DEBUGGING_PROCESS_FLAGS * pRetVal) { DD_ENTER_MAY_THROW; - CLR_DEBUGGING_PROCESS_FLAGS res = (CLR_DEBUGGING_PROCESS_FLAGS)0; - if (g_pDebugger != NULL) - { - res = g_pDebugger->GetAttachStateFlags(); - } - else + HRESULT hr = S_OK; + EX_TRY { - // When launching the process under a managed debugger we - // request these flags when CLR is loaded (before g_pDebugger - // had a chance to be initialized). In these cases simply - // return 0 + + CLR_DEBUGGING_PROCESS_FLAGS res = (CLR_DEBUGGING_PROCESS_FLAGS)0; + if (g_pDebugger != NULL) + { + res = g_pDebugger->GetAttachStateFlags(); + } + else + { + // When launching the process under a managed debugger we + // request these flags when CLR is loaded (before g_pDebugger + // had a chance to be initialized). In these cases simply + // return 0 + } + *pRetVal = res; } - return res; + EX_CATCH_HRESULT(hr); + return hr; } //--------------------------------------------------------------------------------------- @@ -4953,360 +5426,397 @@ void DacDbiInterfaceImpl::WriteExceptionRecordHelper(CORDB_ADDRESS pRemotePtr, } // Implement IDacDbiInterface::Hijack -void DacDbiInterfaceImpl::Hijack( - VMPTR_Thread vmThread, - ULONG32 dwThreadId, - const EXCEPTION_RECORD * pRecord, - T_CONTEXT * pOriginalContext, - ULONG32 cbSizeContext, - EHijackReason::EHijackReason reason, - void * pUserData, - CORDB_ADDRESS * pRemoteContextAddr) +HRESULT DacDbiInterfaceImpl::Hijack(VMPTR_Thread vmThread, ULONG32 dwThreadId, const EXCEPTION_RECORD * pRecord, T_CONTEXT * pOriginalContext, ULONG32 cbSizeContext, EHijackReason::EHijackReason reason, void * pUserData, CORDB_ADDRESS * pRemoteContextAddr) { DD_ENTER_MAY_THROW; - // - // Validate parameters - // + HRESULT hr = S_OK; + EX_TRY + { - // pRecord may be NULL if we're not hijacking at an exception - // pOriginalContext may be NULL if caller doesn't want a copy of the context. - // (The hijack function already has the context) - _ASSERTE((pOriginalContext == NULL) == (cbSizeContext == 0)); - _ASSERTE(EHijackReason::IsValid(reason)); -#ifdef TARGET_UNIX - _ASSERTE(!"Not supported on this platform"); -#endif + // + // Validate parameters + // - // - // If we hijack a thread which might not be managed we can set vmThread = NULL - // The only side-effect in this case is that we can't reuse CONTEXT and - // EXCEPTION_RECORD space on the stack by an already underway in-process exception - // filter. If you depend on those being used and updated you must provide the vmThread - // - Thread* pThread = NULL; - if(!vmThread.IsNull()) - { - pThread = vmThread.GetDacPtr(); - _ASSERTE(pThread->GetOSThreadIdForDebugger() == dwThreadId); - } + // pRecord may be NULL if we're not hijacking at an exception + // pOriginalContext may be NULL if caller doesn't want a copy of the context. + // (The hijack function already has the context) + _ASSERTE((pOriginalContext == NULL) == (cbSizeContext == 0)); + _ASSERTE(EHijackReason::IsValid(reason)); + #ifdef TARGET_UNIX + _ASSERTE(!"Not supported on this platform"); + #endif - TADDR pfnHijackFunction = GetHijackAddress(); + // + // If we hijack a thread which might not be managed we can set vmThread = NULL + // The only side-effect in this case is that we can't reuse CONTEXT and + // EXCEPTION_RECORD space on the stack by an already underway in-process exception + // filter. If you depend on those being used and updated you must provide the vmThread + // + Thread* pThread = NULL; + if(!vmThread.IsNull()) + { + pThread = vmThread.GetDacPtr(); + _ASSERTE(pThread->GetOSThreadIdForDebugger() == dwThreadId); + } - // - // Setup context for hijack - // - T_CONTEXT ctx; -#if !defined(CROSS_COMPILE) && !defined(TARGET_WINDOWS) && (defined(DTCONTEXT_IS_AMD64) || defined(DTCONTEXT_IS_ARM64)) - // If the host or target is not Windows, then we can assume that the DT_CONTEXT - // is the same as the T_CONTEXT, except for the XSTATE registers. - static_assert(sizeof(DT_CONTEXT) == offsetof(T_CONTEXT, XStateFeaturesMask), "DT_CONTEXT does not include the XSTATE registers"); -#else - // Since Dac + DBI are tightly coupled, context sizes should be the same. - static_assert(sizeof(DT_CONTEXT) == sizeof(T_CONTEXT), "DT_CONTEXT size must equal the T_CONTEXT size"); -#endif - HRESULT hr = m_pTarget->GetThreadContext( - dwThreadId, - CONTEXT_FULL | CONTEXT_FLOATING_POINT -#ifdef CONTEXT_EXTENDED_REGISTERS - | CONTEXT_EXTENDED_REGISTERS -#endif - , - sizeof(DT_CONTEXT), - (BYTE*) &ctx); - IfFailThrow(hr); + TADDR pfnHijackFunction = GetHijackAddress(); - // If caller requested, copy back the original context that we're hijacking from. - if (pOriginalContext != NULL) - { + // + // Setup context for hijack + // + T_CONTEXT ctx; + #if !defined(CROSS_COMPILE) && !defined(TARGET_WINDOWS) && (defined(DTCONTEXT_IS_AMD64) || defined(DTCONTEXT_IS_ARM64)) + // If the host or target is not Windows, then we can assume that the DT_CONTEXT + // is the same as the T_CONTEXT, except for the XSTATE registers. + static_assert(sizeof(DT_CONTEXT) == offsetof(T_CONTEXT, XStateFeaturesMask), "DT_CONTEXT does not include the XSTATE registers"); + #else // Since Dac + DBI are tightly coupled, context sizes should be the same. - if (cbSizeContext != sizeof(T_CONTEXT)) + static_assert(sizeof(DT_CONTEXT) == sizeof(T_CONTEXT), "DT_CONTEXT size must equal the T_CONTEXT size"); + #endif + HRESULT hr = m_pTarget->GetThreadContext( + dwThreadId, + CONTEXT_FULL | CONTEXT_FLOATING_POINT + #ifdef CONTEXT_EXTENDED_REGISTERS + | CONTEXT_EXTENDED_REGISTERS + #endif + , + sizeof(DT_CONTEXT), + (BYTE*) &ctx); + IfFailThrow(hr); + + // If caller requested, copy back the original context that we're hijacking from. + if (pOriginalContext != NULL) { - ThrowHR(E_INVALIDARG); - } + // Since Dac + DBI are tightly coupled, context sizes should be the same. + if (cbSizeContext != sizeof(T_CONTEXT)) + { + ThrowHR(E_INVALIDARG); + } - memcpy(pOriginalContext, &ctx, cbSizeContext); - } + memcpy(pOriginalContext, &ctx, cbSizeContext); + } - // Make sure the trace flag isn't on. This can happen if we were single stepping the thread when we faulted. This - // will ensure that we don't try to single step through the OS's exception logic, which greatly confuses our second - // chance hijack logic. This also mimics what the OS does for us automaically when single stepping in process, i.e., - // when you turn the trace flag on in-process and go, if there is a fault, the fault is reported and the trace flag - // is automatically turned off. - // - // The debugger could always re-enable the single-step flag if it wants to. -#ifndef FEATURE_EMULATE_SINGLESTEP - UnsetSSFlag(reinterpret_cast(&ctx)); -#endif + // Make sure the trace flag isn't on. This can happen if we were single stepping the thread when we faulted. This + // will ensure that we don't try to single step through the OS's exception logic, which greatly confuses our second + // chance hijack logic. This also mimics what the OS does for us automaically when single stepping in process, i.e., + // when you turn the trace flag on in-process and go, if there is a fault, the fault is reported and the trace flag + // is automatically turned off. + // + // The debugger could always re-enable the single-step flag if it wants to. + #ifndef FEATURE_EMULATE_SINGLESTEP + UnsetSSFlag(reinterpret_cast(&ctx)); + #endif - // Push pointers - void* espContext = NULL; - void* espRecord = NULL; - const void* pData = pUserData; + // Push pointers + void* espContext = NULL; + void* espRecord = NULL; + const void* pData = pUserData; - // @dbgtodo cross-plat - this is not cross plat - CORDB_ADDRESS esp = GetSP(&ctx); + // @dbgtodo cross-plat - this is not cross plat + CORDB_ADDRESS esp = GetSP(&ctx); - // - // Find out where the OS exception dispatcher has pushed the EXCEPTION_RECORD and CONTEXT. The ExInfo - // has pointers to these data structures, but when we get the unhandled exception notification, - // the OS exception dispatcher is no longer on the stack, so these pointers are no longer - // valid. We need to either update these pointers in the ExInfo/ExcepionTracker, or reuse the stack - // space used by the OS exception dispatcher. We are using the latter approach here. - // + // + // Find out where the OS exception dispatcher has pushed the EXCEPTION_RECORD and CONTEXT. The ExInfo + // has pointers to these data structures, but when we get the unhandled exception notification, + // the OS exception dispatcher is no longer on the stack, so these pointers are no longer + // valid. We need to either update these pointers in the ExInfo/ExcepionTracker, or reuse the stack + // space used by the OS exception dispatcher. We are using the latter approach here. + // - CORDB_ADDRESS espOSContext = (CORDB_ADDRESS)NULL; - CORDB_ADDRESS espOSRecord = (CORDB_ADDRESS)NULL; - if (pThread != NULL && pThread->IsExceptionInProgress()) - { - espOSContext = (CORDB_ADDRESS)PTR_TO_TADDR(pThread->GetExceptionState()->GetContextRecord()); - espOSRecord = (CORDB_ADDRESS)PTR_TO_TADDR(pThread->GetExceptionState()->GetExceptionRecord()); + CORDB_ADDRESS espOSContext = (CORDB_ADDRESS)NULL; + CORDB_ADDRESS espOSRecord = (CORDB_ADDRESS)NULL; + if (pThread != NULL && pThread->IsExceptionInProgress()) + { + espOSContext = (CORDB_ADDRESS)PTR_TO_TADDR(pThread->GetExceptionState()->GetContextRecord()); + espOSRecord = (CORDB_ADDRESS)PTR_TO_TADDR(pThread->GetExceptionState()->GetExceptionRecord()); + + // The managed exception may not be related to the unhandled exception for which we are trying to + // hijack. An example would be when a thread hits a managed exception, VS tries to do func eval on + // the thread, but the func eval causes an unhandled exception (e.g. AV in mscorwks.dll). In this + // case, the pointers stored on the ExInfo are closer to the root than the current SP of the thread. + // The check below makes sure we don't reuse the pointers in this case. + if (espOSContext < esp) + { + SafeWriteStructOrThrow(espOSContext, &ctx); + espContext = CORDB_ADDRESS_TO_PTR(espOSContext); + + // We should have an EXCEPTION_RECORD if we are hijacked at an exception. + // We need to be careful when we overwrite the exception record. On x86, the OS doesn't + // always push the full record onto the stack, and so we can't blindly use sizeof(EXCEPTION_RECORD). + // Instead, we have to look at the number of exception parameters and calculate the size. + _ASSERTE(pRecord != NULL); + WriteExceptionRecordHelper(espOSRecord, pRecord); + espRecord = CORDB_ADDRESS_TO_PTR(espOSRecord); + + esp = min(espOSContext, espOSRecord); + } + } - // The managed exception may not be related to the unhandled exception for which we are trying to - // hijack. An example would be when a thread hits a managed exception, VS tries to do func eval on - // the thread, but the func eval causes an unhandled exception (e.g. AV in mscorwks.dll). In this - // case, the pointers stored on the ExInfo are closer to the root than the current SP of the thread. - // The check below makes sure we don't reuse the pointers in this case. - if (espOSContext < esp) + // If we haven't reused the pointers, then push everything at the leaf of the stack. + if (espContext == NULL) { - SafeWriteStructOrThrow(espOSContext, &ctx); - espContext = CORDB_ADDRESS_TO_PTR(espOSContext); + _ASSERTE(espRecord == NULL); - // We should have an EXCEPTION_RECORD if we are hijacked at an exception. - // We need to be careful when we overwrite the exception record. On x86, the OS doesn't - // always push the full record onto the stack, and so we can't blindly use sizeof(EXCEPTION_RECORD). - // Instead, we have to look at the number of exception parameters and calculate the size. - _ASSERTE(pRecord != NULL); - WriteExceptionRecordHelper(espOSRecord, pRecord); - espRecord = CORDB_ADDRESS_TO_PTR(espOSRecord); + // Push on full Context and ExceptionRecord structures. We'll then push pointers to these, + // and those pointers will serve as the actual args to the function. + espContext = CORDB_ADDRESS_TO_PTR(PushHelper(&esp, &ctx, TRUE)); - esp = min(espOSContext, espOSRecord); + // If caller didn't pass an exception-record, then we're not being hijacked at an exception. + // We'll just pass NULL for the exception-record to the Hijack function. + if (pRecord != NULL) + { + espRecord = CORDB_ADDRESS_TO_PTR(PushHelper(&esp, pRecord, TRUE)); + } } - } - - // If we haven't reused the pointers, then push everything at the leaf of the stack. - if (espContext == NULL) - { - _ASSERTE(espRecord == NULL); - - // Push on full Context and ExceptionRecord structures. We'll then push pointers to these, - // and those pointers will serve as the actual args to the function. - espContext = CORDB_ADDRESS_TO_PTR(PushHelper(&esp, &ctx, TRUE)); - // If caller didn't pass an exception-record, then we're not being hijacked at an exception. - // We'll just pass NULL for the exception-record to the Hijack function. - if (pRecord != NULL) + if(pRemoteContextAddr != NULL) { - espRecord = CORDB_ADDRESS_TO_PTR(PushHelper(&esp, pRecord, TRUE)); + *pRemoteContextAddr = PTR_TO_CORDB_ADDRESS(espContext); } - } - - if(pRemoteContextAddr != NULL) - { - *pRemoteContextAddr = PTR_TO_CORDB_ADDRESS(espContext); - } - - // - // Push args onto the stack to be able to call the hijack function - // - // Prototype of hijack is: - // void __stdcall ExceptionHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRecord, EHijackReason, void * pData) - // Set up everything so that the hijack stub can just do a "call" instruction. - // - // Regarding stack overflow: We could do an explicit check against the thread's stack base limit. - // However, we don't need an explicit overflow check because if the stack does overflow, - // the hijack will just hit a regular stack-overflow exception. -#if defined(TARGET_X86) // TARGET - // X86 calling convention is to push args on the stack in reverse order. - // If we fail here, the stack is written, but esp hasn't been committed yet so it shouldn't matter. - PushHelper(&esp, &pData, TRUE); - PushHelper(&esp, &reason, TRUE); - PushHelper(&esp, &espRecord, TRUE); - PushHelper(&esp, &espContext, TRUE); -#elif defined (TARGET_AMD64) // TARGET - // AMD64 calling convention is to place first 4 parameters in: rcx, rdx, r8 and r9 - ctx.Rcx = (DWORD64) espContext; - ctx.Rdx = (DWORD64) espRecord; - ctx.R8 = (DWORD64) reason; - ctx.R9 = (DWORD64) pData; - - // Caller must allocate stack space to spill for args. - // Push the arguments onto the outgoing argument homes. - // Make sure we push pointer-sized values to keep the stack aligned. - PushHelper(&esp, reinterpret_cast(&(ctx.R9)), FALSE); - PushHelper(&esp, reinterpret_cast(&(ctx.R8)), FALSE); - PushHelper(&esp, reinterpret_cast(&(ctx.Rdx)), FALSE); - PushHelper(&esp, reinterpret_cast(&(ctx.Rcx)), FALSE); -#elif defined(TARGET_ARM) - ctx.R0 = (DWORD)espContext; - ctx.R1 = (DWORD)espRecord; - ctx.R2 = (DWORD)reason; - ctx.R3 = (DWORD)pData; -#elif defined(TARGET_ARM64) - ctx.X0 = (DWORD64)espContext; - ctx.X1 = (DWORD64)espRecord; - ctx.X2 = (DWORD64)reason; - ctx.X3 = (DWORD64)pData; -#else - PORTABILITY_ASSERT("CordbThread::HijackForUnhandledException is not implemented on this platform."); -#endif - SetSP(&ctx, CORDB_ADDRESS_TO_TADDR(esp)); + // + // Push args onto the stack to be able to call the hijack function + // - // @dbgtodo cross-plat - not cross-platform safe - SetIP(&ctx, pfnHijackFunction); + // Prototype of hijack is: + // void __stdcall ExceptionHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRecord, EHijackReason, void * pData) + // Set up everything so that the hijack stub can just do a "call" instruction. + // + // Regarding stack overflow: We could do an explicit check against the thread's stack base limit. + // However, we don't need an explicit overflow check because if the stack does overflow, + // the hijack will just hit a regular stack-overflow exception. + #if defined(TARGET_X86) // TARGET + // X86 calling convention is to push args on the stack in reverse order. + // If we fail here, the stack is written, but esp hasn't been committed yet so it shouldn't matter. + PushHelper(&esp, &pData, TRUE); + PushHelper(&esp, &reason, TRUE); + PushHelper(&esp, &espRecord, TRUE); + PushHelper(&esp, &espContext, TRUE); + #elif defined (TARGET_AMD64) // TARGET + // AMD64 calling convention is to place first 4 parameters in: rcx, rdx, r8 and r9 + ctx.Rcx = (DWORD64) espContext; + ctx.Rdx = (DWORD64) espRecord; + ctx.R8 = (DWORD64) reason; + ctx.R9 = (DWORD64) pData; + + // Caller must allocate stack space to spill for args. + // Push the arguments onto the outgoing argument homes. + // Make sure we push pointer-sized values to keep the stack aligned. + PushHelper(&esp, reinterpret_cast(&(ctx.R9)), FALSE); + PushHelper(&esp, reinterpret_cast(&(ctx.R8)), FALSE); + PushHelper(&esp, reinterpret_cast(&(ctx.Rdx)), FALSE); + PushHelper(&esp, reinterpret_cast(&(ctx.Rcx)), FALSE); + #elif defined(TARGET_ARM) + ctx.R0 = (DWORD)espContext; + ctx.R1 = (DWORD)espRecord; + ctx.R2 = (DWORD)reason; + ctx.R3 = (DWORD)pData; + #elif defined(TARGET_ARM64) + ctx.X0 = (DWORD64)espContext; + ctx.X1 = (DWORD64)espRecord; + ctx.X2 = (DWORD64)reason; + ctx.X3 = (DWORD64)pData; + #else + PORTABILITY_ASSERT("CordbThread::HijackForUnhandledException is not implemented on this platform."); + #endif + SetSP(&ctx, CORDB_ADDRESS_TO_TADDR(esp)); + + // @dbgtodo cross-plat - not cross-platform safe + SetIP(&ctx, pfnHijackFunction); - // - // Commit the context. - // - hr = m_pMutableTarget->SetThreadContext(dwThreadId, sizeof(DT_CONTEXT), reinterpret_cast (&ctx)); - IfFailThrow(hr); + // + // Commit the context. + // + hr = m_pMutableTarget->SetThreadContext(dwThreadId, sizeof(DT_CONTEXT), reinterpret_cast (&ctx)); + IfFailThrow(hr); + } + EX_CATCH_HRESULT(hr); + return hr; } // Return the filter CONTEXT on the LS. -VMPTR_CONTEXT DacDbiInterfaceImpl::GetManagedStoppedContext(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::GetManagedStoppedContext(VMPTR_Thread vmThread, OUT VMPTR_CONTEXT * pRetVal) { DD_ENTER_MAY_THROW; - VMPTR_CONTEXT vmContext = VMPTR_CONTEXT::NullPtr(); - - Thread * pThread = vmThread.GetDacPtr(); - if (pThread->GetInteropDebuggingHijacked()) - { - _ASSERTE(!ISREDIRECTEDTHREAD(pThread)); - vmContext = VMPTR_CONTEXT::NullPtr(); - } - else + HRESULT hr = S_OK; + EX_TRY { - DT_CONTEXT * pLSContext = reinterpret_cast(pThread->GetFilterContext()); - if (pLSContext != NULL) + + VMPTR_CONTEXT vmContext = VMPTR_CONTEXT::NullPtr(); + + Thread * pThread = vmThread.GetDacPtr(); + if (pThread->GetInteropDebuggingHijacked()) { _ASSERTE(!ISREDIRECTEDTHREAD(pThread)); - vmContext.SetHostPtr(pLSContext); + vmContext = VMPTR_CONTEXT::NullPtr(); } - else if (ISREDIRECTEDTHREAD(pThread)) + else { - pLSContext = reinterpret_cast(GETREDIRECTEDCONTEXT(pThread)); - _ASSERTE(pLSContext != NULL); - + DT_CONTEXT * pLSContext = reinterpret_cast(pThread->GetFilterContext()); if (pLSContext != NULL) { + _ASSERTE(!ISREDIRECTEDTHREAD(pThread)); vmContext.SetHostPtr(pLSContext); } + else if (ISREDIRECTEDTHREAD(pThread)) + { + pLSContext = reinterpret_cast(GETREDIRECTEDCONTEXT(pThread)); + _ASSERTE(pLSContext != NULL); + + if (pLSContext != NULL) + { + vmContext.SetHostPtr(pLSContext); + } + } } - } - return vmContext; + *pRetVal = vmContext; + } + EX_CATCH_HRESULT(hr); + return hr; } // Return a TargetBuffer for the raw vararg signature. -TargetBuffer DacDbiInterfaceImpl::GetVarArgSig(CORDB_ADDRESS VASigCookieAddr, - CORDB_ADDRESS * pArgBase) +HRESULT DacDbiInterfaceImpl::GetVarArgSig(CORDB_ADDRESS VASigCookieAddr, OUT CORDB_ADDRESS * pArgBase, OUT TargetBuffer * pRetVal) { DD_ENTER_MAY_THROW; - _ASSERTE(pArgBase != NULL); - *pArgBase = (CORDB_ADDRESS)NULL; + HRESULT hr = S_OK; + EX_TRY + { + + _ASSERTE(pArgBase != NULL); + *pArgBase = (CORDB_ADDRESS)NULL; - // First, read the VASigCookie pointer. - TADDR taVASigCookie = (TADDR)NULL; - SafeReadStructOrThrow(VASigCookieAddr, &taVASigCookie); + // First, read the VASigCookie pointer. + TADDR taVASigCookie = (TADDR)NULL; + SafeReadStructOrThrow(VASigCookieAddr, &taVASigCookie); - // Now create a DAC copy of VASigCookie. - VASigCookie * pVACookie = PTR_VASigCookie(taVASigCookie); + // Now create a DAC copy of VASigCookie. + VASigCookie * pVACookie = PTR_VASigCookie(taVASigCookie); - // Figure out where the first argument is. -#if defined(TARGET_X86) // (STACK_GROWS_DOWN_ON_ARGS_WALK) - *pArgBase = VASigCookieAddr + pVACookie->sizeOfArgs; -#else // !TARGET_X86 (STACK_GROWS_UP_ON_ARGS_WALK) - *pArgBase = VASigCookieAddr + sizeof(VASigCookie *); -#endif // !TARGET_X86 (STACK_GROWS_UP_ON_ARGS_WALK) + // Figure out where the first argument is. + #if defined(TARGET_X86) // (STACK_GROWS_DOWN_ON_ARGS_WALK) + *pArgBase = VASigCookieAddr + pVACookie->sizeOfArgs; + #else // !TARGET_X86 (STACK_GROWS_UP_ON_ARGS_WALK) + *pArgBase = VASigCookieAddr + sizeof(VASigCookie *); + #endif // !TARGET_X86 (STACK_GROWS_UP_ON_ARGS_WALK) - return TargetBuffer(PTR_TO_CORDB_ADDRESS(pVACookie->signature.GetRawSig()), - pVACookie->signature.GetRawSigLen()); + *pRetVal = TargetBuffer(PTR_TO_CORDB_ADDRESS(pVACookie->signature.GetRawSig()), + pVACookie->signature.GetRawSigLen()); + } + EX_CATCH_HRESULT(hr); + return hr; } // returns TRUE if the type requires 8-byte alignment -BOOL DacDbiInterfaceImpl::RequiresAlign8(VMPTR_TypeHandle thExact) +HRESULT DacDbiInterfaceImpl::RequiresAlign8(VMPTR_TypeHandle thExact, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; -#ifdef FEATURE_64BIT_ALIGNMENT - TypeHandle th = TypeHandle::FromPtr(thExact.GetDacPtr()); - PTR_MethodTable mt = th.AsMethodTable(); + HRESULT hr = S_OK; + EX_TRY + { + + #ifdef FEATURE_64BIT_ALIGNMENT + TypeHandle th = TypeHandle::FromPtr(thExact.GetDacPtr()); + PTR_MethodTable mt = th.AsMethodTable(); - return mt->RequiresAlign8(); -#else - ThrowHR(E_NOTIMPL); -#endif + *pResult = mt->RequiresAlign8(); + #else + ThrowHR(E_NOTIMPL); + #endif + } + EX_CATCH_HRESULT(hr); + return hr; } // Resolve the raw generics token to the real generics type token. The resolution is based on the // given index. -GENERICS_TYPE_TOKEN DacDbiInterfaceImpl::ResolveExactGenericArgsToken(DWORD dwExactGenericArgsTokenIndex, - GENERICS_TYPE_TOKEN rawToken) +HRESULT DacDbiInterfaceImpl::ResolveExactGenericArgsToken(DWORD dwExactGenericArgsTokenIndex, GENERICS_TYPE_TOKEN rawToken, OUT GENERICS_TYPE_TOKEN * pRetVal) { DD_ENTER_MAY_THROW; - if (dwExactGenericArgsTokenIndex == 0) + HRESULT hr = S_OK; + EX_TRY { - // In a rare case of VS4Mac debugging VS4Mac ARM64 optimized code we get a null generics argument token. We aren't sure - // why the token is null, it may be a bug or it may be by design in the runtime. In the interest of time we are working - // around the issue rather than investigating the root cause. This workaround should only cause us to degrade generic - // types from exact type parameters to approximate or canonical type parameters. In the future if we discover this issue - // is happening more frequently than we expect or the workaround is more impactful than we expect we may need to remove - // this workaround and resolve the underlying issue. - if (rawToken == 0) + + if (dwExactGenericArgsTokenIndex == 0) { - return rawToken; - } - // In this case the real generics type token is the MethodTable of the "this" object. - // Note that we want the target address here. + // In a rare case of VS4Mac debugging VS4Mac ARM64 optimized code we get a null generics argument token. We aren't sure + // why the token is null, it may be a bug or it may be by design in the runtime. In the interest of time we are working + // around the issue rather than investigating the root cause. This workaround should only cause us to degrade generic + // types from exact type parameters to approximate or canonical type parameters. In the future if we discover this issue + // is happening more frequently than we expect or the workaround is more impactful than we expect we may need to remove + // this workaround and resolve the underlying issue. + if (rawToken == 0) + { + *pRetVal = rawToken; + } + else + { + // In this case the real generics type token is the MethodTable of the "this" object. + // Note that we want the target address here. - // Incoming rawToken is actually a PTR_Object for the 'this' pointer. - // Need to do some casting to convert GENERICS_TYPE_TOKEN --> PTR_Object - TADDR addrObjThis = CORDB_ADDRESS_TO_TADDR(rawToken); - PTR_Object pObjThis = dac_cast(addrObjThis); + // Incoming rawToken is actually a PTR_Object for the 'this' pointer. + // Need to do some casting to convert GENERICS_TYPE_TOKEN --> PTR_Object + TADDR addrObjThis = CORDB_ADDRESS_TO_TADDR(rawToken); + PTR_Object pObjThis = dac_cast(addrObjThis); - PTR_MethodTable pMT = pObjThis->GetMethodTable(); + PTR_MethodTable pMT = pObjThis->GetMethodTable(); - // Now package up the PTR_MethodTable back into a GENERICS_TYPE_TOKEN - TADDR addrMT = dac_cast(pMT); - GENERICS_TYPE_TOKEN realToken = (GENERICS_TYPE_TOKEN) addrMT; - return realToken; - } - else if (dwExactGenericArgsTokenIndex == (DWORD)ICorDebugInfo::TYPECTXT_ILNUM) - { - // rawToken is already initialized correctly. Nothing to do here. - return rawToken; + // Now package up the PTR_MethodTable back into a GENERICS_TYPE_TOKEN + TADDR addrMT = dac_cast(pMT); + GENERICS_TYPE_TOKEN realToken = (GENERICS_TYPE_TOKEN) addrMT; + *pRetVal = realToken; + } + } + else if (dwExactGenericArgsTokenIndex == (DWORD)ICorDebugInfo::TYPECTXT_ILNUM) + { + // rawToken is already initialized correctly. Nothing to do here. + *pRetVal = rawToken; + } + else + { + // The index of the generics type token should not be anything else. + // This is indeed an error condition, and so we throw here. + _ASSERTE(!"DDII::REGAT - Unexpected generics type token index."); + ThrowHR(CORDBG_E_TARGET_INCONSISTENT); + } } - - // The index of the generics type token should not be anything else. - // This is indeed an error condition, and so we throw here. - _ASSERTE(!"DDII::REGAT - Unexpected generics type token index."); - ThrowHR(CORDBG_E_TARGET_INCONSISTENT); + EX_CATCH_HRESULT(hr); + return hr; } // Check if the given method is a DiagnosticHidden or an LCG method. -IDacDbiInterface::DynamicMethodType DacDbiInterfaceImpl::IsDiagnosticsHiddenOrLCGMethod(VMPTR_MethodDesc vmMethodDesc) +HRESULT DacDbiInterfaceImpl::IsDiagnosticsHiddenOrLCGMethod(VMPTR_MethodDesc vmMethodDesc, OUT DynamicMethodType * pRetVal) { DD_ENTER_MAY_THROW; - MethodDesc * pMD = vmMethodDesc.GetDacPtr(); - - if (pMD->IsDiagnosticsHidden()) - { - return kDiagnosticHidden; - } - else if (pMD->IsLCGMethod()) - { - return kLCGMethod; - } - else + HRESULT hr = S_OK; + EX_TRY { - return kNone; + + MethodDesc * pMD = vmMethodDesc.GetDacPtr(); + + if (pMD->IsDiagnosticsHidden()) + { + *pRetVal = kDiagnosticHidden; + } + else if (pMD->IsLCGMethod()) + { + *pRetVal = kLCGMethod; + } + else + { + *pRetVal = kNone; + } } + EX_CATCH_HRESULT(hr); + return hr; } //--------------------------------------------------------------------------------------- @@ -5366,47 +5876,54 @@ BOOL DacDbiInterfaceImpl::IsThreadAtGCSafePlace(VMPTR_Thread vmThread) // Return the partial user state except for USER_UNSAFE_POINT // -CorDebugUserState DacDbiInterfaceImpl::GetPartialUserState(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::GetPartialUserState(VMPTR_Thread vmThread, OUT CorDebugUserState * pRetVal) { DD_ENTER_MAY_THROW; - Thread * pThread = vmThread.GetDacPtr(); - Thread::ThreadState ts = pThread->GetSnapshotState(); - - UINT result = 0; - if (ts & Thread::TS_Background) + HRESULT hr = S_OK; + EX_TRY { - result |= USER_BACKGROUND; - } - if (ts & Thread::TS_Unstarted) - { - result |= USER_UNSTARTED; - } + Thread * pThread = vmThread.GetDacPtr(); + Thread::ThreadState ts = pThread->GetSnapshotState(); - // Don't report a StopRequested if the thread has actually stopped. - if (ts & Thread::TS_Dead) - { - result |= USER_STOPPED; - } + UINT result = 0; + if (ts & Thread::TS_Background) + { + result |= USER_BACKGROUND; + } - // Don't report Thread::TS_AbortRequested + if (ts & Thread::TS_Unstarted) + { + result |= USER_UNSTARTED; + } - // The interruptible flag is unreliable (see issue 699245) - // The Debugger_SleepWaitJoin is always accurate when it is present, but it is still - // just a band-aid fix to cover some of the race conditions interruptible has. + // Don't report a StopRequested if the thread has actually stopped. + if (ts & Thread::TS_Dead) + { + result |= USER_STOPPED; + } - if (ts & Thread::TS_Interruptible || pThread->HasThreadStateNC(Thread::TSNC_DebuggerSleepWaitJoin)) - { - result |= USER_WAIT_SLEEP_JOIN; - } + // Don't report Thread::TS_AbortRequested - if (pThread->IsThreadPoolThread()) - { - result |= USER_THREADPOOL; - } + // The interruptible flag is unreliable (see issue 699245) + // The Debugger_SleepWaitJoin is always accurate when it is present, but it is still + // just a band-aid fix to cover some of the race conditions interruptible has. + + if (ts & Thread::TS_Interruptible || pThread->HasThreadStateNC(Thread::TSNC_DebuggerSleepWaitJoin)) + { + result |= USER_WAIT_SLEEP_JOIN; + } + + if (pThread->IsThreadPoolThread()) + { + result |= USER_THREADPOOL; + } - return (CorDebugUserState)result; + *pRetVal = (CorDebugUserState)result; + } + EX_CATCH_HRESULT(hr); + return hr; } //--------------------------------------------------------------------------------------- @@ -5495,96 +6012,119 @@ void DacDbiInterfaceImpl::LookupEnCVersions(Module* pModule, // Arguments: none // Return Value: The remote address of the Debugger control block allocated on the helper thread // if it has been successfully allocated or NULL otherwise. -CORDB_ADDRESS DacDbiInterfaceImpl::GetDebuggerControlBlockAddress() +HRESULT DacDbiInterfaceImpl::GetDebuggerControlBlockAddress(OUT CORDB_ADDRESS * pRetVal) { DD_ENTER_MAY_THROW; - if ((g_pDebugger != NULL) && - (g_pDebugger->m_pRCThread != NULL)) + HRESULT hr = S_OK; + EX_TRY { - return CORDB_ADDRESS(dac_cast(g_pDebugger->m_pRCThread->GetDCB())); - } - return (CORDB_ADDRESS)NULL; + if ((g_pDebugger != NULL) && + (g_pDebugger->m_pRCThread != NULL)) + { + *pRetVal = CORDB_ADDRESS(dac_cast(g_pDebugger->m_pRCThread->GetDCB())); + } + else + { + *pRetVal = (CORDB_ADDRESS)NULL; + } + } + EX_CATCH_HRESULT(hr); + return hr; } // DacDbi API: Get the context for a particular thread of the target process -void DacDbiInterfaceImpl::GetContext(VMPTR_Thread vmThread, DT_CONTEXT * pContextBuffer) +HRESULT DacDbiInterfaceImpl::GetContext(VMPTR_Thread vmThread, DT_CONTEXT * pContextBuffer) { DD_ENTER_MAY_THROW - _ASSERTE(pContextBuffer != NULL); + HRESULT hr = S_OK; + EX_TRY + { + + _ASSERTE(pContextBuffer != NULL); - Thread * pThread = vmThread.GetDacPtr(); + Thread * pThread = vmThread.GetDacPtr(); - // @dbgtodo Once the filter context is removed, then we should always - // start with the leaf CONTEXT. - DT_CONTEXT * pFilterContext = reinterpret_cast(pThread->GetFilterContext()); + // @dbgtodo Once the filter context is removed, then we should always + // start with the leaf CONTEXT. + DT_CONTEXT * pFilterContext = reinterpret_cast(pThread->GetFilterContext()); - if (pFilterContext == NULL) - { - // If the filter context is NULL, then we use the true context of the thread. - pContextBuffer->ContextFlags = DT_CONTEXT_ALL; - HRESULT hr = m_pTarget->GetThreadContext(pThread->GetOSThreadId(), - pContextBuffer->ContextFlags, - sizeof(DT_CONTEXT), - reinterpret_cast(pContextBuffer)); - if (hr == E_NOTIMPL) + if (pFilterContext == NULL) { - // GetThreadContext is not implemented on this data target. - // That's why we have to make do with context we can obtain from Frames explicitly stored in Thread object. - // It suffices for managed debugging stackwalk. - REGDISPLAY tmpRd = {}; - T_CONTEXT tmpContext = {}; - FillRegDisplay(&tmpRd, &tmpContext); - - // Going through thread Frames and looking for first (deepest one) one that - // that has context available for stackwalking (SP and PC) - // For example: RedirectedThreadFrame, InlinedCallFrame, DynamicHelperFrame, CLRToCOMMethodFrame - Frame *frame = pThread->GetFrame(); - while (frame != NULL && frame != FRAME_TOP) + // If the filter context is NULL, then we use the true context of the thread. + pContextBuffer->ContextFlags = DT_CONTEXT_ALL; + HRESULT hr = m_pTarget->GetThreadContext(pThread->GetOSThreadId(), + pContextBuffer->ContextFlags, + sizeof(DT_CONTEXT), + reinterpret_cast(pContextBuffer)); + if (hr == E_NOTIMPL) { - frame->UpdateRegDisplay(&tmpRd); - if (GetRegdisplaySP(&tmpRd) != 0 && GetControlPC(&tmpRd) != 0) + // GetThreadContext is not implemented on this data target. + // That's why we have to make do with context we can obtain from Frames explicitly stored in Thread object. + // It suffices for managed debugging stackwalk. + REGDISPLAY tmpRd = {}; + T_CONTEXT tmpContext = {}; + FillRegDisplay(&tmpRd, &tmpContext); + + // Going through thread Frames and looking for first (deepest one) one that + // that has context available for stackwalking (SP and PC) + // For example: RedirectedThreadFrame, InlinedCallFrame, DynamicHelperFrame, CLRToCOMMethodFrame + Frame *frame = pThread->GetFrame(); + while (frame != NULL && frame != FRAME_TOP) { - UpdateContextFromRegDisp(&tmpRd, &tmpContext); - CopyMemory(pContextBuffer, &tmpContext, sizeof(*pContextBuffer)); - pContextBuffer->ContextFlags = DT_CONTEXT_CONTROL -#if defined(TARGET_AMD64) || defined(TARGET_ARM) - | DT_CONTEXT_INTEGER // DT_CONTEXT_INTEGER is needed to include the frame register on ARM32 and AMD64 architectures - // DT_CONTEXT_CONTROL already includes the frame register for X86 and ARM64 architectures -#endif - ; - return; + frame->UpdateRegDisplay(&tmpRd); + if (GetRegdisplaySP(&tmpRd) != 0 && GetControlPC(&tmpRd) != 0) + { + UpdateContextFromRegDisp(&tmpRd, &tmpContext); + CopyMemory(pContextBuffer, &tmpContext, sizeof(*pContextBuffer)); + pContextBuffer->ContextFlags = DT_CONTEXT_CONTROL + #if defined(TARGET_AMD64) || defined(TARGET_ARM) + | DT_CONTEXT_INTEGER // DT_CONTEXT_INTEGER is needed to include the frame register on ARM32 and AMD64 architectures + // DT_CONTEXT_CONTROL already includes the frame register for X86 and ARM64 architectures + #endif + ; + return hr; + } + frame = frame->Next(); } - frame = frame->Next(); - } - // It looks like this thread is not running managed code. - ZeroMemory(pContextBuffer, sizeof(*pContextBuffer)); + // It looks like this thread is not running managed code. + ZeroMemory(pContextBuffer, sizeof(*pContextBuffer)); + } + else + { + IfFailThrow(hr); + } } else { - IfFailThrow(hr); + *pContextBuffer = *pFilterContext; } - } - else - { - *pContextBuffer = *pFilterContext; - } -} // DacDbiInterfaceImpl::GetContext + } + EX_CATCH_HRESULT(hr); + return hr; +} // Create a VMPTR_Object from a target object address // @dbgtodo validate the VMPTR_Object is in fact a object, possibly by DACizing // Object::Validate -VMPTR_Object DacDbiInterfaceImpl::GetObject(CORDB_ADDRESS ptr) +HRESULT DacDbiInterfaceImpl::GetObject(CORDB_ADDRESS ptr, OUT VMPTR_Object * pRetVal) { DD_ENTER_MAY_THROW; - VMPTR_Object vmObj = VMPTR_Object::NullPtr(); - vmObj.SetDacTargetPtr(CORDB_ADDRESS_TO_TADDR(ptr)); - return vmObj; + HRESULT hr = S_OK; + EX_TRY + { + + VMPTR_Object vmObj = VMPTR_Object::NullPtr(); + vmObj.SetDacTargetPtr(CORDB_ADDRESS_TO_TADDR(ptr)); + *pRetVal = vmObj; + } + EX_CATCH_HRESULT(hr); + return hr; } HRESULT DacDbiInterfaceImpl::EnableNGENPolicy(CorDebugNGENPolicy ePolicy) @@ -5611,56 +6151,77 @@ typedef DPTR(OBJECTREF) PTR_ObjectRef; // Create a VMPTR_Object from an address which points to a reference to an object // @dbgtodo validate the VMPTR_Object is in fact a object, possibly by DACizing // Object::Validate -VMPTR_Object DacDbiInterfaceImpl::GetObjectFromRefPtr(CORDB_ADDRESS ptr) +HRESULT DacDbiInterfaceImpl::GetObjectFromRefPtr(CORDB_ADDRESS ptr, OUT VMPTR_Object * pRetVal) { DD_ENTER_MAY_THROW; - VMPTR_Object vmObj = VMPTR_Object::NullPtr(); - PTR_ObjectRef objRef = PTR_ObjectRef(CORDB_ADDRESS_TO_TADDR(ptr)); - vmObj.SetDacTargetPtr(PTR_TO_TADDR(*objRef)); + HRESULT hr = S_OK; + EX_TRY + { + + VMPTR_Object vmObj = VMPTR_Object::NullPtr(); + PTR_ObjectRef objRef = PTR_ObjectRef(CORDB_ADDRESS_TO_TADDR(ptr)); + vmObj.SetDacTargetPtr(PTR_TO_TADDR(*objRef)); - return vmObj; + *pRetVal = vmObj; + } + EX_CATCH_HRESULT(hr); + return hr; } // Create a VMPTR_OBJECTHANDLE from a handle -VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetVmObjectHandle(CORDB_ADDRESS handleAddress) +HRESULT DacDbiInterfaceImpl::GetVmObjectHandle(CORDB_ADDRESS handleAddress, OUT VMPTR_OBJECTHANDLE * pRetVal) { DD_ENTER_MAY_THROW; - VMPTR_OBJECTHANDLE vmObjHandle = VMPTR_OBJECTHANDLE::NullPtr(); - vmObjHandle.SetDacTargetPtr(CORDB_ADDRESS_TO_TADDR(handleAddress)); + HRESULT hr = S_OK; + EX_TRY + { + + VMPTR_OBJECTHANDLE vmObjHandle = VMPTR_OBJECTHANDLE::NullPtr(); + vmObjHandle.SetDacTargetPtr(CORDB_ADDRESS_TO_TADDR(handleAddress)); - return vmObjHandle; + *pRetVal = vmObjHandle; + } + EX_CATCH_HRESULT(hr); + return hr; } // Validate that the VMPTR_OBJECTHANDLE refers to a legitimate managed object -BOOL DacDbiInterfaceImpl::IsVmObjectHandleValid(VMPTR_OBJECTHANDLE vmHandle) +HRESULT DacDbiInterfaceImpl::IsVmObjectHandleValid(VMPTR_OBJECTHANDLE vmHandle, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - BOOL ret = FALSE; - // this may cause unallocated debuggee memory to be read - // SEH exceptions will be caught + HRESULT hr = S_OK; EX_TRY { - OBJECTREF objRef = ObjectFromHandle((OBJECTHANDLE)vmHandle.GetDacPtr()); - // NULL is certainly valid... - if (objRef != NULL) + BOOL ret = FALSE; + // this may cause unallocated debuggee memory to be read + // SEH exceptions will be caught + EX_TRY { - if (objRef->ValidateObjectWithPossibleAV()) + OBJECTREF objRef = ObjectFromHandle((OBJECTHANDLE)vmHandle.GetDacPtr()); + + // NULL is certainly valid... + if (objRef != NULL) { - ret = TRUE; + if (objRef->ValidateObjectWithPossibleAV()) + { + ret = TRUE; + } } } - } - EX_CATCH - { - } - EX_END_CATCH + EX_CATCH + { + } + EX_END_CATCH - return ret; + *pResult = ret; + } + EX_CATCH_HRESULT(hr); + return hr; } // determines if the specified module is a WinRT module @@ -5675,31 +6236,52 @@ HRESULT DacDbiInterfaceImpl::IsWinRTModule(VMPTR_Module vmModule, BOOL& isWinRT) } // Determines the app domain id for the object referred to by a given VMPTR_OBJECTHANDLE -ULONG DacDbiInterfaceImpl::GetAppDomainIdFromVmObjectHandle(VMPTR_OBJECTHANDLE vmHandle) +HRESULT DacDbiInterfaceImpl::GetAppDomainIdFromVmObjectHandle(VMPTR_OBJECTHANDLE vmHandle, OUT ULONG * pRetVal) { DD_ENTER_MAY_THROW; - return DefaultADID; + HRESULT hr = S_OK; + EX_TRY + { + + *pRetVal = DefaultADID; + } + EX_CATCH_HRESULT(hr); + return hr; } // Get the target address from a VMPTR_OBJECTHANDLE, i.e., the handle address -CORDB_ADDRESS DacDbiInterfaceImpl::GetHandleAddressFromVmHandle(VMPTR_OBJECTHANDLE vmHandle) +HRESULT DacDbiInterfaceImpl::GetHandleAddressFromVmHandle(VMPTR_OBJECTHANDLE vmHandle, OUT CORDB_ADDRESS * pRetVal) { DD_ENTER_MAY_THROW; - CORDB_ADDRESS handle = vmHandle.GetDacPtr(); + HRESULT hr = S_OK; + EX_TRY + { + + CORDB_ADDRESS handle = vmHandle.GetDacPtr(); - return handle; + *pRetVal = handle; + } + EX_CATCH_HRESULT(hr); + return hr; } // Create a TargetBuffer which describes the location of the object -TargetBuffer DacDbiInterfaceImpl::GetObjectContents(VMPTR_Object vmObj) +HRESULT DacDbiInterfaceImpl::GetObjectContents(VMPTR_Object obj, OUT TargetBuffer * pRetVal) { DD_ENTER_MAY_THROW; - PTR_Object objPtr = vmObj.GetDacPtr(); - _ASSERTE(objPtr->GetSize() <= 0xffffffff); - return TargetBuffer(PTR_TO_TADDR(objPtr), (ULONG)objPtr->GetSize()); + HRESULT hr = S_OK; + EX_TRY + { + PTR_Object objPtr = obj.GetDacPtr(); + + _ASSERTE(objPtr->GetSize() <= 0xffffffff); + *pRetVal = TargetBuffer(PTR_TO_TADDR(objPtr), (ULONG)objPtr->GetSize()); + } + EX_CATCH_HRESULT(hr); + return hr; } // ============================================================================ @@ -5865,234 +6447,279 @@ void DacDbiInterfaceImpl::InitObjectData(PTR_Object objPtr, // } // Initializes the objRef and typedByRefType fields of pObjectData (type info for the referent). -void DacDbiInterfaceImpl::GetTypedByRefInfo(CORDB_ADDRESS pTypedByRef, - VMPTR_AppDomain vmAppDomain, - DebuggerIPCE_ObjectData * pObjectData) +HRESULT DacDbiInterfaceImpl::GetTypedByRefInfo(CORDB_ADDRESS pTypedByRef, VMPTR_AppDomain vmAppDomain, DebuggerIPCE_ObjectData * pObjectData) { DD_ENTER_MAY_THROW; - // pTypedByRef is really the address of a TypedByRef struct rather than of a normal object. - // The data field of the TypedByRef struct is the actual object ref. - PTR_TypedByRef refAddr = PTR_TypedByRef(TADDR(pTypedByRef)); + HRESULT hr = S_OK; + EX_TRY + { + + // pTypedByRef is really the address of a TypedByRef struct rather than of a normal object. + // The data field of the TypedByRef struct is the actual object ref. + PTR_TypedByRef refAddr = PTR_TypedByRef(TADDR(pTypedByRef)); - _ASSERTE(refAddr != NULL); - _ASSERTE(pObjectData != NULL); + _ASSERTE(refAddr != NULL); + _ASSERTE(pObjectData != NULL); - // The type of the referent is in the type field of the TypedByRef. We need to initialize the object - // data type information. - TypeHandleToBasicTypeInfo(refAddr->type, - &(pObjectData->typedByrefInfo.typedByrefType), - vmAppDomain.GetDacPtr()); + // The type of the referent is in the type field of the TypedByRef. We need to initialize the object + // data type information. + TypeHandleToBasicTypeInfo(refAddr->type, + &(pObjectData->typedByrefInfo.typedByrefType), + vmAppDomain.GetDacPtr()); - // The reference to the object is in the data field of the TypedByRef. - CORDB_ADDRESS tempRef = dac_cast(refAddr->data); - pObjectData->objRef = CORDB_ADDRESS_TO_PTR(tempRef); + // The reference to the object is in the data field of the TypedByRef. + CORDB_ADDRESS tempRef = dac_cast(refAddr->data); + pObjectData->objRef = CORDB_ADDRESS_TO_PTR(tempRef); - LOG((LF_CORDB, LL_INFO10000, "D::GASOI: sending REFANY result: " - "ref=0x%08x, cls=0x%08x, mod=0x%p\n", - pObjectData->objRef, - pObjectData->typedByrefType.metadataToken, - pObjectData->typedByrefType.vmDomainAssembly.GetDacPtr())); -} // DacDbiInterfaceImpl::GetTypedByRefInfo + LOG((LF_CORDB, LL_INFO10000, "D::GASOI: sending REFANY result: " + "ref=0x%08x, cls=0x%08x, mod=0x%p\n", + pObjectData->objRef, + pObjectData->typedByrefType.metadataToken, + pObjectData->typedByrefType.vmDomainAssembly.GetDacPtr())); + } + EX_CATCH_HRESULT(hr); + return hr; +} // Get the string data associated withn obj and put it into the pointers // DAC/DBI API // Get the string length and offset to string base for a string object -void DacDbiInterfaceImpl::GetStringData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData) +HRESULT DacDbiInterfaceImpl::GetStringData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData) { DD_ENTER_MAY_THROW; - PTR_Object objPtr = PTR_Object(TADDR(objectAddress)); - LOG((LF_CORDB, LL_INFO10000, "D::GOI: The referent is a string.\n")); - - if (objPtr->GetGCSafeMethodTable() != g_pStringClass) + HRESULT hr = S_OK; + EX_TRY { - ThrowHR(CORDBG_E_TARGET_INCONSISTENT); - } - PTR_StringObject pStrObj = dac_cast(objPtr); + PTR_Object objPtr = PTR_Object(TADDR(objectAddress)); + LOG((LF_CORDB, LL_INFO10000, "D::GOI: The referent is a string.\n")); + + if (objPtr->GetGCSafeMethodTable() != g_pStringClass) + { + ThrowHR(CORDBG_E_TARGET_INCONSISTENT); + } + + PTR_StringObject pStrObj = dac_cast(objPtr); - _ASSERTE(pStrObj != NULL); - pObjectData->stringInfo.length = pStrObj->GetStringLength(); - pObjectData->stringInfo.offsetToStringBase = (UINT_PTR) pStrObj->GetBufferOffset(); + _ASSERTE(pStrObj != NULL); + pObjectData->stringInfo.length = pStrObj->GetStringLength(); + pObjectData->stringInfo.offsetToStringBase = (UINT_PTR) pStrObj->GetBufferOffset(); -} // DacDbiInterfaceImpl::GetStringData + } + EX_CATCH_HRESULT(hr); + return hr; +} // DAC/DBI API // Get information for an array type referent of an objRef, including rank, upper and lower // bounds, element size and type, and the number of elements. -void DacDbiInterfaceImpl::GetArrayData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData) +HRESULT DacDbiInterfaceImpl::GetArrayData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData) { DD_ENTER_MAY_THROW; - PTR_Object objPtr = PTR_Object(TADDR(objectAddress)); - PTR_MethodTable pMT = objPtr->GetGCSafeMethodTable(); - - if (!objPtr->GetGCSafeTypeHandle().IsArray()) - { - LOG((LF_CORDB, LL_INFO10000, - "D::GASOI: object should be an array.\n")); - - pObjectData->objRefBad = true; - } - else + HRESULT hr = S_OK; + EX_TRY { - PTR_ArrayBase arrPtr = dac_cast(objPtr); - // this is also returned in the type information for the array - we return both for sanity checking... - pObjectData->arrayInfo.rank = arrPtr->GetRank(); - pObjectData->arrayInfo.componentCount = arrPtr->GetNumComponents(); - pObjectData->arrayInfo.offsetToArrayBase = arrPtr->GetDataPtrOffset(pMT); + PTR_Object objPtr = PTR_Object(TADDR(objectAddress)); + PTR_MethodTable pMT = objPtr->GetGCSafeMethodTable(); - if (arrPtr->IsMultiDimArray()) + if (!objPtr->GetGCSafeTypeHandle().IsArray()) { - pObjectData->arrayInfo.offsetToUpperBounds = SIZE_T(arrPtr->GetBoundsOffset(pMT)); + LOG((LF_CORDB, LL_INFO10000, + "D::GASOI: object should be an array.\n")); - pObjectData->arrayInfo.offsetToLowerBounds = SIZE_T(arrPtr->GetLowerBoundsOffset(pMT)); + pObjectData->objRefBad = true; } else { - pObjectData->arrayInfo.offsetToUpperBounds = 0; - pObjectData->arrayInfo.offsetToLowerBounds = 0; - } + PTR_ArrayBase arrPtr = dac_cast(objPtr); + + // this is also returned in the type information for the array - we return both for sanity checking... + pObjectData->arrayInfo.rank = arrPtr->GetRank(); + pObjectData->arrayInfo.componentCount = arrPtr->GetNumComponents(); + pObjectData->arrayInfo.offsetToArrayBase = arrPtr->GetDataPtrOffset(pMT); + + if (arrPtr->IsMultiDimArray()) + { + pObjectData->arrayInfo.offsetToUpperBounds = SIZE_T(arrPtr->GetBoundsOffset(pMT)); - pObjectData->arrayInfo.elementSize = arrPtr->GetComponentSize(); + pObjectData->arrayInfo.offsetToLowerBounds = SIZE_T(arrPtr->GetLowerBoundsOffset(pMT)); + } + else + { + pObjectData->arrayInfo.offsetToUpperBounds = 0; + pObjectData->arrayInfo.offsetToLowerBounds = 0; + } - LOG((LF_CORDB, LL_INFO10000, "D::GOI: array info: " - "baseOff=%d, lowerOff=%d, upperOff=%d, cnt=%d, rank=%d, rank (2) = %d," - "eleSize=%d, eleType=0x%02x\n", - pObjectData->arrayInfo.offsetToArrayBase, - pObjectData->arrayInfo.offsetToLowerBounds, - pObjectData->arrayInfo.offsetToUpperBounds, - pObjectData->arrayInfo.componentCount, - pObjectData->arrayInfo.rank, - pObjectData->objTypeData.ArrayTypeData.arrayRank, - pObjectData->arrayInfo.elementSize, - pObjectData->objTypeData.ArrayTypeData.arrayTypeArg.elementType)); + pObjectData->arrayInfo.elementSize = arrPtr->GetComponentSize(); + + LOG((LF_CORDB, LL_INFO10000, "D::GOI: array info: " + "baseOff=%d, lowerOff=%d, upperOff=%d, cnt=%d, rank=%d, rank (2) = %d," + "eleSize=%d, eleType=0x%02x\n", + pObjectData->arrayInfo.offsetToArrayBase, + pObjectData->arrayInfo.offsetToLowerBounds, + pObjectData->arrayInfo.offsetToUpperBounds, + pObjectData->arrayInfo.componentCount, + pObjectData->arrayInfo.rank, + pObjectData->objTypeData.ArrayTypeData.arrayRank, + pObjectData->arrayInfo.elementSize, + pObjectData->objTypeData.ArrayTypeData.arrayTypeArg.elementType)); + } } -} // DacDbiInterfaceImpl::GetArrayData + EX_CATCH_HRESULT(hr); + return hr; +} // DAC/DBI API: Get information about an object for which we have a reference, including the object size and // type information. -void DacDbiInterfaceImpl::GetBasicObjectInfo(CORDB_ADDRESS objectAddress, - CorElementType type, - VMPTR_AppDomain vmAppDomain, - DebuggerIPCE_ObjectData * pObjectData) +HRESULT DacDbiInterfaceImpl::GetBasicObjectInfo(CORDB_ADDRESS objectAddress, CorElementType type, VMPTR_AppDomain vmAppDomain, DebuggerIPCE_ObjectData * pObjectData) { DD_ENTER_MAY_THROW; - PTR_Object objPtr = PTR_Object(TADDR(objectAddress)); - pObjectData->objRefBad = CheckRef(objPtr); - if (pObjectData->objRefBad != true) + HRESULT hr = S_OK; + EX_TRY { - // initialize object type, size, offset information. Note: We may have a different element type - // after this. For example, we may start with E_T_CLASS but return with something more specific. - InitObjectData (objPtr, vmAppDomain, pObjectData); + + PTR_Object objPtr = PTR_Object(TADDR(objectAddress)); + pObjectData->objRefBad = CheckRef(objPtr); + if (pObjectData->objRefBad != true) + { + // initialize object type, size, offset information. Note: We may have a different element type + // after this. For example, we may start with E_T_CLASS but return with something more specific. + InitObjectData (objPtr, vmAppDomain, pObjectData); + } } -} // DacDbiInterfaceImpl::GetBasicObjectInfo + EX_CATCH_HRESULT(hr); + return hr; +} // DAC/DBI API: // Returns the thread which owns the monitor lock on an object and the acquisition count -MonitorLockInfo DacDbiInterfaceImpl::GetThreadOwningMonitorLock(VMPTR_Object vmObject) +HRESULT DacDbiInterfaceImpl::GetThreadOwningMonitorLock(VMPTR_Object vmObject, OUT MonitorLockInfo * pRetVal) { DD_ENTER_MAY_THROW; - MonitorLockInfo info; - info.lockOwner = VMPTR_Thread::NullPtr(); - info.acquisitionCount = 0; - Object* pObj = vmObject.GetDacPtr(); + HRESULT hr = S_OK; + EX_TRY + { + MonitorLockInfo info; + info.lockOwner = VMPTR_Thread::NullPtr(); + info.acquisitionCount = 0; - DWORD threadId = 0; - DWORD recursionCount = 0; - BOOL isLockHeld = pObj->GetHeader()->PassiveGetSyncBlock()->TryGetLockInfo(&threadId, &recursionCount); + Object* pObj = vmObject.GetDacPtr(); - if (!isLockHeld) - { - // The lock is not owned by any thread, so no thread owning the monitor lock - return info; - } + DWORD threadId = 0; + DWORD recursionCount = 0; + BOOL isLockHeld = pObj->GetHeader()->PassiveGetSyncBlock()->TryGetLockInfo(&threadId, &recursionCount); - Thread *pThread = ThreadStore::GetThreadList(NULL); - while (pThread != NULL) - { - if(pThread->GetThreadId() == threadId) + if (!isLockHeld) + { + *pRetVal = info; + } + else { - info.lockOwner.SetDacTargetPtr(PTR_HOST_TO_TADDR(pThread)); - info.acquisitionCount = recursionCount + 1; // The runtime tracks recursion count starting at 0, but diagnostics users expect it to start at 1. - return info; + Thread *pThread = ThreadStore::GetThreadList(NULL); + while (pThread != NULL) + { + if(pThread->GetThreadId() == threadId) + { + info.lockOwner.SetDacTargetPtr(PTR_HOST_TO_TADDR(pThread)); + info.acquisitionCount = recursionCount + 1; // The runtime tracks recursion count starting at 0, but diagnostics users expect it to start at 1. + break; + } + pThread = ThreadStore::GetThreadList(pThread); + } + if (pThread == NULL) + { + _ASSERTE(!"A thread should have been found"); + } + *pRetVal = info; } - pThread = ThreadStore::GetThreadList(pThread); } - _ASSERTE(!"A thread should have been found"); - return info; + EX_CATCH_HRESULT(hr); + return hr; } // DAC/DBI API: // Enumerate all threads waiting on the monitor event for an object -void DacDbiInterfaceImpl::EnumerateMonitorEventWaitList(VMPTR_Object vmObject, - FP_THREAD_ENUMERATION_CALLBACK fpCallback, - CALLBACK_DATA pUserData) +HRESULT DacDbiInterfaceImpl::EnumerateMonitorEventWaitList(VMPTR_Object vmObject, FP_THREAD_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData) { DD_ENTER_MAY_THROW; - Object* pObj = vmObject.GetDacPtr(); - - SyncBlock* psb = pObj->PassiveGetSyncBlock(); + HRESULT hr = S_OK; + EX_TRY + { - // no sync block means no wait list - if(psb == NULL) - return; + Object* pObj = vmObject.GetDacPtr(); - FieldDesc* pConditionTableField = (&g_CoreLib)->GetField(FIELD__MONITOR__CONDITION_TABLE); - CONDITIONAL_WEAK_TABLE_REF conditionTable = *(DPTR(CONDITIONAL_WEAK_TABLE_REF))PTR_TO_TADDR(pConditionTableField->GetStaticAddressHandle(pConditionTableField->GetBase())); + SyncBlock* psb = pObj->PassiveGetSyncBlock(); + // no sync block means no wait list + if(psb == NULL) + return hr; - OBJECTREF condition = NULL; - if (!conditionTable->TryGetValue(OBJECTREF(pObj), &condition)) - { - return; - } + FieldDesc* pConditionTableField = (&g_CoreLib)->GetField(FIELD__MONITOR__CONDITION_TABLE); + CONDITIONAL_WEAK_TABLE_REF conditionTable = *(DPTR(CONDITIONAL_WEAK_TABLE_REF))PTR_TO_TADDR(pConditionTableField->GetStaticAddressHandle(pConditionTableField->GetBase())); - MapSHash waiterToThreadMap; - FieldDesc* pConditionWaiterField = (&g_CoreLib)->GetField(FIELD__CONDITION__WAITERS_HEAD); - FieldDesc* pWaiterNextField = (&g_CoreLib)->GetField(FIELD__WAITER__NEXT); - FieldDesc* pThisThreadWaiterField = (&g_CoreLib)->GetField(FIELD__CONDITION__CURRENT_THREAD_WAITER); - // Build a map of Waiter objects to their owning Threads. - for (Thread *pThread = ThreadStore::GetThreadList(NULL); pThread != NULL; pThread = ThreadStore::GetThreadList(pThread)) - { - PTR_PTR_Object pThisThreadWaiterStorage = dac_cast(pThread->GetStaticFieldAddrNoCreate(pThisThreadWaiterField)); - if (pThisThreadWaiterStorage == NULL || *pThisThreadWaiterStorage == NULL) + OBJECTREF condition = NULL; + if (!conditionTable->TryGetValue(OBJECTREF(pObj), &condition)) { - continue; // this thread is not waiting on the monitor for this object. It has never waited on any monitor. + return hr; } - OBJECTREF pThisThreadWaiter = *pThisThreadWaiterStorage; - waiterToThreadMap.Add(dac_cast(pThisThreadWaiter), pThread); - } + MapSHash waiterToThreadMap; + FieldDesc* pConditionWaiterField = (&g_CoreLib)->GetField(FIELD__CONDITION__WAITERS_HEAD); + FieldDesc* pWaiterNextField = (&g_CoreLib)->GetField(FIELD__WAITER__NEXT); + FieldDesc* pThisThreadWaiterField = (&g_CoreLib)->GetField(FIELD__CONDITION__CURRENT_THREAD_WAITER); - // Iterate through the waiters in the condition object and invoke the user's callback for each thread - for (OBJECTREF pWaiter = pConditionWaiterField->GetRefValue(condition); pWaiter != NULL; pWaiter = pWaiterNextField->GetRefValue(pWaiter)) - { - Thread* pThread = NULL; - if (!waiterToThreadMap.Lookup(dac_cast(pWaiter), &pThread)) + // Build a map of Waiter objects to their owning Threads. + for (Thread *pThread = ThreadStore::GetThreadList(NULL); pThread != NULL; pThread = ThreadStore::GetThreadList(pThread)) + { + PTR_PTR_Object pThisThreadWaiterStorage = dac_cast(pThread->GetStaticFieldAddrNoCreate(pThisThreadWaiterField)); + if (pThisThreadWaiterStorage == NULL || *pThisThreadWaiterStorage == NULL) + { + continue; // this thread is not waiting on the monitor for this object. It has never waited on any monitor. + } + + OBJECTREF pThisThreadWaiter = *pThisThreadWaiterStorage; + waiterToThreadMap.Add(dac_cast(pThisThreadWaiter), pThread); + } + + // Iterate through the waiters in the condition object and invoke the user's callback for each thread + for (OBJECTREF pWaiter = pConditionWaiterField->GetRefValue(condition); pWaiter != NULL; pWaiter = pWaiterNextField->GetRefValue(pWaiter)) { - // This waiter is not in the map, so we can't find its thread. - LOG((LF_CORDB, LL_INFO10000, "D::EMEWL: Waiter not found in waiter->thread map.\n")); - continue; + Thread* pThread = NULL; + if (!waiterToThreadMap.Lookup(dac_cast(pWaiter), &pThread)) + { + // This waiter is not in the map, so we can't find its thread. + LOG((LF_CORDB, LL_INFO10000, "D::EMEWL: Waiter not found in waiter->thread map.\n")); + continue; + } + VMPTR_Thread vmThread = VMPTR_Thread::NullPtr(); + vmThread.SetDacTargetPtr(PTR_HOST_TO_TADDR(pThread)); + // Invoke the user's callback with the thread and user data + fpCallback(vmThread, pUserData); } - VMPTR_Thread vmThread = VMPTR_Thread::NullPtr(); - vmThread.SetDacTargetPtr(PTR_HOST_TO_TADDR(pThread)); - // Invoke the user's callback with the thread and user data - fpCallback(vmThread, pUserData); } + EX_CATCH_HRESULT(hr); + return hr; } -bool DacDbiInterfaceImpl::AreGCStructuresValid() +HRESULT DacDbiInterfaceImpl::AreGCStructuresValid(OUT bool * pResult) { - return true; + HRESULT hr = S_OK; + EX_TRY + { + *pResult = true; + } + EX_CATCH_HRESULT(hr); + return hr; } HeapData::HeapData() @@ -6631,13 +7258,20 @@ HRESULT DacHeapWalker::InitHeapDataWks(HeapData *&pHeaps, size_t &pCount) return hr; } -void DacDbiInterfaceImpl::DeleteHeapWalk(HeapWalkHandle handle) +HRESULT DacDbiInterfaceImpl::DeleteHeapWalk(HeapWalkHandle handle) { DD_ENTER_MAY_THROW; - DacHeapWalker *data = reinterpret_cast(handle); - if (data) - delete data; + HRESULT hr = S_OK; + EX_TRY + { + + DacHeapWalker *data = reinterpret_cast(handle); + if (data) + delete data; + } + EX_CATCH_HRESULT(hr); + return hr; } HRESULT DacDbiInterfaceImpl::WalkHeap(HeapWalkHandle handle, @@ -6801,55 +7435,70 @@ HRESULT DacDbiInterfaceImpl::GetHeapSegments(OUT DacDbiArrayList *p return hr; } -bool DacDbiInterfaceImpl::IsValidObject(CORDB_ADDRESS addr) +HRESULT DacDbiInterfaceImpl::IsValidObject(CORDB_ADDRESS obj, OUT bool * pResult) { DD_ENTER_MAY_THROW; - bool isValid = false; - - if (addr != 0 && addr != (CORDB_ADDRESS)-1) + HRESULT hr = S_OK; + EX_TRY { - EX_TRY - { - PTR_Object obj(TO_TADDR(addr)); - PTR_MethodTable mt = obj->GetMethodTable(); - PTR_EEClass cls = mt->GetClass(); + bool isValid = false; - if (mt == cls->GetMethodTable()) - isValid = true; - else if (!mt->IsCanonicalMethodTable() || mt->IsContinuation()) - isValid = cls->GetMethodTable()->GetClass() == cls; - } - EX_CATCH + if (obj != 0 && obj != (CORDB_ADDRESS)-1) { - isValid = false; + EX_TRY + { + PTR_Object pObj(TO_TADDR(obj)); + + PTR_MethodTable mt = pObj->GetMethodTable(); + PTR_EEClass cls = mt->GetClass(); + + if (mt == cls->GetMethodTable()) + isValid = true; + else if (!mt->IsCanonicalMethodTable() || mt->IsContinuation()) + isValid = cls->GetMethodTable()->GetClass() == cls; + } + EX_CATCH + { + isValid = false; + } + EX_END_CATCH } - EX_END_CATCH - } - return isValid; + *pResult = isValid; + } + EX_CATCH_HRESULT(hr); + return hr; } -bool DacDbiInterfaceImpl::GetAppDomainForObject(CORDB_ADDRESS addr, OUT VMPTR_AppDomain * pAppDomain, - OUT VMPTR_Module *pModule, OUT VMPTR_DomainAssembly *pDomainAssembly) +HRESULT DacDbiInterfaceImpl::GetAppDomainForObject(CORDB_ADDRESS obj, OUT VMPTR_AppDomain * pApp, OUT VMPTR_Module * pModule, OUT VMPTR_DomainAssembly * pDomainAssembly, OUT bool * pResult) { DD_ENTER_MAY_THROW; - if (addr == 0 || addr == (CORDB_ADDRESS)-1) + HRESULT hr = S_OK; + EX_TRY { - return false; - } - PTR_Object obj(TO_TADDR(addr)); - MethodTable *mt = obj->GetMethodTable(); - PTR_Module module = mt->GetModule(); + if (obj == 0 || obj == (CORDB_ADDRESS)-1) + { + *pResult = false; + } + else + { + PTR_Object pObj(TO_TADDR(obj)); + MethodTable *mt = pObj->GetMethodTable(); + PTR_Module module = mt->GetModule(); - pAppDomain->SetDacTargetPtr(PTR_HOST_TO_TADDR(AppDomain::GetCurrentDomain())); - pModule->SetDacTargetPtr(PTR_HOST_TO_TADDR(module)); - pDomainAssembly->SetDacTargetPtr(PTR_HOST_TO_TADDR(module->GetDomainAssembly())); + pApp->SetDacTargetPtr(PTR_HOST_TO_TADDR(AppDomain::GetCurrentDomain())); + pModule->SetDacTargetPtr(PTR_HOST_TO_TADDR(module)); + pDomainAssembly->SetDacTargetPtr(PTR_HOST_TO_TADDR(module->GetDomainAssembly())); - return true; + *pResult = true; + } + } + EX_CATCH_HRESULT(hr); + return hr; } HRESULT DacDbiInterfaceImpl::CreateRefWalk(OUT RefWalkHandle * pHandle, BOOL walkStacks, BOOL walkFQ, UINT32 handleWalkMask) @@ -6875,14 +7524,21 @@ HRESULT DacDbiInterfaceImpl::CreateRefWalk(OUT RefWalkHandle * pHandle, BOOL wal } -void DacDbiInterfaceImpl::DeleteRefWalk(IN RefWalkHandle handle) +HRESULT DacDbiInterfaceImpl::DeleteRefWalk(RefWalkHandle handle) { DD_ENTER_MAY_THROW; - DacRefWalker *walker = reinterpret_cast(handle); + HRESULT hr = S_OK; + EX_TRY + { - if (walker) - delete walker; + DacRefWalker *walker = reinterpret_cast(handle); + + if (walker) + delete walker; + } + EX_CATCH_HRESULT(hr); + return hr; } @@ -7107,28 +7763,35 @@ HRESULT DacDbiInterfaceImpl::GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT *pLa } -void DacDbiInterfaceImpl::GetGCHeapInformation(COR_HEAPINFO * pHeapInfo) +HRESULT DacDbiInterfaceImpl::GetGCHeapInformation(OUT COR_HEAPINFO * pHeapInfo) { DD_ENTER_MAY_THROW; - size_t heapCount = 0; - pHeapInfo->areGCStructuresValid = *g_gcDacGlobals->gc_structures_invalid_cnt == 0; - -#ifdef FEATURE_SVR_GC - if (GCHeapUtilities::IsServerHeap()) - { - pHeapInfo->gcType = CorDebugServerGC; - pHeapInfo->numHeaps = DacGetNumHeaps(); - } - else -#endif + HRESULT hr = S_OK; + EX_TRY { - pHeapInfo->gcType = CorDebugWorkstationGC; - pHeapInfo->numHeaps = 1; - } - pHeapInfo->pointerSize = sizeof(TADDR); - pHeapInfo->concurrent = g_pConfig->GetGCconcurrent() ? TRUE : FALSE; + size_t heapCount = 0; + pHeapInfo->areGCStructuresValid = *g_gcDacGlobals->gc_structures_invalid_cnt == 0; + + #ifdef FEATURE_SVR_GC + if (GCHeapUtilities::IsServerHeap()) + { + pHeapInfo->gcType = CorDebugServerGC; + pHeapInfo->numHeaps = DacGetNumHeaps(); + } + else + #endif + { + pHeapInfo->gcType = CorDebugWorkstationGC; + pHeapInfo->numHeaps = 1; + } + + pHeapInfo->pointerSize = sizeof(TADDR); + pHeapInfo->concurrent = g_pConfig->GetGCconcurrent() ? TRUE : FALSE; + } + EX_CATCH_HRESULT(hr); + return hr; } @@ -7414,69 +8077,72 @@ static BYTE* DebugInfoStoreNew(void * pData, size_t cBytes) return new (nothrow) BYTE[cBytes]; } -void DacDbiInterfaceImpl::GetAsyncLocals( - VMPTR_MethodDesc vmMethod, - CORDB_ADDRESS codeAddr, - UINT32 state, - DacDbiArrayList * pAsyncLocals) +HRESULT DacDbiInterfaceImpl::GetAsyncLocals(VMPTR_MethodDesc vmMethod, CORDB_ADDRESS codeAddr, UINT32 state, OUT DacDbiArrayList* pAsyncLocals) { DD_ENTER_MAY_THROW; - MethodDesc* pMethodDesc = vmMethod.GetDacPtr(); - if (pMethodDesc->IsAsyncThunkMethod()) - { - return; - } - TADDR nativeCodeStartAddr; - if (codeAddr != (TADDR)NULL) + HRESULT hr = S_OK; + EX_TRY { - NativeCodeVersion requestedNativeCodeVersion = ExecutionManager::GetNativeCodeVersion(static_cast(codeAddr)); - if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == (PCODE)NULL) + + MethodDesc* pMethodDesc = vmMethod.GetDacPtr(); + if (pMethodDesc->IsAsyncThunkMethod()) { - return; + return hr; + } + TADDR nativeCodeStartAddr; + if (codeAddr != (TADDR)NULL) + { + NativeCodeVersion requestedNativeCodeVersion = ExecutionManager::GetNativeCodeVersion(static_cast(codeAddr)); + if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == (PCODE)NULL) + { + return hr; + } + nativeCodeStartAddr = PCODEToPINSTR(requestedNativeCodeVersion.GetNativeCode()); + } + else + { + nativeCodeStartAddr = PCODEToPINSTR(pMethodDesc->GetNativeCode()); } - nativeCodeStartAddr = PCODEToPINSTR(requestedNativeCodeVersion.GetNativeCode()); - } - else - { - nativeCodeStartAddr = PCODEToPINSTR(pMethodDesc->GetNativeCode()); - } - DebugInfoRequest request; - request.InitFromStartingAddr(pMethodDesc, nativeCodeStartAddr); + DebugInfoRequest request; + request.InitFromStartingAddr(pMethodDesc, nativeCodeStartAddr); - ICorDebugInfo::AsyncInfo asyncInfo = {}; - NewArrayHolder asyncSuspensionPoints(NULL); - NewArrayHolder asyncVars(NULL); - ULONG32 cAsyncVars = 0; + ICorDebugInfo::AsyncInfo asyncInfo = {}; + NewArrayHolder asyncSuspensionPoints(NULL); + NewArrayHolder asyncVars(NULL); + ULONG32 cAsyncVars = 0; - BOOL success = DebugInfoManager::GetAsyncDebugInfo( - request, - DebugInfoStoreNew, - nullptr, - &asyncInfo, - &asyncSuspensionPoints, - &asyncVars, - &cAsyncVars); + BOOL success = DebugInfoManager::GetAsyncDebugInfo( + request, + DebugInfoStoreNew, + nullptr, + &asyncInfo, + &asyncSuspensionPoints, + &asyncVars, + &cAsyncVars); - if (!success) return; - if (state >= asyncInfo.NumSuspensionPoints) return; + if (!success) return hr; + if (state >= asyncInfo.NumSuspensionPoints) return hr; - UINT32 varBeginIndex = 0; - for (UINT32 i = 0; i < state; i++) - { - varBeginIndex += asyncSuspensionPoints[i].NumContinuationVars; - } + UINT32 varBeginIndex = 0; + for (UINT32 i = 0; i < state; i++) + { + varBeginIndex += asyncSuspensionPoints[i].NumContinuationVars; + } - UINT32 varCount = asyncSuspensionPoints[state].NumContinuationVars; - pAsyncLocals->Alloc(varCount); + UINT32 varCount = asyncSuspensionPoints[state].NumContinuationVars; + pAsyncLocals->Alloc(varCount); - _ASSERTE(varBeginIndex + varCount <= cAsyncVars); - for (UINT32 i = 0; i < varCount; i++) - { - (*pAsyncLocals)[i].offset = asyncVars[varBeginIndex + i].Offset; - (*pAsyncLocals)[i].ilVarNum = asyncVars[varBeginIndex + i].VarNumber; + _ASSERTE(varBeginIndex + varCount <= cAsyncVars); + for (UINT32 i = 0; i < varCount; i++) + { + (*pAsyncLocals)[i].offset = asyncVars[varBeginIndex + i].Offset; + (*pAsyncLocals)[i].ilVarNum = asyncVars[varBeginIndex + i].VarNumber; + } } + EX_CATCH_HRESULT(hr); + return hr; } HRESULT DacDbiInterfaceImpl::GetGenericArgTokenIndex(VMPTR_MethodDesc vmMethod, OUT UINT32* pIndex) diff --git a/src/coreclr/debug/daccess/dacdbiimpl.h b/src/coreclr/debug/daccess/dacdbiimpl.h index 43524cd22377aa..2c4a2b0558782f 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.h +++ b/src/coreclr/debug/daccess/dacdbiimpl.h @@ -368,7 +368,7 @@ class DacDbiInterfaceImpl : TADDR funcIp, OUT VMPTR_MethodDesc *ppMD); - HRESULT IsExceptionObject(VMPTR_Object vmObject, OUT BOOL * pResult); + BOOL IsExceptionObject(MethodTable* pMT); // Get the approximate and exact type handles for a type void GetTypeHandles(VMPTR_TypeHandle vmThExact, @@ -774,7 +774,7 @@ class DacDbiInterfaceImpl : // Get the CONTEXT of the current frame at which the stackwalker is stopped. HRESULT GetStackWalkCurrentContext(StackWalkHandle pSFIHandle, DT_CONTEXT * pContext); - HRESULT GetStackWalkCurrentContext(StackWalkHandle pSFIHandle, DT_CONTEXT * pContext); + void GetStackWalkCurrentContext(StackFrameIterator * pIter, DT_CONTEXT * pContext); // Set the stackwalker to the specified CONTEXT. HRESULT SetStackWalkCurrentContext(VMPTR_Thread vmThread, StackWalkHandle pSFIHandle, CorDebugSetContextFlag flag, DT_CONTEXT * pContext); @@ -801,6 +801,9 @@ class DacDbiInterfaceImpl : // Return the stack parameter size of the given method. HRESULT GetStackParameterSize(CORDB_ADDRESS controlPC, OUT ULONG32 * pRetVal); + // Return the stack parameter size of the given method. + ULONG32 GetStackParameterSize(EECodeInfo * pCodeInfo); + // Return the FramePointer of the current frame at which the stackwalker is stopped. HRESULT GetFramePointer(StackWalkHandle pSFIHandle, OUT FramePointer * pRetVal); @@ -944,9 +947,6 @@ class DacDbiInterfaceImpl : void InitParentFrameInfo(CrawlFrame * pCF, DebuggerIPCE_JITFuncData * pJITFuncData); - // Return the stack parameter size of the given method. - HRESULT GetStackParameterSize(CORDB_ADDRESS controlPC, OUT ULONG32 * pRetVal); - typedef enum { kFromManagedToUnmanaged, diff --git a/src/coreclr/debug/daccess/dacdbiimpllocks.cpp b/src/coreclr/debug/daccess/dacdbiimpllocks.cpp index 6c0d5a7e70e875..b34cf3cbf947d8 100644 --- a/src/coreclr/debug/daccess/dacdbiimpllocks.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpllocks.cpp @@ -25,18 +25,32 @@ #ifdef TEST_DATA_CONSISTENCY #include "crst.h" -void DacDbiInterfaceImpl::TestCrst(VMPTR_Crst vmCrst) +HRESULT DacDbiInterfaceImpl::TestCrst(VMPTR_Crst vmCrst) { DD_ENTER_MAY_THROW; - DebugTryCrst(vmCrst.GetDacPtr()); + HRESULT hr = S_OK; + EX_TRY + { + + DebugTryCrst(vmCrst.GetDacPtr()); + } + EX_CATCH_HRESULT(hr); + return hr; } -void DacDbiInterfaceImpl::TestRWLock(VMPTR_SimpleRWLock vmRWLock) +HRESULT DacDbiInterfaceImpl::TestRWLock(VMPTR_SimpleRWLock vmRWLock) { DD_ENTER_MAY_THROW; - DebugTryRWLock(vmRWLock.GetDacPtr()); + HRESULT hr = S_OK; + EX_TRY + { + + DebugTryRWLock(vmRWLock.GetDacPtr()); + } + EX_CATCH_HRESULT(hr); + return hr; } #endif diff --git a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp index fb96ef718a73ae..36bfd976e50b95 100644 --- a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp +++ b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp @@ -109,50 +109,67 @@ T_CONTEXT * GetContextBufferFromHandle(StackWalkHandle pSFIHandle) // Create and return a stackwalker on the specified thread. -void DacDbiInterfaceImpl::CreateStackWalk(VMPTR_Thread vmThread, - DT_CONTEXT * pInternalContextBuffer, - StackWalkHandle * ppSFIHandle) +HRESULT DacDbiInterfaceImpl::CreateStackWalk(VMPTR_Thread vmThread, DT_CONTEXT * pInternalContextBuffer, OUT StackWalkHandle * ppSFIHandle) { DD_ENTER_MAY_THROW; - _ASSERTE(ppSFIHandle != NULL); + HRESULT hr = S_OK; + EX_TRY + { + + _ASSERTE(ppSFIHandle != NULL); - Thread * pThread = vmThread.GetDacPtr(); + Thread * pThread = vmThread.GetDacPtr(); - // Set the stackwalk flags. We pretty much want to stop at everything. - DWORD dwFlags = (NOTIFY_ON_U2M_TRANSITIONS | - NOTIFY_ON_NO_FRAME_TRANSITIONS | - NOTIFY_ON_INITIAL_NATIVE_CONTEXT); + // Set the stackwalk flags. We pretty much want to stop at everything. + DWORD dwFlags = (NOTIFY_ON_U2M_TRANSITIONS | + NOTIFY_ON_NO_FRAME_TRANSITIONS | + NOTIFY_ON_INITIAL_NATIVE_CONTEXT); - // allocate memory for various stackwalker buffers (StackFrameIterator, RegDisplay, Context) - AllocateStackwalk(ppSFIHandle, pThread, NULL, dwFlags); + // allocate memory for various stackwalker buffers (StackFrameIterator, RegDisplay, Context) + AllocateStackwalk(ppSFIHandle, pThread, NULL, dwFlags); - // initialize the CONTEXT. - // SetStackWalk will initial the RegDisplay from this context. - GetContext(vmThread, pInternalContextBuffer); + // initialize the CONTEXT. + // SetStackWalk will initial the RegDisplay from this context. + GetContext(vmThread, pInternalContextBuffer); - // initialize the stackwalker - SetStackWalkCurrentContext(vmThread, - *ppSFIHandle, - SET_CONTEXT_FLAG_ACTIVE_FRAME, - pInternalContextBuffer); + // initialize the stackwalker + SetStackWalkCurrentContext(vmThread, + *ppSFIHandle, + SET_CONTEXT_FLAG_ACTIVE_FRAME, + pInternalContextBuffer); + } + EX_CATCH_HRESULT(hr); + return hr; } // Delete the stackwalk object allocated by code:AllocateStackwalk -void DacDbiInterfaceImpl::DeleteStackWalk(StackWalkHandle ppSFIHandle) +HRESULT DacDbiInterfaceImpl::DeleteStackWalk(StackWalkHandle ppSFIHandle) { - DeleteStackwalk(ppSFIHandle); + HRESULT hr = S_OK; + EX_TRY + { + DeleteStackwalk(ppSFIHandle); + } + EX_CATCH_HRESULT(hr); + return hr; } // Get the CONTEXT of the current frame at which the stackwalker is stopped. -void DacDbiInterfaceImpl::GetStackWalkCurrentContext(StackWalkHandle pSFIHandle, - DT_CONTEXT * pContext) +HRESULT DacDbiInterfaceImpl::GetStackWalkCurrentContext(StackWalkHandle pSFIHandle, DT_CONTEXT * pContext) { DD_ENTER_MAY_THROW; - StackFrameIterator * pIter = GetIteratorFromHandle(pSFIHandle); + HRESULT hr = S_OK; + EX_TRY + { + + StackFrameIterator * pIter = GetIteratorFromHandle(pSFIHandle); - GetStackWalkCurrentContext(pIter, pContext); + GetStackWalkCurrentContext(pIter, pContext); + } + EX_CATCH_HRESULT(hr); + return hr; } // Internal Worker for GetStackWalkCurrentContext(). @@ -172,142 +189,157 @@ void DacDbiInterfaceImpl::GetStackWalkCurrentContext(StackFrameIterator * pIter, // Set the stackwalker to the specified CONTEXT. -void DacDbiInterfaceImpl::SetStackWalkCurrentContext(VMPTR_Thread vmThread, - StackWalkHandle pSFIHandle, - CorDebugSetContextFlag flag, - DT_CONTEXT * pContext) +HRESULT DacDbiInterfaceImpl::SetStackWalkCurrentContext(VMPTR_Thread vmThread, StackWalkHandle pSFIHandle, CorDebugSetContextFlag flag, DT_CONTEXT * pContext) { DD_ENTER_MAY_THROW; - StackFrameIterator * pIter = GetIteratorFromHandle(pSFIHandle); - REGDISPLAY * pRD = GetRegDisplayFromHandle(pSFIHandle); - -#if defined(_DEBUG) - // The caller should have checked this already. - _ASSERTE(CheckContext(vmThread, pContext) == S_OK); -#endif // _DEBUG - - // DD can't keep pointers back into the RS address space. - // Allocate a context in DDImpl's memory space. DDImpl can't contain raw pointers back into - // the client space since that may not marshal. - T_CONTEXT * pContext2 = GetContextBufferFromHandle(pSFIHandle); - CopyMemory(pContext2, pContext, sizeof(*pContext)); - - // update the REGDISPLAY with the given CONTEXT. - // Be sure that the context is in DDImpl's memory space and not the Right-sides. - FillRegDisplay(pRD, pContext2); - BOOL fSuccess = pIter->ResetRegDisp(pRD, (flag == SET_CONTEXT_FLAG_ACTIVE_FRAME)); - if (!fSuccess) + HRESULT hr = S_OK; + EX_TRY { - // ResetRegDisp() may fail for the same reason Init() may fail, i.e. - // because the stackwalker tries to unwind one frame ahead of time, - // or because the stackwalker needs to filter out some frames based on the stackwalk flags. - ThrowHR(E_FAIL); + + StackFrameIterator * pIter = GetIteratorFromHandle(pSFIHandle); + REGDISPLAY * pRD = GetRegDisplayFromHandle(pSFIHandle); + + #if defined(_DEBUG) + // The caller should have checked this already. + _ASSERTE(CheckContext(vmThread, pContext) == S_OK); + #endif // _DEBUG + + // DD can't keep pointers back into the RS address space. + // Allocate a context in DDImpl's memory space. DDImpl can't contain raw pointers back into + // the client space since that may not marshal. + T_CONTEXT * pContext2 = GetContextBufferFromHandle(pSFIHandle); + CopyMemory(pContext2, pContext, sizeof(*pContext)); + + // update the REGDISPLAY with the given CONTEXT. + // Be sure that the context is in DDImpl's memory space and not the Right-sides. + FillRegDisplay(pRD, pContext2); + BOOL fSuccess = pIter->ResetRegDisp(pRD, (flag == SET_CONTEXT_FLAG_ACTIVE_FRAME)); + if (!fSuccess) + { + // ResetRegDisp() may fail for the same reason Init() may fail, i.e. + // because the stackwalker tries to unwind one frame ahead of time, + // or because the stackwalker needs to filter out some frames based on the stackwalk flags. + ThrowHR(E_FAIL); + } } + EX_CATCH_HRESULT(hr); + return hr; } // Unwind the stackwalker to the next frame. -BOOL DacDbiInterfaceImpl::UnwindStackWalkFrame(StackWalkHandle pSFIHandle) +HRESULT DacDbiInterfaceImpl::UnwindStackWalkFrame(StackWalkHandle pSFIHandle, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - StackFrameIterator * pIter = GetIteratorFromHandle(pSFIHandle); + HRESULT hr = S_OK; + EX_TRY + { + + StackFrameIterator * pIter = GetIteratorFromHandle(pSFIHandle); - CrawlFrame * pCF = &(pIter->m_crawl); + CrawlFrame * pCF = &(pIter->m_crawl); - if ((pIter->GetFrameState() == StackFrameIterator::SFITER_INITIAL_NATIVE_CONTEXT) || - (pIter->GetFrameState() == StackFrameIterator::SFITER_NATIVE_MARKER_FRAME)) - { - if (IsRuntimeUnwindableStub(GetControlPC(pCF->GetRegisterSet()))) + // Declare variables up front so goto doesn't bypass initialization + DWORD cbStackParameterSize = 0; + BOOL fIsAtEndOfStack = TRUE; + + if ((pIter->GetFrameState() == StackFrameIterator::SFITER_INITIAL_NATIVE_CONTEXT) || + (pIter->GetFrameState() == StackFrameIterator::SFITER_NATIVE_MARKER_FRAME)) { - // This is a native stack frame which the StackFrameIterator doesn't know how to unwind. - // Use our special unwind logic. - return UnwindRuntimeStackFrame(pIter); + if (IsRuntimeUnwindableStub(GetControlPC(pCF->GetRegisterSet()))) + { + // This is a native stack frame which the StackFrameIterator doesn't know how to unwind. + // Use our special unwind logic. + *pResult = UnwindRuntimeStackFrame(pIter); + goto Done; + } } - } - - // On x86, we need to adjust the stack pointer for the callee parameter adjustment. - // This requires us to save the number of bytes used for the stack parameters of the callee. - // Thus, let's save it here before we unwind. - DWORD cbStackParameterSize = 0; - if (pIter->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD) - { - cbStackParameterSize = GetStackParameterSize(pCF->GetCodeInfo()); - } - - // If the stackwalker is invalid to begin with, we'll just say that it is at the end of the stack. - BOOL fIsAtEndOfStack = TRUE; - while (pIter->IsValid()) - { - StackWalkAction swa = pIter->Next(); - if (swa == SWA_FAILED) + // On x86, we need to adjust the stack pointer for the callee parameter adjustment. + // This requires us to save the number of bytes used for the stack parameters of the callee. + // Thus, let's save it here before we unwind. + if (pIter->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD) { - // The stackwalker is valid to begin with, so this must be a failure case. - ThrowHR(E_FAIL); + cbStackParameterSize = GetStackParameterSize(pCF->GetCodeInfo()); } - else if (swa == SWA_CONTINUE) + + // If the stackwalker is invalid to begin with, we'll just say that it is at the end of the stack. + while (pIter->IsValid()) { - if (pIter->GetFrameState() == StackFrameIterator::SFITER_DONE) - { - // We are at the end of the stack. We will break at the end of the loop and fIsAtEndOfStack - // will be TRUE. - } - else if ((pIter->GetFrameState() == StackFrameIterator::SFITER_FRAME_FUNCTION) || - (pIter->GetFrameState() == StackFrameIterator::SFITER_SKIPPED_FRAME_FUNCTION)) - { - // If the stackwalker is stopped at an explicit frame, unwind directly to the next frame. - // The V3 stackwalker doesn't stop on explicit frames. - continue; - } - else if (pIter->GetFrameState() == StackFrameIterator::SFITER_NO_FRAME_TRANSITION) + StackWalkAction swa = pIter->Next(); + + if (swa == SWA_FAILED) { - // No frame transitions are not exposed in V2. - // Just continue onto the next managed stack frame. - continue; + // The stackwalker is valid to begin with, so this must be a failure case. + ThrowHR(E_FAIL); } - else if (pIter->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD) + else if (swa == SWA_CONTINUE) { - // Skip the new exception handling managed code, the debugger clients are not supposed to see them - MethodDesc *pMD = pIter->m_crawl.GetFunction(); - - // EH.DispatchEx, EH.RhThrowEx, EH.RhThrowHwEx, ExceptionServices.InternalCalls.SfiInit, ExceptionServices.InternalCalls.SfiNext - if (pMD->GetMethodTable() == g_pEHClass || pMD->GetMethodTable() == g_pExceptionServicesInternalCallsClass) + if (pIter->GetFrameState() == StackFrameIterator::SFITER_DONE) + { + // We are at the end of the stack. We will break at the end of the loop and fIsAtEndOfStack + // will be TRUE. + } + else if ((pIter->GetFrameState() == StackFrameIterator::SFITER_FRAME_FUNCTION) || + (pIter->GetFrameState() == StackFrameIterator::SFITER_SKIPPED_FRAME_FUNCTION)) { + // If the stackwalker is stopped at an explicit frame, unwind directly to the next frame. + // The V3 stackwalker doesn't stop on explicit frames. continue; } + else if (pIter->GetFrameState() == StackFrameIterator::SFITER_NO_FRAME_TRANSITION) + { + // No frame transitions are not exposed in V2. + // Just continue onto the next managed stack frame. + continue; + } + else if (pIter->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD) + { + // Skip the new exception handling managed code, the debugger clients are not supposed to see them + MethodDesc *pMD = pIter->m_crawl.GetFunction(); - fIsAtEndOfStack = FALSE; + // EH.DispatchEx, EH.RhThrowEx, EH.RhThrowHwEx, ExceptionServices.InternalCalls.SfiInit, ExceptionServices.InternalCalls.SfiNext + if (pMD->GetMethodTable() == g_pEHClass || pMD->GetMethodTable() == g_pExceptionServicesInternalCallsClass) + { + continue; + } + + fIsAtEndOfStack = FALSE; + } + else + { + fIsAtEndOfStack = FALSE; + } } else { - fIsAtEndOfStack = FALSE; + UNREACHABLE(); } - } - else - { - UNREACHABLE(); - } - // If we get here, then we want to stop at this current frame. - break; - } + // If we get here, then we want to stop at this current frame. + break; + } - if (fIsAtEndOfStack == FALSE) - { - // Currently the only case where we adjust the stack pointer is at M2U transitions. - if (pIter->GetFrameState() == StackFrameIterator::SFITER_NATIVE_MARKER_FRAME) + if (fIsAtEndOfStack == FALSE) { - _ASSERTE(!pCF->IsActiveFrame()); - AdjustRegDisplayForStackParameter(pCF->GetRegisterSet(), - cbStackParameterSize, - pCF->IsActiveFrame(), - kFromManagedToUnmanaged); + // Currently the only case where we adjust the stack pointer is at M2U transitions. + if (pIter->GetFrameState() == StackFrameIterator::SFITER_NATIVE_MARKER_FRAME) + { + _ASSERTE(!pCF->IsActiveFrame()); + AdjustRegDisplayForStackParameter(pCF->GetRegisterSet(), + cbStackParameterSize, + pCF->IsActiveFrame(), + kFromManagedToUnmanaged); + } } - } - return (fIsAtEndOfStack == FALSE); + *pResult = (fIsAtEndOfStack == FALSE); + Done: ; + } + EX_CATCH_HRESULT(hr); + return hr; } bool g_fSkipStackCheck = false; @@ -353,89 +385,95 @@ HRESULT DacDbiInterfaceImpl::CheckContext(VMPTR_Thread vmThread, } // Retrieve information about the current frame from the stackwalker. -IDacDbiInterface::FrameType DacDbiInterfaceImpl::GetStackWalkCurrentFrameInfo(StackWalkHandle pSFIHandle, - DebuggerIPCE_STRData * pFrameData) +HRESULT DacDbiInterfaceImpl::GetStackWalkCurrentFrameInfo(StackWalkHandle pSFIHandle, OPTIONAL DebuggerIPCE_STRData * pFrameData, OUT FrameType * pRetVal) { DD_ENTER_MAY_THROW; - _ASSERTE(pSFIHandle != NULL); + HRESULT hr = S_OK; + EX_TRY + { - StackFrameIterator * pIter = GetIteratorFromHandle(pSFIHandle); + _ASSERTE(pSFIHandle != NULL); - FrameType ftResult = kInvalid; - if (pIter->GetFrameState() == StackFrameIterator::SFITER_DONE) - { - _ASSERTE(!pIter->IsValid()); - ftResult = kAtEndOfStack; - } - else - { - BOOL fInitFrameData = FALSE; - switch (pIter->GetFrameState()) + StackFrameIterator * pIter = GetIteratorFromHandle(pSFIHandle); + + FrameType ftResult = kInvalid; + if (pIter->GetFrameState() == StackFrameIterator::SFITER_DONE) { - case StackFrameIterator::SFITER_UNINITIALIZED: - ftResult = kInvalid; - break; + _ASSERTE(!pIter->IsValid()); + ftResult = kAtEndOfStack; + } + else + { + BOOL fInitFrameData = FALSE; + switch (pIter->GetFrameState()) + { + case StackFrameIterator::SFITER_UNINITIALIZED: + ftResult = kInvalid; + break; - case StackFrameIterator::SFITER_FRAMELESS_METHOD: - { - MethodDesc *pMD = pIter->m_crawl.GetFunction(); - // EH.DispatchEx, EH.RhThrowEx, EH.RhThrowHwEx, ExceptionServices.InternalCalls.SfiInit, ExceptionServices.InternalCalls.SfiNext - if (pMD->GetMethodTable() == g_pEHClass || pMD->GetMethodTable() == g_pExceptionServicesInternalCallsClass) + case StackFrameIterator::SFITER_FRAMELESS_METHOD: { - ftResult = kManagedExceptionHandlingCodeFrame; + MethodDesc *pMD = pIter->m_crawl.GetFunction(); + // EH.DispatchEx, EH.RhThrowEx, EH.RhThrowHwEx, ExceptionServices.InternalCalls.SfiInit, ExceptionServices.InternalCalls.SfiNext + if (pMD->GetMethodTable() == g_pEHClass || pMD->GetMethodTable() == g_pExceptionServicesInternalCallsClass) + { + ftResult = kManagedExceptionHandlingCodeFrame; + } + else + { + ftResult = kManagedStackFrame; + fInitFrameData = TRUE; + } } - else + break; + + case StackFrameIterator::SFITER_FRAME_FUNCTION: + // + // fall through + // + case StackFrameIterator::SFITER_SKIPPED_FRAME_FUNCTION: + ftResult = kExplicitFrame; + fInitFrameData = TRUE; + break; + + case StackFrameIterator::SFITER_NO_FRAME_TRANSITION: + // no-frame transition represents an ExInfo for a native exception on x86. + // For all intents and purposes this should be treated just like another explicit frame. + ftResult = kExplicitFrame; + fInitFrameData = TRUE; + break; + + case StackFrameIterator::SFITER_NATIVE_MARKER_FRAME: + // + // fall through + // + case StackFrameIterator::SFITER_INITIAL_NATIVE_CONTEXT: + if (IsRuntimeUnwindableStub(GetControlPC(pIter->m_crawl.GetRegisterSet()))) { - ftResult = kManagedStackFrame; + ftResult = kNativeRuntimeUnwindableStackFrame; fInitFrameData = TRUE; } - } - break; - - case StackFrameIterator::SFITER_FRAME_FUNCTION: - // - // fall through - // - case StackFrameIterator::SFITER_SKIPPED_FRAME_FUNCTION: - ftResult = kExplicitFrame; - fInitFrameData = TRUE; - break; - - case StackFrameIterator::SFITER_NO_FRAME_TRANSITION: - // no-frame transition represents an ExInfo for a native exception on x86. - // For all intents and purposes this should be treated just like another explicit frame. - ftResult = kExplicitFrame; - fInitFrameData = TRUE; - break; - - case StackFrameIterator::SFITER_NATIVE_MARKER_FRAME: - // - // fall through - // - case StackFrameIterator::SFITER_INITIAL_NATIVE_CONTEXT: - if (IsRuntimeUnwindableStub(GetControlPC(pIter->m_crawl.GetRegisterSet()))) - { - ftResult = kNativeRuntimeUnwindableStackFrame; - fInitFrameData = TRUE; - } - else - { - ftResult = kNativeStackFrame; - } - break; + else + { + ftResult = kNativeStackFrame; + } + break; - default: - UNREACHABLE(); - } + default: + UNREACHABLE(); + } - if ((fInitFrameData == TRUE) && (pFrameData != NULL)) - { - InitFrameData(pIter, ftResult, pFrameData); + if ((fInitFrameData == TRUE) && (pFrameData != NULL)) + { + InitFrameData(pIter, ftResult, pFrameData); + } } - } - return ftResult; + *pRetVal = ftResult; + } + EX_CATCH_HRESULT(hr); + return hr; } //--------------------------------------------------------------------------------------- @@ -452,37 +490,44 @@ IDacDbiInterface::FrameType DacDbiInterfaceImpl::GetStackWalkCurrentFrameInfo(St // Internal frames are interesting if they are not of type STUBFRAME_NONE. // -ULONG32 DacDbiInterfaceImpl::GetCountOfInternalFrames(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::GetCountOfInternalFrames(VMPTR_Thread vmThread, OUT ULONG32 * pRetVal) { DD_ENTER_MAY_THROW; - Thread * pThread = vmThread.GetDacPtr(); - Frame * pFrame = pThread->GetFrame(); - - // We could call EnumerateInternalFrames() here, but it would be a lot of overhead for what we need. - ULONG32 uCount = 0; - while (pFrame != FRAME_TOP) + HRESULT hr = S_OK; + EX_TRY { - if (InlinedCallFrame::FrameHasActiveCall(pFrame)) + + Thread * pThread = vmThread.GetDacPtr(); + Frame * pFrame = pThread->GetFrame(); + + // We could call EnumerateInternalFrames() here, but it would be a lot of overhead for what we need. + ULONG32 uCount = 0; + while (pFrame != FRAME_TOP) { - // Skip new exception handling helpers - InlinedCallFrame *pInlinedCallFrame = dac_cast(pFrame); - PTR_PInvokeMethodDesc pMD = pInlinedCallFrame->m_Datum; - TADDR datum = dac_cast(pMD); - if ((datum & (TADDR)InlinedCallFrameMarker::Mask) == (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper) + if (InlinedCallFrame::FrameHasActiveCall(pFrame)) { - pFrame = pFrame->Next(); - continue; + // Skip new exception handling helpers + InlinedCallFrame *pInlinedCallFrame = dac_cast(pFrame); + PTR_PInvokeMethodDesc pMD = pInlinedCallFrame->m_Datum; + TADDR datum = dac_cast(pMD); + if ((datum & (TADDR)InlinedCallFrameMarker::Mask) == (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper) + { + pFrame = pFrame->Next(); + continue; + } } + CorDebugInternalFrameType ift = GetInternalFrameType(pFrame); + if (ift != STUBFRAME_NONE) + { + uCount++; + } + pFrame = pFrame->Next(); } - CorDebugInternalFrameType ift = GetInternalFrameType(pFrame); - if (ift != STUBFRAME_NONE) - { - uCount++; - } - pFrame = pFrame->Next(); + *pRetVal = uCount; } - return uCount; + EX_CATCH_HRESULT(hr); + return hr; } //--------------------------------------------------------------------------------------- @@ -495,145 +540,171 @@ ULONG32 DacDbiInterfaceImpl::GetCountOfInternalFrames(VMPTR_Thread vmThread) // pUserData - user-defined custom data to be passed to the callback // -void DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread vmThread, - FP_INTERNAL_FRAME_ENUMERATION_CALLBACK fpCallback, - void * pUserData) +HRESULT DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread vmThread, FP_INTERNAL_FRAME_ENUMERATION_CALLBACK fpCallback, CALLBACK_DATA pUserData) { DD_ENTER_MAY_THROW; - DebuggerIPCE_STRData frameData; + HRESULT hr = S_OK; + EX_TRY + { - Thread * pThread = vmThread.GetDacPtr(); - Frame * pFrame = pThread->GetFrame(); - AppDomain * pAppDomain = AppDomain::GetCurrentDomain(); + DebuggerIPCE_STRData frameData; - // This used to be only true for Enter-Managed chains. - // Since we don't have chains anymore, this can always be false. - frameData.quicklyUnwound = false; - frameData.eType = DebuggerIPCE_STRData::cStubFrame; + Thread * pThread = vmThread.GetDacPtr(); + Frame * pFrame = pThread->GetFrame(); + AppDomain * pAppDomain = AppDomain::GetCurrentDomain(); - while (pFrame != FRAME_TOP) - { - if (InlinedCallFrame::FrameHasActiveCall(pFrame)) + // This used to be only true for Enter-Managed chains. + // Since we don't have chains anymore, this can always be false. + frameData.quicklyUnwound = false; + frameData.eType = DebuggerIPCE_STRData::cStubFrame; + + while (pFrame != FRAME_TOP) { - // Skip new exception handling helpers - InlinedCallFrame *pInlinedCallFrame = dac_cast(pFrame); - PTR_PInvokeMethodDesc pMD = pInlinedCallFrame->m_Datum; - TADDR datum = dac_cast(pMD); - if ((datum & (TADDR)InlinedCallFrameMarker::Mask) == (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper) + if (InlinedCallFrame::FrameHasActiveCall(pFrame)) { - pFrame = pFrame->Next(); - continue; + // Skip new exception handling helpers + InlinedCallFrame *pInlinedCallFrame = dac_cast(pFrame); + PTR_PInvokeMethodDesc pMD = pInlinedCallFrame->m_Datum; + TADDR datum = dac_cast(pMD); + if ((datum & (TADDR)InlinedCallFrameMarker::Mask) == (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper) + { + pFrame = pFrame->Next(); + continue; + } } - } - // check if the internal frame is interesting - frameData.stubFrame.frameType = GetInternalFrameType(pFrame); - if (frameData.stubFrame.frameType != STUBFRAME_NONE) - { - frameData.fp = FramePointer::MakeFramePointer(PTR_HOST_TO_TADDR(pFrame)); + // check if the internal frame is interesting + frameData.stubFrame.frameType = GetInternalFrameType(pFrame); + if (frameData.stubFrame.frameType != STUBFRAME_NONE) + { + frameData.fp = FramePointer::MakeFramePointer(PTR_HOST_TO_TADDR(pFrame)); - frameData.vmCurrentAppDomainToken.SetHostPtr(pAppDomain); + frameData.vmCurrentAppDomainToken.SetHostPtr(pAppDomain); - MethodDesc * pMD = pFrame->GetFunction(); -#if defined(FEATURE_COMINTEROP) - if (frameData.stubFrame.frameType == STUBFRAME_U2M) - { - _ASSERTE(pMD == NULL); - - // U2M transition frame generally don't store the target MD because we know what the target - // is by looking at the callee stack frame. However, for reverse COM interop, we can try - // to get the MD for the interface. - // - // Note that some reverse COM interop cases don't have an intermediate interface MD, so - // pMD may still be NULL. - // - // Even if there is an MD on the ComMethodFrame, it could be in a different appdomain than - // the ComMethodFrame itself. The only known scenario is a cross-appdomain reverse COM - // interop call. We need to check for this case. The end result is that GetFunction() and - // GetFunctionToken() on ICDInternalFrame will return NULL. - - // Minidumps without full memory don't guarantee to capture the CCW since we can do without - // it. In this case, pMD will remain NULL. - EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY + MethodDesc * pMD = pFrame->GetFunction(); + #if defined(FEATURE_COMINTEROP) + if (frameData.stubFrame.frameType == STUBFRAME_U2M) { - if (pFrame->GetFrameIdentifier() == FrameIdentifier::ComMethodFrame) + _ASSERTE(pMD == NULL); + + // U2M transition frame generally don't store the target MD because we know what the target + // is by looking at the callee stack frame. However, for reverse COM interop, we can try + // to get the MD for the interface. + // + // Note that some reverse COM interop cases don't have an intermediate interface MD, so + // pMD may still be NULL. + // + // Even if there is an MD on the ComMethodFrame, it could be in a different appdomain than + // the ComMethodFrame itself. The only known scenario is a cross-appdomain reverse COM + // interop call. We need to check for this case. The end result is that GetFunction() and + // GetFunctionToken() on ICDInternalFrame will return NULL. + + // Minidumps without full memory don't guarantee to capture the CCW since we can do without + // it. In this case, pMD will remain NULL. + EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY { - ComMethodFrame * pCOMFrame = dac_cast(pFrame); - PTR_VOID pUnkStackSlot = pCOMFrame->GetPointerToArguments(); - PTR_IUnknown pUnk = dac_cast(*dac_cast(pUnkStackSlot)); - ComCallWrapper * pCCW = ComCallWrapper::GetWrapperFromIP(pUnk); - - ComCallMethodDesc * pCMD = NULL; - pCMD = dac_cast(pCOMFrame->ComMethodFrame::GetDatum()); - pMD = pCMD->GetInterfaceMethodDesc(); + if (pFrame->GetFrameIdentifier() == FrameIdentifier::ComMethodFrame) + { + ComMethodFrame * pCOMFrame = dac_cast(pFrame); + PTR_VOID pUnkStackSlot = pCOMFrame->GetPointerToArguments(); + PTR_IUnknown pUnk = dac_cast(*dac_cast(pUnkStackSlot)); + ComCallWrapper * pCCW = ComCallWrapper::GetWrapperFromIP(pUnk); + + ComCallMethodDesc * pCMD = NULL; + pCMD = dac_cast(pCOMFrame->ComMethodFrame::GetDatum()); + pMD = pCMD->GetInterfaceMethodDesc(); + } } + EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY } - EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY - } -#endif // FEATURE_COMINTEROP + #endif // FEATURE_COMINTEROP - Module * pModule = (pMD ? pMD->GetModule() : NULL); - DomainAssembly * pDomainAssembly = (pModule ? pModule->GetDomainAssembly() : NULL); + Module * pModule = (pMD ? pMD->GetModule() : NULL); + DomainAssembly * pDomainAssembly = (pModule ? pModule->GetDomainAssembly() : NULL); - if (frameData.stubFrame.frameType == STUBFRAME_FUNC_EVAL) - { - FuncEvalFrame * pFEF = dac_cast(pFrame); - DebuggerEval * pDE = pFEF->GetDebuggerEval(); + if (frameData.stubFrame.frameType == STUBFRAME_FUNC_EVAL) + { + FuncEvalFrame * pFEF = dac_cast(pFrame); + DebuggerEval * pDE = pFEF->GetDebuggerEval(); - frameData.stubFrame.funcMetadataToken = pDE->m_methodToken; - frameData.stubFrame.vmDomainAssembly.SetHostPtr( - pDE->m_debuggerModule ? pDE->m_debuggerModule->GetDomainAssembly() : NULL); - frameData.stubFrame.vmMethodDesc = VMPTR_MethodDesc::NullPtr(); - } - else - { - frameData.stubFrame.funcMetadataToken = (pMD == NULL ? mdTokenNil : pMD->GetMemberDef()); - frameData.stubFrame.vmDomainAssembly.SetHostPtr(pDomainAssembly); - frameData.stubFrame.vmMethodDesc.SetHostPtr(pMD); + frameData.stubFrame.funcMetadataToken = pDE->m_methodToken; + frameData.stubFrame.vmDomainAssembly.SetHostPtr( + pDE->m_debuggerModule ? pDE->m_debuggerModule->GetDomainAssembly() : NULL); + frameData.stubFrame.vmMethodDesc = VMPTR_MethodDesc::NullPtr(); + } + else + { + frameData.stubFrame.funcMetadataToken = (pMD == NULL ? mdTokenNil : pMD->GetMemberDef()); + frameData.stubFrame.vmDomainAssembly.SetHostPtr(pDomainAssembly); + frameData.stubFrame.vmMethodDesc.SetHostPtr(pMD); + } + + // invoke the callback + fpCallback(&frameData, pUserData); } - // invoke the callback - fpCallback(&frameData, pUserData); + // move on to the next internal frame + pFrame = pFrame->Next(); } - - // move on to the next internal frame - pFrame = pFrame->Next(); } + EX_CATCH_HRESULT(hr); + return hr; } // Given the FramePointer of the parent frame and the FramePointer of the current frame, // check if the current frame is the parent frame. -BOOL DacDbiInterfaceImpl::IsMatchingParentFrame(FramePointer fpToCheck, FramePointer fpParent) +HRESULT DacDbiInterfaceImpl::IsMatchingParentFrame(FramePointer fpToCheck, FramePointer fpParent, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - StackFrame sfToCheck = StackFrame((UINT_PTR)fpToCheck.GetSPValue()); + HRESULT hr = S_OK; + EX_TRY + { + + StackFrame sfToCheck = StackFrame((UINT_PTR)fpToCheck.GetSPValue()); - StackFrame sfParent = StackFrame((UINT_PTR)fpParent.GetSPValue()); + StackFrame sfParent = StackFrame((UINT_PTR)fpParent.GetSPValue()); - // Ask the ExInfo to figure out the answer. - // Don't try to compare the StackFrames/FramePointers ourselves. - return ExInfo::IsUnwoundToTargetParentFrame(sfToCheck, sfParent); + // Ask the ExInfo to figure out the answer. + // Don't try to compare the StackFrames/FramePointers ourselves. + *pResult = ExInfo::IsUnwoundToTargetParentFrame(sfToCheck, sfParent); + } + EX_CATCH_HRESULT(hr); + return hr; } // Return the stack parameter size of the given method. -ULONG32 DacDbiInterfaceImpl::GetStackParameterSize(CORDB_ADDRESS controlPC) +HRESULT DacDbiInterfaceImpl::GetStackParameterSize(CORDB_ADDRESS controlPC, OUT ULONG32 * pRetVal) { DD_ENTER_MAY_THROW; - PCODE currentPC = PCODE(controlPC); + HRESULT hr = S_OK; + EX_TRY + { + + PCODE currentPC = PCODE(controlPC); - EECodeInfo codeInfo(currentPC); - return GetStackParameterSize(&codeInfo); + EECodeInfo codeInfo(currentPC); + *pRetVal = GetStackParameterSize(&codeInfo); + } + EX_CATCH_HRESULT(hr); + return hr; } // Return the FramePointer of the current frame at which the stackwalker is stopped. -FramePointer DacDbiInterfaceImpl::GetFramePointer(StackWalkHandle pSFIHandle) +HRESULT DacDbiInterfaceImpl::GetFramePointer(StackWalkHandle pSFIHandle, OUT FramePointer * pRetVal) { DD_ENTER_MAY_THROW; - StackFrameIterator * pIter = GetIteratorFromHandle(pSFIHandle); - return GetFramePointerWorker(pIter); + HRESULT hr = S_OK; + EX_TRY + { + + StackFrameIterator * pIter = GetIteratorFromHandle(pSFIHandle); + *pRetVal = GetFramePointerWorker(pIter); + } + EX_CATCH_HRESULT(hr); + return hr; } // Internal helper for GetFramePointer. @@ -688,35 +759,46 @@ FramePointer DacDbiInterfaceImpl::GetFramePointerWorker(StackFrameIterator * pIt // Return TRUE if the specified CONTEXT is the CONTEXT of the leaf frame. // @dbgtodo filter CONTEXT - Currently we check for the filter CONTEXT first. -BOOL DacDbiInterfaceImpl::IsLeafFrame(VMPTR_Thread vmThread, - const DT_CONTEXT * pContext) +HRESULT DacDbiInterfaceImpl::IsLeafFrame(VMPTR_Thread vmThread, const DT_CONTEXT * pContext, OUT BOOL * pResult) { DD_ENTER_MAY_THROW; - DT_CONTEXT ctxLeaf; - GetContext(vmThread, &ctxLeaf); + HRESULT hr = S_OK; + EX_TRY + { + + DT_CONTEXT ctxLeaf; + GetContext(vmThread, &ctxLeaf); - // Call a platform-specific helper to compare the two contexts. - return CompareControlRegisters(pContext, &ctxLeaf); + // Call a platform-specific helper to compare the two contexts. + *pResult = CompareControlRegisters(pContext, &ctxLeaf); + } + EX_CATCH_HRESULT(hr); + return hr; } // This is a simple helper function to convert a CONTEXT to a DebuggerREGDISPLAY. We need to do this // inside DDI because the RS has no notion of REGDISPLAY. -void DacDbiInterfaceImpl::ConvertContextToDebuggerRegDisplay(const DT_CONTEXT * pInContext, - DebuggerREGDISPLAY * pOutDRD, - BOOL fActive) +HRESULT DacDbiInterfaceImpl::ConvertContextToDebuggerRegDisplay(const DT_CONTEXT * pInContext, DebuggerREGDISPLAY * pOutDRD, BOOL fActive) { DD_ENTER_MAY_THROW; - // This is a bit cumbersome. First we need to convert the CONTEXT into a REGDISPLAY. Then we need - // to convert the REGDISPLAY to a DebuggerREGDISPLAY. - T_CONTEXT tmpContext = { }; - CopyMemory(&tmpContext, pInContext, sizeof(*pInContext)); + HRESULT hr = S_OK; + EX_TRY + { + + // This is a bit cumbersome. First we need to convert the CONTEXT into a REGDISPLAY. Then we need + // to convert the REGDISPLAY to a DebuggerREGDISPLAY. + T_CONTEXT tmpContext = { }; + CopyMemory(&tmpContext, pInContext, sizeof(*pInContext)); - REGDISPLAY rd; - FillRegDisplay(&rd, &tmpContext); + REGDISPLAY rd; + FillRegDisplay(&rd, &tmpContext); - SetDebuggerREGDISPLAYFromREGDISPLAY(pOutDRD, &rd); + SetDebuggerREGDISPLAYFromREGDISPLAY(pOutDRD, &rd); + } + EX_CATCH_HRESULT(hr); + return hr; } //--------------------------------------------------------------------------------------- @@ -1314,23 +1396,31 @@ BOOL DacDbiInterfaceImpl::UnwindRuntimeStackFrame(StackFrameIterator * pIter) // Return true iff TS_SyncSuspended or TS_Hijacked is set on the specified thread. // -bool DacDbiInterfaceImpl::IsThreadSuspendedOrHijacked(VMPTR_Thread vmThread) +HRESULT DacDbiInterfaceImpl::IsThreadSuspendedOrHijacked(VMPTR_Thread vmThread, OUT bool * pResult) { DD_ENTER_MAY_THROW; - Thread * pThread = vmThread.GetDacPtr(); - Thread::ThreadState ts = pThread->GetSnapshotState(); - if ((ts & Thread::TS_SyncSuspended) != 0) + HRESULT hr = S_OK; + EX_TRY { - return true; - } -#ifdef FEATURE_HIJACK - if ((ts & Thread::TS_Hijacked) != 0) - { - return true; + Thread * pThread = vmThread.GetDacPtr(); + Thread::ThreadState ts = pThread->GetSnapshotState(); + if ((ts & Thread::TS_SyncSuspended) != 0) + { + *pResult = true; + } + #ifdef FEATURE_HIJACK + else if ((ts & Thread::TS_Hijacked) != 0) + { + *pResult = true; + } + #endif + else + { + *pResult = false; + } } -#endif - - return false; + EX_CATCH_HRESULT(hr); + return hr; } diff --git a/src/coreclr/debug/di/divalue.cpp b/src/coreclr/debug/di/divalue.cpp index 53ba0f6e9d9885..206a2c69b755c1 100644 --- a/src/coreclr/debug/di/divalue.cpp +++ b/src/coreclr/debug/di/divalue.cpp @@ -280,7 +280,8 @@ CordbReferenceValue* CordbValue::CreateHeapReferenceValue(CordbAppDomain* pAppDo { IDacDbiInterface* pDac = pAppDomain->GetProcess()->GetDAC(); - TargetBuffer objBuffer = pDac->GetObjectContents(vmObj); + TargetBuffer objBuffer; + IfFailThrow(pDac->GetObjectContents(vmObj, &objBuffer)); VOID* pRemoteAddr = CORDB_ADDRESS_TO_PTR(objBuffer.pAddress); // This creates a local reference that has a remote address in it. Ie &pRemoteAddr is an address // in the host address space and pRemoteAddr is an address in the target. @@ -1314,7 +1315,9 @@ HRESULT CordbReferenceValue::BuildFromGCHandle( TargetBuffer remoteValue; EX_TRY { - remoteValue.Init(pProc->GetDAC()->GetHandleAddressFromVmHandle(gcHandle), sizeof(void *)); + CORDB_ADDRESS _handleAddr; + IfFailThrow(pProc->GetDAC()->GetHandleAddressFromVmHandle(gcHandle, &_handleAddr)); + remoteValue.Init(_handleAddr, sizeof(void *)); } EX_CATCH_HRESULT(hr); IfFailRet(hr); @@ -1565,7 +1568,7 @@ void CordbReferenceValue::GetTypedByRefData(CordbProcess * pProcess, // TypedByref objects, it is actually the address of the TypedByRef struct which contains the // type and the object address. - pProcess->GetDAC()->GetTypedByRefInfo(pTypedByRef, vmAppDomain, pInfo); + IfFailThrow(pProcess->GetDAC()->GetTypedByRefInfo(pTypedByRef, vmAppDomain, pInfo)); } // CordbReferenceValue::GetTypedByRefData // get the address of the object referenced @@ -2452,11 +2455,12 @@ HRESULT CordbObjectValue::EnumerateExceptionCallStack(ICorDebugExceptionObjectCa CORDB_ADDRESS objAddr = m_valueHome.GetAddress(); IDacDbiInterface* pDAC = GetProcess()->GetDAC(); - VMPTR_Object vmObj = pDAC->GetObject(objAddr); + VMPTR_Object vmObj; + IfFailThrow(pDAC->GetObject(objAddr, &vmObj)); DacDbiArrayList dacStackFrames; - pDAC->GetStackFramesFromException(vmObj, dacStackFrames); + IfFailThrow(pDAC->GetStackFramesFromException(vmObj, dacStackFrames)); int stackFramesLength = dacStackFrames.Count(); if (stackFramesLength > 0) @@ -2508,7 +2512,8 @@ HRESULT CordbObjectValue::ForceCatchHandlerFoundEvents(BOOL enableEvents) CORDB_ADDRESS objAddr = m_valueHome.GetAddress(); IDacDbiInterface* pDAC = GetProcess()->GetDAC(); - VMPTR_Object vmObj = pDAC->GetObject(objAddr); + VMPTR_Object vmObj; + IfFailThrow(pDAC->GetObject(objAddr, &vmObj)); DebuggerIPCEvent event; CordbAppDomain * pAppDomain = GetAppDomain(); @@ -2549,8 +2554,10 @@ HRESULT CordbObjectValue::IsExceptionObject() { IDacDbiInterface* pDAC = GetProcess()->GetDAC(); - VMPTR_Object vmObj = pDAC->GetObject(objAddr); - BOOL fIsException = pDAC->IsExceptionObject(vmObj); + VMPTR_Object vmObj; + IfFailThrow(pDAC->GetObject(objAddr, &vmObj)); + BOOL fIsException; + IfFailThrow(pDAC->IsExceptionObject(vmObj, &fIsException)); if (!fIsException) hr = S_FALSE; @@ -2581,8 +2588,10 @@ HRESULT CordbObjectValue::IsRcw() { IDacDbiInterface* pDAC = GetProcess()->GetDAC(); - VMPTR_Object vmObj = pDAC->GetObject(objAddr); - BOOL fIsRcw = pDAC->IsRcw(vmObj); + VMPTR_Object vmObj; + IfFailThrow(pDAC->GetObject(objAddr, &vmObj)); + BOOL fIsRcw; + IfFailThrow(pDAC->IsRcw(vmObj, &fIsRcw)); if (!fIsRcw) hr = S_FALSE; @@ -2613,8 +2622,10 @@ HRESULT CordbObjectValue::IsDelegate() { IDacDbiInterface *pDAC = GetProcess()->GetDAC(); - VMPTR_Object vmObj = pDAC->GetObject(objAddr); - BOOL fIsDelegate = pDAC->IsDelegate(vmObj); + VMPTR_Object vmObj; + IfFailThrow(pDAC->GetObject(objAddr, &vmObj)); + BOOL fIsDelegate; + IfFailThrow(pDAC->IsDelegate(vmObj, &fIsDelegate)); if (!fIsDelegate) hr = S_FALSE; @@ -2646,7 +2657,7 @@ HRESULT CordbObjectValue::GetTargetHelper(ICorDebugReferenceValue **ppTarget) CORDB_ADDRESS delegateAddr = m_valueHome.GetAddress(); IDacDbiInterface *pDAC = GetProcess()->GetDAC(); - pDelegateObj = pDAC->GetObject(delegateAddr); + IfFailThrow(pDAC->GetObject(delegateAddr, &pDelegateObj)); HRESULT hr = pDAC->GetDelegateType(pDelegateObj, &delType); if (hr != S_OK) @@ -2681,7 +2692,7 @@ HRESULT CordbObjectValue::GetFunctionHelper(ICorDebugFunction **ppFunction) CORDB_ADDRESS delegateAddr = m_valueHome.GetAddress(); IDacDbiInterface *pDAC = GetProcess()->GetDAC(); - pDelegateObj = pDAC->GetObject(delegateAddr); + IfFailThrow(pDAC->GetObject(delegateAddr, &pDelegateObj)); HRESULT hr = pDAC->GetDelegateType(pDelegateObj, &delType); if (hr != S_OK) @@ -2704,7 +2715,7 @@ HRESULT CordbObjectValue::GetFunctionHelper(ICorDebugFunction **ppFunction) // TODO: How to ensure results are sanitized? // Also, this is expensive. Do we really care that much about this? NativeCodeFunctionData nativeCodeForDelFunc; - pDAC->GetNativeCodeInfo(functionDomainAssembly, functionMethodDef, &nativeCodeForDelFunc); + IfFailThrow(pDAC->GetNativeCodeInfo(functionDomainAssembly, functionMethodDef, &nativeCodeForDelFunc)); RSSmartPtr funcModule(GetProcess()->LookupOrCreateModule(functionDomainAssembly)); func.Assign(funcModule->LookupOrCreateFunction(functionMethodDef, nativeCodeForDelFunc.encVersion)); @@ -2783,11 +2794,12 @@ HRESULT CordbObjectValue::GetCachedInterfaceTypes( IDacDbiInterface* pDAC = GetProcess()->GetDAC(); CORDB_ADDRESS objAddr = m_valueHome.GetAddress(); - VMPTR_Object vmObj = pDAC->GetObject(objAddr); + VMPTR_Object vmObj; + IfFailThrow(pDAC->GetObject(objAddr, &vmObj)); // retrieve type info from LS - pDAC->GetRcwCachedInterfaceTypes(vmObj, m_appdomain->GetADToken(), - bIInspectableOnly, &dacInterfaces); + IfFailThrow(pDAC->GetRcwCachedInterfaceTypes(vmObj, m_appdomain->GetADToken(), + bIInspectableOnly, &dacInterfaces)); // synthesize CordbType instances int cItfs = dacInterfaces.Count(); @@ -2851,10 +2863,11 @@ HRESULT CordbObjectValue::GetCachedInterfacePointers( EX_TRY { IDacDbiInterface* pDAC = GetProcess()->GetDAC(); - VMPTR_Object vmObj = pDAC->GetObject(objAddr); + VMPTR_Object vmObj; + IfFailThrow(pDAC->GetObject(objAddr, &vmObj)); // retrieve type info from LS - pDAC->GetRcwCachedInterfacePointers(vmObj, bIInspectableOnly, &dacItfPtrs); + IfFailThrow(pDAC->GetRcwCachedInterfacePointers(vmObj, bIInspectableOnly, &dacItfPtrs)); } EX_CATCH_HRESULT(hr); IfFailRet(hr); @@ -4307,7 +4320,7 @@ HRESULT CordbHandleValue::RefreshHandleValue() EX_TRY { - objectHandle = pProcess->GetDAC()->GetHandleAddressFromVmHandle(m_vmHandle); + IfFailThrow(pProcess->GetDAC()->GetHandleAddressFromVmHandle(m_vmHandle, &objectHandle)); if (type != ELEMENT_TYPE_TYPEDBYREF) { pProcess->SafeReadBuffer(TargetBuffer(objectHandle, sizeof(void *)), (BYTE *)&objectAddress); @@ -4592,7 +4605,7 @@ HRESULT CordbHandleValue::GetAddress(CORDB_ADDRESS *pAddress) HRESULT hr = S_OK; EX_TRY { - *pAddress = GetProcess()->GetDAC()->GetHandleAddressFromVmHandle(m_vmHandle); + IfFailThrow(GetProcess()->GetDAC()->GetHandleAddressFromVmHandle(m_vmHandle, pAddress)); } EX_CATCH_HRESULT(hr); return hr; @@ -4752,8 +4765,10 @@ HRESULT CordbHeapValue3Impl::GetThreadOwningMonitorLock(CordbProcess* pProcess, EX_TRY { IDacDbiInterface *pDac = pProcess->GetDAC(); - VMPTR_Object vmObj = pDac->GetObject(remoteObjAddress); - MonitorLockInfo info = pDac->GetThreadOwningMonitorLock(vmObj); + VMPTR_Object vmObj; + IfFailThrow(pDac->GetObject(remoteObjAddress, &vmObj)); + MonitorLockInfo info; + IfFailThrow(pDac->GetThreadOwningMonitorLock(vmObj, &info)); if(info.acquisitionCount == 0) { // unowned @@ -4806,7 +4821,8 @@ HRESULT CordbHeapValue3Impl::GetMonitorEventWaitList(CordbProcess* pProcess, EX_TRY { IDacDbiInterface *pDac = pProcess->GetDAC(); - VMPTR_Object vmObj = pDac->GetObject(remoteObjAddress); + VMPTR_Object vmObj; + IfFailThrow(pDac->GetObject(remoteObjAddress, &vmObj)); CQuickArrayList threads; pDac->EnumerateMonitorEventWaitList(vmObj, (IDacDbiInterface::FP_THREAD_ENUMERATION_CALLBACK)ThreadEnumerationCallback, (VOID*)&threads); diff --git a/src/coreclr/debug/di/module.cpp b/src/coreclr/debug/di/module.cpp index 7f944fa9995214..5cda8918098b2a 100644 --- a/src/coreclr/debug/di/module.cpp +++ b/src/coreclr/debug/di/module.cpp @@ -50,7 +50,7 @@ CordbModule::CordbModule( // Fill out properties via DAC. ModuleInfo modInfo; - pProcess->GetDAC()->GetModuleData(vmModule, &modInfo); // throws + IfFailThrow(pProcess->GetDAC()->GetModuleData(vmModule, &modInfo)); // throws m_PEBuffer.Init(modInfo.pPEBaseAddress, modInfo.nPESize); @@ -62,7 +62,7 @@ CordbModule::CordbModule( { DomainAssemblyInfo dfInfo; - pProcess->GetDAC()->GetDomainAssemblyData(vmDomainAssembly, &dfInfo); // throws + IfFailThrow(pProcess->GetDAC()->GetDomainAssemblyData(vmDomainAssembly, &dfInfo)); // throws m_pAppDomain = pProcess->LookupOrCreateAppDomain(dfInfo.vmAppDomain); _ASSERTE(m_pAppDomain == pProcess->GetAppDomain()); @@ -117,10 +117,10 @@ void DbgAssertModuleDeletedCallback(VMPTR_DomainAssembly vmDomainAssembly, void // void CordbModule::DbgAssertModuleDeleted() { - GetProcess()->GetDAC()->EnumerateAssembliesInAppDomain( + IfFailThrow(GetProcess()->GetDAC()->EnumerateAssembliesInAppDomain( m_pAppDomain->GetADToken(), DbgAssertModuleDeletedCallback, - this); + this)); } #endif // _DEBUG @@ -223,7 +223,7 @@ IDacDbiInterface::SymbolFormat CordbModule::GetInMemorySymbolStream(IStream ** p TargetBuffer bufferPdb; IDacDbiInterface::SymbolFormat symFormat; - GetProcess()->GetDAC()->GetSymbolsBuffer(m_vmModule, &bufferPdb, &symFormat); + IfFailThrow(GetProcess()->GetDAC()->GetSymbolsBuffer(m_vmModule, &bufferPdb, &symFormat)); if (bufferPdb.IsEmpty()) { // No in-memory PDB. Common case. @@ -499,7 +499,7 @@ void CordbModule::RefreshMetaData() // We could make a reader for MDInternalRO, but no need yet. This also ensures we don't encroach into common // scenario where we can map a file on disk. TADDR remoteMDInternalRWAddr = (TADDR)NULL; - GetProcess()->GetDAC()->GetPEFileMDInternalRW(m_vmPEFile, &remoteMDInternalRWAddr); + IfFailThrow(GetProcess()->GetDAC()->GetPEFileMDInternalRW(m_vmPEFile, &remoteMDInternalRWAddr)); if (remoteMDInternalRWAddr != (TADDR)NULL) { // we should only be doing this once to initialize, we don't support reopen with this technique @@ -527,7 +527,7 @@ void CordbModule::RefreshMetaData() if(!m_fForceMetaDataSerialize) // case 1 and 2 { LOG((LF_CORDB,LL_INFO10000, "CM::RM !m_fForceMetaDataSerialize case\n")); - GetProcess()->GetDAC()->GetMetadata(m_vmModule, &bufferMetaData); // throws + IfFailThrow(GetProcess()->GetDAC()->GetMetadata(m_vmModule, &bufferMetaData)); // throws } else if (GetProcess()->GetShim() == NULL) // case 3 won't work on a dump so don't try { @@ -797,10 +797,13 @@ HRESULT CordbModule::InitPublicMetaDataFromFile(const WCHAR * pszFullPathName, _ASSERTE(!m_vmPEFile.IsNull()); // MetaData lookup favors the NGEN image, which is what we want here. - if (!this->GetProcess()->GetDAC()->GetMetaDataFileInfoFromPEFile(m_vmPEFile, + bool _mdFileInfoResult; + IfFailThrow(this->GetProcess()->GetDAC()->GetMetaDataFileInfoFromPEFile(m_vmPEFile, dwImageTimeStamp, dwImageSize, - &filePath)) + &filePath, + &_mdFileInfoResult)); + if (!_mdFileInfoResult) { LOG((LF_CORDB,LL_WARNING, "CM::IM: Couldn't get metadata info for file \"%s\"\n", pszFullPathName)); return CORDBG_E_MISSING_METADATA; @@ -1184,10 +1187,13 @@ HRESULT CordbModule::GetName(ULONG32 cchName, ULONG32 *pcchName, _Out_writes_to_ StringCopyHolder filePath; _ASSERTE(!m_vmPEFile.IsNull()); - if (this->GetProcess()->GetDAC()->GetMetaDataFileInfoFromPEFile(m_vmPEFile, + bool _mdFileInfoResult; + IfFailThrow(this->GetProcess()->GetDAC()->GetMetaDataFileInfoFromPEFile(m_vmPEFile, dwImageTimeStamp, dwImageSize, - &filePath)) + &filePath, + &_mdFileInfoResult)); + if (_mdFileInfoResult) { _ASSERTE(filePath.IsSet()); hr = CopyOutString(filePath, cchName, pcchName, szName); @@ -1275,7 +1281,7 @@ HRESULT CordbModule::GetNameWorker(ULONG32 cchName, ULONG32 *pcchName, _Out_writ // Tempting to use the metadata-scope name, but that's a regression from Whidbey. For manifest modules, // the metadata scope name is not initialized with the string the user supplied to create the // dynamic assembly. So we call into the runtime to use CLR heuristics to get a more accurate name. - m_pProcess->GetDAC()->GetModuleSimpleName(m_vmModule, &buffer); + IfFailThrow(m_pProcess->GetDAC()->GetModuleSimpleName(m_vmModule, &buffer)); _ASSERTE(buffer.IsSet()); szTempName = buffer; // Note that we considered returning S_FALSE for fabricated names like this, but that's a breaking @@ -1308,7 +1314,8 @@ const WCHAR * CordbModule::GetModulePath() if (!m_strModulePath.IsSet()) { IDacDbiInterface * pDac = m_pProcess->GetDAC(); // throws - pDac->GetModulePath(m_vmModule, &m_strModulePath); // throws + BOOL fNonEmpty; + IfFailThrow(pDac->GetModulePath(m_vmModule, &m_strModulePath, &fNonEmpty)); // throws _ASSERTE(m_strModulePath.IsSet()); } @@ -1909,7 +1916,7 @@ HRESULT CordbModule::ResolveTypeRef(mdTypeRef token, CordbClass **ppClass) { RSLockHolder lockHolder(pProcess->GetProcessLock()); - pProcess->GetDAC()->ResolveTypeReference(&inData, &outData); + IfFailThrow(pProcess->GetDAC()->ResolveTypeReference(&inData, &outData)); } CordbModule * pModule = m_pAppDomain->LookupOrCreateModule(outData.vmDomainAssembly); @@ -2377,7 +2384,8 @@ CordbAssembly * CordbModule::ResolveAssemblyInternal(mdToken tkAssemblyRef) if (!m_vmDomainAssembly.IsNull()) { // Get DAC to do the real work to resolve the assembly - VMPTR_DomainAssembly vmDomainAssembly = GetProcess()->GetDAC()->ResolveAssembly(m_vmDomainAssembly, tkAssemblyRef); + VMPTR_DomainAssembly vmDomainAssembly; + IfFailThrow(GetProcess()->GetDAC()->ResolveAssembly(m_vmDomainAssembly, tkAssemblyRef, &vmDomainAssembly)); // now find the ICorDebugAssembly corresponding to it if (!vmDomainAssembly.IsNull() && m_pAppDomain != NULL) @@ -2583,10 +2591,10 @@ HRESULT CordbModule::GetJITCompilerFlags(DWORD *pdwFlags ) BOOL fAllowJitOpts; BOOL fEnableEnC; - pProcess->GetDAC()->GetCompilerFlags ( + IfFailThrow(pProcess->GetDAC()->GetCompilerFlags ( GetRuntimeDomainAssembly(), &fAllowJitOpts, - &fEnableEnC); + &fEnableEnC)); if (fEnableEnC) { @@ -5103,7 +5111,7 @@ CordbNativeCode * CordbModule::LookupOrCreateNativeCode(mdMethodDef methodToken, if (pNativeCode == NULL) { - GetProcess()->GetDAC()->GetNativeCodeInfoForAddr(startAddress, &codeInfo, NULL, NULL); + IfFailThrow(GetProcess()->GetDAC()->GetNativeCodeInfoForAddr(startAddress, &codeInfo, NULL, NULL)); // We didn't have an instance, so we'll build one and add it to the hash table LOG((LF_CORDB, @@ -5158,11 +5166,11 @@ void CordbNativeCode::LoadNativeInfo() if (m_fCodeAvailable) { RSLockHolder lockHolder(pProcess->GetProcessLock()); - pProcess->GetDAC()->GetNativeCodeSequencePointsAndVarInfo(GetVMNativeCodeMethodDescToken(), + IfFailThrow(pProcess->GetDAC()->GetNativeCodeSequencePointsAndVarInfo(GetVMNativeCodeMethodDescToken(), GetAddress(), m_fCodeAvailable, &m_nativeVarData, - &m_sequencePoints); + &m_sequencePoints)); } } // CordbNativeCode::LoadNativeInfo diff --git a/src/coreclr/debug/di/process.cpp b/src/coreclr/debug/di/process.cpp index f22ff5b1703a36..f1f0246d6fb935 100644 --- a/src/coreclr/debug/di/process.cpp +++ b/src/coreclr/debug/di/process.cpp @@ -416,7 +416,9 @@ IMDInternalImport * CordbProcess::LookupMetaDataFromDebugger( IMDInternalImport * pMDII = NULL; // First, see if the debugger can locate the exact metadata we want. - if (this->GetDAC()->GetMetaDataFileInfoFromPEFile(vmPEAssembly, dwImageTimeStamp, dwImageSize, &filePath)) + bool _metaDataFileInfoResult; + IfFailThrow(this->GetDAC()->GetMetaDataFileInfoFromPEFile(vmPEAssembly, dwImageTimeStamp, dwImageSize, &filePath, &_metaDataFileInfoResult)); + if (_metaDataFileInfoResult) { _ASSERTE(filePath.IsSet()); @@ -1832,7 +1834,7 @@ HRESULT CordbProcess::Init() { // Invoke DAC primitive. _ASSERTE(m_pDacPrimitives != NULL); - fIsLSStarted = m_pDacPrimitives->IsLeftSideInitialized(); + IfFailThrow(m_pDacPrimitives->IsLeftSideInitialized(&fIsLSStarted)); } else { @@ -1957,7 +1959,7 @@ void CordbProcess::QueueManagedAttachIfNeededWorker() if (m_fDoDelayedManagedAttached && GetShim()->GetAttached()) { RSLockHolder lockHolder(&this->m_processMutex); - GetDAC()->MarkDebuggerAttachPending(); + IfFailThrow(GetDAC()->MarkDebuggerAttachPending()); hrQueue = this->QueueManagedAttach(); } @@ -2108,7 +2110,8 @@ CordbThread * CordbProcess::TryLookupThreadByVolatileOSId(DWORD dwThreadId) _ASSERTE(pThread != NULL); // Get the OS tid. This returns 0 if the thread is switched out. - DWORD dwThreadId2 = GetDAC()->TryGetVolatileOSThreadID(pThread->m_vmThreadToken); + DWORD dwThreadId2; + IfFailThrow(GetDAC()->TryGetVolatileOSThreadID(pThread->m_vmThreadToken, &dwThreadId2)); if (dwThreadId2 == dwThreadId) { return pThread; @@ -2247,7 +2250,9 @@ HRESULT CordbProcess::EnumerateHeap(ICorDebugHeapEnum **ppObjects) EX_TRY { - if (m_pDacPrimitives->AreGCStructuresValid()) + bool gcValid; + IfFailThrow(m_pDacPrimitives->AreGCStructuresValid(&gcValid)); + if (gcValid) { CordbHeapEnum *pHeapEnum = new CordbHeapEnum(this); GetContinueNeuterList()->Add(this, pHeapEnum); @@ -2274,7 +2279,7 @@ HRESULT CordbProcess::GetGCHeapInformation(COR_HEAPINFO *pHeapInfo) EX_TRY { - GetDAC()->GetGCHeapInformation(pHeapInfo); + IfFailThrow(GetDAC()->GetGCHeapInformation(pHeapInfo)); } EX_CATCH_HRESULT(hr); @@ -2328,7 +2333,9 @@ HRESULT CordbProcess::GetObjectInternal(CORDB_ADDRESS addr, ICorDebugObjectValue EX_TRY { - if (!m_pDacPrimitives->IsValidObject(addr)) + bool validObj; + IfFailThrow(m_pDacPrimitives->IsValidObject(addr, &validObj)); + if (!validObj) { hr = CORDBG_E_CORRUPT_OBJECT; } @@ -2448,7 +2455,7 @@ HRESULT CordbProcess::GetTypeForTypeID(COR_TYPEID id, ICorDebugType **ppType) EX_TRY { DebuggerIPCE_ExpandedTypeData data; - GetDAC()->GetObjectExpandedTypeInfoFromID(AllBoxed, VMPTR_AppDomain::NullPtr(), id, &data); + IfFailThrow(GetDAC()->GetObjectExpandedTypeInfoFromID(AllBoxed, VMPTR_AppDomain::NullPtr(), id, &data)); CordbType *type = 0; hr = CordbType::TypeDataToType(GetAppDomain(), &data, &type); @@ -2594,7 +2601,9 @@ COM_METHOD CordbProcess::GetAsyncStack(CORDB_ADDRESS continuationAddress, ICorDe EX_TRY { - if (!m_pDacPrimitives->IsValidObject(continuationAddress)) + bool validObj; + IfFailThrow(m_pDacPrimitives->IsValidObject(continuationAddress, &validObj)); + if (!validObj) { // throw if not a valid object ThrowHR(E_INVALIDARG); @@ -2628,14 +2637,16 @@ HRESULT CordbProcess::GetTypeForObject(CORDB_ADDRESS addr, CordbType **ppType, C VMPTR_DomainAssembly domainAssembly; HRESULT hr = E_FAIL; - if (GetDAC()->GetAppDomainForObject(addr, &appDomain, &mod, &domainAssembly)) + bool _appDomainResult; + IfFailThrow(GetDAC()->GetAppDomainForObject(addr, &appDomain, &mod, &domainAssembly, &_appDomainResult)); + if (_appDomainResult) { CordbAppDomain *cdbAppDomain = appDomain.IsNull() ? GetAppDomain() : LookupOrCreateAppDomain(appDomain); _ASSERTE(cdbAppDomain); DebuggerIPCE_ExpandedTypeData data; - GetDAC()->GetObjectExpandedTypeInfo(AllBoxed, appDomain, addr, &data); + IfFailThrow(GetDAC()->GetObjectExpandedTypeInfo(AllBoxed, appDomain, addr, &data)); CordbType *type = 0; hr = CordbType::TypeDataToType(cdbAppDomain, &data, &type); @@ -2673,7 +2684,7 @@ void CordbRefEnum::Neuter() { if (mRefHandle) { - GetProcess()->GetDAC()->DeleteRefWalk(mRefHandle); + IfFailThrow(GetProcess()->GetDAC()->DeleteRefWalk(mRefHandle)); mRefHandle = 0; } } @@ -2722,7 +2733,7 @@ HRESULT CordbRefEnum::Reset() { if (mRefHandle) { - GetProcess()->GetDAC()->DeleteRefWalk(mRefHandle); + IfFailThrow(GetProcess()->GetDAC()->DeleteRefWalk(mRefHandle)); mRefHandle = 0; } } @@ -2889,7 +2900,7 @@ void CordbHeapEnum::Clear() { if (mHeapHandle) { - GetProcess()->GetDAC()->DeleteHeapWalk(mHeapHandle); + IfFailThrow(GetProcess()->GetDAC()->DeleteHeapWalk(mHeapHandle)); mHeapHandle = 0; } } @@ -3074,7 +3085,7 @@ HRESULT CordbProcess::Detach() HRESULT hrIgnore = S_OK; EX_TRY { - GetDAC()->MarkDebuggerAttached(FALSE); + IfFailThrow(GetDAC()->MarkDebuggerAttached(FALSE)); } EX_CATCH_HRESULT(hrIgnore); } @@ -4486,10 +4497,10 @@ void CordbProcess::GetAssembliesInLoadOrder( ShimAssemblyCallbackData data(pAppDomainInternal, pAssemblies, countAssemblies); // Enumerate through and fill out pAssemblies table. - GetDAC()->EnumerateAssembliesInAppDomain( + IfFailThrow(GetDAC()->EnumerateAssembliesInAppDomain( pAppDomainInternal->GetADToken(), ShimAssemblyCallbackData::Callback, - &data); // user data + &data)); // user data // pAssemblies array has now been updated. } @@ -4635,10 +4646,10 @@ void CordbProcess::GetModulesInLoadOrder( ShimModuleCallbackData data(pAssemblyInternal, pModules, countModules); // Enumerate through and fill out pModules table. - GetDAC()->EnumerateModulesInAssembly( + IfFailThrow(GetDAC()->EnumerateModulesInAssembly( pAssemblyInternal->GetDomainAssemblyPtr(), ShimModuleCallbackData::Callback, - &data); // user data + &data)); // user data // pModules array has now been updated. } @@ -4858,9 +4869,9 @@ void CordbProcess::DbgAssertAppDomainDeleted(VMPTR_AppDomain vmAppDomainDeleted) callbackData.m_pThis = this; callbackData.m_vmAppDomainDeleted = vmAppDomainDeleted; - GetDAC()->EnumerateAppDomains( + IfFailThrow(GetDAC()->EnumerateAppDomains( CordbProcess::DbgAssertAppDomainDeletedCallback, - &callbackData); + &callbackData)); } #endif // _DEBUG @@ -5940,7 +5951,7 @@ void CordbProcess::RawDispatchEvent( EX_TRY { // the left side has signaled that we should test whether pEvent->TestCrstData.vmCrst is held - GetDAC()->TestCrst(pEvent->TestCrstData.vmCrst); + IfFailThrow(GetDAC()->TestCrst(pEvent->TestCrstData.vmCrst)); } EX_CATCH_HRESULT(hr); @@ -5972,7 +5983,7 @@ void CordbProcess::RawDispatchEvent( EX_TRY { // the left side has signaled that we should test whether pEvent->TestRWLockData.vmRWLock is held - GetDAC()->TestRWLock(pEvent->TestRWLockData.vmRWLock); + IfFailThrow(GetDAC()->TestRWLock(pEvent->TestRWLockData.vmRWLock)); } EX_CATCH_HRESULT(hr); @@ -6038,7 +6049,7 @@ void CordbProcess::PrepopulateThreadsOrThrow() if (IsDacInitialized()) { STRESS_LOG0(LF_CORDB, LL_INFO1000, "PrepopulateThreadsOrThrow()\n"); - GetDAC()->EnumerateThreads(ThreadEnumerationCallback, this); + IfFailThrow(GetDAC()->EnumerateThreads(ThreadEnumerationCallback, this)); } } @@ -6318,7 +6329,8 @@ HRESULT CordbProcess::IsTransitionStub(CORDB_ADDRESS address, BOOL *pfTransition // Check against DAC primitives { - BOOL fIsStub2 = GetDAC()->IsTransitionStub(address); + BOOL fIsStub2; + IfFailThrow(GetDAC()->IsTransitionStub(address, &fIsStub2)); (void)fIsStub2; //prevent "unused variable" error from GCC CONSISTENCY_CHECK_MSGF(*pfTransitionStub == fIsStub2, ("IsStub2 failed, DAC2:%d, IPC:%d, addr:0x%p", (int) fIsStub2, (int) *pfTransitionStub, CORDB_ADDRESS_TO_PTR(address))); @@ -7155,7 +7167,8 @@ HRESULT CordbProcess::FindPatchByAddress(CORDB_ADDRESS address, bool *pfPatchFou EX_TRY { // We should be able to double check w/ DAC that this really is outside of the runtime. - IDacDbiInterface::AddressType addrType = GetDAC()->GetAddressType(address); + IDacDbiInterface::AddressType addrType; + IfFailThrow(GetDAC()->GetAddressType(address, &addrType)); CONSISTENCY_CHECK_MSGF(addrType == IDacDbiInterface::kAddressUnrecognized, ("Bad address type = %d", addrType)); } EX_CATCH_HRESULT(hrDac); @@ -7543,7 +7556,7 @@ void CordbProcess::GetEventBlock(BOOL * pfBlockExists) // This is not technically necessary for Mac debugging. The event channel doesn't rely on // knowing the target address of the DCB on the LS. CORDB_ADDRESS pLeftSideDCB = (CORDB_ADDRESS)NULL; - pLeftSideDCB = (GetDAC()->GetDebuggerControlBlockAddress()); + IfFailThrow(GetDAC()->GetDebuggerControlBlockAddress(&pLeftSideDCB)); if (pLeftSideDCB == (CORDB_ADDRESS)NULL) { *pfBlockExists = false; @@ -8779,7 +8792,8 @@ CordbAppDomain * CordbProcess::GetAppDomain() return appDomain; } - VMPTR_AppDomain vmAppDomain = GetDAC()->GetCurrentAppDomain(); + VMPTR_AppDomain vmAppDomain; + IfFailThrow(GetDAC()->GetCurrentAppDomain(&vmAppDomain)); appDomain = LookupOrCreateAppDomain(vmAppDomain); return appDomain; } @@ -8886,9 +8900,9 @@ void CordbProcess::PrepopulateAppDomainsOrThrow() } // DD-primitive that invokes a callback. This may throw. - GetDAC()->EnumerateAppDomains( + IfFailThrow(GetDAC()->EnumerateAppDomains( CordbProcess::AppDomainEnumerationCallback, - this); + this)); } //--------------------------------------------------------------------------------------- @@ -11154,7 +11168,7 @@ void CordbProcess::FilterClrNotification( InitializeDac(); // @dbgtodo 'attach-bit': we don't want the debugger automatically invading the process. - GetDAC()->MarkDebuggerAttached(TRUE); + IfFailThrow(GetDAC()->MarkDebuggerAttached(TRUE)); } else if (pManagedEvent->type == DB_IPCE_SYNC_COMPLETE) { @@ -11914,7 +11928,7 @@ void CordbProcess::ContinueStatusChanged(DWORD dwThreadId, CORDB_CONTINUE_STATUS //--------------------------------------------------------------------------------------- void CordbProcess::RequestSyncAtEvent() { - GetDAC()->RequestSyncAtEvent(); + IfFailThrow(GetDAC()->RequestSyncAtEvent()); } //--------------------------------------------------------------------------------------- @@ -12658,7 +12672,7 @@ Reaction CordbProcess::Triage1stChanceNonSpecial(CordbUnmanagedThread * pUnmanag IDacDbiInterface::AddressType addrType; - addrType = GetDAC()->GetAddressType(address); + IfFailThrow(GetDAC()->GetAddressType(address, &addrType)); bool fIsCorCode =((addrType == IDacDbiInterface::kAddressManagedMethod) || (addrType == IDacDbiInterface::kAddressRuntimeManagedCode) || (addrType == IDacDbiInterface::kAddressRuntimeUnmanagedCode)); @@ -14565,7 +14579,9 @@ void CordbWin32EventThread::AttachProcess() EX_TRY { // Don't allow attach if any metadata/IL updates have been applied - if (pProcess->GetDAC()->MetadataUpdatesApplied()) + bool _metadataUpdatesApplied; + IfFailThrow(pProcess->GetDAC()->MetadataUpdatesApplied(&_metadataUpdatesApplied)); + if (_metadataUpdatesApplied) { hr = CORDBG_E_ASSEMBLY_UPDATES_APPLIED; goto LExit; @@ -15370,13 +15386,18 @@ HRESULT CordbProcess::GetReferenceValueFromGCHandle( } IDacDbiInterface* pDAC = GetProcess()->GetDAC(); - VMPTR_OBJECTHANDLE vmObjHandle = pDAC->GetVmObjectHandle(gcHandle); - if(!pDAC->IsVmObjectHandleValid(vmObjHandle)) + VMPTR_OBJECTHANDLE vmObjHandle; + IfFailThrow(pDAC->GetVmObjectHandle(gcHandle, &vmObjHandle)); + BOOL isValid; + IfFailThrow(pDAC->IsVmObjectHandleValid(vmObjHandle, &isValid)); + if(!isValid) { ThrowHR(CORDBG_E_BAD_REFERENCE_VALUE); } - ULONG appDomainId = pDAC->GetAppDomainIdFromVmObjectHandle(vmObjHandle); - VMPTR_AppDomain vmAppDomain = pDAC->GetAppDomainFromId(appDomainId); + ULONG appDomainId; + IfFailThrow(pDAC->GetAppDomainIdFromVmObjectHandle(vmObjHandle, &appDomainId)); + VMPTR_AppDomain vmAppDomain; + IfFailThrow(pDAC->GetAppDomainFromId(appDomainId, &vmAppDomain)); RSLockHolder lockHolder(GetProcessLock()); CordbAppDomain * pAppDomain = LookupOrCreateAppDomain(vmAppDomain); @@ -15519,7 +15540,7 @@ CordbClass * CordbProcess::LookupClass(ICorDebugAppDomain * pAppDomain, VMPTR_Do if (pAppDomain != NULL) { VMPTR_Module vmModule = VMPTR_Module::NullPtr(); - GetProcess()->GetDAC()->GetModuleForDomainAssembly(vmDomainAssembly, &vmModule); + IfFailThrow(GetProcess()->GetDAC()->GetModuleForDomainAssembly(vmDomainAssembly, &vmModule)); _ASSERTE(!vmModule.IsNull()); CordbModule * pModule = ((CordbAppDomain *)pAppDomain)->m_modules.GetBase(VmPtrToCookie(vmModule)); if (pModule != NULL) @@ -15555,7 +15576,7 @@ CordbModule * CordbProcess::LookupOrCreateModule(VMPTR_DomainAssembly vmDomainAs _ASSERTE(!vmDomainAssembly.IsNull()); DomainAssemblyInfo data; - GetDAC()->GetDomainAssemblyData(vmDomainAssembly, &data); // throws + IfFailThrow(GetDAC()->GetDomainAssemblyData(vmDomainAssembly, &data)); CordbAppDomain * pAppDomain = LookupOrCreateAppDomain(data.vmAppDomain); return pAppDomain->LookupOrCreateModule(vmDomainAssembly); @@ -15654,7 +15675,7 @@ HRESULT CordbProcess::GetAttachStateFlags(CLR_DEBUGGING_PROCESS_FLAGS *pFlags) if(pFlags == NULL) hr = E_POINTER; else - *pFlags = GetDAC()->GetAttachStateFlags(); + IfFailThrow(GetDAC()->GetAttachStateFlags(pFlags)); } PUBLIC_API_END(hr); @@ -15733,7 +15754,9 @@ bool CordbProcess::IsThreadSuspendedOrHijacked(ICorDebugThread * pICorDebugThrea PUBLIC_REENTRANT_API_ENTRY_FOR_SHIM(this); CordbThread * pCordbThread = static_cast (pICorDebugThread); - return GetDAC()->IsThreadSuspendedOrHijacked(pCordbThread->m_vmThreadToken); + bool _isSuspendedOrHijacked; + IfFailThrow(GetDAC()->IsThreadSuspendedOrHijacked(pCordbThread->m_vmThreadToken, &_isSuspendedOrHijacked)); + return _isSuspendedOrHijacked; } void CordbProcess::HandleControlCTrapResult(HRESULT result) diff --git a/src/coreclr/debug/di/rsappdomain.cpp b/src/coreclr/debug/di/rsappdomain.cpp index 221c0791f53235..8bd33db0d4d9a0 100644 --- a/src/coreclr/debug/di/rsappdomain.cpp +++ b/src/coreclr/debug/di/rsappdomain.cpp @@ -52,7 +52,7 @@ CordbAppDomain::CordbAppDomain(CordbProcess * pProcess, VMPTR_AppDomain vmAppDo // @dbgtodo reliability: we should probably tolerate failures here and keep track // of whether our ADID is valid or not, and requery if necessary. - m_AppDomainId = m_pProcess->GetDAC()->GetAppDomainId(m_vmAppDomain); + IfFailThrow(m_pProcess->GetDAC()->GetAppDomainId(m_vmAppDomain, &m_AppDomainId)); LOG((LF_CORDB,LL_INFO10000, "CAD::CAD: this:0x%x (void*)this:0x%x<%d>\n", this, (void *)this, m_AppDomainId)); @@ -434,10 +434,10 @@ void CordbAppDomain::PrepopulateAssembliesOrThrow() } // DD-primitive that invokes a callback. - GetProcess()->GetDAC()->EnumerateAssembliesInAppDomain( + IfFailThrow(GetProcess()->GetDAC()->EnumerateAssembliesInAppDomain( this->m_vmAppDomain, CordbAppDomain::AssemblyEnumerationCallback, - this); // user data + this)); // user data } //--------------------------------------------------------------------------------------- @@ -725,7 +725,8 @@ HRESULT CordbAppDomain::GetObject(ICorDebugValue **ppObject) EX_TRY { pDac = m_pProcess->GetDAC(); - VMPTR_OBJECTHANDLE vmObjHandle = pDac->GetAppDomainObject(m_vmAppDomain); + VMPTR_OBJECTHANDLE vmObjHandle; + IfFailThrow(pDac->GetAppDomainObject(m_vmAppDomain, &vmObjHandle)); if (!vmObjHandle.IsNull()) { ICorDebugReferenceValue * pRefValue = NULL; @@ -771,7 +772,7 @@ void CordbAppDomain::RemoveAssemblyFromCache(VMPTR_DomainAssembly vmDomainAssemb // This will handle if the assembly is not in the hash. // This could happen if we attach right before an assembly-unload event. VMPTR_Assembly vmAssembly; - GetProcess()->GetDAC()->GetAssemblyFromDomainAssembly(vmDomainAssembly, &vmAssembly); + IfFailThrow(GetProcess()->GetDAC()->GetAssemblyFromDomainAssembly(vmDomainAssembly, &vmAssembly)); m_assemblies.RemoveBase(VmPtrToCookie(vmAssembly)); } @@ -789,7 +790,7 @@ void CordbAppDomain::RemoveAssemblyFromCache(VMPTR_DomainAssembly vmDomainAssemb CordbAssembly * CordbAppDomain::LookupOrCreateAssembly(VMPTR_DomainAssembly vmDomainAssembly) { VMPTR_Assembly vmAssembly; - GetProcess()->GetDAC()->GetAssemblyFromDomainAssembly(vmDomainAssembly, &vmAssembly); + IfFailThrow(GetProcess()->GetDAC()->GetAssemblyFromDomainAssembly(vmDomainAssembly, &vmAssembly)); CordbAssembly * pAssembly = m_assemblies.GetBase(VmPtrToCookie(vmAssembly)); if (pAssembly != NULL) { @@ -834,7 +835,7 @@ CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_Module vmModule, VMPTR_D _ASSERTE(!vmDomainAssembly.IsNull() || !vmModule.IsNull()); if (vmModule.IsNull()) - GetProcess()->GetDAC()->GetModuleForDomainAssembly(vmDomainAssembly, &vmModule); + IfFailThrow(GetProcess()->GetDAC()->GetModuleForDomainAssembly(vmDomainAssembly, &vmModule)); _ASSERTE(!vmModule.IsNull()); @@ -848,7 +849,7 @@ CordbModule* CordbAppDomain::LookupOrCreateModule(VMPTR_Module vmModule, VMPTR_D if (vmDomainAssembly.IsNull()) { // If we don't have a domain assembly, we can look it up from the module. - GetProcess()->GetDAC()->GetDomainAssemblyFromModule(vmModule, &vmDomainAssembly); + IfFailThrow(GetProcess()->GetDAC()->GetDomainAssemblyFromModule(vmModule, &vmDomainAssembly)); } _ASSERTE(!vmDomainAssembly.IsNull()); @@ -931,10 +932,10 @@ void CordbAppDomain::PrepopulateModules() { // DD-primitive that invokes a callback. - GetProcess()->GetDAC()->EnumerateModulesInAssembly( + IfFailThrow(GetProcess()->GetDAC()->EnumerateModulesInAssembly( pAssembly->GetDomainAssemblyPtr(), CordbAppDomain::ModuleEnumerationCallback, - this); // user data + this)); // user data } } @@ -1089,7 +1090,8 @@ HRESULT CordbAppDomain::GetObjectForCCW(CORDB_ADDRESS ccwPointer, ICorDebugValue EX_TRY { - VMPTR_OBJECTHANDLE vmObjHandle = GetProcess()->GetDAC()->GetObjectForCCW(ccwPointer); + VMPTR_OBJECTHANDLE vmObjHandle; + IfFailThrow(GetProcess()->GetDAC()->GetObjectForCCW(ccwPointer, &vmObjHandle)); if (vmObjHandle.IsNull()) { hr = E_INVALIDARG; diff --git a/src/coreclr/debug/di/rsassembly.cpp b/src/coreclr/debug/di/rsassembly.cpp index 991d44c06cb7b1..445e15ae81599b 100644 --- a/src/coreclr/debug/di/rsassembly.cpp +++ b/src/coreclr/debug/di/rsassembly.cpp @@ -106,10 +106,10 @@ void CordbAssembly::DbgAssertAssemblyDeletedCallback(VMPTR_DomainAssembly vmDoma // void CordbAssembly::DbgAssertAssemblyDeleted() { - GetProcess()->GetDAC()->EnumerateAssembliesInAppDomain( + IfFailThrow(GetProcess()->GetDAC()->EnumerateAssembliesInAppDomain( GetAppDomain()->GetADToken(), CordbAssembly::DbgAssertAssemblyDeletedCallback, - this); + this)); } #endif // _DEBUG @@ -245,7 +245,8 @@ HRESULT CordbAssembly::GetName(ULONG32 cchName, if (!m_strAssemblyFileName.IsSet()) { IDacDbiInterface * pDac = m_pProcess->GetDAC(); // throws - BOOL fNonEmpty = pDac->GetAssemblyPath(m_vmAssembly, &m_strAssemblyFileName); // throws + BOOL fNonEmpty; + IfFailThrow(pDac->GetAssemblyPath(m_vmAssembly, &m_strAssemblyFileName, &fNonEmpty)); // throws _ASSERTE(m_strAssemblyFileName.IsSet()); @@ -302,7 +303,8 @@ HRESULT CordbAssembly::IsFullyTrusted( BOOL *pbFullyTrusted ) CordbProcess * pProcess = m_pAppDomain->GetProcess(); IDacDbiInterface * pDac = pProcess->GetDAC(); - BOOL fIsFullTrust = pDac->IsAssemblyFullyTrusted(m_vmDomainAssembly); + BOOL fIsFullTrust; + IfFailThrow(pDac->IsAssemblyFullyTrusted(m_vmDomainAssembly, &fIsFullTrust)); // Once the trust level of an assembly is known, it cannot change. m_foptIsFullTrust = fIsFullTrust; diff --git a/src/coreclr/debug/di/rsclass.cpp b/src/coreclr/debug/di/rsclass.cpp index d60d1777de0b58..6e8c6572995f58 100644 --- a/src/coreclr/debug/di/rsclass.cpp +++ b/src/coreclr/debug/di/rsclass.cpp @@ -245,8 +245,9 @@ HRESULT CordbClass::GetStaticFieldValue2(CordbModule * pModule, { EX_TRY { - pRmtStaticValue = pProcess->GetDAC()->GetCollectibleTypeStaticAddress(pFieldData->m_vmFieldDesc, - pModule->GetAppDomain()->GetADToken()); + IfFailThrow(pProcess->GetDAC()->GetCollectibleTypeStaticAddress(pFieldData->m_vmFieldDesc, + pModule->GetAppDomain()->GetADToken(), + &pRmtStaticValue)); } EX_CATCH_HRESULT(hr); if(FAILED(hr)) @@ -287,8 +288,9 @@ HRESULT CordbClass::GetStaticFieldValue2(CordbModule * pModule, EX_TRY { - pRmtStaticValue = pProcess->GetDAC()->GetThreadStaticAddress(pFieldData->m_vmFieldDesc, - pThread->m_vmThreadToken); + IfFailThrow(pProcess->GetDAC()->GetThreadStaticAddress(pFieldData->m_vmFieldDesc, + pThread->m_vmThreadToken, + &pRmtStaticValue)); } EX_CATCH_HRESULT(hr); if(FAILED(hr)) @@ -771,9 +773,13 @@ void CordbClass::Init(ClassLoadLevel desiredLoadLevel) // basic info load level if(desiredLoadLevel >= BasicInfo) { - vmTypeHandle = pDac->GetTypeHandle(m_pModule->GetRuntimeModule(), GetToken()); - SetIsValueClass(pDac->IsValueType(vmTypeHandle)); - m_fHasTypeParams = !!pDac->HasTypeParams(vmTypeHandle); + IfFailThrow(pDac->GetTypeHandle(m_pModule->GetRuntimeModule(), GetToken(), &vmTypeHandle)); + BOOL isValueType; + IfFailThrow(pDac->IsValueType(vmTypeHandle, &isValueType)); + SetIsValueClass(isValueType); + BOOL hasTypeParams; + IfFailThrow(pDac->HasTypeParams(vmTypeHandle, &hasTypeParams)); + m_fHasTypeParams = !!hasTypeParams; m_loadLevel = BasicInfo; } @@ -948,7 +954,9 @@ void CordbClass::InitEnCFieldInfo(EnCHangingFieldInfo * pEncField, // This is an instance field, we need to pass a bunch of type information back _ASSERTE(pObject != NULL); - pEncField->Init(pInterface->GetObject(pObject->m_id), // VMPTR to the object instance of interest. + VMPTR_Object vmObj; + IfFailThrow(pInterface->GetObject(pObject->m_id, &vmObj)); + pEncField->Init(vmObj, // VMPTR to the object instance of interest. pObject->GetInfo().objOffsetToVars, // The offset from the beginning of the object // to the beginning of the fields. Fields added // with EnC don't actually reside in the object @@ -995,7 +1003,7 @@ FieldData * CordbClass::GetEnCFieldFromDac(BOOL fStatic, InitEnCFieldInfo(&encField, fStatic, pObject, fieldToken, metadataToken); // Go get this particular field. - pProcess->GetDAC()->GetEnCHangingFieldInfo(&encField, &fieldData, &fDacStatic); + IfFailThrow(pProcess->GetDAC()->GetEnCHangingFieldInfo(&encField, &fieldData, &fDacStatic)); _ASSERTE(fStatic == fDacStatic); // Save the field results in our cache and get a stable pointer to the data diff --git a/src/coreclr/debug/di/rsfunction.cpp b/src/coreclr/debug/di/rsfunction.cpp index 84688137a7f369..e80848e0382155 100644 --- a/src/coreclr/debug/di/rsfunction.cpp +++ b/src/coreclr/debug/di/rsfunction.cpp @@ -571,7 +571,7 @@ HRESULT CordbFunction::GetActiveReJitRequestILCode(ICorDebugILCode **ppReJitedIL *ppReJitedILCode = NULL; VMPTR_ILCodeVersionNode vmILCodeVersionNode = VMPTR_ILCodeVersionNode::NullPtr(); - GetProcess()->GetDAC()->GetActiveRejitILCodeVersionNode(GetModule()->m_vmModule, m_MDToken, &vmILCodeVersionNode); + IfFailThrow(GetProcess()->GetDAC()->GetActiveRejitILCodeVersionNode(GetModule()->m_vmModule, m_MDToken, &vmILCodeVersionNode)); if (!vmILCodeVersionNode.IsNull()) { RSSmartPtr pILCode; @@ -788,10 +788,10 @@ HRESULT CordbFunction::GetILCodeAndSigToken() // and we also fallback on creating an empty ILCode object. // See issue DD 273199 for cases where IL and NGEN metadata mismatch (different RVAs). ALLOW_DATATARGET_MISSING_OR_INCONSISTENT_MEMORY( - pProcess->GetDAC()->GetILCodeAndSig(m_pModule->GetRuntimeDomainAssembly(), + IfFailThrow(pProcess->GetDAC()->GetILCodeAndSig(m_pModule->GetRuntimeDomainAssembly(), m_MDToken, &codeInfo, - &localVarSigToken); + &localVarSigToken)); ); currentEnCVersion = m_pModule->LookupFunctionLatestVersion(m_MDToken)->m_dwEnCVersionNumber; @@ -933,7 +933,7 @@ HRESULT CordbFunction::InitNativeCodeInfo() // All we actually need is the start address and method desc which are cheap to get relative // to some of the other members. So far this doesn't appear to be a perf hotspot, but if it // shows up in some scenario it wouldn't be too hard to improve it - pProcess->GetDAC()->GetNativeCodeInfo(m_pModule->GetRuntimeDomainAssembly(), m_MDToken, &codeInfo); + IfFailThrow(pProcess->GetDAC()->GetNativeCodeInfo(m_pModule->GetRuntimeDomainAssembly(), m_MDToken, &codeInfo)); } // populate the m_nativeCode pointer with the code info we found diff --git a/src/coreclr/debug/di/rsstackwalk.cpp b/src/coreclr/debug/di/rsstackwalk.cpp index 79038742cddc74..6b9c0b1a731f6b 100644 --- a/src/coreclr/debug/di/rsstackwalk.cpp +++ b/src/coreclr/debug/di/rsstackwalk.cpp @@ -38,9 +38,9 @@ void CordbStackWalk::Init() m_lastSyncFlushCounter = pProcess->m_flushCounter; IDacDbiInterface * pDAC = pProcess->GetDAC(); - pDAC->CreateStackWalk(m_pCordbThread->m_vmThreadToken, + IfFailThrow(pDAC->CreateStackWalk(m_pCordbThread->m_vmThreadToken, &m_context, - &m_pSFIHandle); + &m_pSFIHandle)); // see the function header of code:CordbStackWalk::CheckForLegacyHijackCase CheckForLegacyHijackCase(); @@ -80,10 +80,10 @@ void CordbStackWalk::CheckForLegacyHijackCase() m_context.ContextFlags = DT_CONTEXT_FULL; pUT->GetThreadContext(&m_context); IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - pDAC->SetStackWalkCurrentContext(m_pCordbThread->m_vmThreadToken, + IfFailThrow(pDAC->SetStackWalkCurrentContext(m_pCordbThread->m_vmThreadToken, m_pSFIHandle, SET_CONTEXT_FLAG_ACTIVE_FRAME, - &m_context); + &m_context)); } } } @@ -129,7 +129,7 @@ void CordbStackWalk::DeleteAll() #endif // FEATURE_DBGIPC_TRANSPORT_DI { // This Delete call shouldn't actually throw. Worst case, the DDImpl leaked memory. - GetProcess()->GetDAC()->DeleteStackWalk(m_pSFIHandle); + IfFailThrow(GetProcess()->GetDAC()->DeleteStackWalk(m_pSFIHandle)); } } EX_CATCH_HRESULT(hr); @@ -218,9 +218,9 @@ void CordbStackWalk::RefreshIfNeeded() DeleteAll(); // create a new stackwalk handle - pProcess->GetDAC()->CreateStackWalk(m_pCordbThread->m_vmThreadToken, + IfFailThrow(pProcess->GetDAC()->CreateStackWalk(m_pCordbThread->m_vmThreadToken, &m_context, - &m_pSFIHandle); + &m_pSFIHandle)); // advance the stackwalker to where we originally were SetContextWorker(m_cachedSetContextFlag, sizeof(DT_CONTEXT), reinterpret_cast(&ctx)); @@ -305,7 +305,8 @@ HRESULT CordbStackWalk::GetContext(ULONG32 contextFlags, // No easy way out in this case. We have to call the DDI. IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - IDacDbiInterface::FrameType ft = pDAC->GetStackWalkCurrentFrameInfo(m_pSFIHandle, NULL); + IDacDbiInterface::FrameType ft; + IfFailThrow(pDAC->GetStackWalkCurrentFrameInfo(m_pSFIHandle, NULL, &ft)); if (ft == IDacDbiInterface::kInvalid) { ThrowHR(E_FAIL); @@ -398,10 +399,10 @@ void CordbStackWalk::SetContextWorker(CorDebugSetContextFlag flag, ULONG32 conte m_context = tmpCtx; m_cachedSetContextFlag = flag; - pDAC->SetStackWalkCurrentContext(m_pCordbThread->m_vmThreadToken, + IfFailThrow(pDAC->SetStackWalkCurrentContext(m_pCordbThread->m_vmThreadToken, m_pSFIHandle, flag, - &m_context); + &m_context)); } //--------------------------------------------------------------------------------------- @@ -422,11 +423,12 @@ BOOL CordbStackWalk::UnwindStackFrame() _ASSERTE(pProcess->GetProcessLock()->HasLock()); IDacDbiInterface * pDAC = pProcess->GetDAC(); - BOOL retVal = pDAC->UnwindStackWalkFrame(m_pSFIHandle); + BOOL retVal; + IfFailThrow(pDAC->UnwindStackWalkFrame(m_pSFIHandle, &retVal)); // Now that we have unwound, make sure we update the CONTEXT buffer to reflect the current stack frame. // This call is safe regardless of whether the unwind is successful or not. - pDAC->GetStackWalkCurrentContext(m_pSFIHandle, &m_context); + IfFailThrow(pDAC->GetStackWalkCurrentContext(m_pSFIHandle, &m_context)); return retVal; } // CordbStackWalk::UnwindStackWalkFrame @@ -465,7 +467,7 @@ HRESULT CordbStackWalk::Next() IDacDbiInterface * pDAC = GetProcess()->GetDAC(); IDacDbiInterface::FrameType ft = IDacDbiInterface::kInvalid; - ft = pDAC->GetStackWalkCurrentFrameInfo(this->m_pSFIHandle, NULL); + IfFailThrow(pDAC->GetStackWalkCurrentFrameInfo(this->m_pSFIHandle, NULL, &ft)); if (ft == IDacDbiInterface::kAtEndOfStack) { ThrowHR(CORDBG_E_PAST_END_OF_STACK); @@ -578,7 +580,7 @@ HRESULT CordbStackWalk::GetFrameWorker(ICorDebugFrame ** ppFrame) IDacDbiInterface::FrameType ft = IDacDbiInterface::kInvalid; pDAC = GetProcess()->GetDAC(); - ft = pDAC->GetStackWalkCurrentFrameInfo(m_pSFIHandle, &frameData); + IfFailThrow(pDAC->GetStackWalkCurrentFrameInfo(m_pSFIHandle, &frameData, &ft)); if (ft == IDacDbiInterface::kInvalid) { @@ -622,7 +624,7 @@ HRESULT CordbStackWalk::GetFrameWorker(ICorDebugFrame ** ppFrame) m_fIsOneFrameAhead = true; #if defined(TARGET_X86) - frameData.fp = pDAC->GetFramePointer(m_pSFIHandle); + IfFailThrow(pDAC->GetFramePointer(m_pSFIHandle, &frameData.fp)); #endif // TARGET_X86 // currentFuncData contains general information about the method. @@ -807,7 +809,7 @@ HRESULT CordbStackWalk::GetFrameWorker(ICorDebugFrame ** ppFrame) m_fIsOneFrameAhead = true; #if defined(TARGET_X86) - frameData.fp = pDAC->GetFramePointer(m_pSFIHandle); + IfFailThrow(pDAC->GetFramePointer(m_pSFIHandle, &frameData.fp)); #endif // TARGET_X86 // Lookup the appdomain that the thread was in when it was executing code for this frame. We pass this @@ -907,7 +909,8 @@ HRESULT CordbAsyncStackWalk::PopulateFrame() &pModule, &methodDef); - IDacDbiInterface::DynamicMethodType dynMethodType = pDac->IsDiagnosticsHiddenOrLCGMethod(codeData.vmNativeCodeMethodDescToken); + IDacDbiInterface::DynamicMethodType dynMethodType; + IfFailThrow(pDac->IsDiagnosticsHiddenOrLCGMethod(codeData.vmNativeCodeMethodDescToken, &dynMethodType)); if (dynMethodType == IDacDbiInterface::kDiagnosticHidden) { // Skipping async frame creation for async thunks. These can not be converted to a CordbAsyncFrame as they lack DebugInfo diff --git a/src/coreclr/debug/di/rsthread.cpp b/src/coreclr/debug/di/rsthread.cpp index 2c5b73a510b5c4..f152b5f66c34b6 100644 --- a/src/coreclr/debug/di/rsthread.cpp +++ b/src/coreclr/debug/di/rsthread.cpp @@ -93,7 +93,7 @@ CordbThread::CordbThread(CordbProcess * pProcess, VMPTR_Thread vmThread) : // This id must be unique for the thread. V2 uses the current OS thread id. // If we ever support fibers, then we need to use something more unique than that. - m_dwUniqueID = pProcess->GetDAC()->GetUniqueThreadID(vmThread); // may throw + IfFailThrow(pProcess->GetDAC()->GetUniqueThreadID(vmThread, &m_dwUniqueID)); // may throw LOG((LF_CORDB, LL_INFO1000, "CT::CT new thread 0x%p vmptr=0x%p id=0x%x\n", this, m_vmThreadToken, m_dwUniqueID)); @@ -227,9 +227,9 @@ void CordbThread::DbgAssertThreadDeletedCallback(VMPTR_Thread vmThread, void * p void CordbThread::DbgAssertThreadDeleted() { // Enumerate through all threads and ensure the deleted threads don't show up. - GetProcess()->GetDAC()->EnumerateThreads( + IfFailThrow(GetProcess()->GetDAC()->EnumerateThreads( DbgAssertThreadDeletedCallback, - this); + this)); } #endif // _DEBUG @@ -286,7 +286,8 @@ BOOL CordbThread::IsThreadExceptionManaged() // It's the presence of a throwable that makes the difference between a managed // exception event and an unmanaged exception event. - VMPTR_OBJECTHANDLE vmObject = GetProcess()->GetDAC()->GetCurrentException(m_vmThreadToken); + VMPTR_OBJECTHANDLE vmObject; + IfFailThrow(GetProcess()->GetDAC()->GetCurrentException(m_vmThreadToken, &vmObject)); bool fHasThrowable = !vmObject.IsNull(); @@ -332,7 +333,7 @@ void CordbThread::CreateCordbRegisterSet(DT_CONTEXT * pContext, // convert the CONTEXT to a DebuggerREGDISPLAY IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - pDAC->ConvertContextToDebuggerRegDisplay(pContext, pDRD, fLeaf); + IfFailThrow(pDAC->ConvertContextToDebuggerRegDisplay(pContext, pDRD, fLeaf)); // create the CordbRegisterSet RSInitHolder pRS(new CordbRegisterSet(pDRD, @@ -450,7 +451,7 @@ void CordbThread::HijackForUnhandledException() // We don't bother remembering the original context. LS hijack will have the // context on its stack and will pass it to RS just like it does for filter-context. - GetProcess()->GetDAC()->Hijack( + IfFailThrow(GetProcess()->GetDAC()->Hijack( m_vmThreadToken, dwThreadId, m_pExceptionRecord, @@ -458,7 +459,7 @@ void CordbThread::HijackForUnhandledException() 0, // size of context EHijackReason::kUnhandledException, NULL, - NULL); + NULL)); // Notify debugger to clear the exception. // This will invoke the data-target. @@ -628,7 +629,8 @@ void CordbThread::RefreshHandle(HANDLE * phThread) *phThread = INVALID_HANDLE_VALUE; IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - HANDLE hThread = pDAC->GetThreadHandle(m_vmThreadToken); + HANDLE hThread; + IfFailThrow(pDAC->GetThreadHandle(m_vmThreadToken, &hThread)); _ASSERTE(hThread != INVALID_HANDLE_VALUE); _ASSERTE(hThread != NULL); @@ -713,7 +715,7 @@ HRESULT CordbThread::SetDebugState(CorDebugThreadState state) } IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - pDAC->SetDebugState(m_vmThreadToken, state); + IfFailThrow(pDAC->SetDebugState(m_vmThreadToken, state)); m_debugState = state; } @@ -778,7 +780,7 @@ CorDebugUserState CordbThread::GetUserState() if (m_userState == kInvalidUserState) { IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - m_userState = pDAC->GetUserState(m_vmThreadToken); + IfFailThrow(pDAC->GetUserState(m_vmThreadToken, (CorDebugUserState *)&m_userState)); } return (CorDebugUserState)m_userState; @@ -815,7 +817,8 @@ HRESULT CordbThread::GetCurrentException(ICorDebugValue ** ppExceptionObject) // Go to the LS and retrieve any exception object. // IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - VMPTR_OBJECTHANDLE vmObjHandle = pDAC->GetCurrentException(m_vmThreadToken); + VMPTR_OBJECTHANDLE vmObjHandle; + IfFailThrow(pDAC->GetCurrentException(m_vmThreadToken, &vmObjHandle)); if (vmObjHandle.IsNull()) { @@ -826,7 +829,8 @@ HRESULT CordbThread::GetCurrentException(ICorDebugValue ** ppExceptionObject) #if defined(_DEBUG) // Since we know an exception is in progress on this thread, our assumption about the // thread's current AppDomain should be correct - VMPTR_AppDomain vmAppDomain = pDAC->GetCurrentAppDomain(); + VMPTR_AppDomain vmAppDomain; + IfFailThrow(pDAC->GetCurrentAppDomain(&vmAppDomain)); _ASSERTE(GetAppDomain()->GetADToken() == vmAppDomain); #endif // _DEBUG @@ -893,7 +897,9 @@ bool CordbThread::IsThreadWaitingOrSleeping() //of reading USER_UNSAFE_POINT flag. //We don't cache the value, because it's potentially incomplete. IDacDbiInterface *pDAC = GetProcess()->GetDAC(); - userState = pDAC->GetPartialUserState(m_vmThreadToken); + CorDebugUserState partialState; + IfFailThrow(pDAC->GetPartialUserState(m_vmThreadToken, &partialState)); + userState = partialState; } return (userState & USER_WAIT_SLEEP_JOIN) != 0; @@ -906,7 +912,9 @@ bool CordbThread::IsThreadWaitingOrSleeping() // bool CordbThread::IsThreadDead() { - return GetProcess()->GetDAC()->IsThreadMarkedDead(m_vmThreadToken); + bool _isDead; + IfFailThrow(GetProcess()->GetDAC()->IsThreadMarkedDead(m_vmThreadToken, &_isDead)); + return _isDead; } // Helper to return CORDBG_E_BAD_THREAD_STATE if IsThreadDead @@ -1157,7 +1165,7 @@ HRESULT CordbThread::GetRegisterSet(ICorDebugRegisterSet ** ppRegisters) // convert the CONTEXT to a DebuggerREGDISPLAY IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - pDAC->ConvertContextToDebuggerRegDisplay(&ctx, pDRD, true); + IfFailThrow(pDAC->ConvertContextToDebuggerRegDisplay(&ctx, pDRD, true)); // create the CordbRegisterSet RSInitHolder pRS(new CordbRegisterSet(pDRD, @@ -1580,7 +1588,7 @@ void CordbThread::LoadFloatState() INTERNAL_SYNC_API_ENTRY(GetProcess()); DT_CONTEXT tempContext; - GetProcess()->GetDAC()->GetContext(m_vmThreadToken, &tempContext); + IfFailThrow(GetProcess()->GetDAC()->GetContext(m_vmThreadToken, &tempContext)); #if defined(TARGET_X86) Get32bitFPRegisters((CONTEXT*) &tempContext); @@ -1710,7 +1718,7 @@ HRESULT CordbThread::GetManagedContext(DT_CONTEXT ** ppContext) if (m_fContextFresh == false) { IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - m_vmLeftSideContext = pDAC->GetManagedStoppedContext(m_vmThreadToken); + IfFailThrow(pDAC->GetManagedStoppedContext(m_vmThreadToken, &m_vmLeftSideContext)); if (m_vmLeftSideContext.IsNull()) { @@ -1752,7 +1760,7 @@ HRESULT CordbThread::SetManagedContext(DT_CONTEXT * pContext) HRESULT hr = S_OK; IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - m_vmLeftSideContext = pDAC->GetManagedStoppedContext(m_vmThreadToken); + IfFailThrow(pDAC->GetManagedStoppedContext(m_vmThreadToken, &m_vmLeftSideContext)); if (m_vmLeftSideContext.IsNull()) { @@ -1884,7 +1892,8 @@ HRESULT CordbThread::GetObject(ICorDebugValue ** ppThreadObject) if (SUCCEEDED(hr)) { IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - VMPTR_OBJECTHANDLE vmObjHandle = pDAC->GetThreadObject(m_vmThreadToken); + VMPTR_OBJECTHANDLE vmObjHandle; + IfFailThrow(pDAC->GetThreadObject(m_vmThreadToken, &vmObjHandle)); if (vmObjHandle.IsNull()) { ThrowHR(E_FAIL); @@ -2210,7 +2219,9 @@ HRESULT CordbThread::HasUnhandledException() PUBLIC_REENTRANT_API_BEGIN(this) { IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - if(pDAC->HasUnhandledException(m_vmThreadToken)) + BOOL hasUnhandled; + IfFailThrow(pDAC->HasUnhandledException(m_vmThreadToken, &hasUnhandled)); + if(hasUnhandled) { hr = S_OK; } @@ -2342,7 +2353,8 @@ HRESULT CordbThread::GetActiveInternalFrames(ULONG32 cInternalFrames, *pcInternalFrames = 0; IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - ULONG32 cActiveInternalFrames = pDAC->GetCountOfInternalFrames(m_vmThreadToken); + ULONG32 cActiveInternalFrames; + IfFailThrow(pDAC->GetCountOfInternalFrames(m_vmThreadToken, &cActiveInternalFrames)); // Set the count. *pcInternalFrames = cActiveInternalFrames; @@ -2367,9 +2379,9 @@ HRESULT CordbThread::GetActiveInternalFrames(ULONG32 cInternalFrames, // caught above this frame. data.pInternalFrames.EnableAutoClear(); - pDAC->EnumerateInternalFrames(m_vmThreadToken, + IfFailThrow(pDAC->EnumerateInternalFrames(m_vmThreadToken, &CordbThread::GetActiveInternalFramesCallback, - &data); + &data)); _ASSERTE(cActiveInternalFrames == data.pInternalFrames.Length()); // Copy the internal frames we have accumulated in GetActiveInternalFramesData to the out @@ -2417,12 +2429,14 @@ HRESULT CordbThread::GetCurrentCustomDebuggerNotification(ICorDebugValue ** ppNo // Go to the LS and retrieve any notification object. // IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - VMPTR_OBJECTHANDLE vmObjHandle = pDAC->GetCurrentCustomDebuggerNotification(m_vmThreadToken); + VMPTR_OBJECTHANDLE vmObjHandle; + IfFailThrow(pDAC->GetCurrentCustomDebuggerNotification(m_vmThreadToken, &vmObjHandle)); #if defined(_DEBUG) // Since we know a notification has occurred on this thread, our assumption about the // thread's current AppDomain should be correct - VMPTR_AppDomain vmAppDomain = pDAC->GetCurrentAppDomain(); + VMPTR_AppDomain vmAppDomain; + IfFailThrow(pDAC->GetCurrentAppDomain(&vmAppDomain)); _ASSERTE(GetAppDomain()->GetADToken() == vmAppDomain); #endif // _DEBUG @@ -2464,7 +2478,7 @@ HRESULT CordbThread::GetBytesAllocated(ULONG64 *pSohAllocatedBytes, } IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - pDAC->GetThreadAllocInfo(m_vmThreadToken, &threadAllocInfo); + IfFailThrow(pDAC->GetThreadAllocInfo(m_vmThreadToken, &threadAllocInfo)); *pSohAllocatedBytes = threadAllocInfo.m_allocBytesSOH; *pUohAllocatedBytes = threadAllocInfo.m_allocBytesUOH; @@ -2537,7 +2551,7 @@ HRESULT CordbThread::GetConnectionID(CONNID * pConnectionID) } IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - *pConnectionID = pDAC->GetConnectionID(m_vmThreadToken); + IfFailThrow(pDAC->GetConnectionID(m_vmThreadToken, pConnectionID)); if (*pConnectionID == INVALID_CONNECTION_ID) { @@ -2595,7 +2609,9 @@ HRESULT CordbThread::GetTaskID(TASKID * pTaskID) TASKID CordbThread::GetTaskID() { IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - return pDAC->GetTaskID(m_vmThreadToken); + TASKID taskId; + IfFailThrow(pDAC->GetTaskID(m_vmThreadToken, &taskId)); + return taskId; } @@ -2628,7 +2644,7 @@ HRESULT CordbThread::GetVolatileOSThreadID(DWORD * pdwTID) } IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - *pdwTID = pDAC->TryGetVolatileOSThreadID(m_vmThreadToken); + IfFailThrow(pDAC->TryGetVolatileOSThreadID(m_vmThreadToken, pdwTID)); if (*pdwTID == 0) { @@ -2650,7 +2666,8 @@ HRESULT CordbThread::GetVolatileOSThreadID(DWORD * pdwTID) DWORD CordbThread::GetVolatileOSThreadID() { IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - DWORD dwThreadID = pDAC->TryGetVolatileOSThreadID(m_vmThreadToken); + DWORD dwThreadID; + IfFailThrow(pDAC->TryGetVolatileOSThreadID(m_vmThreadToken, &dwThreadID)); if (dwThreadID == 0) { @@ -3770,14 +3787,14 @@ HRESULT CordbUnmanagedThread::SetupFirstChanceHijack(EHijackReason::EHijackReaso ThrowHR(hr); #endif CORDB_ADDRESS LSContextAddr; - GetProcess()->GetDAC()->Hijack(VMPTR_Thread::NullPtr(), + IfFailThrow(GetProcess()->GetDAC()->Hijack(VMPTR_Thread::NullPtr(), GetOSTid(), pExceptionRecord, (T_CONTEXT*) GetHijackCtx(), sizeof(T_CONTEXT), reason, NULL, - &LSContextAddr); + &LSContextAddr)); LOG((LF_CORDB, LL_INFO10000, "CUT::SFCH: pLeftSideContext=0x%p\n", LSContextAddr)); m_pLeftSideContext.Set(CORDB_ADDRESS_TO_PTR(LSContextAddr)); } @@ -3843,7 +3860,7 @@ HRESULT CordbUnmanagedThread::SetupGenericHijack(DWORD eventCode, const EXCEPTIO // Note that the data-target is not atomic, and we have no rollback mechanism. // We have to do several writes. If the data-target fails the writes half-way through the // target will be inconsistent. - GetProcess()->GetDAC()->Hijack( + IfFailThrow(GetProcess()->GetDAC()->Hijack( pThread->m_vmThreadToken, dwThreadId, pRecord, @@ -3851,7 +3868,7 @@ HRESULT CordbUnmanagedThread::SetupGenericHijack(DWORD eventCode, const EXCEPTIO sizeof(T_CONTEXT), EHijackReason::kGenericHijack, NULL, - NULL); + NULL)); } EX_CATCH_HRESULT(hr); if (SUCCEEDED(hr)) @@ -5221,7 +5238,8 @@ BOOL CordbInternalFrame::ConvertInternalFrameForILMethodWithoutMetadata( } // Retrieve the type of the method associated with the STUBFRAME_JIT_COMPILATION. - IDacDbiInterface::DynamicMethodType type = GetProcess()->GetDAC()->IsDiagnosticsHiddenOrLCGMethod(m_vmMethodDesc); + IDacDbiInterface::DynamicMethodType type; + IfFailThrow(GetProcess()->GetDAC()->IsDiagnosticsHiddenOrLCGMethod(m_vmMethodDesc, &type)); // Here are the conversion rules: // 1) For a normal managed method, we don't convert, and we return FALSE. @@ -5907,7 +5925,7 @@ HRESULT CordbNativeFrame::IsMatchingParentFrame(ICorDebugNativeFrame2 * pPotenti FramePointer fpToCheck = pFrameToCheck->m_misc.fpParentOrSelf; IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - *pIsParent = pDAC->IsMatchingParentFrame(fpToCheck, fpParent); + IfFailThrow(pDAC->IsMatchingParentFrame(fpToCheck, fpParent, pIsParent)); } } EX_CATCH_HRESULT(hr); @@ -5947,7 +5965,7 @@ HRESULT CordbNativeFrame::GetStackParameterSize(ULONG32 * pSize) #if defined(TARGET_X86) IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - *pSize = pDAC->GetStackParameterSize(PTR_TO_CORDB_ADDRESS(CORDbgGetIP(&m_context))); + IfFailThrow(pDAC->GetStackParameterSize(PTR_TO_CORDB_ADDRESS(CORDbgGetIP(&m_context)), pSize)); #else // !TARGET_X86 hr = S_FALSE; *pSize = 0; @@ -7222,7 +7240,9 @@ bool CordbNativeFrame::IsLeafFrame() const else { IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - m_optfIsLeafFrame = (pDAC->IsLeafFrame(m_pThread->m_vmThreadToken, &m_context) == TRUE); + BOOL isLeaf; + IfFailThrow(pDAC->IsLeafFrame(m_pThread->m_vmThreadToken, &m_context, &isLeaf)); + m_optfIsLeafFrame = (isLeaf == TRUE); } } return m_optfIsLeafFrame.GetValue(); @@ -7299,8 +7319,9 @@ BOOL CordbNativeFrame::ConvertNativeFrameForILMethodWithoutMetadata( *ppInternalFrame2 = NULL; IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - IDacDbiInterface::DynamicMethodType type = - pDAC->IsDiagnosticsHiddenOrLCGMethod(GetNativeCode()->GetVMNativeCodeMethodDescToken()); + IDacDbiInterface::DynamicMethodType type; + IfFailThrow( + pDAC->IsDiagnosticsHiddenOrLCGMethod(GetNativeCode()->GetVMNativeCodeMethodDescToken(), &type)); // Here are the conversion rules: // 1) For a normal managed method, we don't convert, and we return FALSE. @@ -7430,7 +7451,8 @@ HRESULT CordbJITILFrame::Init() CORDB_ADDRESS argBase; // Now is the time to ask DacDbi to retrieve the information based on the VASigCookie. IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - TargetBuffer sigTargetBuf = pDAC->GetVarArgSig(pRemoteValue, &argBase); + TargetBuffer sigTargetBuf; + IfFailThrow(pDAC->GetVarArgSig(pRemoteValue, &argBase, &sigTargetBuf)); // make sure we are not leaking any memory _ASSERTE(m_rgbSigParserBuf == NULL); @@ -7520,8 +7542,10 @@ HRESULT CordbJITILFrame::Init() // Ask DAC to resolve the token for us. We really don't want to deal with all the logic here. IDacDbiInterface * pDAC = GetProcess()->GetDAC(); // On a minidump, we'll throw if we're missing the memory. + GENERICS_TYPE_TOKEN resolvedToken; ALLOW_DATATARGET_MISSING_MEMORY( - m_frameParamsToken = pDAC->ResolveExactGenericArgsToken(m_dwFrameParamsTokenIndex, uRawToken); + IfFailThrow(pDAC->ResolveExactGenericArgsToken(m_dwFrameParamsTokenIndex, uRawToken, &resolvedToken)); + m_frameParamsToken = resolvedToken; ); } } @@ -7626,11 +7650,11 @@ void CordbJITILFrame::LoadGenericArgs() UINT32 cGenericClassTypeParams = 0; DacDbiArrayList rgGenericTypeParams; - pDAC->GetMethodDescParams(GetCurrentAppDomain()->GetADToken(), + IfFailThrow(pDAC->GetMethodDescParams(GetCurrentAppDomain()->GetADToken(), m_nativeFrame->GetNativeCode()->GetVMNativeCodeMethodDescToken(), m_frameParamsToken, &cGenericClassTypeParams, - &rgGenericTypeParams); + &rgGenericTypeParams)); UINT32 cTotalGenericTypeParams = rgGenericTypeParams.Count(); @@ -10960,7 +10984,7 @@ HRESULT CordbAsyncFrame::Init() // LookupOrCreateNativeCode is marked INTERNAL_SYNC_API_ENTRY and requires the StopGoLock. m_pCode.Assign(pModule->LookupOrCreateNativeCode(m_methodDef, m_vmMethodDesc, m_pCodeStart)); m_pCode->LoadNativeInfo(); - GetProcess()->GetDAC()->GetAsyncLocals(m_vmMethodDesc, m_pCodeStart, m_state, &m_asyncVars); + IfFailThrow(GetProcess()->GetDAC()->GetAsyncLocals(m_vmMethodDesc, m_pCodeStart, m_state, &m_asyncVars)); // Initialize function and IL code m_pFunction.Assign(m_pCode->GetFunction()); @@ -11507,14 +11531,16 @@ void CordbAsyncFrame::LoadGenericArgs() break; } } - genericTypeParam = pDAC->ResolveExactGenericArgsToken(genericArgIndex, genericTypeParam); + GENERICS_TYPE_TOKEN resolvedToken; + IfFailThrow(pDAC->ResolveExactGenericArgsToken(genericArgIndex, genericTypeParam, &resolvedToken)); + genericTypeParam = resolvedToken; } - pDAC->GetMethodDescParams(m_pAppDomain->GetADToken(), + IfFailThrow(pDAC->GetMethodDescParams(m_pAppDomain->GetADToken(), m_vmMethodDesc, genericTypeParam, &cGenericClassTypeParams, - &rgGenericTypeParams); + &rgGenericTypeParams)); UINT32 cTotalGenericTypeParams = rgGenericTypeParams.Count(); diff --git a/src/coreclr/debug/di/rstype.cpp b/src/coreclr/debug/di/rstype.cpp index ae686064e96cb1..de6922416706ef 100644 --- a/src/coreclr/debug/di/rstype.cpp +++ b/src/coreclr/debug/di/rstype.cpp @@ -1163,11 +1163,11 @@ HRESULT CordbType::TypeDataToType(CordbAppDomain *pAppDomain, DebuggerIPCE_Basic { RSLockHolder lockHolder(pProcess->GetProcessLock()); - pProcess->GetDAC()->TypeHandleToExpandedTypeInfo(NoValueTypeBoxing, // could be generics + IfFailThrow(pProcess->GetDAC()->TypeHandleToExpandedTypeInfo(NoValueTypeBoxing, // could be generics // which are never boxed pAppDomain->GetADToken(), data->vmTypeHandle, - &typeInfo); + &typeInfo)); } IfFailThrow(CordbType::TypeDataToType(pAppDomain,&typeInfo, pRes)); @@ -1373,7 +1373,7 @@ HRESULT CordbType::InstantiateFromTypeHandle(CordbAppDomain * pAppDomain, TypeParamsList params; { RSLockHolder lockHolder(pProcess->GetProcessLock()); - pProcess->GetDAC()->GetTypeHandleParams(pAppDomain->GetADToken(), vmTypeHandle, ¶ms); + IfFailThrow(pProcess->GetDAC()->GetTypeHandleParams(pAppDomain->GetADToken(), vmTypeHandle, ¶ms)); } // convert the parameter type information to a list of CordbTypeInstances (one for each parameter) @@ -1616,11 +1616,11 @@ HRESULT CordbType::InitStringOrObjectClass(BOOL fForceInit) { RSLockHolder lockHolder(GetProcess()->GetProcessLock()); - pProcess->GetDAC()->GetSimpleType(m_appdomain->GetADToken(), + IfFailThrow(pProcess->GetDAC()->GetSimpleType(m_appdomain->GetADToken(), m_elementType, &metadataToken, &vmModule, - &vmDomainAssembly); + &vmDomainAssembly)); } // @@ -1689,7 +1689,7 @@ HRESULT CordbType::InitInstantiationFieldInfo(BOOL fForceInit) CordbProcess *pProcess = GetProcess(); { RSLockHolder lockHolder(pProcess->GetProcessLock()); - typeHandleApprox = pProcess->GetDAC()->GetApproxTypeHandle(&typeData); + IfFailThrow(pProcess->GetDAC()->GetApproxTypeHandle(&typeData, &typeHandleApprox)); } } EX_CATCH_HRESULT(hr); @@ -1704,11 +1704,11 @@ HRESULT CordbType::InitInstantiationFieldInfo(BOOL fForceInit) // this may be called multiple times. Each call will discard previous values in m_fieldList and reinitialize // the list with updated information RSLockHolder lockHolder(pProcess->GetProcessLock()); - pProcess->GetDAC()->GetInstantiationFieldInfo(m_pClass->GetModule()->GetRuntimeDomainAssembly(), + IfFailThrow(pProcess->GetDAC()->GetInstantiationFieldInfo(m_pClass->GetModule()->GetRuntimeDomainAssembly(), m_typeHandleExact, typeHandleApprox, &m_fieldList, - &m_objectSize); + &m_objectSize)); } } EX_CATCH_HRESULT(hr); @@ -2342,13 +2342,13 @@ HRESULT CordbType::GetTypeID(COR_TYPEID *pId) VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr(); // get module and token of the simple type - GetProcess()->GetDAC()->GetSimpleType(GetAppDomain()->GetADToken(), + IfFailThrow(GetProcess()->GetDAC()->GetSimpleType(GetAppDomain()->GetADToken(), et, &mdToken, &vmModule, - &vmDomainAssembly); + &vmDomainAssembly)); - vmTypeHandle = GetProcess()->GetDAC()->GetTypeHandle(vmModule, mdToken); + IfFailThrow(GetProcess()->GetDAC()->GetTypeHandle(vmModule, mdToken, &vmTypeHandle)); } break; case ELEMENT_TYPE_ARRAY: @@ -2382,7 +2382,7 @@ HRESULT CordbType::GetTypeID(COR_TYPEID *pId) IfFailThrow(hr); VMPTR_Module vmModule = GetModule(); - vmTypeHandle = GetProcess()->GetDAC()->GetTypeHandle(vmModule, mdToken); + IfFailThrow(GetProcess()->GetDAC()->GetTypeHandle(vmModule, mdToken, &vmTypeHandle)); } } break; @@ -2397,7 +2397,7 @@ HRESULT CordbType::GetTypeID(COR_TYPEID *pId) break; } - GetProcess()->GetDAC()->GetTypeIDForType(vmTypeHandle, pId); + IfFailThrow(GetProcess()->GetDAC()->GetTypeIDForType(vmTypeHandle, pId)); } EX_CATCH_HRESULT(hr); @@ -2681,7 +2681,9 @@ HRESULT CordbType::RequiresAlign8(BOOL* isRequired) if (m_typeHandleExact.IsNull()) InitInstantiationTypeHandle(FALSE); - *isRequired = GetProcess()->GetDAC()->RequiresAlign8(m_typeHandleExact); + BOOL _alignResult; + IfFailThrow(GetProcess()->GetDAC()->RequiresAlign8(m_typeHandleExact, &_alignResult)); + *isRequired = _alignResult; } else { diff --git a/src/coreclr/debug/di/valuehome.cpp b/src/coreclr/debug/di/valuehome.cpp index 5320ed22332507..5a12b504b6241c 100644 --- a/src/coreclr/debug/di/valuehome.cpp +++ b/src/coreclr/debug/di/valuehome.cpp @@ -882,7 +882,7 @@ CORDB_ADDRESS HandleValueHome::GetAddress() CORDB_ADDRESS handle = PTR_TO_CORDB_ADDRESS((void *)NULL); EX_TRY { - handle = m_pProcess->GetDAC()->GetHandleAddressFromVmHandle(m_vmObjectHandle); + IfFailThrow(m_pProcess->GetDAC()->GetHandleAddressFromVmHandle(m_vmObjectHandle, &handle)); } EX_CATCH { @@ -897,7 +897,7 @@ void HandleValueHome::GetValue(MemoryRange dest) { _ASSERTE((m_pProcess != NULL) && !m_vmObjectHandle.IsNull()); CORDB_ADDRESS objPtr = PTR_TO_CORDB_ADDRESS((void *)NULL); - objPtr = m_pProcess->GetDAC()->GetHandleAddressFromVmHandle(m_vmObjectHandle); + IfFailThrow(m_pProcess->GetDAC()->GetHandleAddressFromVmHandle(m_vmObjectHandle, &objPtr)); _ASSERTE(dest.Size() <= sizeof(void *)); _ASSERTE(dest.StartAddress() != NULL);