+    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;
+
+    // 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]);
+
+    // now do user-defined operations on each frame
+    for ( int n = 0; n < towalk - (int)skip; n++ )
+        OnStackFrame(frames[n]);
+}
+
+void wxStackWalker::FreeStack()
+{
+    // ms_symbols has been allocated by backtrace_symbols() and it's the responsibility
+    // of the caller, i.e. us, to free that pointer
+    if (ms_symbols)
+        free( ms_symbols );
+    ms_symbols = NULL;
+    m_depth = 0;
+}
+
+int wxStackWalker::InitFrames(wxStackFrame *arr, size_t n, void **addresses, char **syminfo)
+{