00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
00105
00106
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 }