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


cpp_common
Author(s): John Faust
autogenerated on Sat Jun 8 2019 20:30:20