diff options
author | Andy Schwerin <schwerin@mongodb.com> | 2014-05-19 15:18:02 -0400 |
---|---|---|
committer | Andy Schwerin <schwerin@mongodb.com> | 2014-06-04 15:06:44 -0400 |
commit | f43fd35390995c4aa6ef53477e95998c891eb6d2 (patch) | |
tree | eb8d588ce56e1dfc983e54c79308f33178677f80 /src/mongo/util | |
parent | dd0469332e0777e366cb4d4d75dce2c52ab7164a (diff) | |
download | mongo-f43fd35390995c4aa6ef53477e95998c891eb6d2.tar.gz |
SERVER-13957 Print load location and build uuid information in OS X stack traces.
Diffstat (limited to 'src/mongo/util')
-rw-r--r-- | src/mongo/util/stacktrace_posix.cpp | 114 |
1 files changed, 102 insertions, 12 deletions
diff --git a/src/mongo/util/stacktrace_posix.cpp b/src/mongo/util/stacktrace_posix.cpp index e1619bfdd59..856744b4717 100644 --- a/src/mongo/util/stacktrace_posix.cpp +++ b/src/mongo/util/stacktrace_posix.cpp @@ -33,6 +33,7 @@ #include <dlfcn.h> #include <iostream> #include <string> +#include <sys/utsname.h> #include "mongo/base/init.h" #include "mongo/db/jsobj.h" @@ -170,6 +171,35 @@ namespace { os << std::dec << std::nouppercase; os << "----- END BACKTRACE -----" << std::endl; } + +namespace { + + void addOSComponentsToSoMap(BSONObjBuilder* soMap); + + /** + * Builds the "soMapJson" string, which is a JSON encoding of various pieces of information + * about a running process, including the map from load addresses to shared objects loaded at + * those addresses. + */ + MONGO_INITIALIZER(ExtractSOMap)(InitializerContext*) { + BSONObjBuilder soMap; + soMap << "mongodbVersion" << versionString; + soMap << "gitVersion" << gitVersion(); + utsname unameData; + if (!uname(&unameData)) { + BSONObjBuilder unameBuilder(soMap.subobjStart("uname")); + unameBuilder << + "sysname" << unameData.sysname << + "release" << unameData.release << + "version" << unameData.version << + "machine" << unameData.machine; + } + addOSComponentsToSoMap(&soMap); + soMapJson = new std::string(soMap.done().jsonString(Strict)); + return Status::OK(); + } +} // namespace + } // namespace mongo #if defined(__linux__) @@ -336,23 +366,83 @@ namespace { return 0; } - /** - * Builds the "soMapJson" string for Linux, which is of the following form: - * - * '"somap": [<Objects described by outputSOInfo, above>]' - */ - MONGO_INITIALIZER(ExtractSOMap)(InitializerContext*) { - BSONObjBuilder soMap; - soMap << "mongodbVersion" << versionString; - soMap << "gitVersion" << gitVersion(); - BSONArrayBuilder soList(soMap.subarrayStart("somap")); + void addOSComponentsToSoMap(BSONObjBuilder* soMap) { + BSONArrayBuilder soList(soMap->subarrayStart("somap")); dl_iterate_phdr(outputSOInfo, &soList); soList.done(); - soMapJson = new std::string(soMap.done().jsonString(Strict)); - return Status::OK(); } + } // namespace } // namespace mongo +#elif defined(__APPLE__) && defined(__MACH__) + +#include <mach-o/dyld.h> +#include <mach-o/ldsyms.h> +#include <mach-o/loader.h> + +namespace mongo { +namespace { + const char* lcNext(const char* lcCurr) { + const load_command* cmd = reinterpret_cast<const load_command*>(lcCurr); + return lcCurr + cmd->cmdsize; + } + + uint32_t lcType(const char* lcCurr) { + const load_command* cmd = reinterpret_cast<const load_command*>(lcCurr); + return cmd->cmd; + } + + void addOSComponentsToSoMap(BSONObjBuilder* soMap) { + const uint32_t numImages = _dyld_image_count(); + BSONArrayBuilder soList(soMap->subarrayStart("somap")); + for (uint32_t i = 0; i < numImages; ++i) { + BSONObjBuilder soInfo(soList.subobjStart()); + const char* name = _dyld_get_image_name(i); + if (name) + soInfo << "path" << name; + const mach_header* header = _dyld_get_image_header(i); + if (!header) + continue; + size_t headerSize; + if (header->magic == MH_MAGIC) { + headerSize = sizeof(mach_header); + } + else if (header->magic == MH_MAGIC_64) { + headerSize = sizeof(mach_header_64); + } + else { + continue; + } + soInfo << "machType" << header->filetype; + soInfo << "b" << integerToHex(reinterpret_cast<intptr_t>(header)); + const char* const loadCommandsBegin = + reinterpret_cast<const char*>(header) + headerSize; + const char* const loadCommandsEnd = loadCommandsBegin + header->sizeofcmds; + + // Search the "load command" data in the Mach object for the entry + // encoding the UUID of the object. + for (const char* lcCurr = loadCommandsBegin; + lcCurr < loadCommandsEnd; + lcCurr = lcNext(lcCurr)) { + + if (LC_UUID != lcType(lcCurr)) + continue; + + const uuid_command* uuidCmd = reinterpret_cast<const uuid_command*>(lcCurr); + soInfo << "buildId" << toHex(uuidCmd->uuid, 16); + break; + } + } + } +} // namepace +} // namespace mongo +#else +namespace mongo { +namespace { + void addOSComponentsToSoMap(BSONObjBuilder* soMap) { + } +} // namepace +} // namespace mongo #endif |