]>
git.saurik.com Git - wxWidgets.git/blob - src/unix/stackwalk.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/stackwalk.cpp
3 // Purpose: wxStackWalker implementation for Unix/glibc
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2005 Vadim Zeitlin <vadim@wxwindows.org>
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/wxprec.h"
29 #include "wx/string.h"
35 #include "wx/stackwalk.h"
39 #ifdef HAVE_CXA_DEMANGLE
41 #endif // HAVE_CXA_DEMANGLE
43 // ----------------------------------------------------------------------------
44 // tiny helper wrapper around popen/pclose()
45 // ----------------------------------------------------------------------------
50 // ctor parameters are passed to popen()
51 wxStdioPipe(const char *command
, const char *type
)
53 m_fp
= popen(command
, type
);
56 // conversion to stdio FILE
57 operator FILE *() const { return m_fp
; }
59 // dtor closes the pipe
69 DECLARE_NO_COPY_CLASS(wxStdioPipe
)
72 // ============================================================================
74 // ============================================================================
76 wxString
wxStackWalker::ms_exepath
;
78 // ----------------------------------------------------------------------------
80 // ----------------------------------------------------------------------------
82 void wxStackFrame::OnGetName()
89 // try addr2line first because it always gives us demangled names (even if
90 // __cxa_demangle is not available) and because it seems less error-prone
91 // when it works, backtrace_symbols() sometimes returns incorrect results
94 // format is: "module(funcname+offset) [address]" but the part in
95 // parentheses can be not present
96 wxString syminfo
= wxString::FromAscii(m_syminfo
);
97 const size_t posOpen
= syminfo
.find(_T('('));
98 if ( posOpen
!= wxString::npos
)
100 const size_t posPlus
= syminfo
.find(_T('+'), posOpen
+ 1);
101 if ( posPlus
!= wxString::npos
)
103 const size_t posClose
= syminfo
.find(_T(')'), posPlus
+ 1);
104 if ( posClose
!= wxString::npos
)
106 if ( m_name
.empty() )
108 m_name
.assign(syminfo
, posOpen
+ 1, posPlus
- posOpen
- 1);
110 #ifdef HAVE_CXA_DEMANGLE
112 char *cppfunc
= __cxxabiv1::__cxa_demangle
115 NULL
, // output buffer (none, alloc it)
116 NULL
, // [out] len of output buffer
120 m_name
= wxString::FromAscii(cppfunc
);
123 #endif // HAVE_CXA_DEMANGLE
127 if ( wxString(syminfo
, posPlus
+ 1, posClose
- posPlus
- 1).
134 m_module
.assign(syminfo
, posOpen
);
137 void wxStackFrame::OnGetLocation()
142 m_hasLocation
= true;
144 // we need to launch addr2line tool to get this information and we need to
145 // have the program name for this
146 wxString exepath
= wxStackWalker::GetExePath();
147 if ( exepath
.empty() )
149 if ( !wxTheApp
|| !wxTheApp
->argv
)
151 exepath
= wxTheApp
->argv
[0];
154 wxStdioPipe
fp(wxString::Format(_T("addr2line -C -f -e \"%s\" %p"),
155 exepath
.c_str(), m_address
).mb_str(),
161 // parse addr2line output
163 if ( !fgets(buf
, WXSIZEOF(buf
), fp
) )
165 wxLogDebug(_T("Empty addr2line output?"));
169 // 1st line has function name
170 if ( GetName().empty() )
172 m_name
= wxString::FromAscii(buf
);
173 m_name
.RemoveLast(); // trailing newline
175 if ( m_name
== _T("??") )
179 // 2nd one -- the file/line info
180 if ( fgets(buf
, WXSIZEOF(buf
), fp
) )
182 wxString
output(wxString::FromAscii(buf
));
185 const size_t posColon
= output
.find(_T(':'));
186 if ( posColon
!= wxString::npos
)
188 m_filename
.assign(output
, 0, posColon
);
189 if ( m_filename
== _T("??") )
196 if ( wxString(output
, posColon
+ 1, wxString::npos
).
203 wxLogDebug(_T("Unexpected addr2line format: \"%s\""),
209 // ----------------------------------------------------------------------------
211 // ----------------------------------------------------------------------------
213 void wxStackWalker::Walk(size_t skip
)
215 // that many frames should be enough for everyone
216 void *addresses
[200];
218 int depth
= backtrace(addresses
, WXSIZEOF(addresses
));
222 char **symbols
= backtrace_symbols(addresses
, depth
);
224 for ( int n
= 0; n
< depth
; n
++ )
226 wxStackFrame
frame(n
, addresses
[n
], symbols
[n
]);
231 #endif // wxUSE_STACKWALKER