about summary refs log tree commit diff
path: root/src/rt
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-09-23 15:05:24 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-09-23 15:06:28 -0700
commit557d641175c505d34bf3eac194597d1d2fc3a494 (patch)
tree3682443763943603f4afc8c52e166d313475ce19 /src/rt
parent7b1a3bb8e6296541f0200e42d54a77363709a9bd (diff)
rt: Get RUST_TRACK_ORIGINS working. You can now call 'debug::dump_origin' in gdb and get a backtrace saying where a box came from.
Diffstat (limited to 'src/rt')
-rw-r--r--src/rt/rust_abi.cpp44
-rw-r--r--src/rt/rust_abi.h4
-rw-r--r--src/rt/rust_debug.cpp38
3 files changed, 51 insertions, 35 deletions
diff --git a/src/rt/rust_abi.cpp b/src/rt/rust_abi.cpp
index 2a08a25a9fa..3fba1ada3f3 100644
--- a/src/rt/rust_abi.cpp
+++ b/src/rt/rust_abi.cpp
@@ -1,10 +1,19 @@
 // ABI-specific routines.
 
+#include <sstream>
+#include <string>
 #include <vector>
 #include <cstdlib>
 #include <stdint.h>
 #include "rust_abi.h"
 
+#if defined(__APPLE__) || defined(__linux__)
+#define HAVE_DLFCN_H
+#include <dlfcn.h>
+#elif defined(_WIN32)
+// TODO
+#endif
+
 #define END_OF_STACK_RA     (void (*)())0xdeadbeef
 
 weak_symbol<uint32_t> abi_version("rust_abi_version");
@@ -15,6 +24,29 @@ uint32_t get_abi_version() {
 
 namespace stack_walk {
 
+#ifdef HAVE_DLFCN_H
+std::string
+frame::symbol() const {
+    std::stringstream ss;
+
+    Dl_info info;
+    if (!dladdr((void *)ra, &info))
+        ss << "??";
+    else
+        ss << info.dli_sname;
+
+    ss << " @ " << std::hex << (uintptr_t)ra;
+    return ss.str();
+}
+#else
+std::string
+frame::symbol() {
+    std::stringstream ss;
+    ss << std::hex << (uintptr_t)ra;
+    return ss.str();
+}
+#endif
+
 std::vector<frame>
 backtrace() {
     std::vector<frame> frames;
@@ -31,5 +63,17 @@ backtrace() {
     return frames;
 }
 
+std::string
+symbolicate(const std::vector<frame> &frames) {
+    std::stringstream ss;
+    std::vector<frame>::const_iterator begin(frames.begin()),
+                                       end(frames.end());
+    while (begin != end) {
+        ss << begin->symbol() << std::endl;
+        ++begin;
+    }
+    return ss.str();
+}
+
 }   // end namespace stack_walk
 
diff --git a/src/rt/rust_abi.h b/src/rt/rust_abi.h
index 884eed4b717..c533d372b72 100644
--- a/src/rt/rust_abi.h
+++ b/src/rt/rust_abi.h
@@ -4,6 +4,7 @@
 #define RUST_ABI_H
 
 #include <cstdlib>
+#include <string>
 #include <vector>
 
 #ifdef __WIN32__
@@ -51,9 +52,12 @@ struct frame {
         ra = *(void (**)())(bp + sizeof(void *));
         bp = *(uint8_t **)bp;
     }
+
+    std::string symbol() const;
 };
 
 std::vector<frame> backtrace();
+std::string symbolicate(const std::vector<frame> &frames);
 
 }   // end namespace stack_walk
 
diff --git a/src/rt/rust_debug.cpp b/src/rt/rust_debug.cpp
index 7bb80a4f36e..9591d9ade07 100644
--- a/src/rt/rust_debug.cpp
+++ b/src/rt/rust_debug.cpp
@@ -1,5 +1,6 @@
 // Routines useful when debugging the Rust runtime.
 
+#include "rust_abi.h"
 #include "rust_debug.h"
 #include "rust_internal.h"
 
@@ -8,13 +9,6 @@
 #include <sstream>
 #include <stdint.h>
 
-#if defined(__APPLE__) || defined(__linux__)
-#define HAVE_BACKTRACE
-#include <execinfo.h>
-#elif defined(_WIN32)
-#include <windows.h>
-#endif
-
 namespace {
 
 debug::flag track_origins("RUST_TRACK_ORIGINS");
@@ -23,38 +17,12 @@ debug::flag track_origins("RUST_TRACK_ORIGINS");
 
 namespace debug {
 
-#ifdef HAVE_BACKTRACE
-std::string
-backtrace() {
-    void *call_stack[128];
-    int n_frames = ::backtrace(call_stack, 128);
-    char **syms = backtrace_symbols(call_stack, n_frames);
-
-    std::cerr << "n_frames: " << n_frames << std::endl;
-
-    std::stringstream ss;
-    for (int i = 0; i < n_frames; i++) {
-        std::cerr << syms[i] << std::endl;
-        ss << syms[i] << std::endl;
-    }
-
-    free(syms);
-
-    return ss.str();
-}
-#else
-std::string
-backtrace() {
-    std::string s;
-    return s;
-}
-#endif
-
 void
 maybe_track_origin(rust_task *task, void *ptr) {
     if (!*track_origins)
         return;
-    task->debug.origins[ptr] = backtrace();
+    task->debug.origins[ptr] =
+        stack_walk::symbolicate(stack_walk::backtrace());
 }
 
 void