Go to the documentation of this file.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 }