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