107793f95SMichael Jones //===-- Implementation of a class for mapping signals to strings ----------===// 207793f95SMichael Jones // 307793f95SMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 407793f95SMichael Jones // See https://llvm.org/LICENSE.txt for license information. 507793f95SMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 607793f95SMichael Jones // 707793f95SMichael Jones //===----------------------------------------------------------------------===// 807793f95SMichael Jones 925174976SSiva Chandra Reddy #include "signal_to_string.h" 1025174976SSiva Chandra Reddy #include "platform_signals.h" 1107793f95SMichael Jones 1207793f95SMichael Jones #include "src/__support/CPP/span.h" 1307793f95SMichael Jones #include "src/__support/CPP/string_view.h" 1407793f95SMichael Jones #include "src/__support/CPP/stringstream.h" 1507793f95SMichael Jones #include "src/__support/StringUtil/message_mapper.h" 1607793f95SMichael Jones #include "src/__support/integer_to_string.h" 17daeee567SSiva Chandra Reddy #include "src/__support/macros/attributes.h" 18*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 1907793f95SMichael Jones 2007793f95SMichael Jones #include <signal.h> 2107793f95SMichael Jones #include <stddef.h> 2207793f95SMichael Jones 23*5ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 2407793f95SMichael Jones namespace internal { 2507793f95SMichael Jones 2607793f95SMichael Jones constexpr size_t max_buff_size() { 2707793f95SMichael Jones constexpr size_t base_str_len = sizeof("Real-time signal"); 2807793f95SMichael Jones // the buffer should be able to hold "Real-time signal" + ' ' + num_str 29b555912eSGuillaume Chatelet return (base_str_len + 1 + IntegerToString<int>::buffer_size()) * 30b555912eSGuillaume Chatelet sizeof(char); 3107793f95SMichael Jones } 3207793f95SMichael Jones 3307793f95SMichael Jones // This is to hold signal strings that have to be custom built. It may be 3407793f95SMichael Jones // rewritten on every call to strsignal (or other signal to string function). 3507793f95SMichael Jones constexpr size_t SIG_BUFFER_SIZE = max_buff_size(); 36daeee567SSiva Chandra Reddy LIBC_THREAD_LOCAL char signal_buffer[SIG_BUFFER_SIZE]; 3707793f95SMichael Jones 38bb2ebbd1SSiva Chandra Reddy constexpr size_t TOTAL_STR_LEN = total_str_len(PLATFORM_SIGNALS); 3907793f95SMichael Jones 40bb2ebbd1SSiva Chandra Reddy constexpr size_t SIG_ARRAY_SIZE = max_key_val(PLATFORM_SIGNALS) + 1; 4107793f95SMichael Jones 42bb2ebbd1SSiva Chandra Reddy constexpr MessageMapper<SIG_ARRAY_SIZE, TOTAL_STR_LEN> 43bb2ebbd1SSiva Chandra Reddy signal_mapper(PLATFORM_SIGNALS); 4407793f95SMichael Jones 4507793f95SMichael Jones cpp::string_view build_signal_string(int sig_num, cpp::span<char> buffer) { 4607793f95SMichael Jones cpp::string_view base_str; 4707793f95SMichael Jones if (sig_num >= SIGRTMIN && sig_num <= SIGRTMAX) { 4807793f95SMichael Jones base_str = cpp::string_view("Real-time signal"); 4907793f95SMichael Jones sig_num -= SIGRTMIN; 5007793f95SMichael Jones } else { 5107793f95SMichael Jones base_str = cpp::string_view("Unknown signal"); 5207793f95SMichael Jones } 5307793f95SMichael Jones 5407793f95SMichael Jones // if the buffer can't hold "Unknown signal" + ' ' + num_str, then just 5507793f95SMichael Jones // return "Unknown signal". 5607793f95SMichael Jones if (buffer.size() < 57b555912eSGuillaume Chatelet (base_str.size() + 1 + IntegerToString<int>::buffer_size())) 5807793f95SMichael Jones return base_str; 5907793f95SMichael Jones 6007793f95SMichael Jones cpp::StringStream buffer_stream( 6107793f95SMichael Jones {const_cast<char *>(buffer.data()), buffer.size()}); 6207793f95SMichael Jones buffer_stream << base_str << ' ' << sig_num << '\0'; 6307793f95SMichael Jones return buffer_stream.str(); 6407793f95SMichael Jones } 6507793f95SMichael Jones 6607793f95SMichael Jones } // namespace internal 6707793f95SMichael Jones 6807793f95SMichael Jones cpp::string_view get_signal_string(int sig_num) { 6907793f95SMichael Jones return get_signal_string( 7007793f95SMichael Jones sig_num, {internal::signal_buffer, internal::SIG_BUFFER_SIZE}); 7107793f95SMichael Jones } 7207793f95SMichael Jones 7307793f95SMichael Jones cpp::string_view get_signal_string(int sig_num, cpp::span<char> buffer) { 7407793f95SMichael Jones auto opt_str = internal::signal_mapper.get_str(sig_num); 7507793f95SMichael Jones if (opt_str) 7607793f95SMichael Jones return *opt_str; 7707793f95SMichael Jones else 7807793f95SMichael Jones return internal::build_signal_string(sig_num, buffer); 7907793f95SMichael Jones } 8007793f95SMichael Jones 81*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 82