1 // This file is part of the ustl library, an STL implementation.
3 // Copyright (C) 2006 by Mike Sharov <msharov@users.sourceforge.net>
4 // This file is free software, distributed under the MIT License.
15 static inline int backtrace (void**, int) { return (0); }
16 static inline char** backtrace_symbols (void* const*, int) { return (NULL
); }
24 /// Default constructor. The backtrace is obtained here.
25 CBacktrace::CBacktrace (void) throw()
30 m_nFrames
= backtrace (VectorBlock (m_Addresses
));
35 CBacktrace::CBacktrace (const CBacktrace
& v
) throw()
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
;
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
59 // Copy out the name; the strings are: "file(function+0x42) [0xAddress]"
60 const char* mnStart
= strchr (isym
, '(');
61 if (++mnStart
== (const char*)(1))
63 const char* mnEnd
= strchr (isym
, '+');
64 const char* isymEnd
= isym
+ strlen (isym
);
67 nmSize
= min (size_t (distance (mnStart
, mnEnd
)), 256U);
68 memcpy (nmbuf
, mnStart
, nmSize
);
72 demangle_type_name (nmbuf
, 256U, &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
);
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';
97 /// Default destructor.
98 CBacktrace::~CBacktrace (void) throw()
100 free_nullok (m_Symbols
);
103 #if SIZE_OF_LONG == 8
104 #define ADDRESS_FMT "%16p "
106 #define ADDRESS_FMT "%8p "
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
));
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;
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
);
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*) +