X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/7176085f1a329f1ad90b37aec14a424ec008e4a6..4a8bc21517c2e7759a0036d879338f84ed6bf56e:/src/xbt/backtrace.cpp diff --git a/src/xbt/backtrace.cpp b/src/xbt/backtrace.cpp index 575d2a5e67..469b757bb1 100644 --- a/src/xbt/backtrace.cpp +++ b/src/xbt/backtrace.cpp @@ -5,6 +5,12 @@ #include "src/internal_config.h" +#include "simgrid/simix.h" /* SIMIX_process_self_get_name() */ +#include +#include +#include +#include + #include #include #include @@ -19,15 +25,14 @@ #ifdef __GXX_ABI_VERSION #include #endif -#ifdef HAVE_EXECINFO_H +#if HAVE_EXECINFO_H #include #endif -#include "simgrid/simix.h" /* SIMIX_process_self_get_name() */ -#include -#include -#include -#include +#if HAVE_BOOST_STACKTRACE +#define BOOST_STACKTRACE_USE_BACKTRACE +#include +#endif XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_backtrace, xbt, "Backtrace"); @@ -36,12 +41,11 @@ static bool startWith(std::string str, const char* prefix) return strncmp(str.c_str(), prefix, strlen(prefix)) == 0; } -void xbt_backtrace_display(xbt_backtrace_location_t* loc, std::size_t count) +void xbt_backtrace_display(const simgrid::xbt::Backtrace& bt) { -#ifdef HAVE_BACKTRACE - std::vector backtrace = simgrid::xbt::resolve_backtrace(loc, count); + std::vector backtrace = simgrid::xbt::resolve_backtrace(bt); if (backtrace.empty()) { - fprintf(stderr, "(backtrace not set)\n"); + fprintf(stderr, "(backtrace not set -- maybe unavailable on this architecture?)\n"); return; } fprintf(stderr, "Backtrace (displayed in process %s):\n", SIMIX_process_self_get_name()); @@ -54,18 +58,13 @@ void xbt_backtrace_display(xbt_backtrace_location_t* loc, std::size_t count) startWith(s, "simgrid::xbt::MainFunction") /* main used with thread factory */) break; } -#else - XBT_ERROR("Cannot display backtrace when compiled without libunwind."); -#endif } /** @brief show the backtrace of the current point (lovely while debugging) */ void xbt_backtrace_display_current() { - const std::size_t size = 10; - xbt_backtrace_location_t bt[size]; - size_t used = xbt_backtrace_current(bt, size); - xbt_backtrace_display(bt, used); + simgrid::xbt::Backtrace bt = simgrid::xbt::Backtrace(); + xbt_backtrace_display(bt); } namespace simgrid { @@ -87,30 +86,56 @@ std::unique_ptr demangle(const char* name) return std::unique_ptr(xbt_strdup(name), std::free); } -Backtrace backtrace() -{ - const std::size_t size = 10; - xbt_backtrace_location_t loc[size]; - size_t used = xbt_backtrace_current(loc, size); - return Backtrace(loc, loc + used); -} +class BacktraceImpl { + short refcount_ = 1; -} -} +public: + void ref() { refcount_++; } + bool unref() + { + refcount_--; + return refcount_ == 0; + } +#if HAVE_BOOST_STACKTRACE + boost::stacktrace::stacktrace st; +#elif HAVE_BACKTRACE + std::vector frames; +#endif +}; -#if HAVE_BACKTRACE && HAVE_EXECINFO_H && HAVE_POPEN && defined(ADDR2LINE) -size_t xbt_backtrace_current(xbt_backtrace_location_t* loc, std::size_t count) +Backtrace::Backtrace() { - std::size_t used = backtrace(loc, count); +#if HAVE_BOOST_STACKTRACE + impl_ = new BacktraceImpl(); + impl_->st = boost::stacktrace::stacktrace(); +#elif HAVE_BACKTRACE + impl_ = new BacktraceImpl(); + impl_->frames.resize(15); + int used = backtrace(impl_->frames.data(), impl_->frames.size()); if (used == 0) { std::fprintf(stderr, "The backtrace() function failed, which probably means that the memory is exhausted\n."); std::fprintf(stderr, "Bailing out now since there is nothing I can do without a decent amount of memory\n."); std::fprintf(stderr, "Please go fix the memleaks\n"); std::exit(1); } - return used; + impl_->frames.shrink_to_fit(); +#endif +} +Backtrace::Backtrace(const Backtrace& bt) +{ + impl_ = bt.impl_; + impl_->ref(); } +Backtrace::~Backtrace() +{ + if (impl_ != nullptr && impl_->unref()) { + delete impl_; + } +} +} // namespace xbt +} // namespace simgrid + namespace simgrid { namespace xbt { @@ -130,10 +155,11 @@ static std::string get_binary_path() char* path = getenv("PATH"); if (path == nullptr) return ""; + XBT_DEBUG("Looking in the PATH: %s\n", path); std::vector path_list; - // TODO, on Windows, this is ";" - boost::split(path_list, path, boost::is_any_of(":")); + boost::split(path_list, path, boost::is_any_of(":;")); + for (std::string const& path_item : path_list) { std::string binary_name = simgrid::xbt::string_printf("%s/%s", path_item.c_str(), xbt_binary_name); bool found = (stat(binary_name.c_str(), &stat_buf) == 0); @@ -146,36 +172,37 @@ static std::string get_binary_path() return ""; } -// FIXME: This code could be greatly improved/simplifyied with -// http://cairo.sourcearchive.com/documentation/1.9.4/backtrace-symbols_8c-source.html -std::vector resolve_backtrace(xbt_backtrace_location_t const* loc, std::size_t count) +std::vector resolve_backtrace(const Backtrace& bt) { std::vector result; - if (count == 0) +#if HAVE_BOOST_STACKTRACE + std::stringstream ss; + ss << bt.impl_->st; + result.push_back(ss.str()); +#elif HAVE_BACKTRACE && HAVE_EXECINFO_H && HAVE_POPEN && defined(ADDR2LINE) + // FIXME: This code could be greatly improved/simplified with + // http://cairo.sourcearchive.com/documentation/1.9.4/backtrace-symbols_8c-source.html + if (bt.impl_->frames.size() == 0) return result; if (xbt_binary_name == nullptr) XBT_WARN("XBT not initialized, the backtrace will not be resolved."); - // Drop the first one: - loc++; - count--; - - char** backtrace_syms = backtrace_symbols(loc, count); + char** backtrace_syms = backtrace_symbols(bt.impl_->frames.data(), bt.impl_->frames.size()); std::string binary_name = get_binary_path(); if (binary_name.empty()) { - for (std::size_t i = 0; i < count; i++) - result.push_back(simgrid::xbt::string_printf("%p", loc[i])); + for (std::size_t i = 1; i < bt.impl_->frames.size(); i++) // the first one is not interesting + result.push_back(simgrid::xbt::string_printf("%p", bt.impl_->frames[i])); return result; } // Create the system command for add2line: std::ostringstream stream; stream << ADDR2LINE << " -f -e " << binary_name << ' '; - std::vector addrs(count); - for (std::size_t i = 0; i < count; i++) { + std::vector addrs(bt.impl_->frames.size()); + for (std::size_t i = 1; i < bt.impl_->frames.size(); i++) { // the first one is not interesting /* retrieve this address */ XBT_DEBUG("Retrieving address number %zu from '%s'", i, backtrace_syms[i]); char buff[256]; @@ -202,7 +229,7 @@ std::vector resolve_backtrace(xbt_backtrace_location_t const* loc, /* To read the output of addr2line */ char line_func[1024]; char line_pos[1024]; - for (std::size_t i = 0; i < count; i++) { + for (std::size_t i = 1; i < bt.impl_->frames.size(); i++) { // The first one is not interesting XBT_DEBUG("Looking for symbol %zu, addr = '%s'", i, addrs[i].c_str()); if (fgets(line_func, 1024, pipe)) { line_func[strlen(line_func) - 1] = '\0'; @@ -220,7 +247,7 @@ std::vector resolve_backtrace(xbt_backtrace_location_t const* loc, if (strcmp("??", line_func) != 0) { auto name = simgrid::xbt::demangle(line_func); XBT_DEBUG("Found static symbol %s at %s", name.get(), line_pos); - result.push_back(simgrid::xbt::string_printf("%s at %s, %p", name.get(), line_pos, loc[i])); + result.push_back(simgrid::xbt::string_printf("%s at %s, %p", name.get(), line_pos, bt.impl_->frames[i])); } else { /* Damn. The symbol is in a dynamic library. Let's get wild */ @@ -316,7 +343,7 @@ std::vector resolve_backtrace(xbt_backtrace_location_t const* loc, if (strcmp("??", line_func)) { auto name = simgrid::xbt::demangle(line_func); XBT_DEBUG("Found dynamic symbol %s at %s", name.get(), line_pos); - result.push_back(simgrid::xbt::string_printf("%s at %s, %p", name.get(), line_pos, loc[i])); + result.push_back(simgrid::xbt::string_printf("%s at %s, %p", name.get(), line_pos, bt.impl_->frames[i])); } else { /* damn, nothing to do here. Let's print the raw address */ XBT_DEBUG("Dynamic symbol not found. Raw address = %s", backtrace_syms[i]); @@ -342,27 +369,10 @@ std::vector resolve_backtrace(xbt_backtrace_location_t const* loc, break; } pclose(pipe); - free(backtrace_syms); + xbt_free(backtrace_syms); +#endif /* ADDR2LINE usable to resolve the backtrace */ return result; } } // namespace xbt } // namespace simgrid -#else /* We must use dummy backtraces because of missing dependencies */ -/* create a backtrace in the given exception */ -size_t xbt_backtrace_current(xbt_backtrace_location_t* loc, size_t count) -{ - return 0; -} - -namespace simgrid { -namespace xbt { - -std::vector resolve_backtrace(xbt_backtrace_location_t const* loc, std::size_t count) -{ - return std::vector(); -} - -} // namespace xbt -} // namespace simgrid -#endif