1af526226Smrg /* ARM EABI compliant unwinding routines 2*ff135a7aSmrg Copyright (C) 2004-2019 Free Software Foundation, Inc. 3af526226Smrg Contributed by Paul Brook 4af526226Smrg 5af526226Smrg This file is free software; you can redistribute it and/or modify it 6af526226Smrg under the terms of the GNU General Public License as published by the 7af526226Smrg Free Software Foundation; either version 3, or (at your option) any 8af526226Smrg later version. 9af526226Smrg 10af526226Smrg This file is distributed in the hope that it will be useful, but 11af526226Smrg WITHOUT ANY WARRANTY; without even the implied warranty of 12af526226Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13af526226Smrg General Public License for more details. 14af526226Smrg 15af526226Smrg Under Section 7 of GPL version 3, you are granted additional 16af526226Smrg permissions described in the GCC Runtime Library Exception, version 17af526226Smrg 3.1, as published by the Free Software Foundation. 18af526226Smrg 19af526226Smrg You should have received a copy of the GNU General Public License and 20af526226Smrg a copy of the GCC Runtime Library Exception along with this program; 21af526226Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22af526226Smrg <http://www.gnu.org/licenses/>. */ 23af526226Smrg 24*ff135a7aSmrg #pragma GCC target ("general-regs-only") 25af526226Smrg #include "unwind.h" 26af526226Smrg 27af526226Smrg /* We add a prototype for abort here to avoid creating a dependency on 28af526226Smrg target headers. */ 29af526226Smrg extern void abort (void); 30af526226Smrg 31af526226Smrg typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */ 32af526226Smrg 33af526226Smrg /* Misc constants. */ 34af526226Smrg #define R_IP 12 35af526226Smrg #define R_SP 13 36af526226Smrg #define R_LR 14 37af526226Smrg #define R_PC 15 38af526226Smrg 39af526226Smrg #define uint32_highbit (((_uw) 1) << 31) 40af526226Smrg 41af526226Smrg void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp); 42af526226Smrg 43af526226Smrg /* Unwind descriptors. */ 44af526226Smrg 45af526226Smrg typedef struct 46af526226Smrg { 47af526226Smrg _uw16 length; 48af526226Smrg _uw16 offset; 49af526226Smrg } EHT16; 50af526226Smrg 51af526226Smrg typedef struct 52af526226Smrg { 53af526226Smrg _uw length; 54af526226Smrg _uw offset; 55af526226Smrg } EHT32; 56af526226Smrg 57af526226Smrg /* Calculate the address encoded by a 31-bit self-relative offset at address 58af526226Smrg P. Copy of routine in unwind-arm.c. */ 59af526226Smrg 60af526226Smrg static inline _uw 61af526226Smrg selfrel_offset31 (const _uw *p) 62af526226Smrg { 63af526226Smrg _uw offset; 64af526226Smrg 65af526226Smrg offset = *p; 66af526226Smrg /* Sign extend to 32 bits. */ 67af526226Smrg if (offset & (1 << 30)) 68af526226Smrg offset |= 1u << 31; 69af526226Smrg 70af526226Smrg return offset + (_uw) p; 71af526226Smrg } 72af526226Smrg 73af526226Smrg 74af526226Smrg /* Personality routine helper functions. */ 75af526226Smrg 76af526226Smrg #define CODE_FINISH (0xb0) 77af526226Smrg 78af526226Smrg /* Return the next byte of unwinding information, or CODE_FINISH if there is 79af526226Smrg no data remaining. */ 80af526226Smrg static inline _uw8 81af526226Smrg next_unwind_byte (__gnu_unwind_state * uws) 82af526226Smrg { 83af526226Smrg _uw8 b; 84af526226Smrg 85af526226Smrg if (uws->bytes_left == 0) 86af526226Smrg { 87af526226Smrg /* Load another word */ 88af526226Smrg if (uws->words_left == 0) 89af526226Smrg return CODE_FINISH; /* Nothing left. */ 90af526226Smrg uws->words_left--; 91af526226Smrg uws->data = *(uws->next++); 92af526226Smrg uws->bytes_left = 3; 93af526226Smrg } 94af526226Smrg else 95af526226Smrg uws->bytes_left--; 96af526226Smrg 97af526226Smrg /* Extract the most significant byte. */ 98af526226Smrg b = (uws->data >> 24) & 0xff; 99af526226Smrg uws->data <<= 8; 100af526226Smrg return b; 101af526226Smrg } 102af526226Smrg 103af526226Smrg /* Execute the unwinding instructions described by UWS. */ 104af526226Smrg _Unwind_Reason_Code 105af526226Smrg __gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws) 106af526226Smrg { 107af526226Smrg _uw op; 108af526226Smrg int set_pc; 109af526226Smrg _uw reg; 110af526226Smrg 111af526226Smrg set_pc = 0; 112af526226Smrg for (;;) 113af526226Smrg { 114af526226Smrg op = next_unwind_byte (uws); 115af526226Smrg if (op == CODE_FINISH) 116af526226Smrg { 117af526226Smrg /* If we haven't already set pc then copy it from lr. */ 118af526226Smrg if (!set_pc) 119af526226Smrg { 120af526226Smrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_LR, _UVRSD_UINT32, 121af526226Smrg ®); 122af526226Smrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, 123af526226Smrg ®); 124af526226Smrg set_pc = 1; 125af526226Smrg } 126af526226Smrg /* Drop out of the loop. */ 127af526226Smrg break; 128af526226Smrg } 129af526226Smrg if ((op & 0x80) == 0) 130af526226Smrg { 131af526226Smrg /* vsp = vsp +- (imm6 << 2 + 4). */ 132af526226Smrg _uw offset; 133af526226Smrg 134af526226Smrg offset = ((op & 0x3f) << 2) + 4; 135af526226Smrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®); 136af526226Smrg if (op & 0x40) 137af526226Smrg reg -= offset; 138af526226Smrg else 139af526226Smrg reg += offset; 140af526226Smrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®); 141af526226Smrg continue; 142af526226Smrg } 143af526226Smrg 144af526226Smrg if ((op & 0xf0) == 0x80) 145af526226Smrg { 146af526226Smrg op = (op << 8) | next_unwind_byte (uws); 147af526226Smrg if (op == 0x8000) 148af526226Smrg { 149af526226Smrg /* Refuse to unwind. */ 150af526226Smrg return _URC_FAILURE; 151af526226Smrg } 152af526226Smrg /* Pop r4-r15 under mask. */ 153af526226Smrg op = (op << 4) & 0xfff0; 154af526226Smrg if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32) 155af526226Smrg != _UVRSR_OK) 156af526226Smrg return _URC_FAILURE; 157af526226Smrg if (op & (1 << R_PC)) 158af526226Smrg set_pc = 1; 159af526226Smrg continue; 160af526226Smrg } 161af526226Smrg if ((op & 0xf0) == 0x90) 162af526226Smrg { 163af526226Smrg op &= 0xf; 164af526226Smrg if (op == 13 || op == 15) 165af526226Smrg /* Reserved. */ 166af526226Smrg return _URC_FAILURE; 167af526226Smrg /* vsp = r[nnnn]. */ 168af526226Smrg _Unwind_VRS_Get (context, _UVRSC_CORE, op, _UVRSD_UINT32, ®); 169af526226Smrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®); 170af526226Smrg continue; 171af526226Smrg } 172af526226Smrg if ((op & 0xf0) == 0xa0) 173af526226Smrg { 174af526226Smrg /* Pop r4-r[4+nnn], [lr]. */ 175af526226Smrg _uw mask; 176af526226Smrg 177af526226Smrg mask = (0xff0 >> (7 - (op & 7))) & 0xff0; 178af526226Smrg if (op & 8) 179af526226Smrg mask |= (1 << R_LR); 180af526226Smrg if (_Unwind_VRS_Pop (context, _UVRSC_CORE, mask, _UVRSD_UINT32) 181af526226Smrg != _UVRSR_OK) 182af526226Smrg return _URC_FAILURE; 183af526226Smrg continue; 184af526226Smrg } 185af526226Smrg if ((op & 0xf0) == 0xb0) 186af526226Smrg { 187af526226Smrg /* op == 0xb0 already handled. */ 188af526226Smrg if (op == 0xb1) 189af526226Smrg { 190af526226Smrg op = next_unwind_byte (uws); 191af526226Smrg if (op == 0 || ((op & 0xf0) != 0)) 192af526226Smrg /* Spare. */ 193af526226Smrg return _URC_FAILURE; 194af526226Smrg /* Pop r0-r4 under mask. */ 195af526226Smrg if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32) 196af526226Smrg != _UVRSR_OK) 197af526226Smrg return _URC_FAILURE; 198af526226Smrg continue; 199af526226Smrg } 200af526226Smrg if (op == 0xb2) 201af526226Smrg { 202af526226Smrg /* vsp = vsp + 0x204 + (uleb128 << 2). */ 203af526226Smrg int shift; 204af526226Smrg 205af526226Smrg _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, 206af526226Smrg ®); 207af526226Smrg op = next_unwind_byte (uws); 208af526226Smrg shift = 2; 209af526226Smrg while (op & 0x80) 210af526226Smrg { 211af526226Smrg reg += ((op & 0x7f) << shift); 212af526226Smrg shift += 7; 213af526226Smrg op = next_unwind_byte (uws); 214af526226Smrg } 215af526226Smrg reg += ((op & 0x7f) << shift) + 0x204; 216af526226Smrg _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, 217af526226Smrg ®); 218af526226Smrg continue; 219af526226Smrg } 220af526226Smrg if (op == 0xb3) 221af526226Smrg { 222af526226Smrg /* Pop VFP registers with fldmx. */ 223af526226Smrg op = next_unwind_byte (uws); 224af526226Smrg op = ((op & 0xf0) << 12) | ((op & 0xf) + 1); 225af526226Smrg if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX) 226af526226Smrg != _UVRSR_OK) 227af526226Smrg return _URC_FAILURE; 228af526226Smrg continue; 229af526226Smrg } 230af526226Smrg if ((op & 0xfc) == 0xb4) /* Obsolete FPA. */ 231af526226Smrg return _URC_FAILURE; 232af526226Smrg 233af526226Smrg /* op & 0xf8 == 0xb8. */ 234af526226Smrg /* Pop VFP D[8]-D[8+nnn] with fldmx. */ 235af526226Smrg op = 0x80000 | ((op & 7) + 1); 236af526226Smrg if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX) 237af526226Smrg != _UVRSR_OK) 238af526226Smrg return _URC_FAILURE; 239af526226Smrg continue; 240af526226Smrg } 241af526226Smrg if ((op & 0xf0) == 0xc0) 242af526226Smrg { 243af526226Smrg if (op == 0xc6) 244af526226Smrg { 245af526226Smrg /* Pop iWMMXt D registers. */ 246af526226Smrg op = next_unwind_byte (uws); 247af526226Smrg op = ((op & 0xf0) << 12) | ((op & 0xf) + 1); 248af526226Smrg if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64) 249af526226Smrg != _UVRSR_OK) 250af526226Smrg return _URC_FAILURE; 251af526226Smrg continue; 252af526226Smrg } 253af526226Smrg if (op == 0xc7) 254af526226Smrg { 255af526226Smrg op = next_unwind_byte (uws); 256af526226Smrg if (op == 0 || (op & 0xf0) != 0) 257af526226Smrg /* Spare. */ 258af526226Smrg return _URC_FAILURE; 259af526226Smrg /* Pop iWMMXt wCGR{3,2,1,0} under mask. */ 260af526226Smrg if (_Unwind_VRS_Pop (context, _UVRSC_WMMXC, op, _UVRSD_UINT32) 261af526226Smrg != _UVRSR_OK) 262af526226Smrg return _URC_FAILURE; 263af526226Smrg continue; 264af526226Smrg } 265af526226Smrg if ((op & 0xf8) == 0xc0) 266af526226Smrg { 267af526226Smrg /* Pop iWMMXt wR[10]-wR[10+nnn]. */ 268af526226Smrg op = 0xa0000 | ((op & 0xf) + 1); 269af526226Smrg if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64) 270af526226Smrg != _UVRSR_OK) 271af526226Smrg return _URC_FAILURE; 272af526226Smrg continue; 273af526226Smrg } 274af526226Smrg if (op == 0xc8) 275af526226Smrg { 276af526226Smrg /* Pop VFPv3 registers D[16+ssss]-D[16+ssss+cccc] with vldm. */ 277af526226Smrg op = next_unwind_byte (uws); 278af526226Smrg op = (((op & 0xf0) + 16) << 12) | ((op & 0xf) + 1); 279af526226Smrg if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE) 280af526226Smrg != _UVRSR_OK) 281af526226Smrg return _URC_FAILURE; 282af526226Smrg continue; 283af526226Smrg } 284af526226Smrg if (op == 0xc9) 285af526226Smrg { 286af526226Smrg /* Pop VFP registers with fldmd. */ 287af526226Smrg op = next_unwind_byte (uws); 288af526226Smrg op = ((op & 0xf0) << 12) | ((op & 0xf) + 1); 289af526226Smrg if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE) 290af526226Smrg != _UVRSR_OK) 291af526226Smrg return _URC_FAILURE; 292af526226Smrg continue; 293af526226Smrg } 294af526226Smrg /* Spare. */ 295af526226Smrg return _URC_FAILURE; 296af526226Smrg } 297af526226Smrg if ((op & 0xf8) == 0xd0) 298af526226Smrg { 299af526226Smrg /* Pop VFP D[8]-D[8+nnn] with fldmd. */ 300af526226Smrg op = 0x80000 | ((op & 7) + 1); 301af526226Smrg if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE) 302af526226Smrg != _UVRSR_OK) 303af526226Smrg return _URC_FAILURE; 304af526226Smrg continue; 305af526226Smrg } 306af526226Smrg /* Spare. */ 307af526226Smrg return _URC_FAILURE; 308af526226Smrg } 309af526226Smrg return _URC_OK; 310af526226Smrg } 311af526226Smrg 312af526226Smrg 313af526226Smrg /* Execute the unwinding instructions associated with a frame. UCBP and 314af526226Smrg CONTEXT are the current exception object and virtual CPU state 315af526226Smrg respectively. */ 316af526226Smrg 317af526226Smrg _Unwind_Reason_Code 318af526226Smrg __gnu_unwind_frame (_Unwind_Control_Block * ucbp, _Unwind_Context * context) 319af526226Smrg { 320af526226Smrg _uw *ptr; 321af526226Smrg __gnu_unwind_state uws; 322af526226Smrg 323af526226Smrg ptr = (_uw *) ucbp->pr_cache.ehtp; 324af526226Smrg /* Skip over the personality routine address. */ 325af526226Smrg ptr++; 326af526226Smrg /* Setup the unwinder state. */ 327af526226Smrg uws.data = (*ptr) << 8; 328af526226Smrg uws.next = ptr + 1; 329af526226Smrg uws.bytes_left = 3; 330af526226Smrg uws.words_left = ((*ptr) >> 24) & 0xff; 331af526226Smrg 332af526226Smrg return __gnu_unwind_execute (context, &uws); 333af526226Smrg } 334af526226Smrg 335af526226Smrg /* Get the _Unwind_Control_Block from an _Unwind_Context. */ 336af526226Smrg 337af526226Smrg static inline _Unwind_Control_Block * 338af526226Smrg unwind_UCB_from_context (_Unwind_Context * context) 339af526226Smrg { 340af526226Smrg return (_Unwind_Control_Block *) _Unwind_GetGR (context, R_IP); 341af526226Smrg } 342af526226Smrg 343af526226Smrg /* Get the start address of the function being unwound. */ 344af526226Smrg 345af526226Smrg _Unwind_Ptr 346af526226Smrg _Unwind_GetRegionStart (_Unwind_Context * context) 347af526226Smrg { 348af526226Smrg _Unwind_Control_Block *ucbp; 349af526226Smrg 350af526226Smrg ucbp = unwind_UCB_from_context (context); 351af526226Smrg return (_Unwind_Ptr) ucbp->pr_cache.fnstart; 352af526226Smrg } 353af526226Smrg 354af526226Smrg /* Find the Language specific exception data. */ 355af526226Smrg 356f062cf65Sjoerg _Unwind_Ptr 357af526226Smrg _Unwind_GetLanguageSpecificData (_Unwind_Context * context) 358af526226Smrg { 359af526226Smrg _Unwind_Control_Block *ucbp; 360af526226Smrg _uw *ptr; 361af526226Smrg 362af526226Smrg /* Get a pointer to the exception table entry. */ 363af526226Smrg ucbp = unwind_UCB_from_context (context); 364af526226Smrg ptr = (_uw *) ucbp->pr_cache.ehtp; 365af526226Smrg /* Skip the personality routine address. */ 366af526226Smrg ptr++; 367af526226Smrg /* Skip the unwind opcodes. */ 368af526226Smrg ptr += (((*ptr) >> 24) & 0xff) + 1; 369af526226Smrg 370a0903846Sozaki-r return (_Unwind_Ptr) ptr; 371af526226Smrg } 372af526226Smrg 373af526226Smrg 374af526226Smrg /* These two should never be used. */ 375af526226Smrg 376af526226Smrg _Unwind_Ptr 377af526226Smrg _Unwind_GetDataRelBase (_Unwind_Context *context __attribute__ ((unused))) 378af526226Smrg { 379af526226Smrg abort (); 380af526226Smrg } 381af526226Smrg 382af526226Smrg _Unwind_Ptr 383af526226Smrg _Unwind_GetTextRelBase (_Unwind_Context *context __attribute__ ((unused))) 384af526226Smrg { 385af526226Smrg abort (); 386af526226Smrg } 387