1/* C6X ABI compliant unwinding routines 2 Copyright (C) 2011-2015 Free Software Foundation, Inc. 3 4 This file is free software; you can redistribute it and/or modify it 5 under the terms of the GNU General Public License as published by the 6 Free Software Foundation; either version 3, or (at your option) any 7 later version. 8 9 This file is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 General Public License 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#include "unwind.h" 24 25/* We add a prototype for abort here to avoid creating a dependency on 26 target headers. */ 27extern void abort (void); 28 29typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */ 30 31/* Misc constants. */ 32#define R_A0 0 33#define R_A1 1 34#define R_A2 2 35#define R_A3 3 36#define R_A4 4 37#define R_A5 5 38#define R_A6 6 39#define R_A7 7 40#define R_A8 8 41#define R_A9 9 42#define R_A10 10 43#define R_A11 11 44#define R_A12 12 45#define R_A13 13 46#define R_A14 14 47#define R_A15 15 48#define R_B0 16 49#define R_B1 17 50#define R_B2 18 51#define R_B3 19 52#define R_B4 20 53#define R_B5 21 54#define R_B6 22 55#define R_B7 23 56#define R_B8 24 57#define R_B9 25 58#define R_B10 26 59#define R_B11 27 60#define R_B12 28 61#define R_B13 29 62#define R_B14 30 63#define R_B15 31 64 65#define R_SP R_B15 66#define R_PC 33 67 68#define uint32_highbit (((_uw) 1) << 31) 69 70void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp); 71 72/* Unwind descriptors. */ 73 74typedef struct 75{ 76 _uw16 length; 77 _uw16 offset; 78} EHT16; 79 80typedef struct 81{ 82 _uw length; 83 _uw offset; 84} EHT32; 85 86/* Calculate the address encoded by a 31-bit self-relative offset at address 87 P. Copy of routine in unwind-arm.c. */ 88 89static inline _uw 90selfrel_offset31 (const _uw *p) 91{ 92 _uw offset; 93 94 offset = *p; 95 /* Sign extend to 32 bits. */ 96 if (offset & (1 << 30)) 97 offset |= 1u << 31; 98 99 return offset + (_uw) p; 100} 101 102 103/* Personality routine helper functions. */ 104 105#define CODE_FINISH (0xe7) 106 107/* Return the next byte of unwinding information, or CODE_FINISH if there is 108 no data remaining. */ 109static inline _uw8 110next_unwind_byte (__gnu_unwind_state * uws) 111{ 112 _uw8 b; 113 114 if (uws->bytes_left == 0) 115 { 116 /* Load another word */ 117 if (uws->words_left == 0) 118 return CODE_FINISH; /* Nothing left. */ 119 uws->words_left--; 120 uws->data = *(uws->next++); 121 uws->bytes_left = 3; 122 } 123 else 124 uws->bytes_left--; 125 126 /* Extract the most significant byte. */ 127 b = (uws->data >> 24) & 0xff; 128 uws->data <<= 8; 129 return b; 130} 131 132static void 133unwind_restore_pair (_Unwind_Context * context, int reg, _uw *ptr) 134{ 135#ifdef _BIG_ENDIAN 136 _Unwind_VRS_Set (context, _UVRSC_CORE, reg, _UVRSD_UINT32, ptr + 1); 137 _Unwind_VRS_Set (context, _UVRSC_CORE, reg + 1, _UVRSD_UINT32, ptr); 138#else 139 _Unwind_VRS_Set (context, _UVRSC_CORE, reg, _UVRSD_UINT32, ptr); 140 _Unwind_VRS_Set (context, _UVRSC_CORE, reg + 1, _UVRSD_UINT32, ptr + 1); 141#endif 142} 143 144static const int 145unwind_frame_regs[13] = 146{ 147 R_A15, R_B15, R_B14, R_B13, R_B12, R_B11, R_B10, R_B3, 148 R_A14, R_A13, R_A12, R_A11, R_A10 149}; 150 151static void 152pop_compact_frame (_Unwind_Context * context, _uw mask, _uw *ptr, int inc_sp) 153{ 154 int size; 155 _uw test; 156 int i, regno, nregs; 157 158 size = 0; 159 nregs = __builtin_popcount (mask); 160 for (i = 0; i < 13; i++) 161 { 162 test = 1 << i; 163 if ((mask & test) == 0) 164 continue; 165 166 regno = unwind_frame_regs[12 - i]; 167 168 if (i < 12 && nregs > 2 169 && (mask & (test << 1)) != 0 170 && unwind_frame_regs[11 - i] == regno + 1 171 && (regno & 1) == 0) 172 { 173 i++; 174 nregs--; 175 } 176 177 nregs--; 178 size += 2; 179 } 180 181 if (!inc_sp) 182 ptr -= size; 183 184 /* SP points just past the end of the stack. */ 185 ptr += 2; 186 nregs = __builtin_popcount (mask); 187 for (i = 0; i < 13; i++) 188 { 189 test = 1 << i; 190 if ((mask & test) == 0) 191 continue; 192 193 regno = unwind_frame_regs[12 - i]; 194 195 if (i < 12 && nregs > 2 196 && (mask & (test << 1)) != 0 197 && unwind_frame_regs[11 - i] == regno + 1 198 && (regno & 1) == 0) 199 { 200 /* Register pair. */ 201 unwind_restore_pair (context, regno, ptr); 202 i++; 203 nregs--; 204 } 205 else 206 { 207 /* Single register with padding. */ 208 _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, ptr); 209 } 210 211 nregs--; 212 ptr += 2; 213 } 214 215 ptr -= 2; 216 if ((mask & (1 << 11)) == 0) 217 _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr); 218} 219 220static void 221pop_frame (_Unwind_Context * context, _uw mask, _uw *ptr, int inc_sp) 222{ 223 int i; 224 int regno; 225 int nregs; 226 227 nregs = __builtin_popcount (mask); 228 229 if (!inc_sp) 230 ptr -= nregs; 231 else if (nregs & 1) 232 ptr++; 233 234 ptr++; 235 for (i = 0; i < 13; i++) 236 { 237 if ((mask & (1 << i)) == 0) 238 continue; 239 regno = unwind_frame_regs[12 - i]; 240 if (i < 12 && unwind_frame_regs[11 - i] == (regno + 1) 241 && (mask & (1 << (i + 1))) != 0 242 && (((_uw)ptr) & 4) == 0 243 && (regno & 1) == 0) 244 { 245 unwind_restore_pair (context, regno, ptr); 246 i++; 247 ptr += 2; 248 } 249 else 250 { 251 _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, 252 ptr); 253 ptr++; 254 } 255 } 256 257 ptr--; 258 if ((mask & (1 << 11)) == 0) 259 _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr); 260} 261 262/* Unwind a 24-bit encoded frame. */ 263_Unwind_Reason_Code 264__gnu_unwind_24bit (_Unwind_Context * context, _uw data, int compact) 265{ 266 _uw offset; 267 _uw mask; 268 _uw *ptr; 269 _uw tmp; 270 int ret_reg = unwind_frame_regs[data & 0xf]; 271 272 if (ret_reg != R_B3) 273 { 274 _Unwind_VRS_Get (context, _UVRSC_CORE, unwind_frame_regs[data & 0xf], 275 _UVRSD_UINT32, &tmp); 276 _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, &tmp); 277 } 278 279 mask = (data >> 4) & 0x1fff; 280 281 offset = (data >> 17) & 0x7f; 282 if (offset == 0x7f) 283 _Unwind_VRS_Get (context, _UVRSC_CORE, R_A15, _UVRSD_UINT32, &ptr); 284 else 285 { 286 _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr); 287 ptr += offset * 2; 288 } 289 290 291 if (compact) 292 pop_compact_frame (context, mask, ptr, offset != 0x7f); 293 else 294 pop_frame (context, mask, ptr, offset != 0x7f); 295 296 _Unwind_VRS_Get (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, &tmp); 297 _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, &tmp); 298 299 return _URC_OK; 300} 301 302static void 303unwind_pop_rts (_Unwind_Context * context) 304{ 305 _uw *ptr; 306 307 _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr); 308#ifdef _BIG_ENDIAN 309 _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, ptr + 1); 310#else 311 _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, ptr + 2); 312#endif 313 ptr += 3; 314 unwind_restore_pair (context, R_A10, ptr); 315 ptr += 2; 316 unwind_restore_pair (context, R_B10, ptr); 317 ptr += 2; 318 unwind_restore_pair (context, R_A12, ptr); 319 ptr += 2; 320 unwind_restore_pair (context, R_B12, ptr); 321 ptr += 2; 322 unwind_restore_pair (context, R_A14, ptr); 323 ptr += 2; 324 _Unwind_VRS_Set (context, _UVRSC_CORE, R_B14, _UVRSD_UINT32, ptr); 325 _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr); 326 /* PC will be set by implicit RETURN opcode. */ 327} 328 329/* Execute the unwinding instructions described by UWS. */ 330_Unwind_Reason_Code 331__gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws) 332{ 333 _uw op; 334 int inc_sp; 335 _uw reg; 336 _uw *ptr; 337 338 inc_sp = 1; 339 for (;;) 340 { 341 op = next_unwind_byte (uws); 342 if (op == CODE_FINISH) 343 { 344 /* Drop out of the loop. */ 345 break; 346 } 347 if ((op & 0xc0) == 0) 348 { 349 /* sp += (imm6 << 3) + 8. */ 350 _uw offset; 351 352 offset = ((op & 0x3f) << 3) + 8; 353 _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®); 354 reg += offset; 355 _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®); 356 continue; 357 } 358 359 if (op == 0xd2) 360 { 361 /* vsp = vsp + 0x204 + (uleb128 << 2). */ 362 int shift; 363 364 _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®); 365 op = next_unwind_byte (uws); 366 shift = 3; 367 while (op & 0x80) 368 { 369 reg += ((op & 0x7f) << shift); 370 shift += 7; 371 op = next_unwind_byte (uws); 372 } 373 reg += ((op & 0x7f) << shift) + 0x408; 374 _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®); 375 continue; 376 } 377 378 if ((op & 0xe0) == 0x80) 379 { 380 /* POP bitmask */ 381 _uw mask = ((op & 0x1f) << 8) | next_unwind_byte (uws); 382 383 if (mask == 0) 384 { 385 /* CANTUNWIND */ 386 return _URC_FAILURE; 387 } 388 389 _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr); 390 pop_frame (context, mask, ptr, inc_sp); 391 continue; 392 } 393 394 if ((op & 0xe0) == 0xa0) 395 { 396 /* POP bitmask (compact) */ 397 _uw mask = ((op & 0x1f) << 8) | next_unwind_byte (uws); 398 399 _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr); 400 pop_compact_frame (context, mask, ptr, inc_sp); 401 continue; 402 } 403 404 if ((op & 0xf0) == 0xc0) 405 { 406 /* POP registers */ 407 int nregs = op & 0xf; 408 409 _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &ptr); 410 while (nregs > 0) 411 { 412 op = next_unwind_byte (uws); 413 if ((op >> 4) != 0xf) 414 { 415 reg = unwind_frame_regs[op >> 4]; 416 _Unwind_VRS_Set (context, _UVRSC_CORE, reg, _UVRSD_UINT32, 417 ptr); 418 nregs--; 419 } 420 ptr--; 421 if ((op & 0xf) != 0xf) 422 { 423 reg = unwind_frame_regs[op & 0xf]; 424 _Unwind_VRS_Set (context, _UVRSC_CORE, reg, _UVRSD_UINT32, 425 ptr); 426 nregs--; 427 } 428 ptr--; 429 } 430 431 continue; 432 } 433 434 if (op == 0xd0) 435 { 436 /* MV FP, SP */ 437 inc_sp = 0; 438 _Unwind_VRS_Get (context, _UVRSC_CORE, R_A15, _UVRSD_UINT32, ®); 439 _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, ®); 440 continue; 441 } 442 443 if (op == 0xd1) 444 { 445 /* __cx6abi_pop_rts */ 446 unwind_pop_rts (context); 447 break; 448 } 449 450 if ((op & 0xf0) == 0xe0) 451 { 452 /* B3 = reg. RETURN case alreadh handled above. */ 453 int regno = unwind_frame_regs[op & 0xf]; 454 455 _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, ®); 456 _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, ®); 457 continue; 458 } 459 460 /* Reserved. */ 461 return _URC_FAILURE; 462 } 463 464 /* Implicit RETURN. */ 465 _Unwind_VRS_Get (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, ®); 466 _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, ®); 467 return _URC_OK; 468} 469 470 471/* Execute the unwinding instructions associated with a frame. UCBP and 472 CONTEXT are the current exception object and virtual CPU state 473 respectively. */ 474 475_Unwind_Reason_Code 476__gnu_unwind_frame (_Unwind_Control_Block * ucbp, _Unwind_Context * context) 477{ 478 _uw *ptr; 479 __gnu_unwind_state uws; 480 481 ptr = (_uw *) ucbp->pr_cache.ehtp; 482 /* Skip over the personality routine address. */ 483 ptr++; 484 /* Setup the unwinder state. */ 485 uws.data = (*ptr) << 8; 486 uws.next = ptr + 1; 487 uws.bytes_left = 3; 488 uws.words_left = ((*ptr) >> 24) & 0xff; 489 490 return __gnu_unwind_execute (context, &uws); 491} 492 493/* Data segment base pointer corresponding to the function catching 494 the exception. */ 495 496_Unwind_Ptr 497_Unwind_GetDataRelBase (_Unwind_Context *context) 498{ 499 return _Unwind_GetGR (context, R_B14); 500} 501 502/* This should never be used. */ 503 504_Unwind_Ptr 505_Unwind_GetTextRelBase (_Unwind_Context *context __attribute__ ((unused))) 506{ 507 abort (); 508} 509 510/* Only used by gcc personality routines, so can rely on a value they hid 511 there earlier. */ 512_Unwind_Ptr 513_Unwind_GetRegionStart (_Unwind_Context *context) 514{ 515 _Unwind_Control_Block *ucbp; 516 517 ucbp = (_Unwind_Control_Block *) _Unwind_GetGR (context, UNWIND_POINTER_REG); 518 return (_Unwind_Ptr) ucbp->pr_cache.fnstart; 519} 520 521void * 522_Unwind_GetLanguageSpecificData (_Unwind_Context *context) 523{ 524 _Unwind_Control_Block *ucbp; 525 _uw *ptr; 526 527 ucbp = (_Unwind_Control_Block *) _Unwind_GetGR (context, UNWIND_POINTER_REG); 528 ptr = (_uw *) ucbp->pr_cache.ehtp; 529 /* Skip the personality routine address. */ 530 ptr++; 531 /* Skip the unwind opcodes. */ 532 ptr += (((*ptr) >> 24) & 0xff) + 1; 533 534 return ptr; 535} 536