2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
6 // COM+99 Debug Interface Header
11 #ifndef _dbgInterface_h_
12 #define _dbgInterface_h_
15 #include "eedbginterface.h"
17 #include "../debug/inc/dbgipcevents.h"
18 #include "primitives.h"
20 typedef DPTR(struct ICorDebugInfo::NativeVarInfo) PTR_NativeVarInfo;
22 typedef void (*FAVORCALLBACK)(void *);
25 // The purpose of this object is to serve as an entry point to the
26 // debugger, which used to reside in a seperate DLL.
31 VPTR_BASE_VTABLE_CLASS_AND_CTOR(DebugInterface);
36 // Functions exported from the debugger to the EE.
39 #ifndef DACCESS_COMPILE
41 virtual HRESULT Startup(void) = 0;
43 virtual HRESULT StartupPhase2(Thread * pThread) = 0;
45 // Some callers into the debugger (e.g., ETW rundown) know they will need the lazy
46 // data initialized but cannot afford to have it initialized unpredictably or inside a
47 // lock. They can use this function to force the data to be initialized at a
48 // controlled point in time
49 virtual void InitializeLazyDataIfNecessary() = 0;
51 virtual void SetEEInterface(EEDebugInterface* i) = 0;
53 virtual void StopDebugger(void) = 0;
55 virtual BOOL IsStopped(void) = 0;
57 virtual void ThreadCreated(Thread* pRuntimeThread) = 0;
59 virtual void ThreadStarted(Thread* pRuntimeThread) = 0;
61 virtual void DetachThread(Thread *pRuntimeThread) = 0;
63 // Called when a module is being loaded into an AppDomain.
64 // This includes when a domain neutral module is loaded into a new AppDomain.
65 // This is called only when a debugger is attached, and will occur after the
66 // related LoadAssembly and AddAppDomainToIPCBlock calls and before any
67 // LoadClass calls for this module.
68 virtual void LoadModule(Module * pRuntimeModule, // the module being loaded
69 LPCWSTR psModuleName, // module file name
70 DWORD dwModuleName, // number of characters in file name excludign null
71 Assembly * pAssembly, // the assembly the module belongs to
72 AppDomain * pAppDomain, // the AppDomain the module is being loaded into
73 DomainFile * pDomainFile,
74 BOOL fAttaching) = 0; // true if this notification is due to a debugger
75 // being attached to the process
77 // Called AFTER LoadModule, and after the module has reached FILE_LOADED. This lets
78 // dbgapi do any processing that needs to wait until the FILE_LOADED stage (e.g.,
79 // binding breakpoints in NGENd generics).
80 virtual void LoadModuleFinished(Module * pModule, AppDomain * pAppDomain) = 0;
82 // Called for all modules in an AppDomain when the AppDomain is unloaded.
83 // This includes domain neutral modules that are also loaded into other domains.
84 // This is called only when a debugger is attached, and will occur after all UnloadClass
85 // calls and before any UnloadAssembly or RemoveAppDomainFromIPCBlock calls realted
86 // to this module. On CLR shutdown, we are not guarenteed to get UnloadModule calls for
87 // all outstanding loaded modules.
88 virtual void UnloadModule(Module* pRuntimeModule, AppDomain *pAppDomain) = 0;
90 // Called when a Module* is being destroyed.
91 // Specifically, the Module has completed unloading (which may have been done asyncronously), all resources
92 // associated are being freed, and the Module* is about to become invalid. The debugger should remove all
93 // references to this Module*.
94 // NOTE: This is called REGARDLESS of whether a debugger is attached or not, and will occur after any other
95 // notifications about this module (including any RemoveAppDomainFromIPCBlock call indicating the module's
96 // domain has been unloaded).
97 virtual void DestructModule(Module *pModule) = 0;
99 virtual BOOL LoadClass(TypeHandle th,
100 mdTypeDef classMetadataToken,
102 AppDomain *pAppDomain) = 0;
104 virtual void UnloadClass(mdTypeDef classMetadataToken,
106 AppDomain *pAppDomain) = 0;
108 // Filter we call in 1st-pass to dispatch a CHF callback.
109 // pCatchStackAddress really should be a Frame* onto the stack. That way the CHF stack address
110 // and the debugger's stacktrace Frames will match up.
111 // This is only called by stubs.
112 virtual LONG NotifyOfCHFFilter(EXCEPTION_POINTERS* pExceptionPointers, PVOID pCatchStackAddr) = 0;
115 virtual bool FirstChanceNativeException(EXCEPTION_RECORD *exception,
120 // pThread is thread that exception is on.
121 // currentSP is stack frame of the throw site.
122 // currentIP is ip of the throw site.
123 // pStubFrame = NULL if the currentSp is for a non-stub frame (ie, a regular JITed catched).
124 // For stub-based throws, pStubFrame is the EE Frame of the stub.
125 virtual bool FirstChanceManagedException(Thread *pThread, SIZE_T currentIP, SIZE_T currentSP) = 0;
127 virtual void FirstChanceManagedExceptionCatcherFound(Thread *pThread,
128 MethodDesc *pMD, TADDR pMethodAddr,
130 EE_ILEXCEPTION_CLAUSE *pEHClause) = 0;
132 virtual LONG LastChanceManagedException(EXCEPTION_POINTERS * pExceptionInfo,
134 BOOL jitAttachRequested) = 0;
136 virtual void ManagedExceptionUnwindBegin(Thread *pThread) = 0;
138 virtual void DeleteInterceptContext(void *pContext) = 0;
140 virtual void ExceptionFilter(MethodDesc *fd, TADDR pMethodAddr,
144 virtual void ExceptionHandle(MethodDesc *fd, TADDR pMethodAddr,
148 virtual void SendUserBreakpoint(Thread *thread) = 0;
150 // Send an UpdateModuleSyms event, and block waiting for the debugger to continue it.
151 virtual void SendUpdateModuleSymsEventAndBlock(Module *pRuntimeModule,
152 AppDomain *pAppDomain) = 0;
155 // RequestFavor gets the debugger helper thread to call a function. It's
156 // typically called when the current thread can't call the function directly,
157 // e.g, there isn't enough stack space.
159 // RequestFavor ensures that the helper thread has been initialized to
160 // execute favors and then calls Debugger:DoFavor. It blocks until the
161 // favor callback completes.
164 // fp - Favour callback function
165 // pData - the parameter passed to the favor callback function.
168 // S_OK if the function succeeds, else a failure HRESULT
170 virtual HRESULT RequestFavor(FAVORCALLBACK fp, void * pData) = 0;
172 #endif // #ifndef DACCESS_COMPILE
174 // JITComplete() is called after a method is jit-compiled, successfully or not
176 #ifndef DACCESS_COMPILE
178 virtual void JITComplete(MethodDesc* fd, TADDR newAddress) = 0;
184 // Notify that an existing method has been edited in a loaded type
185 virtual HRESULT UpdateFunction(MethodDesc* md, SIZE_T enCVersion) = 0;
187 // Notify that a new method has been added to a loaded type
188 virtual HRESULT AddFunction(MethodDesc* md, SIZE_T enCVersion) = 0;
190 virtual HRESULT UpdateNotYetLoadedFunction(mdMethodDef token, Module * pModule, SIZE_T enCVersion) = 0;
192 // Notify that a field has been added
193 virtual HRESULT AddField(FieldDesc* fd, SIZE_T enCVersion) = 0;
195 // Notify that the EE has completed the remap and is about to resume execution
196 virtual HRESULT RemapComplete(MethodDesc *pMd, TADDR addr, SIZE_T nativeOffset) = 0;
198 // Used by the codemanager FixContextForEnC() to update
199 virtual HRESULT MapILInfoToCurrentNative(MethodDesc *pMD,
201 TADDR nativeFnxStart,
202 SIZE_T *nativeOffset) = 0;
203 #endif // EnC_SUPPORTED
205 // Get debugger variable information for a specific version of a method
206 virtual void GetVarInfo(MethodDesc * fd, // [IN] method of interest
207 void *DebuggerVersionToken, // [IN] which edit version
208 SIZE_T * cVars, // [OUT] size of 'vars'
209 const ICorDebugInfo::NativeVarInfo **vars // [OUT] map telling where local vars are stored
212 virtual void getBoundaries(MethodDesc * ftn,
213 unsigned int *cILOffsets, DWORD **pILOffsets,
214 ICorDebugInfo::BoundaryTypes* implictBoundaries) = 0;
216 virtual void getVars(MethodDesc * ftn,
217 ULONG32 *cVars, ICorDebugInfo::ILVarInfo **vars,
218 bool *extendOthers) = 0;
220 virtual BOOL CheckGetPatchedOpcode(CORDB_ADDRESS_TYPE *address, /*OUT*/ PRD_TYPE *pOpcode) = 0;
222 virtual PRD_TYPE GetPatchedOpcode(CORDB_ADDRESS_TYPE *ip) = 0;
224 virtual void TraceCall(const BYTE *target) = 0;
226 virtual bool ThreadsAtUnsafePlaces(void) = 0;
228 virtual HRESULT LaunchDebuggerForUser(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo, BOOL sendManagedEvent, BOOL explicitUserRequest) = 0;
230 // Launches a debugger and waits for it to attach
231 virtual void JitAttach(Thread * pThread, EXCEPTION_POINTERS * pExceptionInfo, BOOL willSendManagedEvent, BOOL explicitUserRequest) = 0;
233 // Prepares for a jit attach and decides which of several potentially
234 // racing threads get to launch the debugger
235 virtual BOOL PreJitAttach(BOOL willSendManagedEvent, BOOL willLaunchDebugger, BOOL explicitUserRequest) = 0;
237 // Waits for a jit attach to complete
238 virtual void WaitForDebuggerAttach() = 0;
240 // Completes the jit attach, unblocking all threads waiting for attach,
241 // regardless of whether or not the debugger actually attached
242 virtual void PostJitAttach() = 0;
244 virtual void SendUserBreakpointAndSynchronize(Thread * pThread) = 0;
246 virtual void SendLogMessage(int iLevel,
247 SString * pSwitchName,
248 SString * pMessage) = 0;
250 // send a custom notification from the target to the RS. This will become an ICorDebugThread and
251 // ICorDebugAppDomain on the RS.
252 virtual void SendCustomDebuggerNotification(Thread * pThread, DomainFile * pDomainFile, mdTypeDef classToken) = 0;
254 // Send an MDA notification. This ultimately translates to an ICorDebugMDA object on the Right-Side.
255 virtual void SendMDANotification(
256 Thread * pThread, // may be NULL. Lets us send on behalf of other threads.
258 SString * szDescription,
260 CorDebugMDAFlags flags,
264 virtual bool IsJMCMethod(Module* pModule, mdMethodDef tkMethod) = 0;
266 // Given a method, get's its EnC version number. 1 if the method is not EnCed.
267 // Note that MethodDescs are reused between versions so this will give us
268 // the most recent EnC number.
269 virtual int GetMethodEncNumber(MethodDesc * pMethod) = 0;
271 virtual void SendLogSwitchSetting (int iLevel,
273 __in_z LPCWSTR pLogSwitchName,
274 __in_z LPCWSTR pParentSwitchName) = 0;
276 virtual bool IsLoggingEnabled (void) = 0;
278 virtual bool GetILOffsetFromNative (MethodDesc *PFD,
281 DWORD *ilOffset) = 0;
283 virtual HRESULT GetILToNativeMapping(MethodDesc *pMD,
286 COR_DEBUG_IL_TO_NATIVE_MAP map[]) = 0;
288 virtual HRESULT GetILToNativeMappingIntoArrays(
292 UINT ** prguiILOffset,
293 UINT ** prguiNativeOffset) = 0;
295 virtual DWORD GetHelperThreadID(void ) = 0;
297 // Called whenever a new AppDomain is created, regardless of whether a debugger is attached.
298 // This will be called before any LoadAssembly calls for assemblies in this domain.
299 virtual HRESULT AddAppDomainToIPC (AppDomain *pAppDomain) = 0;
301 // Called whenever an AppDomain is unloaded, regardless of whether a Debugger is attached
302 // This will occur after any UnloadAssembly and UnloadModule callbacks for this domain (if any).
303 virtual HRESULT RemoveAppDomainFromIPC (AppDomain *pAppDomain) = 0;
305 virtual HRESULT UpdateAppDomainEntryInIPC (AppDomain *pAppDomain) = 0;
307 // Called when an assembly is being loaded into an AppDomain.
308 // This includes when a domain neutral assembly is loaded into a new AppDomain.
309 // This is called only when a debugger is attached, and will occur after the
310 // related AddAppDomainToIPCBlock call and before any LoadModule or
311 // LoadClass calls for this assembly.
312 virtual void LoadAssembly(DomainAssembly * pDomainAssembly) = 0; // the assembly being loaded
315 // Called for all assemblies in an AppDomain when the AppDomain is unloaded.
316 // This includes domain neutral assemblies that are also loaded into other domains.
317 // This is called only when a debugger is attached, and will occur after all UnloadClass
318 // and UnloadModule calls and before any RemoveAppDomainFromIPCBlock calls realted
319 // to this assembly. On CLR shutdown, we are not guarenteed to get UnloadAssembly calls for
320 // all outstanding loaded assemblies.
321 virtual void UnloadAssembly(DomainAssembly * pDomainAssembly) = 0;
323 virtual HRESULT SetILInstrumentedCodeMap(MethodDesc *fd,
325 ULONG32 cILMapEntries,
326 COR_IL_MAP rgILMapEntries[]) = 0;
328 virtual void EarlyHelperThreadDeath(void) = 0;
330 virtual void ShutdownBegun(void) = 0;
332 virtual void LockDebuggerForShutdown(void) = 0;
334 virtual void DisableDebugger(void) = 0;
336 virtual HRESULT NameChangeEvent(AppDomain *pAppDomain,
337 Thread *pThread) = 0;
339 // send an event to the RS indicating that there's a Ctrl-C or Ctrl-Break
340 virtual BOOL SendCtrlCToDebugger(DWORD dwCtrlType) = 0;
342 // Allows the debugger to keep an up to date list of special threads
343 virtual HRESULT UpdateSpecialThreadList(DWORD cThreadArrayLength,
344 DWORD *rgdwThreadIDArray) = 0;
346 // Updates the pointer for the debugger services
347 virtual void SetIDbgThreadControl(IDebuggerThreadControl *pIDbgThreadControl) = 0;
349 virtual DWORD GetRCThreadId(void) = 0;
351 virtual HRESULT GetVariablesFromOffset(MethodDesc *pMD,
352 UINT varNativeInfoCount,
353 ICorDebugInfo::NativeVarInfo *varNativeInfo,
361 virtual HRESULT SetVariablesAtOffset(MethodDesc *pMD,
362 UINT varNativeInfoCount,
363 ICorDebugInfo::NativeVarInfo *varNativeInfo,
370 virtual BOOL IsThreadContextInvalid(Thread *pThread) = 0;
372 // For Just-My-Code (aka Just-User-Code).
373 // The jit inserts probes that look like.
374 // if (*pAddr != 0) call g_pDebugInterface->OnMethodEnter()
376 // Invoked when we enter a user method.
377 // pIP is an ip within the method, right after the prolog.
378 virtual void OnMethodEnter(void * pIP) = 0;
380 // Given a method, the debugger provides the address of the flag.
381 // This allows the debugger to store the flag whereever it wants
382 // and with whatever granularity (per-module, per-class, per-function, etc).
383 virtual DWORD* GetJMCFlagAddr(Module * pModule) = 0;
385 // notification for SQL fiber debugging support
386 virtual void CreateConnection(CONNID dwConnectionId, __in_z WCHAR *wzName) = 0;
387 virtual void DestroyConnection(CONNID dwConnectionId) = 0;
388 virtual void ChangeConnection(CONNID dwConnectionId) = 0;
391 // This function is used to identify the helper thread.
393 virtual bool ThisIsHelperThread(void) = 0;
395 virtual HRESULT ReDaclEvents(PSECURITY_DESCRIPTOR securityDescriptor) = 0;
397 virtual BOOL ShouldAutoAttach() = 0;
398 virtual BOOL FallbackJITAttachPrompt() = 0;
399 virtual HRESULT SetFiberMode(bool isFiberMode) = 0;
401 #ifdef FEATURE_INTEROP_DEBUGGING
402 virtual LONG FirstChanceSuspendHijackWorker(PCONTEXT pContext, PEXCEPTION_RECORD pExceptionRecord) = 0;
405 #endif // #ifndef DACCESS_COMPILE
407 #ifdef DACCESS_COMPILE
408 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) = 0;
409 virtual void EnumMemoryRegionsIfFuncEvalFrame(CLRDataEnumMemoryFlags flags, Frame * pFrame) = 0;
413 #ifndef DACCESS_COMPILE
414 // Helper to make GCC compile. GCC can't handle putting a virtual call in a filter.
415 struct NotifyOfCHFFilterWrapperParam { void *pFrame; };
416 LONG NotifyOfCHFFilterWrapper(EXCEPTION_POINTERS *pExceptionInfo, PVOID pNotifyOfCHFFilterWrapperParam);
420 #endif // _dbgInterface_h_