X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/eaff0f0d3f7828c2acd9ebde4979acc0b3fa43b5..f46ad98f0df1e1b073a484cb34a91e2e1278fdb7:/src/unix/stackwalk.cpp diff --git a/src/unix/stackwalk.cpp b/src/unix/stackwalk.cpp index 556eaf6837..ae48c30a31 100644 --- a/src/unix/stackwalk.cpp +++ b/src/unix/stackwalk.cpp @@ -27,6 +27,9 @@ #ifndef WX_PRECOMP #include "wx/string.h" + #include "wx/app.h" + #include "wx/log.h" + #include "wx/utils.h" #endif #include "wx/stackwalk.h" @@ -37,6 +40,35 @@ #include #endif // HAVE_CXA_DEMANGLE +// ---------------------------------------------------------------------------- +// tiny helper wrapper around popen/pclose() +// ---------------------------------------------------------------------------- + +class wxStdioPipe +{ +public: + // ctor parameters are passed to popen() + wxStdioPipe(const char *command, const char *type) + { + m_fp = popen(command, type); + } + + // conversion to stdio FILE + operator FILE *() const { return m_fp; } + + // dtor closes the pipe + ~wxStdioPipe() + { + if ( m_fp ) + pclose(m_fp); + } + +private: + FILE *m_fp; + + DECLARE_NO_COPY_CLASS(wxStdioPipe) +}; + // ============================================================================ // implementation // ============================================================================ @@ -97,9 +129,13 @@ void wxStackFrame::OnGetName() m_offset = ofs; } } - } - m_module.assign(syminfo, posOpen); + m_module.assign(syminfo, posOpen); + } + else // not in "module(funcname+offset)" format + { + m_module = syminfo; + } } void wxStackFrame::OnGetLocation() @@ -119,47 +155,58 @@ void wxStackFrame::OnGetLocation() exepath = wxTheApp->argv[0]; } - wxArrayString output; - wxLogNull noLog; - if ( wxExecute(wxString::Format(_T("addr2line -C -f -e \"%s\" %p"), - exepath.c_str(), - m_address), output) == 0 ) + wxStdioPipe fp(wxString::Format(_T("addr2line -C -f -e \"%s\" %p"), + exepath.c_str(), m_address).mb_str(), + "r"); + + if ( !fp ) + return; + + // parse addr2line output + char buf[1024]; + if ( !fgets(buf, WXSIZEOF(buf), fp) ) { - if ( output.GetCount() != 2 ) - { - wxLogDebug(_T("Unexpected addr2line output.")); - } - else // 1st line has function name, 2nd one -- the file/line info - { - if ( GetName().empty() ) - { - m_name = output[0]; - if ( m_name == _T("??") ) - m_name.clear(); - } + wxLogDebug(_T("Empty addr2line output?")); + return; + } + + // 1st line has function name + if ( GetName().empty() ) + { + m_name = wxString::FromAscii(buf); + m_name.RemoveLast(); // trailing newline + + if ( m_name == _T("??") ) + m_name.clear(); + } - const size_t posColon = output[1].find(_T(':')); - if ( posColon != wxString::npos ) + // 2nd one -- the file/line info + if ( fgets(buf, WXSIZEOF(buf), fp) ) + { + wxString output(wxString::FromAscii(buf)); + output.RemoveLast(); + + const size_t posColon = output.find(_T(':')); + if ( posColon != wxString::npos ) + { + m_filename.assign(output, 0, posColon); + if ( m_filename == _T("??") ) { - m_filename.assign(output[1], 0, posColon); - if ( m_filename == _T("??") ) - { - m_filename.clear(); - } - else - { - unsigned long line; - if ( wxString(output[1], posColon + 1, wxString::npos). - ToULong(&line) ) - m_line = line; - } + m_filename.clear(); } else { - wxLogDebug(_T("Unexpected addr2line format: \"%s\""), - output[1].c_str()); + unsigned long line; + if ( wxString(output, posColon + 1, wxString::npos). + ToULong(&line) ) + m_line = line; } } + else + { + wxLogDebug(_T("Unexpected addr2line format: \"%s\""), + output.c_str()); + } } } @@ -178,9 +225,13 @@ void wxStackWalker::Walk(size_t skip) char **symbols = backtrace_symbols(addresses, depth); - for ( int n = 0; n < depth; n++ ) + // we have 3 more "intermediate" frames which the calling code doesn't know + // about., account for them + skip += 3; + + for ( int n = skip; n < depth; n++ ) { - wxStackFrame frame(n, addresses[n], symbols[n]); + wxStackFrame frame(n - skip, addresses[n], symbols[n]); OnStackFrame(frame); } }