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: 35 ResumeActionList() = default; 36 ResumeActionList(lldb::StateType default_action,int signal)37 ResumeActionList(lldb::StateType default_action, int signal) { 38 SetDefaultThreadActionIfNeeded(default_action, signal); 39 } 40 ResumeActionList(const ResumeAction * actions,size_t num_actions)41 ResumeActionList(const ResumeAction *actions, size_t num_actions) { 42 if (actions && num_actions) { 43 m_actions.assign(actions, actions + num_actions); 44 m_signal_handled.assign(num_actions, false); 45 } 46 } 47 48 ~ResumeActionList() = default; 49 IsEmpty()50 bool IsEmpty() const { return m_actions.empty(); } 51 Append(const ResumeAction & action)52 void Append(const ResumeAction &action) { 53 m_actions.push_back(action); 54 m_signal_handled.push_back(false); 55 } 56 57 void AppendAction(lldb::tid_t tid, lldb::StateType state, int signal = 0) { 58 ResumeAction action = {tid, state, signal}; 59 Append(action); 60 } 61 AppendResumeAll()62 void AppendResumeAll() { 63 AppendAction(LLDB_INVALID_THREAD_ID, lldb::eStateRunning); 64 } 65 AppendSuspendAll()66 void AppendSuspendAll() { 67 AppendAction(LLDB_INVALID_THREAD_ID, lldb::eStateStopped); 68 } 69 AppendStepAll()70 void AppendStepAll() { 71 AppendAction(LLDB_INVALID_THREAD_ID, lldb::eStateStepping); 72 } 73 GetActionForThread(lldb::tid_t tid,bool default_ok)74 const ResumeAction *GetActionForThread(lldb::tid_t tid, 75 bool default_ok) const { 76 const size_t num_actions = m_actions.size(); 77 for (size_t i = 0; i < num_actions; ++i) { 78 if (m_actions[i].tid == tid) 79 return &m_actions[i]; 80 } 81 if (default_ok && tid != LLDB_INVALID_THREAD_ID) 82 return GetActionForThread(LLDB_INVALID_THREAD_ID, false); 83 return nullptr; 84 } 85 NumActionsWithState(lldb::StateType state)86 size_t NumActionsWithState(lldb::StateType state) const { 87 size_t count = 0; 88 const size_t num_actions = m_actions.size(); 89 for (size_t i = 0; i < num_actions; ++i) { 90 if (m_actions[i].state == state) 91 ++count; 92 } 93 return count; 94 } 95 SetDefaultThreadActionIfNeeded(lldb::StateType action,int signal)96 bool SetDefaultThreadActionIfNeeded(lldb::StateType action, int signal) { 97 if (GetActionForThread(LLDB_INVALID_THREAD_ID, true) == nullptr) { 98 // There isn't a default action so we do need to set it. 99 ResumeAction default_action = {LLDB_INVALID_THREAD_ID, action, signal}; 100 m_actions.push_back(default_action); 101 m_signal_handled.push_back(false); 102 return true; // Return true as we did add the default action 103 } 104 return false; 105 } 106 SetSignalHandledForThread(lldb::tid_t tid)107 void SetSignalHandledForThread(lldb::tid_t tid) const { 108 if (tid != LLDB_INVALID_THREAD_ID) { 109 const size_t num_actions = m_actions.size(); 110 for (size_t i = 0; i < num_actions; ++i) { 111 if (m_actions[i].tid == tid) 112 m_signal_handled[i] = true; 113 } 114 } 115 } 116 GetFirst()117 const ResumeAction *GetFirst() const { return m_actions.data(); } 118 GetSize()119 size_t GetSize() const { return m_actions.size(); } 120 Clear()121 void Clear() { 122 m_actions.clear(); 123 m_signal_handled.clear(); 124 } 125 126 protected: 127 std::vector<ResumeAction> m_actions; 128 mutable std::vector<bool> m_signal_handled; 129 }; 130 131 struct ThreadStopInfo { 132 lldb::StopReason reason; 133 uint32_t signo; 134 union { 135 // eStopReasonException 136 struct { 137 uint64_t type; 138 uint32_t data_count; 139 lldb::addr_t data[8]; 140 } exception; 141 142 // eStopReasonFork / eStopReasonVFork 143 struct { 144 lldb::pid_t child_pid; 145 lldb::tid_t child_tid; 146 } fork; 147 } details; 148 }; 149 } 150 151 #endif // LLDB_HOST_DEBUG_H 152