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