1155408Srwatson//===- Win32/Signals.cpp - Win32 Signals Implementation ---------*- C++ -*-===//
2155408Srwatson//
3155408Srwatson// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4155408Srwatson// See https://llvm.org/LICENSE.txt for license information.
5155408Srwatson// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6155408Srwatson//
7155408Srwatson//===----------------------------------------------------------------------===//
8155408Srwatson//
9155408Srwatson// This file provides the Win32 specific implementation of the Signals class.
10155408Srwatson//
11155408Srwatson//===----------------------------------------------------------------------===//
12155408Srwatson#include "llvm/Support/ConvertUTF.h"
13155408Srwatson#include "llvm/Support/ExitCodes.h"
14155408Srwatson#include "llvm/Support/FileSystem.h"
15155408Srwatson#include "llvm/Support/Path.h"
16155408Srwatson#include "llvm/Support/Process.h"
17155408Srwatson#include "llvm/Support/WindowsError.h"
18155408Srwatson#include <algorithm>
19155408Srwatson#include <io.h>
20155408Srwatson#include <signal.h>
21155408Srwatson#include <stdio.h>
22155408Srwatson
23155408Srwatson#include "llvm/Support/Format.h"
24155408Srwatson#include "llvm/Support/raw_ostream.h"
25155408Srwatson
26155408Srwatson// The Windows.h header must be after LLVM and standard headers.
27155408Srwatson#include "llvm/Support/Windows/WindowsSupport.h"
28155408Srwatson
29155408Srwatson#ifdef __MINGW32__
30155408Srwatson#include <imagehlp.h>
31155408Srwatson#else
32155408Srwatson#include <crtdbg.h>
33155408Srwatson#include <dbghelp.h>
34155408Srwatson#endif
35155408Srwatson#include <psapi.h>
36155408Srwatson
37155408Srwatson#ifdef _MSC_VER
38155408Srwatson#pragma comment(lib, "psapi.lib")
39155408Srwatson#elif __MINGW32__
40155408Srwatson// The version of g++ that comes with MinGW does *not* properly understand
41155408Srwatson// the ll format specifier for printf. However, MinGW passes the format
42155408Srwatson// specifiers on to the MSVCRT entirely, and the CRT understands the ll
43155408Srwatson// specifier. So these warnings are spurious in this case. Since we compile
44155408Srwatson// with -Wall, this will generate these warnings which should be ignored. So
45155408Srwatson// we will turn off the warnings for this just file. However, MinGW also does
46155408Srwatson// not support push and pop for diagnostics, so we have to manually turn it
47155408Srwatson// back on at the end of the file.
48155408Srwatson#pragma GCC diagnostic ignored "-Wformat"
49155408Srwatson#pragma GCC diagnostic ignored "-Wformat-extra-args"
50155408Srwatson
51156880Srwatson#if !defined(__MINGW64_VERSION_MAJOR)
52155408Srwatson// MinGW.org does not have updated support for the 64-bit versions of the
53155408Srwatson// DebugHlp APIs. So we will have to load them manually. The structures and
54155408Srwatson// method signatures were pulled from DbgHelp.h in the Windows Platform SDK,
55155408Srwatson// and adjusted for brevity.
56155408Srwatsontypedef struct _IMAGEHLP_LINE64 {
57155408Srwatson  DWORD SizeOfStruct;
58159269Srwatson  PVOID Key;
59159269Srwatson  DWORD LineNumber;
60155408Srwatson  PCHAR FileName;
61155408Srwatson  DWORD64 Address;
62155408Srwatson} IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;
63155408Srwatson
64155408Srwatsontypedef struct _IMAGEHLP_SYMBOL64 {
65155408Srwatson  DWORD SizeOfStruct;
66155408Srwatson  DWORD64 Address;
67155408Srwatson  DWORD Size;
68159269Srwatson  DWORD Flags;
69159269Srwatson  DWORD MaxNameLength;
70155408Srwatson  CHAR Name[1];
71155408Srwatson} IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;
72155408Srwatson
73155408Srwatsontypedef struct _tagADDRESS64 {
74156883Srwatson  DWORD64 Offset;
75156880Srwatson  WORD Segment;
76155408Srwatson  ADDRESS_MODE Mode;
77155408Srwatson} ADDRESS64, *LPADDRESS64;
78155408Srwatson
79155408Srwatsontypedef struct _KDHELP64 {
80155408Srwatson  DWORD64 Thread;
81155408Srwatson  DWORD ThCallbackStack;
82155408Srwatson  DWORD ThCallbackBStore;
83155408Srwatson  DWORD NextCallback;
84155408Srwatson  DWORD FramePointer;
85155408Srwatson  DWORD64 KiCallUserMode;
86155408Srwatson  DWORD64 KeUserCallbackDispatcher;
87155408Srwatson  DWORD64 SystemRangeStart;
88159269Srwatson  DWORD64 KiUserExceptionDispatcher;
89159269Srwatson  DWORD64 StackBase;
90159269Srwatson  DWORD64 StackLimit;
91159269Srwatson  DWORD64 Reserved[5];
92159269Srwatson} KDHELP64, *PKDHELP64;
93159269Srwatson
94159269Srwatsontypedef struct _tagSTACKFRAME64 {
95159269Srwatson  ADDRESS64 AddrPC;
96159269Srwatson  ADDRESS64 AddrReturn;
97159269Srwatson  ADDRESS64 AddrFrame;
98159269Srwatson  ADDRESS64 AddrStack;
99159269Srwatson  ADDRESS64 AddrBStore;
100159269Srwatson  PVOID FuncTableEntry;
101159269Srwatson  DWORD64 Params[4];
102159269Srwatson  BOOL Far;
103159269Srwatson  BOOL Virtual;
104159269Srwatson  DWORD64 Reserved[3];
105155408Srwatson  KDHELP64 KdHelp;
106155408Srwatson} STACKFRAME64, *LPSTACKFRAME64;
107155408Srwatson#endif // !defined(__MINGW64_VERSION_MAJOR)
108155408Srwatson#endif // __MINGW32__
109155408Srwatson
110155408Srwatsontypedef BOOL(__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(
111155408Srwatson    HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize,
112155408Srwatson    LPDWORD lpNumberOfBytesRead);
113155408Srwatson
114155408Srwatsontypedef PVOID(__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)(HANDLE ahProcess,
115155408Srwatson                                                           DWORD64 AddrBase);
116155408Srwatson
117155408Srwatsontypedef DWORD64(__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,
118155408Srwatson                                                       DWORD64 Address);
119155408Srwatson
120155408Srwatsontypedef DWORD64(__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,
121155408Srwatson                                                         HANDLE hThread,
122155408Srwatson                                                         LPADDRESS64 lpaddr);
123155408Srwatson
124155408Srwatsontypedef BOOL(WINAPI *fpMiniDumpWriteDump)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE,
125159269Srwatson                                          PMINIDUMP_EXCEPTION_INFORMATION,
126159269Srwatson                                          PMINIDUMP_USER_STREAM_INFORMATION,
127159269Srwatson                                          PMINIDUMP_CALLBACK_INFORMATION);
128159269Srwatsonstatic fpMiniDumpWriteDump fMiniDumpWriteDump;
129159269Srwatson
130159269Srwatsontypedef BOOL(WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64,
131159269Srwatson                                    PVOID, PREAD_PROCESS_MEMORY_ROUTINE64,
132159269Srwatson                                    PFUNCTION_TABLE_ACCESS_ROUTINE64,
133159269Srwatson                                    PGET_MODULE_BASE_ROUTINE64,
134159269Srwatson                                    PTRANSLATE_ADDRESS_ROUTINE64);
135159269Srwatsonstatic fpStackWalk64 fStackWalk64;
136159269Srwatson
137159269Srwatsontypedef DWORD64(WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64);
138155408Srwatsonstatic fpSymGetModuleBase64 fSymGetModuleBase64;
139155408Srwatson
140159269Srwatsontypedef BOOL(WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64,
141159269Srwatson                                            PIMAGEHLP_SYMBOL64);
142159269Srwatsonstatic fpSymGetSymFromAddr64 fSymGetSymFromAddr64;
143155408Srwatson
144155408Srwatsontypedef BOOL(WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64, PDWORD,
145155408Srwatson                                             PIMAGEHLP_LINE64);
146155408Srwatsonstatic fpSymGetLineFromAddr64 fSymGetLineFromAddr64;
147159269Srwatson
148155408Srwatsontypedef BOOL(WINAPI *fpSymGetModuleInfo64)(HANDLE hProcess, DWORD64 dwAddr,
149155408Srwatson                                           PIMAGEHLP_MODULE64 ModuleInfo);
150155408Srwatsonstatic fpSymGetModuleInfo64 fSymGetModuleInfo64;
151155408Srwatson
152155408Srwatsontypedef PVOID(WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64);
153155408Srwatsonstatic fpSymFunctionTableAccess64 fSymFunctionTableAccess64;
154159269Srwatson
155159269Srwatsontypedef DWORD(WINAPI *fpSymSetOptions)(DWORD);
156159269Srwatsonstatic fpSymSetOptions fSymSetOptions;
157155408Srwatson
158155408Srwatsontypedef BOOL(WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL);
159155408Srwatsonstatic fpSymInitialize fSymInitialize;
160155408Srwatson
161155408Srwatsontypedef BOOL(WINAPI *fpEnumerateLoadedModules)(HANDLE,
162155408Srwatson                                               PENUMLOADED_MODULES_CALLBACK64,
163155408Srwatson                                               PVOID);
164155408Srwatsonstatic fpEnumerateLoadedModules fEnumerateLoadedModules;
165155408Srwatson
166155408Srwatsonstatic bool isDebugHelpInitialized() {
167155408Srwatson  return fStackWalk64 && fSymInitialize && fSymSetOptions && fMiniDumpWriteDump;
168155408Srwatson}
169155408Srwatson
170155408Srwatsonstatic bool load64BitDebugHelp(void) {
171155408Srwatson  HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll");
172155408Srwatson  if (hLib) {
173155408Srwatson    fMiniDumpWriteDump =
174155408Srwatson        (fpMiniDumpWriteDump)::GetProcAddress(hLib, "MiniDumpWriteDump");
175161582Srwatson    fStackWalk64 = (fpStackWalk64)::GetProcAddress(hLib, "StackWalk64");
176155408Srwatson    fSymGetModuleBase64 =
177155408Srwatson        (fpSymGetModuleBase64)::GetProcAddress(hLib, "SymGetModuleBase64");
178155408Srwatson    fSymGetSymFromAddr64 =
179159269Srwatson        (fpSymGetSymFromAddr64)::GetProcAddress(hLib, "SymGetSymFromAddr64");
180155408Srwatson    fSymGetLineFromAddr64 =
181155408Srwatson        (fpSymGetLineFromAddr64)::GetProcAddress(hLib, "SymGetLineFromAddr64");
182155408Srwatson    fSymGetModuleInfo64 =
183155408Srwatson        (fpSymGetModuleInfo64)::GetProcAddress(hLib, "SymGetModuleInfo64");
184155408Srwatson    fSymFunctionTableAccess64 = (fpSymFunctionTableAccess64)::GetProcAddress(
185161582Srwatson        hLib, "SymFunctionTableAccess64");
186155408Srwatson    fSymSetOptions = (fpSymSetOptions)::GetProcAddress(hLib, "SymSetOptions");
187155408Srwatson    fSymInitialize = (fpSymInitialize)::GetProcAddress(hLib, "SymInitialize");
188155408Srwatson    fEnumerateLoadedModules = (fpEnumerateLoadedModules)::GetProcAddress(
189161582Srwatson        hLib, "EnumerateLoadedModules64");
190161582Srwatson  }
191161582Srwatson  return isDebugHelpInitialized();
192161582Srwatson}
193161582Srwatson
194161582Srwatsonusing namespace llvm;
195161582Srwatson
196161582Srwatson// Forward declare.
197161582Srwatsonstatic LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep);
198161582Srwatsonstatic BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType);
199155408Srwatson
200155408Srwatson// The function to call if ctrl-c is pressed.
201155408Srwatsonstatic void (*InterruptFunction)() = 0;
202155408Srwatson
203155408Srwatsonstatic std::vector<std::string> *FilesToRemove = NULL;
204155408Srwatsonstatic bool RegisteredUnhandledExceptionFilter = false;
205155408Srwatsonstatic bool CleanupExecuted = false;
206155408Srwatsonstatic PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL;
207155408Srwatson
208155408Srwatson/// The function to call on "SIGPIPE" (one-time use only).
209155408Srwatsonstatic std::atomic<void (*)()> OneShotPipeSignalFunction(nullptr);
210155408Srwatson
211155408Srwatson// Windows creates a new thread to execute the console handler when an event
212155408Srwatson// (such as CTRL/C) occurs.  This causes concurrency issues with the above
213155408Srwatson// globals which this critical section addresses.
214155408Srwatsonstatic CRITICAL_SECTION CriticalSection;
215155408Srwatsonstatic bool CriticalSectionInitialized = false;
216155408Srwatson
217155408Srwatsonstatic StringRef Argv0;
218155408Srwatson
219159269Srwatsonenum {
220159269Srwatson#if defined(_M_X64)
221159269Srwatson  NativeMachineType = IMAGE_FILE_MACHINE_AMD64
222159269Srwatson#elif defined(_M_ARM64)
223159269Srwatson  NativeMachineType = IMAGE_FILE_MACHINE_ARM64
224159269Srwatson#elif defined(_M_IX86)
225159269Srwatson  NativeMachineType = IMAGE_FILE_MACHINE_I386
226159269Srwatson#elif defined(_M_ARM)
227159269Srwatson  NativeMachineType = IMAGE_FILE_MACHINE_ARMNT
228159269Srwatson#else
229159269Srwatson  NativeMachineType = IMAGE_FILE_MACHINE_UNKNOWN
230159269Srwatson#endif
231159269Srwatson};
232159269Srwatson
233159269Srwatsonstatic bool printStackTraceWithLLVMSymbolizer(llvm::raw_ostream &OS,
234159269Srwatson                                              HANDLE hProcess, HANDLE hThread,
235159269Srwatson                                              STACKFRAME64 &StackFrameOrig,
236159269Srwatson                                              CONTEXT *ContextOrig) {
237159269Srwatson  // StackWalk64 modifies the incoming stack frame and context, so copy them.
238159269Srwatson  STACKFRAME64 StackFrame = StackFrameOrig;
239159269Srwatson
240159269Srwatson  // Copy the register context so that we don't modify it while we unwind. We
241159269Srwatson  // could use InitializeContext + CopyContext, but that's only required to get
242159269Srwatson  // at AVX registers, which typically aren't needed by StackWalk64. Reduce the
243159269Srwatson  // flag set to indicate that there's less data.
244159269Srwatson  CONTEXT Context = *ContextOrig;
245159269Srwatson  Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
246159269Srwatson
247159269Srwatson  static void *StackTrace[256];
248159269Srwatson  size_t Depth = 0;
249159269Srwatson  while (fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame,
250159269Srwatson                      &Context, 0, fSymFunctionTableAccess64,
251159269Srwatson                      fSymGetModuleBase64, 0)) {
252159269Srwatson    if (StackFrame.AddrFrame.Offset == 0)
253159269Srwatson      break;
254159269Srwatson    StackTrace[Depth++] = (void *)(uintptr_t)StackFrame.AddrPC.Offset;
255159269Srwatson    if (Depth >= std::size(StackTrace))
256159269Srwatson      break;
257159269Srwatson  }
258159269Srwatson
259159269Srwatson  return printSymbolizedStackTrace(Argv0, &StackTrace[0], Depth, OS);
260159269Srwatson}
261159269Srwatson
262159269Srwatsonnamespace {
263159269Srwatsonstruct FindModuleData {
264159269Srwatson  void **StackTrace;
265159269Srwatson  int Depth;
266159269Srwatson  const char **Modules;
267159269Srwatson  intptr_t *Offsets;
268159269Srwatson  StringSaver *StrPool;
269159269Srwatson};
270159269Srwatson} // namespace
271159269Srwatson
272159269Srwatsonstatic BOOL CALLBACK findModuleCallback(PCSTR ModuleName, DWORD64 ModuleBase,
273159269Srwatson                                        ULONG ModuleSize, void *VoidData) {
274159269Srwatson  FindModuleData *Data = (FindModuleData *)VoidData;
275159269Srwatson  intptr_t Beg = ModuleBase;
276159269Srwatson  intptr_t End = Beg + ModuleSize;
277159269Srwatson  for (int I = 0; I < Data->Depth; I++) {
278159269Srwatson    if (Data->Modules[I])
279159269Srwatson      continue;
280159269Srwatson    intptr_t Addr = (intptr_t)Data->StackTrace[I];
281159269Srwatson    if (Beg <= Addr && Addr < End) {
282159269Srwatson      Data->Modules[I] = Data->StrPool->save(ModuleName).data();
283159269Srwatson      Data->Offsets[I] = Addr - Beg;
284159269Srwatson    }
285159269Srwatson  }
286159269Srwatson  return TRUE;
287159269Srwatson}
288159269Srwatson
289159269Srwatsonstatic bool findModulesAndOffsets(void **StackTrace, int Depth,
290159269Srwatson                                  const char **Modules, intptr_t *Offsets,
291159269Srwatson                                  const char *MainExecutableName,
292159269Srwatson                                  StringSaver &StrPool) {
293159269Srwatson  if (!fEnumerateLoadedModules)
294159269Srwatson    return false;
295159269Srwatson  FindModuleData Data;
296159269Srwatson  Data.StackTrace = StackTrace;
297159269Srwatson  Data.Depth = Depth;
298159269Srwatson  Data.Modules = Modules;
299159269Srwatson  Data.Offsets = Offsets;
300159269Srwatson  Data.StrPool = &StrPool;
301159269Srwatson  fEnumerateLoadedModules(GetCurrentProcess(), findModuleCallback, &Data);
302159269Srwatson  return true;
303159269Srwatson}
304159269Srwatson
305159269Srwatsonstatic bool printMarkupContext(llvm::raw_ostream &OS,
306159269Srwatson                               const char *MainExecutableName) {
307159269Srwatson  return false;
308159269Srwatson}
309159269Srwatson
310159269Srwatsonstatic void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE hProcess,
311159269Srwatson                                     HANDLE hThread, STACKFRAME64 &StackFrame,
312159269Srwatson                                     CONTEXT *Context) {
313159269Srwatson  // It's possible that DbgHelp.dll hasn't been loaded yet (e.g. if this
314159269Srwatson  // function is called before the main program called `llvm::InitLLVM`).
315159269Srwatson  // In this case just return, not stacktrace will be printed.
316159269Srwatson  if (!isDebugHelpInitialized())
317159269Srwatson    return;
318159269Srwatson
319159269Srwatson  // Initialize the symbol handler.
320159269Srwatson  fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
321159269Srwatson  fSymInitialize(hProcess, NULL, TRUE);
322159269Srwatson
323159269Srwatson  // Try llvm-symbolizer first. llvm-symbolizer knows how to deal with both PDBs
324159269Srwatson  // and DWARF, so it should do a good job regardless of what debug info or
325159269Srwatson  // linker is in use.
326159269Srwatson  if (printStackTraceWithLLVMSymbolizer(OS, hProcess, hThread, StackFrame,
327159269Srwatson                                        Context)) {
328159269Srwatson    return;
329159269Srwatson  }
330159269Srwatson
331159269Srwatson  while (true) {
332159269Srwatson    if (!fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame,
333159269Srwatson                      Context, 0, fSymFunctionTableAccess64,
334159269Srwatson                      fSymGetModuleBase64, 0)) {
335159269Srwatson      break;
336159269Srwatson    }
337159269Srwatson
338159269Srwatson    if (StackFrame.AddrFrame.Offset == 0)
339159269Srwatson      break;
340159269Srwatson
341159269Srwatson    using namespace llvm;
342159269Srwatson    // Print the PC in hexadecimal.
343159269Srwatson    DWORD64 PC = StackFrame.AddrPC.Offset;
344159269Srwatson#if defined(_M_X64) || defined(_M_ARM64)
345159269Srwatson    OS << format("0x%016llX", PC);
346159269Srwatson#elif defined(_M_IX86) || defined(_M_ARM)
347159269Srwatson    OS << format("0x%08lX", static_cast<DWORD>(PC));
348159269Srwatson#endif
349159269Srwatson
350159269Srwatson    // Verify the PC belongs to a module in this process.
351159269Srwatson    if (!fSymGetModuleBase64(hProcess, PC)) {
352159269Srwatson      OS << " <unknown module>\n";
353159269Srwatson      continue;
354159269Srwatson    }
355159269Srwatson
356159269Srwatson    IMAGEHLP_MODULE64 M;
357159269Srwatson    memset(&M, 0, sizeof(IMAGEHLP_MODULE64));
358159269Srwatson    M.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
359159269Srwatson    if (fSymGetModuleInfo64(hProcess, fSymGetModuleBase64(hProcess, PC), &M)) {
360159269Srwatson      DWORD64 const disp = PC - M.BaseOfImage;
361159269Srwatson      OS << format(", %s(0x%016llX) + 0x%llX byte(s)",
362159269Srwatson                   static_cast<char *>(M.ImageName), M.BaseOfImage,
363159269Srwatson                   static_cast<long long>(disp));
364159269Srwatson    } else {
365159269Srwatson      OS << ", <unknown module>";
366159269Srwatson    }
367159269Srwatson
368159269Srwatson    // Print the symbol name.
369159269Srwatson    char buffer[512];
370159269Srwatson    IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer);
371159269Srwatson    memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64));
372159269Srwatson    symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
373159269Srwatson    symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64);
374159269Srwatson
375159269Srwatson    DWORD64 dwDisp;
376159269Srwatson    if (!fSymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) {
377159269Srwatson      OS << '\n';
378159269Srwatson      continue;
379159269Srwatson    }
380159269Srwatson
381159269Srwatson    buffer[511] = 0;
382159269Srwatson    OS << format(", %s() + 0x%llX byte(s)", static_cast<char *>(symbol->Name),
383159269Srwatson                 static_cast<long long>(dwDisp));
384159269Srwatson
385159269Srwatson    // Print the source file and line number information.
386159269Srwatson    IMAGEHLP_LINE64 line = {};
387159269Srwatson    DWORD dwLineDisp;
388159269Srwatson    line.SizeOfStruct = sizeof(line);
389159269Srwatson    if (fSymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) {
390159269Srwatson      OS << format(", %s, line %lu + 0x%lX byte(s)", line.FileName,
391159269Srwatson                   line.LineNumber, dwLineDisp);
392159269Srwatson    }
393159269Srwatson
394159269Srwatson    OS << '\n';
395159269Srwatson  }
396159269Srwatson}
397159269Srwatson
398155408Srwatsonnamespace llvm {
399155408Srwatson
400155408Srwatson//===----------------------------------------------------------------------===//
401155408Srwatson//=== WARNING: Implementation here must contain only Win32 specific code
402155408Srwatson//===          and must not be UNIX code
403155408Srwatson//===----------------------------------------------------------------------===//
404155408Srwatson
405155408Srwatson#ifdef _MSC_VER
406155408Srwatson/// Emulates hitting "retry" from an "abort, retry, ignore" CRT debug report
407155408Srwatson/// dialog. "retry" raises an exception which ultimately triggers our stack
408155408Srwatson/// dumper.
409155408Srwatsonstatic LLVM_ATTRIBUTE_UNUSED int
410155408SrwatsonAvoidMessageBoxHook(int ReportType, char *Message, int *Return) {
411155408Srwatson  // Set *Return to the retry code for the return value of _CrtDbgReport:
412156292Srwatson  // http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx
413155408Srwatson  // This may also trigger just-in-time debugging via DebugBreak().
414155408Srwatson  if (Return)
415155408Srwatson    *Return = 1;
416155408Srwatson  // Don't call _CrtDbgReport.
417155408Srwatson  return TRUE;
418155408Srwatson}
419155408Srwatson
420155408Srwatson#endif
421155408Srwatson
422155408Srwatsonextern "C" void HandleAbort(int Sig) {
423155408Srwatson  if (Sig == SIGABRT) {
424155408Srwatson    LLVM_BUILTIN_TRAP;
425155408Srwatson  }
426155408Srwatson}
427155408Srwatson
428155408Srwatsonstatic void InitializeThreading() {
429155408Srwatson  if (CriticalSectionInitialized)
430155408Srwatson    return;
431155428Srwatson
432155408Srwatson  // Now's the time to create the critical section. This is the first time
433155408Srwatson  // through here, and there's only one thread.
434155408Srwatson  InitializeCriticalSection(&CriticalSection);
435155408Srwatson  CriticalSectionInitialized = true;
436155408Srwatson}
437155408Srwatson
438155408Srwatsonstatic void RegisterHandler() {
439155408Srwatson  // If we cannot load up the APIs (which would be unexpected as they should
440161582Srwatson  // exist on every version of Windows we support), we will bail out since
441155408Srwatson  // there would be nothing to report.
442155408Srwatson  if (!load64BitDebugHelp()) {
443155408Srwatson    assert(false && "These APIs should always be available");
444155408Srwatson    return;
445155408Srwatson  }
446155408Srwatson
447155408Srwatson  if (RegisteredUnhandledExceptionFilter) {
448155408Srwatson    EnterCriticalSection(&CriticalSection);
449155408Srwatson    return;
450159269Srwatson  }
451159269Srwatson
452155408Srwatson  InitializeThreading();
453155408Srwatson
454155408Srwatson  // Enter it immediately.  Now if someone hits CTRL/C, the console handler
455155408Srwatson  // can't proceed until the globals are updated.
456155408Srwatson  EnterCriticalSection(&CriticalSection);
457155408Srwatson
458155408Srwatson  RegisteredUnhandledExceptionFilter = true;
459155408Srwatson  OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter);
460155408Srwatson  SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE);
461155408Srwatson
462159269Srwatson  // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or
463159269Srwatson  // else multi-threading problems will ensue.
464159269Srwatson}
465159269Srwatson
466159269Srwatson// The public API
467159269Srwatsonbool sys::RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg) {
468159269Srwatson  RegisterHandler();
469159269Srwatson
470159269Srwatson  if (CleanupExecuted) {
471159269Srwatson    if (ErrMsg)
472159269Srwatson      *ErrMsg = "Process terminating -- cannot register for removal";
473159269Srwatson    return true;
474159269Srwatson  }
475159269Srwatson
476159269Srwatson  if (FilesToRemove == NULL)
477159269Srwatson    FilesToRemove = new std::vector<std::string>;
478159269Srwatson
479159269Srwatson  FilesToRemove->push_back(std::string(Filename));
480159269Srwatson
481159269Srwatson  LeaveCriticalSection(&CriticalSection);
482159269Srwatson  return false;
483159269Srwatson}
484159269Srwatson
485159269Srwatson// The public API
486159269Srwatsonvoid sys::DontRemoveFileOnSignal(StringRef Filename) {
487159269Srwatson  if (FilesToRemove == NULL)
488159269Srwatson    return;
489159269Srwatson
490159269Srwatson  RegisterHandler();
491159269Srwatson
492155408Srwatson  std::vector<std::string>::reverse_iterator I =
493155408Srwatson      find(reverse(*FilesToRemove), Filename);
494155408Srwatson  if (I != FilesToRemove->rend())
495155408Srwatson    FilesToRemove->erase(I.base() - 1);
496155408Srwatson
497155408Srwatson  LeaveCriticalSection(&CriticalSection);
498155408Srwatson}
499159269Srwatson
500155408Srwatsonvoid sys::DisableSystemDialogsOnCrash() {
501159269Srwatson  // Crash to stack trace handler on abort.
502155408Srwatson  signal(SIGABRT, HandleAbort);
503155408Srwatson
504155408Srwatson  // The following functions are not reliably accessible on MinGW.
505155408Srwatson#ifdef _MSC_VER
506155408Srwatson  // We're already handling writing a "something went wrong" message.
507155408Srwatson  _set_abort_behavior(0, _WRITE_ABORT_MSG);
508155408Srwatson  // Disable Dr. Watson.
509155408Srwatson  _set_abort_behavior(0, _CALL_REPORTFAULT);
510155408Srwatson  _CrtSetReportHook(AvoidMessageBoxHook);
511155408Srwatson#endif
512155408Srwatson
513155408Srwatson  // Disable standard error dialog box.
514155408Srwatson  SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
515155408Srwatson               SEM_NOOPENFILEERRORBOX);
516155408Srwatson  _set_error_mode(_OUT_TO_STDERR);
517155408Srwatson}
518155408Srwatson
519155408Srwatson/// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
520155408Srwatson/// process, print a stack trace and then exit.
521155408Srwatsonvoid sys::PrintStackTraceOnErrorSignal(StringRef Argv0,
522155408Srwatson                                       bool DisableCrashReporting) {
523155408Srwatson  ::Argv0 = Argv0;
524155408Srwatson
525155408Srwatson  if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT"))
526155408Srwatson    Process::PreventCoreFiles();
527155408Srwatson
528155408Srwatson  DisableSystemDialogsOnCrash();
529155408Srwatson  RegisterHandler();
530155408Srwatson  LeaveCriticalSection(&CriticalSection);
531155408Srwatson}
532155408Srwatson} // namespace llvm
533155408Srwatson
534155408Srwatson#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
535155408Srwatson// Provide a prototype for RtlCaptureContext, mingw32 from mingw.org is
536161582Srwatson// missing it but mingw-w64 has it.
537161582Srwatsonextern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord);
538159269Srwatson#endif
539159269Srwatson
540159269Srwatsonstatic void LocalPrintStackTrace(raw_ostream &OS, PCONTEXT C) {
541159269Srwatson  STACKFRAME64 StackFrame{};
542159269Srwatson  CONTEXT Context{};
543159269Srwatson  if (!C) {
544159269Srwatson    ::RtlCaptureContext(&Context);
545159269Srwatson    C = &Context;
546159269Srwatson  }
547159269Srwatson#if defined(_M_X64)
548159269Srwatson  StackFrame.AddrPC.Offset = Context.Rip;
549159269Srwatson  StackFrame.AddrStack.Offset = Context.Rsp;
550159269Srwatson  StackFrame.AddrFrame.Offset = Context.Rbp;
551161582Srwatson#elif defined(_M_IX86)
552161582Srwatson  StackFrame.AddrPC.Offset = Context.Eip;
553161582Srwatson  StackFrame.AddrStack.Offset = Context.Esp;
554155408Srwatson  StackFrame.AddrFrame.Offset = Context.Ebp;
555155408Srwatson#elif defined(_M_ARM64)
556155408Srwatson  StackFrame.AddrPC.Offset = Context.Pc;
557159269Srwatson  StackFrame.AddrStack.Offset = Context.Sp;
558155408Srwatson  StackFrame.AddrFrame.Offset = Context.Fp;
559155408Srwatson#elif defined(_M_ARM)
560155408Srwatson  StackFrame.AddrPC.Offset = Context.Pc;
561155408Srwatson  StackFrame.AddrStack.Offset = Context.Sp;
562159269Srwatson  StackFrame.AddrFrame.Offset = Context.R11;
563155408Srwatson#endif
564155408Srwatson  StackFrame.AddrPC.Mode = AddrModeFlat;
565159269Srwatson  StackFrame.AddrStack.Mode = AddrModeFlat;
566155408Srwatson  StackFrame.AddrFrame.Mode = AddrModeFlat;
567155408Srwatson  PrintStackTraceForThread(OS, GetCurrentProcess(), GetCurrentThread(),
568155408Srwatson                           StackFrame, C);
569155408Srwatson}
570155408Srwatson
571155408Srwatsonvoid llvm::sys::PrintStackTrace(raw_ostream &OS, int Depth) {
572155408Srwatson  // FIXME: Handle "Depth" parameter to print stack trace upto specified Depth
573155408Srwatson  LocalPrintStackTrace(OS, nullptr);
574155408Srwatson}
575155408Srwatson
576155408Srwatsonvoid llvm::sys::SetInterruptFunction(void (*IF)()) {
577159269Srwatson  RegisterHandler();
578159269Srwatson  InterruptFunction = IF;
579159269Srwatson  LeaveCriticalSection(&CriticalSection);
580159269Srwatson}
581159269Srwatson
582159269Srwatsonvoid llvm::sys::SetInfoSignalFunction(void (*Handler)()) {
583159269Srwatson  // Unimplemented.
584159269Srwatson}
585159269Srwatson
586159269Srwatsonvoid llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) {
587159269Srwatson  OneShotPipeSignalFunction.exchange(Handler);
588159269Srwatson}
589159269Srwatson
590159269Srwatsonvoid llvm::sys::DefaultOneShotPipeSignalHandler() {
591159269Srwatson  llvm::sys::Process::Exit(EX_IOERR, /*NoCleanup=*/true);
592159269Srwatson}
593161582Srwatson
594159269Srwatsonvoid llvm::sys::CallOneShotPipeSignalHandler() {
595155408Srwatson  if (auto OldOneShotPipeFunction = OneShotPipeSignalFunction.exchange(nullptr))
596155408Srwatson    OldOneShotPipeFunction();
597155408Srwatson}
598155408Srwatson
599155408Srwatson/// Add a function to be called when a signal is delivered to the process. The
600155408Srwatson/// handler can have a cookie passed to it to identify what instance of the
601155408Srwatson/// handler it is.
602155408Srwatsonvoid llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr,
603155408Srwatson                                 void *Cookie) {
604155408Srwatson  insertSignalHandler(FnPtr, Cookie);
605155408Srwatson  RegisterHandler();
606155408Srwatson  LeaveCriticalSection(&CriticalSection);
607155408Srwatson}
608155408Srwatson
609155408Srwatsonstatic void Cleanup(bool ExecuteSignalHandlers) {
610155408Srwatson  if (CleanupExecuted)
611155408Srwatson    return;
612155408Srwatson
613155408Srwatson  EnterCriticalSection(&CriticalSection);
614155408Srwatson
615155408Srwatson  // Prevent other thread from registering new files and directories for
616155408Srwatson  // removal, should we be executing because of the console handler callback.
617155408Srwatson  CleanupExecuted = true;
618155408Srwatson
619155408Srwatson  // FIXME: open files cannot be deleted.
620155408Srwatson  if (FilesToRemove != NULL)
621155408Srwatson    while (!FilesToRemove->empty()) {
622155408Srwatson      llvm::sys::fs::remove(FilesToRemove->back());
623155408Srwatson      FilesToRemove->pop_back();
624155408Srwatson    }
625155408Srwatson
626155408Srwatson  if (ExecuteSignalHandlers)
627155408Srwatson    llvm::sys::RunSignalHandlers();
628155408Srwatson
629155408Srwatson  LeaveCriticalSection(&CriticalSection);
630155408Srwatson}
631155408Srwatson
632155408Srwatsonvoid llvm::sys::RunInterruptHandlers() {
633155408Srwatson  // The interrupt handler may be called from an interrupt, but it may also be
634155408Srwatson  // called manually (such as the case of report_fatal_error with no registered
635155408Srwatson  // error handler). We must ensure that the critical section is properly
636155408Srwatson  // initialized.
637155408Srwatson  InitializeThreading();
638155408Srwatson  Cleanup(true);
639155408Srwatson}
640155408Srwatson
641155408Srwatson/// Find the Windows Registry Key for a given location.
642155408Srwatson///
643155408Srwatson/// \returns a valid HKEY if the location exists, else NULL.
644155408Srwatsonstatic HKEY FindWERKey(const llvm::Twine &RegistryLocation) {
645155408Srwatson  HKEY Key;
646155408Srwatson  if (ERROR_SUCCESS != ::RegOpenKeyExA(HKEY_LOCAL_MACHINE,
647155408Srwatson                                       RegistryLocation.str().c_str(), 0,
648155408Srwatson                                       KEY_QUERY_VALUE | KEY_READ, &Key))
649155408Srwatson    return NULL;
650155408Srwatson
651155408Srwatson  return Key;
652155408Srwatson}
653155408Srwatson
654155408Srwatson/// Populate ResultDirectory with the value for "DumpFolder" for a given
655155408Srwatson/// Windows Registry key.
656155408Srwatson///
657155408Srwatson/// \returns true if a valid value for DumpFolder exists, false otherwise.
658155408Srwatsonstatic bool GetDumpFolder(HKEY Key,
659155408Srwatson                          llvm::SmallVectorImpl<char> &ResultDirectory) {
660155408Srwatson  using llvm::sys::windows::UTF16ToUTF8;
661155408Srwatson
662155408Srwatson  if (!Key)
663155408Srwatson    return false;
664155408Srwatson
665155408Srwatson  DWORD BufferLengthBytes = 0;
666155408Srwatson
667155408Srwatson  if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ,
668155408Srwatson                                      NULL, NULL, &BufferLengthBytes))
669155408Srwatson    return false;
670155408Srwatson
671155408Srwatson  SmallVector<wchar_t, MAX_PATH> Buffer(BufferLengthBytes);
672155408Srwatson
673155408Srwatson  if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ,
674155408Srwatson                                      NULL, Buffer.data(), &BufferLengthBytes))
675155408Srwatson    return false;
676155408Srwatson
677155408Srwatson  DWORD ExpandBufferSize = ::ExpandEnvironmentStringsW(Buffer.data(), NULL, 0);
678155408Srwatson
679156880Srwatson  if (!ExpandBufferSize)
680156880Srwatson    return false;
681155408Srwatson
682155408Srwatson  SmallVector<wchar_t, MAX_PATH> ExpandBuffer(ExpandBufferSize);
683155408Srwatson
684155408Srwatson  if (ExpandBufferSize != ::ExpandEnvironmentStringsW(Buffer.data(),
685155408Srwatson                                                      ExpandBuffer.data(),
686155408Srwatson                                                      ExpandBufferSize))
687155408Srwatson    return false;
688155408Srwatson
689159269Srwatson  if (UTF16ToUTF8(ExpandBuffer.data(), ExpandBufferSize - 1, ResultDirectory))
690155408Srwatson    return false;
691159269Srwatson
692159269Srwatson  return true;
693159269Srwatson}
694155408Srwatson
695155408Srwatson/// Populate ResultType with a valid MINIDUMP_TYPE based on the value of
696155408Srwatson/// "DumpType" for a given Windows Registry key.
697159269Srwatson///
698159269Srwatson/// According to
699159269Srwatson/// https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181(v=vs.85).aspx
700159269Srwatson/// valid values for DumpType are:
701159269Srwatson///   * 0: Custom dump
702159269Srwatson///   * 1: Mini dump
703155408Srwatson///   * 2: Full dump
704155408Srwatson/// If "Custom dump" is specified then the "CustomDumpFlags" field is read
705155408Srwatson/// containing a bitwise combination of MINIDUMP_TYPE values.
706155408Srwatson///
707155408Srwatson/// \returns true if a valid value for ResultType can be set, false otherwise.
708155408Srwatsonstatic bool GetDumpType(HKEY Key, MINIDUMP_TYPE &ResultType) {
709155408Srwatson  if (!Key)
710155408Srwatson    return false;
711155408Srwatson
712155408Srwatson  DWORD DumpType;
713155408Srwatson  DWORD TypeSize = sizeof(DumpType);
714155408Srwatson  if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"DumpType", RRF_RT_REG_DWORD,
715155408Srwatson                                      NULL, &DumpType, &TypeSize))
716155408Srwatson    return false;
717155408Srwatson
718155408Srwatson  switch (DumpType) {
719155408Srwatson  case 0: {
720155408Srwatson    DWORD Flags = 0;
721155408Srwatson    if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"CustomDumpFlags",
722155408Srwatson                                        RRF_RT_REG_DWORD, NULL, &Flags,
723155408Srwatson                                        &TypeSize))
724155408Srwatson      return false;
725155408Srwatson
726155408Srwatson    ResultType = static_cast<MINIDUMP_TYPE>(Flags);
727155408Srwatson    break;
728155408Srwatson  }
729155408Srwatson  case 1:
730155408Srwatson    ResultType = MiniDumpNormal;
731155408Srwatson    break;
732155408Srwatson  case 2:
733155408Srwatson    ResultType = MiniDumpWithFullMemory;
734155408Srwatson    break;
735155408Srwatson  default:
736155408Srwatson    return false;
737155408Srwatson  }
738155408Srwatson  return true;
739155408Srwatson}
740155408Srwatson
741155408Srwatson/// Write a Windows dump file containing process information that can be
742156880Srwatson/// used for post-mortem debugging.
743155408Srwatson///
744156880Srwatson/// \returns zero error code if a mini dump created, actual error code
745156880Srwatson/// otherwise.
746156880Srwatsonstatic std::error_code WINAPI
747156880SrwatsonWriteWindowsDumpFile(PMINIDUMP_EXCEPTION_INFORMATION ExceptionInfo) {
748156880Srwatson  struct ScopedCriticalSection {
749156880Srwatson    ScopedCriticalSection() { EnterCriticalSection(&CriticalSection); }
750156880Srwatson    ~ScopedCriticalSection() { LeaveCriticalSection(&CriticalSection); }
751156880Srwatson  } SCS;
752156880Srwatson
753156880Srwatson  using namespace llvm;
754156880Srwatson  using namespace llvm::sys;
755156880Srwatson
756156880Srwatson  std::string MainExecutableName = fs::getMainExecutable(nullptr, nullptr);
757156880Srwatson  StringRef ProgramName;
758156880Srwatson
759156880Srwatson  if (MainExecutableName.empty()) {
760156880Srwatson    // If we can't get the executable filename,
761156880Srwatson    // things are in worse shape than we realize
762156880Srwatson    // and we should just bail out.
763156880Srwatson    return mapWindowsError(::GetLastError());
764156884Srwatson  }
765156884Srwatson
766156884Srwatson  ProgramName = path::filename(MainExecutableName.c_str());
767156884Srwatson
768156884Srwatson  // The Windows Registry location as specified at
769156884Srwatson  // https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181%28v=vs.85%29.aspx
770156884Srwatson  // "Collecting User-Mode Dumps" that may optionally be set to collect crash
771156884Srwatson  // dumps in a specified location.
772156884Srwatson  StringRef LocalDumpsRegistryLocation =
773156884Srwatson      "SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps";
774159269Srwatson
775159269Srwatson  // The key pointing to the Registry location that may contain global crash
776159269Srwatson  // dump settings.  This will be NULL if the location can not be found.
777159269Srwatson  ScopedRegHandle DefaultLocalDumpsKey(FindWERKey(LocalDumpsRegistryLocation));
778159269Srwatson
779159269Srwatson  // The key pointing to the Registry location that may contain
780159269Srwatson  // application-specific crash dump settings.  This will be NULL if the
781159269Srwatson  // location can not be found.
782159269Srwatson  ScopedRegHandle AppSpecificKey(
783159269Srwatson      FindWERKey(Twine(LocalDumpsRegistryLocation) + "\\" + ProgramName));
784159269Srwatson
785159269Srwatson  // Look to see if a dump type is specified in the registry; first with the
786159269Srwatson  // app-specific key and failing that with the global key.  If none are found
787159269Srwatson  // default to a normal dump (GetDumpType will return false either if the key
788159269Srwatson  // is NULL or if there is no valid DumpType value at its location).
789159269Srwatson  MINIDUMP_TYPE DumpType;
790159269Srwatson  if (!GetDumpType(AppSpecificKey, DumpType))
791159269Srwatson    if (!GetDumpType(DefaultLocalDumpsKey, DumpType))
792159269Srwatson      DumpType = MiniDumpNormal;
793159269Srwatson
794159269Srwatson  // Look to see if a dump location is specified on the command line.  If not,
795159269Srwatson  // look to see if a dump location is specified in the registry; first with the
796159269Srwatson  // app-specific key and failing that with the global key.  If none are found
797159269Srwatson  // we'll just create the dump file in the default temporary file location
798159269Srwatson  // (GetDumpFolder will return false either if the key is NULL or if there is
799159269Srwatson  // no valid DumpFolder value at its location).
800159269Srwatson  bool ExplicitDumpDirectorySet = true;
801159269Srwatson  SmallString<MAX_PATH> DumpDirectory(*CrashDiagnosticsDirectory);
802159269Srwatson  if (DumpDirectory.empty())
803159269Srwatson    if (!GetDumpFolder(AppSpecificKey, DumpDirectory))
804159269Srwatson      if (!GetDumpFolder(DefaultLocalDumpsKey, DumpDirectory))
805159269Srwatson        ExplicitDumpDirectorySet = false;
806159269Srwatson
807159269Srwatson  int FD;
808159269Srwatson  SmallString<MAX_PATH> DumpPath;
809159269Srwatson
810159269Srwatson  if (ExplicitDumpDirectorySet) {
811159269Srwatson    if (std::error_code EC = fs::create_directories(DumpDirectory))
812159269Srwatson      return EC;
813159269Srwatson    if (std::error_code EC = fs::createUniqueFile(
814159269Srwatson            Twine(DumpDirectory) + "\\" + ProgramName + ".%%%%%%.dmp", FD,
815159269Srwatson            DumpPath))
816159269Srwatson      return EC;
817159269Srwatson  } else if (std::error_code EC =
818159269Srwatson                 fs::createTemporaryFile(ProgramName, "dmp", FD, DumpPath))
819159269Srwatson    return EC;
820159269Srwatson
821159269Srwatson  // Our support functions return a file descriptor but Windows wants a handle.
822159269Srwatson  ScopedCommonHandle FileHandle(reinterpret_cast<HANDLE>(_get_osfhandle(FD)));
823159269Srwatson
824159269Srwatson  if (!fMiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(),
825159269Srwatson                          FileHandle, DumpType, ExceptionInfo, NULL, NULL))
826159269Srwatson    return mapWindowsError(::GetLastError());
827159269Srwatson
828159269Srwatson  llvm::errs() << "Wrote crash dump file \"" << DumpPath << "\"\n";
829159269Srwatson  return std::error_code();
830159269Srwatson}
831159269Srwatson
832159269Srwatsonvoid sys::CleanupOnSignal(uintptr_t Context) {
833159269Srwatson  LPEXCEPTION_POINTERS EP = (LPEXCEPTION_POINTERS)Context;
834159269Srwatson  // Broken pipe is not a crash.
835159269Srwatson  //
836159269Srwatson  // 0xE0000000 is combined with the return code in the exception raised in
837159269Srwatson  // CrashRecoveryContext::HandleExit().
838159269Srwatson  unsigned RetCode = EP->ExceptionRecord->ExceptionCode;
839159269Srwatson  if (RetCode == (0xE0000000 | EX_IOERR))
840159269Srwatson    return;
841159269Srwatson  LLVMUnhandledExceptionFilter(EP);
842159269Srwatson}
843159269Srwatson
844159269Srwatsonstatic LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
845159269Srwatson  Cleanup(true);
846159269Srwatson
847159269Srwatson  // Write out the exception code.
848159269Srwatson  if (ep && ep->ExceptionRecord)
849159269Srwatson    llvm::errs() << format("Exception Code: 0x%08X",
850159269Srwatson                           ep->ExceptionRecord->ExceptionCode)
851159269Srwatson                 << "\n";
852159269Srwatson
853159269Srwatson  // We'll automatically write a Minidump file here to help diagnose
854159269Srwatson  // the nasty sorts of crashes that aren't 100% reproducible from a set of
855159269Srwatson  // inputs (or in the event that the user is unable or unwilling to provide a
856159269Srwatson  // reproducible case).
857159269Srwatson  if (!llvm::sys::Process::AreCoreFilesPrevented()) {
858161646Srwatson    MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo;
859161646Srwatson    ExceptionInfo.ThreadId = ::GetCurrentThreadId();
860161646Srwatson    ExceptionInfo.ExceptionPointers = ep;
861161646Srwatson    ExceptionInfo.ClientPointers = FALSE;
862161646Srwatson
863156880Srwatson    if (std::error_code EC = WriteWindowsDumpFile(&ExceptionInfo))
864156880Srwatson      llvm::errs() << "Could not write crash dump file: " << EC.message()
865156880Srwatson                   << "\n";
866156880Srwatson  }
867156880Srwatson
868156880Srwatson  // Stack unwinding appears to modify the context. Copy it to preserve the
869156880Srwatson  // caller's context.
870156880Srwatson  CONTEXT ContextCopy;
871156880Srwatson  if (ep)
872156880Srwatson    memcpy(&ContextCopy, ep->ContextRecord, sizeof(ContextCopy));
873156880Srwatson
874156880Srwatson  LocalPrintStackTrace(llvm::errs(), ep ? &ContextCopy : nullptr);
875156880Srwatson
876156880Srwatson  return EXCEPTION_EXECUTE_HANDLER;
877156880Srwatson}
878156880Srwatson
879156880Srwatsonstatic BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) {
880156880Srwatson  // We are running in our very own thread, courtesy of Windows.
881156880Srwatson  EnterCriticalSection(&CriticalSection);
882156880Srwatson  // This function is only ever called when a CTRL-C or similar control signal
883155408Srwatson  // is fired. Killing a process in this way is normal, so don't trigger the
884155408Srwatson  // signal handlers.
885155408Srwatson  Cleanup(false);
886155408Srwatson
887155408Srwatson  // If an interrupt function has been set, go and run one it; otherwise,
888155408Srwatson  // the process dies.
889155408Srwatson  void (*IF)() = InterruptFunction;
890155408Srwatson  InterruptFunction = 0; // Don't run it on another CTRL-C.
891155408Srwatson
892159269Srwatson  if (IF) {
893159269Srwatson    // Note: if the interrupt function throws an exception, there is nothing
894159269Srwatson    // to catch it in this thread so it will kill the process.
895159269Srwatson    IF(); // Run it now.
896159269Srwatson    LeaveCriticalSection(&CriticalSection);
897159269Srwatson    return TRUE; // Don't kill the process.
898159269Srwatson  }
899159269Srwatson
900159269Srwatson  // Allow normal processing to take place; i.e., the process dies.
901159269Srwatson  LeaveCriticalSection(&CriticalSection);
902159269Srwatson  return FALSE;
903155408Srwatson}
904155408Srwatson
905155408Srwatson#if __MINGW32__
906155408Srwatson// We turned these warnings off for this file so that MinGW-g++ doesn't
907155408Srwatson// complain about the ll format specifiers used.  Now we are turning the
908155408Srwatson// warnings back on.  If MinGW starts to support diagnostic stacks, we can
909155408Srwatson// replace this with a pop.
910155408Srwatson#pragma GCC diagnostic warning "-Wformat"
911155408Srwatson#pragma GCC diagnostic warning "-Wformat-extra-args"
912155408Srwatson#endif
913155408Srwatson
914155408Srwatsonvoid sys::unregisterHandlers() {}
915155408Srwatson