diff options
author | Tad Marshall <tad@10gen.com> | 2013-06-21 13:34:53 -0400 |
---|---|---|
committer | Tad Marshall <tad@10gen.com> | 2013-07-18 14:45:33 -0400 |
commit | 71082c54a4bb5007445f1a0c19e14aca3567b284 (patch) | |
tree | 1e98d08ac8fc1bb5af5531b03bce96b0bbdbc565 | |
parent | 66f4a37277cc2f309851e525e3392a20295cf737 (diff) | |
download | mongo-71082c54a4bb5007445f1a0c19e14aca3567b284.tar.gz |
SERVER-7080 Add code to emulate backtrace()
backtrace() fills a buffer provided by the caller with addresses
constituting a stack trace. This emulation allows the display of
addresses in Solaris 10, which can be used with addr2line to see
code locations.
-rw-r--r-- | src/mongo/platform/backtrace.cpp | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/mongo/platform/backtrace.cpp b/src/mongo/platform/backtrace.cpp index 9bb3fd0283c..64d593d0157 100644 --- a/src/mongo/platform/backtrace.cpp +++ b/src/mongo/platform/backtrace.cpp @@ -19,6 +19,7 @@ #include "mongo/platform/backtrace.h" #include <dlfcn.h> +#include <ucontext.h> #include "mongo/base/init.h" #include "mongo/base/status.h" @@ -26,7 +27,48 @@ namespace mongo { namespace pal { +namespace { + class WalkcontextCallback { + public: + WalkcontextCallback(uintptr_t* array, int size) + : _position(0), + _count(size), + _addresses(array) {} + + // This callback function is called from C code, and so must not throw exceptions + // + static int callbackFunction(uintptr_t address, + int signalNumber, + WalkcontextCallback* thisContext) { + if (thisContext->_position < thisContext->_count) { + thisContext->_addresses[thisContext->_position++] = address; + return 0; + } + return 1; + } + int getCount() const { return static_cast<int>(_position); } + private: + size_t _position; + size_t _count; + uintptr_t* _addresses; + }; +} // namespace + + typedef int (*WalkcontextCallbackFunc)(uintptr_t address, int signalNumber, void* thisContext); + int backtrace_emulation(void** array, int size) { + WalkcontextCallback walkcontextCallback(reinterpret_cast<uintptr_t*>(array), size); + ucontext_t context; + if (getcontext(&context) != 0) { + return 0; + } + int wcReturn = walkcontext( + &context, + reinterpret_cast<WalkcontextCallbackFunc>(WalkcontextCallback::callbackFunction), + static_cast<void*>(&walkcontextCallback)); + if (wcReturn == 0) { + return walkcontextCallback.getCount(); + } return 0; } |