1fda155e9665d497f629cb575ea93a33b12a7d3b
[libs/core.git] / source / debug / backtrace.cpp
1 // Must include something to test for glibc
2 #include <cstdlib>
3 #if !defined(WIN32) && defined(__GLIBC__)
4 #include <dlfcn.h>
5 #include <execinfo.h>
6 #endif
7 #include "backtrace.h"
8 #include "demangle.h"
9
10 using namespace std;
11
12 namespace Msp {
13 namespace Debug {
14
15 Backtrace Backtrace::create()
16 {
17 #if !defined(WIN32) && defined(__GLIBC__)
18         void *addresses[50];
19         int count = ::backtrace(addresses, 50);
20
21         Backtrace bt;
22         Dl_info dli;
23         for(int i=0; i<count; ++i)
24         {
25                 StackFrame frame;
26                 frame.address = addresses[i];
27                 if(dladdr(addresses[i], &dli))
28                 {
29                         frame.file = dli.dli_fname;
30                         if(dli.dli_sname)
31                                 frame.symbol = demangle(dli.dli_sname);
32                 }
33                 else
34                         frame.file = "<unknown>";
35                 bt.frames.push_back(frame);
36         }
37
38         return bt;
39 #else
40         return Backtrace();
41 #endif
42 }
43
44 ostream &operator<<(ostream &out, const Backtrace &bt)
45 {
46         const list<Backtrace::StackFrame> &frames = bt.get_frames();
47         for(list<Backtrace::StackFrame>::const_iterator i=frames.begin(); i!=frames.end(); ++i)
48                 out<<*i<<'\n';
49
50         return out;
51 }
52
53 ostream &operator<<(ostream &out, const Backtrace::StackFrame &sf)
54 {
55         out<<sf.address;
56         if(!sf.symbol.empty())
57                 out<<" in "<<sf.symbol;
58         out<<" from "<<sf.file;
59
60         return out;
61 }
62
63 } // namespace Debug
64 } // namespace Msp