1/**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6
7#include <windows.h>
8#include <excpt.h>
9#include <string.h>
10#include <stdlib.h>
11#include <malloc.h>
12#include <memory.h>
13#include <signal.h>
14#include <stdio.h>
15
16EXCEPTION_DISPOSITION __cdecl __mingw_SEH_error_handler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *);
17
18#if defined(__x86_64__) && !defined(_MSC_VER) && !defined(__SEH__)
19
20#pragma pack(push,1)
21typedef struct _UNWIND_INFO {
22 BYTE Version:3;
23 BYTE Flags:5;
24 BYTE PrologSize;
25 BYTE CountOfUnwindCodes;
26 BYTE FrameRegisterAndOffset;
27 ULONG AddressOfExceptionHandler;
28} UNWIND_INFO,*PUNWIND_INFO;
29#pragma pack(pop)
30
31PIMAGE_SECTION_HEADER _FindPESectionByName (const char *);
32PIMAGE_SECTION_HEADER _FindPESectionExec (size_t);
33PBYTE _GetPEImageBase (void);
34
35#define MAX_PDATA_ENTRIES 32
36static RUNTIME_FUNCTION emu_pdata[MAX_PDATA_ENTRIES];
37static UNWIND_INFO emu_xdata[MAX_PDATA_ENTRIES];
38
39int __mingw_init_ehandler (void);
40int
41__mingw_init_ehandler (void)
42{
43 static int was_here = 0;
44 size_t e = 0;
45 PIMAGE_SECTION_HEADER pSec;
46 PBYTE _ImageBase = _GetPEImageBase ();
47
48 if (was_here || !_ImageBase)
49 return was_here;
50 was_here = 1;
51 if (_FindPESectionByName (".pdata") != NULL)
52 return 1;
53
54 e = 0;
55 /* Fill tables and entries. */
56 while (e < MAX_PDATA_ENTRIES && (pSec = _FindPESectionExec (e)) != NULL)
57 {
58 emu_xdata[e].Version = 1;
59 emu_xdata[e].Flags = UNW_FLAG_EHANDLER;
60 emu_xdata[e].AddressOfExceptionHandler =
61 (DWORD)(size_t) ((LPBYTE)__mingw_SEH_error_handler - _ImageBase);
62 emu_pdata[e].BeginAddress = pSec->VirtualAddress;
63 emu_pdata[e].EndAddress = pSec->VirtualAddress + pSec->Misc.VirtualSize;
64 emu_pdata[e].UnwindData =
65 (DWORD)(size_t)((LPBYTE)&emu_xdata[e] - _ImageBase);
66 ++e;
67 }
68#ifdef _DEBUG_CRT
69 if (!e || e > MAX_PDATA_ENTRIES)
70 abort ();
71#endif
72 /* RtlAddFunctionTable. */
73 if (e != 0)
74 RtlAddFunctionTable (emu_pdata, e, (DWORD64)_ImageBase);
75 return 1;
76}
77
78#endif
79
80#if defined(__i386__)
81/* We need to make sure that we align the stack to 16 bytes for the sake of SSE */
82__attribute__((force_align_arg_pointer))
83#endif
84EXCEPTION_DISPOSITION __cdecl
85__mingw_SEH_error_handler (struct _EXCEPTION_RECORD* ExceptionRecord,
86 void *EstablisherFrame __attribute__ ((unused)),
87 struct _CONTEXT* ContextRecord,
88 void *DispatcherContext __attribute__ ((unused)))
89{
90 long action;
91
92 if (ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING)
93 return ExceptionContinueSearch;
94
95 /* Despite that the CRT _XcptFilter() function is SEH __except filter function,
96 * it directly executes the handler registered by CRT signal() function. Normally
97 * the SEH __except handler is called based on the SEH __except filter result.
98 *
99 * If the CRT signal handler function (called by _XcptFilter() function) returns
100 * then the CRT _XcptFilter() returns back to us and the action is set to:
101 * EXCEPTION_CONTINUE_EXECUTION - execution of the process should continue
102 * EXCEPTION_EXECUTE_HANDLER - execution of the process should be aborted
103 * EXCEPTION_CONTINUE_SEARCH - parent SEH handler should be called
104 */
105 action = _XcptFilter(ExceptionRecord->ExceptionCode, &(EXCEPTION_POINTERS){.ExceptionRecord = ExceptionRecord, .ContextRecord = ContextRecord});
106 switch (action)
107 {
108 case EXCEPTION_CONTINUE_SEARCH:
109 return ExceptionContinueSearch;
110
111 case EXCEPTION_CONTINUE_EXECUTION:
112 return ExceptionContinueExecution;
113
114 case EXCEPTION_EXECUTE_HANDLER:
115 default:
116 /* msvc CRT EXE exception handler just exit process with exception code */
117 _exit(ExceptionRecord->ExceptionCode);
118 }
119}