Add zypp::dumpBacktrace to dump current stack trace to a stream.
authorMichael Andres <ma@suse.de>
Wed, 31 Oct 2012 14:00:14 +0000 (15:00 +0100)
committerMichael Andres <ma@suse.de>
Wed, 31 Oct 2012 14:00:14 +0000 (15:00 +0100)
CMakeLists.txt
zypp/CMakeLists.txt
zypp/base/Backtrace.cc [new file with mode: 0644]
zypp/base/Backtrace.h [new file with mode: 0644]

index 587f154..dd2fc2c 100644 (file)
@@ -29,8 +29,8 @@ include(CheckCXXCompilerFlag)
 CHECK_C_COMPILER_FLAG("-Werror=format-security" CC_FORMAT_SECURITY)
 CHECK_CXX_COMPILER_FLAG("-Werror=format-security" CXX_FORMAT_SECURITY)
 
-SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden -fno-strict-aliasing -fPIC -g -Wall -Woverloaded-virtual -Wnon-virtual-dtor -Wl,-as-needed -std=c++0x" )
-SET( CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -fno-strict-aliasing -fPIC -g -Wall -Wl,-as-needed" )
+SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden -fno-strict-aliasing -fPIC -g -rdynamic -Wall -Woverloaded-virtual -Wnon-virtual-dtor -Wl,-as-needed -std=c++0x" )
+SET( CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -fno-strict-aliasing -fPIC -g -rdynamic -Wall -Wl,-as-needed" )
 
 set( CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3" )
 set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O3" )
index cac4aee..fe78e42 100644 (file)
@@ -191,6 +191,7 @@ INSTALL(  FILES ${zypp_HEADERS} DESTINATION "${CMAKE_INSTALL_PREFIX}/include/zyp
 
 SET( zypp_base_SRCS
   base/InterProcessMutex.cc
+  base/Backtrace.cc
   base/SerialNumber.cc
   base/Random.cc
   base/Measure.cc
@@ -215,6 +216,7 @@ SET( zypp_base_SRCS
 
 SET( zypp_base_HEADERS
   base/InterProcessMutex.h
+  base/Backtrace.h
   base/Collector.h
   base/SerialNumber.h
   base/Easy.h
diff --git a/zypp/base/Backtrace.cc b/zypp/base/Backtrace.cc
new file mode 100644 (file)
index 0000000..6bee0cf
--- /dev/null
@@ -0,0 +1,100 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/base/Backtrace.cc
+ */
+#include <execinfo.h>
+#include <cxxabi.h>
+
+#include <iostream>
+#include "zypp/base/LogTools.h"
+#include "zypp/base/String.h"
+#include "zypp/base/Backtrace.h"
+
+using std::endl;
+
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{
+  std::ostream & dumpBacktrace( std::ostream & stream_r )
+  {
+    // get void*'s for all entries on the stack
+    static const size_t arraySize = 50;
+    void *array[arraySize];
+    size_t size = ::backtrace( array, arraySize );
+
+    // print out all the frames to stderr
+    char ** messages = ::backtrace_symbols( array, size );
+    if ( messages )
+    {
+      static const size_t first = 1;
+      for ( size_t i = first; i < size; ++i )
+      {
+       char * mangled_name = 0;
+       char * offset_begin = 0;
+       char * offset_end = 0;
+
+       // find parantheses and +address offset surrounding mangled name
+       for ( char * p = messages[i]; *p; ++p )
+       {
+         if ( *p == '(' )
+         {
+           mangled_name = p;
+         }
+         else if ( *p == '+' )
+         {
+           offset_begin = p;
+         }
+         else if ( *p == ')' )
+         {
+           offset_end = p;
+           break;
+         }
+       }
+
+       if ( i > first )
+         stream_r << endl;
+
+       // if the line could be processed, attempt to demangle the symbol
+       if ( mangled_name && offset_begin && offset_end && mangled_name < offset_begin )
+       {
+         *mangled_name++ = '\0';
+         *offset_begin++ = '\0';
+         *offset_end++ = '\0';
+
+         int status;
+         char * real_name = ::abi::__cxa_demangle( mangled_name, 0, 0, &status );
+
+         // if demangling is successful, output the demangled function name
+         if ( status == 0 )
+         {
+           stream_r << "[bt]: (" << i << ") " << messages[i] << " : "
+           << real_name << "+" << offset_begin << offset_end;
+
+         }
+         // otherwise, output the mangled function name
+         else
+         {
+           stream_r << "[bt]: (" << i << ") " << messages[i] << " : "
+           << mangled_name << "+" << offset_begin << offset_end;
+         }
+         ::free( real_name );
+       }
+       else
+       {
+         // otherwise, print the whole line
+         stream_r << "[bt]: (" << i << ") " << messages[i];
+       }
+      }
+      ::free( messages );
+    }
+    return stream_r;
+  }
+
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
diff --git a/zypp/base/Backtrace.h b/zypp/base/Backtrace.h
new file mode 100644 (file)
index 0000000..b94a9ef
--- /dev/null
@@ -0,0 +1,36 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/base/Backtrace.h
+ */
+#ifndef ZYPP_BASE_BACKTRACE_H
+#define ZYPP_BASE_BACKTRACE_H
+
+#include <iosfwd>
+#include <string>
+
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{
+
+  /** Dump current stack trace to a stream.
+   * Thanks to http://stackoverflow.com/questions/77005.
+    * \code
+   * #include <iostream>
+   * std::cerr << zypp::dumpBacktrace << std::endl;
+   * \endcode
+   * \code
+   * #include <zypp/base/String.h>
+   * std::string trace( str::Str() << zypp::dumpBacktrace );
+   * \endcode
+   */
+  std::ostream & dumpBacktrace( std::ostream & stream_r );
+
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
+#endif // ZYPP_BASE_BACKTRACE_H