24#ifndef H_6B9572DA_A64B_49E6_B234_051480991C89
25#define H_6B9572DA_A64B_49E6_B234_051480991C89
28# error "It's not going to compile without a C++ compiler..."
31#if defined(BACKWARD_CXX11)
32#elif defined(BACKWARD_CXX98)
34# if __cplusplus >= 201103L
35# define BACKWARD_CXX11
36# define BACKWARD_ATLEAST_CXX11
37# define BACKWARD_ATLEAST_CXX98
39# define BACKWARD_CXX98
40# define BACKWARD_ATLEAST_CXX98
52#if defined(BACKWARD_SYSTEM_LINUX)
53#elif defined(BACKWARD_SYSTEM_UNKNOWN)
56# define BACKWARD_SYSTEM_LINUX
58# define BACKWARD_SYSTEM_UNKNOWN
75#if defined(BACKWARD_SYSTEM_LINUX)
98# if BACKWARD_HAS_UNWIND == 1
99# elif BACKWARD_HAS_BACKTRACE == 1
101# undef BACKWARD_HAS_UNWIND
102# define BACKWARD_HAS_UNWIND 1
103# undef BACKWARD_HAS_BACKTRACE
104# define BACKWARD_HAS_BACKTRACE 0
144# if BACKWARD_HAS_DW == 1
145# elif BACKWARD_HAS_BFD == 1
146# elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1
148# undef BACKWARD_HAS_DW
149# define BACKWARD_HAS_DW 0
150# undef BACKWARD_HAS_BFD
151# define BACKWARD_HAS_BFD 0
152# undef BACKWARD_HAS_BACKTRACE_SYMBOL
153# define BACKWARD_HAS_BACKTRACE_SYMBOL 1
157# if BACKWARD_HAS_UNWIND == 1
172#ifdef __CLANG_UNWIND_H
184# include <sys/stat.h>
189# if BACKWARD_HAS_BFD == 1
196# ifndef PACKAGE_VERSION
197# define PACKAGE_VERSION
209# if BACKWARD_HAS_DW == 1
210# include <elfutils/libdw.h>
211# include <elfutils/libdwfl.h>
215# if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1)
217# include <execinfo.h>
222#ifdef BACKWARD_ATLEAST_CXX11
223# include <unordered_map>
227 template <
typename K,
typename V>
229 using type = std::unordered_map<K, V>;
238 template <
typename K,
typename V>
242 template <
typename T>
243 const T&
move(
const T& v) {
return v; }
244 template <
typename T>
252namespace system_tag {
257#if defined(BACKWARD_SYSTEM_LINUX)
259#elif defined(BACKWARD_SYSTEM_UNKNOWN)
262# error "May I please get my system defines?"
267namespace trace_resolver_tag {
268#ifdef BACKWARD_SYSTEM_LINUX
273# if BACKWARD_HAS_DW == 1
275# elif BACKWARD_HAS_BFD == 1
277# elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1
280# error "You shall not pass, until you know what you want."
297template <
typename R,
typename T, R (*F)(T)>
299 template <
typename U>
312template <
typename T,
typename Deleter = deleter<
void,
void*, &::free> >
318#ifdef BACKWARD_ATLEAST_CXX11
333#ifdef BACKWARD_ATLEAST_CXX11
355 operator const dummy*()
const {
359 return reinterpret_cast<const dummy*
>(
_val);
392template <
typename TAG>
399#ifdef BACKWARD_SYSTEM_LINUX
402struct demangler_impl<system_tag::current_tag> {
406 using namespace details;
460 return !(*
this == b);
492template <
typename TAG>
495 size_t size()
const {
return 0; }
503#ifdef BACKWARD_SYSTEM_LINUX
509 unsigned thread_id()
const {
513 void skip_n_firsts(
size_t n) {
_skip = n; }
525 size_t skip_n_firsts()
const {
return _skip; }
534 size_t size()
const {
537 Trace operator[](
size_t idx) {
541 return Trace(
_stacktrace[idx + skip_n_firsts()], idx);
555#if BACKWARD_HAS_UNWIND == 1
562 size_t operator()(
F&
f,
size_t depth) {
581 if (
_index >= 0 &&
static_cast<size_t>(
_index) >= _depth)
623 size_t load_from(
void* addr,
size_t depth=32) {
640 StackTraceImpl&
self;
643 void operator()(
size_t idx,
void* addr) {
644 self._stacktrace[idx] = addr;
668 size_t load_from(
void* addr,
size_t depth=32) {
693template <
typename TAG>
696#ifdef BACKWARD_SYSTEM_UNKNOWN
710#ifdef BACKWARD_SYSTEM_LINUX
714 std::string demangle(
const char*
funcname) {
722template <
typename STACKTRACE_TAG>
725#if BACKWARD_HAS_BACKTRACE_SYMBOL == 1
732 void load_stacktrace(
ST&
st) {
733 using namespace details;
734 if (
st.size() == 0) {
742 ResolvedTrace resolve(ResolvedTrace
trace) {
755 trace.source.function =
trace.object_function;
765#if BACKWARD_HAS_BFD == 1
774 void load_stacktrace(
ST&) {}
776 ResolvedTrace resolve(ResolvedTrace
trace) {
823#if BACKWARD_HAS_UNWIND == 0
869 trace.object_function =
trace.source.function;
879 if (
trace.inliners.size() == 0) {
906 if (details.filename) {
909 if (details.funcname) {
930 details::deleter<bfd_boolean, bfd*, &bfd_close>
943 using fobj_bfd_map_t = details::hashtable<std::string, bfd_fileobject>::type;
947 using namespace details;
950 using namespace details;
955 fobj_bfd_map_t::iterator it =
1028 const char* filename;
1057 context->self->find_in_section(
1068 if (result.found)
return;
1085 if (!result.found &&
fobj.symtab) {
1088 &result.funcname, &result.line);
1091 if (!result.found &&
fobj.dynamic_symtab) {
1094 &result.filename, &result.funcname, &result.line);
1103 ResolvedTrace::source_locs_t
results;
1107 &result.filename, &result.funcname, &result.line);
1114 ResolvedTrace::SourceLoc
src_loc;
1116 if (result.filename) {
1117 src_loc.filename = result.filename;
1119 if (result.funcname) {
1120 src_loc.function = demangle(result.funcname);
1133 return strcmp(a, b) == 0;
1139#if BACKWARD_HAS_DW == 1
1148 void load_stacktrace(
ST&) {}
1150 ResolvedTrace resolve(ResolvedTrace
trace) {
1151 using namespace details;
1190 0, 0, 0, 0, 0, 0, 0);
1238#ifdef BACKWARD_I_DO_NOT_RECOMMEND_TO_ENABLE_THIS_HORRIBLE_PIECE_OF_CODE
1283 int line = 0, col = 0;
1286 trace.source.line = line;
1287 trace.source.col = col;
1292 if (
trace.source.function.size() == 0) {
1294 trace.source.function =
trace.object_function;
1301 using dwfl_handle_t = details::handle<Dwfl*, details::deleter<void, Dwfl*, &dwfl_end>>;
1302 details::handle<Dwfl_Callbacks*, details::default_delete<Dwfl_Callbacks*> >
1315 trace.source.function = name;
1320 ResolvedTrace::SourceLoc
sloc;
1324 sloc.function = name;
1327 sloc.filename = name;
1342 ResolvedTrace&
trace;
1365 return pc >= low &&
pc < high;
1372 if (
pc >= low &&
pc < high) {
1413 template <
typename CB>
1475class TraceResolverImpl<system_tag::
linux_tag>:
1487 using lines_t = std::vector<std::pair<unsigned, std::string>>;
1494 using namespace std;
1510 std::getline(*
_file, line);
1520 bool operator()(
char c) {
1521 return std::isspace(c);
1532 if (std::find_if(line.begin(), line.end(),
1556 return !std::isspace(c);
1563 return !(std::find_if(p.second.begin(), p.second.end(),
1572#ifdef BACKWARD_ATLEAST_CXX11
1595#ifdef BACKWARD_ATLEAST_CXX11
1631 using std::min;
using std::max;
1652 src_files_t::iterator it =
_src_files.find(filename);
1664#ifdef BACKWARD_SYSTEM_LINUX
1696 _os <<
"\033[" <<
static_cast<int>(
ccode) <<
"m";
1751 template <
typename ST>
1753 std::stringstream
ss;
1763 template <
typename ST>
1772 template <
typename IT>
1774 std::stringstream
ss;
1784 template <
typename IT>
1785 void print(
IT begin,
IT end, std::ostream&
os,
size_t thread_id = 0) {
1797 template <
typename ST>
1806 template <
typename IT>
1809 for (; begin != end; ++begin) {
1815 os <<
"Stack trace (most recent call last)";
1817 os <<
" in thread " << thread_id;
1825 << std::left << std::setw(2) <<
trace.idx
1829 if (!
trace.source.filename.size() ||
object) {
1831 <<
trace.object_filename
1835 <<
trace.object_function
1855 if (
trace.source.filename.size()) {
1872 using namespace std;
1878 for (lines_t::const_iterator it =
lines.begin();
1879 it !=
lines.end(); ++it) {
1882 os << indent <<
">";
1884 os << indent <<
" ";
1886 os << std::setw(4) << it->first
1908 os <<
" [" << addr <<
"]";
1916#ifdef BACKWARD_SYSTEM_LINUX
1919class SignalHandling {
2001#elif defined(REG_EIP)
2003#elif defined(__arm__)
2006# warning ":/ sorry, ain't know no nothing none not of your architecture!"
2018#if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
2023 raise(info->si_signo);
2033#ifdef BACKWARD_SYSTEM_UNKNOWN
void set_color(Color::type)
void print_header(std::ostream &os, unsigned thread_id)
void print_source_loc(std::ostream &os, const char *indent, const ResolvedTrace::SourceLoc &source_loc, void *addr=0)
FILE * print(ST &st, FILE *os=stderr)
void print(IT begin, IT end, std::ostream &os, size_t thread_id, Colorize &colorize)
void print(IT begin, IT end, std::ostream &os, size_t thread_id=0)
FILE * print(IT begin, IT end, FILE *os=stderr, size_t thread_id=0)
void print(ST &st, std::ostream &os, Colorize &colorize)
void print(ST &st, std::ostream &os)
void print_trace(std::ostream &os, const ResolvedTrace &trace, Colorize &colorize)
void print_snippet(std::ostream &os, const char *indent, const ResolvedTrace::SourceLoc &source_loc, Colorize &colorize, Color::type color_code, int context_size)
SignalHandling(const std::vector< int > &=std::vector< int >())
SourceFile & get_src_file(const std::string &filename)
SourceFile::lines_t lines_t
lines_t get_coalesced_snippet(const std::string &filename, unsigned line_a, unsigned line_b, unsigned context_size)
lines_t get_snippet(const std::string &filename, unsigned line_start, unsigned context_size)
details::hashtable< std::string, SourceFile >::type src_files_t
lines_t get_combined_snippet(const std::string &filename_a, unsigned line_a, const std::string &filename_b, unsigned line_b, unsigned context_size)
lines_t get_lines(unsigned line_start, unsigned line_count)
std::vector< std::pair< unsigned, std::string > > lines_t
SourceFile & operator=(const SourceFile &from)
SourceFile(const SourceFile &from)
lines_t & get_lines(unsigned line_start, unsigned line_count, lines_t &lines)
details::handle< std::ifstream *, details::default_delete< std::ifstream * > > _file
SourceFile(const std::string &path)
size_t load_from(void *, size_t=0)
size_t load_here(size_t=0)
void skip_n_firsts(size_t)
unsigned thread_id() const
void load_stacktrace(ST &)
ResolvedTrace resolve(ResolvedTrace t)
handle(const handle &from)
const typename rm_ptr< T >::type & const_ref_t
handle & operator=(const handle &from)
ref_t operator[](size_t idx)
const_ref_t operator*() const
typename rm_ptr< T >::type & ref_t
const T operator->() const
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
const T & move(const T &v)
bool operator==(const SourceLoc &b) const
bool operator!=(const SourceLoc &b) const
ResolvedTrace(const Trace &mini_trace)
std::vector< SourceLoc > source_locs_t
std::string object_filename
std::string object_function
bool operator()(const lines_t::value_type &p)
Trace(void *_addr, size_t _idx)
void operator()(T &ptr) const
void operator()(U &ptr) const
static std::string demangle(const char *funcname)