$search
00001 /* 00002 * Copyright (C) 2009, Willow Garage, Inc. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions are met: 00006 * * Redistributions of source code must retain the above copyright notice, 00007 * this list of conditions and the following disclaimer. 00008 * * Redistributions in binary form must reproduce the above copyright 00009 * notice, this list of conditions and the following disclaimer in the 00010 * documentation and/or other materials provided with the distribution. 00011 * * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its 00012 * contributors may be used to endorse or promote products derived from 00013 * this software without specific prior written permission. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00016 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00017 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00019 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00020 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00021 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00023 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00024 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00025 * POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 #include "ros/debug.h" 00029 00030 #if defined(HAVE_EXECINFO_H) 00031 #include <execinfo.h> 00032 #endif 00033 00034 #if defined(HAVE_CXXABI_H) 00035 #include <cxxabi.h> 00036 #endif 00037 00038 #include <cstdlib> 00039 #include <cstdio> 00040 #include <sstream> 00041 00042 namespace ros 00043 { 00044 namespace debug 00045 { 00046 00047 void getBacktrace(V_void& addresses) 00048 { 00049 #if HAVE_GLIBC_BACKTRACE 00050 void *array[64]; 00051 00052 size_t size = backtrace(array, 64); 00053 for (size_t i = 1; i < size; i++) 00054 { 00055 addresses.push_back(array[i]); 00056 } 00057 #endif 00058 } 00059 00060 void translateAddresses(const V_void& addresses, V_string& lines) 00061 { 00062 #if HAVE_GLIBC_BACKTRACE 00063 if (addresses.empty()) 00064 { 00065 return; 00066 } 00067 00068 size_t size = addresses.size(); 00069 char **strings = backtrace_symbols(&addresses.front(), size); 00070 00071 for (size_t i = 0; i < size; ++i) 00072 { 00073 lines.push_back(strings[i]); 00074 } 00075 00076 free(strings); 00077 #endif 00078 } 00079 00080 std::string demangleName(const std::string& name) 00081 { 00082 #if HAVE_CXXABI_H 00083 int status; 00084 char* demangled = abi::__cxa_demangle(name.c_str(), 0, 0, &status); 00085 std::string out; 00086 if (demangled) 00087 { 00088 out = demangled; 00089 free(demangled); 00090 } 00091 else 00092 { 00093 out = name; 00094 } 00095 00096 return out; 00097 #else 00098 return name; 00099 #endif 00100 } 00101 00102 std::string demangleBacktraceLine(const std::string& line) 00103 { 00104 // backtrace_symbols outputs in the form: 00105 // executable(function+offset) [address] 00106 // We want everything between ( and + to send to demangleName() 00107 size_t paren_pos = line.find('('); 00108 size_t plus_pos = line.find('+'); 00109 if (paren_pos == std::string::npos || plus_pos == std::string::npos) 00110 { 00111 return line; 00112 } 00113 00114 std::string name(line, paren_pos + 1, plus_pos - paren_pos - 1); 00115 return line.substr(0, paren_pos + 1) + demangleName(name) + line.substr(plus_pos); 00116 } 00117 00118 void demangleBacktrace(const V_string& lines, V_string& demangled) 00119 { 00120 V_string::const_iterator it = lines.begin(); 00121 V_string::const_iterator end = lines.end(); 00122 for (; it != end; ++it) 00123 { 00124 demangled.push_back(demangleBacktraceLine(*it)); 00125 } 00126 } 00127 00128 std::string backtraceToString(const V_void& addresses) 00129 { 00130 V_string lines, demangled; 00131 translateAddresses(addresses, lines); 00132 demangleBacktrace(lines, demangled); 00133 00134 std::stringstream ss; 00135 V_string::const_iterator it = demangled.begin(); 00136 V_string::const_iterator end = demangled.end(); 00137 for (; it != end; ++it) 00138 { 00139 ss << *it << std::endl; 00140 } 00141 00142 return ss.str(); 00143 } 00144 00145 std::string getBacktrace() 00146 { 00147 V_void addresses; 00148 getBacktrace(addresses); 00149 return backtraceToString(addresses); 00150 } 00151 00152 } 00153 00154 }