Home | History | Annotate | Line # | Download | only in unwind
      1 // Exception handling and frame unwind runtime interface routines.
      2 // Copyright (C) 2011-2022 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 ARM EABI and C6X unwinders.
     24 // This corresponds to unwind-arm-common.h
     25 
     26 module gcc.unwind.arm_common;
     27 
     28 import gcc.config;
     29 
     30 static if (GNU_ARM_EABI_Unwinder):
     31 
     32 import gcc.builtins;
     33 
     34 extern (C):
     35 
     36 // Placed outside @nogc in order to not constrain what the callback does.
     37 // ??? Does this really need to be extern(C) alias?
     38 extern(C) alias _Unwind_Exception_Cleanup_Fn
     39     = void function(_Unwind_Reason_Code, _Unwind_Exception*);
     40 
     41 extern(C) alias personality_routine
     42     = _Unwind_Reason_Code function(_Unwind_State,
     43                                    _Unwind_Control_Block*,
     44                                    _Unwind_Context*);
     45 
     46 extern(C) alias _Unwind_Stop_Fn
     47     =_Unwind_Reason_Code function(int, _Unwind_Action,
     48                                   _Unwind_Exception_Class,
     49                                   _Unwind_Control_Block*,
     50                                   _Unwind_Context*, void*);
     51 
     52 extern(C) alias _Unwind_Trace_Fn
     53     = _Unwind_Reason_Code function(_Unwind_Context*, void*);
     54 
     55 @nogc:
     56 
     57 alias _Unwind_Word = __builtin_machine_uint;
     58 alias _Unwind_Sword = __builtin_machine_int;
     59 alias _Unwind_Ptr = __builtin_pointer_uint;
     60 alias _Unwind_Internal_Ptr =__builtin_pointer_uint;
     61 alias _uw = _Unwind_Word;
     62 alias _uw64 = ulong;
     63 alias _uw16 = ushort;
     64 alias _uw8 = ubyte;
     65 
     66 alias _Unwind_Reason_Code = uint;
     67 enum : _Unwind_Reason_Code
     68 {
     69     _URC_OK = 0,        // operation completed successfully
     70     _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
     71     _URC_END_OF_STACK = 5,
     72     _URC_HANDLER_FOUND = 6,
     73     _URC_INSTALL_CONTEXT = 7,
     74     _URC_CONTINUE_UNWIND = 8,
     75     _URC_FAILURE = 9    // unspecified failure of some kind
     76 }
     77 
     78 alias _Unwind_State = int;
     79 enum : _Unwind_State
     80 {
     81     _US_VIRTUAL_UNWIND_FRAME = 0,
     82     _US_UNWIND_FRAME_STARTING = 1,
     83     _US_UNWIND_FRAME_RESUME = 2,
     84     _US_ACTION_MASK = 3,
     85     _US_FORCE_UNWIND = 8,
     86     _US_END_OF_STACK = 16
     87 }
     88 
     89 // Provided only for for compatibility with existing code.
     90 alias _Unwind_Action = int;
     91 enum : _Unwind_Action
     92 {
     93     _UA_SEARCH_PHASE = 1,
     94     _UA_CLEANUP_PHASE = 2,
     95     _UA_HANDLER_FRAME = 4,
     96     _UA_FORCE_UNWIND = 8,
     97     _UA_END_OF_STACK = 16,
     98     _URC_NO_REASON = _URC_OK
     99 }
    100 
    101 struct _Unwind_Context;
    102 alias _Unwind_EHT_Header = _uw;
    103 
    104 struct _Unwind_Control_Block
    105 {
    106     _Unwind_Exception_Class exception_class = '\0';
    107     _Unwind_Exception_Cleanup_Fn exception_cleanup;
    108     // Unwinder cache, private fields for the unwinder's use
    109     struct _unwinder_cache
    110     {
    111         _uw reserved1;  // Forced unwind stop fn, 0 if not forced
    112         _uw reserved2;  // Personality routine address
    113         _uw reserved3;  // Saved callsite address
    114         _uw reserved4;  // Forced unwind stop arg
    115         _uw reserved5;
    116     }
    117     _unwinder_cache unwinder_cache;
    118     // Propagation barrier cache (valid after phase 1):
    119     struct _barrier_cache
    120     {
    121         _uw sp;
    122         _uw[5] bitpattern;
    123     }
    124     _barrier_cache barrier_cache;
    125     // Cleanup cache (preserved over cleanup):
    126     struct _cleanup_cache
    127     {
    128         _uw[4] bitpattern;
    129     }
    130     _cleanup_cache cleanup_cache;
    131     // Pr cache (for pr's benefit):
    132     struct _pr_cache
    133     {
    134         _uw fnstart;                // function start address */
    135         _Unwind_EHT_Header* ehtp;   // pointer to EHT entry header word
    136         _uw additional;             // additional data
    137         _uw reserved1;
    138     }
    139     _pr_cache pr_cache;
    140     long[0] _force_alignment;       // Force alignment to 8-byte boundary
    141 }
    142 
    143 // Virtual Register Set
    144 alias _Unwind_VRS_RegClass = int;
    145 enum : _Unwind_VRS_RegClass
    146 {
    147     _UVRSC_CORE = 0,    // integer register
    148     _UVRSC_VFP = 1,     // vfp
    149     _UVRSC_FPA = 2,     // fpa
    150     _UVRSC_WMMXD = 3,   // Intel WMMX data register
    151     _UVRSC_WMMXC = 4    // Intel WMMX control register
    152 }
    153 
    154 alias _Unwind_VRS_DataRepresentation = int;
    155 enum : _Unwind_VRS_DataRepresentation
    156 {
    157     _UVRSD_UINT32 = 0,
    158     _UVRSD_VFPX = 1,
    159     _UVRSD_FPAX = 2,
    160     _UVRSD_UINT64 = 3,
    161     _UVRSD_FLOAT = 4,
    162     _UVRSD_DOUBLE = 5
    163 }
    164 
    165 alias _Unwind_VRS_Result = int;
    166 enum : _Unwind_VRS_Result
    167 {
    168     _UVRSR_OK = 0,
    169     _UVRSR_NOT_IMPLEMENTED = 1,
    170     _UVRSR_FAILED = 2
    171 }
    172 
    173 // Frame unwinding state.
    174 struct __gnu_unwind_state
    175 {
    176     _uw data;           // The current word (bytes packed msb first).
    177     _uw* next;          // Pointer to the next word of data.
    178     _uw8 bytes_left;    // The number of bytes left in this word.
    179     _uw8 words_left;    // The number of words pointed to by ptr.
    180 }
    181 
    182 _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context*, _Unwind_VRS_RegClass,
    183                                    _uw, _Unwind_VRS_DataRepresentation,
    184                                    void*);
    185 
    186 _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context*, _Unwind_VRS_RegClass,
    187                                    _uw, _Unwind_VRS_DataRepresentation,
    188                                    void*);
    189 
    190 _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context*, _Unwind_VRS_RegClass,
    191                                    _uw, _Unwind_VRS_DataRepresentation);
    192 
    193 
    194 // Support functions for the PR.
    195 alias _Unwind_Exception = _Unwind_Control_Block;
    196 alias _Unwind_Exception_Class = char[8];
    197 
    198 void* _Unwind_GetLanguageSpecificData(_Unwind_Context*);
    199 _Unwind_Ptr _Unwind_GetRegionStart(_Unwind_Context*);
    200 
    201 _Unwind_Ptr _Unwind_GetDataRelBase(_Unwind_Context*);
    202 // This should never be used.
    203 _Unwind_Ptr _Unwind_GetTextRelBase(_Unwind_Context*);
    204 
    205 // Interface functions:
    206 _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block*);
    207 void _Unwind_Resume(_Unwind_Control_Block*);
    208 _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Control_Block*);
    209 
    210 _Unwind_Reason_Code _Unwind_ForcedUnwind(_Unwind_Control_Block*,
    211                                          _Unwind_Stop_Fn, void*);
    212 
    213 // @@@ Use unwind data to perform a stack backtrace.  The trace callback
    214 // is called for every stack frame in the call chain, but no cleanup
    215 // actions are performed.
    216 _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void*);
    217 
    218 _Unwind_Word _Unwind_GetCFA(_Unwind_Context*);
    219 void _Unwind_Complete(_Unwind_Control_Block*);
    220 void _Unwind_DeleteException(_Unwind_Exception*);
    221 
    222 _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Control_Block*,
    223                                        _Unwind_Context*);
    224 _Unwind_Reason_Code __gnu_unwind_execute(_Unwind_Context*,
    225                                          __gnu_unwind_state*);
    226 
    227 _Unwind_Word _Unwind_GetGR(_Unwind_Context* context, int regno)
    228 {
    229     _uw val;
    230     _Unwind_VRS_Get(context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
    231     return val;
    232 }
    233 
    234 void _Unwind_SetGR(_Unwind_Context* context, int regno, _Unwind_Word val)
    235 {
    236     _Unwind_VRS_Set(context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
    237 }
    238 
    239 // leb128 type numbers have a potentially unlimited size.
    240 // The target of the following definitions of _sleb128_t and _uleb128_t
    241 // is to have efficient data types large enough to hold the leb128 type
    242 // numbers used in the unwind code.
    243 alias _sleb128_t = __builtin_clong;
    244 alias _uleb128_t = __builtin_culong;
    245