summaryrefslogtreecommitdiff
path: root/src/vm/debugdebugger.h
blob: 35758e185b6a1c5a6f163ed561e2bdd420ebbbbb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// 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>


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;
    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;

    BOOLARRAYREF rgiLastFrameFromForeignExceptionStackTrace;

    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;
        // TRUE if this element represents the last frame of the foreign
        // exception stack trace.
        BOOL			fIsLastFrameFromForeignStackTrace;

        // Initialization done under TSL.
        // This is used when first collecting the stack frame data.
        void InitPass1(
            DWORD dwNativeOffset,
            MethodDesc *pFunc,
            PCODE ip
            , BOOL			fIsLastFrameFromForeignStackTrace = FALSE
			);

        // 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;
        BOOL	fDoWeHaveAnyFramesFromForeignStackTrace;


        GetStackFramesData() :  skip(0), 
                                NumFramesRequested (0),
                                cElementsAllocated(0), 
                                cElements(0), 
                                pElements(NULL),
                                TargetThread((THREADBASEREF)(TADDR)NULL)
        { 
            LIMITED_METHOD_CONTRACT;
            fDoWeHaveAnyFramesFromForeignStackTrace = FALSE;

        }

        ~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);

};

#endif  // __DEBUG_DEBUGGER_h__