1 // Exception handling and frame unwind runtime interface routines. 2 // Copyright (C) 2011-2020 Free Software Foundation, Inc. 3 4 // GCC is free software; you can redistribute it and/or modify it under 5 // the terms of the GNU General Public License as published by the Free 6 // Software Foundation; either version 3, or (at your option) any later 7 // version. 8 9 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY 10 // WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 // for more details. 13 14 // Under Section 7 of GPL version 3, you are granted additional 15 // permissions described in the GCC Runtime Library Exception, version 16 // 3.1, as published by the Free Software Foundation. 17 18 // You should have received a copy of the GNU General Public License and 19 // a copy of the GCC Runtime Library Exception along with this program; 20 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 21 // <http://www.gnu.org/licenses/>. 22 23 // extern(C) interface for the generic unwinder library. 24 // This corresponds to unwind-generic.h 25 26 module gcc.unwind.generic; 27 28 import gcc.config; 29 30 static if (!GNU_ARM_EABI_Unwinder): 31 32 import gcc.builtins; 33 34 // This is derived from the C++ ABI for IA-64. Where we diverge 35 // for cross-architecture compatibility are noted with "@@@". 36 37 extern (C): 38 39 // Placed outside @nogc in order to not constrain what the callback does. 40 // ??? Does this really need to be extern(C) alias? 41 42 extern(C) alias _Unwind_Exception_Cleanup_Fn 43 = void function(_Unwind_Reason_Code, _Unwind_Exception*); 44 45 extern(C) alias _Unwind_Stop_Fn 46 = _Unwind_Reason_Code function(int, _Unwind_Action, 47 _Unwind_Exception_Class, 48 _Unwind_Exception*, 49 _Unwind_Context*, void*); 50 51 extern(C) alias _Unwind_Trace_Fn 52 = _Unwind_Reason_Code function(_Unwind_Context*, void*); 53 54 // The personality routine is the function in the C++ (or other language) 55 // runtime library which serves as an interface between the system unwind 56 // library and language-specific exception handling semantics. It is 57 // specific to the code fragment described by an unwind info block, and 58 // it is always referenced via the pointer in the unwind info block, and 59 // hence it has no ABI-specified name. 60 61 // Note that this implies that two different C++ implementations can 62 // use different names, and have different contents in the language 63 // specific data area. Moreover, that the language specific data 64 // area contains no version info because name of the function invoked 65 // provides more effective versioning by detecting at link time the 66 // lack of code to handle the different data format. 67 68 extern(C) alias _Unwind_Personality_Fn 69 = _Unwind_Reason_Code function(int, _Unwind_Action, 70 _Unwind_Exception_Class, 71 _Unwind_Exception*, 72 _Unwind_Context*); 73 74 @nogc: 75 76 // Level 1: Base ABI 77 78 // @@@ The IA-64 ABI uses uint64 throughout. 79 // Most places this is inefficient for 32-bit and smaller machines. 80 alias _Unwind_Word = __builtin_unwind_uint; 81 alias _Unwind_Sword = __builtin_unwind_int; 82 version (IA64) 83 { 84 version (HPUX) 85 alias _Unwind_Ptr = __builtin_machine_uint; 86 else 87 alias _Unwind_Ptr = __builtin_pointer_uint; 88 } 89 else 90 { 91 alias _Unwind_Ptr = __builtin_pointer_uint; 92 } 93 alias _Unwind_Internal_Ptr = __builtin_pointer_uint; 94 95 // @@@ The IA-64 ABI uses a 64-bit word to identify the producer and 96 // consumer of an exception. We'll go along with this for now even on 97 // 32-bit machines. We'll need to provide some other option for 98 // 16-bit machines and for machines with > 8 bits per byte. 99 alias _Unwind_Exception_Class = ulong; 100 101 // The unwind interface uses reason codes in several contexts to 102 // identify the reasons for failures or other actions. 103 alias _Unwind_Reason_Code = uint; 104 enum : _Unwind_Reason_Code 105 { 106 _URC_NO_REASON = 0, 107 _URC_FOREIGN_EXCEPTION_CAUGHT = 1, 108 _URC_FATAL_PHASE2_ERROR = 2, 109 _URC_FATAL_PHASE1_ERROR = 3, 110 _URC_NORMAL_STOP = 4, 111 _URC_END_OF_STACK = 5, 112 _URC_HANDLER_FOUND = 6, 113 _URC_INSTALL_CONTEXT = 7, 114 _URC_CONTINUE_UNWIND = 8 115 } 116 117 // The unwind interface uses a pointer to an exception header object 118 // as its representation of an exception being thrown. In general, the 119 // full representation of an exception object is language- and 120 // implementation-specific, but it will be prefixed by a header 121 // understood by the unwind interface. 122 123 // @@@ The IA-64 ABI says that this structure must be double-word aligned. 124 // Taking that literally does not make much sense generically. Instead we 125 // provide the maximum alignment required by any type for the machine. 126 version (ARM) private enum __aligned__ = 8; 127 else version (AArch64) private enum __aligned__ = 16; 128 else version (HPPA) private enum __aligned__ = 8; 129 else version (HPPA64) private enum __aligned__ = 16; 130 else version (MIPS_N32) private enum __aligned__ = 16; 131 else version (MIPS_N64) private enum __aligned__ = 16; 132 else version (MIPS32) private enum __aligned__ = 8; 133 else version (MIPS64) private enum __aligned__ = 8; 134 else version (PPC) private enum __aligned__ = 16; 135 else version (PPC64) private enum __aligned__ = 16; 136 else version (RISCV32) private enum __aligned__ = 16; 137 else version (RISCV64) private enum __aligned__ = 16; 138 else version (S390) private enum __aligned__ = 8; 139 else version (SPARC) private enum __aligned__ = 8; 140 else version (SPARC64) private enum __aligned__ = 16; 141 else version (SystemZ) private enum __aligned__ = 8; 142 else version (X86) private enum __aligned__ = 16; 143 else version (X86_64) private enum __aligned__ = 16; 144 else static assert( false, "Platform not supported."); 145 146 align(__aligned__) struct _Unwind_Exception 147 { 148 _Unwind_Exception_Class exception_class; 149 _Unwind_Exception_Cleanup_Fn exception_cleanup; 150 _Unwind_Word private_1; 151 _Unwind_Word private_2; 152 } 153 154 // The ACTIONS argument to the personality routine is a bitwise OR of one 155 // or more of the following constants. 156 alias _Unwind_Action = int; 157 enum : _Unwind_Action 158 { 159 _UA_SEARCH_PHASE = 1, 160 _UA_CLEANUP_PHASE = 2, 161 _UA_HANDLER_FRAME = 4, 162 _UA_FORCE_UNWIND = 8, 163 _UA_END_OF_STACK = 16 164 } 165 166 // This is an opaque type used to refer to a system-specific data 167 // structure used by the system unwinder. This context is created and 168 // destroyed by the system, and passed to the personality routine 169 // during unwinding. 170 struct _Unwind_Context; 171 172 // Raise an exception, passing along the given exception object. 173 _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*); 174 175 // Raise an exception for forced unwinding. 176 _Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Exception*, _Unwind_Stop_Fn, void*); 177 178 // Helper to invoke the exception_cleanup routine. 179 void _Unwind_DeleteException(_Unwind_Exception*); 180 181 // Resume propagation of an existing exception. This is used after 182 // e.g. executing cleanup code, and not to implement rethrowing. 183 void _Unwind_Resume(_Unwind_Exception*); 184 185 // @@@ Resume propagation of an FORCE_UNWIND exception, or to rethrow 186 // a normal exception that was handled. 187 _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Exception*); 188 189 // @@@ Use unwind data to perform a stack backtrace. The trace callback 190 // is called for every stack frame in the call chain, but no cleanup 191 // actions are performed. 192 _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void*); 193 194 // These functions are used for communicating information about the unwind 195 // context (i.e. the unwind descriptors and the user register state) between 196 // the unwind library and the personality routine and landing pad. Only 197 // selected registers may be manipulated. 198 199 _Unwind_Word _Unwind_GetGR(_Unwind_Context*, int); 200 void _Unwind_SetGR(_Unwind_Context*, int, _Unwind_Word); 201 202 _Unwind_Ptr _Unwind_GetIP(_Unwind_Context*); 203 _Unwind_Ptr _Unwind_GetIPInfo(_Unwind_Context*, int*); 204 void _Unwind_SetIP(_Unwind_Context*, _Unwind_Ptr); 205 206 // @@@ Retrieve the CFA of the given context. 207 _Unwind_Word _Unwind_GetCFA(_Unwind_Context*); 208 209 void* _Unwind_GetLanguageSpecificData(_Unwind_Context*); 210 211 _Unwind_Ptr _Unwind_GetRegionStart(_Unwind_Context*); 212 213 214 // @@@ The following alternate entry points are for setjmp/longjmp 215 // based unwinding. 216 217 struct SjLj_Function_Context; 218 extern void _Unwind_SjLj_Register(SjLj_Function_Context*); 219 extern void _Unwind_SjLj_Unregister(SjLj_Function_Context*); 220 221 _Unwind_Reason_Code _Unwind_SjLj_RaiseException(_Unwind_Exception*); 222 _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind(_Unwind_Exception*, _Unwind_Stop_Fn, void*); 223 void _Unwind_SjLj_Resume(_Unwind_Exception*); 224 _Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception*); 225 226 // @@@ The following provide access to the base addresses for text 227 // and data-relative addressing in the LDSA. In order to stay link 228 // compatible with the standard ABI for IA-64, we inline these. 229 230 version (IA64) 231 { 232 _Unwind_Ptr _Unwind_GetDataRelBase(_Unwind_Context* _C) 233 { 234 // The GP is stored in R1. 235 return _Unwind_GetGR(_C, 1); 236 } 237 238 _Unwind_Ptr _Unwind_GetTextRelBase(_Unwind_Context*) 239 { 240 __builtin_abort(); 241 return 0; 242 } 243 244 // @@@ Retrieve the Backing Store Pointer of the given context. 245 _Unwind_Word _Unwind_GetBSP(_Unwind_Context*); 246 } 247 else 248 { 249 _Unwind_Ptr _Unwind_GetDataRelBase(_Unwind_Context*); 250 _Unwind_Ptr _Unwind_GetTextRelBase(_Unwind_Context*); 251 } 252 253 // @@@ Given an address, return the entry point of the function that 254 // contains it. 255 extern void* _Unwind_FindEnclosingFunction(void* pc); 256 257 258 // leb128 type numbers have a potentially unlimited size. 259 // The target of the following definitions of _sleb128_t and _uleb128_t 260 // is to have efficient data types large enough to hold the leb128 type 261 // numbers used in the unwind code. 262 // Mostly these types will simply be defined to long and unsigned long 263 // except when a unsigned long data type on the target machine is not 264 // capable of storing a pointer. 265 266 static if (__builtin_clong.sizeof >= (void*).sizeof) 267 { 268 alias _sleb128_t = __builtin_clong; 269 alias _uleb128_t = __builtin_culong; 270 } 271 else static if (long.sizeof >= (void*).sizeof) 272 { 273 alias _sleb128_t = long; 274 alias _uleb128_t = ulong; 275 } 276 else 277 { 278 static assert(false, "What type shall we use for _sleb128_t?"); 279 } 280 281 version (GNU_SEH_Exceptions) 282 { 283 // We're lazy, exact definition in MinGW/winnt.h 284 enum EXCEPTION_DISPOSITION 285 { 286 ExceptionContinueExecution, 287 ExceptionContinueSearch, 288 ExceptionNestedException, 289 ExceptionCollidedUnwind 290 } 291 292 extern(C) EXCEPTION_DISPOSITION _GCC_specific_handler(void*, void*, void*, 293 _Unwind_Personality_Fn); 294 } 295