34 #if defined(TTG_HAS_LIBUNWIND)
35 #define UNW_LOCAL_ONLY
36 #include <libunwind.h>
38 #if __has_include(<execinfo.h>)
39 #define TTG_HAS_BACKTRACE
44 #if __has_include(<cxxabi.h>)
46 #define TTG_HAS_CXA_DEMANGLE
52 #ifdef TTG_HAS_LIBUNWIND
56 unw_word_t ip, sp, offp;
60 unw_init_local(&cursor, &uc);
61 while (unw_step(&cursor) > 0) {
62 unw_get_reg(&cursor, UNW_REG_IP, &ip);
63 unw_get_reg(&cursor, UNW_REG_SP, &sp);
65 unw_get_proc_name(&cursor, name, 32768, &offp);
66 std::ostringstream oss;
67 oss << prefix_ <<
"frame " << frame <<
": "
68 <<
"ip = 0x" << (long)ip <<
" sp = 0x" << (
long)sp <<
" symbol = " << __demangle(name);
69 frames_.push_back(oss.str());
73 #elif defined(TTG_HAS_BACKTRACE)
74 void *stack_addrs[1024];
75 const int naddrs = backtrace(stack_addrs, 1024);
76 char **frame_symbols = backtrace_symbols(stack_addrs, naddrs);
78 for (
int i = 1; i < naddrs; ++i) {
82 std::string mangled_function_name = frame_symbols[i];
83 #if defined(__APPLE__)
86 std::istringstream iss(std::string(frame_symbols[i]), std::istringstream::in);
87 std::string frame, file, address;
88 iss >> frame >> file >> address >> mangled_function_name;
90 #elif defined(__linux__)
94 const auto last_right_bracket = mangled_function_name.rfind(
']');
95 const auto last_left_bracket = mangled_function_name.rfind(
'[', last_right_bracket);
96 const auto last_right_parens = mangled_function_name.rfind(
')', last_left_bracket);
97 const auto offset = mangled_function_name.rfind(
"+0x", last_right_parens);
98 const auto last_left_parens = mangled_function_name.rfind(
'(', last_right_parens);
99 if (last_left_parens + 1 < mangled_function_name.size()) {
100 mangled_function_name = mangled_function_name.substr(last_left_parens + 1, offset - last_left_parens - 1);
105 std::ostringstream oss;
106 oss << prefix_ <<
"frame " << i <<
": return address = " << stack_addrs[i] << std::endl
107 <<
" symbol = " << __demangle(mangled_function_name);
108 frames_.push_back(oss.str());
112 #if defined(SIMPLE_STACK)
114 void **topstack = (
void **)0xffffffffL;
115 void **botstack = (
void **)0x70000000L;
118 void **toptext = (
void **)0xffffffffL;
119 void **bottext = (
void **)0x00010000L;
122 #if (defined(linux) && defined(i386))
123 topstack = (
void **)0xc0000000;
124 botstack = (
void **)0xb0000000;
126 #if (defined(__OSF1__) && defined(i860))
127 topstack = (
void **)0x80000000;
128 botstack = (
void **)0x70000000;
131 #if defined(SIMPLE_STACK)
136 void **stack = (
void **)⊥
138 void **frame_pointer = (
void **)stack[3];
139 while (frame_pointer >= botstack && frame_pointer < topstack && frame_pointer[1] >= bottext &&
140 frame_pointer[1] < toptext) {
141 std::ostringstream oss;
142 oss << prefix_ <<
"frame: " << (
void *)frame_pointer;
143 oss <<
" retaddr: " << frame_pointer[1];
144 frames_.push_back(oss.str());
146 frame_pointer = (
void **)*frame_pointer;
155 std::ostringstream oss;
156 std::copy(frames_.begin() + nframes_to_skip, frames_.end(), std::ostream_iterator<std::string>(oss,
"\n"));
160 std::string Backtrace::__demangle(
const std::string &symbol) {
162 #ifdef TTG_HAS_CXA_DEMANGLE
165 char *dsymbol_char = abi::__cxa_demangle(symbol.c_str(), 0, 0, &status);
167 dsymbol = dsymbol_char;
std::string str(const size_t nframes_to_skip=0) const
Backtrace(const std::string &prefix=std::string(""))
top-level TTG namespace contains runtime-neutral functionality