X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1d2c115e44e0d74bcda27b1bfe6a7d28d2541489..88ff049184c77fd73b60c01f4f831860d2ec5cef:/src/unix/stackwalk.cpp diff --git a/src/unix/stackwalk.cpp b/src/unix/stackwalk.cpp index 34c812366d..e8cf6edff3 100644 --- a/src/unix/stackwalk.cpp +++ b/src/unix/stackwalk.cpp @@ -1,10 +1,9 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: msw/stackwalk.cpp +// Name: src/unix/stackwalk.cpp // Purpose: wxStackWalker implementation for Unix/glibc // Author: Vadim Zeitlin // Modified by: // Created: 2005-01-18 -// RCS-ID: $Id$ // Copyright: (c) 2005 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -67,7 +66,7 @@ public: private: FILE *m_fp; - DECLARE_NO_COPY_CLASS(wxStdioPipe) + wxDECLARE_NO_COPY_CLASS(wxStdioPipe); }; // ============================================================================ @@ -92,13 +91,13 @@ void wxStackFrame::OnGetName() // format is: "module(funcname+offset) [address]" but the part in // parentheses can be not present wxString syminfo = wxString::FromAscii(m_syminfo); - const size_t posOpen = syminfo.find(_T('(')); + const size_t posOpen = syminfo.find(wxT('(')); if ( posOpen != wxString::npos ) { - const size_t posPlus = syminfo.find(_T('+'), posOpen + 1); + const size_t posPlus = syminfo.find(wxT('+'), posOpen + 1); if ( posPlus != wxString::npos ) { - const size_t posClose = syminfo.find(_T(')'), posPlus + 1); + const size_t posClose = syminfo.find(wxT(')'), posPlus + 1); if ( posClose != wxString::npos ) { if ( m_name.empty() ) @@ -130,10 +129,12 @@ void wxStackFrame::OnGetName() m_module.assign(syminfo, posOpen); } +#ifndef __WXOSX__ else // not in "module(funcname+offset)" format { m_module = syminfo; } +#endif // !__WXOSX__ } @@ -180,17 +181,18 @@ void wxStackWalker::ProcessFrames(size_t skip) if (!ms_symbols || !m_depth) return; - // we have 3 more "intermediate" frames which the calling code doesn't know - // about, account for them - skip += 3; + // we are another level down from Walk(), so adjust the number of stack + // frames to skip accordingly + skip += 1; // call addr2line only once since this call may be very slow // (it has to load in memory the entire EXE of this app which may be quite // big, especially if it contains debug info and is compiled statically!) - int towalk = InitFrames(frames, m_depth - skip, &ms_addresses[skip], &ms_symbols[skip]); + int numFrames = InitFrames(frames, m_depth - skip, + &ms_addresses[skip], &ms_symbols[skip]); // now do user-defined operations on each frame - for ( int n = 0; n < towalk - (int)skip; n++ ) + for ( int n = 0; n < numFrames; n++ ) OnStackFrame(frames[n]); } @@ -204,6 +206,28 @@ void wxStackWalker::FreeStack() m_depth = 0; } +namespace +{ + +// Helper function to read a line from the file and return it without the +// trailing newline. Line number is only used for error reporting. +bool ReadLine(FILE* fp, unsigned long num, wxString* line) +{ + if ( !fgets(g_buf, WXSIZEOF(g_buf), fp) ) + { + wxLogDebug(wxS("cannot read address information for stack frame #%lu"), + num); + return false; + } + + *line = wxString::FromAscii(g_buf); + line->RemoveLast(); + + return true; +} + +} // anonymous namespace + int wxStackWalker::InitFrames(wxStackFrame *arr, size_t n, void **addresses, char **syminfo) { // we need to launch addr2line tool to get this information and we need to @@ -220,9 +244,13 @@ int wxStackWalker::InitFrames(wxStackFrame *arr, size_t n, void **addresses, cha } } - // build the (long) command line for executing addr2line in an optimized way - // (e.g. use always chars, even in Unicode build: popen() always takes chars) + // build the command line for executing addr2line or atos under OS X using + // char* directly to avoid the conversions from Unicode +#ifdef __WXOSX__ + int len = snprintf(g_buf, BUFSIZE, "atos -p %d", (int)getpid()); +#else int len = snprintf(g_buf, BUFSIZE, "addr2line -C -f -e \"%s\"", (const char*) exepath.mb_str()); +#endif len = (len <= 0) ? strlen(g_buf) : len; // in case snprintf() is broken for (size_t i=0; i