File indexing completed on 2025-01-18 09:52:31
0001
0002
0003
0004
0005
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 , const char *symname, uintptr_t , uintptr_t ) {
0036 pc_data& d = *static_cast<pc_data*>(data);
0037 if (d.function && symname) {
0038 *d.function = symname;
0039 }
0040 }
0041
0042
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 , 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* , const char* , int ) noexcept {
0060
0061 }
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 BOOST_SYMBOL_VISIBLE inline ::backtrace_state* construct_state(const program_location& prog_location) noexcept {
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
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
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* ) {
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 }
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 }}
0247
0248 #endif