]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/stackwalk.cpp
Possible crash fix from Ryan (patch #1194315).
[wxWidgets.git] / src / unix / stackwalk.cpp
index 556eaf68379842fcab6c3e3181df09d957f37ba9..b8b92ef92470ab822cf3223d2890d54fed4eec63 100644 (file)
@@ -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"
     #include <cxxabi.h>
 #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
 // ============================================================================
@@ -119,47 +151,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();
+    }
+
+    // 2nd one -- the file/line info
+    if ( fgets(buf, WXSIZEOF(buf), fp) )
+    {
+        wxString output(wxString::FromAscii(buf));
+        output.RemoveLast();
 
-            const size_t posColon = output[1].find(_T(':'));
-            if ( posColon != wxString::npos )
+        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 +221,12 @@ void wxStackWalker::Walk(size_t skip)
 
     char **symbols = backtrace_symbols(addresses, depth);
 
-    for ( int n = 0; n < depth; n++ )
+    if (skip > (size_t) depth)
+        skip = (size_t) depth;
+
+    for ( int n = skip; n < depth; n++ )
     {
-        wxStackFrame frame(n, addresses[n], symbols[n]);
+        wxStackFrame frame(n, addresses[n-skip], symbols[n-skip]);
         OnStackFrame(frame);
     }
 }