1 1.1 mrg /* DWARF2 exception handling and frame unwinding for Xtensa. 2 1.11 mrg Copyright (C) 1997-2022 Free Software Foundation, Inc. 3 1.1 mrg 4 1.1 mrg This file is part of GCC. 5 1.1 mrg 6 1.1 mrg GCC is free software; you can redistribute it and/or modify it 7 1.1 mrg under the terms of the GNU General Public License as published by 8 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 9 1.1 mrg any later version. 10 1.1 mrg 11 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT 12 1.1 mrg ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 1.1 mrg License for more details. 15 1.1 mrg 16 1.1 mrg Under Section 7 of GPL version 3, you are granted additional 17 1.1 mrg permissions described in the GCC Runtime Library Exception, version 18 1.1 mrg 3.1, as published by the Free Software Foundation. 19 1.1 mrg 20 1.1 mrg You should have received a copy of the GNU General Public License and 21 1.1 mrg a copy of the GCC Runtime Library Exception along with this program; 22 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 1.1 mrg <http://www.gnu.org/licenses/>. */ 24 1.1 mrg 25 1.1 mrg #include "tconfig.h" 26 1.1 mrg #include "tsystem.h" 27 1.1 mrg #include "coretypes.h" 28 1.1 mrg #include "tm.h" 29 1.1 mrg #include "libgcc_tm.h" 30 1.1 mrg #include "dwarf2.h" 31 1.1 mrg #include "unwind.h" 32 1.1 mrg #ifdef __USING_SJLJ_EXCEPTIONS__ 33 1.1 mrg # define NO_SIZE_OF_ENCODED_VALUE 34 1.1 mrg #endif 35 1.1 mrg #include "unwind-pe.h" 36 1.1 mrg #include "unwind-dw2-fde.h" 37 1.1 mrg #include "unwind-dw2-xtensa.h" 38 1.1 mrg 39 1.1 mrg #ifndef __USING_SJLJ_EXCEPTIONS__ 40 1.1 mrg 41 1.1 mrg /* The standard CIE and FDE structures work fine for Xtensa but the 42 1.1 mrg variable-size register window save areas are not a good fit for the rest 43 1.1 mrg of the standard DWARF unwinding mechanism. Nor is that mechanism 44 1.1 mrg necessary, since the register save areas are always in fixed locations 45 1.1 mrg in each stack frame. This file is a stripped down and customized version 46 1.1 mrg of the standard DWARF unwinding code. It needs to be customized to have 47 1.1 mrg builtin logic for finding the save areas and also to track the stack 48 1.1 mrg pointer value (besides the CFA) while unwinding since the primary save 49 1.1 mrg area is located below the stack pointer. It is stripped down to reduce 50 1.1 mrg code size and ease the maintenance burden of tracking changes in the 51 1.1 mrg standard version of the code. */ 52 1.1 mrg 53 1.1 mrg #ifndef DWARF_REG_TO_UNWIND_COLUMN 54 1.1 mrg #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO) 55 1.1 mrg #endif 56 1.1 mrg 57 1.1 mrg #define XTENSA_RA_FIELD_MASK 0x3FFFFFFF 58 1.1 mrg 59 1.1 mrg /* This is the register and unwind state for a particular frame. This 60 1.1 mrg provides the information necessary to unwind up past a frame and return 61 1.1 mrg to its caller. */ 62 1.1 mrg struct _Unwind_Context 63 1.1 mrg { 64 1.1 mrg /* Track register window save areas of 4 registers each, instead of 65 1.1 mrg keeping separate addresses for the individual registers. */ 66 1.1 mrg _Unwind_Word *reg[4]; 67 1.1 mrg 68 1.1 mrg void *cfa; 69 1.1 mrg void *sp; 70 1.1 mrg void *ra; 71 1.1 mrg 72 1.1 mrg /* Cache the 2 high bits to replace the window size in return addresses. */ 73 1.1 mrg _Unwind_Word ra_high_bits; 74 1.1 mrg 75 1.1 mrg void *lsda; 76 1.1 mrg struct dwarf_eh_bases bases; 77 1.1 mrg /* Signal frame context. */ 78 1.1 mrg #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1) 79 1.1 mrg _Unwind_Word flags; 80 1.1 mrg /* 0 for now, can be increased when further fields are added to 81 1.1 mrg struct _Unwind_Context. */ 82 1.1 mrg _Unwind_Word version; 83 1.1 mrg }; 84 1.1 mrg 85 1.1 mrg 86 1.1 mrg /* Read unaligned data from the instruction buffer. */ 88 1.1 mrg 89 1.1 mrg union unaligned 90 1.1 mrg { 91 1.1 mrg void *p; 92 1.1 mrg } __attribute__ ((packed)); 93 1.1 mrg 94 1.1 mrg static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *); 95 1.1 mrg static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *, 96 1.1 mrg _Unwind_FrameState *); 97 1.1 mrg 98 1.1 mrg static inline void * 99 1.1 mrg read_pointer (const void *p) { const union unaligned *up = p; return up->p; } 100 1.1 mrg 101 1.1 mrg static inline _Unwind_Word 103 1.1 mrg _Unwind_IsSignalFrame (struct _Unwind_Context *context) 104 1.1 mrg { 105 1.1 mrg return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0; 106 1.1 mrg } 107 1.1 mrg 108 1.1 mrg static inline void 109 1.1 mrg _Unwind_SetSignalFrame (struct _Unwind_Context *context, int val) 110 1.1 mrg { 111 1.1 mrg if (val) 112 1.1 mrg context->flags |= SIGNAL_FRAME_BIT; 113 1.1 mrg else 114 1.1 mrg context->flags &= ~SIGNAL_FRAME_BIT; 115 1.1 mrg } 116 1.1 mrg 117 1.1 mrg /* Get the value of register INDEX as saved in CONTEXT. */ 119 1.1 mrg 120 1.1 mrg inline _Unwind_Word 121 1.1 mrg _Unwind_GetGR (struct _Unwind_Context *context, int index) 122 1.1 mrg { 123 1.1 mrg _Unwind_Word *ptr; 124 1.1 mrg 125 1.1 mrg index = DWARF_REG_TO_UNWIND_COLUMN (index); 126 1.1 mrg ptr = context->reg[index >> 2] + (index & 3); 127 1.1 mrg 128 1.1 mrg return *ptr; 129 1.1 mrg } 130 1.1 mrg 131 1.1 mrg /* Get the value of the CFA as saved in CONTEXT. */ 132 1.1 mrg 133 1.4 mrg _Unwind_Word 134 1.1 mrg _Unwind_GetCFA (struct _Unwind_Context *context) 135 1.1 mrg { 136 1.1 mrg return (_Unwind_Ptr) context->sp; 137 1.1 mrg } 138 1.1 mrg 139 1.1 mrg /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */ 140 1.1 mrg 141 1.1 mrg inline void 142 1.1 mrg _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val) 143 1.1 mrg { 144 1.1 mrg _Unwind_Word *ptr; 145 1.1 mrg 146 1.1 mrg index = DWARF_REG_TO_UNWIND_COLUMN (index); 147 1.1 mrg ptr = context->reg[index >> 2] + (index & 3); 148 1.1 mrg 149 1.1 mrg *ptr = val; 150 1.1 mrg } 151 1.1 mrg 152 1.1 mrg /* Retrieve the return address for CONTEXT. */ 153 1.1 mrg 154 1.1 mrg inline _Unwind_Ptr 155 1.1 mrg _Unwind_GetIP (struct _Unwind_Context *context) 156 1.1 mrg { 157 1.1 mrg return (_Unwind_Ptr) context->ra; 158 1.1 mrg } 159 1.1 mrg 160 1.1 mrg /* Retrieve the return address and flag whether that IP is before 161 1.1 mrg or after first not yet fully executed instruction. */ 162 1.1 mrg 163 1.1 mrg inline _Unwind_Ptr 164 1.1 mrg _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn) 165 1.1 mrg { 166 1.1 mrg *ip_before_insn = _Unwind_IsSignalFrame (context); 167 1.1 mrg return (_Unwind_Ptr) context->ra; 168 1.1 mrg } 169 1.1 mrg 170 1.1 mrg /* Overwrite the return address for CONTEXT with VAL. */ 171 1.1 mrg 172 1.1 mrg inline void 173 1.1 mrg _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val) 174 1.1 mrg { 175 1.1 mrg context->ra = (void *) val; 176 1.1 mrg } 177 1.1 mrg 178 1.1 mrg _Unwind_Ptr 179 1.1 mrg _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context) 180 1.1 mrg { 181 1.1 mrg return context->lsda; 182 1.1 mrg } 183 1.1 mrg 184 1.1 mrg _Unwind_Ptr 185 1.1 mrg _Unwind_GetRegionStart (struct _Unwind_Context *context) 186 1.1 mrg { 187 1.1 mrg return (_Unwind_Ptr) context->bases.func; 188 1.1 mrg } 189 1.1 mrg 190 1.1 mrg void * 191 1.1 mrg _Unwind_FindEnclosingFunction (void *pc) 192 1.1 mrg { 193 1.1 mrg struct dwarf_eh_bases bases; 194 1.1 mrg const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases); 195 1.1 mrg if (fde) 196 1.1 mrg return bases.func; 197 1.1 mrg else 198 1.1 mrg return NULL; 199 1.1 mrg } 200 1.1 mrg 201 1.1 mrg _Unwind_Ptr 202 1.1 mrg _Unwind_GetDataRelBase (struct _Unwind_Context *context) 203 1.1 mrg { 204 1.1 mrg return (_Unwind_Ptr) context->bases.dbase; 205 1.1 mrg } 206 1.1 mrg 207 1.1 mrg _Unwind_Ptr 208 1.1 mrg _Unwind_GetTextRelBase (struct _Unwind_Context *context) 209 1.1 mrg { 210 1.1 mrg return (_Unwind_Ptr) context->bases.tbase; 211 1.1 mrg } 212 1.1 mrg 213 1.1 mrg #include "md-unwind-support.h" 214 1.1 mrg 215 1.1 mrg /* Extract any interesting information from the CIE for the translation 217 1.1 mrg unit F belongs to. Return a pointer to the byte after the augmentation, 218 1.1 mrg or NULL if we encountered an undecipherable augmentation. */ 219 1.1 mrg 220 1.1 mrg static const unsigned char * 221 1.1 mrg extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context, 222 1.1 mrg _Unwind_FrameState *fs) 223 1.1 mrg { 224 1.1 mrg const unsigned char *aug = cie->augmentation; 225 1.1 mrg const unsigned char *p = aug + strlen ((const char *)aug) + 1; 226 1.1 mrg const unsigned char *ret = NULL; 227 1.1 mrg _uleb128_t utmp; 228 1.1 mrg _sleb128_t stmp; 229 1.1 mrg 230 1.1 mrg /* g++ v2 "eh" has pointer immediately following augmentation string, 231 1.1 mrg so it must be handled first. */ 232 1.1 mrg if (aug[0] == 'e' && aug[1] == 'h') 233 1.1 mrg { 234 1.1 mrg fs->eh_ptr = read_pointer (p); 235 1.1 mrg p += sizeof (void *); 236 1.1 mrg aug += 2; 237 1.1 mrg } 238 1.1 mrg 239 1.1 mrg /* Immediately following the augmentation are the code and 240 1.1 mrg data alignment and return address column. */ 241 1.1 mrg p = read_uleb128 (p, &utmp); 242 1.1 mrg p = read_sleb128 (p, &stmp); 243 1.1 mrg if (cie->version == 1) 244 1.1 mrg fs->retaddr_column = *p++; 245 1.1 mrg else 246 1.1 mrg { 247 1.1 mrg p = read_uleb128 (p, &utmp); 248 1.1 mrg fs->retaddr_column = (_Unwind_Word)utmp; 249 1.1 mrg } 250 1.1 mrg fs->lsda_encoding = DW_EH_PE_omit; 251 1.1 mrg 252 1.1 mrg /* If the augmentation starts with 'z', then a uleb128 immediately 253 1.1 mrg follows containing the length of the augmentation field following 254 1.1 mrg the size. */ 255 1.1 mrg if (*aug == 'z') 256 1.1 mrg { 257 1.1 mrg p = read_uleb128 (p, &utmp); 258 1.1 mrg ret = p + utmp; 259 1.1 mrg 260 1.1 mrg fs->saw_z = 1; 261 1.1 mrg ++aug; 262 1.1 mrg } 263 1.1 mrg 264 1.1 mrg /* Iterate over recognized augmentation subsequences. */ 265 1.1 mrg while (*aug != '\0') 266 1.1 mrg { 267 1.1 mrg /* "L" indicates a byte showing how the LSDA pointer is encoded. */ 268 1.1 mrg if (aug[0] == 'L') 269 1.1 mrg { 270 1.1 mrg fs->lsda_encoding = *p++; 271 1.1 mrg aug += 1; 272 1.1 mrg } 273 1.1 mrg 274 1.1 mrg /* "R" indicates a byte indicating how FDE addresses are encoded. */ 275 1.1 mrg else if (aug[0] == 'R') 276 1.1 mrg { 277 1.1 mrg fs->fde_encoding = *p++; 278 1.1 mrg aug += 1; 279 1.1 mrg } 280 1.1 mrg 281 1.1 mrg /* "P" indicates a personality routine in the CIE augmentation. */ 282 1.1 mrg else if (aug[0] == 'P') 283 1.1 mrg { 284 1.1 mrg _Unwind_Ptr personality; 285 1.1 mrg 286 1.1 mrg p = read_encoded_value (context, *p, p + 1, &personality); 287 1.1 mrg fs->personality = (_Unwind_Personality_Fn) personality; 288 1.1 mrg aug += 1; 289 1.1 mrg } 290 1.1 mrg 291 1.1 mrg /* "S" indicates a signal frame. */ 292 1.1 mrg else if (aug[0] == 'S') 293 1.1 mrg { 294 1.1 mrg fs->signal_frame = 1; 295 1.1 mrg aug += 1; 296 1.1 mrg } 297 1.1 mrg 298 1.1 mrg /* Otherwise we have an unknown augmentation string. 299 1.1 mrg Bail unless we saw a 'z' prefix. */ 300 1.1 mrg else 301 1.1 mrg return ret; 302 1.1 mrg } 303 1.1 mrg 304 1.1 mrg return ret ? ret : p; 305 1.1 mrg } 306 1.1 mrg 307 1.1 mrg /* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for 309 1.1 mrg its caller and decode it into FS. This function also sets the 310 1.1 mrg lsda member of CONTEXT, as it is really information 311 1.1 mrg about the caller's frame. */ 312 1.1 mrg 313 1.1 mrg static _Unwind_Reason_Code 314 1.1 mrg uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) 315 1.1 mrg { 316 1.1 mrg const struct dwarf_fde *fde; 317 1.1 mrg const struct dwarf_cie *cie; 318 1.1 mrg const unsigned char *aug; 319 1.1 mrg int window_size; 320 1.1 mrg _Unwind_Word *ra_ptr; 321 1.1 mrg 322 1.1 mrg memset (fs, 0, sizeof (*fs)); 323 1.1 mrg context->lsda = 0; 324 1.1 mrg 325 1.1 mrg fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1, 326 1.1 mrg &context->bases); 327 1.1 mrg if (fde == NULL) 328 1.1 mrg { 329 1.1 mrg #ifdef MD_FALLBACK_FRAME_STATE_FOR 330 1.1 mrg _Unwind_Reason_Code reason; 331 1.1 mrg /* Couldn't find frame unwind info for this function. Try a 332 1.1 mrg target-specific fallback mechanism. This will necessarily 333 1.1 mrg not provide a personality routine or LSDA. */ 334 1.1 mrg reason = MD_FALLBACK_FRAME_STATE_FOR (context, fs); 335 1.1 mrg if (reason != _URC_END_OF_STACK) 336 1.1 mrg return reason; 337 1.1 mrg #endif 338 1.1 mrg /* The frame was not recognized and handled by the fallback function, 339 1.1 mrg but it is not really the end of the stack. Fall through here and 340 1.1 mrg unwind it anyway. */ 341 1.1 mrg } 342 1.1 mrg else 343 1.1 mrg { 344 1.1 mrg cie = get_cie (fde); 345 1.1 mrg if (extract_cie_info (cie, context, fs) == NULL) 346 1.1 mrg /* CIE contained unknown augmentation. */ 347 1.1 mrg return _URC_FATAL_PHASE1_ERROR; 348 1.1 mrg 349 1.1 mrg /* Locate augmentation for the fde. */ 350 1.1 mrg aug = (const unsigned char *) fde + sizeof (*fde); 351 1.1 mrg aug += 2 * size_of_encoded_value (fs->fde_encoding); 352 1.1 mrg if (fs->saw_z) 353 1.1 mrg { 354 1.1 mrg _uleb128_t i; 355 1.1 mrg aug = read_uleb128 (aug, &i); 356 1.1 mrg } 357 1.1 mrg if (fs->lsda_encoding != DW_EH_PE_omit) 358 1.1 mrg { 359 1.1 mrg _Unwind_Ptr lsda; 360 1.1 mrg 361 1.1 mrg aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda); 362 1.1 mrg context->lsda = (void *) lsda; 363 1.1 mrg } 364 1.1 mrg } 365 1.1 mrg 366 1.1 mrg /* Check for the end of the stack. This needs to be checked after 367 1.1 mrg the MD_FALLBACK_FRAME_STATE_FOR check for signal frames because 368 1.1 mrg the contents of context->reg[0] are undefined at a signal frame, 369 1.1 mrg and register a0 may appear to be zero. (The return address in 370 1.1 mrg context->ra comes from register a4 or a8). */ 371 1.1 mrg ra_ptr = context->reg[0]; 372 1.1 mrg if (ra_ptr && *ra_ptr == 0) 373 1.1 mrg return _URC_END_OF_STACK; 374 1.1 mrg 375 1.1 mrg /* Find the window size from the high bits of the return address. */ 376 1.1 mrg if (ra_ptr) 377 1.1 mrg window_size = (*ra_ptr >> 30) * 4; 378 1.1 mrg else 379 1.1 mrg window_size = 8; 380 1.1 mrg 381 1.1 mrg fs->retaddr_column = window_size; 382 1.1 mrg 383 1.1 mrg return _URC_NO_REASON; 384 1.1 mrg } 385 1.1 mrg 386 1.1 mrg static void 388 1.1 mrg uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs) 389 1.1 mrg { 390 1.1 mrg struct _Unwind_Context orig_context = *context; 391 1.1 mrg _Unwind_Word *sp, *cfa, *next_cfa; 392 1.1 mrg int i; 393 1.1 mrg 394 1.1 mrg if (fs->signal_regs) 395 1.1 mrg { 396 1.1 mrg cfa = (_Unwind_Word *) fs->signal_regs[1]; 397 1.1 mrg next_cfa = (_Unwind_Word *) cfa[-3]; 398 1.1 mrg 399 1.1 mrg for (i = 0; i < 4; i++) 400 1.1 mrg context->reg[i] = fs->signal_regs + (i << 2); 401 1.1 mrg } 402 1.1 mrg else 403 1.1 mrg { 404 1.1 mrg int window_size = fs->retaddr_column >> 2; 405 1.1 mrg 406 1.1 mrg sp = (_Unwind_Word *) orig_context.sp; 407 1.1 mrg cfa = (_Unwind_Word *) orig_context.cfa; 408 1.1 mrg next_cfa = (_Unwind_Word *) cfa[-3]; 409 1.1 mrg 410 1.1 mrg /* Registers a0-a3 are in the save area below sp. */ 411 1.1 mrg context->reg[0] = sp - 4; 412 1.1 mrg 413 1.1 mrg /* Find the extra save area below next_cfa. */ 414 1.1 mrg for (i = 1; i < window_size; i++) 415 1.1 mrg context->reg[i] = next_cfa - 4 * (1 + window_size - i); 416 1.1 mrg 417 1.1 mrg /* Remaining registers rotate from previous save areas. */ 418 1.1 mrg for (i = window_size; i < 4; i++) 419 1.1 mrg context->reg[i] = orig_context.reg[i - window_size]; 420 1.1 mrg } 421 1.1 mrg 422 1.1 mrg context->sp = cfa; 423 1.1 mrg context->cfa = next_cfa; 424 1.1 mrg 425 1.1 mrg _Unwind_SetSignalFrame (context, fs->signal_frame); 426 1.1 mrg } 427 1.1 mrg 428 1.1 mrg /* CONTEXT describes the unwind state for a frame, and FS describes the FDE 429 1.1 mrg of its caller. Update CONTEXT to refer to the caller as well. Note 430 1.1 mrg that the lsda member is not updated here, but later in 431 1.1 mrg uw_frame_state_for. */ 432 1.1 mrg 433 1.1 mrg static void 434 1.1 mrg uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) 435 1.1 mrg { 436 1.1 mrg uw_update_context_1 (context, fs); 437 1.1 mrg 438 1.1 mrg /* Compute the return address now, since the return address column 439 1.1 mrg can change from frame to frame. */ 440 1.1 mrg if (fs->signal_ra != 0) 441 1.1 mrg context->ra = (void *) fs->signal_ra; 442 1.1 mrg else 443 1.1 mrg context->ra = (void *) ((_Unwind_GetGR (context, fs->retaddr_column) 444 1.1 mrg & XTENSA_RA_FIELD_MASK) | context->ra_high_bits); 445 1.1 mrg } 446 1.1 mrg 447 1.1 mrg static void 448 1.1 mrg uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) 449 1.1 mrg { 450 1.1 mrg uw_update_context (context, fs); 451 1.1 mrg } 452 1.1 mrg 453 1.1 mrg /* Fill in CONTEXT for top-of-stack. The only valid registers at this 455 1.1 mrg level will be the return address and the CFA. */ 456 1.1 mrg 457 1.1 mrg #define uw_init_context(CONTEXT) \ 458 1.1 mrg do \ 459 1.1 mrg { \ 460 1.1 mrg __builtin_unwind_init (); \ 461 1.1 mrg uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \ 462 1.1 mrg __builtin_return_address (0)); \ 463 1.1 mrg } \ 464 1.1 mrg while (0) 465 1.1 mrg 466 1.1 mrg static void __attribute__((noinline)) 467 1.1 mrg uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa, 468 1.1 mrg void *outer_ra) 469 1.1 mrg { 470 1.1 mrg void *ra = __builtin_return_address (0); 471 1.1 mrg void *cfa = __builtin_dwarf_cfa (); 472 1.1 mrg _Unwind_FrameState fs; 473 1.1 mrg 474 1.1 mrg memset (context, 0, sizeof (struct _Unwind_Context)); 475 1.1 mrg context->ra = ra; 476 1.1 mrg 477 1.1 mrg memset (&fs, 0, sizeof (fs)); 478 1.1 mrg fs.retaddr_column = 8; 479 1.1 mrg context->sp = cfa; 480 1.1 mrg context->cfa = outer_cfa; 481 1.1 mrg context->ra_high_bits = 482 1.1 mrg ((_Unwind_Word) uw_init_context_1) & ~XTENSA_RA_FIELD_MASK; 483 1.1 mrg uw_update_context_1 (context, &fs); 484 1.11 mrg 485 1.11 mrg context->ra = outer_ra; 486 1.11 mrg } 487 1.11 mrg 488 1.11 mrg 489 1.1 mrg /* Install TARGET into CURRENT so that we can return to it. This is a 490 1.11 mrg macro because __builtin_eh_return must be invoked in the context of 491 1.1 mrg our caller, and also because spilling registers of the caller before 492 1.1 mrg the context installation may result in reload of wrong register values 493 1.1 mrg after the context installation due to the change of the stack pointer 494 1.11 mrg in the base save area. This spilling may be caused by an interrupt 495 1.11 mrg handler on baremetal host. */ 496 1.11 mrg 497 1.11 mrg #define uw_install_context(CURRENT, TARGET, FRAMES) \ 498 1.11 mrg do \ 499 1.11 mrg { \ 500 1.11 mrg void *handler = __builtin_frob_return_addr ((TARGET)->ra); \ 501 1.11 mrg long i; \ 502 1.11 mrg \ 503 1.11 mrg /* The eh_return insn assumes a window size of 8, so don't bother \ 504 1.11 mrg copying the save areas for registers a8-a15 since they won't be \ 505 1.11 mrg reloaded. */ \ 506 1.11 mrg for (i = 0; i < 2; ++i) \ 507 1.11 mrg { \ 508 1.11 mrg _Unwind_Word *c = (CURRENT)->reg[i]; \ 509 1.11 mrg _Unwind_Word *t = (TARGET)->reg[i]; \ 510 1.1 mrg int j; \ 511 1.1 mrg \ 512 1.1 mrg if (t && c && t != c) \ 513 1.1 mrg for (j = 0; j < 4; ++j) \ 514 1.1 mrg *c++ = *t++; \ 515 1.1 mrg } \ 516 1.1 mrg __builtin_eh_return (0, handler); \ 517 1.1 mrg } \ 518 1.1 mrg while (0) 519 1.1 mrg 520 1.1 mrg static inline _Unwind_Ptr 521 1.1 mrg uw_identify_context (struct _Unwind_Context *context) 522 1.1 mrg { 523 1.1 mrg return _Unwind_GetCFA (context); 524 1.1 mrg } 525 1.1 mrg 526 1.1 mrg 527 1.1 mrg #include "unwind.inc" 528 1.1 mrg 529 1.1 mrg #if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS) 530 1.1 mrg alias (_Unwind_Backtrace); 531 1.1 mrg alias (_Unwind_DeleteException); 532 1.1 mrg alias (_Unwind_FindEnclosingFunction); 533 1.1 mrg alias (_Unwind_ForcedUnwind); 534 1.1 mrg alias (_Unwind_GetDataRelBase); 535 1.1 mrg alias (_Unwind_GetTextRelBase); 536 1.1 mrg alias (_Unwind_GetCFA); 537 1.1 mrg alias (_Unwind_GetGR); 538 1.1 mrg alias (_Unwind_GetIP); 539 1.1 mrg alias (_Unwind_GetLanguageSpecificData); 540 1.1 mrg alias (_Unwind_GetRegionStart); 541 1.1 mrg alias (_Unwind_RaiseException); 542 alias (_Unwind_Resume); 543 alias (_Unwind_Resume_or_Rethrow); 544 alias (_Unwind_SetGR); 545 alias (_Unwind_SetIP); 546 #endif 547 548 #endif /* !USING_SJLJ_EXCEPTIONS */ 549