Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Host/Debug.h
Line
Count
Source (jump to first uncovered line)
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
0
  ResumeActionList() = default;
36
37
0
  ResumeActionList(lldb::StateType default_action, int signal) {
38
0
    SetDefaultThreadActionIfNeeded(default_action, signal);
39
0
  }
40
41
0
  ResumeActionList(const ResumeAction *actions, size_t num_actions) {
42
0
    if (actions && num_actions) {
43
0
      m_actions.assign(actions, actions + num_actions);
44
0
      m_signal_handled.assign(num_actions, false);
45
0
    }
46
0
  }
47
48
0
  ~ResumeActionList() = default;
49
50
0
  bool IsEmpty() const { return m_actions.empty(); }
51
52
0
  void Append(const ResumeAction &action) {
53
0
    m_actions.push_back(action);
54
0
    m_signal_handled.push_back(false);
55
0
  }
56
57
0
  void AppendAction(lldb::tid_t tid, lldb::StateType state, int signal = 0) {
58
0
    ResumeAction action = {tid, state, signal};
59
0
    Append(action);
60
0
  }
61
62
0
  void AppendResumeAll() {
63
0
    AppendAction(LLDB_INVALID_THREAD_ID, lldb::eStateRunning);
64
0
  }
65
66
0
  void AppendSuspendAll() {
67
0
    AppendAction(LLDB_INVALID_THREAD_ID, lldb::eStateStopped);
68
0
  }
69
70
0
  void AppendStepAll() {
71
0
    AppendAction(LLDB_INVALID_THREAD_ID, lldb::eStateStepping);
72
0
  }
73
74
  const ResumeAction *GetActionForThread(lldb::tid_t tid,
75
0
                                         bool default_ok) const {
76
0
    const size_t num_actions = m_actions.size();
77
0
    for (size_t i = 0; i < num_actions; ++i) {
78
0
      if (m_actions[i].tid == tid)
79
0
        return &m_actions[i];
80
0
    }
81
0
    if (default_ok && tid != LLDB_INVALID_THREAD_ID)
82
0
      return GetActionForThread(LLDB_INVALID_THREAD_ID, false);
83
0
    return nullptr;
84
0
  }
85
86
0
  size_t NumActionsWithState(lldb::StateType state) const {
87
0
    size_t count = 0;
88
0
    const size_t num_actions = m_actions.size();
89
0
    for (size_t i = 0; i < num_actions; ++i) {
90
0
      if (m_actions[i].state == state)
91
0
        ++count;
92
0
    }
93
0
    return count;
94
0
  }
95
96
0
  bool SetDefaultThreadActionIfNeeded(lldb::StateType action, int signal) {
97
0
    if (GetActionForThread(LLDB_INVALID_THREAD_ID, true) == nullptr) {
98
      // There isn't a default action so we do need to set it.
99
0
      ResumeAction default_action = {LLDB_INVALID_THREAD_ID, action, signal};
100
0
      m_actions.push_back(default_action);
101
0
      m_signal_handled.push_back(false);
102
0
      return true; // Return true as we did add the default action
103
0
    }
104
0
    return false;
105
0
  }
106
107
0
  void SetSignalHandledForThread(lldb::tid_t tid) const {
108
0
    if (tid != LLDB_INVALID_THREAD_ID) {
109
0
      const size_t num_actions = m_actions.size();
110
0
      for (size_t i = 0; i < num_actions; ++i) {
111
0
        if (m_actions[i].tid == tid)
112
0
          m_signal_handled[i] = true;
113
0
      }
114
0
    }
115
0
  }
116
117
0
  const ResumeAction *GetFirst() const { return m_actions.data(); }
118
119
0
  size_t GetSize() const { return m_actions.size(); }
120
121
0
  void Clear() {
122
0
    m_actions.clear();
123
0
    m_signal_handled.clear();
124
0
  }
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