]>
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). 
 133         m_module
.assign(syminfo
, posOpen
); 
 135     else // not in "module(funcname+offset)" format 
 141 void wxStackFrame::OnGetLocation() 
 146     m_hasLocation 
= true; 
 148     // we need to launch addr2line tool to get this information and we need to 
 149     // have the program name for this 
 150     wxString exepath 
= wxStackWalker::GetExePath(); 
 151     if ( exepath
.empty() ) 
 153         if ( !wxTheApp 
|| !wxTheApp
->argv 
) 
 155         exepath 
= wxTheApp
->argv
[0]; 
 158     wxStdioPipe 
fp(wxString::Format(_T("addr2line -C -f -e \"%s\" %p"), 
 159                                     exepath
.c_str(), m_address
).mb_str(), 
 165     // parse addr2line output 
 167     if ( !fgets(buf
, WXSIZEOF(buf
), fp
) ) 
 169         wxLogDebug(_T("Empty addr2line output?")); 
 173     // 1st line has function name 
 174     if ( GetName().empty() ) 
 176         m_name 
= wxString::FromAscii(buf
); 
 177         m_name
.RemoveLast(); // trailing newline 
 179         if ( m_name 
== _T("??") ) 
 183     // 2nd one -- the file/line info 
 184     if ( fgets(buf
, WXSIZEOF(buf
), fp
) ) 
 186         wxString 
output(wxString::FromAscii(buf
)); 
 189         const size_t posColon 
= output
.find(_T(':')); 
 190         if ( posColon 
!= wxString::npos 
) 
 192             m_filename
.assign(output
, 0, posColon
); 
 193             if ( m_filename 
== _T("??") ) 
 200                 if ( wxString(output
, posColon 
+ 1, wxString::npos
). 
 207             wxLogDebug(_T("Unexpected addr2line format: \"%s\""), 
 213 // ---------------------------------------------------------------------------- 
 215 // ---------------------------------------------------------------------------- 
 217 void wxStackWalker::Walk(size_t skip
) 
 219     // that many frames should be enough for everyone 
 220     void *addresses
[200]; 
 222     int depth 
= backtrace(addresses
, WXSIZEOF(addresses
)); 
 226     char **symbols 
= backtrace_symbols(addresses
, depth
); 
 228     // we have 3 more "intermediate" frames which the calling code doesn't know 
 229     // about., account for them 
 232     for ( int n 
= skip
; n 
< depth
; n
++ ) 
 234         wxStackFrame 
frame(n 
- skip
, addresses
[n
], symbols
[n
]); 
 239 #endif // wxUSE_STACKWALKER