36LPTOP_LEVEL_EXCEPTION_FILTER g_previous_filter =
nullptr;
38bool g_dump_stack_in_signal_handler =
true;
39bool g_initialized_symbols =
false;
40DWORD g_init_error = ERROR_SUCCESS;
44long WINAPI StackDumpExceptionFilter(EXCEPTION_POINTERS* info) {
45 if (g_dump_stack_in_signal_handler) {
46 debug::StackTrace(info).Print();
48 if (g_previous_filter)
return g_previous_filter(info);
49 return EXCEPTION_CONTINUE_SEARCH;
52bool InitializeSymbols() {
53 if (g_initialized_symbols)
return g_init_error == ERROR_SUCCESS;
54 g_initialized_symbols =
true;
57 SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
58 if (!SymInitialize(GetCurrentProcess(),
nullptr, TRUE)) {
59 g_init_error = GetLastError();
72 const size_t kSymbolsArraySize = 1024;
73 std::unique_ptr<wchar_t[]> symbols_path(
new wchar_t[kSymbolsArraySize]);
77 if (!SymGetSearchPathW(GetCurrentProcess(), symbols_path.get(),
79 g_init_error = GetLastError();
83 wchar_t exe_path[MAX_PATH];
84 GetModuleFileName(
nullptr, exe_path, MAX_PATH);
85 std::wstring exe_path_wstring(exe_path);
88 std::wstring new_path(
89 std::wstring(symbols_path.get()) + L
";" +
90 exe_path_wstring.substr(0, exe_path_wstring.find_last_of(L
"\\/")));
91 if (!SymSetSearchPathW(GetCurrentProcess(), new_path.c_str())) {
92 g_init_error = GetLastError();
96 g_init_error = ERROR_SUCCESS;
109void OutputTraceToStream(
const void*
const* trace,
size_t count,
111 for (
size_t i = 0; (
i <
count) && os->good(); ++
i) {
112 const int kMaxNameLength = 256;
113 DWORD_PTR frame =
reinterpret_cast<DWORD_PTR
>(trace[
i]);
117 ULONG64 buffer[(
sizeof(SYMBOL_INFO) + kMaxNameLength *
sizeof(wchar_t) +
118 sizeof(ULONG64) - 1) /
120 memset(buffer, 0,
sizeof(buffer));
123 DWORD64 sym_displacement = 0;
124 PSYMBOL_INFO symbol =
reinterpret_cast<PSYMBOL_INFO
>(&buffer[0]);
125 symbol->SizeOfStruct =
sizeof(SYMBOL_INFO);
126 symbol->MaxNameLen = kMaxNameLength - 1;
128 SymFromAddr(GetCurrentProcess(), frame, &sym_displacement, symbol);
131 DWORD line_displacement = 0;
132 IMAGEHLP_LINE64 line = {};
133 line.SizeOfStruct =
sizeof(IMAGEHLP_LINE64);
134 BOOL has_line = SymGetLineFromAddr64(GetCurrentProcess(), frame,
135 &line_displacement, &line);
140 (*os) << symbol->Name <<
" [0x" << trace[
i] <<
"+" << sym_displacement
144 (*os) <<
"(No symbol) [0x" << trace[
i] <<
"]";
147 (*os) <<
" (" << line.FileName <<
":" << line.LineNumber <<
")";
158 g_previous_filter = SetUnhandledExceptionFilter(&StackDumpExceptionFilter);
159 g_dump_stack_in_signal_handler =
true;
164 return InitializeSymbols();
168 g_dump_stack_in_signal_handler =
false;
177 InitTrace(exception_pointers->ContextRecord);
182void StackTrace::InitTrace(
const CONTEXT* context_record) {
187 CONTEXT context_copy;
188 memcpy(&context_copy, context_record,
sizeof(context_copy));
189 context_copy.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
194 STACKFRAME64 stack_frame;
195 memset(&stack_frame, 0,
sizeof(stack_frame));
198 int machine_type = IMAGE_FILE_MACHINE_AMD64;
199 stack_frame.AddrPC.Offset = context_record->Rip;
200 stack_frame.AddrFrame.Offset = context_record->Rbp;
201 stack_frame.AddrStack.Offset = context_record->Rsp;
202#elif defined(_M_ARM64)
203 int machine_type = IMAGE_FILE_MACHINE_ARM64;
204 stack_frame.AddrPC.Offset = context_record->Pc;
205 stack_frame.AddrFrame.Offset = context_record->Fp;
206 stack_frame.AddrStack.Offset = context_record->Sp;
208#error Unsupported Arch
211 int machine_type = IMAGE_FILE_MACHINE_I386;
212 stack_frame.AddrPC.Offset = context_record->Eip;
213 stack_frame.AddrFrame.Offset = context_record->Ebp;
214 stack_frame.AddrStack.Offset = context_record->Esp;
216 stack_frame.AddrPC.Mode = AddrModeFlat;
217 stack_frame.AddrFrame.Mode = AddrModeFlat;
218 stack_frame.AddrStack.Mode = AddrModeFlat;
219 while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(),
220 &stack_frame, &context_copy,
nullptr,
221 &SymFunctionTableAccess64, &SymGetModuleBase64,
nullptr) &&
223 trace_[
count_++] =
reinterpret_cast<void*
>(stack_frame.AddrPC.Offset);
233 if (g_init_error != ERROR_SUCCESS) {
234 (*os) <<
"Error initializing symbols (" << g_init_error
235 <<
"). Dumping unresolved backtrace:\n";
236 for (
size_t i = 0; (
i <
count_) && os->good(); ++
i) {
237 (*os) <<
"\t" <<
trace_[
i] <<
"\n";
241 (*os) <<
"==== C stack trace ===============================\n";
void OutputToStream(std::ostream *os) const
void * trace_[kMaxTraces]
V8_BASE_EXPORT bool EnableInProcessStackDumping()
V8_BASE_EXPORT void DisableSignalStackDump()