| Index: src/platform-win32.cc
|
| diff --git a/src/platform-win32.cc b/src/platform-win32.cc
|
| index 073b21a011aae732b7db5dc15ca3b18c85e3858b..ea4f7ea11f4177bdbee4f5de2dca570e50985741 100644
|
| --- a/src/platform-win32.cc
|
| +++ b/src/platform-win32.cc
|
| @@ -1208,9 +1208,133 @@ void OS::SignalCodeMovingGC() {
|
| }
|
|
|
|
|
| +// Walk the stack using the facilities in dbghelp.dll and tlhelp32.dll
|
| +
|
| +// Switch off warning 4748 (/GS can not protect parameters and local variables
|
| +// from local buffer overrun because optimizations are disabled in function) as
|
| +// it is triggered by the use of inline assembler.
|
| +#pragma warning(push)
|
| +#pragma warning(disable : 4748)
|
| +int OS::StackWalk(Vector<OS::StackFrame> frames) {
|
| + BOOL ok;
|
| +
|
| + // Load the required functions from DLL's.
|
| + if (!LoadDbgHelpAndTlHelp32()) return kStackWalkError;
|
| +
|
| + // Get the process and thread handles.
|
| + HANDLE process_handle = GetCurrentProcess();
|
| + HANDLE thread_handle = GetCurrentThread();
|
| +
|
| + // Read the symbols.
|
| + if (!LoadSymbols(Isolate::Current(), process_handle)) return kStackWalkError;
|
| +
|
| + // Capture current context.
|
| + CONTEXT context;
|
| + RtlCaptureContext(&context);
|
| +
|
| + // Initialize the stack walking
|
| + STACKFRAME64 stack_frame;
|
| + memset(&stack_frame, 0, sizeof(stack_frame));
|
| +#ifdef _WIN64
|
| + stack_frame.AddrPC.Offset = context.Rip;
|
| + stack_frame.AddrFrame.Offset = context.Rbp;
|
| + stack_frame.AddrStack.Offset = context.Rsp;
|
| +#else
|
| + stack_frame.AddrPC.Offset = context.Eip;
|
| + stack_frame.AddrFrame.Offset = context.Ebp;
|
| + stack_frame.AddrStack.Offset = context.Esp;
|
| +#endif
|
| + stack_frame.AddrPC.Mode = AddrModeFlat;
|
| + stack_frame.AddrFrame.Mode = AddrModeFlat;
|
| + stack_frame.AddrStack.Mode = AddrModeFlat;
|
| + int frames_count = 0;
|
| +
|
| + // Collect stack frames.
|
| + int frames_size = frames.length();
|
| + while (frames_count < frames_size) {
|
| + ok = _StackWalk64(
|
| + IMAGE_FILE_MACHINE_I386, // MachineType
|
| + process_handle, // hProcess
|
| + thread_handle, // hThread
|
| + &stack_frame, // StackFrame
|
| + &context, // ContextRecord
|
| + NULL, // ReadMemoryRoutine
|
| + _SymFunctionTableAccess64, // FunctionTableAccessRoutine
|
| + _SymGetModuleBase64, // GetModuleBaseRoutine
|
| + NULL); // TranslateAddress
|
| + if (!ok) break;
|
| +
|
| + // Store the address.
|
| + ASSERT((stack_frame.AddrPC.Offset >> 32) == 0); // 32-bit address.
|
| + frames[frames_count].address =
|
| + reinterpret_cast<void*>(stack_frame.AddrPC.Offset);
|
| +
|
| + // Try to locate a symbol for this frame.
|
| + DWORD64 symbol_displacement;
|
| + SmartArrayPointer<IMAGEHLP_SYMBOL64> symbol(
|
| + NewArray<IMAGEHLP_SYMBOL64>(kStackWalkMaxNameLen));
|
| + if (symbol.is_empty()) return kStackWalkError; // Out of memory.
|
| + memset(*symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + kStackWalkMaxNameLen);
|
| + (*symbol)->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
| + (*symbol)->MaxNameLength = kStackWalkMaxNameLen;
|
| + ok = _SymGetSymFromAddr64(process_handle, // hProcess
|
| + stack_frame.AddrPC.Offset, // Address
|
| + &symbol_displacement, // Displacement
|
| + *symbol); // Symbol
|
| + if (ok) {
|
| + // Try to locate more source information for the symbol.
|
| + IMAGEHLP_LINE64 Line;
|
| + memset(&Line, 0, sizeof(Line));
|
| + Line.SizeOfStruct = sizeof(Line);
|
| + DWORD line_displacement;
|
| + ok = _SymGetLineFromAddr64(
|
| + process_handle, // hProcess
|
| + stack_frame.AddrPC.Offset, // dwAddr
|
| + &line_displacement, // pdwDisplacement
|
| + &Line); // Line
|
| + // Format a text representation of the frame based on the information
|
| + // available.
|
| + if (ok) {
|
| + SNPrintF(MutableCStrVector(frames[frames_count].text,
|
| + kStackWalkMaxTextLen),
|
| + "%s %s:%d:%d",
|
| + (*symbol)->Name, Line.FileName, Line.LineNumber,
|
| + line_displacement);
|
| + } else {
|
| + SNPrintF(MutableCStrVector(frames[frames_count].text,
|
| + kStackWalkMaxTextLen),
|
| + "%s",
|
| + (*symbol)->Name);
|
| + }
|
| + // Make sure line termination is in place.
|
| + frames[frames_count].text[kStackWalkMaxTextLen - 1] = '\0';
|
| + } else {
|
| + // No text representation of this frame
|
| + frames[frames_count].text[0] = '\0';
|
| +
|
| + // Continue if we are just missing a module (for non C/C++ frames a
|
| + // module will never be found).
|
| + int err = GetLastError();
|
| + if (err != ERROR_MOD_NOT_FOUND) {
|
| + break;
|
| + }
|
| + }
|
| +
|
| + frames_count++;
|
| + }
|
| +
|
| + // Return the number of frames filled in.
|
| + return frames_count;
|
| +}
|
| +
|
| +
|
| +// Restore warnings to previous settings.
|
| +#pragma warning(pop)
|
| +
|
| #else // __MINGW32__
|
| void OS::LogSharedLibraryAddresses(Isolate* isolate) { }
|
| void OS::SignalCodeMovingGC() { }
|
| +int OS::StackWalk(Vector<OS::StackFrame> frames) { return 0; }
|
| #endif // __MINGW32__
|
|
|
|
|
|
|