]>
Commit | Line | Data |
---|---|---|
eaff0f0d VZ |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: msw/stackwalk.cpp | |
3 | // Purpose: wxStackWalker implementation for Unix/glibc | |
4 | // Author: Vadim Zeitlin | |
5 | // Modified by: | |
6 | // Created: 2005-01-18 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) 2005 Vadim Zeitlin <vadim@wxwindows.org> | |
9 | // Licence: wxWindows licence | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | // ============================================================================ | |
13 | // declarations | |
14 | // ============================================================================ | |
15 | ||
16 | // ---------------------------------------------------------------------------- | |
17 | // headers | |
18 | // ---------------------------------------------------------------------------- | |
19 | ||
20 | #include "wx/wxprec.h" | |
21 | ||
22 | #ifdef __BORLANDC__ | |
23 | #pragma hdrstop | |
24 | #endif | |
25 | ||
26 | #if wxUSE_STACKWALKER | |
27 | ||
28 | #ifndef WX_PRECOMP | |
29 | #include "wx/string.h" | |
7a3ba35d KH |
30 | #include "wx/app.h" |
31 | #include "wx/log.h" | |
32 | #include "wx/utils.h" | |
eaff0f0d VZ |
33 | #endif |
34 | ||
35 | #include "wx/stackwalk.h" | |
36 | ||
37 | #include <execinfo.h> | |
38 | ||
39 | #ifdef HAVE_CXA_DEMANGLE | |
40 | #include <cxxabi.h> | |
41 | #endif // HAVE_CXA_DEMANGLE | |
42 | ||
43 | // ============================================================================ | |
44 | // implementation | |
45 | // ============================================================================ | |
46 | ||
47 | wxString wxStackWalker::ms_exepath; | |
48 | ||
49 | // ---------------------------------------------------------------------------- | |
50 | // wxStackFrame | |
51 | // ---------------------------------------------------------------------------- | |
52 | ||
53 | void wxStackFrame::OnGetName() | |
54 | { | |
55 | if ( m_hasName ) | |
56 | return; | |
57 | ||
58 | m_hasName = true; | |
59 | ||
60 | // try addr2line first because it always gives us demangled names (even if | |
61 | // __cxa_demangle is not available) and because it seems less error-prone | |
62 | // when it works, backtrace_symbols() sometimes returns incorrect results | |
63 | OnGetLocation(); | |
64 | ||
65 | // format is: "module(funcname+offset) [address]" but the part in | |
66 | // parentheses can be not present | |
67 | wxString syminfo = wxString::FromAscii(m_syminfo); | |
68 | const size_t posOpen = syminfo.find(_T('(')); | |
69 | if ( posOpen != wxString::npos ) | |
70 | { | |
71 | const size_t posPlus = syminfo.find(_T('+'), posOpen + 1); | |
72 | if ( posPlus != wxString::npos ) | |
73 | { | |
74 | const size_t posClose = syminfo.find(_T(')'), posPlus + 1); | |
75 | if ( posClose != wxString::npos ) | |
76 | { | |
77 | if ( m_name.empty() ) | |
78 | { | |
79 | m_name.assign(syminfo, posOpen + 1, posPlus - posOpen - 1); | |
80 | ||
81 | #ifdef HAVE_CXA_DEMANGLE | |
82 | int rc = -1; | |
83 | char *cppfunc = __cxxabiv1::__cxa_demangle | |
84 | ( | |
85 | m_name.mb_str(), | |
86 | NULL, // output buffer (none, alloc it) | |
87 | NULL, // [out] len of output buffer | |
88 | &rc | |
89 | ); | |
90 | if ( rc == 0 ) | |
91 | m_name = wxString::FromAscii(cppfunc); | |
92 | ||
93 | free(cppfunc); | |
94 | #endif // HAVE_CXA_DEMANGLE | |
95 | } | |
96 | ||
97 | unsigned long ofs; | |
98 | if ( wxString(syminfo, posPlus + 1, posClose - posPlus - 1). | |
99 | ToULong(&ofs, 0) ) | |
100 | m_offset = ofs; | |
101 | } | |
102 | } | |
103 | } | |
104 | ||
105 | m_module.assign(syminfo, posOpen); | |
106 | } | |
107 | ||
108 | void wxStackFrame::OnGetLocation() | |
109 | { | |
110 | if ( m_hasLocation ) | |
111 | return; | |
112 | ||
113 | m_hasLocation = true; | |
114 | ||
115 | // we need to launch addr2line tool to get this information and we need to | |
116 | // have the program name for this | |
117 | wxString exepath = wxStackWalker::GetExePath(); | |
118 | if ( exepath.empty() ) | |
119 | { | |
120 | if ( !wxTheApp || !wxTheApp->argv ) | |
121 | return; | |
122 | exepath = wxTheApp->argv[0]; | |
123 | } | |
124 | ||
125 | wxArrayString output; | |
126 | wxLogNull noLog; | |
127 | if ( wxExecute(wxString::Format(_T("addr2line -C -f -e \"%s\" %p"), | |
128 | exepath.c_str(), | |
129 | m_address), output) == 0 ) | |
130 | { | |
131 | if ( output.GetCount() != 2 ) | |
132 | { | |
133 | wxLogDebug(_T("Unexpected addr2line output.")); | |
134 | } | |
135 | else // 1st line has function name, 2nd one -- the file/line info | |
136 | { | |
137 | if ( GetName().empty() ) | |
138 | { | |
139 | m_name = output[0]; | |
140 | if ( m_name == _T("??") ) | |
141 | m_name.clear(); | |
142 | } | |
143 | ||
144 | const size_t posColon = output[1].find(_T(':')); | |
145 | if ( posColon != wxString::npos ) | |
146 | { | |
147 | m_filename.assign(output[1], 0, posColon); | |
148 | if ( m_filename == _T("??") ) | |
149 | { | |
150 | m_filename.clear(); | |
151 | } | |
152 | else | |
153 | { | |
154 | unsigned long line; | |
155 | if ( wxString(output[1], posColon + 1, wxString::npos). | |
156 | ToULong(&line) ) | |
157 | m_line = line; | |
158 | } | |
159 | } | |
160 | else | |
161 | { | |
162 | wxLogDebug(_T("Unexpected addr2line format: \"%s\""), | |
163 | output[1].c_str()); | |
164 | } | |
165 | } | |
166 | } | |
167 | } | |
168 | ||
169 | // ---------------------------------------------------------------------------- | |
170 | // wxStackWalker | |
171 | // ---------------------------------------------------------------------------- | |
172 | ||
173 | void wxStackWalker::Walk(size_t skip) | |
174 | { | |
175 | // that many frames should be enough for everyone | |
176 | void *addresses[200]; | |
177 | ||
178 | int depth = backtrace(addresses, WXSIZEOF(addresses)); | |
179 | if ( !depth ) | |
180 | return; | |
181 | ||
182 | char **symbols = backtrace_symbols(addresses, depth); | |
183 | ||
184 | for ( int n = 0; n < depth; n++ ) | |
185 | { | |
186 | wxStackFrame frame(n, addresses[n], symbols[n]); | |
187 | OnStackFrame(frame); | |
188 | } | |
189 | } | |
190 | ||
191 | #endif // wxUSE_STACKWALKER |