Build system improvements
[ustl.git] / bktrace.cc
blob718c8f4507bab3d8e76cde1803d55aa633b3fecd
1 // This file is part of the ustl library, an STL implementation.
2 //
3 // Copyright (C) 2006 by Mike Sharov <msharov@users.sourceforge.net>
4 // This file is free software, distributed under the MIT License.
5 //
6 // bktrace.cc
7 //
9 #include "bktrace.h"
10 #include "sostream.h"
11 #include "mistream.h"
12 #if linux && __GNUC__
13 #include <execinfo.h>
14 #else
15 static inline int backtrace (void**, int) { return (0); }
16 static inline char** backtrace_symbols (void* const*, int) { return (NULL); }
17 #endif
18 #if __GNUC__ >= 3
19 #include <cxxabi.h>
20 #endif
22 namespace ustl {
24 /// Default constructor. The backtrace is obtained here.
25 CBacktrace::CBacktrace (void) throw()
26 : m_Symbols (NULL),
27 m_nFrames (0),
28 m_SymbolsSize (0)
30 m_nFrames = backtrace (VectorBlock (m_Addresses));
31 GetSymbols();
34 /// Copy constructor.
35 CBacktrace::CBacktrace (const CBacktrace& v) throw()
36 : m_Symbols (NULL),
37 m_nFrames (0),
38 m_SymbolsSize (0)
40 operator= (v);
43 /// Copy operator.
44 const CBacktrace& CBacktrace::operator= (const CBacktrace& v) throw()
46 memcpy (m_Addresses, v.m_Addresses, sizeof(m_Addresses));
47 m_Symbols = strdup (v.m_Symbols);
48 m_nFrames = v.m_nFrames;
49 m_SymbolsSize = v.m_SymbolsSize;
50 return (*this);
53 /// Converts a string returned by backtrace_symbols into readable form.
54 static size_t ExtractAbiName (const char* isym, char* nmbuf) throw()
56 // Prepare the demangled name, if possible
57 size_t nmSize = 0;
58 if (isym) {
59 // Copy out the name; the strings are: "file(function+0x42) [0xAddress]"
60 const char* mnStart = strchr (isym, '(');
61 if (++mnStart == (const char*)(1))
62 mnStart = isym;
63 const char* mnEnd = strchr (isym, '+');
64 const char* isymEnd = isym + strlen (isym);
65 if (!mnEnd)
66 mnEnd = isymEnd;
67 nmSize = min (size_t (distance (mnStart, mnEnd)), 256U);
68 memcpy (nmbuf, mnStart, nmSize);
70 nmbuf[nmSize] = 0;
71 // Demangle
72 demangle_type_name (nmbuf, 256U, &nmSize);
73 return (nmSize);
76 /// Tries to get symbol information for the addresses.
77 void CBacktrace::GetSymbols (void) throw()
79 char** symbols = backtrace_symbols (m_Addresses, m_nFrames);
80 if (!symbols)
81 return;
82 char nmbuf [256];
83 size_t symSize = 1;
84 for (uoff_t i = 0; i < m_nFrames; ++ i)
85 symSize += ExtractAbiName (symbols[i], nmbuf) + 1;
86 if ((m_Symbols = (char*) calloc (symSize, 1))) {
87 for (uoff_t i = 0; m_SymbolsSize < symSize - 1; ++ i) {
88 size_t sz = ExtractAbiName (symbols[i], nmbuf);
89 memcpy (m_Symbols + m_SymbolsSize, nmbuf, sz);
90 m_SymbolsSize += sz + 1;
91 m_Symbols [m_SymbolsSize - 1] = '\n';
94 free (symbols);
97 /// Default destructor.
98 CBacktrace::~CBacktrace (void) throw()
100 free_nullok (m_Symbols);
103 #if SIZE_OF_LONG == 8
104 #define ADDRESS_FMT "%16p "
105 #else
106 #define ADDRESS_FMT "%8p "
107 #endif
109 /// Prints the backtrace to \p os.
110 void CBacktrace::text_write (ostringstream& os) const
112 const char *ss = m_Symbols, *se;
113 for (uoff_t i = 0; i < m_nFrames; ++ i) {
114 os.format (ADDRESS_FMT, m_Addresses[i]);
115 se = strchr (ss, '\n') + 1;
116 os.write (ss, distance (ss, se));
117 ss = se;
121 /// Reads the object from stream \p is.
122 void CBacktrace::read (istream& is)
124 assert (is.aligned (alignof (m_Addresses[0])) && "Backtrace object contains pointers and must be void* aligned");
125 is >> m_nFrames >> m_SymbolsSize;
126 free_nullok (m_Symbols);
127 m_Symbols = (char*) malloc (m_SymbolsSize + 1);
128 is.read (m_Symbols, m_SymbolsSize);
129 m_Symbols [m_SymbolsSize] = 0;
130 is.align();
131 is.read (m_Addresses, m_nFrames * sizeof(void*));
134 /// Writes the object to stream \p os.
135 void CBacktrace::write (ostream& os) const
137 assert (os.aligned (alignof (m_Addresses[0])) && "Backtrace object contains pointers and must be void* aligned");
138 os << m_nFrames << m_SymbolsSize;
139 os.write (m_Symbols, m_SymbolsSize);
140 os.align();
141 os.write (m_Addresses, m_nFrames * sizeof(void*));
144 /// Returns the size of the written object.
145 size_t CBacktrace::stream_size (void) const
147 return (Align (stream_size_of (m_nFrames) +
148 stream_size_of (m_SymbolsSize) +
149 m_nFrames * sizeof(void*) +
150 m_SymbolsSize));
153 } // namespace ustl