summaryrefslogtreecommitdiff
path: root/src/mongo/util/stacktrace_windows.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/util/stacktrace_windows.cpp')
-rw-r--r--src/mongo/util/stacktrace_windows.cpp421
1 files changed, 206 insertions, 215 deletions
diff --git a/src/mongo/util/stacktrace_windows.cpp b/src/mongo/util/stacktrace_windows.cpp
index e99f0c4d87a..a3ae0e87c7a 100644
--- a/src/mongo/util/stacktrace_windows.cpp
+++ b/src/mongo/util/stacktrace_windows.cpp
@@ -46,248 +46,239 @@
namespace mongo {
- /**
- * Get the path string to be used when searching for PDB files.
- *
- * @param process Process handle
- * @return searchPath Returned search path string
- */
- static const char* getSymbolSearchPath(HANDLE process) {
- static std::string symbolSearchPath;
+/**
+ * Get the path string to be used when searching for PDB files.
+ *
+ * @param process Process handle
+ * @return searchPath Returned search path string
+ */
+static const char* getSymbolSearchPath(HANDLE process) {
+ static std::string symbolSearchPath;
- if (symbolSearchPath.empty()) {
- static const size_t bufferSize = 1024;
- std::unique_ptr<char[]> pathBuffer(new char[bufferSize]);
- GetModuleFileNameA(NULL, pathBuffer.get(), bufferSize);
- boost::filesystem::path exePath(pathBuffer.get());
- symbolSearchPath = exePath.parent_path().string();
- symbolSearchPath += ";C:\\Windows\\System32;C:\\Windows";
- }
- return symbolSearchPath.c_str();
+ if (symbolSearchPath.empty()) {
+ static const size_t bufferSize = 1024;
+ std::unique_ptr<char[]> pathBuffer(new char[bufferSize]);
+ GetModuleFileNameA(NULL, pathBuffer.get(), bufferSize);
+ boost::filesystem::path exePath(pathBuffer.get());
+ symbolSearchPath = exePath.parent_path().string();
+ symbolSearchPath += ";C:\\Windows\\System32;C:\\Windows";
}
+ return symbolSearchPath.c_str();
+}
- /**
- * Get the display name of the executable module containing the specified address.
- *
- * @param process Process handle
- * @param address Address to find
- * @param returnedModuleName Returned module name
- */
- static void getModuleName( HANDLE process, DWORD64 address, std::string* returnedModuleName ) {
- IMAGEHLP_MODULE64 module64;
- memset ( &module64, 0, sizeof(module64) );
- module64.SizeOfStruct = sizeof(module64);
- BOOL ret = SymGetModuleInfo64( process, address, &module64 );
- if ( FALSE == ret ) {
- returnedModuleName->clear();
- return;
- }
- char* moduleName = module64.LoadedImageName;
- char* backslash = strrchr( moduleName, '\\' );
- if ( backslash ) {
- moduleName = backslash + 1;
- }
- *returnedModuleName = moduleName;
+/**
+ * Get the display name of the executable module containing the specified address.
+ *
+ * @param process Process handle
+ * @param address Address to find
+ * @param returnedModuleName Returned module name
+ */
+static void getModuleName(HANDLE process, DWORD64 address, std::string* returnedModuleName) {
+ IMAGEHLP_MODULE64 module64;
+ memset(&module64, 0, sizeof(module64));
+ module64.SizeOfStruct = sizeof(module64);
+ BOOL ret = SymGetModuleInfo64(process, address, &module64);
+ if (FALSE == ret) {
+ returnedModuleName->clear();
+ return;
+ }
+ char* moduleName = module64.LoadedImageName;
+ char* backslash = strrchr(moduleName, '\\');
+ if (backslash) {
+ moduleName = backslash + 1;
}
+ *returnedModuleName = moduleName;
+}
- /**
- * Get the display name and line number of the source file containing the specified address.
- *
- * @param process Process handle
- * @param address Address to find
- * @param returnedSourceAndLine Returned source code file name with line number
- */
- static void getSourceFileAndLineNumber( HANDLE process,
- DWORD64 address,
- std::string* returnedSourceAndLine ) {
- IMAGEHLP_LINE64 line64;
- memset( &line64, 0, sizeof(line64) );
- line64.SizeOfStruct = sizeof(line64);
- DWORD displacement32;
- BOOL ret = SymGetLineFromAddr64( process, address, &displacement32, &line64 );
- if ( FALSE == ret ) {
- returnedSourceAndLine->clear();
- return;
- }
+/**
+ * Get the display name and line number of the source file containing the specified address.
+ *
+ * @param process Process handle
+ * @param address Address to find
+ * @param returnedSourceAndLine Returned source code file name with line number
+ */
+static void getSourceFileAndLineNumber(HANDLE process,
+ DWORD64 address,
+ std::string* returnedSourceAndLine) {
+ IMAGEHLP_LINE64 line64;
+ memset(&line64, 0, sizeof(line64));
+ line64.SizeOfStruct = sizeof(line64);
+ DWORD displacement32;
+ BOOL ret = SymGetLineFromAddr64(process, address, &displacement32, &line64);
+ if (FALSE == ret) {
+ returnedSourceAndLine->clear();
+ return;
+ }
- std::string filename( line64.FileName );
- std::string::size_type start = filename.find( "\\src\\mongo\\" );
- if ( start == std::string::npos ) {
- start = filename.find( "\\src\\third_party\\" );
- }
- if ( start != std::string::npos ) {
- std::string shorter( "..." );
- shorter += filename.substr( start );
- filename.swap( shorter );
- }
- static const size_t bufferSize = 32;
- std::unique_ptr<char[]> lineNumber( new char[bufferSize] );
- _snprintf( lineNumber.get(), bufferSize, "(%u)", line64.LineNumber );
- filename += lineNumber.get();
- returnedSourceAndLine->swap( filename );
+ std::string filename(line64.FileName);
+ std::string::size_type start = filename.find("\\src\\mongo\\");
+ if (start == std::string::npos) {
+ start = filename.find("\\src\\third_party\\");
}
+ if (start != std::string::npos) {
+ std::string shorter("...");
+ shorter += filename.substr(start);
+ filename.swap(shorter);
+ }
+ static const size_t bufferSize = 32;
+ std::unique_ptr<char[]> lineNumber(new char[bufferSize]);
+ _snprintf(lineNumber.get(), bufferSize, "(%u)", line64.LineNumber);
+ filename += lineNumber.get();
+ returnedSourceAndLine->swap(filename);
+}
- /**
- * Get the display text of the symbol and offset of the specified address.
- *
- * @param process Process handle
- * @param address Address to find
- * @param symbolInfo Caller's pre-built SYMBOL_INFO struct (for efficiency)
- * @param returnedSymbolAndOffset Returned symbol and offset
- */
- static void getsymbolAndOffset( HANDLE process,
- DWORD64 address,
- SYMBOL_INFO* symbolInfo,
- std::string* returnedSymbolAndOffset ) {
- DWORD64 displacement64;
- BOOL ret = SymFromAddr( process, address, &displacement64, symbolInfo );
- if ( FALSE == ret ) {
- *returnedSymbolAndOffset = "???";
- return;
- }
- std::string symbolString( symbolInfo->Name );
- static const size_t bufferSize = 32;
- std::unique_ptr<char[]> symbolOffset( new char[bufferSize] );
- _snprintf( symbolOffset.get(), bufferSize, "+0x%x", displacement64 );
- symbolString += symbolOffset.get();
- returnedSymbolAndOffset->swap( symbolString );
+/**
+ * Get the display text of the symbol and offset of the specified address.
+ *
+ * @param process Process handle
+ * @param address Address to find
+ * @param symbolInfo Caller's pre-built SYMBOL_INFO struct (for efficiency)
+ * @param returnedSymbolAndOffset Returned symbol and offset
+ */
+static void getsymbolAndOffset(HANDLE process,
+ DWORD64 address,
+ SYMBOL_INFO* symbolInfo,
+ std::string* returnedSymbolAndOffset) {
+ DWORD64 displacement64;
+ BOOL ret = SymFromAddr(process, address, &displacement64, symbolInfo);
+ if (FALSE == ret) {
+ *returnedSymbolAndOffset = "???";
+ return;
}
+ std::string symbolString(symbolInfo->Name);
+ static const size_t bufferSize = 32;
+ std::unique_ptr<char[]> symbolOffset(new char[bufferSize]);
+ _snprintf(symbolOffset.get(), bufferSize, "+0x%x", displacement64);
+ symbolString += symbolOffset.get();
+ returnedSymbolAndOffset->swap(symbolString);
+}
- struct TraceItem {
- std::string moduleName;
- std::string sourceAndLine;
- std::string symbolAndOffset;
- };
+struct TraceItem {
+ std::string moduleName;
+ std::string sourceAndLine;
+ std::string symbolAndOffset;
+};
- static const int maxBackTraceFrames = 100;
+static const int maxBackTraceFrames = 100;
- /**
- * Print a stack backtrace for the current thread to the specified ostream.
- *
- * @param os ostream& to receive printed stack backtrace
- */
- void printStackTrace( std::ostream& os ) {
- CONTEXT context;
- memset( &context, 0, sizeof(context) );
- context.ContextFlags = CONTEXT_CONTROL;
- RtlCaptureContext( &context );
- printWindowsStackTrace( context, os );
- }
+/**
+ * Print a stack backtrace for the current thread to the specified ostream.
+ *
+ * @param os ostream& to receive printed stack backtrace
+ */
+void printStackTrace(std::ostream& os) {
+ CONTEXT context;
+ memset(&context, 0, sizeof(context));
+ context.ContextFlags = CONTEXT_CONTROL;
+ RtlCaptureContext(&context);
+ printWindowsStackTrace(context, os);
+}
- static SimpleMutex _stackTraceMutex;
+static SimpleMutex _stackTraceMutex;
- /**
- * Print stack trace (using a specified stack context) to "os"
- *
- * @param context CONTEXT record for stack trace
- * @param os ostream& to receive printed stack backtrace
- */
- void printWindowsStackTrace( CONTEXT& context, std::ostream& os ) {
- stdx::lock_guard<SimpleMutex> lk(_stackTraceMutex);
- HANDLE process = GetCurrentProcess();
- BOOL ret = SymInitialize(process, getSymbolSearchPath(process), TRUE);
- if ( ret == FALSE ) {
- DWORD dosError = GetLastError();
- log() << "Stack trace failed, SymInitialize failed with error " <<
- std::dec << dosError << std::endl;
- return;
- }
- DWORD options = SymGetOptions();
- options |= SYMOPT_LOAD_LINES | SYMOPT_FAIL_CRITICAL_ERRORS;
- SymSetOptions( options );
+/**
+ * Print stack trace (using a specified stack context) to "os"
+ *
+ * @param context CONTEXT record for stack trace
+ * @param os ostream& to receive printed stack backtrace
+ */
+void printWindowsStackTrace(CONTEXT& context, std::ostream& os) {
+ stdx::lock_guard<SimpleMutex> lk(_stackTraceMutex);
+ HANDLE process = GetCurrentProcess();
+ BOOL ret = SymInitialize(process, getSymbolSearchPath(process), TRUE);
+ if (ret == FALSE) {
+ DWORD dosError = GetLastError();
+ log() << "Stack trace failed, SymInitialize failed with error " << std::dec << dosError
+ << std::endl;
+ return;
+ }
+ DWORD options = SymGetOptions();
+ options |= SYMOPT_LOAD_LINES | SYMOPT_FAIL_CRITICAL_ERRORS;
+ SymSetOptions(options);
- STACKFRAME64 frame64;
- memset( &frame64, 0, sizeof(frame64) );
+ STACKFRAME64 frame64;
+ memset(&frame64, 0, sizeof(frame64));
#if defined(_M_AMD64)
- DWORD imageType = IMAGE_FILE_MACHINE_AMD64;
- frame64.AddrPC.Offset = context.Rip;
- frame64.AddrFrame.Offset = context.Rbp;
- frame64.AddrStack.Offset = context.Rsp;
+ DWORD imageType = IMAGE_FILE_MACHINE_AMD64;
+ frame64.AddrPC.Offset = context.Rip;
+ frame64.AddrFrame.Offset = context.Rbp;
+ frame64.AddrStack.Offset = context.Rsp;
#elif defined(_M_IX86)
- DWORD imageType = IMAGE_FILE_MACHINE_I386;
- frame64.AddrPC.Offset = context.Eip;
- frame64.AddrFrame.Offset = context.Ebp;
- frame64.AddrStack.Offset = context.Esp;
+ DWORD imageType = IMAGE_FILE_MACHINE_I386;
+ frame64.AddrPC.Offset = context.Eip;
+ frame64.AddrFrame.Offset = context.Ebp;
+ frame64.AddrStack.Offset = context.Esp;
#else
#error Neither _M_IX86 nor _M_AMD64 were defined
#endif
- frame64.AddrPC.Mode = AddrModeFlat;
- frame64.AddrFrame.Mode = AddrModeFlat;
- frame64.AddrStack.Mode = AddrModeFlat;
+ frame64.AddrPC.Mode = AddrModeFlat;
+ frame64.AddrFrame.Mode = AddrModeFlat;
+ frame64.AddrStack.Mode = AddrModeFlat;
- const size_t nameSize = 1024;
- const size_t symbolBufferSize = sizeof(SYMBOL_INFO) + nameSize;
- std::unique_ptr<char[]> symbolCharBuffer( new char[symbolBufferSize] );
- memset( symbolCharBuffer.get(), 0, symbolBufferSize );
- SYMBOL_INFO* symbolBuffer = reinterpret_cast<SYMBOL_INFO*>( symbolCharBuffer.get() );
- symbolBuffer->SizeOfStruct = sizeof(SYMBOL_INFO);
- symbolBuffer->MaxNameLen = nameSize;
+ const size_t nameSize = 1024;
+ const size_t symbolBufferSize = sizeof(SYMBOL_INFO) + nameSize;
+ std::unique_ptr<char[]> symbolCharBuffer(new char[symbolBufferSize]);
+ memset(symbolCharBuffer.get(), 0, symbolBufferSize);
+ SYMBOL_INFO* symbolBuffer = reinterpret_cast<SYMBOL_INFO*>(symbolCharBuffer.get());
+ symbolBuffer->SizeOfStruct = sizeof(SYMBOL_INFO);
+ symbolBuffer->MaxNameLen = nameSize;
- // build list
- std::vector<TraceItem> traceList;
- TraceItem traceItem;
- size_t moduleWidth = 0;
- size_t sourceWidth = 0;
- for ( size_t i = 0; i < maxBackTraceFrames; ++i ) {
- ret = StackWalk64( imageType,
- process,
- GetCurrentThread(),
- &frame64,
- &context,
- NULL,
- NULL,
- NULL,
- NULL );
- if ( ret == FALSE || frame64.AddrReturn.Offset == 0 ) {
- break;
- }
- DWORD64 address = frame64.AddrPC.Offset;
- getModuleName( process, address, &traceItem.moduleName );
- size_t width = traceItem.moduleName.length();
- if ( width > moduleWidth ) {
- moduleWidth = width;
- }
- getSourceFileAndLineNumber( process, address, &traceItem.sourceAndLine );
- width = traceItem.sourceAndLine.length();
- if ( width > sourceWidth ) {
- sourceWidth = width;
- }
- getsymbolAndOffset( process, address, symbolBuffer, &traceItem.symbolAndOffset );
- traceList.push_back( traceItem );
+ // build list
+ std::vector<TraceItem> traceList;
+ TraceItem traceItem;
+ size_t moduleWidth = 0;
+ size_t sourceWidth = 0;
+ for (size_t i = 0; i < maxBackTraceFrames; ++i) {
+ ret = StackWalk64(
+ imageType, process, GetCurrentThread(), &frame64, &context, NULL, NULL, NULL, NULL);
+ if (ret == FALSE || frame64.AddrReturn.Offset == 0) {
+ break;
}
- SymCleanup( process );
-
- // print list
- ++moduleWidth;
- ++sourceWidth;
- size_t frameCount = traceList.size();
- for ( size_t i = 0; i < frameCount; ++i ) {
- std::stringstream ss;
- ss << traceList[i].moduleName << " ";
- size_t width = traceList[i].moduleName.length();
- while ( width < moduleWidth ) {
- ss << " ";
- ++width;
- }
- ss << traceList[i].sourceAndLine << " ";
- width = traceList[i].sourceAndLine.length();
- while ( width < sourceWidth ) {
- ss << " ";
- ++width;
- }
- ss << traceList[i].symbolAndOffset;
- log() << ss.str() << std::endl;
+ DWORD64 address = frame64.AddrPC.Offset;
+ getModuleName(process, address, &traceItem.moduleName);
+ size_t width = traceItem.moduleName.length();
+ if (width > moduleWidth) {
+ moduleWidth = width;
+ }
+ getSourceFileAndLineNumber(process, address, &traceItem.sourceAndLine);
+ width = traceItem.sourceAndLine.length();
+ if (width > sourceWidth) {
+ sourceWidth = width;
}
+ getsymbolAndOffset(process, address, symbolBuffer, &traceItem.symbolAndOffset);
+ traceList.push_back(traceItem);
}
+ SymCleanup(process);
- // Print error message from C runtime, then fassert
- int crtDebugCallback(int, char* originalMessage, int*) {
- StringData message(originalMessage);
- log() << "*** C runtime error: "
- << message.substr(0, message.find('\n'))
- << ", terminating" << std::endl;
- fassertFailed( 17006 );
+ // print list
+ ++moduleWidth;
+ ++sourceWidth;
+ size_t frameCount = traceList.size();
+ for (size_t i = 0; i < frameCount; ++i) {
+ std::stringstream ss;
+ ss << traceList[i].moduleName << " ";
+ size_t width = traceList[i].moduleName.length();
+ while (width < moduleWidth) {
+ ss << " ";
+ ++width;
+ }
+ ss << traceList[i].sourceAndLine << " ";
+ width = traceList[i].sourceAndLine.length();
+ while (width < sourceWidth) {
+ ss << " ";
+ ++width;
+ }
+ ss << traceList[i].symbolAndOffset;
+ log() << ss.str() << std::endl;
}
+}
+// Print error message from C runtime, then fassert
+int crtDebugCallback(int, char* originalMessage, int*) {
+ StringData message(originalMessage);
+ log() << "*** C runtime error: " << message.substr(0, message.find('\n')) << ", terminating"
+ << std::endl;
+ fassertFailed(17006);
+}
}