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