// Routines useful when debugging the Rust runtime. #include "rust_debug.h" #include "rust_internal.h" #include #include #include #include #if defined(__APPLE__) || defined(__linux__) #define HAVE_BACKTRACE #include #elif defined(_WIN32) #include #endif namespace { debug::flag track_origins("RUST_TRACK_ORIGINS"); } // end anonymous namespace namespace debug { std::string backtrace() { void *call_stack[256]; int n_frames = ::backtrace(call_stack, 256); char **syms = backtrace_symbols(call_stack, n_frames); std::stringstream ss; for (int i = 0; i < n_frames; i++) ss << syms[i] << std::endl; free(syms); return ss.str(); } void maybe_track_origin(rust_task *task, void *ptr) { if (!*track_origins) return; task->debug.origins[ptr] = backtrace(); } void maybe_untrack_origin(rust_task *task, void *ptr) { if (!*track_origins) return; task->debug.origins.erase(ptr); } // This function is intended to be called by the debugger. void dump_origin(rust_task *task, void *ptr) { if (!*track_origins) { std::cerr << "Try again with RUST_TRACK_ORIGINS=1." << std::endl; } else if (task->debug.origins.find(ptr) == task->debug.origins.end()) { std::cerr << "Pointer " << std::hex << (uintptr_t)ptr << " does not have a tracked origin."; } else { std::cerr << "Origin of pointer " << std::hex << ":" << std::endl << task->debug.origins[ptr]; } } } // end namespace debug