Debug.h revision 263367
1//===-- Debug.h -------------------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef liblldb_Debug_h_
11#define liblldb_Debug_h_
12
13#include "lldb/lldb-private.h"
14#include "lldb/Core/Error.h"
15#include "lldb/Core/StreamString.h"
16#include "lldb/Host/Mutex.h"
17#include <vector>
18
19namespace lldb_private {
20
21    //------------------------------------------------------------------
22    // Tells a thread what it needs to do when the process is resumed.
23    //------------------------------------------------------------------
24    struct ResumeAction
25    {
26        lldb::tid_t tid;        // The thread ID that this action applies to, LLDB_INVALID_THREAD_ID for the default thread action
27        lldb::StateType state;  // Valid values are eStateStopped/eStateSuspended, eStateRunning, and eStateStepping.
28        int signal;             // When resuming this thread, resume it with this signal if this value is > 0
29    };
30
31    //------------------------------------------------------------------
32    // A class that contains instructions for all threads for
33    // NativeProcessProtocol::Resume(). Each thread can either run, stay
34    // suspended, or step when the process is resumed. We optionally
35    // have the ability to also send a signal to the thread when the
36    // action is run or step.
37    //------------------------------------------------------------------
38    class ResumeActionList
39    {
40    public:
41        ResumeActionList () :
42            m_actions (),
43            m_signal_handled ()
44        {
45        }
46
47        ResumeActionList (lldb::StateType default_action, int signal) :
48            m_actions(),
49            m_signal_handled ()
50        {
51            SetDefaultThreadActionIfNeeded (default_action, signal);
52        }
53
54
55        ResumeActionList (const ResumeAction *actions, size_t num_actions) :
56            m_actions (),
57            m_signal_handled ()
58        {
59            if (actions && num_actions)
60            {
61                m_actions.assign (actions, actions + num_actions);
62                m_signal_handled.assign (num_actions, false);
63            }
64        }
65
66        ~ResumeActionList()
67        {
68        }
69
70        bool
71        IsEmpty() const
72        {
73            return m_actions.empty();
74        }
75
76        void
77        Append (const ResumeAction &action)
78        {
79            m_actions.push_back (action);
80            m_signal_handled.push_back (false);
81        }
82
83        void
84        AppendAction (lldb::tid_t tid,
85                      lldb::StateType state,
86                      int signal = 0)
87        {
88            ResumeAction action = { tid, state, signal };
89            Append (action);
90        }
91
92        void
93        AppendResumeAll ()
94        {
95            AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateRunning);
96        }
97
98        void
99        AppendSuspendAll ()
100        {
101            AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateStopped);
102        }
103
104        void
105        AppendStepAll ()
106        {
107            AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateStepping);
108        }
109
110        const ResumeAction *
111        GetActionForThread (lldb::tid_t tid, bool default_ok) const
112        {
113            const size_t num_actions = m_actions.size();
114            for (size_t i=0; i<num_actions; ++i)
115            {
116                if (m_actions[i].tid == tid)
117                    return &m_actions[i];
118            }
119            if (default_ok && tid != LLDB_INVALID_THREAD_ID)
120                return GetActionForThread (LLDB_INVALID_THREAD_ID, false);
121            return NULL;
122        }
123
124        size_t
125        NumActionsWithState (lldb::StateType state) const
126        {
127            size_t count = 0;
128            const size_t num_actions = m_actions.size();
129            for (size_t i=0; i<num_actions; ++i)
130            {
131                if (m_actions[i].state == state)
132                    ++count;
133            }
134            return count;
135        }
136
137        bool
138        SetDefaultThreadActionIfNeeded (lldb::StateType action, int signal)
139        {
140            if (GetActionForThread (LLDB_INVALID_THREAD_ID, true) == NULL)
141            {
142                // There isn't a default action so we do need to set it.
143                ResumeAction default_action = {LLDB_INVALID_THREAD_ID, action, signal };
144                m_actions.push_back (default_action);
145                m_signal_handled.push_back (false);
146                return true; // Return true as we did add the default action
147            }
148            return false;
149        }
150
151        void
152        SetSignalHandledForThread (lldb::tid_t tid) const
153        {
154            if (tid != LLDB_INVALID_THREAD_ID)
155            {
156                const size_t num_actions = m_actions.size();
157                for (size_t i=0; i<num_actions; ++i)
158                {
159                    if (m_actions[i].tid == tid)
160                        m_signal_handled[i] = true;
161                }
162            }
163        }
164
165        const ResumeAction *
166        GetFirst() const
167        {
168            return m_actions.data();
169        }
170
171        size_t
172        GetSize () const
173        {
174            return m_actions.size();
175        }
176
177        void
178        Clear()
179        {
180            m_actions.clear();
181            m_signal_handled.clear();
182        }
183
184    protected:
185        std::vector<ResumeAction> m_actions;
186        mutable std::vector<bool> m_signal_handled;
187    };
188
189    struct ThreadStopInfo
190    {
191        lldb::StopReason reason;
192        union
193        {
194            // eStopTypeSignal
195            struct
196            {
197                uint32_t signo;
198            } signal;
199
200            // eStopTypeException
201            struct
202            {
203                uint64_t type;
204                uint32_t data_count;
205                lldb::addr_t data[2];
206            } exception;
207        } details;
208    };
209
210    //------------------------------------------------------------------
211    // NativeThreadProtocol
212    //------------------------------------------------------------------
213    class NativeThreadProtocol {
214
215    public:
216        NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid) :
217            m_process (process),
218            m_tid (tid)
219        {
220        }
221
222        virtual ~NativeThreadProtocol()
223        {
224        }
225        virtual const char *GetName() = 0;
226        virtual lldb::StateType GetState () = 0;
227        virtual Error ReadRegister (uint32_t reg, RegisterValue &reg_value) = 0;
228        virtual Error WriteRegister (uint32_t reg, const RegisterValue &reg_value) = 0;
229        virtual Error SaveAllRegisters (lldb::DataBufferSP &data_sp) = 0;
230        virtual Error RestoreAllRegisters (lldb::DataBufferSP &data_sp) = 0;
231        virtual bool GetStopReason (ThreadStopInfo &stop_info) = 0;
232
233        lldb::tid_t
234        GetID() const
235        {
236            return m_tid;
237        }
238    protected:
239        NativeProcessProtocol *m_process;
240        lldb::tid_t m_tid;
241    };
242
243
244    //------------------------------------------------------------------
245    // NativeProcessProtocol
246    //------------------------------------------------------------------
247    class NativeProcessProtocol {
248    public:
249
250        static NativeProcessProtocol *
251        CreateInstance (lldb::pid_t pid);
252
253        // lldb_private::Host calls should be used to launch a process for debugging, and
254        // then the process should be attached to. When attaching to a process
255        // lldb_private::Host calls should be used to locate the process to attach to,
256        // and then this function should be called.
257        NativeProcessProtocol (lldb::pid_t pid) :
258            m_pid (pid),
259            m_threads(),
260            m_threads_mutex (Mutex::eMutexTypeRecursive),
261            m_state (lldb::eStateInvalid),
262            m_exit_status(0),
263            m_exit_description()
264        {
265        }
266
267    public:
268        virtual ~NativeProcessProtocol ()
269        {
270        }
271
272        virtual Error Resume (const ResumeActionList &resume_actions) = 0;
273        virtual Error Halt () = 0;
274        virtual Error Detach () = 0;
275        virtual Error Signal (int signo) = 0;
276        virtual Error Kill () = 0;
277
278        virtual Error ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) = 0;
279        virtual Error WriteMemory (lldb::addr_t addr, const void *buf, lldb::addr_t size, lldb::addr_t &bytes_written) = 0;
280        virtual Error AllocateMemory (lldb::addr_t size, uint32_t permissions, lldb::addr_t &addr) = 0;
281        virtual Error DeallocateMemory (lldb::addr_t addr) = 0;
282
283        virtual lldb::addr_t GetSharedLibraryInfoAddress () = 0;
284
285        virtual bool IsAlive () = 0;
286        virtual size_t UpdateThreads () = 0;
287        virtual bool GetArchitecture (ArchSpec &arch) = 0;
288
289        //----------------------------------------------------------------------
290        // Breakpoint functions
291        //----------------------------------------------------------------------
292        virtual Error SetBreakpoint (lldb::addr_t addr, size_t size, bool hardware) = 0;
293        virtual Error RemoveBreakpoint (lldb::addr_t addr, size_t size) = 0;
294
295        //----------------------------------------------------------------------
296        // Watchpoint functions
297        //----------------------------------------------------------------------
298        virtual uint32_t GetMaxWatchpoints () = 0;
299        virtual Error SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) = 0;
300        virtual Error RemoveWatchpoint (lldb::addr_t addr) = 0;
301
302
303        //----------------------------------------------------------------------
304        // Accessors
305        //----------------------------------------------------------------------
306        lldb::pid_t
307        GetID() const
308        {
309            return m_pid;
310        }
311
312        lldb::StateType
313        GetState () const
314        {
315            return m_state;
316        }
317
318        bool
319        IsRunning () const
320        {
321            return m_state == lldb::eStateRunning || IsStepping();
322        }
323
324        bool
325        IsStepping () const
326        {
327            return m_state == lldb::eStateStepping;
328        }
329
330        bool
331        CanResume () const
332        {
333            return m_state == lldb::eStateStopped;
334        }
335
336
337        void
338        SetState (lldb::StateType state)
339        {
340            m_state = state;
341        }
342
343        //----------------------------------------------------------------------
344        // Exit Status
345        //----------------------------------------------------------------------
346        virtual bool
347        GetExitStatus (int *status)
348        {
349            if (m_state == lldb::eStateExited)
350            {
351                *status = m_exit_status;
352                return true;
353            }
354            *status = 0;
355            return false;
356        }
357        virtual bool
358        SetExitStatus (int status, const char *exit_description)
359        {
360            // Exit status already set
361            if (m_state == lldb::eStateExited)
362                return false;
363            m_state = lldb::eStateExited;
364            m_exit_status = status;
365            if (exit_description && exit_description[0])
366                m_exit_description = exit_description;
367            else
368                m_exit_description.clear();
369            return true;
370        }
371
372        //----------------------------------------------------------------------
373        // Access to threads
374        //----------------------------------------------------------------------
375        lldb::NativeThreadProtocolSP
376        GetThreadAtIndex (uint32_t idx)
377        {
378            Mutex::Locker locker(m_threads_mutex);
379            if (idx < m_threads.size())
380                return m_threads[idx];
381            return lldb::NativeThreadProtocolSP();
382        }
383
384        lldb::NativeThreadProtocolSP
385        GetThreadByID (lldb::tid_t tid)
386        {
387            Mutex::Locker locker(m_threads_mutex);
388            for (auto thread_sp : m_threads)
389            {
390                if (thread_sp->GetID() == tid)
391                    return thread_sp;
392            }
393            return lldb::NativeThreadProtocolSP();
394        }
395
396    protected:
397        lldb::pid_t m_pid;
398        std::vector<lldb::NativeThreadProtocolSP> m_threads;
399        mutable Mutex m_threads_mutex;
400        lldb::StateType m_state;
401        int m_exit_status;
402        std::string m_exit_description;
403    };
404
405}
406#endif // #ifndef liblldb_Debug_h_
407