From 528fa2ce6be027b5428d122666ffc37706155449 Mon Sep 17 00:00:00 2001 From: Gabriel Corona Date: Fri, 10 Jun 2016 12:14:46 +0200 Subject: [PATCH] Move the backtrace code out of the exception code --- include/xbt/backtrace.h | 71 ++++++ include/xbt/ex.h | 17 +- include/xbt/misc.h | 2 - src/bindings/java/JavaContext.cpp | 1 - src/xbt/backtrace.cpp | 69 ++++++ ...{backtrace_dummy.c => backtrace_dummy.cpp} | 18 +- ...{backtrace_linux.c => backtrace_linux.cpp} | 207 ++++++++---------- src/xbt/ex.cpp | 74 +++---- src/xbt/ex_interface.h | 16 +- src/xbt/log.c | 1 + src/xbt/xbt_log_layout_format.c | 1 - src/xbt/xbt_os_thread.c | 1 - tools/cmake/DefinePackages.cmake | 6 +- 13 files changed, 290 insertions(+), 194 deletions(-) create mode 100644 include/xbt/backtrace.h create mode 100644 src/xbt/backtrace.cpp rename src/xbt/{backtrace_dummy.c => backtrace_dummy.cpp} (73%) rename src/xbt/{backtrace_linux.c => backtrace_linux.cpp} (65%) diff --git a/include/xbt/backtrace.h b/include/xbt/backtrace.h new file mode 100644 index 0000000000..bb2a90597d --- /dev/null +++ b/include/xbt/backtrace.h @@ -0,0 +1,71 @@ +/* Copyright (c) 2005-2019. The SimGrid Team. + * All rights reserved. */ + +/* Copyright (c) 2002-2004 Ralf S. Engelschall */ +/* Copyright (c) 2002-2004 The OSSP Project */ +/* Copyright (c) 2002-2004 Cable & Wireless */ +/* All rights reserved. */ + +/* This code is inspirated from the OSSP version (as retrieved back in 2004)*/ +/* It was heavily modified to fit the SimGrid framework. */ + +/* The OSSP version has the following copyright notice: +** OSSP ex - Exception Handling +** Copyright (c) 2002-2004 Ralf S. Engelschall +** Copyright (c) 2002-2004 The OSSP Project +** Copyright (c) 2002-2004 Cable & Wireless +** +** This file is part of OSSP ex, an exception handling library +** which can be found at http://www.ossp.org/pkg/lib/ex/. +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. + */ + +/* The extensions made for the SimGrid project can either be distributed */ +/* under the same license, or under the LGPL v2.1 */ + +#ifndef SIMGRIX_XBT_BACKTRACE_H +#define SIMGRIX_XBT_BACKTRACE_H + +#include + +#include + +SG_BEGIN_DECL() + +typedef void* xbt_backtrace_location_t; + +/** @brief Shows a backtrace of the current location */ +XBT_PUBLIC(void) xbt_backtrace_display_current(void); + +/** @brief reimplementation of glibc backtrace based directly on gcc library, without implicit malloc */ +XBT_PUBLIC(int) xbt_backtrace_no_malloc(void**bt, int size); + +/** @brief Captures a backtrace for further use */ +XBT_PUBLIC(size_t) xbt_backtrace_current(xbt_backtrace_location_t* loc, size_t count); + +/** @brief Display a previously captured backtrace */ +XBT_PUBLIC(void) xbt_backtrace_display(xbt_backtrace_location_t* loc, size_t count); + +/** @brief Get current backtrace with libunwind */ +XBT_PUBLIC(int) xbt_libunwind_backtrace(void** bt, int size); + +SG_END_DECL() + +#endif diff --git a/include/xbt/ex.h b/include/xbt/ex.h index a7ec2f895d..6a4e505cbd 100644 --- a/include/xbt/ex.h +++ b/include/xbt/ex.h @@ -1,5 +1,3 @@ -/* ex - Exception Handling */ - /* Copyright (c) 2005-2015. The SimGrid Team. * All rights reserved. */ @@ -115,9 +113,7 @@ public: const char *file; /**< Thrown point */ int line; /**< Thrown point */ const char *func; /**< Thrown point */ - /* Backtrace */ - std::vector bt_strings; - std::vector bt; + std::vector bt; /**< Backtrace */ }; #endif @@ -149,17 +145,6 @@ XBT_PUBLIC(void) xbt_throw(char* message, xbt_errcat_t errcat, int value, const /** @brief The display made by an exception that is not catched */ XBT_PUBLIC(void) xbt_ex_display(xbt_ex_t * e); -/** @brief Shows a backtrace of the current location */ -XBT_PUBLIC(void) xbt_backtrace_display_current(void); -/** @brief reimplementation of glibc backtrace based directly on gcc library, without implicit malloc */ -XBT_PUBLIC(int) xbt_backtrace_no_malloc(void**bt, int size); -/** @brief Captures a backtrace for further use */ -XBT_PUBLIC(void) xbt_backtrace_current(xbt_ex_t * e); -/** @brief Display a previously captured backtrace */ -XBT_PUBLIC(void) xbt_backtrace_display(xbt_ex_t * e); -/** @brief Get current backtrace with libunwind */ -XBT_PUBLIC(int) xbt_libunwind_backtrace(void *bt[XBT_BACKTRACE_SIZE], int size); - SG_END_DECL() /** @} */ diff --git a/include/xbt/misc.h b/include/xbt/misc.h index df98adb74c..1d17aa2f07 100644 --- a/include/xbt/misc.h +++ b/include/xbt/misc.h @@ -35,8 +35,6 @@ XBT_PUBLIC(void) sg_version_check(int lib_version_major,int lib_version_minor,in /** Contains all the parameters we got from the command line */ XBT_PUBLIC_DATA(xbt_dynar_t) sg_cmdline; -#define XBT_BACKTRACE_SIZE 10 /* FIXME: better place? Do document */ - /* snprintf related functions */ /** @addtogroup XBT_str * @{ */ diff --git a/src/bindings/java/JavaContext.cpp b/src/bindings/java/JavaContext.cpp index 21af3724e5..c6a3d481ac 100644 --- a/src/bindings/java/JavaContext.cpp +++ b/src/bindings/java/JavaContext.cpp @@ -93,7 +93,6 @@ JavaContext::JavaContext(std::function code, new_exception.func = ex.func; new_exception.pid = ex.pid; new_exception.bt = ex.bt; - new_exception.bt_strings = ex.bt_strings; throw new_exception; } } else { diff --git a/src/xbt/backtrace.cpp b/src/xbt/backtrace.cpp new file mode 100644 index 0000000000..e64eab1add --- /dev/null +++ b/src/xbt/backtrace.cpp @@ -0,0 +1,69 @@ +/* Copyright (c) 2005-2016. The SimGrid Team. + * All rights reserved. */ + +/* Copyright (c) 2002-2004 Ralf S. Engelschall */ +/* Copyright (c) 2002-2004 The OSSP Project */ +/* Copyright (c) 2002-2004 Cable & Wireless */ +/* All rights reserved. */ + +/* This code is inspirated from the OSSP version (as retrieved back in 2004)*/ +/* It was heavily modified to fit the SimGrid framework. */ + +/* The OSSP version has the following copyright notice: +** OSSP ex - Exception Handling +** Copyright (c) 2002-2004 Ralf S. Engelschall +** Copyright (c) 2002-2004 The OSSP Project +** Copyright (c) 2002-2004 Cable & Wireless +** +** This file is part of OSSP ex, an exception handling library +** which can be found at http://www.ossp.org/pkg/lib/ex/. +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. + */ + +/* The extensions made for the SimGrid project can either be distributed */ +/* under the same license, or under the LGPL v2.1 */ + +#include + +#include +#include + +#include "src/internal_config.h" + +extern "C" { + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_backtrace, xbt, "Backtrace"); + +} + +/** \brief show the backtrace of the current point (lovely while debuging) */ +void xbt_backtrace_display_current(void) +{ + 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); +} + +#if HAVE_BACKTRACE && HAVE_EXECINFO_H && HAVE_POPEN && defined(ADDR2LINE) +# include "src/xbt/backtrace_linux.cpp" +#else +# include "src/xbt/backtrace_dummy.cpp" +#endif diff --git a/src/xbt/backtrace_dummy.c b/src/xbt/backtrace_dummy.cpp similarity index 73% rename from src/xbt/backtrace_dummy.c rename to src/xbt/backtrace_dummy.cpp index 65a4fdaf83..8d5c57aab1 100644 --- a/src/xbt/backtrace_dummy.c +++ b/src/xbt/backtrace_dummy.cpp @@ -19,15 +19,23 @@ void xbt_backtrace_postexit(void) } /* create a backtrace in the given exception */ -void xbt_backtrace_current(xbt_ex_t * e) +size_t xbt_backtrace_current(xbt_backtrace_location_t* loc, size_t count) { + return 0; +} + +int xbt_backtrace_no_malloc(void **array, int size) { + return 0; } -/* prepare a backtrace for display */ -void xbt_ex_setup_backtrace(xbt_ex_t * e) +namespace simgrid { +namespace xbt { + +std::vector resolveBacktrace( + xbt_backtrace_location_t* loc, std::size_t count) { + return [};] } -int xbt_backtrace_no_malloc(void **array, int size) { - return 0; } +} \ No newline at end of file diff --git a/src/xbt/backtrace_linux.c b/src/xbt/backtrace_linux.cpp similarity index 65% rename from src/xbt/backtrace_linux.c rename to src/xbt/backtrace_linux.cpp index 741c28f025..97665f5af3 100644 --- a/src/xbt/backtrace_linux.c +++ b/src/xbt/backtrace_linux.cpp @@ -7,12 +7,16 @@ /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ +#include + #include #include #include /* This file is to be included in ex.cpp, so the following headers are not mandatory, but it's to make sure that eclipse see them too */ +#include #include "xbt/ex.h" +#include "src/xbt/ex_interface.h" #include "xbt/log.h" #include "xbt/str.h" #include "xbt/module.h" /* xbt_binary_name */ @@ -86,58 +90,45 @@ int xbt_backtrace_no_malloc(void **array, int size) { return arg.cnt != -1 ? arg.cnt : 0; } -void xbt_backtrace_current(xbt_ex_t * e) +size_t xbt_backtrace_current(xbt_backtrace_location_t* loc, std::size_t count) { - void* bt[XBT_BACKTRACE_SIZE]; - std::size_t used = backtrace((void **) bt, XBT_BACKTRACE_SIZE); - e->bt.assign(bt, bt + used); + std::size_t used = backtrace(loc, count); if (used == 0) { - fprintf(stderr, "The backtrace() function failed, which probably means that the memory is exhausted. Here is a crude dump of the exception that I was trying to build:"); - fprintf(stderr, "%s(%d) [%s:%d] %s", - e->procname.c_str(), e->pid, e->file, e->line, e->what()); - fprintf(stderr, "Bailing out now since there is nothing I can do without a decent amount of memory. Please go fix the memleaks\n"); - exit(1); + 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; } -void xbt_ex_setup_backtrace(xbt_ex_t * e) //FIXME: This code could be greatly improved/simplifyied with http://cairo.sourcearchive.com/documentation/1.9.4/backtrace-symbols_8c-source.html -{ - /* to get the backtrace from the libc */ - char **backtrace_syms; - - /* To build the commandline of addr2line */ - char *cmd, *curr; - - /* to extract the addresses from the backtrace */ - char **addrs; - char buff[256]; - - /* To read the output of addr2line */ - FILE *pipe; - char line_func[1024], line_pos[1024]; +namespace simgrid { +namespace xbt { - /* size (in char) of pointers on this arch */ - int addr_len = 0; +//FIXME: This code could be greatly improved/simplifyied with +// http://cairo.sourcearchive.com/documentation/1.9.4/backtrace-symbols_8c-source.html +std::vector resolveBacktrace( + xbt_backtrace_location_t* loc, std::size_t count) +{ + std::vector result; /* To search for the right executable path when not trivial */ struct stat stat_buf; - char *binary_name = NULL; - - xbt_assert(e, "Backtrace not setup yet, cannot set it up for display"); - - e->bt_strings.clear(); - if (xbt_binary_name == NULL) /* no binary name, nothing to do */ - return; + /* no binary name, nothing to do */ + if (xbt_binary_name == NULL) + return result; - if (e->bt.empty()) - return; + if (count == 0) + return result; - /* ignore first one, which is xbt_backtrace_current() */ - e->bt.erase(e->bt.begin()); + // Drop the first one: + loc++; count--; - backtrace_syms = backtrace_symbols(e->bt.data(), e->bt.size()); + char** backtrace_syms = backtrace_symbols(loc, count); + // Find the binary name: + std::string binary_name; /* build the commandline */ if (stat(xbt_binary_name, &stat_buf)) { /* Damn. binary not in current dir. We'll have to dig the PATH to find it */ @@ -148,105 +139,100 @@ void xbt_ex_setup_backtrace(xbt_ex_t * e) //FIXME: This code could be greatly im char *data; xbt_dynar_foreach(path, cpt, data) { - free(binary_name); - binary_name = bprintf("%s/%s", data, xbt_binary_name); - if (!stat(binary_name, &stat_buf)) { + binary_name = simgrid::xbt::string_printf("%s/%s", data, xbt_binary_name); + if (!stat(binary_name.c_str(), &stat_buf)) { /* Found. */ - XBT_DEBUG("Looked in the PATH for the binary. Found %s", binary_name); + XBT_DEBUG("Looked in the PATH for the binary. Found %s", binary_name.c_str()); break; } } xbt_dynar_free(&path); - if (stat(binary_name, &stat_buf)) { + if (stat(binary_name.c_str(), &stat_buf)) { /* not found */ - char* str = bprintf("(binary '%s' not found in the PATH)", xbt_binary_name); - e->bt_strings = { str }; - free(str); + result = { simgrid::xbt::string_printf( + "(binary '%s' not found in the PATH)", xbt_binary_name) }; free(backtrace_syms); - return; + return result; } break; } } } else { - binary_name = xbt_strdup(xbt_binary_name); + binary_name = xbt_binary_name; } - int strsize = strlen(ADDR2LINE) + 25 + strlen(binary_name) + 32 * e->bt_strings.size(); - cmd = curr = xbt_new(char, strsize); - curr += snprintf(curr,strsize, "%s -f -e %s ", ADDR2LINE, binary_name); - free(binary_name); - - addrs = xbt_new(char *, e->bt.size()); - for (std::size_t i = 0; i < e->bt.size(); i++) { - char *p; + // 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++) { /* retrieve this address */ XBT_DEBUG("Retrieving address number %zd from '%s'", i, backtrace_syms[i]); + char buff[256]; snprintf(buff, 256, "%s", strchr(backtrace_syms[i], '[') + 1); - p = strchr(buff, ']'); + char* p = strchr(buff, ']'); *p = '\0'; if (strcmp(buff, "(nil)")) - addrs[i] = xbt_strdup(buff); + addrs[i] = buff; else - addrs[i] = xbt_strdup("0x0"); - XBT_DEBUG("Set up a new address: %zd, '%s'(%p)", i, addrs[i], addrs[i]); - + addrs[i] = "0x0"; + XBT_DEBUG("Set up a new address: %zd, '%s'", i, addrs[i].c_str()); /* Add it to the command line args */ - curr += snprintf(curr,strsize, "%s ", addrs[i]); + stream << addrs[i] << ' '; } - addr_len = strlen(addrs[0]); + binary_name.clear(); + std::string cmd = stream.str(); - /* parse the output and build a new backtrace */ - e->bt_strings.resize(e->bt.size()); + /* size (in char) of pointers on this arch */ + int addr_len = addrs[0].size(); - XBT_VERB("Fire a first command: '%s'", cmd); - pipe = popen(cmd, "r"); + XBT_VERB("Fire a first command: '%s'", cmd.c_str()); + FILE* pipe = popen(cmd.c_str(), "r"); if (!pipe) { xbt_die("Cannot fork addr2line to display the backtrace"); } - for (std::size_t i = 0; i < e->bt.size(); i++) { - XBT_DEBUG("Looking for symbol %zd, addr = '%s'", i, addrs[i]); + /* To read the output of addr2line */ + char line_func[1024], line_pos[1024]; + for (std::size_t i = 0; i < count; i++) { + XBT_DEBUG("Looking for symbol %zd, addr = '%s'", i, addrs[i].c_str()); if (fgets(line_func, 1024, pipe)) { line_func[strlen(line_func) - 1] = '\0'; } else { - XBT_VERB("Cannot run fgets to look for symbol %zd, addr %s", i, addrs[i]); + XBT_VERB("Cannot run fgets to look for symbol %zd, addr %s", i, addrs[i].c_str()); strncpy(line_func, "???",3); } if (fgets(line_pos, 1024, pipe)) { line_pos[strlen(line_pos) - 1] = '\0'; } else { - XBT_VERB("Cannot run fgets to look for symbol %zd, addr %s", i, addrs[i]); + XBT_VERB("Cannot run fgets to look for symbol %zd, addr %s", i, addrs[i].c_str()); strncpy(line_pos, backtrace_syms[i],1024); } if (strcmp("??", line_func) != 0) { XBT_DEBUG("Found static symbol %s() at %s", line_func, line_pos); - char* s = bprintf("** In %s() at %s", line_func, line_pos); - e->bt_strings[i] = s; - free(s); + result.push_back(simgrid::xbt::string_printf( + "%s() at %s", line_func, line_pos + )); } else { /* Damn. The symbol is in a dynamic library. Let's get wild */ - char *maps_name; - FILE *maps; - char maps_buff[512]; - long int addr, offset = 0; + char maps_buff[512]; + long int offset = 0; char *p, *p2; - - char *subcmd; - FILE *subpipe; int found = 0; /* let's look for the offset of this library in our addressing space */ - maps_name = bprintf("/proc/%d/maps", (int) getpid()); - maps = fopen(maps_name, "r"); + char* maps_name = bprintf("/proc/%d/maps", (int) getpid()); + FILE* maps = fopen(maps_name, "r"); - addr = strtol(addrs[i], &p, 16); + long int addr = strtol(addrs[i].c_str(), &p, 16); if (*p != '\0') { - XBT_CRITICAL("Cannot parse backtrace address '%s' (addr=%#lx)", addrs[i], addr); + XBT_CRITICAL("Cannot parse backtrace address '%s' (addr=%#lx)", + addrs[i].c_str(), addr); } - XBT_DEBUG("addr=%s (as string) =%#lx (as number)", addrs[i], addr); + XBT_DEBUG("addr=%s (as string) =%#lx (as number)", + addrs[i].c_str(), addr); while (!found) { long int first, last; @@ -271,14 +257,12 @@ void xbt_ex_setup_backtrace(xbt_ex_t * e) //FIXME: This code could be greatly im } fclose(maps); free(maps_name); - free(addrs[i]); + addrs[i].clear(); if (!found) { XBT_VERB("Problem while reading the maps file. Following backtrace will be mangled."); XBT_DEBUG("No dynamic. Static symbol: %s", backtrace_syms[i]); - char* s = bprintf("** In ?? (%s)", backtrace_syms[i]); - e->bt_strings[i] = s; - free(s); + result.push_back(simgrid::xbt::string_printf("?? (%s)", backtrace_syms[i])); continue; } @@ -286,8 +270,8 @@ void xbt_ex_setup_backtrace(xbt_ex_t * e) //FIXME: This code could be greatly im We now need to substract this from the address we got from backtrace. */ - addrs[i] = bprintf("0x%0*lx", addr_len - 2, addr - offset); - XBT_DEBUG("offset=%#lx new addr=%s", offset, addrs[i]); + addrs[i] = simgrid::xbt::string_printf("0x%0*lx", addr_len - 2, addr - offset); + XBT_DEBUG("offset=%#lx new addr=%s", offset, addrs[i].c_str()); /* Got it. We have our new address. Let's get the library path and we are set */ p = xbt_strdup(backtrace_syms[i]); @@ -304,10 +288,10 @@ void xbt_ex_setup_backtrace(xbt_ex_t * e) //FIXME: This code could be greatly im *p2 = '\0'; /* Here we go, fire an addr2line up */ - subcmd = bprintf("%s -f -e %s %s", ADDR2LINE, p, addrs[i]); + char* subcmd = bprintf("%s -f -e %s %s", ADDR2LINE, p, addrs[i].c_str()); free(p); XBT_VERB("Fire a new command: '%s'", subcmd); - subpipe = popen(subcmd, "r"); + FILE* subpipe = popen(subcmd, "r"); if (!subpipe) { xbt_die("Cannot fork addr2line to display the backtrace"); } @@ -330,44 +314,33 @@ void xbt_ex_setup_backtrace(xbt_ex_t * e) //FIXME: This code could be greatly im /* check whether the trick worked */ if (strcmp("??", line_func)) { XBT_DEBUG("Found dynamic symbol %s() at %s", line_func, line_pos); - char* s = bprintf("** In %s() at %s", line_func, line_pos); - e->bt_strings[i] = s; - free(s); + result.push_back(simgrid::xbt::string_printf( + "%s() at %s", line_func, line_pos)); } else { /* damn, nothing to do here. Let's print the raw address */ XBT_DEBUG("Dynamic symbol not found. Raw address = %s", backtrace_syms[i]); - char* s = bprintf("** In ?? at %s", backtrace_syms[i]); - e->bt_strings[i] = s; - free(s); + result.push_back(simgrid::xbt::string_printf( + "?? at %s", backtrace_syms[i])); } } - free(addrs[i]); + addrs[i].clear(); /* Mask the bottom of the stack */ if (!strncmp("main", line_func, strlen("main")) || !strncmp("xbt_thread_context_wrapper", line_func, strlen("xbt_thread_context_wrapper")) - || !strncmp("smx_ctx_sysv_wrapper", line_func, strlen("smx_ctx_sysv_wrapper"))) { - - for (std::size_t j = i + 1; j < e->bt.size(); j++) - free(addrs[j]); - - if (!strncmp - ("xbt_thread_context_wrapper", line_func, strlen("xbt_thread_context_wrapper"))) { - e->bt_strings.push_back("** (in a separate thread)"); - } else { - e->bt_strings.push_back(""); - } - - } + || !strncmp("smx_ctx_sysv_wrapper", line_func, strlen("smx_ctx_sysv_wrapper"))) + break; } pclose(pipe); - free(addrs); free(backtrace_syms); - free(cmd); + return result; +} + +} } #if HAVE_MC -int xbt_libunwind_backtrace(void* bt[XBT_BACKTRACE_SIZE], int size){ +int xbt_libunwind_backtrace(void** bt, int size){ int i = 0; for(i=0; i < size; i++) bt[i] = NULL; diff --git a/src/xbt/ex.cpp b/src/xbt/ex.cpp index 821d1acbdf..2fd2e3b2a2 100644 --- a/src/xbt/ex.cpp +++ b/src/xbt/ex.cpp @@ -47,6 +47,7 @@ #include "src/internal_config.h" /* execinfo when available */ #include "xbt/ex.h" +#include "xbt/backtrace.h" #include "xbt/str.h" #include "xbt/synchro_core.h" #include "src/xbt_modinter.h" /* backtrace initialization headers */ @@ -61,43 +62,26 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_ex, xbt, "Exception mechanism"); xbt_ex::~xbt_ex() {} /* Change raw libc symbols to file names and line numbers */ -void xbt_ex_setup_backtrace(xbt_ex_t * e); +void xbt_setup_backtrace(xbt_backtrace_location_t** loc, std::size_t count, + char** res); -void xbt_backtrace_display(xbt_ex_t * e) +void xbt_backtrace_display(xbt_backtrace_location_t* loc, std::size_t count) { - // TODO, backtrace -#if 0 - xbt_ex_setup_backtrace(e); - #ifdef HAVE_BACKTRACE - if (e->bt_strings.empty()) { + std::vector backtrace = + simgrid::xbt::resolveBacktrace(loc, count); + if (backtrace.empty()) { fprintf(stderr, "(backtrace not set)\n"); - } else { - fprintf(stderr, "Backtrace (displayed in process %s):\n", SIMIX_process_self_get_name()); - for (std::string const& s : e->bt_strings) /* no need to display "xbt_backtrace_display" */ - fprintf(stderr, "---> %s\n", s.c_str() + 4); + return; } - xbt_ex_free(*e); + fprintf(stderr, "Backtrace (displayed in process %s):\n", SIMIX_process_self_get_name()); + for (std::string const& s : backtrace) + fprintf(stderr, "---> %s\n", s.c_str()); #else XBT_ERROR("No backtrace on this arch"); #endif - #endif -} - -/** \brief show the backtrace of the current point (lovely while debuging) */ -void xbt_backtrace_display_current(void) -{ - xbt_ex_t e; - xbt_backtrace_current(&e); - xbt_backtrace_display(&e); } -#if HAVE_BACKTRACE && HAVE_EXECINFO_H && HAVE_POPEN && defined(ADDR2LINE) -# include "src/xbt/backtrace_linux.c" -#else -# include "src/xbt/backtrace_dummy.c" -#endif - void xbt_throw( char* message, xbt_errcat_t errcat, int value, const char* file, int line, const char* func) @@ -121,7 +105,7 @@ void xbt_ex_display(xbt_ex_t * e) if (e->pid != xbt_getpid()) thrower = bprintf(" on process %d",e->pid); - fprintf(stderr, "** SimGrid: UNCAUGHT EXCEPTION received on %s(%d): category: %s; value: %d\n" + std::fprintf(stderr, "** SimGrid: UNCAUGHT EXCEPTION received on %s(%d): category: %s; value: %d\n" "** %s\n" "** Thrown by %s()%s\n", xbt_binary_name, xbt_getpid(), xbt_ex_catname(e->category), e->value, e->what(), @@ -134,11 +118,11 @@ void xbt_ex_display(xbt_ex_t * e) return; /* Not started yet or already closing. Trying to generate a backtrace would probably fail */ } - if (e->bt_strings.empty()) - xbt_ex_setup_backtrace(e); + std::vector backtrace = simgrid::xbt::resolveBacktrace( + e->bt.data(), e->bt.size()); #ifdef HAVE_BACKTRACE - if (!e->bt.empty() && !e->bt_strings.empty()) { + if (!backtrace.empty()) { /* We have everything to build neat backtraces */ int cutpath = 0; try { // We don't want to have an exception while checking how to deal with the one we already have, do we? @@ -148,35 +132,31 @@ void xbt_ex_display(xbt_ex_t * e) // Nothing to do } - fprintf(stderr, "\n"); - for (std::string const& s : e->bt_strings) { + std::fprintf(stderr, "\n"); + for (std::string const& s : backtrace) { + // TODO, move this logic into solveBacktrace if (cutpath) { - // TODO, backtrace - /* - char* p = e->bt_strings[i]; + // TODO, simplify this + char* p = xbt_strdup(s.c_str()); xbt_str_rtrim(p, ":0123456789"); char* filename = strrchr(p, '/')+1; char* end_of_message = strrchr(p, ' '); - int length = strlen(p)-strlen(end_of_message); - char* dest = malloc(length); - - memcpy(dest, &p[0], length); + char* dest = (char*) std::malloc(length); + std::memcpy(dest, &p[0], length); dest[length] = 0; - - fprintf(stderr, "%s %s\n", dest, filename); - - free(dest); - */ + std::fprintf(stderr, "%s %s\n", dest, filename); + std::free(dest); + std::free(p); } else { - fprintf(stderr, "%s\n", s.c_str()); + std::fprintf(stderr, "%s\n", s.c_str()); } } } else #endif - fprintf(stderr, "\n" + std::fprintf(stderr, "\n" "** In %s() at %s:%d\n" "** (no backtrace available)\n", e->func, e->file, e->line); } diff --git a/src/xbt/ex_interface.h b/src/xbt/ex_interface.h index cef5284762..cbff4ea2d0 100644 --- a/src/xbt/ex_interface.h +++ b/src/xbt/ex_interface.h @@ -11,10 +11,22 @@ #ifndef _XBT_EX_INTERFACE_H_ #define _XBT_EX_INTERFACE_H_ +#include + +#include +#include + #include "xbt/base.h" -#include "xbt/ex.h" +#include "xbt/backtrace.h" + +namespace simgrid { +namespace xbt { /* Change raw libc symbols to file names and line numbers */ -XBT_PRIVATE void xbt_ex_setup_backtrace(xbt_ex_t * e); +XBT_PUBLIC(std::vector) resolveBacktrace( + xbt_backtrace_location_t* loc, std::size_t count); + +} +} #endif /* _XBT_EX_INTERFACE_H_ */ diff --git a/src/xbt/log.c b/src/xbt/log.c index a591421faf..23482c3fb0 100644 --- a/src/xbt/log.c +++ b/src/xbt/log.c @@ -106,6 +106,7 @@ static void xbt_log_connect_categories(void) XBT_LOG_CONNECT(xbt_dict_elm); XBT_LOG_CONNECT(xbt_dyn); XBT_LOG_CONNECT(xbt_ex); + XBT_LOG_CONNECT(xbt_backtrace); XBT_LOG_CONNECT(xbt_fifo); XBT_LOG_CONNECT(xbt_graph); XBT_LOG_CONNECT(xbt_heap); diff --git a/src/xbt/xbt_log_layout_format.c b/src/xbt/xbt_log_layout_format.c index 884f6379f0..594f001f50 100644 --- a/src/xbt/xbt_log_layout_format.c +++ b/src/xbt/xbt_log_layout_format.c @@ -8,7 +8,6 @@ #include "src/internal_config.h" /* execinfo when available */ #include "xbt/synchro_core.h" /* xbt_thread_self_name */ -#include "src/xbt/ex_interface.h" #include "xbt/sysdep.h" #include "xbt/strbuff.h" #include "src/xbt/log_private.h" diff --git a/src/xbt/xbt_os_thread.c b/src/xbt/xbt_os_thread.c index 60e5e13a93..c66cbfc652 100644 --- a/src/xbt/xbt_os_thread.c +++ b/src/xbt/xbt_os_thread.c @@ -37,7 +37,6 @@ #include "xbt/sysdep.h" #include "xbt/ex.h" -#include "src/xbt/ex_interface.h" /* We play crude games with exceptions */ #include "src/internal_config.h" #include "xbt/xbt_os_time.h" /* Portable time facilities */ #include "xbt/xbt_os_thread.h" /* This module */ diff --git a/tools/cmake/DefinePackages.cmake b/tools/cmake/DefinePackages.cmake index 3bb436dff1..87ef125abe 100644 --- a/tools/cmake/DefinePackages.cmake +++ b/tools/cmake/DefinePackages.cmake @@ -90,8 +90,8 @@ set(EXTRA_DIST src/xbt/automaton/parserPromela.tab.cacc src/xbt/automaton/parserPromela.tab.hacc src/xbt/automaton/parserPromela.yacc - src/xbt/backtrace_dummy.c - src/xbt/backtrace_linux.c + src/xbt/backtrace_dummy.cpp + src/xbt/backtrace_linux.cpp src/xbt/dict_private.h src/xbt/ex_interface.h src/xbt/fifo_private.h @@ -244,6 +244,7 @@ set(XBT_SRC src/xbt/RngStream.c src/xbt/automaton/automaton.c src/xbt/automaton/automatonparse_promela.c + src/xbt/backtrace.cpp src/xbt/config.cpp src/xbt/cunit.cpp src/xbt/dict.cpp @@ -666,6 +667,7 @@ set(headers_to_install include/xbt/dynar.h include/xbt/dynar.hpp include/xbt/ex.h + include/xbt/backtrace.h include/xbt/fifo.h include/xbt/file.h include/xbt/function_types.h -- 2.20.1