Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
When an exception occures in kernel mode, display both kernel and actor stacks
[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 = boost::stacktrace::stacktrace();
59 public:
60   std::string resolve() const
61   {
62     std::stringstream ss;
63
64     int frame_count = 0;
65     int state       = 0;
66
67     for (boost::stacktrace::frame frame : st) {
68       if (state == 1) {
69         if (boost::starts_with(frame.name(), "simgrid::xbt::MainFunction") ||
70             boost::starts_with(frame.name(), "simgrid::kernel::context::Context::operator()()"))
71           break;
72         ss << "  ->  " << frame_count++ << "# " << frame.name() << " at " << frame.source_file() << ":"
73            << frame.source_line() << std::endl;
74         if (frame.name() == "main")
75           break;
76       } else {
77         if (frame.name() == "simgrid::xbt::Backtrace::Backtrace()")
78           state = 1;
79       }
80     }
81
82     return ss.str();
83   }
84 #else
85 public:
86   std::string resolve() const { return ""; } // fallback value
87 #endif
88 };
89
90 Backtrace::Backtrace() : impl_(std::make_shared<BacktraceImpl>()) {}
91
92 std::string Backtrace::resolve() const
93 {
94   return impl_->resolve();
95 }
96
97 void Backtrace::display() const
98 {
99   std::string backtrace = resolve();
100   std::fprintf(stderr, "Backtrace (displayed in actor %s):\n%s\n", xbt_procname(),
101                backtrace.empty() ? "(backtrace not set -- did you install Boost.Stacktrace?)" : backtrace.c_str());
102 }
103
104 } // namespace xbt
105 } // namespace simgrid