From ef1e2ab328087c61a6878c1e84f4fc5d710aebce Mon Sep 17 00:00:00 2001 From: dotnet-bot Date: Fri, 30 Jan 2015 14:14:42 -0800 Subject: Initial commit to populate CoreCLR repo [tfs-changeset: 1407945] --- src/vm/dbginterface.h | 420 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 420 insertions(+) create mode 100644 src/vm/dbginterface.h (limited to 'src/vm/dbginterface.h') diff --git a/src/vm/dbginterface.h b/src/vm/dbginterface.h new file mode 100644 index 0000000000..fb3e167374 --- /dev/null +++ b/src/vm/dbginterface.h @@ -0,0 +1,420 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// +// COM+99 Debug Interface Header +// + + + +#ifndef _dbgInterface_h_ +#define _dbgInterface_h_ + +#include "common.h" +#include "eedbginterface.h" +#include "corjit.h" +#include "../debug/inc/dbgipcevents.h" +#include "primitives.h" + +typedef DPTR(struct ICorDebugInfo::NativeVarInfo) PTR_NativeVarInfo; + +typedef void (*FAVORCALLBACK)(void *); + +// +// The purpose of this object is to serve as an entry point to the +// debugger, which used to reside in a seperate DLL. +// + +class DebugInterface +{ + VPTR_BASE_VTABLE_CLASS(DebugInterface); + +public: + + // + // Functions exported from the debugger to the EE. + // + +#ifndef DACCESS_COMPILE + + virtual HRESULT Startup(void) = 0; + + virtual HRESULT StartupPhase2(Thread * pThread) = 0; + + // Some callers into the debugger (e.g., ETW rundown) know they will need the lazy + // data initialized but cannot afford to have it initialized unpredictably or inside a + // lock. They can use this function to force the data to be initialized at a + // controlled point in time + virtual void InitializeLazyDataIfNecessary() = 0; + + virtual void SetEEInterface(EEDebugInterface* i) = 0; + + virtual void StopDebugger(void) = 0; + + virtual BOOL IsStopped(void) = 0; + + virtual void ThreadCreated(Thread* pRuntimeThread) = 0; + + virtual void ThreadStarted(Thread* pRuntimeThread) = 0; + + virtual void DetachThread(Thread *pRuntimeThread) = 0; + + // Called when a module is being loaded into an AppDomain. + // This includes when a domain neutral module is loaded into a new AppDomain. + // This is called only when a debugger is attached, and will occur after the + // related LoadAssembly and AddAppDomainToIPCBlock calls and before any + // LoadClass calls for this module. + virtual void LoadModule(Module * pRuntimeModule, // the module being loaded + LPCWSTR psModuleName, // module file name + DWORD dwModuleName, // number of characters in file name excludign null + Assembly * pAssembly, // the assembly the module belongs to + AppDomain * pAppDomain, // the AppDomain the module is being loaded into + DomainFile * pDomainFile, + BOOL fAttaching) = 0; // true if this notification is due to a debugger + // being attached to the process + + // Called AFTER LoadModule, and after the module has reached FILE_LOADED. This lets + // dbgapi do any processing that needs to wait until the FILE_LOADED stage (e.g., + // binding breakpoints in NGENd generics). + virtual void LoadModuleFinished(Module * pModule, AppDomain * pAppDomain) = 0; + + // Called for all modules in an AppDomain when the AppDomain is unloaded. + // This includes domain neutral modules that are also loaded into other domains. + // This is called only when a debugger is attached, and will occur after all UnloadClass + // calls and before any UnloadAssembly or RemoveAppDomainFromIPCBlock calls realted + // to this module. On CLR shutdown, we are not guarenteed to get UnloadModule calls for + // all outstanding loaded modules. + virtual void UnloadModule(Module* pRuntimeModule, AppDomain *pAppDomain) = 0; + + // Called when a Module* is being destroyed. + // Specifically, the Module has completed unloading (which may have been done asyncronously), all resources + // associated are being freed, and the Module* is about to become invalid. The debugger should remove all + // references to this Module*. + // NOTE: This is called REGARDLESS of whether a debugger is attached or not, and will occur after any other + // notifications about this module (including any RemoveAppDomainFromIPCBlock call indicating the module's + // domain has been unloaded). + virtual void DestructModule(Module *pModule) = 0; + + virtual BOOL LoadClass(TypeHandle th, + mdTypeDef classMetadataToken, + Module *classModule, + AppDomain *pAppDomain) = 0; + + virtual void UnloadClass(mdTypeDef classMetadataToken, + Module *classModule, + AppDomain *pAppDomain) = 0; + + // Filter we call in 1st-pass to dispatch a CHF callback. + // pCatchStackAddress really should be a Frame* onto the stack. That way the CHF stack address + // and the debugger's stacktrace Frames will match up. + // This is only called by stubs. + virtual LONG NotifyOfCHFFilter(EXCEPTION_POINTERS* pExceptionPointers, PVOID pCatchStackAddr) = 0; + + + virtual bool FirstChanceNativeException(EXCEPTION_RECORD *exception, + CONTEXT *context, + DWORD code, + Thread *thread) = 0; + + // pThread is thread that exception is on. + // currentSP is stack frame of the throw site. + // currentIP is ip of the throw site. + // pStubFrame = NULL if the currentSp is for a non-stub frame (ie, a regular JITed catched). + // For stub-based throws, pStubFrame is the EE Frame of the stub. + virtual bool FirstChanceManagedException(Thread *pThread, SIZE_T currentIP, SIZE_T currentSP) = 0; + + virtual void FirstChanceManagedExceptionCatcherFound(Thread *pThread, + MethodDesc *pMD, TADDR pMethodAddr, + BYTE *currentSP, + EE_ILEXCEPTION_CLAUSE *pEHClause) = 0; + + virtual LONG LastChanceManagedException(EXCEPTION_POINTERS * pExceptionInfo, + Thread *thread, + BOOL jitAttachRequested) = 0; + + virtual void ManagedExceptionUnwindBegin(Thread *pThread) = 0; + + virtual void DeleteInterceptContext(void *pContext) = 0; + + virtual void ExceptionFilter(MethodDesc *fd, TADDR pMethodAddr, + SIZE_T offset, + BYTE *pStack) = 0; + + virtual void ExceptionHandle(MethodDesc *fd, TADDR pMethodAddr, + SIZE_T offset, + BYTE *pStack) = 0; + + virtual void SendUserBreakpoint(Thread *thread) = 0; + + // Send an UpdateModuleSyms event, and block waiting for the debugger to continue it. + virtual void SendUpdateModuleSymsEventAndBlock(Module *pRuntimeModule, + AppDomain *pAppDomain) = 0; + + // + // RequestFavor gets the debugger helper thread to call a function. It's + // typically called when the current thread can't call the function directly, + // e.g, there isn't enough stack space. + // + // RequestFavor ensures that the helper thread has been initialized to + // execute favors and then calls Debugger:DoFavor. It blocks until the + // favor callback completes. + // + // Parameters: + // fp - Favour callback function + // pData - the parameter passed to the favor callback function. + // + // Return values: + // S_OK if the function succeeds, else a failure HRESULT + // + virtual HRESULT RequestFavor(FAVORCALLBACK fp, void * pData) = 0; + +#endif // #ifndef DACCESS_COMPILE + + // JITComplete() is called after a method is jit-compiled, successfully or not + +#ifndef DACCESS_COMPILE + + virtual void JITComplete(MethodDesc* fd, TADDR newAddress) = 0; + + // + // EnC functions + // +#ifdef EnC_SUPPORTED + // Notify that an existing method has been edited in a loaded type + virtual HRESULT UpdateFunction(MethodDesc* md, SIZE_T enCVersion) = 0; + + // Notify that a new method has been added to a loaded type + virtual HRESULT AddFunction(MethodDesc* md, SIZE_T enCVersion) = 0; + + virtual HRESULT UpdateNotYetLoadedFunction(mdMethodDef token, Module * pModule, SIZE_T enCVersion) = 0; + + // Notify that a field has been added + virtual HRESULT AddField(FieldDesc* fd, SIZE_T enCVersion) = 0; + + // Notify that the EE has completed the remap and is about to resume execution + virtual HRESULT RemapComplete(MethodDesc *pMd, TADDR addr, SIZE_T nativeOffset) = 0; + + // Used by the codemanager FixContextForEnC() to update + virtual HRESULT MapILInfoToCurrentNative(MethodDesc *pMD, + SIZE_T ilOffset, + TADDR nativeFnxStart, + SIZE_T *nativeOffset) = 0; +#endif // EnC_SUPPORTED + + // Get debugger variable information for a specific version of a method + virtual void GetVarInfo(MethodDesc * fd, // [IN] method of interest + void *DebuggerVersionToken, // [IN] which edit version + SIZE_T * cVars, // [OUT] size of 'vars' + const ICorDebugInfo::NativeVarInfo **vars // [OUT] map telling where local vars are stored + ) = 0; + + virtual void getBoundaries(MethodDesc * ftn, + unsigned int *cILOffsets, DWORD **pILOffsets, + ICorDebugInfo::BoundaryTypes* implictBoundaries) = 0; + + virtual void getVars(MethodDesc * ftn, + ULONG32 *cVars, ICorDebugInfo::ILVarInfo **vars, + bool *extendOthers) = 0; + + virtual BOOL CheckGetPatchedOpcode(CORDB_ADDRESS_TYPE *address, /*OUT*/ PRD_TYPE *pOpcode) = 0; + + virtual PRD_TYPE GetPatchedOpcode(CORDB_ADDRESS_TYPE *ip) = 0; + + virtual void TraceCall(const BYTE *target) = 0; + + virtual bool ThreadsAtUnsafePlaces(void) = 0; + + virtual HRESULT LaunchDebuggerForUser(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo, BOOL sendManagedEvent, BOOL explicitUserRequest) = 0; + + // Launches a debugger and waits for it to attach + virtual void JitAttach(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo, BOOL willSendManagedEvent, BOOL explicitUserRequest) = 0; + + // Prepares for a jit attach and decides which of several potentially + // racing threads get to launch the debugger + virtual BOOL PreJitAttach(BOOL willSendManagedEvent, BOOL willLaunchDebugger, BOOL explicitUserRequest) = 0; + + // Waits for a jit attach to complete + virtual void WaitForDebuggerAttach() = 0; + + // Completes the jit attach, unblocking all threads waiting for attach, + // regardless of whether or not the debugger actually attached + virtual void PostJitAttach() = 0; + + virtual void SendUserBreakpointAndSynchronize(Thread * pThread) = 0; + + virtual void SendLogMessage(int iLevel, + SString * pSwitchName, + SString * pMessage) = 0; + + // send a custom notification from the target to the RS. This will become an ICorDebugThread and + // ICorDebugAppDomain on the RS. + virtual void SendCustomDebuggerNotification(Thread * pThread, DomainFile * pDomainFile, mdTypeDef classToken) = 0; + + // Send an MDA notification. This ultimately translates to an ICorDebugMDA object on the Right-Side. + virtual void SendMDANotification( + Thread * pThread, // may be NULL. Lets us send on behalf of other threads. + SString * szName, + SString * szDescription, + SString * szXML, + CorDebugMDAFlags flags, + BOOL bAttach + ) = 0; + + virtual bool IsJMCMethod(Module* pModule, mdMethodDef tkMethod) = 0; + + // Given a method, get's its EnC version number. 1 if the method is not EnCed. + // Note that MethodDescs are reused between versions so this will give us + // the most recent EnC number. + virtual int GetMethodEncNumber(MethodDesc * pMethod) = 0; + + virtual void SendLogSwitchSetting (int iLevel, + int iReason, + __in_z LPCWSTR pLogSwitchName, + __in_z LPCWSTR pParentSwitchName) = 0; + + virtual bool IsLoggingEnabled (void) = 0; + + virtual bool GetILOffsetFromNative (MethodDesc *PFD, + const BYTE *pbAddr, + DWORD nativeOffset, + DWORD *ilOffset) = 0; + + virtual HRESULT GetILToNativeMapping(MethodDesc *pMD, + ULONG32 cMap, + ULONG32 *pcMap, + COR_DEBUG_IL_TO_NATIVE_MAP map[]) = 0; + + virtual HRESULT GetILToNativeMappingIntoArrays( + MethodDesc * pMD, + USHORT cMapMax, + USHORT * pcMap, + UINT ** prguiILOffset, + UINT ** prguiNativeOffset) = 0; + + virtual DWORD GetHelperThreadID(void ) = 0; + + // Called whenever a new AppDomain is created, regardless of whether a debugger is attached. + // This will be called before any LoadAssembly calls for assemblies in this domain. + virtual HRESULT AddAppDomainToIPC (AppDomain *pAppDomain) = 0; + + // Called whenever an AppDomain is unloaded, regardless of whether a Debugger is attached + // This will occur after any UnloadAssembly and UnloadModule callbacks for this domain (if any). + virtual HRESULT RemoveAppDomainFromIPC (AppDomain *pAppDomain) = 0; + + virtual HRESULT UpdateAppDomainEntryInIPC (AppDomain *pAppDomain) = 0; + + // Called when an assembly is being loaded into an AppDomain. + // This includes when a domain neutral assembly is loaded into a new AppDomain. + // This is called only when a debugger is attached, and will occur after the + // related AddAppDomainToIPCBlock call and before any LoadModule or + // LoadClass calls for this assembly. + virtual void LoadAssembly(DomainAssembly * pDomainAssembly) = 0; // the assembly being loaded + + + // Called for all assemblies in an AppDomain when the AppDomain is unloaded. + // This includes domain neutral assemblies that are also loaded into other domains. + // This is called only when a debugger is attached, and will occur after all UnloadClass + // and UnloadModule calls and before any RemoveAppDomainFromIPCBlock calls realted + // to this assembly. On CLR shutdown, we are not guarenteed to get UnloadAssembly calls for + // all outstanding loaded assemblies. + virtual void UnloadAssembly(DomainAssembly * pDomainAssembly) = 0; + + virtual HRESULT SetILInstrumentedCodeMap(MethodDesc *fd, + BOOL fStartJit, + ULONG32 cILMapEntries, + COR_IL_MAP rgILMapEntries[]) = 0; + + virtual void EarlyHelperThreadDeath(void) = 0; + + virtual void ShutdownBegun(void) = 0; + + virtual void LockDebuggerForShutdown(void) = 0; + + virtual void DisableDebugger(void) = 0; + + virtual HRESULT NameChangeEvent(AppDomain *pAppDomain, + Thread *pThread) = 0; + + // send an event to the RS indicating that there's a Ctrl-C or Ctrl-Break + virtual BOOL SendCtrlCToDebugger(DWORD dwCtrlType) = 0; + + // Allows the debugger to keep an up to date list of special threads + virtual HRESULT UpdateSpecialThreadList(DWORD cThreadArrayLength, + DWORD *rgdwThreadIDArray) = 0; + + // Updates the pointer for the debugger services + virtual void SetIDbgThreadControl(IDebuggerThreadControl *pIDbgThreadControl) = 0; + + virtual DWORD GetRCThreadId(void) = 0; + + virtual HRESULT GetVariablesFromOffset(MethodDesc *pMD, + UINT varNativeInfoCount, + ICorDebugInfo::NativeVarInfo *varNativeInfo, + SIZE_T offsetFrom, + CONTEXT *pCtx, + SIZE_T *rgVal1, + SIZE_T *rgVal2, + UINT uRgValSize, + BYTE ***rgpVCs) = 0; + + virtual HRESULT SetVariablesAtOffset(MethodDesc *pMD, + UINT varNativeInfoCount, + ICorDebugInfo::NativeVarInfo *varNativeInfo, + SIZE_T offsetTo, + CONTEXT *pCtx, + SIZE_T *rgVal1, + SIZE_T *rgVal2, + BYTE **rgpVCs) = 0; + + virtual BOOL IsThreadContextInvalid(Thread *pThread) = 0; + + // For Just-My-Code (aka Just-User-Code). + // The jit inserts probes that look like. + // if (*pAddr != 0) call g_pDebugInterface->OnMethodEnter() + + // Invoked when we enter a user method. + // pIP is an ip within the method, right after the prolog. + virtual void OnMethodEnter(void * pIP) = 0; + + // Given a method, the debugger provides the address of the flag. + // This allows the debugger to store the flag whereever it wants + // and with whatever granularity (per-module, per-class, per-function, etc). + virtual DWORD* GetJMCFlagAddr(Module * pModule) = 0; + + // notification for SQL fiber debugging support + virtual void CreateConnection(CONNID dwConnectionId, __in_z WCHAR *wzName) = 0; + virtual void DestroyConnection(CONNID dwConnectionId) = 0; + virtual void ChangeConnection(CONNID dwConnectionId) = 0; + + // + // This function is used to identify the helper thread. + // + virtual bool ThisIsHelperThread(void) = 0; + + virtual HRESULT ReDaclEvents(PSECURITY_DESCRIPTOR securityDescriptor) = 0; + + virtual BOOL ShouldAutoAttach() = 0; + virtual BOOL FallbackJITAttachPrompt() = 0; + virtual HRESULT SetFiberMode(bool isFiberMode) = 0; + +#ifdef FEATURE_INTEROP_DEBUGGING + virtual LONG FirstChanceSuspendHijackWorker(PCONTEXT pContext, PEXCEPTION_RECORD pExceptionRecord) = 0; +#endif + +#endif // #ifndef DACCESS_COMPILE + +#ifdef DACCESS_COMPILE + virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) = 0; + virtual void EnumMemoryRegionsIfFuncEvalFrame(CLRDataEnumMemoryFlags flags, Frame * pFrame) = 0; +#endif +}; + +#ifndef DACCESS_COMPILE +// Helper to make GCC compile. GCC can't handle putting a virtual call in a filter. +struct NotifyOfCHFFilterWrapperParam { void *pFrame; }; +LONG NotifyOfCHFFilterWrapper(EXCEPTION_POINTERS *pExceptionInfo, PVOID pNotifyOfCHFFilterWrapperParam); +#endif + + +#endif // _dbgInterface_h_ -- cgit v1.2.3