ttg 1.0.0
Template Task Graph (TTG): flowgraph-based programming model for high-performance distributed-memory algorithms
Loading...
Searching...
No Matches
backtrace.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// backtrace.cpp
4//
5// Copyright (C) 1996 Limit Point Systems, Inc.
6//
7// Author: Curtis Janssen <cljanss@limitpt.com>
8// Maintainer: LPS
9//
10// This file is part of the SC Toolkit.
11//
12// The SC Toolkit is free software; you can redistribute it and/or modify
13// it under the terms of the GNU Library General Public License as published by
14// the Free Software Foundation; either version 2, or (at your option)
15// any later version.
16//
17// The SC Toolkit is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU Library General Public License for more details.
21//
22// You should have received a copy of the GNU Library General Public License
23// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
24// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
25//
26// The U.S. Government is granted a limited license as per AL 91-7.
27//
28
29#include "backtrace.h"
30
31#include <cstring>
32#include <iterator>
33#include <sstream>
34
35#if defined(TTG_HAS_LIBUNWIND)
36#define UNW_LOCAL_ONLY
37#include <libunwind.h>
38#else
39#if __has_include(<execinfo.h>)
40#define TTG_HAS_BACKTRACE
41#include <execinfo.h>
42#endif
43#endif
44
45#if __has_include(<cxxabi.h>)
46#include <cxxabi.h>
47#define TTG_HAS_CXA_DEMANGLE
48#endif
49
50namespace ttg {
51 namespace detail {
52 Backtrace::Backtrace(const std::string &prefix) : prefix_(prefix) {
53#ifdef TTG_HAS_LIBUNWIND
54 {
55 unw_cursor_t cursor;
56 unw_context_t uc;
57 unw_word_t ip, sp, offp;
58 int frame = 0;
59
60 unw_getcontext(&uc);
61 unw_init_local(&cursor, &uc);
62 while (unw_step(&cursor) > 0) {
63 unw_get_reg(&cursor, UNW_REG_IP, &ip);
64 unw_get_reg(&cursor, UNW_REG_SP, &sp);
65 char name[32768];
66 unw_get_proc_name(&cursor, name, 32768, &offp);
67 std::ostringstream oss;
68 oss << prefix_ << "frame " << frame << ": "
69 << "ip = 0x" << (long)ip << " sp = 0x" << (long)sp << " symbol = " << __demangle(name);
70 frames_.push_back(oss.str());
71 ++frame;
72 }
73 }
74#elif defined(TTG_HAS_BACKTRACE) // !TTG_HAS_LIBUNWIND
75 void *stack_addrs[1024];
76 const int naddrs = backtrace(stack_addrs, 1024);
77 char **frame_symbols = backtrace_symbols(stack_addrs, naddrs);
78 // starting @ 1 to skip this function
79 for (int i = 1; i < naddrs; ++i) {
80 // extract (mangled) function name
81 // parsing frame_symbols[i] is OS-specific
82 // for unknown OS ... just return the whole string
83 std::string mangled_function_name = frame_symbols[i];
84#if defined(__APPLE__)
85 {
86 // "frame_id /path/to/exec address symbol"
87 std::istringstream iss(std::string(frame_symbols[i]), std::istringstream::in);
88 std::string frame, file, address;
89 iss >> frame >> file >> address >> mangled_function_name;
90 }
91#elif defined(__linux__)
92 {
93 // "/path/to/exec(symbol+0x...) [address]"
94 // parse from the back to avoid dealing with parentheses in the path
95 const auto last_right_bracket = mangled_function_name.rfind(']');
96 const auto last_left_bracket = mangled_function_name.rfind('[', last_right_bracket);
97 const auto last_right_parens = mangled_function_name.rfind(')', last_left_bracket);
98 const auto offset = mangled_function_name.rfind("+0x", last_right_parens);
99 const auto last_left_parens = mangled_function_name.rfind('(', last_right_parens);
100 if (last_left_parens + 1 < mangled_function_name.size()) {
101 mangled_function_name = mangled_function_name.substr(last_left_parens + 1, offset - last_left_parens - 1);
102 }
103 }
104#endif
105
106 std::ostringstream oss;
107 oss << prefix_ << "frame " << i << ": return address = " << stack_addrs[i] << std::endl
108 << " symbol = " << __demangle(mangled_function_name);
109 frames_.push_back(oss.str());
110 }
111 free(frame_symbols);
112#else // !TTG_HAS_LIBUNWIND && !TTG_HAS_BACKTRACE
113#if defined(SIMPLE_STACK)
114 int bottom = 0x1234;
115 void **topstack = (void **)0xffffffffL;
116 void **botstack = (void **)0x70000000L;
117 // signal handlers can put weird things in the return address slot,
118 // so it is usually best to keep toptext large.
119 void **toptext = (void **)0xffffffffL;
120 void **bottext = (void **)0x00010000L;
121#endif // SIMPLE_STACK
122
123#if (defined(linux) && defined(i386))
124 topstack = (void **)0xc0000000;
125 botstack = (void **)0xb0000000;
126#endif
127#if (defined(__OSF1__) && defined(i860))
128 topstack = (void **)0x80000000;
129 botstack = (void **)0x70000000;
130#endif
131
132#if defined(SIMPLE_STACK)
133 // This will go through the stack assuming a simple linked list
134 // of pointers to the previous frame followed by the return address.
135 // It trys to be careful and avoid creating new exceptions, but there
136 // are no guarantees.
137 void **stack = (void **)&bottom;
138
139 void **frame_pointer = (void **)stack[3];
140 while (frame_pointer >= botstack && frame_pointer < topstack && frame_pointer[1] >= bottext &&
141 frame_pointer[1] < toptext) {
142 std::ostringstream oss;
143 oss << prefix_ << "frame: " << (void *)frame_pointer;
144 oss << " retaddr: " << frame_pointer[1];
145 frames_.push_back(oss.str());
146
147 frame_pointer = (void **)*frame_pointer;
148 }
149#endif // SIMPLE_STACK
150#endif // TTG_HAS_BACKTRACE
151 }
152
153 Backtrace::Backtrace(const Backtrace &other) : frames_(other.frames_), prefix_(other.prefix_) {}
154
155 std::string Backtrace::str(size_t nframes_to_skip) const {
156 std::ostringstream oss;
157 std::copy(frames_.begin() + nframes_to_skip, frames_.end(), std::ostream_iterator<std::string>(oss, "\n"));
158 return oss.str();
159 }
160
161 std::string Backtrace::__demangle(const std::string &symbol) {
162 std::string dsymbol;
163#ifdef TTG_HAS_CXA_DEMANGLE
164 {
165 int status;
166 char *dsymbol_char = abi::__cxa_demangle(symbol.c_str(), 0, 0, &status);
167 if (status == 0) { // success
168 dsymbol = dsymbol_char;
169 free(dsymbol_char);
170 } else // fail
171 dsymbol = symbol;
172 }
173#else
174 dsymbol = symbol;
175#endif
176 return dsymbol;
177 }
178
179 } // namespace detail
180} // namespace ttg
std::string str(const size_t nframes_to_skip=0) const
Backtrace(const std::string &prefix=std::string(""))
Definition backtrace.cpp:52
top-level TTG namespace contains runtime-neutral functionality
Definition keymap.h:9