Debug.h revision 344779
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
17namespace lldb_private {
18
19//------------------------------------------------------------------
20// Tells a thread what it needs to do when the process is resumed.
21//------------------------------------------------------------------
22struct 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//------------------------------------------------------------------
38class ResumeActionList {
39public:
40  ResumeActionList() : m_actions(), m_signal_handled() {}
41
42  ResumeActionList(lldb::StateType default_action, int signal)
43      : m_actions(), m_signal_handled() {
44    SetDefaultThreadActionIfNeeded(default_action, signal);
45  }
46
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
57  bool IsEmpty() const { return m_actions.empty(); }
58
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
69  void AppendResumeAll() {
70    AppendAction(LLDB_INVALID_THREAD_ID, lldb::eStateRunning);
71  }
72
73  void AppendSuspendAll() {
74    AppendAction(LLDB_INVALID_THREAD_ID, lldb::eStateStopped);
75  }
76
77  void AppendStepAll() {
78    AppendAction(LLDB_INVALID_THREAD_ID, lldb::eStateStepping);
79  }
80
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
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
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
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
124  const ResumeAction *GetFirst() const { return m_actions.data(); }
125
126  size_t GetSize() const { return m_actions.size(); }
127
128  void Clear() {
129    m_actions.clear();
130    m_signal_handled.clear();
131  }
132
133protected:
134  std::vector<ResumeAction> m_actions;
135  mutable std::vector<bool> m_signal_handled;
136};
137
138struct 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