summaryrefslogtreecommitdiffstats
path: root/src/VBox/Runtime/common/compiler/vcc/except-vcc.h
blob: f611adb66060db25cb6bfd629482b3d1fcbbf53d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/* $Id: except-vcc.h $ */
/** @file
 * IPRT - Visual C++ Compiler - Exception Management.
 */

/*
 * Copyright (C) 2022-2023 Oracle and/or its affiliates.
 *
 * This file is part of VirtualBox base platform packages, as
 * available from https://www.virtualbox.org.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, in version 3 of the
 * License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <https://www.gnu.org/licenses>.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
 * in the VirtualBox distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 *
 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
 */

#ifndef IPRT_INCLUDED_SRC_common_compiler_vcc_except_vcc_h
#define IPRT_INCLUDED_SRC_common_compiler_vcc_except_vcc_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif

#define __C_specific_handler their___C_specific_handler
#include <iprt/win/windows.h>
#undef __C_specific_handler

#include <iprt/types.h>
#include <iprt/assertcompile.h>


RT_C_DECLS_BEGIN

#if 0
/** This is part of the AMD64 and ARM (?) exception interface, but appear to
 * live in the runtime headers for some weird reason. */
typedef enum
{
    ExceptionContinueExecution = 0,
    ExceptionContinueSearch,
    ExceptionNestedException,
    ExceptionCollidedUnwind
} EXCEPTION_DISPOSITION;
#endif

/* The following two are borrowed from pecoff.h, as we typically want to include
   winnt.h with this header and the two header cannot co-exist. */

/**
 * An unwind code for AMD64 and ARM64.
 *
 * @note Also known as UNWIND_CODE or _UNWIND_CODE.
 */
typedef union IMAGE_UNWIND_CODE
{
    struct
    {
        /** The prolog offset where the change takes effect.
         * This means the instruction following the one being described.  */
        uint8_t CodeOffset;
        /** Unwind opcode.
         * For AMD64 see IMAGE_AMD64_UNWIND_OP_CODES. */
        RT_GCC_EXTENSION uint8_t UnwindOp : 4;
        /** Opcode specific. */
        RT_GCC_EXTENSION uint8_t OpInfo   : 4;
    } u;
    uint16_t    FrameOffset;
} IMAGE_UNWIND_CODE;
AssertCompileSize(IMAGE_UNWIND_CODE, 2);

/**
 * Unwind information for AMD64 and ARM64.
 *
 * Pointed to by IMAGE_RUNTIME_FUNCTION_ENTRY::UnwindInfoAddress,
 *
 * @note Also known as UNWIND_INFO or _UNWIND_INFO.
 */
typedef struct IMAGE_UNWIND_INFO
{
    /** Version, currently 1 or 2.  The latter if IMAGE_AMD64_UWOP_EPILOG is used. */
    RT_GCC_EXTENSION uint8_t    Version : 3;
    /** IMAGE_UNW_FLAG_XXX */
    RT_GCC_EXTENSION uint8_t    Flags : 5;
    /** Size of function prolog. */
    uint8_t                     SizeOfProlog;
    /** Number of opcodes in aOpcodes. */
    uint8_t                     CountOfCodes;
    /** Initial frame register. */
    RT_GCC_EXTENSION uint8_t    FrameRegister : 4;
    /** Scaled frame register offset. */
    RT_GCC_EXTENSION uint8_t    FrameOffset : 4;
    /** Unwind opcodes. */
    RT_FLEXIBLE_ARRAY_EXTENSION
    IMAGE_UNWIND_CODE           aOpcodes[RT_FLEXIBLE_ARRAY];
} IMAGE_UNWIND_INFO;
AssertCompileMemberOffset(IMAGE_UNWIND_INFO, aOpcodes, 4);
typedef IMAGE_UNWIND_INFO *PIMAGE_UNWIND_INFO;
typedef IMAGE_UNWIND_INFO const *PCIMAGE_UNWIND_INFO;



#ifdef RT_ARCH_AMD64
/**
 * The Visual C++ 2019 layout of the GS_HANDLER_DATA data type for AMD64.
 *
 * This is pointed to by DISPATCHER_CONTEXT::HandlerData when dispatching
 * exceptions.  The data resides after the unwind info for the function.
 */
typedef struct _GS_HANDLER_DATA
{
    union
    {
        struct
        {
            uint32_t    fEHandler : 1;
#define GS_HANDLER_OFF_COOKIE_IS_EHANDLER   RT_BIT(0) /**< Handles exceptions. */
            uint32_t    fUHandler : 1;
#define GS_HANDLER_OFF_COOKIE_IS_UHANDLER   RT_BIT(1) /**< Handles unwind. */
            uint32_t    fHasAlignment : 1;
#define GS_HANDLER_OFF_COOKIE_HAS_ALIGNMENT RT_BIT(2) /**< Has the uAlignmentMask member. */
        } Bits;
#define GS_HANDLER_OFF_COOKIE_MASK          UINT32_C(0xfffffff8) /**< Mask to apply to offCookie to the the value. */
        uint32_t        offCookie;
    } u;
    int32_t             offAlignedBase;
    /** This field is only there when GS_HANDLER_OFF_COOKIE_HAS_ALIGNMENT is set.
     * it seems. */
    uint32_t            uAlignmentMask;
} GS_HANDLER_DATA;
typedef GS_HANDLER_DATA *PGS_HANDLER_DATA;
typedef GS_HANDLER_DATA const *PCGS_HANDLER_DATA;
#endif /* RT_ARCH_AMD64 */

#ifdef RT_ARCH_X86
void __fastcall __security_check_cookie(uintptr_t uCookieToCheck);
#else
void __cdecl    __security_check_cookie(uintptr_t uCookieToCheck);
#endif


#ifdef RT_ARCH_X86

/**
 * Exception registration record for _except_handler4 users
 * (aka EH4_EXCEPTION_REGISTRATION_RECORD).
 *
 * This record is emitted immediately following the stack frame setup, i.e.
 * after doing PUSH EBP and MOV EBP, ESP.  So, EBP equals the address following
 * this structure.
 */
typedef struct EH4_XCPT_REG_REC_T
{
    /** The saved ESP after setting up the stack frame and before the __try. */
    uintptr_t                       uSavedEsp;
    PEXCEPTION_POINTERS             pXctpPtrs;
    /** The SEH exception registration record (chained). */
    EXCEPTION_REGISTRATION_RECORD   XcptRec;
    uintptr_t                       uEncodedScopeTable;
    uint32_t                        uTryLevel;
    /* uintptr_t                    uSavedCallerEbp; */
} EH4_XCPT_REG_REC_T;
AssertCompileSize(EH4_XCPT_REG_REC_T, 24);
/** Pointer to an exception registration record for _except_handler4 (aka
 *  PEH4_EXCEPTION_REGISTRATION_RECORD). */
typedef EH4_XCPT_REG_REC_T *PEH4_XCPT_REG_REC_T;


/** Exception filter function for _except_handler4 users (aka
 * PEXCEPTION_FILTER_X86). */
typedef uint32_t (__cdecl *PFN_EH4_XCPT_FILTER_T)(void);
/** Exception handler block function for _except_handler4 users (aka
 * PEXCEPTION_HANDLER_X86). */
typedef void     (__cdecl *PFN_EH4_XCPT_HANDLER_T)(void);
/** Exception finally block function for _except_handler4 users (aka
 * PTERMINATION_HANDLER_X86).
 */
typedef void  (__fastcall *PFN_EH4_FINALLY_T)(BOOL fAbend);

/**
 * Scope table record describing  __try / __except / __finally blocks (aka
 * EH4_SCOPETABLE_RECORD).
 */
typedef struct EH4_SCOPE_TAB_REC_T
{
    uint32_t                    uEnclosingLevel;
    /** Pointer to the filter sub-function if this is a __try/__except, NULL for
     *  __try/__finally. */
    PFN_EH4_XCPT_FILTER_T       pfnFilter;
    union
    {
        PFN_EH4_XCPT_HANDLER_T  pfnHandler;
        PFN_EH4_FINALLY_T       pfnFinally;
    };
} EH4_SCOPE_TAB_REC_T;
AssertCompileSize(EH4_SCOPE_TAB_REC_T, 12);
/** Pointer to a const _except_handler4 scope table entry. */
typedef EH4_SCOPE_TAB_REC_T const *PCEH4_SCOPE_TAB_REC_T;

/** Special EH4_SCOPE_TAB_REC_T::uEnclosingLevel used to terminate the chain. */
#define EH4_TOPMOST_TRY_LEVEL   UINT32_C(0xfffffffe)

/**
 * Scope table used by _except_handler4 (aka EH4_SCOPETABLE).
 */
typedef struct EH4_SCOPE_TAB_T
{
    uint32_t                    offGSCookie;
    uint32_t                    offGSCookieXor;
    uint32_t                    offEHCookie;
    uint32_t                    offEHCookieXor;
    EH4_SCOPE_TAB_REC_T         aScopeRecords[RT_FLEXIBLE_ARRAY];
} EH4_SCOPE_TAB_T;
AssertCompileMemberOffset(EH4_SCOPE_TAB_T, aScopeRecords, 16);
/** Pointer to a const _except_handler4 scope table. */
typedef EH4_SCOPE_TAB_T const *PCEH4_SCOPE_TAB_T;

/** Special EH4_SCOPE_TAB_T::offGSCookie value. */
# define EH4_NO_GS_COOKIE       UINT32_C(0xfffffffe)

#endif /* RT_ARCH_X86 */



#if defined(RT_ARCH_AMD64)
EXCEPTION_DISPOSITION __C_specific_handler(PEXCEPTION_RECORD pXcptRec, PEXCEPTION_REGISTRATION_RECORD pXcptRegRec,
                                           PCONTEXT pCpuCtx, PDISPATCHER_CONTEXT pDispCtx);
#endif

RT_C_DECLS_END

#endif /* !IPRT_INCLUDED_SRC_common_compiler_vcc_except_vcc_h */