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 <vector>
14 
15 #include "lldb/lldb-private.h"
16 
17 namespace lldb_private {
18 
19 //------------------------------------------------------------------
20 // Tells a thread what it needs to do when the process is resumed.
21 //------------------------------------------------------------------
22 struct ResumeAction {
23   lldb::tid_t tid;       // The thread ID that this action applies to,
24                          // LLDB_INVALID_THREAD_ID for the default thread
25                          // action
26   lldb::StateType state; // Valid values are eStateStopped/eStateSuspended,
27                          // eStateRunning, and eStateStepping.
28   int signal; // When resuming this thread, resume it with this signal if this
29               // value is > 0
30 };
31 
32 //------------------------------------------------------------------
33 // A class that contains instructions for all threads for
34 // NativeProcessProtocol::Resume(). Each thread can either run, stay suspended,
35 // or step when the process is resumed. We optionally have the ability to also
36 // send a signal to the thread when the action is run or step.
37 //------------------------------------------------------------------
38 class ResumeActionList {
39 public:
ResumeActionList()40   ResumeActionList() : m_actions(), m_signal_handled() {}
41 
ResumeActionList(lldb::StateType default_action,int signal)42   ResumeActionList(lldb::StateType default_action, int signal)
43       : m_actions(), m_signal_handled() {
44     SetDefaultThreadActionIfNeeded(default_action, signal);
45   }
46 
ResumeActionList(const ResumeAction * actions,size_t num_actions)47   ResumeActionList(const ResumeAction *actions, size_t num_actions)
48       : m_actions(), m_signal_handled() {
49     if (actions && num_actions) {
50       m_actions.assign(actions, actions + num_actions);
51       m_signal_handled.assign(num_actions, false);
52     }
53   }
54 
55   ~ResumeActionList() = default;
56 
IsEmpty()57   bool IsEmpty() const { return m_actions.empty(); }
58 
Append(const ResumeAction & action)59   void Append(const ResumeAction &action) {
60     m_actions.push_back(action);
61     m_signal_handled.push_back(false);
62   }
63 
64   void AppendAction(lldb::tid_t tid, lldb::StateType state, int signal = 0) {
65     ResumeAction action = {tid, state, signal};
66     Append(action);
67   }
68 
AppendResumeAll()69   void AppendResumeAll() {
70     AppendAction(LLDB_INVALID_THREAD_ID, lldb::eStateRunning);
71   }
72 
AppendSuspendAll()73   void AppendSuspendAll() {
74     AppendAction(LLDB_INVALID_THREAD_ID, lldb::eStateStopped);
75   }
76 
AppendStepAll()77   void AppendStepAll() {
78     AppendAction(LLDB_INVALID_THREAD_ID, lldb::eStateStepping);
79   }
80 
GetActionForThread(lldb::tid_t tid,bool default_ok)81   const ResumeAction *GetActionForThread(lldb::tid_t tid,
82                                          bool default_ok) const {
83     const size_t num_actions = m_actions.size();
84     for (size_t i = 0; i < num_actions; ++i) {
85       if (m_actions[i].tid == tid)
86         return &m_actions[i];
87     }
88     if (default_ok && tid != LLDB_INVALID_THREAD_ID)
89       return GetActionForThread(LLDB_INVALID_THREAD_ID, false);
90     return nullptr;
91   }
92 
NumActionsWithState(lldb::StateType state)93   size_t NumActionsWithState(lldb::StateType state) const {
94     size_t count = 0;
95     const size_t num_actions = m_actions.size();
96     for (size_t i = 0; i < num_actions; ++i) {
97       if (m_actions[i].state == state)
98         ++count;
99     }
100     return count;
101   }
102 
SetDefaultThreadActionIfNeeded(lldb::StateType action,int signal)103   bool SetDefaultThreadActionIfNeeded(lldb::StateType action, int signal) {
104     if (GetActionForThread(LLDB_INVALID_THREAD_ID, true) == nullptr) {
105       // There isn't a default action so we do need to set it.
106       ResumeAction default_action = {LLDB_INVALID_THREAD_ID, action, signal};
107       m_actions.push_back(default_action);
108       m_signal_handled.push_back(false);
109       return true; // Return true as we did add the default action
110     }
111     return false;
112   }
113 
SetSignalHandledForThread(lldb::tid_t tid)114   void SetSignalHandledForThread(lldb::tid_t tid) const {
115     if (tid != LLDB_INVALID_THREAD_ID) {
116       const size_t num_actions = m_actions.size();
117       for (size_t i = 0; i < num_actions; ++i) {
118         if (m_actions[i].tid == tid)
119           m_signal_handled[i] = true;
120       }
121     }
122   }
123 
GetFirst()124   const ResumeAction *GetFirst() const { return m_actions.data(); }
125 
GetSize()126   size_t GetSize() const { return m_actions.size(); }
127 
Clear()128   void Clear() {
129     m_actions.clear();
130     m_signal_handled.clear();
131   }
132 
133 protected:
134   std::vector<ResumeAction> m_actions;
135   mutable std::vector<bool> m_signal_handled;
136 };
137 
138 struct ThreadStopInfo {
139   lldb::StopReason reason;
140   union {
141     // eStopReasonSignal
142     struct {
143       uint32_t signo;
144     } signal;
145 
146     // eStopReasonException
147     struct {
148       uint64_t type;
149       uint32_t data_count;
150       lldb::addr_t data[8];
151     } exception;
152   } details;
153 };
154 }
155 
156 #endif // liblldb_Debug_h_
157