Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
35122fbc645c1571a26da6c80330bbb0bfd61b00
[simgrid.git] / src / xbt / backtrace.cpp
1 /* Copyright (c) 2005-2021. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "src/internal_config.h"
7
8 #include <xbt/backtrace.hpp>
9 #include <xbt/string.hpp>
10 #include <xbt/sysdep.h>
11 #include <xbt/virtu.h>
12
13 #include <boost/algorithm/string/predicate.hpp>
14 #include <cstdio>
15 #include <cstdlib>
16 #include <sstream>
17
18 // Try to detect and use the C++ itanium ABI for name demangling:
19 #ifdef __GXX_ABI_VERSION
20 #include <cxxabi.h>
21 #endif
22
23 #if HAVE_BOOST_STACKTRACE_BACKTRACE
24 #define BOOST_STACKTRACE_USE_BACKTRACE
25 #include <boost/stacktrace.hpp>
26 #include <boost/stacktrace/detail/frame_decl.hpp>
27 #elif HAVE_BOOST_STACKTRACE_ADDR2LINE
28 #define BOOST_STACKTRACE_USE_ADDR2LINE
29 #include <boost/stacktrace.hpp>
30 #include <boost/stacktrace/detail/frame_decl.hpp>
31 #endif
32
33 /** @brief show the backtrace of the current point (lovely while debugging) */
34 void xbt_backtrace_display_current()
35 {
36   simgrid::xbt::Backtrace().display();
37 }
38
39 namespace simgrid {
40 namespace xbt {
41
42 std::unique_ptr<char, std::function<void(char*)>> demangle(const char* name)
43 {
44 #ifdef __GXX_ABI_VERSION
45   int status;
46   std::unique_ptr<char, std::function<void(char*)>> res(abi::__cxa_demangle(name, nullptr, nullptr, &status),
47                                                         &std::free);
48   if (res != nullptr)
49     return res;
50   // We did not manage to resolve this. Probably because this is not a mangled symbol:
51 #endif
52   // Return the symbol:
53   return std::unique_ptr<char, std::function<void(char*)>>(xbt_strdup(name), &xbt_free_f);
54 }
55
56 class BacktraceImpl {
57 #if HAVE_BOOST_STACKTRACE_BACKTRACE || HAVE_BOOST_STACKTRACE_ADDR2LINE
58   const boost::stacktrace::stacktrace st;
59
60 public:
61   std::string resolve() const
62   {
63     std::stringstream ss;
64
65     int frame_count = 0;
66     int state       = 0;
67
68     for (boost::stacktrace::frame frame : st) {
69       if (state == 1) {
70         if (boost::starts_with(frame.name(), "simgrid::xbt::MainFunction") ||
71             boost::starts_with(frame.name(), "simgrid::kernel::context::Context::operator()()"))
72           break;
73         ss << "  ->  " << frame_count++ << "# " << frame.name() << " at " << frame.source_file() << ":"
74            << frame.source_line() << std::endl;
75         if (frame.name() == "main")
76           break;
77       } else {
78         if (frame.name() == "simgrid::xbt::Backtrace::Backtrace()")
79           state = 1;
80       }
81     }
82
83     return ss.str();
84   }
85 #else
86
87 public:
88   std::string resolve() const { return ""; } // fallback value
89 #endif
90 };
91
92 Backtrace::Backtrace() : impl_(std::make_shared<BacktraceImpl>()) {}
93
94 std::string Backtrace::resolve() const
95 {
96   return impl_->resolve();
97 }
98
99 void Backtrace::display() const
100 {
101   std::string backtrace = resolve();
102   std::fprintf(stderr, "Backtrace (displayed in actor %s):\n%s\n", xbt_procname(),
103                backtrace.empty() ? "(backtrace not set -- did you install Boost.Stacktrace?)" : backtrace.c_str());
104 }
105
106 } // namespace xbt
107 } // namespace simgrid