]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/stacktrace/detail/libbacktrace_impls.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / stacktrace / detail / libbacktrace_impls.hpp
1 // Copyright Antony Polukhin, 2016-2017.
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6
7 #ifndef BOOST_STACKTRACE_DETAIL_LIBBACKTRACE_IMPLS_HPP
8 #define BOOST_STACKTRACE_DETAIL_LIBBACKTRACE_IMPLS_HPP
9
10 #include <boost/config.hpp>
11 #ifdef BOOST_HAS_PRAGMA_ONCE
12 # pragma once
13 #endif
14
15 #include <boost/stacktrace/detail/to_hex_array.hpp>
16 #include <boost/stacktrace/detail/location_from_symbol.hpp>
17 #include <boost/core/demangle.hpp>
18 #include <boost/lexical_cast.hpp>
19
20 #include <backtrace.h>
21
22 namespace boost { namespace stacktrace { namespace detail {
23
24
25 struct pc_data {
26 std::string* function;
27 std::string* filename;
28 std::size_t line;
29 };
30
31 inline int libbacktrace_full_callback(void *data, uintptr_t /*pc*/, const char *filename, int lineno, const char *function) {
32 pc_data& d = *static_cast<pc_data*>(data);
33 if (d.filename && filename) {
34 *d.filename = filename;
35 }
36 if (d.function && function) {
37 *d.function = function;
38 }
39 d.line = lineno;
40 return 0;
41 }
42
43 inline void libbacktrace_error_callback(void* /*data*/, const char* /*msg*/, int /*errnum*/) BOOST_NOEXCEPT {
44 // Do nothing, just return.
45 }
46
47
48 inline ::backtrace_state* construct_state(const program_location& prog_location) BOOST_NOEXCEPT {
49 // Currently `backtrace_create_state` can not detect file name on Windows https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82543
50 // That's why we provide a `prog_location` here.
51 return ::backtrace_create_state(
52 prog_location.name(), 0 /*thread-safe*/, boost::stacktrace::detail::libbacktrace_error_callback, 0
53 );
54
55 // TODO: this does not seem to work well when this function is in .so:
56 // Not async-signal-safe, so this method is not called from async-safe functions.
57 //
58 // This function is not async signal safe because:
59 // * Dynamic initialization of a block-scope variable with static storage duration could lock a mutex
60 // * No guarantees on `backtrace_create_state` function.
61
62 // [dcl.inline]: A static local variable in an inline function with external linkage always refers to the same object.
63
64 /*
65 static ::backtrace_state* state = ::backtrace_create_state(
66 0, 1 , boost::stacktrace::detail::libbacktrace_error_callback, 0
67 );
68
69 return state;
70 */
71 }
72
73 struct to_string_using_backtrace {
74 std::string res;
75 boost::stacktrace::detail::program_location prog_location;
76 ::backtrace_state* state;
77 std::string filename;
78 std::size_t line;
79
80 void prepare_function_name(const void* addr) {
81 boost::stacktrace::detail::pc_data data = {&res, &filename, 0};
82 if (state) {
83 ::backtrace_pcinfo(
84 state,
85 reinterpret_cast<uintptr_t>(addr),
86 boost::stacktrace::detail::libbacktrace_full_callback,
87 boost::stacktrace::detail::libbacktrace_error_callback,
88 &data
89 );
90 }
91 line = data.line;
92 }
93
94 bool prepare_source_location(const void* /*addr*/) {
95 if (filename.empty() || !line) {
96 return false;
97 }
98
99 res += " at ";
100 res += filename;
101 res += ':';
102 res += boost::lexical_cast<boost::array<char, 40> >(line).data();
103 return true;
104 }
105
106 to_string_using_backtrace() BOOST_NOEXCEPT {
107 state = boost::stacktrace::detail::construct_state(prog_location);
108 }
109 };
110
111 template <class Base> class to_string_impl_base;
112 typedef to_string_impl_base<to_string_using_backtrace> to_string_impl;
113
114 inline std::string name_impl(const void* addr) {
115 std::string res;
116
117 boost::stacktrace::detail::program_location prog_location;
118 ::backtrace_state* state = boost::stacktrace::detail::construct_state(prog_location);
119
120 boost::stacktrace::detail::pc_data data = {&res, 0, 0};
121 if (state) {
122 ::backtrace_pcinfo(
123 state,
124 reinterpret_cast<uintptr_t>(addr),
125 boost::stacktrace::detail::libbacktrace_full_callback,
126 boost::stacktrace::detail::libbacktrace_error_callback,
127 &data
128 );
129 }
130 if (!res.empty()) {
131 res = boost::core::demangle(res.c_str());
132 }
133
134 return res;
135 }
136
137 } // namespace detail
138
139 std::string frame::source_file() const {
140 std::string res;
141
142 boost::stacktrace::detail::program_location prog_location;
143 ::backtrace_state* state = boost::stacktrace::detail::construct_state(prog_location);
144
145 boost::stacktrace::detail::pc_data data = {0, &res, 0};
146 if (state) {
147 ::backtrace_pcinfo(
148 state,
149 reinterpret_cast<uintptr_t>(addr_),
150 boost::stacktrace::detail::libbacktrace_full_callback,
151 boost::stacktrace::detail::libbacktrace_error_callback,
152 &data
153 );
154 }
155
156 return res;
157 }
158
159 std::size_t frame::source_line() const {
160 boost::stacktrace::detail::program_location prog_location;
161 ::backtrace_state* state = boost::stacktrace::detail::construct_state(prog_location);
162
163 boost::stacktrace::detail::pc_data data = {0, 0, 0};
164 if (state) {
165 ::backtrace_pcinfo(
166 state,
167 reinterpret_cast<uintptr_t>(addr_),
168 boost::stacktrace::detail::libbacktrace_full_callback,
169 boost::stacktrace::detail::libbacktrace_error_callback,
170 &data
171 );
172 }
173
174 return data.line;
175 }
176
177
178 }} // namespace boost::stacktrace
179
180 #endif // BOOST_STACKTRACE_DETAIL_LIBBACKTRACE_IMPLS_HPP