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__ |