Signals.inc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  1. //===- Win32/Signals.cpp - Win32 Signals Implementation ---------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file provides the Win32 specific implementation of the Signals class.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "llvm/Support/ConvertUTF.h"
  13. #include "llvm/Support/ExitCodes.h"
  14. #include "llvm/Support/FileSystem.h"
  15. #include "llvm/Support/Path.h"
  16. #include "llvm/Support/Process.h"
  17. #include "llvm/Support/WindowsError.h"
  18. #include <algorithm>
  19. #include <io.h>
  20. #include <signal.h>
  21. #include <stdio.h>
  22. #include "llvm/Support/Format.h"
  23. #include "llvm/Support/raw_ostream.h"
  24. // The Windows.h header must be after LLVM and standard headers.
  25. #include "llvm/Support/Windows/WindowsSupport.h"
  26. #ifdef __MINGW32__
  27. #include <imagehlp.h>
  28. #else
  29. #include <crtdbg.h>
  30. #include <dbghelp.h>
  31. #endif
  32. #include <psapi.h>
  33. #ifdef _MSC_VER
  34. #pragma comment(lib, "psapi.lib")
  35. #elif __MINGW32__
  36. // The version of g++ that comes with MinGW does *not* properly understand
  37. // the ll format specifier for printf. However, MinGW passes the format
  38. // specifiers on to the MSVCRT entirely, and the CRT understands the ll
  39. // specifier. So these warnings are spurious in this case. Since we compile
  40. // with -Wall, this will generate these warnings which should be ignored. So
  41. // we will turn off the warnings for this just file. However, MinGW also does
  42. // not support push and pop for diagnostics, so we have to manually turn it
  43. // back on at the end of the file.
  44. #pragma GCC diagnostic ignored "-Wformat"
  45. #pragma GCC diagnostic ignored "-Wformat-extra-args"
  46. #if !defined(__MINGW64_VERSION_MAJOR)
  47. // MinGW.org does not have updated support for the 64-bit versions of the
  48. // DebugHlp APIs. So we will have to load them manually. The structures and
  49. // method signatures were pulled from DbgHelp.h in the Windows Platform SDK,
  50. // and adjusted for brevity.
  51. typedef struct _IMAGEHLP_LINE64 {
  52. DWORD SizeOfStruct;
  53. PVOID Key;
  54. DWORD LineNumber;
  55. PCHAR FileName;
  56. DWORD64 Address;
  57. } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;
  58. typedef struct _IMAGEHLP_SYMBOL64 {
  59. DWORD SizeOfStruct;
  60. DWORD64 Address;
  61. DWORD Size;
  62. DWORD Flags;
  63. DWORD MaxNameLength;
  64. CHAR Name[1];
  65. } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;
  66. typedef struct _tagADDRESS64 {
  67. DWORD64 Offset;
  68. WORD Segment;
  69. ADDRESS_MODE Mode;
  70. } ADDRESS64, *LPADDRESS64;
  71. typedef struct _KDHELP64 {
  72. DWORD64 Thread;
  73. DWORD ThCallbackStack;
  74. DWORD ThCallbackBStore;
  75. DWORD NextCallback;
  76. DWORD FramePointer;
  77. DWORD64 KiCallUserMode;
  78. DWORD64 KeUserCallbackDispatcher;
  79. DWORD64 SystemRangeStart;
  80. DWORD64 KiUserExceptionDispatcher;
  81. DWORD64 StackBase;
  82. DWORD64 StackLimit;
  83. DWORD64 Reserved[5];
  84. } KDHELP64, *PKDHELP64;
  85. typedef struct _tagSTACKFRAME64 {
  86. ADDRESS64 AddrPC;
  87. ADDRESS64 AddrReturn;
  88. ADDRESS64 AddrFrame;
  89. ADDRESS64 AddrStack;
  90. ADDRESS64 AddrBStore;
  91. PVOID FuncTableEntry;
  92. DWORD64 Params[4];
  93. BOOL Far;
  94. BOOL Virtual;
  95. DWORD64 Reserved[3];
  96. KDHELP64 KdHelp;
  97. } STACKFRAME64, *LPSTACKFRAME64;
  98. #endif // !defined(__MINGW64_VERSION_MAJOR)
  99. #endif // __MINGW32__
  100. typedef BOOL(__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(
  101. HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize,
  102. LPDWORD lpNumberOfBytesRead);
  103. typedef PVOID(__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)(HANDLE ahProcess,
  104. DWORD64 AddrBase);
  105. typedef DWORD64(__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,
  106. DWORD64 Address);
  107. typedef DWORD64(__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,
  108. HANDLE hThread,
  109. LPADDRESS64 lpaddr);
  110. typedef BOOL(WINAPI *fpMiniDumpWriteDump)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE,
  111. PMINIDUMP_EXCEPTION_INFORMATION,
  112. PMINIDUMP_USER_STREAM_INFORMATION,
  113. PMINIDUMP_CALLBACK_INFORMATION);
  114. static fpMiniDumpWriteDump fMiniDumpWriteDump;
  115. typedef BOOL(WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64,
  116. PVOID, PREAD_PROCESS_MEMORY_ROUTINE64,
  117. PFUNCTION_TABLE_ACCESS_ROUTINE64,
  118. PGET_MODULE_BASE_ROUTINE64,
  119. PTRANSLATE_ADDRESS_ROUTINE64);
  120. static fpStackWalk64 fStackWalk64;
  121. typedef DWORD64(WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64);
  122. static fpSymGetModuleBase64 fSymGetModuleBase64;
  123. typedef BOOL(WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64,
  124. PIMAGEHLP_SYMBOL64);
  125. static fpSymGetSymFromAddr64 fSymGetSymFromAddr64;
  126. typedef BOOL(WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64, PDWORD,
  127. PIMAGEHLP_LINE64);
  128. static fpSymGetLineFromAddr64 fSymGetLineFromAddr64;
  129. typedef BOOL(WINAPI *fpSymGetModuleInfo64)(HANDLE hProcess, DWORD64 dwAddr,
  130. PIMAGEHLP_MODULE64 ModuleInfo);
  131. static fpSymGetModuleInfo64 fSymGetModuleInfo64;
  132. typedef PVOID(WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64);
  133. static fpSymFunctionTableAccess64 fSymFunctionTableAccess64;
  134. typedef DWORD(WINAPI *fpSymSetOptions)(DWORD);
  135. static fpSymSetOptions fSymSetOptions;
  136. typedef BOOL(WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL);
  137. static fpSymInitialize fSymInitialize;
  138. typedef BOOL(WINAPI *fpEnumerateLoadedModules)(HANDLE,
  139. PENUMLOADED_MODULES_CALLBACK64,
  140. PVOID);
  141. static fpEnumerateLoadedModules fEnumerateLoadedModules;
  142. static bool isDebugHelpInitialized() {
  143. return fStackWalk64 && fSymInitialize && fSymSetOptions && fMiniDumpWriteDump;
  144. }
  145. static bool load64BitDebugHelp(void) {
  146. HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll");
  147. if (hLib) {
  148. fMiniDumpWriteDump =
  149. (fpMiniDumpWriteDump)::GetProcAddress(hLib, "MiniDumpWriteDump");
  150. fStackWalk64 = (fpStackWalk64)::GetProcAddress(hLib, "StackWalk64");
  151. fSymGetModuleBase64 =
  152. (fpSymGetModuleBase64)::GetProcAddress(hLib, "SymGetModuleBase64");
  153. fSymGetSymFromAddr64 =
  154. (fpSymGetSymFromAddr64)::GetProcAddress(hLib, "SymGetSymFromAddr64");
  155. fSymGetLineFromAddr64 =
  156. (fpSymGetLineFromAddr64)::GetProcAddress(hLib, "SymGetLineFromAddr64");
  157. fSymGetModuleInfo64 =
  158. (fpSymGetModuleInfo64)::GetProcAddress(hLib, "SymGetModuleInfo64");
  159. fSymFunctionTableAccess64 = (fpSymFunctionTableAccess64)::GetProcAddress(
  160. hLib, "SymFunctionTableAccess64");
  161. fSymSetOptions = (fpSymSetOptions)::GetProcAddress(hLib, "SymSetOptions");
  162. fSymInitialize = (fpSymInitialize)::GetProcAddress(hLib, "SymInitialize");
  163. fEnumerateLoadedModules = (fpEnumerateLoadedModules)::GetProcAddress(
  164. hLib, "EnumerateLoadedModules64");
  165. }
  166. return isDebugHelpInitialized();
  167. }
  168. using namespace llvm;
  169. // Forward declare.
  170. static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep);
  171. static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType);
  172. // The function to call if ctrl-c is pressed.
  173. static void (*InterruptFunction)() = 0;
  174. static std::vector<std::string> *FilesToRemove = NULL;
  175. static bool RegisteredUnhandledExceptionFilter = false;
  176. static bool CleanupExecuted = false;
  177. static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL;
  178. /// The function to call on "SIGPIPE" (one-time use only).
  179. static std::atomic<void (*)()> OneShotPipeSignalFunction(nullptr);
  180. // Windows creates a new thread to execute the console handler when an event
  181. // (such as CTRL/C) occurs. This causes concurrency issues with the above
  182. // globals which this critical section addresses.
  183. static CRITICAL_SECTION CriticalSection;
  184. static bool CriticalSectionInitialized = false;
  185. static StringRef Argv0;
  186. enum {
  187. #if defined(_M_X64)
  188. NativeMachineType = IMAGE_FILE_MACHINE_AMD64
  189. #elif defined(_M_ARM64)
  190. NativeMachineType = IMAGE_FILE_MACHINE_ARM64
  191. #elif defined(_M_IX86)
  192. NativeMachineType = IMAGE_FILE_MACHINE_I386
  193. #elif defined(_M_ARM)
  194. NativeMachineType = IMAGE_FILE_MACHINE_ARMNT
  195. #else
  196. NativeMachineType = IMAGE_FILE_MACHINE_UNKNOWN
  197. #endif
  198. };
  199. static bool printStackTraceWithLLVMSymbolizer(llvm::raw_ostream &OS,
  200. HANDLE hProcess, HANDLE hThread,
  201. STACKFRAME64 &StackFrameOrig,
  202. CONTEXT *ContextOrig) {
  203. // StackWalk64 modifies the incoming stack frame and context, so copy them.
  204. STACKFRAME64 StackFrame = StackFrameOrig;
  205. // Copy the register context so that we don't modify it while we unwind. We
  206. // could use InitializeContext + CopyContext, but that's only required to get
  207. // at AVX registers, which typically aren't needed by StackWalk64. Reduce the
  208. // flag set to indicate that there's less data.
  209. CONTEXT Context = *ContextOrig;
  210. Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
  211. static void *StackTrace[256];
  212. size_t Depth = 0;
  213. while (fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame,
  214. &Context, 0, fSymFunctionTableAccess64,
  215. fSymGetModuleBase64, 0)) {
  216. if (StackFrame.AddrFrame.Offset == 0)
  217. break;
  218. StackTrace[Depth++] = (void *)(uintptr_t)StackFrame.AddrPC.Offset;
  219. if (Depth >= std::size(StackTrace))
  220. break;
  221. }
  222. return printSymbolizedStackTrace(Argv0, &StackTrace[0], Depth, OS);
  223. }
  224. namespace {
  225. struct FindModuleData {
  226. void **StackTrace;
  227. int Depth;
  228. const char **Modules;
  229. intptr_t *Offsets;
  230. StringSaver *StrPool;
  231. };
  232. } // namespace
  233. static BOOL CALLBACK findModuleCallback(PCSTR ModuleName, DWORD64 ModuleBase,
  234. ULONG ModuleSize, void *VoidData) {
  235. FindModuleData *Data = (FindModuleData *)VoidData;
  236. intptr_t Beg = ModuleBase;
  237. intptr_t End = Beg + ModuleSize;
  238. for (int I = 0; I < Data->Depth; I++) {
  239. if (Data->Modules[I])
  240. continue;
  241. intptr_t Addr = (intptr_t)Data->StackTrace[I];
  242. if (Beg <= Addr && Addr < End) {
  243. Data->Modules[I] = Data->StrPool->save(ModuleName).data();
  244. Data->Offsets[I] = Addr - Beg;
  245. }
  246. }
  247. return TRUE;
  248. }
  249. static bool findModulesAndOffsets(void **StackTrace, int Depth,
  250. const char **Modules, intptr_t *Offsets,
  251. const char *MainExecutableName,
  252. StringSaver &StrPool) {
  253. if (!fEnumerateLoadedModules)
  254. return false;
  255. FindModuleData Data;
  256. Data.StackTrace = StackTrace;
  257. Data.Depth = Depth;
  258. Data.Modules = Modules;
  259. Data.Offsets = Offsets;
  260. Data.StrPool = &StrPool;
  261. fEnumerateLoadedModules(GetCurrentProcess(), findModuleCallback, &Data);
  262. return true;
  263. }
  264. static void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE hProcess,
  265. HANDLE hThread, STACKFRAME64 &StackFrame,
  266. CONTEXT *Context) {
  267. // It's possible that DbgHelp.dll hasn't been loaded yet (e.g. if this
  268. // function is called before the main program called `llvm::InitLLVM`).
  269. // In this case just return, not stacktrace will be printed.
  270. if (!isDebugHelpInitialized())
  271. return;
  272. // Initialize the symbol handler.
  273. fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
  274. fSymInitialize(hProcess, NULL, TRUE);
  275. // Try llvm-symbolizer first. llvm-symbolizer knows how to deal with both PDBs
  276. // and DWARF, so it should do a good job regardless of what debug info or
  277. // linker is in use.
  278. if (printStackTraceWithLLVMSymbolizer(OS, hProcess, hThread, StackFrame,
  279. Context)) {
  280. return;
  281. }
  282. while (true) {
  283. if (!fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame,
  284. Context, 0, fSymFunctionTableAccess64,
  285. fSymGetModuleBase64, 0)) {
  286. break;
  287. }
  288. if (StackFrame.AddrFrame.Offset == 0)
  289. break;
  290. using namespace llvm;
  291. // Print the PC in hexadecimal.
  292. DWORD64 PC = StackFrame.AddrPC.Offset;
  293. #if defined(_M_X64) || defined(_M_ARM64)
  294. OS << format("0x%016llX", PC);
  295. #elif defined(_M_IX86) || defined(_M_ARM)
  296. OS << format("0x%08lX", static_cast<DWORD>(PC));
  297. #endif
  298. // Verify the PC belongs to a module in this process.
  299. if (!fSymGetModuleBase64(hProcess, PC)) {
  300. OS << " <unknown module>\n";
  301. continue;
  302. }
  303. IMAGEHLP_MODULE64 M;
  304. memset(&M, 0, sizeof(IMAGEHLP_MODULE64));
  305. M.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
  306. if (fSymGetModuleInfo64(hProcess, fSymGetModuleBase64(hProcess, PC), &M)) {
  307. DWORD64 const disp = PC - M.BaseOfImage;
  308. OS << format(", %s(0x%016llX) + 0x%llX byte(s)",
  309. static_cast<char *>(M.ImageName), M.BaseOfImage,
  310. static_cast<long long>(disp));
  311. } else {
  312. OS << ", <unknown module>";
  313. }
  314. // Print the symbol name.
  315. char buffer[512];
  316. IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer);
  317. memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64));
  318. symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
  319. symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64);
  320. DWORD64 dwDisp;
  321. if (!fSymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) {
  322. OS << '\n';
  323. continue;
  324. }
  325. buffer[511] = 0;
  326. OS << format(", %s() + 0x%llX byte(s)", static_cast<char *>(symbol->Name),
  327. static_cast<long long>(dwDisp));
  328. // Print the source file and line number information.
  329. IMAGEHLP_LINE64 line = {};
  330. DWORD dwLineDisp;
  331. line.SizeOfStruct = sizeof(line);
  332. if (fSymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) {
  333. OS << format(", %s, line %lu + 0x%lX byte(s)", line.FileName,
  334. line.LineNumber, dwLineDisp);
  335. }
  336. OS << '\n';
  337. }
  338. }
  339. namespace llvm {
  340. //===----------------------------------------------------------------------===//
  341. //=== WARNING: Implementation here must contain only Win32 specific code
  342. //=== and must not be UNIX code
  343. //===----------------------------------------------------------------------===//
  344. #ifdef _MSC_VER
  345. /// Emulates hitting "retry" from an "abort, retry, ignore" CRT debug report
  346. /// dialog. "retry" raises an exception which ultimately triggers our stack
  347. /// dumper.
  348. static LLVM_ATTRIBUTE_UNUSED int
  349. AvoidMessageBoxHook(int ReportType, char *Message, int *Return) {
  350. // Set *Return to the retry code for the return value of _CrtDbgReport:
  351. // http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx
  352. // This may also trigger just-in-time debugging via DebugBreak().
  353. if (Return)
  354. *Return = 1;
  355. // Don't call _CrtDbgReport.
  356. return TRUE;
  357. }
  358. #endif
  359. extern "C" void HandleAbort(int Sig) {
  360. if (Sig == SIGABRT) {
  361. LLVM_BUILTIN_TRAP;
  362. }
  363. }
  364. static void InitializeThreading() {
  365. if (CriticalSectionInitialized)
  366. return;
  367. // Now's the time to create the critical section. This is the first time
  368. // through here, and there's only one thread.
  369. InitializeCriticalSection(&CriticalSection);
  370. CriticalSectionInitialized = true;
  371. }
  372. static void RegisterHandler() {
  373. // If we cannot load up the APIs (which would be unexpected as they should
  374. // exist on every version of Windows we support), we will bail out since
  375. // there would be nothing to report.
  376. if (!load64BitDebugHelp()) {
  377. assert(false && "These APIs should always be available");
  378. return;
  379. }
  380. if (RegisteredUnhandledExceptionFilter) {
  381. EnterCriticalSection(&CriticalSection);
  382. return;
  383. }
  384. InitializeThreading();
  385. // Enter it immediately. Now if someone hits CTRL/C, the console handler
  386. // can't proceed until the globals are updated.
  387. EnterCriticalSection(&CriticalSection);
  388. RegisteredUnhandledExceptionFilter = true;
  389. OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter);
  390. SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE);
  391. // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or
  392. // else multi-threading problems will ensue.
  393. }
  394. // The public API
  395. bool sys::RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg) {
  396. RegisterHandler();
  397. if (CleanupExecuted) {
  398. if (ErrMsg)
  399. *ErrMsg = "Process terminating -- cannot register for removal";
  400. return true;
  401. }
  402. if (FilesToRemove == NULL)
  403. FilesToRemove = new std::vector<std::string>;
  404. FilesToRemove->push_back(std::string(Filename));
  405. LeaveCriticalSection(&CriticalSection);
  406. return false;
  407. }
  408. // The public API
  409. void sys::DontRemoveFileOnSignal(StringRef Filename) {
  410. if (FilesToRemove == NULL)
  411. return;
  412. RegisterHandler();
  413. std::vector<std::string>::reverse_iterator I =
  414. find(reverse(*FilesToRemove), Filename);
  415. if (I != FilesToRemove->rend())
  416. FilesToRemove->erase(I.base() - 1);
  417. LeaveCriticalSection(&CriticalSection);
  418. }
  419. void sys::DisableSystemDialogsOnCrash() {
  420. // Crash to stack trace handler on abort.
  421. signal(SIGABRT, HandleAbort);
  422. // The following functions are not reliably accessible on MinGW.
  423. #ifdef _MSC_VER
  424. // We're already handling writing a "something went wrong" message.
  425. _set_abort_behavior(0, _WRITE_ABORT_MSG);
  426. // Disable Dr. Watson.
  427. _set_abort_behavior(0, _CALL_REPORTFAULT);
  428. _CrtSetReportHook(AvoidMessageBoxHook);
  429. #endif
  430. // Disable standard error dialog box.
  431. SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
  432. SEM_NOOPENFILEERRORBOX);
  433. _set_error_mode(_OUT_TO_STDERR);
  434. }
  435. /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
  436. /// process, print a stack trace and then exit.
  437. void sys::PrintStackTraceOnErrorSignal(StringRef Argv0,
  438. bool DisableCrashReporting) {
  439. ::Argv0 = Argv0;
  440. if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT"))
  441. Process::PreventCoreFiles();
  442. DisableSystemDialogsOnCrash();
  443. RegisterHandler();
  444. LeaveCriticalSection(&CriticalSection);
  445. }
  446. } // namespace llvm
  447. #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
  448. // Provide a prototype for RtlCaptureContext, mingw32 from mingw.org is
  449. // missing it but mingw-w64 has it.
  450. extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord);
  451. #endif
  452. static void LocalPrintStackTrace(raw_ostream &OS, PCONTEXT C) {
  453. STACKFRAME64 StackFrame{};
  454. CONTEXT Context{};
  455. if (!C) {
  456. ::RtlCaptureContext(&Context);
  457. C = &Context;
  458. }
  459. #if defined(_M_X64)
  460. StackFrame.AddrPC.Offset = Context.Rip;
  461. StackFrame.AddrStack.Offset = Context.Rsp;
  462. StackFrame.AddrFrame.Offset = Context.Rbp;
  463. #elif defined(_M_IX86)
  464. StackFrame.AddrPC.Offset = Context.Eip;
  465. StackFrame.AddrStack.Offset = Context.Esp;
  466. StackFrame.AddrFrame.Offset = Context.Ebp;
  467. #elif defined(_M_ARM64)
  468. StackFrame.AddrPC.Offset = Context.Pc;
  469. StackFrame.AddrStack.Offset = Context.Sp;
  470. StackFrame.AddrFrame.Offset = Context.Fp;
  471. #elif defined(_M_ARM)
  472. StackFrame.AddrPC.Offset = Context.Pc;
  473. StackFrame.AddrStack.Offset = Context.Sp;
  474. StackFrame.AddrFrame.Offset = Context.R11;
  475. #endif
  476. StackFrame.AddrPC.Mode = AddrModeFlat;
  477. StackFrame.AddrStack.Mode = AddrModeFlat;
  478. StackFrame.AddrFrame.Mode = AddrModeFlat;
  479. PrintStackTraceForThread(OS, GetCurrentProcess(), GetCurrentThread(),
  480. StackFrame, C);
  481. }
  482. void llvm::sys::PrintStackTrace(raw_ostream &OS, int Depth) {
  483. // FIXME: Handle "Depth" parameter to print stack trace upto specified Depth
  484. LocalPrintStackTrace(OS, nullptr);
  485. }
  486. void llvm::sys::SetInterruptFunction(void (*IF)()) {
  487. RegisterHandler();
  488. InterruptFunction = IF;
  489. LeaveCriticalSection(&CriticalSection);
  490. }
  491. void llvm::sys::SetInfoSignalFunction(void (*Handler)()) {
  492. // Unimplemented.
  493. }
  494. void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) {
  495. OneShotPipeSignalFunction.exchange(Handler);
  496. }
  497. void llvm::sys::DefaultOneShotPipeSignalHandler() {
  498. llvm::sys::Process::Exit(EX_IOERR, /*NoCleanup=*/true);
  499. }
  500. void llvm::sys::CallOneShotPipeSignalHandler() {
  501. if (auto OldOneShotPipeFunction = OneShotPipeSignalFunction.exchange(nullptr))
  502. OldOneShotPipeFunction();
  503. }
  504. /// Add a function to be called when a signal is delivered to the process. The
  505. /// handler can have a cookie passed to it to identify what instance of the
  506. /// handler it is.
  507. void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr,
  508. void *Cookie) {
  509. insertSignalHandler(FnPtr, Cookie);
  510. RegisterHandler();
  511. LeaveCriticalSection(&CriticalSection);
  512. }
  513. static void Cleanup(bool ExecuteSignalHandlers) {
  514. if (CleanupExecuted)
  515. return;
  516. EnterCriticalSection(&CriticalSection);
  517. // Prevent other thread from registering new files and directories for
  518. // removal, should we be executing because of the console handler callback.
  519. CleanupExecuted = true;
  520. // FIXME: open files cannot be deleted.
  521. if (FilesToRemove != NULL)
  522. while (!FilesToRemove->empty()) {
  523. llvm::sys::fs::remove(FilesToRemove->back());
  524. FilesToRemove->pop_back();
  525. }
  526. if (ExecuteSignalHandlers)
  527. llvm::sys::RunSignalHandlers();
  528. LeaveCriticalSection(&CriticalSection);
  529. }
  530. void llvm::sys::RunInterruptHandlers() {
  531. // The interrupt handler may be called from an interrupt, but it may also be
  532. // called manually (such as the case of report_fatal_error with no registered
  533. // error handler). We must ensure that the critical section is properly
  534. // initialized.
  535. InitializeThreading();
  536. Cleanup(true);
  537. }
  538. /// Find the Windows Registry Key for a given location.
  539. ///
  540. /// \returns a valid HKEY if the location exists, else NULL.
  541. static HKEY FindWERKey(const llvm::Twine &RegistryLocation) {
  542. HKEY Key;
  543. if (ERROR_SUCCESS != ::RegOpenKeyExA(HKEY_LOCAL_MACHINE,
  544. RegistryLocation.str().c_str(), 0,
  545. KEY_QUERY_VALUE | KEY_READ, &Key))
  546. return NULL;
  547. return Key;
  548. }
  549. /// Populate ResultDirectory with the value for "DumpFolder" for a given
  550. /// Windows Registry key.
  551. ///
  552. /// \returns true if a valid value for DumpFolder exists, false otherwise.
  553. static bool GetDumpFolder(HKEY Key,
  554. llvm::SmallVectorImpl<char> &ResultDirectory) {
  555. using llvm::sys::windows::UTF16ToUTF8;
  556. if (!Key)
  557. return false;
  558. DWORD BufferLengthBytes = 0;
  559. if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ,
  560. NULL, NULL, &BufferLengthBytes))
  561. return false;
  562. SmallVector<wchar_t, MAX_PATH> Buffer(BufferLengthBytes);
  563. if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ,
  564. NULL, Buffer.data(), &BufferLengthBytes))
  565. return false;
  566. DWORD ExpandBufferSize = ::ExpandEnvironmentStringsW(Buffer.data(), NULL, 0);
  567. if (!ExpandBufferSize)
  568. return false;
  569. SmallVector<wchar_t, MAX_PATH> ExpandBuffer(ExpandBufferSize);
  570. if (ExpandBufferSize != ::ExpandEnvironmentStringsW(Buffer.data(),
  571. ExpandBuffer.data(),
  572. ExpandBufferSize))
  573. return false;
  574. if (UTF16ToUTF8(ExpandBuffer.data(), ExpandBufferSize - 1, ResultDirectory))
  575. return false;
  576. return true;
  577. }
  578. /// Populate ResultType with a valid MINIDUMP_TYPE based on the value of
  579. /// "DumpType" for a given Windows Registry key.
  580. ///
  581. /// According to
  582. /// https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181(v=vs.85).aspx
  583. /// valid values for DumpType are:
  584. /// * 0: Custom dump
  585. /// * 1: Mini dump
  586. /// * 2: Full dump
  587. /// If "Custom dump" is specified then the "CustomDumpFlags" field is read
  588. /// containing a bitwise combination of MINIDUMP_TYPE values.
  589. ///
  590. /// \returns true if a valid value for ResultType can be set, false otherwise.
  591. static bool GetDumpType(HKEY Key, MINIDUMP_TYPE &ResultType) {
  592. if (!Key)
  593. return false;
  594. DWORD DumpType;
  595. DWORD TypeSize = sizeof(DumpType);
  596. if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"DumpType", RRF_RT_REG_DWORD,
  597. NULL, &DumpType, &TypeSize))
  598. return false;
  599. switch (DumpType) {
  600. case 0: {
  601. DWORD Flags = 0;
  602. if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"CustomDumpFlags",
  603. RRF_RT_REG_DWORD, NULL, &Flags,
  604. &TypeSize))
  605. return false;
  606. ResultType = static_cast<MINIDUMP_TYPE>(Flags);
  607. break;
  608. }
  609. case 1:
  610. ResultType = MiniDumpNormal;
  611. break;
  612. case 2:
  613. ResultType = MiniDumpWithFullMemory;
  614. break;
  615. default:
  616. return false;
  617. }
  618. return true;
  619. }
  620. /// Write a Windows dump file containing process information that can be
  621. /// used for post-mortem debugging.
  622. ///
  623. /// \returns zero error code if a mini dump created, actual error code
  624. /// otherwise.
  625. static std::error_code WINAPI
  626. WriteWindowsDumpFile(PMINIDUMP_EXCEPTION_INFORMATION ExceptionInfo) {
  627. struct ScopedCriticalSection {
  628. ScopedCriticalSection() { EnterCriticalSection(&CriticalSection); }
  629. ~ScopedCriticalSection() { LeaveCriticalSection(&CriticalSection); }
  630. } SCS;
  631. using namespace llvm;
  632. using namespace llvm::sys;
  633. std::string MainExecutableName = fs::getMainExecutable(nullptr, nullptr);
  634. StringRef ProgramName;
  635. if (MainExecutableName.empty()) {
  636. // If we can't get the executable filename,
  637. // things are in worse shape than we realize
  638. // and we should just bail out.
  639. return mapWindowsError(::GetLastError());
  640. }
  641. ProgramName = path::filename(MainExecutableName.c_str());
  642. // The Windows Registry location as specified at
  643. // https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181%28v=vs.85%29.aspx
  644. // "Collecting User-Mode Dumps" that may optionally be set to collect crash
  645. // dumps in a specified location.
  646. StringRef LocalDumpsRegistryLocation =
  647. "SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps";
  648. // The key pointing to the Registry location that may contain global crash
  649. // dump settings. This will be NULL if the location can not be found.
  650. ScopedRegHandle DefaultLocalDumpsKey(FindWERKey(LocalDumpsRegistryLocation));
  651. // The key pointing to the Registry location that may contain
  652. // application-specific crash dump settings. This will be NULL if the
  653. // location can not be found.
  654. ScopedRegHandle AppSpecificKey(
  655. FindWERKey(Twine(LocalDumpsRegistryLocation) + "\\" + ProgramName));
  656. // Look to see if a dump type is specified in the registry; first with the
  657. // app-specific key and failing that with the global key. If none are found
  658. // default to a normal dump (GetDumpType will return false either if the key
  659. // is NULL or if there is no valid DumpType value at its location).
  660. MINIDUMP_TYPE DumpType;
  661. if (!GetDumpType(AppSpecificKey, DumpType))
  662. if (!GetDumpType(DefaultLocalDumpsKey, DumpType))
  663. DumpType = MiniDumpNormal;
  664. // Look to see if a dump location is specified on the command line. If not,
  665. // look to see if a dump location is specified in the registry; first with the
  666. // app-specific key and failing that with the global key. If none are found
  667. // we'll just create the dump file in the default temporary file location
  668. // (GetDumpFolder will return false either if the key is NULL or if there is
  669. // no valid DumpFolder value at its location).
  670. bool ExplicitDumpDirectorySet = true;
  671. SmallString<MAX_PATH> DumpDirectory(*CrashDiagnosticsDirectory);
  672. if (DumpDirectory.empty())
  673. if (!GetDumpFolder(AppSpecificKey, DumpDirectory))
  674. if (!GetDumpFolder(DefaultLocalDumpsKey, DumpDirectory))
  675. ExplicitDumpDirectorySet = false;
  676. int FD;
  677. SmallString<MAX_PATH> DumpPath;
  678. if (ExplicitDumpDirectorySet) {
  679. if (std::error_code EC = fs::create_directories(DumpDirectory))
  680. return EC;
  681. if (std::error_code EC = fs::createUniqueFile(
  682. Twine(DumpDirectory) + "\\" + ProgramName + ".%%%%%%.dmp", FD,
  683. DumpPath))
  684. return EC;
  685. } else if (std::error_code EC =
  686. fs::createTemporaryFile(ProgramName, "dmp", FD, DumpPath))
  687. return EC;
  688. // Our support functions return a file descriptor but Windows wants a handle.
  689. ScopedCommonHandle FileHandle(reinterpret_cast<HANDLE>(_get_osfhandle(FD)));
  690. if (!fMiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(),
  691. FileHandle, DumpType, ExceptionInfo, NULL, NULL))
  692. return mapWindowsError(::GetLastError());
  693. llvm::errs() << "Wrote crash dump file \"" << DumpPath << "\"\n";
  694. return std::error_code();
  695. }
  696. void sys::CleanupOnSignal(uintptr_t Context) {
  697. LPEXCEPTION_POINTERS EP = (LPEXCEPTION_POINTERS)Context;
  698. // Broken pipe is not a crash.
  699. //
  700. // 0xE0000000 is combined with the return code in the exception raised in
  701. // CrashRecoveryContext::HandleExit().
  702. unsigned RetCode = EP->ExceptionRecord->ExceptionCode;
  703. if (RetCode == (0xE0000000 | EX_IOERR))
  704. return;
  705. LLVMUnhandledExceptionFilter(EP);
  706. }
  707. static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
  708. Cleanup(true);
  709. // Write out the exception code.
  710. if (ep && ep->ExceptionRecord)
  711. llvm::errs() << format("Exception Code: 0x%08X",
  712. ep->ExceptionRecord->ExceptionCode)
  713. << "\n";
  714. // We'll automatically write a Minidump file here to help diagnose
  715. // the nasty sorts of crashes that aren't 100% reproducible from a set of
  716. // inputs (or in the event that the user is unable or unwilling to provide a
  717. // reproducible case).
  718. if (!llvm::sys::Process::AreCoreFilesPrevented()) {
  719. MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo;
  720. ExceptionInfo.ThreadId = ::GetCurrentThreadId();
  721. ExceptionInfo.ExceptionPointers = ep;
  722. ExceptionInfo.ClientPointers = FALSE;
  723. if (std::error_code EC = WriteWindowsDumpFile(&ExceptionInfo))
  724. llvm::errs() << "Could not write crash dump file: " << EC.message()
  725. << "\n";
  726. }
  727. // Stack unwinding appears to modify the context. Copy it to preserve the
  728. // caller's context.
  729. CONTEXT ContextCopy;
  730. if (ep)
  731. memcpy(&ContextCopy, ep->ContextRecord, sizeof(ContextCopy));
  732. LocalPrintStackTrace(llvm::errs(), ep ? &ContextCopy : nullptr);
  733. return EXCEPTION_EXECUTE_HANDLER;
  734. }
  735. static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) {
  736. // We are running in our very own thread, courtesy of Windows.
  737. EnterCriticalSection(&CriticalSection);
  738. // This function is only ever called when a CTRL-C or similar control signal
  739. // is fired. Killing a process in this way is normal, so don't trigger the
  740. // signal handlers.
  741. Cleanup(false);
  742. // If an interrupt function has been set, go and run one it; otherwise,
  743. // the process dies.
  744. void (*IF)() = InterruptFunction;
  745. InterruptFunction = 0; // Don't run it on another CTRL-C.
  746. if (IF) {
  747. // Note: if the interrupt function throws an exception, there is nothing
  748. // to catch it in this thread so it will kill the process.
  749. IF(); // Run it now.
  750. LeaveCriticalSection(&CriticalSection);
  751. return TRUE; // Don't kill the process.
  752. }
  753. // Allow normal processing to take place; i.e., the process dies.
  754. LeaveCriticalSection(&CriticalSection);
  755. return FALSE;
  756. }
  757. #if __MINGW32__
  758. // We turned these warnings off for this file so that MinGW-g++ doesn't
  759. // complain about the ll format specifiers used. Now we are turning the
  760. // warnings back on. If MinGW starts to support diagnostic stacks, we can
  761. // replace this with a pop.
  762. #pragma GCC diagnostic warning "-Wformat"
  763. #pragma GCC diagnostic warning "-Wformat-extra-args"
  764. #endif
  765. void sys::unregisterHandlers() {}