libzypp  17.3.0
Backtrace.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
11 #include <execinfo.h>
12 #include <cxxabi.h>
13 
14 #include <iostream>
15 #include "zypp/base/LogTools.h"
16 #include "zypp/base/String.h"
17 #include "zypp/base/Backtrace.h"
18 
19 using std::endl;
20 
22 namespace zypp
23 {
24  std::ostream & dumpBacktrace( std::ostream & stream_r )
25  {
26  // get void*'s for all entries on the stack
27  static const size_t arraySize = 50;
28  void *array[arraySize];
29  size_t size = ::backtrace( array, arraySize );
30 
31  // Print out all frames to stderr. Separate sigsegvHandler stack
32  // [dumpBacktrace][sigsegvHandler][libc throwing] from actual
33  // code stack.
34  char ** messages = ::backtrace_symbols( array, size );
35  if ( messages )
36  {
37  static const size_t handlerStack = 3; // [dumpBacktrace][sigsegvHandler][libc throwing]
38  static const size_t first = 0;
39  for ( size_t i = first; i < size; ++i )
40  {
41  char * mangled_name = 0;
42  char * offset_begin = 0;
43  char * offset_end = 0;
44 
45  // find parentheses and +address offset surrounding mangled name
46  for ( char * p = messages[i]; *p; ++p )
47  {
48  if ( *p == '(' )
49  {
50  mangled_name = p;
51  }
52  else if ( *p == '+' )
53  {
54  offset_begin = p;
55  }
56  else if ( *p == ')' )
57  {
58  offset_end = p;
59  break;
60  }
61  }
62 
63  int btLevel = i-handlerStack; // negative level in sigsegvHandler
64  if ( i > first )
65  {
66  stream_r << endl;
67  if ( btLevel == 0 )
68  stream_r << "vvvvvvvvvv----------------------------------------" << endl;
69  }
70  stream_r << "[" << (btLevel<0 ?"hd":"bt") << "]: (" << btLevel << ") ";
71 
72  // if the line could be processed, attempt to demangle the symbol
73  if ( mangled_name && offset_begin && offset_end && mangled_name < offset_begin )
74  {
75  *mangled_name++ = '\0';
76  *offset_begin++ = '\0';
77  *offset_end++ = '\0';
78 
79  int status;
80  char * real_name = ::abi::__cxa_demangle( mangled_name, 0, 0, &status );
81 
82  // if demangling is successful, output the demangled function name
83  if ( status == 0 )
84  {
85  stream_r << messages[i] << " : " << real_name << "+" << offset_begin << offset_end;
86  }
87  // otherwise, output the mangled function name
88  else
89  {
90  stream_r << messages[i] << " : " << mangled_name << "+" << offset_begin << offset_end;
91  }
92  ::free( real_name );
93  }
94  else
95  {
96  // otherwise, print the whole line
97  stream_r << messages[i];
98  }
99  }
100  ::free( messages );
101  }
102  return stream_r;
103  }
104 
105 } // namespace zypp
std::ostream & dumpBacktrace(std::ostream &stream_r)
Dump current stack trace to a stream.
Definition: Backtrace.cc:24
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
#define arraySize(A)
Definition: Easy.h:41