diff options
Diffstat (limited to 'src/vm/debugdebugger.h')
-rw-r--r-- | src/vm/debugdebugger.h | 393 |
1 files changed, 393 insertions, 0 deletions
diff --git a/src/vm/debugdebugger.h b/src/vm/debugdebugger.h new file mode 100644 index 0000000000..9cf5c3c0f0 --- /dev/null +++ b/src/vm/debugdebugger.h @@ -0,0 +1,393 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** Header: DebugDebugger.h +** +** Purpose: Native methods on System.Debug.Debugger +** +** + +===========================================================*/ + +#ifndef __DEBUG_DEBUGGER_h__ +#define __DEBUG_DEBUGGER_h__ +#include <object.h> + + +// ! WARNING ! +// The following constants mirror the constants +// declared in the class LoggingLevelEnum in the +// System.Diagnostic package. Any changes here will also +// need to be made there. +#define TraceLevel0 0 +#define TraceLevel1 1 +#define TraceLevel2 2 +#define TraceLevel3 3 +#define TraceLevel4 4 +#define StatusLevel0 20 +#define StatusLevel1 21 +#define StatusLevel2 22 +#define StatusLevel3 23 +#define StatusLevel4 24 +#define WarningLevel 40 +#define ErrorLevel 50 +#define PanicLevel 100 + +// ! WARNING ! +// The following constants mirror the constants +// declared in the class AssertLevelEnum in the +// System.Diagnostic package. Any changes here will also +// need to be made there. +#define FailDebug 0 +#define FailIgnore 1 +#define FailTerminate 2 +#define FailContinueFilter 3 + +#define MAX_LOG_SWITCH_NAME_LEN 256 + +class DebugDebugger +{ +public: + static FCDECL0(void, Break); + static FCDECL0(FC_BOOL_RET, Launch); + static FCDECL0(FC_BOOL_RET, IsDebuggerAttached); + static FCDECL3(void, Log, INT32 Level, StringObject* strModule, StringObject* strMessage); + + // receives a custom notification object from the target and sends it to the RS via + // code:Debugger::SendCustomDebuggerNotification + static FCDECL1(void, CustomNotification, Object * dataUNSAFE); + + static FCDECL0(FC_BOOL_RET, IsLogging); + +protected: + static BOOL IsLoggingHelper(); +}; + + + + +class StackFrameHelper : public Object +{ + // READ ME: + // Modifying the order or fields of this object may require other changes to the + // classlib defintion of the StackFrameHelper class. +public: + THREADBASEREF targetThread; + I4ARRAYREF rgiOffset; + I4ARRAYREF rgiILOffset; + BASEARRAYREF rgMethodBase; + PTRARRAYREF dynamicMethods; + BASEARRAYREF rgMethodHandle; + PTRARRAYREF rgAssemblyPath; + BASEARRAYREF rgLoadedPeAddress; + I4ARRAYREF rgiLoadedPeSize; + BASEARRAYREF rgInMemoryPdbAddress; + I4ARRAYREF rgiInMemoryPdbSize; + // if rgiMethodToken[i] == 0, then don't attempt to get the portable PDB source/info + I4ARRAYREF rgiMethodToken; + PTRARRAYREF rgFilename; + I4ARRAYREF rgiLineNumber; + I4ARRAYREF rgiColumnNumber; + +#if defined(FEATURE_EXCEPTIONDISPATCHINFO) + BOOLARRAYREF rgiLastFrameFromForeignExceptionStackTrace; +#endif // defined(FEATURE_EXCEPTIONDISPATCHINFO) + + OBJECTREF getSourceLineInfo; + int iFrameCount; + +protected: + StackFrameHelper() {} + ~StackFrameHelper() {} + +public: + void SetFrameCount (int iCount) + { + iFrameCount = iCount; + } + + int GetFrameCount (void) + { + return iFrameCount; + } + +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF <StackFrameHelper> STACKFRAMEHELPERREF; +#else +typedef StackFrameHelper* STACKFRAMEHELPERREF; +#endif + + +class DebugStackTrace +{ +public: + +#ifndef DACCESS_COMPILE +// the DAC directly uses the GetStackFramesData and DebugStackTraceElement types +private: +#endif // DACCESS_COMPILE + struct DebugStackTraceElement { + DWORD dwOffset; // native offset + DWORD dwILOffset; + MethodDesc *pFunc; + PCODE ip; +#if defined(FEATURE_EXCEPTIONDISPATCHINFO) + // TRUE if this element represents the last frame of the foreign + // exception stack trace. + BOOL fIsLastFrameFromForeignStackTrace; +#endif // defined(FEATURE_EXCEPTIONDISPATCHINFO) + + // Initialization done under TSL. + // This is used when first collecting the stack frame data. + void InitPass1( + DWORD dwNativeOffset, + MethodDesc *pFunc, + PCODE ip +#if defined(FEATURE_EXCEPTIONDISPATCHINFO) + , BOOL fIsLastFrameFromForeignStackTrace = FALSE +#endif // defined(FEATURE_EXCEPTIONDISPATCHINFO) + ); + + // Initialization done outside the TSL. + // This will init the dwILOffset field (and potentially anything else + // that can't be done under the TSL). + void InitPass2(); + }; + +public: + + struct GetStackFramesData { + + // Used for the integer-skip version + INT32 skip; + INT32 NumFramesRequested; + INT32 cElementsAllocated; + INT32 cElements; + DebugStackTraceElement* pElements; + THREADBASEREF TargetThread; + AppDomain *pDomain; +#if defined(FEATURE_EXCEPTIONDISPATCHINFO) + BOOL fDoWeHaveAnyFramesFromForeignStackTrace; +#endif // defined(FEATURE_EXCEPTIONDISPATCHINFO) + + + GetStackFramesData() : skip(0), + NumFramesRequested (0), + cElementsAllocated(0), + cElements(0), + pElements(NULL), + TargetThread((THREADBASEREF)(TADDR)NULL) + { + LIMITED_METHOD_CONTRACT; +#if defined(FEATURE_EXCEPTIONDISPATCHINFO) + fDoWeHaveAnyFramesFromForeignStackTrace = FALSE; +#endif // defined(FEATURE_EXCEPTIONDISPATCHINFO) + + } + + ~GetStackFramesData() + { + delete [] pElements; + } + }; + + static FCDECL4(void, + GetStackFramesInternal, + StackFrameHelper* pStackFrameHelper, + INT32 iSkip, + CLR_BOOL fNeedFileInfo, + Object* pException + ); + + static void GetStackFramesFromException(OBJECTREF * e, GetStackFramesData *pData, PTRARRAYREF * pDynamicMethodArray = NULL); + +#ifndef DACCESS_COMPILE +// the DAC directly calls GetStackFramesFromException +private: +#endif + + static void GetStackFramesHelper(Frame *pStartFrame, void* pStopStack, GetStackFramesData *pData); + + static void GetStackFrames(Frame *pStartFrame, void* pStopStack, GetStackFramesData *pData); + + static StackWalkAction GetStackFramesCallback(CrawlFrame* pCf, VOID* data); + +}; + +class DebuggerAssert +{ +private: + +public: + + static FCDECL4(INT32, + ShowDefaultAssertDialog, + StringObject* strConditionUNSAFE, + StringObject* strMessageUNSAFE, + StringObject* strStackTraceUNSAFE, + StringObject* strWindowTitleUNSAFE + ); + +}; + + +// The following code is taken from object.h and modified to suit +// LogSwitchBaseObject +// +class LogSwitchObject : public Object +{ + protected: + // README: + // Modifying the order or fields of this object may require other changes to the + // classlib class defintion of the LogSwitch object. + + STRINGREF m_strName; + STRINGREF strDescription; + OBJECTREF m_ParentSwitch; + INT32 m_iLevel; + INT32 m_iOldLevel; + + protected: + LogSwitchObject() {} + ~LogSwitchObject() {} + + public: + // check for classes that wrap Ole classes + + void SetLevel(INT32 iLevel) + { + m_iLevel = iLevel; + } + + INT32 GetLevel(void) + { + return m_iLevel; + } + + OBJECTREF GetParent (void) + { + return m_ParentSwitch; + } + + STRINGREF GetName (void) + { + return m_strName; + } +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF <LogSwitchObject> LOGSWITCHREF; +#else +typedef LogSwitchObject* LOGSWITCHREF; +#endif + + +#define MAX_KEY_LENGTH 64 +#define MAX_HASH_BUCKETS 20 + +class HashElement +{ +private: + + OBJECTHANDLE m_pData; + SString m_strKey; + HashElement *m_pNext; + +public: + + HashElement () + { + LIMITED_METHOD_CONTRACT; + m_pData = NULL; + m_pNext = NULL; + } + + ~HashElement() + { + if (m_pNext!= NULL) + { + delete m_pNext; + } + + m_pNext=NULL; + + }// ~HashElement + + void SetData (OBJECTHANDLE pData, const WCHAR *pKey) + { + m_pData = pData; + m_strKey.Set(pKey); + } + + OBJECTHANDLE GetData (void) + { + return m_pData; + } + + const WCHAR *GetKey (void) + { + return m_strKey.GetUnicode(); + } + + void SetNext (HashElement *pNext) + { + m_pNext = pNext; + } + + HashElement *GetNext (void) + { + return m_pNext; + } + +}; + +class LogHashTable +{ +private: + + HashElement *m_Buckets [MAX_HASH_BUCKETS]; + +public: + // static global object, no constructors/destructors, assumes zero initialized memory + + HRESULT AddEntryToHashTable (const WCHAR *pKey, OBJECTHANDLE pData); + + OBJECTHANDLE GetEntryFromHashTable (const WCHAR *pKey); + +}; + +extern LogHashTable g_sLogHashTable; + + +class Log +{ +private: + +public: + static FCDECL1(void, AddLogSwitch, LogSwitchObject * m_LogSwitch); + + static FCDECL3(void, + ModifyLogSwitch, + INT32 Level, + StringObject* strLogSwitchNameUNSAFE, + StringObject* strParentNameUNSAFE + ); + + // The following method is called when the level of a log switch is modified + // from the debugger. It is not an ecall. + static void DebuggerModifyingLogSwitch (int iNewLevel, const WCHAR *pLogSwitchName); + +}; + +// +// Returns a textual representation of the current stack trace. The format of the stack +// trace is the same as returned by StackTrace.ToString. +// +void GetManagedStackTraceString(BOOL fNeedFileInfo, SString &result); + +#endif // __DEBUG_DEBUGGER_h__ |