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/Utility/ConstString.h"
18 #include "lldb/lldb-private.h"
19 #include "llvm/Support/JSON.h"
20 
21 namespace lldb_private {
22 
23 class UnixSignals {
24 public:
25   static lldb::UnixSignalsSP Create(const ArchSpec &arch);
26   static lldb::UnixSignalsSP CreateForHost();
27 
28   // Constructors and Destructors
29   UnixSignals();
30 
31   virtual ~UnixSignals();
32 
33   const char *GetSignalAsCString(int32_t signo) const;
34 
35   bool SignalIsValid(int32_t signo) const;
36 
37   int32_t GetSignalNumberFromName(const char *name) const;
38 
39   const char *GetSignalInfo(int32_t signo, bool &should_suppress,
40                             bool &should_stop, bool &should_notify) const;
41 
42   bool GetShouldSuppress(int32_t signo) const;
43 
44   bool SetShouldSuppress(int32_t signo, bool value);
45 
46   bool SetShouldSuppress(const char *signal_name, bool value);
47 
48   bool GetShouldStop(int32_t signo) const;
49 
50   bool SetShouldStop(int32_t signo, bool value);
51   bool SetShouldStop(const char *signal_name, bool value);
52 
53   bool GetShouldNotify(int32_t signo) const;
54 
55   bool SetShouldNotify(int32_t signo, bool value);
56 
57   bool SetShouldNotify(const char *signal_name, bool value);
58 
59   bool ResetSignal(int32_t signo, bool reset_stop = true,
60                    bool reset_notify = true, bool reset_suppress = true);
61 
62   // These provide an iterator through the signals available on this system.
63   // Call GetFirstSignalNumber to get the first entry, then iterate on
64   // GetNextSignalNumber till you get back LLDB_INVALID_SIGNAL_NUMBER.
65   int32_t GetFirstSignalNumber() const;
66 
67   int32_t GetNextSignalNumber(int32_t current_signal) const;
68 
69   int32_t GetNumSignals() const;
70 
71   int32_t GetSignalAtIndex(int32_t index) const;
72 
73   ConstString GetShortName(ConstString name) const;
74 
75   // We assume that the elements of this object are constant once it is
76   // constructed, since a process should never need to add or remove symbols as
77   // it runs.  So don't call these functions anywhere but the constructor of
78   // your subclass of UnixSignals or in your Process Plugin's GetUnixSignals
79   // method before you return the UnixSignal object.
80 
81   void AddSignal(int signo, const char *name, bool default_suppress,
82                  bool default_stop, bool default_notify,
83                  const char *description, const char *alias = nullptr);
84 
85   void RemoveSignal(int signo);
86 
87   /// Track how many times signals are hit as stop reasons.
88   void IncrementSignalHitCount(int signo);
89 
90   /// Get the hit count statistics for signals.
91   ///
92   /// Gettings statistics on the hit counts of signals can help explain why some
93   /// debug sessions are slow since each stop takes a few hundred ms and some
94   /// software use signals a lot and can cause slow debugging performance if
95   /// they are used too often. Even if a signal is not stopped at, it will auto
96   /// continue the process and a delay will happen.
97   llvm::json::Value GetHitCountStatistics() const;
98 
99   // Returns a current version of the data stored in this class. Version gets
100   // incremented each time Set... method is called.
101   uint64_t GetVersion() const;
102 
103   // Returns a vector of signals that meet criteria provided in arguments. Each
104   // should_[suppress|stop|notify] flag can be std::nullopt - no filtering by
105   // this flag true - only signals that have it set to true are returned false -
106   // only signals that have it set to true are returned
107   std::vector<int32_t> GetFilteredSignals(std::optional<bool> should_suppress,
108                                           std::optional<bool> should_stop,
109                                           std::optional<bool> should_notify);
110 
111 protected:
112   // Classes that inherit from UnixSignals can see and modify these
113 
114   struct Signal {
115     ConstString m_name;
116     ConstString m_alias;
117     std::string m_description;
118     uint32_t m_hit_count = 0;
119     bool m_suppress : 1, m_stop : 1, m_notify : 1;
120     bool m_default_suppress : 1, m_default_stop : 1, m_default_notify : 1;
121 
122     Signal(const char *name, bool default_suppress, bool default_stop,
123            bool default_notify, const char *description, const char *alias);
124 
125     ~Signal() = default;
126     void Reset(bool reset_stop, bool reset_notify, bool reset_suppress);
127   };
128 
129   virtual void Reset();
130 
131   typedef std::map<int32_t, Signal> collection;
132 
133   collection m_signals;
134 
135   // This version gets incremented every time something is changing in this
136   // class, including when we call AddSignal from the constructor. So after the
137   // object is constructed m_version is going to be > 0 if it has at least one
138   // signal registered in it.
139   uint64_t m_version = 0;
140 
141   // GDBRemote signals need to be copyable.
142   UnixSignals(const UnixSignals &rhs);
143 
144   const UnixSignals &operator=(const UnixSignals &rhs) = delete;
145 };
146 
147 } // Namespace lldb
148 #endif // LLDB_TARGET_UNIXSIGNALS_H
149