aboutsummaryrefslogtreecommitdiff
path: root/include/lldb/Target/StopInfo.h
blob: d09900f7637d591f7b5f0f5fba99e81bb2f15de9 (plain) (blame)
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
//===-- StopInfo.h ----------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_StopInfo_h_
#define liblldb_StopInfo_h_

// C Includes
// C++ Includes
#include <string>

// Other libraries and framework includes
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Target/Process.h"
#include "lldb/Core/StructuredData.h"

namespace lldb_private {

class StopInfo
{
    friend class Process::ProcessEventData;
    friend class ThreadPlanBase;
    
public:
    //------------------------------------------------------------------
    // Constructors and Destructors
    //------------------------------------------------------------------
    StopInfo (Thread &thread, uint64_t value);

    virtual ~StopInfo()
    {
    }


    bool
    IsValid () const;

    void
    SetThread (const lldb::ThreadSP &thread_sp)
    {
        m_thread_wp = thread_sp;
    }

    lldb::ThreadSP
    GetThread() const
    {
        return m_thread_wp.lock();
    }

    // The value of the StopInfo depends on the StopReason.
    // StopReason                  Meaning
    // ----------------------------------------------
    // eStopReasonBreakpoint       BreakpointSiteID
    // eStopReasonSignal           Signal number
    // eStopReasonWatchpoint       WatchpointLocationID
    // eStopReasonPlanComplete     No significance
    
    uint64_t
    GetValue() const
    {
        return m_value;
    }

    virtual lldb::StopReason
    GetStopReason () const = 0;
        
    // ShouldStopSynchronous will get called before any thread plans are consulted, and if it says we should
    // resume the target, then we will just immediately resume.  This should not run any code in or resume the
    // target.
    
    virtual bool
    ShouldStopSynchronous (Event *event_ptr)
    {
        return true;
    }

    void
    OverrideShouldNotify (bool override_value)
    {
        m_override_should_notify = override_value ? eLazyBoolYes : eLazyBoolNo;
    }
    
    // If should stop returns false, check if we should notify of this event
    virtual bool
    ShouldNotify (Event *event_ptr)
    {
        if (m_override_should_notify == eLazyBoolCalculate)
            return DoShouldNotify (event_ptr);
        else
            return m_override_should_notify == eLazyBoolYes;
    }

    virtual void
    WillResume (lldb::StateType resume_state)
    {
        // By default, don't do anything
    }
    
    virtual const char *
    GetDescription ()
    {
        return m_description.c_str();
    }

    virtual void
    SetDescription (const char *desc_cstr)
    {
        if (desc_cstr && desc_cstr[0])
            m_description.assign (desc_cstr);
        else
            m_description.clear();
    }

    virtual bool
    IsValidForOperatingSystemThread (Thread &thread)
    {
        return true;
    }
    
    // Sometimes the thread plan logic will know that it wants a given stop to stop or not,
    // regardless of what the ordinary logic for that StopInfo would dictate.  The main example
    // of this is the ThreadPlanCallFunction, which for instance knows - based on how that particular
    // expression was executed - whether it wants all breakpoints to auto-continue or not.
    // Use OverrideShouldStop on the StopInfo to implement this.
    
    void
    OverrideShouldStop (bool override_value)
    {
        m_override_should_stop = override_value ? eLazyBoolYes : eLazyBoolNo;
    }
    
    bool
    GetOverrideShouldStop()
    {
        return m_override_should_stop != eLazyBoolCalculate;
    }
    
    bool
    GetOverriddenShouldStopValue ()
    {
        return m_override_should_stop == eLazyBoolYes;
    }
    
    StructuredData::ObjectSP
    GetExtendedInfo ()
    {
        return m_extended_info;
    }
    
    static lldb::StopInfoSP
    CreateStopReasonWithBreakpointSiteID (Thread &thread, lldb::break_id_t break_id);

    // This creates a StopInfo for the thread where the should_stop is already set, and won't be recalculated.
    static lldb::StopInfoSP
    CreateStopReasonWithBreakpointSiteID (Thread &thread, lldb::break_id_t break_id, bool should_stop);

    static lldb::StopInfoSP
    CreateStopReasonWithWatchpointID (Thread &thread, lldb::break_id_t watch_id);

    static lldb::StopInfoSP
    CreateStopReasonWithSignal (Thread &thread, int signo, const char *description = nullptr);

    static lldb::StopInfoSP
    CreateStopReasonToTrace (Thread &thread);

    static lldb::StopInfoSP
    CreateStopReasonWithPlan (lldb::ThreadPlanSP &plan,
                              lldb::ValueObjectSP return_valobj_sp,
                              lldb::ClangExpressionVariableSP expression_variable_sp);

    static lldb::StopInfoSP
    CreateStopReasonWithException (Thread &thread, const char *description);
    
    static lldb::StopInfoSP
    CreateStopReasonWithExec (Thread &thread);

    static lldb::ValueObjectSP
    GetReturnValueObject (lldb::StopInfoSP &stop_info_sp);

    static lldb::ClangExpressionVariableSP
    GetExpressionVariable (lldb::StopInfoSP &stop_info_sp);

protected:
    // Perform any action that is associated with this stop.  This is done as the
    // Event is removed from the event queue.  ProcessEventData::DoOnRemoval does the job.
 
    virtual void
    PerformAction (Event *event_ptr)
    {
    }

    virtual bool
    DoShouldNotify (Event *event_ptr)
    {
        return false;
    }
    
    // Stop the thread by default. Subclasses can override this to allow
    // the thread to continue if desired.  The ShouldStop method should not do anything
    // that might run code.  If you need to run code when deciding whether to stop
    // at this StopInfo, that must be done in the PerformAction.
    // The PerformAction will always get called before the ShouldStop.  This is done by the
    // ProcessEventData::DoOnRemoval, though the ThreadPlanBase needs to consult this later on.
    virtual bool
    ShouldStop (Event *event_ptr)
    {
        return true;
    }
    
    //------------------------------------------------------------------
    // Classes that inherit from StackID can see and modify these
    //------------------------------------------------------------------
    lldb::ThreadWP  m_thread_wp;   // The thread corresponding to the stop reason.
    uint32_t        m_stop_id;  // The process stop ID for which this stop info is valid
    uint32_t        m_resume_id; // This is the resume ID when we made this stop ID.
    uint64_t        m_value;    // A generic value that can be used for things pertaining to this stop info
    std::string     m_description; // A textual description describing this stop.
    LazyBool        m_override_should_notify;
    LazyBool        m_override_should_stop;
    
    StructuredData::ObjectSP m_extended_info; // The extended info for this stop info
    
    // This determines whether the target has run since this stop info.
    // N.B. running to evaluate a user expression does not count. 
    bool HasTargetRunSinceMe ();

    // MakeStopInfoValid is necessary to allow saved stop infos to resurrect themselves as valid.
    // It should only be used by Thread::RestoreThreadStateFromCheckpoint and to make sure the one-step
    // needed for before-the-fact watchpoints does not prevent us from stopping
    void
    MakeStopInfoValid ();
    
private:
    friend class Thread;
    
    DISALLOW_COPY_AND_ASSIGN (StopInfo);
};

} // namespace lldb_private

#endif  // liblldb_StopInfo_h_