33#if defined(TIMEMORY_USE_LIBUNWIND)
34# include <libunwind.h>
37#if defined(TIMEMORY_UNIX)
55#if defined(TIMEMORY_UNIX)
58 demangle_backtrace(
const char* cstr);
64 demangle_unw_backtrace(
const char* cstr);
69template <
size_t Depth,
size_t Offset = 1>
73 static_assert(Depth > 0,
"Error !(Depth > 0)");
74 static_assert(Offset >= 0,
"Error !(Offset >= 0)");
77 std::array<char[512], Depth> btrace{};
78 for(
auto& itr : btrace)
82 std::array<void*, Depth + Offset> buffer{};
86 auto sz = ::backtrace(buffer.data(), Depth + Offset);
91 char** bsym = ::backtrace_symbols(buffer.data() + Offset, n);
96 ::perror(
"backtrace_symbols");
100 for(
decltype(n) i = 0; i < n; ++i)
102 ::snprintf(btrace[i],
sizeof(btrace[i]),
"%s", bsym[i]);
108template <
size_t Depth,
size_t Offset = 1>
109TIMEMORY_NOINLINE
auto
112# if defined(TIMEMORY_USE_LIBUNWIND)
113 static_assert(Depth > 0,
"Error !(Depth > 0)");
114 static_assert(Offset >= 0,
"Error !(Offset >= 0)");
116 unw_cursor_t cursor{};
117 unw_context_t context{};
120 std::array<char[512], Depth> btrace{};
121 for(
auto& itr : btrace)
125 unw_getcontext(&context);
126 if(unw_init_local(&cursor, &context) < 0)
132 while(unw_step(&cursor) > 0)
136 auto _idx = ++tot_idx;
137 if(_idx >= Depth + Offset)
139 unw_get_reg(&cursor, UNW_REG_IP, &ip);
144 if(unw_get_proc_name(&cursor, name,
sizeof(name), &off) == 0)
148 auto _lidx = _idx - Offset;
150 snprintf(btrace[_lidx],
sizeof(btrace[_lidx]),
"%s +0x%lx", name,
153 snprintf(btrace[_lidx],
sizeof(btrace[_lidx]),
"%s", name);
158 std::array<char[512], Depth> btrace{};
159 throw std::runtime_error(
"[timemory]> libunwind not available");
164template <
size_t Depth,
size_t Offset = 1,
typename Func>
165TIMEMORY_NOINLINE
auto
166get_backtrace(Func&& func)
168 static_assert(Depth > 0,
"Error !(Depth > 0)");
169 static_assert(Offset >= 0,
"Error !(Offset >= 0)");
171 using type = std::result_of_t<Func(
const char[512])>;
173 std::array<type, Depth> btrace{};
175 auto&& _data = ::tim::get_backtrace<Depth, Offset + 1>();
176 auto _n = _data.size();
177 for(
decltype(_n) i = 0; i < _n; ++i)
178 btrace[i] = func(_data[i]);
182template <
size_t Depth,
size_t Offset = 1,
typename Func>
183TIMEMORY_NOINLINE
auto
184get_unw_backtrace(Func&& func)
186 static_assert(Depth > 0,
"Error !(Depth > 0)");
187 static_assert(Offset >= 0,
"Error !(Offset >= 0)");
189 using type = std::result_of_t<Func(
const char[512])>;
191 std::array<type, Depth> btrace{};
193 auto&& _data = ::tim::get_unw_backtrace<Depth, Offset + 1>();
194 auto _n = _data.size();
195 for(
decltype(_n) i = 0; i < _n; ++i)
196 btrace[i] = func(_data[i]);
202template <
size_t Depth,
size_t Offset = 1>
203TIMEMORY_NOINLINE
auto
204get_demangled_backtrace()
206 auto demangle_bt = [](
const char cstr[512]) {
return demangle_backtrace(cstr); };
207 return get_backtrace<Depth, Offset + 1>(demangle_bt);
212template <
size_t Depth,
size_t Offset = 1>
213TIMEMORY_NOINLINE
auto
214get_demangled_unw_backtrace()
216 auto demangle_bt = [](
const char cstr[512]) {
return demangle_unw_backtrace(cstr); };
217 return get_unw_backtrace<Depth, Offset + 1>(demangle_bt);
222template <
size_t Depth,
size_t Offset = 2>
223TIMEMORY_NOINLINE std::ostream&
227 os << _indent.substr(0, _indent.length() / 2) <<
"Backtrace";
230 os <<
":\n" << std::flush;
231 auto bt = tim::get_backtrace<Depth, Offset>();
234 for(
const auto& itr : bt)
245template <
size_t Depth,
size_t Offset = 2>
246TIMEMORY_NOINLINE std::ostream&
251 os << _indent.substr(0, _indent.length() / 2) <<
"Backtrace";
254 os <<
":\n" << std::flush;
255 auto bt = tim::get_demangled_backtrace<Depth, Offset>();
258 for(
const auto& itr : bt)
269template <
size_t Depth,
size_t Offset = 2>
270TIMEMORY_NOINLINE std::ostream&
274 os << _indent.substr(0, _indent.length() / 2) <<
"Backtrace";
277 os <<
":\n" << std::flush;
278 auto bt = tim::get_unw_backtrace<Depth, Offset>();
281 for(
const auto& itr : bt)
292template <
size_t Depth,
size_t Offset = 3>
293TIMEMORY_NOINLINE std::ostream&
298 os << _indent.substr(0, _indent.length() / 2) <<
"Backtrace";
301 os <<
":\n" << std::flush;
302 auto bt = tim::get_demangled_unw_backtrace<Depth, Offset>();
305 for(
const auto& itr : bt)
319demangle_backtrace(
const char* cstr)
330template <
size_t Depth,
size_t Offset = 2>
331static inline std::ostream&
335 os <<
"[timemory]> Backtrace not supported on this platform\n";
339template <
size_t Depth,
size_t Offset = 3>
340static inline std::ostream&
341print_demangled_backtrace(std::ostream&
os = std::cerr,
std::string = {},
344 os <<
"[timemory]> Backtrace not supported on this platform\n";
348template <
size_t Depth,
size_t Offset = 2>
349static inline std::ostream&
353 os <<
"[timemory]> libunwind backtrace not supported on this platform\n";
357template <
size_t Depth,
size_t Offset = 3>
358static inline std::ostream&
359print_demangled_unw_backtrace(std::ostream&
os = std::cerr,
std::string = {},
362 os <<
"[timemory]> libunwind backtrace not supported on this platform\n";
char const std::string & _prefix
tim::mpl::apply< std::string > string
const std::string std::ostream * os
#define TIMEMORY_UTILITY_INLINE