1 | //===-- UnixSignals.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_TARGET_UNIXSIGNALS_H |
10 | #define LLDB_TARGET_UNIXSIGNALS_H |
11 | |
12 | #include <map> |
13 | #include <optional> |
14 | #include <string> |
15 | #include <vector> |
16 | |
17 | #include "lldb/lldb-private.h" |
18 | #include "llvm/Support/JSON.h" |
19 | |
20 | namespace lldb_private { |
21 | |
22 | class UnixSignals { |
23 | public: |
24 | static lldb::UnixSignalsSP Create(const ArchSpec &arch); |
25 | static lldb::UnixSignalsSP CreateForHost(); |
26 | |
27 | // Constructors and Destructors |
28 | UnixSignals(); |
29 | |
30 | virtual ~UnixSignals(); |
31 | |
32 | llvm::StringRef GetSignalAsStringRef(int32_t signo) const; |
33 | |
34 | std::string |
35 | GetSignalDescription(int32_t signo, |
36 | std::optional<int32_t> code = std::nullopt, |
37 | std::optional<lldb::addr_t> addr = std::nullopt, |
38 | std::optional<lldb::addr_t> lower = std::nullopt, |
39 | std::optional<lldb::addr_t> upper = std::nullopt) const; |
40 | |
41 | bool SignalIsValid(int32_t signo) const; |
42 | |
43 | int32_t GetSignalNumberFromName(const char *name) const; |
44 | |
45 | /// Gets the information for a particular signal |
46 | /// |
47 | /// GetSignalInfo takes a signal number and populates 3 out parameters |
48 | /// describing how lldb should react when a particular signal is received in |
49 | /// the inferior. |
50 | /// |
51 | /// \param[in] signo |
52 | /// The signal number to get information about. |
53 | /// \param[out] should_suppress |
54 | /// Should we suppress this signal? |
55 | /// \param[out] should_stop |
56 | /// Should we stop if this signal is received? |
57 | /// \param[out] should_notify |
58 | /// Should we notify the user if this signal is received? |
59 | /// |
60 | /// \return |
61 | /// Returns a boolean value. Returns true if the out parameters were |
62 | /// successfully populated, false otherwise. |
63 | bool GetSignalInfo(int32_t signo, bool &should_suppress, bool &should_stop, |
64 | bool &should_notify) const; |
65 | |
66 | bool GetShouldSuppress(int32_t signo) const; |
67 | |
68 | bool SetShouldSuppress(int32_t signo, bool value); |
69 | |
70 | bool SetShouldSuppress(const char *signal_name, bool value); |
71 | |
72 | bool GetShouldStop(int32_t signo) const; |
73 | |
74 | bool SetShouldStop(int32_t signo, bool value); |
75 | bool SetShouldStop(const char *signal_name, bool value); |
76 | |
77 | bool GetShouldNotify(int32_t signo) const; |
78 | |
79 | bool SetShouldNotify(int32_t signo, bool value); |
80 | |
81 | bool SetShouldNotify(const char *signal_name, bool value); |
82 | |
83 | bool ResetSignal(int32_t signo, bool reset_stop = true, |
84 | bool reset_notify = true, bool reset_suppress = true); |
85 | |
86 | // These provide an iterator through the signals available on this system. |
87 | // Call GetFirstSignalNumber to get the first entry, then iterate on |
88 | // GetNextSignalNumber till you get back LLDB_INVALID_SIGNAL_NUMBER. |
89 | int32_t GetFirstSignalNumber() const; |
90 | |
91 | int32_t GetNextSignalNumber(int32_t current_signal) const; |
92 | |
93 | int32_t GetNumSignals() const; |
94 | |
95 | int32_t GetSignalAtIndex(int32_t index) const; |
96 | |
97 | // We assume that the elements of this object are constant once it is |
98 | // constructed, since a process should never need to add or remove symbols as |
99 | // it runs. So don't call these functions anywhere but the constructor of |
100 | // your subclass of UnixSignals or in your Process Plugin's GetUnixSignals |
101 | // method before you return the UnixSignal object. |
102 | |
103 | void AddSignal(int signo, llvm::StringRef name, bool default_suppress, |
104 | bool default_stop, bool default_notify, |
105 | llvm::StringRef description, |
106 | llvm::StringRef alias = llvm::StringRef()); |
107 | |
108 | enum SignalCodePrintOption { None, Address, Bounds }; |
109 | |
110 | // Instead of calling this directly, use a ADD_SIGCODE macro to get compile |
111 | // time checks when on the native platform. |
112 | void AddSignalCode( |
113 | int signo, int code, const llvm::StringLiteral description, |
114 | SignalCodePrintOption print_option = SignalCodePrintOption::None); |
115 | |
116 | void RemoveSignal(int signo); |
117 | |
118 | /// Track how many times signals are hit as stop reasons. |
119 | void IncrementSignalHitCount(int signo); |
120 | |
121 | /// Get the hit count statistics for signals. |
122 | /// |
123 | /// Gettings statistics on the hit counts of signals can help explain why some |
124 | /// debug sessions are slow since each stop takes a few hundred ms and some |
125 | /// software use signals a lot and can cause slow debugging performance if |
126 | /// they are used too often. Even if a signal is not stopped at, it will auto |
127 | /// continue the process and a delay will happen. |
128 | llvm::json::Value GetHitCountStatistics() const; |
129 | |
130 | // Returns a current version of the data stored in this class. Version gets |
131 | // incremented each time Set... method is called. |
132 | uint64_t GetVersion() const; |
133 | |
134 | // Returns a vector of signals that meet criteria provided in arguments. Each |
135 | // should_[suppress|stop|notify] flag can be std::nullopt - no filtering by |
136 | // this flag true - only signals that have it set to true are returned false - |
137 | // only signals that have it set to true are returned |
138 | std::vector<int32_t> GetFilteredSignals(std::optional<bool> should_suppress, |
139 | std::optional<bool> should_stop, |
140 | std::optional<bool> should_notify); |
141 | |
142 | protected: |
143 | // Classes that inherit from UnixSignals can see and modify these |
144 | |
145 | struct SignalCode { |
146 | const llvm::StringLiteral m_description; |
147 | const SignalCodePrintOption m_print_option; |
148 | }; |
149 | |
150 | // The StringRefs in Signal are either backed by string literals or reside in |
151 | // persistent storage (e.g. a StringSet). |
152 | struct Signal { |
153 | llvm::StringRef m_name; |
154 | llvm::StringRef m_alias; |
155 | llvm::StringRef m_description; |
156 | std::map<int32_t, SignalCode> m_codes; |
157 | uint32_t m_hit_count = 0; |
158 | bool m_suppress : 1, m_stop : 1, m_notify : 1; |
159 | bool m_default_suppress : 1, m_default_stop : 1, m_default_notify : 1; |
160 | |
161 | Signal(llvm::StringRef name, bool default_suppress, bool default_stop, |
162 | bool default_notify, llvm::StringRef description, |
163 | llvm::StringRef alias); |
164 | |
165 | ~Signal() = default; |
166 | void Reset(bool reset_stop, bool reset_notify, bool reset_suppress); |
167 | }; |
168 | |
169 | llvm::StringRef GetShortName(llvm::StringRef name) const; |
170 | |
171 | virtual void Reset(); |
172 | |
173 | typedef std::map<int32_t, Signal> collection; |
174 | |
175 | collection m_signals; |
176 | |
177 | // This version gets incremented every time something is changing in this |
178 | // class, including when we call AddSignal from the constructor. So after the |
179 | // object is constructed m_version is going to be > 0 if it has at least one |
180 | // signal registered in it. |
181 | uint64_t m_version = 0; |
182 | |
183 | // GDBRemote signals need to be copyable. |
184 | UnixSignals(const UnixSignals &rhs); |
185 | |
186 | const UnixSignals &operator=(const UnixSignals &rhs) = delete; |
187 | }; |
188 | |
189 | } // Namespace lldb |
190 | #endif // LLDB_TARGET_UNIXSIGNALS_H |
191 | |