Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:52:31

0001 // Copyright Antony Polukhin, 2016-2023.
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See
0004 // accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_STACKTRACE_DETAIL_LIBBACKTRACE_IMPLS_HPP
0008 #define BOOST_STACKTRACE_DETAIL_LIBBACKTRACE_IMPLS_HPP
0009 
0010 #include <boost/config.hpp>
0011 #ifdef BOOST_HAS_PRAGMA_ONCE
0012 #   pragma once
0013 #endif
0014 
0015 #include <boost/stacktrace/detail/to_hex_array.hpp>
0016 #include <boost/stacktrace/detail/to_dec_array.hpp>
0017 #include <boost/stacktrace/detail/location_from_symbol.hpp>
0018 #include <boost/core/demangle.hpp>
0019 
0020 #ifdef BOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE
0021 #   include BOOST_STACKTRACE_BACKTRACE_INCLUDE_FILE
0022 #else
0023 #   include <backtrace.h>
0024 #endif
0025 
0026 namespace boost { namespace stacktrace { namespace detail {
0027 
0028 
0029 struct pc_data {
0030     std::string* function;
0031     std::string* filename;
0032     std::size_t line;
0033 };
0034 
0035 inline void libbacktrace_syminfo_callback(void *data, uintptr_t /*pc*/, const char *symname, uintptr_t /*symval*/, uintptr_t /*symsize*/) {
0036     pc_data& d = *static_cast<pc_data*>(data);
0037     if (d.function && symname) {
0038         *d.function = symname;
0039     }
0040 }
0041 
0042 // Old versions of libbacktrace have different signature for the callback
0043 inline void libbacktrace_syminfo_callback(void *data, uintptr_t pc, const char *symname, uintptr_t symval) {
0044     boost::stacktrace::detail::libbacktrace_syminfo_callback(data, pc, symname, symval, 0);
0045 }
0046 
0047 inline int libbacktrace_full_callback(void *data, uintptr_t /*pc*/, const char *filename, int lineno, const char *function) {
0048     pc_data& d = *static_cast<pc_data*>(data);
0049     if (d.filename && filename) {
0050         *d.filename = filename;
0051     }
0052     if (d.function && function) {
0053         *d.function = function;
0054     }
0055     d.line = lineno;
0056     return 0;
0057 }
0058 
0059 inline void libbacktrace_error_callback(void* /*data*/, const char* /*msg*/, int /*errnum*/) noexcept {
0060     // Do nothing, just return.
0061 }
0062 
0063 // Not async-signal-safe, so this method is not called from async-safe functions.
0064 //
0065 // This function is not async signal safe because:
0066 // * Dynamic initialization of a block-scope variable with static storage duration could lock a mutex
0067 // * No guarantees on `backtrace_create_state` function.
0068 //
0069 // Currently `backtrace_create_state` can not detect file name on Windows https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82543
0070 // That's why we provide a `prog_location` here.
0071 BOOST_SYMBOL_VISIBLE inline ::backtrace_state* construct_state(const program_location& prog_location) noexcept {
0072     // [dcl.inline]: A static local variable in an inline function with external linkage always refers to the same object.
0073 
0074     // TODO: The most obvious solution:
0075     //
0076     //static ::backtrace_state* state = ::backtrace_create_state(
0077     //    prog_location.name(),
0078     //    1, // allow safe concurrent usage of the same state
0079     //    boost::stacktrace::detail::libbacktrace_error_callback,
0080     //    0 // pointer to data that will be passed to callback
0081     //);
0082     //
0083     //
0084     // Unfortunately, that solution segfaults when `construct_state()` function is in .so file
0085     // and multiple threads concurrently work with state. I failed to localize the root cause:
0086     // https://gcc.gnu.org/bugzilla//show_bug.cgi?id=87653
0087 
0088 #define BOOST_STACKTRACE_DETAIL_IS_MT 1
0089 
0090 #if !defined(BOOST_HAS_THREADS)
0091 #   define BOOST_STACKTRACE_DETAIL_STORAGE static
0092 #   undef BOOST_STACKTRACE_DETAIL_IS_MT
0093 #   define BOOST_STACKTRACE_DETAIL_IS_MT 0
0094 #elif defined(BOOST_STACKTRACE_BACKTRACE_FORCE_STATIC)
0095 #   define BOOST_STACKTRACE_DETAIL_STORAGE static
0096 #elif !defined(BOOST_NO_CXX11_THREAD_LOCAL)
0097 #   define BOOST_STACKTRACE_DETAIL_STORAGE thread_local
0098 #elif defined(__GNUC__) && !defined(__clang__)
0099 #   define BOOST_STACKTRACE_DETAIL_STORAGE static __thread
0100 #else
0101 #   define BOOST_STACKTRACE_DETAIL_STORAGE /* just a local variable */
0102 #endif
0103 
0104     BOOST_STACKTRACE_DETAIL_STORAGE ::backtrace_state* state = ::backtrace_create_state(
0105         prog_location.name(),
0106         BOOST_STACKTRACE_DETAIL_IS_MT,
0107         boost::stacktrace::detail::libbacktrace_error_callback,
0108         0
0109     );
0110 
0111 #undef BOOST_STACKTRACE_DETAIL_IS_MT
0112 #undef BOOST_STACKTRACE_DETAIL_STORAGE
0113 
0114     return state;
0115 }
0116 
0117 struct to_string_using_backtrace {
0118     std::string res;
0119     boost::stacktrace::detail::program_location prog_location;
0120     ::backtrace_state* state;
0121     std::string filename;
0122     std::size_t line;
0123 
0124     void prepare_function_name(const void* addr) {
0125         boost::stacktrace::detail::pc_data data = {&res, &filename, 0};
0126         if (state) {
0127             ::backtrace_pcinfo(
0128                 state,
0129                 reinterpret_cast<uintptr_t>(addr),
0130                 boost::stacktrace::detail::libbacktrace_full_callback,
0131                 boost::stacktrace::detail::libbacktrace_error_callback,
0132                 &data
0133             ) 
0134             ||
0135             ::backtrace_syminfo(
0136                 state,
0137                 reinterpret_cast<uintptr_t>(addr),
0138                 boost::stacktrace::detail::libbacktrace_syminfo_callback,
0139                 boost::stacktrace::detail::libbacktrace_error_callback,
0140                 &data
0141             );
0142         }
0143         line = data.line;
0144     }
0145 
0146     bool prepare_source_location(const void* /*addr*/) {
0147         if (filename.empty() || !line) {
0148             return false;
0149         }
0150 
0151         res += " at ";
0152         res += filename;
0153         res += ':';
0154         res += boost::stacktrace::detail::to_dec_array(line).data();
0155         return true;
0156     }
0157 
0158     to_string_using_backtrace() noexcept {
0159         state = boost::stacktrace::detail::construct_state(prog_location);
0160     }
0161 };
0162 
0163 template <class Base> class to_string_impl_base;
0164 typedef to_string_impl_base<to_string_using_backtrace> to_string_impl;
0165 
0166 inline std::string name_impl(const void* addr) {
0167     std::string res;
0168 
0169     boost::stacktrace::detail::program_location prog_location;
0170     ::backtrace_state* state = boost::stacktrace::detail::construct_state(prog_location);
0171 
0172     boost::stacktrace::detail::pc_data data = {&res, 0, 0};
0173     if (state) {
0174         ::backtrace_pcinfo(
0175             state,
0176             reinterpret_cast<uintptr_t>(addr),
0177             boost::stacktrace::detail::libbacktrace_full_callback,
0178             boost::stacktrace::detail::libbacktrace_error_callback,
0179             &data
0180         )
0181         ||
0182         ::backtrace_syminfo(
0183             state,
0184             reinterpret_cast<uintptr_t>(addr),
0185             boost::stacktrace::detail::libbacktrace_syminfo_callback,
0186             boost::stacktrace::detail::libbacktrace_error_callback,
0187             &data
0188         );
0189     }
0190     if (!res.empty()) {
0191         res = boost::core::demangle(res.c_str());
0192     }
0193 
0194     return res;
0195 }
0196 
0197 } // namespace detail
0198 
0199 std::string frame::source_file() const {
0200     std::string res;
0201 
0202     if (!addr_) {
0203         return res;
0204     }
0205 
0206     boost::stacktrace::detail::program_location prog_location;
0207     ::backtrace_state* state = boost::stacktrace::detail::construct_state(prog_location);
0208 
0209     boost::stacktrace::detail::pc_data data = {0, &res, 0};
0210     if (state) {
0211         ::backtrace_pcinfo(
0212             state,
0213             reinterpret_cast<uintptr_t>(addr_),
0214             boost::stacktrace::detail::libbacktrace_full_callback,
0215             boost::stacktrace::detail::libbacktrace_error_callback,
0216             &data
0217         );
0218     }
0219 
0220     return res;
0221 }
0222 
0223 std::size_t frame::source_line() const {
0224     if (!addr_) {
0225         return 0;
0226     }
0227 
0228     boost::stacktrace::detail::program_location prog_location;
0229     ::backtrace_state* state = boost::stacktrace::detail::construct_state(prog_location);
0230 
0231     boost::stacktrace::detail::pc_data data = {0, 0, 0};
0232     if (state) {
0233         ::backtrace_pcinfo(
0234             state,
0235             reinterpret_cast<uintptr_t>(addr_),
0236             boost::stacktrace::detail::libbacktrace_full_callback,
0237             boost::stacktrace::detail::libbacktrace_error_callback,
0238             &data
0239         );
0240     }
0241 
0242     return data.line;
0243 }
0244 
0245 
0246 }} // namespace boost::stacktrace
0247 
0248 #endif // BOOST_STACKTRACE_DETAIL_LIBBACKTRACE_IMPLS_HPP