1130812Smarcel//===-- UnixSignals.h -------------------------------------------*- C++ -*-===// 2130812Smarcel// 3130812Smarcel// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4130812Smarcel// See https://llvm.org/LICENSE.txt for license information. 5130812Smarcel// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6130812Smarcel// 7130812Smarcel//===----------------------------------------------------------------------===// 8130812Smarcel 9130812Smarcel#ifndef LLDB_TARGET_UNIXSIGNALS_H 10130812Smarcel#define LLDB_TARGET_UNIXSIGNALS_H 11130812Smarcel 12130812Smarcel#include <map> 13130812Smarcel#include <optional> 14130812Smarcel#include <string> 15130812Smarcel#include <vector> 16130812Smarcel 17130812Smarcel#include "lldb/lldb-private.h" 18130812Smarcel#include "llvm/Support/JSON.h" 19130812Smarcel 20130812Smarcelnamespace lldb_private { 21130812Smarcel 22130812Smarcelclass UnixSignals { 23130812Smarcelpublic: 24130812Smarcel static lldb::UnixSignalsSP Create(const ArchSpec &arch); 25130812Smarcel static lldb::UnixSignalsSP CreateForHost(); 26130812Smarcel 27130812Smarcel // Constructors and Destructors 28130812Smarcel UnixSignals(); 29130812Smarcel 30130812Smarcel virtual ~UnixSignals(); 31130812Smarcel 32130812Smarcel llvm::StringRef GetSignalAsStringRef(int32_t signo) const; 33130812Smarcel 34130812Smarcel std::string 35130812Smarcel GetSignalDescription(int32_t signo, 36130812Smarcel std::optional<int32_t> code = std::nullopt, 37130812Smarcel std::optional<lldb::addr_t> addr = std::nullopt, 38130812Smarcel std::optional<lldb::addr_t> lower = std::nullopt, 39130812Smarcel std::optional<lldb::addr_t> upper = std::nullopt) const; 40130812Smarcel 41130812Smarcel bool SignalIsValid(int32_t signo) const; 42130812Smarcel 43130812Smarcel int32_t GetSignalNumberFromName(const char *name) const; 44130812Smarcel 45130812Smarcel /// Gets the information for a particular signal 46130812Smarcel /// 47130812Smarcel /// GetSignalInfo takes a signal number and populates 3 out parameters 48130812Smarcel /// describing how lldb should react when a particular signal is received in 49130812Smarcel /// the inferior. 50130812Smarcel /// 51130812Smarcel /// \param[in] signo 52130812Smarcel /// The signal number to get information about. 53130812Smarcel /// \param[out] should_suppress 54130812Smarcel /// Should we suppress this signal? 55130812Smarcel /// \param[out] should_stop 56130812Smarcel /// Should we stop if this signal is received? 57130812Smarcel /// \param[out] should_notify 58130812Smarcel /// Should we notify the user if this signal is received? 59130812Smarcel /// 60130812Smarcel /// \return 61130812Smarcel /// Returns a boolean value. Returns true if the out parameters were 62130812Smarcel /// successfully populated, false otherwise. 63130812Smarcel bool GetSignalInfo(int32_t signo, bool &should_suppress, bool &should_stop, 64130812Smarcel bool &should_notify) const; 65130812Smarcel 66130812Smarcel bool GetShouldSuppress(int32_t signo) const; 67130812Smarcel 68130812Smarcel bool SetShouldSuppress(int32_t signo, bool value); 69130812Smarcel 70130812Smarcel bool SetShouldSuppress(const char *signal_name, bool value); 71130812Smarcel 72130812Smarcel bool GetShouldStop(int32_t signo) const; 73130812Smarcel 74130812Smarcel bool SetShouldStop(int32_t signo, bool value); 75130812Smarcel bool SetShouldStop(const char *signal_name, bool value); 76130812Smarcel 77130812Smarcel bool GetShouldNotify(int32_t signo) const; 78130812Smarcel 79130812Smarcel bool SetShouldNotify(int32_t signo, bool value); 80130812Smarcel 81130812Smarcel bool SetShouldNotify(const char *signal_name, bool value); 82130812Smarcel 83130812Smarcel bool ResetSignal(int32_t signo, bool reset_stop = true, 84130812Smarcel bool reset_notify = true, bool reset_suppress = true); 85130812Smarcel 86130812Smarcel // These provide an iterator through the signals available on this system. 87130812Smarcel // Call GetFirstSignalNumber to get the first entry, then iterate on 88130812Smarcel // GetNextSignalNumber till you get back LLDB_INVALID_SIGNAL_NUMBER. 89130812Smarcel int32_t GetFirstSignalNumber() const; 90130812Smarcel 91130812Smarcel int32_t GetNextSignalNumber(int32_t current_signal) const; 92130812Smarcel 93130812Smarcel int32_t GetNumSignals() const; 94130812Smarcel 95130812Smarcel int32_t GetSignalAtIndex(int32_t index) const; 96130812Smarcel 97130812Smarcel // We assume that the elements of this object are constant once it is 98130812Smarcel // constructed, since a process should never need to add or remove symbols as 99130812Smarcel // it runs. So don't call these functions anywhere but the constructor of 100130812Smarcel // your subclass of UnixSignals or in your Process Plugin's GetUnixSignals 101130812Smarcel // method before you return the UnixSignal object. 102130812Smarcel 103130812Smarcel void AddSignal(int signo, llvm::StringRef name, bool default_suppress, 104130812Smarcel bool default_stop, bool default_notify, 105130812Smarcel llvm::StringRef description, 106130812Smarcel llvm::StringRef alias = llvm::StringRef()); 107130812Smarcel 108130812Smarcel enum SignalCodePrintOption { None, Address, Bounds }; 109130812Smarcel 110130812Smarcel // Instead of calling this directly, use a ADD_SIGCODE macro to get compile 111130812Smarcel // time checks when on the native platform. 112130812Smarcel void AddSignalCode( 113130812Smarcel int signo, int code, const llvm::StringLiteral description, 114130812Smarcel SignalCodePrintOption print_option = SignalCodePrintOption::None); 115130812Smarcel 116130812Smarcel void RemoveSignal(int signo); 117130812Smarcel 118130812Smarcel /// Track how many times signals are hit as stop reasons. 119130812Smarcel void IncrementSignalHitCount(int signo); 120130812Smarcel 121130812Smarcel /// Get the hit count statistics for signals. 122130812Smarcel /// 123130812Smarcel /// Gettings statistics on the hit counts of signals can help explain why some 124130812Smarcel /// debug sessions are slow since each stop takes a few hundred ms and some 125130812Smarcel /// software use signals a lot and can cause slow debugging performance if 126130812Smarcel /// they are used too often. Even if a signal is not stopped at, it will auto 127130812Smarcel /// continue the process and a delay will happen. 128130812Smarcel llvm::json::Value GetHitCountStatistics() const; 129130812Smarcel 130130812Smarcel // Returns a current version of the data stored in this class. Version gets 131130812Smarcel // incremented each time Set... method is called. 132130812Smarcel uint64_t GetVersion() const; 133130812Smarcel 134130812Smarcel // Returns a vector of signals that meet criteria provided in arguments. Each 135130812Smarcel // should_[suppress|stop|notify] flag can be std::nullopt - no filtering by 136130812Smarcel // this flag true - only signals that have it set to true are returned false - 137130812Smarcel // only signals that have it set to true are returned 138130812Smarcel std::vector<int32_t> GetFilteredSignals(std::optional<bool> should_suppress, 139130812Smarcel std::optional<bool> should_stop, 140130812Smarcel std::optional<bool> should_notify); 141130812Smarcel 142130812Smarcelprotected: 143130812Smarcel // Classes that inherit from UnixSignals can see and modify these 144130812Smarcel 145130812Smarcel struct SignalCode { 146130812Smarcel const llvm::StringLiteral m_description; 147130812Smarcel const SignalCodePrintOption m_print_option; 148130812Smarcel }; 149130812Smarcel 150130812Smarcel // The StringRefs in Signal are either backed by string literals or reside in 151130812Smarcel // persistent storage (e.g. a StringSet). 152130812Smarcel struct Signal { 153130812Smarcel llvm::StringRef m_name; 154130812Smarcel llvm::StringRef m_alias; 155130812Smarcel llvm::StringRef m_description; 156130812Smarcel std::map<int32_t, SignalCode> m_codes; 157130812Smarcel uint32_t m_hit_count = 0; 158130812Smarcel bool m_suppress : 1, m_stop : 1, m_notify : 1; 159130812Smarcel bool m_default_suppress : 1, m_default_stop : 1, m_default_notify : 1; 160130812Smarcel 161130812Smarcel Signal(llvm::StringRef name, bool default_suppress, bool default_stop, 162130812Smarcel bool default_notify, llvm::StringRef description, 163130812Smarcel llvm::StringRef alias); 164130812Smarcel 165130812Smarcel ~Signal() = default; 166130812Smarcel void Reset(bool reset_stop, bool reset_notify, bool reset_suppress); 167130812Smarcel }; 168130812Smarcel 169130812Smarcel llvm::StringRef GetShortName(llvm::StringRef name) const; 170130812Smarcel 171130812Smarcel virtual void Reset(); 172130812Smarcel 173130812Smarcel typedef std::map<int32_t, Signal> collection; 174130812Smarcel 175130812Smarcel collection m_signals; 176130812Smarcel 177130812Smarcel // This version gets incremented every time something is changing in this 178130812Smarcel // 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