190075Sobrien/* DWARF2 exception handling and frame unwind runtime interface routines. 2169689Skan Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 390075Sobrien Free Software Foundation, Inc. 490075Sobrien 590075Sobrien This file is part of GCC. 690075Sobrien 790075Sobrien GCC is free software; you can redistribute it and/or modify it 890075Sobrien under the terms of the GNU General Public License as published by 990075Sobrien the Free Software Foundation; either version 2, or (at your option) 1090075Sobrien any later version. 1190075Sobrien 12132718Skan In addition to the permissions in the GNU General Public License, the 13132718Skan Free Software Foundation gives you unlimited permission to link the 14132718Skan compiled version of this file into combinations with other programs, 15132718Skan and to distribute those combinations without any restriction coming 16132718Skan from the use of this file. (The General Public License restrictions 17132718Skan do apply in other respects; for example, they cover modification of 18132718Skan the file, and distribution when not linked into a combined 19132718Skan executable.) 20132718Skan 2190075Sobrien GCC is distributed in the hope that it will be useful, but WITHOUT 2290075Sobrien ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 2390075Sobrien or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 2490075Sobrien License for more details. 2590075Sobrien 2690075Sobrien You should have received a copy of the GNU General Public License 2790075Sobrien along with GCC; see the file COPYING. If not, write to the Free 28169689Skan Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 29169689Skan 02110-1301, USA. */ 3090075Sobrien 3190075Sobrien#include "tconfig.h" 3290075Sobrien#include "tsystem.h" 33132718Skan#include "coretypes.h" 34132718Skan#include "tm.h" 3590075Sobrien#include "dwarf2.h" 3690075Sobrien#include "unwind.h" 37132718Skan#ifdef __USING_SJLJ_EXCEPTIONS__ 38132718Skan# define NO_SIZE_OF_ENCODED_VALUE 39132718Skan#endif 4090075Sobrien#include "unwind-pe.h" 4190075Sobrien#include "unwind-dw2-fde.h" 4290075Sobrien#include "gthr.h" 43169689Skan#include "unwind-dw2.h" 4490075Sobrien 4590075Sobrien#ifndef __USING_SJLJ_EXCEPTIONS__ 4690075Sobrien 4790075Sobrien#ifndef STACK_GROWS_DOWNWARD 4890075Sobrien#define STACK_GROWS_DOWNWARD 0 4990075Sobrien#else 5090075Sobrien#undef STACK_GROWS_DOWNWARD 5190075Sobrien#define STACK_GROWS_DOWNWARD 1 5290075Sobrien#endif 5390075Sobrien 5490075Sobrien/* Dwarf frame registers used for pre gcc 3.0 compiled glibc. */ 5590075Sobrien#ifndef PRE_GCC3_DWARF_FRAME_REGISTERS 5690075Sobrien#define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS 5790075Sobrien#endif 5890075Sobrien 59132718Skan#ifndef DWARF_REG_TO_UNWIND_COLUMN 60132718Skan#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO) 61132718Skan#endif 62132718Skan 63117395Skan/* This is the register and unwind state for a particular frame. This 64117395Skan provides the information necessary to unwind up past a frame and return 65117395Skan to its caller. */ 6690075Sobrienstruct _Unwind_Context 6790075Sobrien{ 6890075Sobrien void *reg[DWARF_FRAME_REGISTERS+1]; 6990075Sobrien void *cfa; 7090075Sobrien void *ra; 7190075Sobrien void *lsda; 7290075Sobrien struct dwarf_eh_bases bases; 73169689Skan /* Signal frame context. */ 74169689Skan#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1) 75169689Skan /* Context which has version/args_size/by_value fields. */ 76169689Skan#define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1) 77169689Skan _Unwind_Word flags; 78169689Skan /* 0 for now, can be increased when further fields are added to 79169689Skan struct _Unwind_Context. */ 80169689Skan _Unwind_Word version; 8190075Sobrien _Unwind_Word args_size; 82169689Skan char by_value[DWARF_FRAME_REGISTERS+1]; 8390075Sobrien}; 8490075Sobrien 8590075Sobrien/* Byte size of every register managed by these routines. */ 86122180Skanstatic unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS+1]; 8790075Sobrien 8890075Sobrien 8990075Sobrien/* Read unaligned data from the instruction buffer. */ 9090075Sobrien 9190075Sobrienunion unaligned 9290075Sobrien{ 9390075Sobrien void *p; 9490075Sobrien unsigned u2 __attribute__ ((mode (HI))); 9590075Sobrien unsigned u4 __attribute__ ((mode (SI))); 9690075Sobrien unsigned u8 __attribute__ ((mode (DI))); 9790075Sobrien signed s2 __attribute__ ((mode (HI))); 9890075Sobrien signed s4 __attribute__ ((mode (SI))); 9990075Sobrien signed s8 __attribute__ ((mode (DI))); 10090075Sobrien} __attribute__ ((packed)); 10190075Sobrien 102169689Skanstatic void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *); 103169689Skanstatic _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *, 104169689Skan _Unwind_FrameState *); 105169689Skan 10690075Sobrienstatic inline void * 10790075Sobrienread_pointer (const void *p) { const union unaligned *up = p; return up->p; } 10890075Sobrien 10990075Sobrienstatic inline int 11090075Sobrienread_1u (const void *p) { return *(const unsigned char *) p; } 11190075Sobrien 11290075Sobrienstatic inline int 11390075Sobrienread_1s (const void *p) { return *(const signed char *) p; } 11490075Sobrien 11590075Sobrienstatic inline int 11690075Sobrienread_2u (const void *p) { const union unaligned *up = p; return up->u2; } 11790075Sobrien 11890075Sobrienstatic inline int 11990075Sobrienread_2s (const void *p) { const union unaligned *up = p; return up->s2; } 12090075Sobrien 12190075Sobrienstatic inline unsigned int 12290075Sobrienread_4u (const void *p) { const union unaligned *up = p; return up->u4; } 12390075Sobrien 12490075Sobrienstatic inline int 12590075Sobrienread_4s (const void *p) { const union unaligned *up = p; return up->s4; } 12690075Sobrien 12790075Sobrienstatic inline unsigned long 12890075Sobrienread_8u (const void *p) { const union unaligned *up = p; return up->u8; } 12990075Sobrien 13090075Sobrienstatic inline unsigned long 13190075Sobrienread_8s (const void *p) { const union unaligned *up = p; return up->s8; } 13290075Sobrien 133169689Skanstatic inline _Unwind_Word 134169689Skan_Unwind_IsSignalFrame (struct _Unwind_Context *context) 135169689Skan{ 136169689Skan return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0; 137169689Skan} 13890075Sobrien 139169689Skanstatic inline void 140169689Skan_Unwind_SetSignalFrame (struct _Unwind_Context *context, int val) 141169689Skan{ 142169689Skan if (val) 143169689Skan context->flags |= SIGNAL_FRAME_BIT; 144169689Skan else 145169689Skan context->flags &= ~SIGNAL_FRAME_BIT; 146169689Skan} 147169689Skan 148169689Skanstatic inline _Unwind_Word 149169689Skan_Unwind_IsExtendedContext (struct _Unwind_Context *context) 150169689Skan{ 151169689Skan return context->flags & EXTENDED_CONTEXT_BIT; 152169689Skan} 153169689Skan 154169689Skan/* Get the value of register INDEX as saved in CONTEXT. */ 155169689Skan 15690075Sobrieninline _Unwind_Word 15790075Sobrien_Unwind_GetGR (struct _Unwind_Context *context, int index) 15890075Sobrien{ 159132718Skan int size; 160132718Skan void *ptr; 161132718Skan 162146895Skan#ifdef DWARF_ZERO_REG 163146895Skan if (index == DWARF_ZERO_REG) 164146895Skan return 0; 165146895Skan#endif 166146895Skan 167132718Skan index = DWARF_REG_TO_UNWIND_COLUMN (index); 168169689Skan gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); 169132718Skan size = dwarf_reg_size_table[index]; 170132718Skan ptr = context->reg[index]; 171132718Skan 172169689Skan if (_Unwind_IsExtendedContext (context) && context->by_value[index]) 173169689Skan return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr; 174169689Skan 17590075Sobrien /* This will segfault if the register hasn't been saved. */ 176132718Skan if (size == sizeof(_Unwind_Ptr)) 177132718Skan return * (_Unwind_Ptr *) ptr; 178169689Skan else 179169689Skan { 180169689Skan gcc_assert (size == sizeof(_Unwind_Word)); 181169689Skan return * (_Unwind_Word *) ptr; 182169689Skan } 18390075Sobrien} 18490075Sobrien 185132718Skanstatic inline void * 186132718Skan_Unwind_GetPtr (struct _Unwind_Context *context, int index) 187132718Skan{ 188132718Skan return (void *)(_Unwind_Ptr) _Unwind_GetGR (context, index); 189132718Skan} 190132718Skan 191117395Skan/* Get the value of the CFA as saved in CONTEXT. */ 192117395Skan 193117395Skan_Unwind_Word 194117395Skan_Unwind_GetCFA (struct _Unwind_Context *context) 195117395Skan{ 196132718Skan return (_Unwind_Ptr) context->cfa; 197117395Skan} 198117395Skan 199169689Skan/* Overwrite the saved value for register INDEX in CONTEXT with VAL. */ 20090075Sobrien 20190075Sobrieninline void 20290075Sobrien_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val) 20390075Sobrien{ 204132718Skan int size; 205132718Skan void *ptr; 206132718Skan 207132718Skan index = DWARF_REG_TO_UNWIND_COLUMN (index); 208169689Skan gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); 209132718Skan size = dwarf_reg_size_table[index]; 210169689Skan 211169689Skan if (_Unwind_IsExtendedContext (context) && context->by_value[index]) 212169689Skan { 213169689Skan context->reg[index] = (void *) (_Unwind_Internal_Ptr) val; 214169689Skan return; 215169689Skan } 216169689Skan 217132718Skan ptr = context->reg[index]; 218132718Skan 219132718Skan if (size == sizeof(_Unwind_Ptr)) 220132718Skan * (_Unwind_Ptr *) ptr = val; 221132718Skan else 222169689Skan { 223169689Skan gcc_assert (size == sizeof(_Unwind_Word)); 224169689Skan * (_Unwind_Word *) ptr = val; 225169689Skan } 22690075Sobrien} 22790075Sobrien 228132718Skan/* Get the pointer to a register INDEX as saved in CONTEXT. */ 229132718Skan 230132718Skanstatic inline void * 231132718Skan_Unwind_GetGRPtr (struct _Unwind_Context *context, int index) 232132718Skan{ 233132718Skan index = DWARF_REG_TO_UNWIND_COLUMN (index); 234169689Skan if (_Unwind_IsExtendedContext (context) && context->by_value[index]) 235169689Skan return &context->reg[index]; 236132718Skan return context->reg[index]; 237132718Skan} 238132718Skan 239132718Skan/* Set the pointer to a register INDEX as saved in CONTEXT. */ 240132718Skan 241132718Skanstatic inline void 242132718Skan_Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p) 243132718Skan{ 244132718Skan index = DWARF_REG_TO_UNWIND_COLUMN (index); 245169689Skan if (_Unwind_IsExtendedContext (context)) 246169689Skan context->by_value[index] = 0; 247132718Skan context->reg[index] = p; 248132718Skan} 249132718Skan 250169689Skan/* Overwrite the saved value for register INDEX in CONTEXT with VAL. */ 251169689Skan 252169689Skanstatic inline void 253169689Skan_Unwind_SetGRValue (struct _Unwind_Context *context, int index, 254169689Skan _Unwind_Word val) 255169689Skan{ 256169689Skan index = DWARF_REG_TO_UNWIND_COLUMN (index); 257169689Skan gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); 258169689Skan gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr)); 259169689Skan 260169689Skan context->by_value[index] = 1; 261169689Skan context->reg[index] = (void *) (_Unwind_Internal_Ptr) val; 262169689Skan} 263169689Skan 264169689Skan/* Return nonzero if register INDEX is stored by value rather than 265169689Skan by reference. */ 266169689Skan 267169689Skanstatic inline int 268169689Skan_Unwind_GRByValue (struct _Unwind_Context *context, int index) 269169689Skan{ 270169689Skan index = DWARF_REG_TO_UNWIND_COLUMN (index); 271169689Skan return context->by_value[index]; 272169689Skan} 273169689Skan 27490075Sobrien/* Retrieve the return address for CONTEXT. */ 27590075Sobrien 27690075Sobrieninline _Unwind_Ptr 27790075Sobrien_Unwind_GetIP (struct _Unwind_Context *context) 27890075Sobrien{ 27990075Sobrien return (_Unwind_Ptr) context->ra; 28090075Sobrien} 28190075Sobrien 282169689Skan/* Retrieve the return address and flag whether that IP is before 283169689Skan or after first not yet fully executed instruction. */ 284169689Skan 285169689Skaninline _Unwind_Ptr 286169689Skan_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn) 287169689Skan{ 288169689Skan *ip_before_insn = _Unwind_IsSignalFrame (context); 289169689Skan return (_Unwind_Ptr) context->ra; 290169689Skan} 291169689Skan 29290075Sobrien/* Overwrite the return address for CONTEXT with VAL. */ 29390075Sobrien 29490075Sobrieninline void 29590075Sobrien_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val) 29690075Sobrien{ 29790075Sobrien context->ra = (void *) val; 29890075Sobrien} 29990075Sobrien 30090075Sobrienvoid * 30190075Sobrien_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context) 30290075Sobrien{ 30390075Sobrien return context->lsda; 30490075Sobrien} 30590075Sobrien 30690075Sobrien_Unwind_Ptr 30790075Sobrien_Unwind_GetRegionStart (struct _Unwind_Context *context) 30890075Sobrien{ 30990075Sobrien return (_Unwind_Ptr) context->bases.func; 31090075Sobrien} 31190075Sobrien 312117395Skanvoid * 313117395Skan_Unwind_FindEnclosingFunction (void *pc) 314117395Skan{ 315117395Skan struct dwarf_eh_bases bases; 316132718Skan const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases); 317117395Skan if (fde) 318117395Skan return bases.func; 319117395Skan else 320117395Skan return NULL; 321117395Skan} 322117395Skan 32390075Sobrien#ifndef __ia64__ 32490075Sobrien_Unwind_Ptr 32590075Sobrien_Unwind_GetDataRelBase (struct _Unwind_Context *context) 32690075Sobrien{ 32790075Sobrien return (_Unwind_Ptr) context->bases.dbase; 32890075Sobrien} 32990075Sobrien 33090075Sobrien_Unwind_Ptr 33190075Sobrien_Unwind_GetTextRelBase (struct _Unwind_Context *context) 33290075Sobrien{ 33390075Sobrien return (_Unwind_Ptr) context->bases.tbase; 33490075Sobrien} 33590075Sobrien#endif 336169689Skan 337169689Skan#ifdef MD_UNWIND_SUPPORT 338169689Skan#include MD_UNWIND_SUPPORT 339169689Skan#endif 34090075Sobrien 34190075Sobrien/* Extract any interesting information from the CIE for the translation 34290075Sobrien unit F belongs to. Return a pointer to the byte after the augmentation, 34390075Sobrien or NULL if we encountered an undecipherable augmentation. */ 34490075Sobrien 34590075Sobrienstatic const unsigned char * 346132718Skanextract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context, 34790075Sobrien _Unwind_FrameState *fs) 34890075Sobrien{ 34990075Sobrien const unsigned char *aug = cie->augmentation; 350169689Skan const unsigned char *p = aug + strlen ((const char *)aug) + 1; 35190075Sobrien const unsigned char *ret = NULL; 35290075Sobrien _Unwind_Word utmp; 35390075Sobrien 35490075Sobrien /* g++ v2 "eh" has pointer immediately following augmentation string, 35590075Sobrien so it must be handled first. */ 35690075Sobrien if (aug[0] == 'e' && aug[1] == 'h') 35790075Sobrien { 35890075Sobrien fs->eh_ptr = read_pointer (p); 35990075Sobrien p += sizeof (void *); 36090075Sobrien aug += 2; 36190075Sobrien } 36290075Sobrien 36390075Sobrien /* Immediately following the augmentation are the code and 36490075Sobrien data alignment and return address column. */ 36590075Sobrien p = read_uleb128 (p, &fs->code_align); 36690075Sobrien p = read_sleb128 (p, &fs->data_align); 367169689Skan if (cie->version == 1) 368169689Skan fs->retaddr_column = *p++; 369169689Skan else 370169689Skan p = read_uleb128 (p, &fs->retaddr_column); 37190075Sobrien fs->lsda_encoding = DW_EH_PE_omit; 37290075Sobrien 37390075Sobrien /* If the augmentation starts with 'z', then a uleb128 immediately 37490075Sobrien follows containing the length of the augmentation field following 37590075Sobrien the size. */ 37690075Sobrien if (*aug == 'z') 37790075Sobrien { 37890075Sobrien p = read_uleb128 (p, &utmp); 37990075Sobrien ret = p + utmp; 38090075Sobrien 38190075Sobrien fs->saw_z = 1; 38290075Sobrien ++aug; 38390075Sobrien } 38490075Sobrien 38590075Sobrien /* Iterate over recognized augmentation subsequences. */ 38690075Sobrien while (*aug != '\0') 38790075Sobrien { 38890075Sobrien /* "L" indicates a byte showing how the LSDA pointer is encoded. */ 38990075Sobrien if (aug[0] == 'L') 39090075Sobrien { 39190075Sobrien fs->lsda_encoding = *p++; 39290075Sobrien aug += 1; 39390075Sobrien } 39490075Sobrien 39590075Sobrien /* "R" indicates a byte indicating how FDE addresses are encoded. */ 39690075Sobrien else if (aug[0] == 'R') 39790075Sobrien { 39890075Sobrien fs->fde_encoding = *p++; 39990075Sobrien aug += 1; 40090075Sobrien } 40190075Sobrien 40290075Sobrien /* "P" indicates a personality routine in the CIE augmentation. */ 40390075Sobrien else if (aug[0] == 'P') 40490075Sobrien { 405169689Skan _Unwind_Ptr personality; 406169689Skan 407169689Skan p = read_encoded_value (context, *p, p + 1, &personality); 408169689Skan fs->personality = (_Unwind_Personality_Fn) personality; 40990075Sobrien aug += 1; 41090075Sobrien } 41190075Sobrien 412169689Skan /* "S" indicates a signal frame. */ 413169689Skan else if (aug[0] == 'S') 414169689Skan { 415169689Skan fs->signal_frame = 1; 416169689Skan aug += 1; 417169689Skan } 418169689Skan 41990075Sobrien /* Otherwise we have an unknown augmentation string. 42090075Sobrien Bail unless we saw a 'z' prefix. */ 42190075Sobrien else 42290075Sobrien return ret; 42390075Sobrien } 42490075Sobrien 42590075Sobrien return ret ? ret : p; 42690075Sobrien} 42790075Sobrien 42890075Sobrien 42990075Sobrien/* Decode a DW_OP stack program. Return the top of stack. Push INITIAL 43090075Sobrien onto the stack to start. */ 43190075Sobrien 43290075Sobrienstatic _Unwind_Word 43390075Sobrienexecute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, 43490075Sobrien struct _Unwind_Context *context, _Unwind_Word initial) 43590075Sobrien{ 43690075Sobrien _Unwind_Word stack[64]; /* ??? Assume this is enough. */ 43790075Sobrien int stack_elt; 43890075Sobrien 43990075Sobrien stack[0] = initial; 44090075Sobrien stack_elt = 1; 44190075Sobrien 44290075Sobrien while (op_ptr < op_end) 44390075Sobrien { 44490075Sobrien enum dwarf_location_atom op = *op_ptr++; 44590075Sobrien _Unwind_Word result, reg, utmp; 44690075Sobrien _Unwind_Sword offset, stmp; 44790075Sobrien 44890075Sobrien switch (op) 44990075Sobrien { 45090075Sobrien case DW_OP_lit0: 45190075Sobrien case DW_OP_lit1: 45290075Sobrien case DW_OP_lit2: 45390075Sobrien case DW_OP_lit3: 45490075Sobrien case DW_OP_lit4: 45590075Sobrien case DW_OP_lit5: 45690075Sobrien case DW_OP_lit6: 45790075Sobrien case DW_OP_lit7: 45890075Sobrien case DW_OP_lit8: 45990075Sobrien case DW_OP_lit9: 46090075Sobrien case DW_OP_lit10: 46190075Sobrien case DW_OP_lit11: 46290075Sobrien case DW_OP_lit12: 46390075Sobrien case DW_OP_lit13: 46490075Sobrien case DW_OP_lit14: 46590075Sobrien case DW_OP_lit15: 46690075Sobrien case DW_OP_lit16: 46790075Sobrien case DW_OP_lit17: 46890075Sobrien case DW_OP_lit18: 46990075Sobrien case DW_OP_lit19: 47090075Sobrien case DW_OP_lit20: 47190075Sobrien case DW_OP_lit21: 47290075Sobrien case DW_OP_lit22: 47390075Sobrien case DW_OP_lit23: 47490075Sobrien case DW_OP_lit24: 47590075Sobrien case DW_OP_lit25: 47690075Sobrien case DW_OP_lit26: 47790075Sobrien case DW_OP_lit27: 47890075Sobrien case DW_OP_lit28: 47990075Sobrien case DW_OP_lit29: 48090075Sobrien case DW_OP_lit30: 48190075Sobrien case DW_OP_lit31: 48290075Sobrien result = op - DW_OP_lit0; 48390075Sobrien break; 48490075Sobrien 48590075Sobrien case DW_OP_addr: 48690075Sobrien result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr); 48790075Sobrien op_ptr += sizeof (void *); 48890075Sobrien break; 48990075Sobrien 49090075Sobrien case DW_OP_const1u: 49190075Sobrien result = read_1u (op_ptr); 49290075Sobrien op_ptr += 1; 49390075Sobrien break; 49490075Sobrien case DW_OP_const1s: 49590075Sobrien result = read_1s (op_ptr); 49690075Sobrien op_ptr += 1; 49790075Sobrien break; 49890075Sobrien case DW_OP_const2u: 49990075Sobrien result = read_2u (op_ptr); 50090075Sobrien op_ptr += 2; 50190075Sobrien break; 50290075Sobrien case DW_OP_const2s: 50390075Sobrien result = read_2s (op_ptr); 50490075Sobrien op_ptr += 2; 50590075Sobrien break; 50690075Sobrien case DW_OP_const4u: 50790075Sobrien result = read_4u (op_ptr); 50890075Sobrien op_ptr += 4; 50990075Sobrien break; 51090075Sobrien case DW_OP_const4s: 51190075Sobrien result = read_4s (op_ptr); 51290075Sobrien op_ptr += 4; 51390075Sobrien break; 51490075Sobrien case DW_OP_const8u: 51590075Sobrien result = read_8u (op_ptr); 51690075Sobrien op_ptr += 8; 51790075Sobrien break; 51890075Sobrien case DW_OP_const8s: 51990075Sobrien result = read_8s (op_ptr); 52090075Sobrien op_ptr += 8; 52190075Sobrien break; 52290075Sobrien case DW_OP_constu: 52390075Sobrien op_ptr = read_uleb128 (op_ptr, &result); 52490075Sobrien break; 52590075Sobrien case DW_OP_consts: 52690075Sobrien op_ptr = read_sleb128 (op_ptr, &stmp); 52790075Sobrien result = stmp; 52890075Sobrien break; 52990075Sobrien 53090075Sobrien case DW_OP_reg0: 53190075Sobrien case DW_OP_reg1: 53290075Sobrien case DW_OP_reg2: 53390075Sobrien case DW_OP_reg3: 53490075Sobrien case DW_OP_reg4: 53590075Sobrien case DW_OP_reg5: 53690075Sobrien case DW_OP_reg6: 53790075Sobrien case DW_OP_reg7: 53890075Sobrien case DW_OP_reg8: 53990075Sobrien case DW_OP_reg9: 54090075Sobrien case DW_OP_reg10: 54190075Sobrien case DW_OP_reg11: 54290075Sobrien case DW_OP_reg12: 54390075Sobrien case DW_OP_reg13: 54490075Sobrien case DW_OP_reg14: 54590075Sobrien case DW_OP_reg15: 54690075Sobrien case DW_OP_reg16: 54790075Sobrien case DW_OP_reg17: 54890075Sobrien case DW_OP_reg18: 54990075Sobrien case DW_OP_reg19: 55090075Sobrien case DW_OP_reg20: 55190075Sobrien case DW_OP_reg21: 55290075Sobrien case DW_OP_reg22: 55390075Sobrien case DW_OP_reg23: 55490075Sobrien case DW_OP_reg24: 55590075Sobrien case DW_OP_reg25: 55690075Sobrien case DW_OP_reg26: 55790075Sobrien case DW_OP_reg27: 55890075Sobrien case DW_OP_reg28: 55990075Sobrien case DW_OP_reg29: 56090075Sobrien case DW_OP_reg30: 56190075Sobrien case DW_OP_reg31: 56290075Sobrien result = _Unwind_GetGR (context, op - DW_OP_reg0); 56390075Sobrien break; 56490075Sobrien case DW_OP_regx: 56590075Sobrien op_ptr = read_uleb128 (op_ptr, ®); 56690075Sobrien result = _Unwind_GetGR (context, reg); 56790075Sobrien break; 56890075Sobrien 56990075Sobrien case DW_OP_breg0: 57090075Sobrien case DW_OP_breg1: 57190075Sobrien case DW_OP_breg2: 57290075Sobrien case DW_OP_breg3: 57390075Sobrien case DW_OP_breg4: 57490075Sobrien case DW_OP_breg5: 57590075Sobrien case DW_OP_breg6: 57690075Sobrien case DW_OP_breg7: 57790075Sobrien case DW_OP_breg8: 57890075Sobrien case DW_OP_breg9: 57990075Sobrien case DW_OP_breg10: 58090075Sobrien case DW_OP_breg11: 58190075Sobrien case DW_OP_breg12: 58290075Sobrien case DW_OP_breg13: 58390075Sobrien case DW_OP_breg14: 58490075Sobrien case DW_OP_breg15: 58590075Sobrien case DW_OP_breg16: 58690075Sobrien case DW_OP_breg17: 58790075Sobrien case DW_OP_breg18: 58890075Sobrien case DW_OP_breg19: 58990075Sobrien case DW_OP_breg20: 59090075Sobrien case DW_OP_breg21: 59190075Sobrien case DW_OP_breg22: 59290075Sobrien case DW_OP_breg23: 59390075Sobrien case DW_OP_breg24: 59490075Sobrien case DW_OP_breg25: 59590075Sobrien case DW_OP_breg26: 59690075Sobrien case DW_OP_breg27: 59790075Sobrien case DW_OP_breg28: 59890075Sobrien case DW_OP_breg29: 59990075Sobrien case DW_OP_breg30: 60090075Sobrien case DW_OP_breg31: 60190075Sobrien op_ptr = read_sleb128 (op_ptr, &offset); 60290075Sobrien result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset; 60390075Sobrien break; 60490075Sobrien case DW_OP_bregx: 60590075Sobrien op_ptr = read_uleb128 (op_ptr, ®); 60690075Sobrien op_ptr = read_sleb128 (op_ptr, &offset); 60790075Sobrien result = _Unwind_GetGR (context, reg) + offset; 60890075Sobrien break; 60990075Sobrien 61090075Sobrien case DW_OP_dup: 611169689Skan gcc_assert (stack_elt); 61290075Sobrien result = stack[stack_elt - 1]; 61390075Sobrien break; 61490075Sobrien 61590075Sobrien case DW_OP_drop: 616169689Skan gcc_assert (stack_elt); 617169689Skan stack_elt -= 1; 61890075Sobrien goto no_push; 61990075Sobrien 62090075Sobrien case DW_OP_pick: 62190075Sobrien offset = *op_ptr++; 622169689Skan gcc_assert (offset < stack_elt - 1); 62390075Sobrien result = stack[stack_elt - 1 - offset]; 62490075Sobrien break; 62590075Sobrien 62690075Sobrien case DW_OP_over: 627169689Skan gcc_assert (stack_elt >= 2); 62890075Sobrien result = stack[stack_elt - 2]; 62990075Sobrien break; 63090075Sobrien 631169689Skan case DW_OP_swap: 632169689Skan { 633169689Skan _Unwind_Word t; 634169689Skan gcc_assert (stack_elt >= 2); 635169689Skan t = stack[stack_elt - 1]; 636169689Skan stack[stack_elt - 1] = stack[stack_elt - 2]; 637169689Skan stack[stack_elt - 2] = t; 638169689Skan goto no_push; 639169689Skan } 640169689Skan 64190075Sobrien case DW_OP_rot: 64290075Sobrien { 64390075Sobrien _Unwind_Word t1, t2, t3; 64490075Sobrien 645169689Skan gcc_assert (stack_elt >= 3); 64690075Sobrien t1 = stack[stack_elt - 1]; 64790075Sobrien t2 = stack[stack_elt - 2]; 64890075Sobrien t3 = stack[stack_elt - 3]; 64990075Sobrien stack[stack_elt - 1] = t2; 65090075Sobrien stack[stack_elt - 2] = t3; 65190075Sobrien stack[stack_elt - 3] = t1; 65290075Sobrien goto no_push; 65390075Sobrien } 65490075Sobrien 65590075Sobrien case DW_OP_deref: 65690075Sobrien case DW_OP_deref_size: 65790075Sobrien case DW_OP_abs: 65890075Sobrien case DW_OP_neg: 65990075Sobrien case DW_OP_not: 66090075Sobrien case DW_OP_plus_uconst: 66190075Sobrien /* Unary operations. */ 662169689Skan gcc_assert (stack_elt); 663169689Skan stack_elt -= 1; 664169689Skan 66590075Sobrien result = stack[stack_elt]; 66690075Sobrien 66790075Sobrien switch (op) 66890075Sobrien { 66990075Sobrien case DW_OP_deref: 67090075Sobrien { 67190075Sobrien void *ptr = (void *) (_Unwind_Ptr) result; 67290075Sobrien result = (_Unwind_Ptr) read_pointer (ptr); 67390075Sobrien } 67490075Sobrien break; 67590075Sobrien 67690075Sobrien case DW_OP_deref_size: 67790075Sobrien { 67890075Sobrien void *ptr = (void *) (_Unwind_Ptr) result; 67990075Sobrien switch (*op_ptr++) 68090075Sobrien { 68190075Sobrien case 1: 68290075Sobrien result = read_1u (ptr); 68390075Sobrien break; 68490075Sobrien case 2: 68590075Sobrien result = read_2u (ptr); 68690075Sobrien break; 68790075Sobrien case 4: 68890075Sobrien result = read_4u (ptr); 68990075Sobrien break; 69090075Sobrien case 8: 69190075Sobrien result = read_8u (ptr); 69290075Sobrien break; 69390075Sobrien default: 694169689Skan gcc_unreachable (); 69590075Sobrien } 69690075Sobrien } 69790075Sobrien break; 69890075Sobrien 69990075Sobrien case DW_OP_abs: 70090075Sobrien if ((_Unwind_Sword) result < 0) 70190075Sobrien result = -result; 70290075Sobrien break; 70390075Sobrien case DW_OP_neg: 70490075Sobrien result = -result; 70590075Sobrien break; 70690075Sobrien case DW_OP_not: 70790075Sobrien result = ~result; 70890075Sobrien break; 70990075Sobrien case DW_OP_plus_uconst: 71090075Sobrien op_ptr = read_uleb128 (op_ptr, &utmp); 71190075Sobrien result += utmp; 71290075Sobrien break; 71390075Sobrien 71490075Sobrien default: 715169689Skan gcc_unreachable (); 71690075Sobrien } 71790075Sobrien break; 71890075Sobrien 71990075Sobrien case DW_OP_and: 72090075Sobrien case DW_OP_div: 72190075Sobrien case DW_OP_minus: 72290075Sobrien case DW_OP_mod: 72390075Sobrien case DW_OP_mul: 72490075Sobrien case DW_OP_or: 72590075Sobrien case DW_OP_plus: 726146895Skan case DW_OP_shl: 727146895Skan case DW_OP_shr: 728146895Skan case DW_OP_shra: 729146895Skan case DW_OP_xor: 73090075Sobrien case DW_OP_le: 73190075Sobrien case DW_OP_ge: 73290075Sobrien case DW_OP_eq: 73390075Sobrien case DW_OP_lt: 73490075Sobrien case DW_OP_gt: 73590075Sobrien case DW_OP_ne: 73690075Sobrien { 73790075Sobrien /* Binary operations. */ 73890075Sobrien _Unwind_Word first, second; 739169689Skan gcc_assert (stack_elt >= 2); 740169689Skan stack_elt -= 2; 741169689Skan 742117395Skan second = stack[stack_elt]; 743117395Skan first = stack[stack_elt + 1]; 74490075Sobrien 745117395Skan switch (op) 746117395Skan { 747117395Skan case DW_OP_and: 748117395Skan result = second & first; 749117395Skan break; 750117395Skan case DW_OP_div: 751117395Skan result = (_Unwind_Sword) second / (_Unwind_Sword) first; 752117395Skan break; 753117395Skan case DW_OP_minus: 754117395Skan result = second - first; 755117395Skan break; 756117395Skan case DW_OP_mod: 757117395Skan result = (_Unwind_Sword) second % (_Unwind_Sword) first; 758117395Skan break; 759117395Skan case DW_OP_mul: 760117395Skan result = second * first; 761117395Skan break; 762117395Skan case DW_OP_or: 763117395Skan result = second | first; 764117395Skan break; 765117395Skan case DW_OP_plus: 766117395Skan result = second + first; 767117395Skan break; 768117395Skan case DW_OP_shl: 769117395Skan result = second << first; 770117395Skan break; 771117395Skan case DW_OP_shr: 772117395Skan result = second >> first; 773117395Skan break; 774117395Skan case DW_OP_shra: 775117395Skan result = (_Unwind_Sword) second >> first; 776117395Skan break; 777117395Skan case DW_OP_xor: 778117395Skan result = second ^ first; 779117395Skan break; 780117395Skan case DW_OP_le: 781117395Skan result = (_Unwind_Sword) first <= (_Unwind_Sword) second; 782117395Skan break; 783117395Skan case DW_OP_ge: 784117395Skan result = (_Unwind_Sword) first >= (_Unwind_Sword) second; 785117395Skan break; 786117395Skan case DW_OP_eq: 787117395Skan result = (_Unwind_Sword) first == (_Unwind_Sword) second; 788117395Skan break; 789117395Skan case DW_OP_lt: 790117395Skan result = (_Unwind_Sword) first < (_Unwind_Sword) second; 791117395Skan break; 792117395Skan case DW_OP_gt: 793117395Skan result = (_Unwind_Sword) first > (_Unwind_Sword) second; 794117395Skan break; 795117395Skan case DW_OP_ne: 796117395Skan result = (_Unwind_Sword) first != (_Unwind_Sword) second; 797117395Skan break; 79890075Sobrien 799117395Skan default: 800169689Skan gcc_unreachable (); 801117395Skan } 80290075Sobrien } 80390075Sobrien break; 80490075Sobrien 80590075Sobrien case DW_OP_skip: 80690075Sobrien offset = read_2s (op_ptr); 80790075Sobrien op_ptr += 2; 80890075Sobrien op_ptr += offset; 80990075Sobrien goto no_push; 81090075Sobrien 81190075Sobrien case DW_OP_bra: 812169689Skan gcc_assert (stack_elt); 813169689Skan stack_elt -= 1; 814169689Skan 81590075Sobrien offset = read_2s (op_ptr); 81690075Sobrien op_ptr += 2; 81790075Sobrien if (stack[stack_elt] != 0) 81890075Sobrien op_ptr += offset; 81990075Sobrien goto no_push; 82090075Sobrien 82190075Sobrien case DW_OP_nop: 82290075Sobrien goto no_push; 82390075Sobrien 82490075Sobrien default: 825169689Skan gcc_unreachable (); 82690075Sobrien } 82790075Sobrien 82890075Sobrien /* Most things push a result value. */ 829169689Skan gcc_assert ((size_t) stack_elt < sizeof(stack)/sizeof(*stack)); 830117395Skan stack[stack_elt++] = result; 83190075Sobrien no_push:; 83290075Sobrien } 83390075Sobrien 83490075Sobrien /* We were executing this program to get a value. It should be 83590075Sobrien at top of stack. */ 836169689Skan gcc_assert (stack_elt); 837169689Skan stack_elt -= 1; 83890075Sobrien return stack[stack_elt]; 83990075Sobrien} 84090075Sobrien 84190075Sobrien 84290075Sobrien/* Decode DWARF 2 call frame information. Takes pointers the 84390075Sobrien instruction sequence to decode, current register information and 84490075Sobrien CIE info, and the PC range to evaluate. */ 84590075Sobrien 84690075Sobrienstatic void 84790075Sobrienexecute_cfa_program (const unsigned char *insn_ptr, 84890075Sobrien const unsigned char *insn_end, 84990075Sobrien struct _Unwind_Context *context, 85090075Sobrien _Unwind_FrameState *fs) 85190075Sobrien{ 85290075Sobrien struct frame_state_reg_info *unused_rs = NULL; 85390075Sobrien 85490075Sobrien /* Don't allow remember/restore between CIE and FDE programs. */ 85590075Sobrien fs->regs.prev = NULL; 85690075Sobrien 85790075Sobrien /* The comparison with the return address uses < rather than <= because 85890075Sobrien we are only interested in the effects of code before the call; for a 85990075Sobrien noreturn function, the return address may point to unrelated code with 86090075Sobrien a different stack configuration that we are not interested in. We 86190075Sobrien assume that the call itself is unwind info-neutral; if not, or if 86290075Sobrien there are delay instructions that adjust the stack, these must be 863169689Skan reflected at the point immediately before the call insn. 864169689Skan In signal frames, return address is after last completed instruction, 865169689Skan so we add 1 to return address to make the comparison <=. */ 866169689Skan while (insn_ptr < insn_end 867169689Skan && fs->pc < context->ra + _Unwind_IsSignalFrame (context)) 86890075Sobrien { 86990075Sobrien unsigned char insn = *insn_ptr++; 87090075Sobrien _Unwind_Word reg, utmp; 87190075Sobrien _Unwind_Sword offset, stmp; 87290075Sobrien 87390075Sobrien if ((insn & 0xc0) == DW_CFA_advance_loc) 87490075Sobrien fs->pc += (insn & 0x3f) * fs->code_align; 87590075Sobrien else if ((insn & 0xc0) == DW_CFA_offset) 87690075Sobrien { 87790075Sobrien reg = insn & 0x3f; 87890075Sobrien insn_ptr = read_uleb128 (insn_ptr, &utmp); 87990075Sobrien offset = (_Unwind_Sword) utmp * fs->data_align; 880132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how 881132718Skan = REG_SAVED_OFFSET; 882132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset; 88390075Sobrien } 88490075Sobrien else if ((insn & 0xc0) == DW_CFA_restore) 88590075Sobrien { 88690075Sobrien reg = insn & 0x3f; 887132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_UNSAVED; 88890075Sobrien } 88990075Sobrien else switch (insn) 89090075Sobrien { 89190075Sobrien case DW_CFA_set_loc: 892169689Skan { 893169689Skan _Unwind_Ptr pc; 894169689Skan 895169689Skan insn_ptr = read_encoded_value (context, fs->fde_encoding, 896169689Skan insn_ptr, &pc); 897169689Skan fs->pc = (void *) pc; 898169689Skan } 89990075Sobrien break; 90090075Sobrien 90190075Sobrien case DW_CFA_advance_loc1: 90290075Sobrien fs->pc += read_1u (insn_ptr) * fs->code_align; 90390075Sobrien insn_ptr += 1; 90490075Sobrien break; 90590075Sobrien case DW_CFA_advance_loc2: 90690075Sobrien fs->pc += read_2u (insn_ptr) * fs->code_align; 90790075Sobrien insn_ptr += 2; 90890075Sobrien break; 90990075Sobrien case DW_CFA_advance_loc4: 91090075Sobrien fs->pc += read_4u (insn_ptr) * fs->code_align; 91190075Sobrien insn_ptr += 4; 91290075Sobrien break; 91390075Sobrien 91490075Sobrien case DW_CFA_offset_extended: 91590075Sobrien insn_ptr = read_uleb128 (insn_ptr, ®); 91690075Sobrien insn_ptr = read_uleb128 (insn_ptr, &utmp); 91790075Sobrien offset = (_Unwind_Sword) utmp * fs->data_align; 918132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how 919132718Skan = REG_SAVED_OFFSET; 920132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset; 92190075Sobrien break; 92290075Sobrien 92390075Sobrien case DW_CFA_restore_extended: 92490075Sobrien insn_ptr = read_uleb128 (insn_ptr, ®); 925169689Skan /* FIXME, this is wrong; the CIE might have said that the 926169689Skan register was saved somewhere. */ 927132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED; 92890075Sobrien break; 92990075Sobrien 93090075Sobrien case DW_CFA_undefined: 93190075Sobrien case DW_CFA_same_value: 932110611Skan insn_ptr = read_uleb128 (insn_ptr, ®); 933169689Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED; 934110611Skan break; 935110611Skan 93690075Sobrien case DW_CFA_nop: 93790075Sobrien break; 93890075Sobrien 93990075Sobrien case DW_CFA_register: 94090075Sobrien { 94190075Sobrien _Unwind_Word reg2; 94290075Sobrien insn_ptr = read_uleb128 (insn_ptr, ®); 94390075Sobrien insn_ptr = read_uleb128 (insn_ptr, ®2); 944132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_REG; 945132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.reg = reg2; 94690075Sobrien } 94790075Sobrien break; 948117395Skan 94990075Sobrien case DW_CFA_remember_state: 95090075Sobrien { 95190075Sobrien struct frame_state_reg_info *new_rs; 95290075Sobrien if (unused_rs) 95390075Sobrien { 95490075Sobrien new_rs = unused_rs; 95590075Sobrien unused_rs = unused_rs->prev; 95690075Sobrien } 95790075Sobrien else 958169689Skan new_rs = alloca (sizeof (struct frame_state_reg_info)); 95990075Sobrien 96090075Sobrien *new_rs = fs->regs; 96190075Sobrien fs->regs.prev = new_rs; 96290075Sobrien } 96390075Sobrien break; 96490075Sobrien 96590075Sobrien case DW_CFA_restore_state: 96690075Sobrien { 96790075Sobrien struct frame_state_reg_info *old_rs = fs->regs.prev; 96890075Sobrien fs->regs = *old_rs; 96990075Sobrien old_rs->prev = unused_rs; 97090075Sobrien unused_rs = old_rs; 97190075Sobrien } 97290075Sobrien break; 97390075Sobrien 97490075Sobrien case DW_CFA_def_cfa: 97590075Sobrien insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg); 97690075Sobrien insn_ptr = read_uleb128 (insn_ptr, &utmp); 97790075Sobrien fs->cfa_offset = utmp; 97890075Sobrien fs->cfa_how = CFA_REG_OFFSET; 97990075Sobrien break; 98090075Sobrien 98190075Sobrien case DW_CFA_def_cfa_register: 98290075Sobrien insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg); 98390075Sobrien fs->cfa_how = CFA_REG_OFFSET; 98490075Sobrien break; 98590075Sobrien 98690075Sobrien case DW_CFA_def_cfa_offset: 98790075Sobrien insn_ptr = read_uleb128 (insn_ptr, &utmp); 98890075Sobrien fs->cfa_offset = utmp; 98990075Sobrien /* cfa_how deliberately not set. */ 99090075Sobrien break; 99190075Sobrien 99290075Sobrien case DW_CFA_def_cfa_expression: 99390075Sobrien fs->cfa_exp = insn_ptr; 99490075Sobrien fs->cfa_how = CFA_EXP; 995117395Skan insn_ptr = read_uleb128 (insn_ptr, &utmp); 99690075Sobrien insn_ptr += utmp; 99790075Sobrien break; 99890075Sobrien 99990075Sobrien case DW_CFA_expression: 100090075Sobrien insn_ptr = read_uleb128 (insn_ptr, ®); 1001132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_EXP; 1002132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr; 1003117395Skan insn_ptr = read_uleb128 (insn_ptr, &utmp); 100490075Sobrien insn_ptr += utmp; 100590075Sobrien break; 100690075Sobrien 1007169689Skan /* Dwarf3. */ 100890075Sobrien case DW_CFA_offset_extended_sf: 100990075Sobrien insn_ptr = read_uleb128 (insn_ptr, ®); 101090075Sobrien insn_ptr = read_sleb128 (insn_ptr, &stmp); 101190075Sobrien offset = stmp * fs->data_align; 1012132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how 1013132718Skan = REG_SAVED_OFFSET; 1014132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset; 101590075Sobrien break; 1016117395Skan 101790075Sobrien case DW_CFA_def_cfa_sf: 101890075Sobrien insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg); 101990075Sobrien insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset); 102090075Sobrien fs->cfa_how = CFA_REG_OFFSET; 1021169689Skan fs->cfa_offset *= fs->data_align; 102290075Sobrien break; 102390075Sobrien 102490075Sobrien case DW_CFA_def_cfa_offset_sf: 102590075Sobrien insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset); 1026169689Skan fs->cfa_offset *= fs->data_align; 102790075Sobrien /* cfa_how deliberately not set. */ 102890075Sobrien break; 102990075Sobrien 1030169689Skan case DW_CFA_val_offset: 1031169689Skan insn_ptr = read_uleb128 (insn_ptr, ®); 1032169689Skan insn_ptr = read_uleb128 (insn_ptr, &utmp); 1033169689Skan offset = (_Unwind_Sword) utmp * fs->data_align; 1034169689Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how 1035169689Skan = REG_SAVED_VAL_OFFSET; 1036169689Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset; 1037169689Skan break; 1038169689Skan 1039169689Skan case DW_CFA_val_offset_sf: 1040169689Skan insn_ptr = read_uleb128 (insn_ptr, ®); 1041169689Skan insn_ptr = read_sleb128 (insn_ptr, &stmp); 1042169689Skan offset = stmp * fs->data_align; 1043169689Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how 1044169689Skan = REG_SAVED_VAL_OFFSET; 1045169689Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset; 1046169689Skan break; 1047169689Skan 1048169689Skan case DW_CFA_val_expression: 1049169689Skan insn_ptr = read_uleb128 (insn_ptr, ®); 1050169689Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how 1051169689Skan = REG_SAVED_VAL_EXP; 1052169689Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr; 1053169689Skan insn_ptr = read_uleb128 (insn_ptr, &utmp); 1054169689Skan insn_ptr += utmp; 1055169689Skan break; 1056169689Skan 105790075Sobrien case DW_CFA_GNU_window_save: 105890075Sobrien /* ??? Hardcoded for SPARC register window configuration. */ 105990075Sobrien for (reg = 16; reg < 32; ++reg) 106090075Sobrien { 106190075Sobrien fs->regs.reg[reg].how = REG_SAVED_OFFSET; 106290075Sobrien fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *); 106390075Sobrien } 106490075Sobrien break; 106590075Sobrien 106690075Sobrien case DW_CFA_GNU_args_size: 106790075Sobrien insn_ptr = read_uleb128 (insn_ptr, &context->args_size); 106890075Sobrien break; 106990075Sobrien 107090075Sobrien case DW_CFA_GNU_negative_offset_extended: 107190075Sobrien /* Obsoleted by DW_CFA_offset_extended_sf, but used by 107290075Sobrien older PowerPC code. */ 107390075Sobrien insn_ptr = read_uleb128 (insn_ptr, ®); 107490075Sobrien insn_ptr = read_uleb128 (insn_ptr, &utmp); 107590075Sobrien offset = (_Unwind_Word) utmp * fs->data_align; 1076132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how 1077132718Skan = REG_SAVED_OFFSET; 1078132718Skan fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = -offset; 107990075Sobrien break; 108090075Sobrien 108190075Sobrien default: 1082169689Skan gcc_unreachable (); 108390075Sobrien } 108490075Sobrien } 108590075Sobrien} 108690075Sobrien 1087117395Skan/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for 1088117395Skan its caller and decode it into FS. This function also sets the 1089117395Skan args_size and lsda members of CONTEXT, as they are really information 1090117395Skan about the caller's frame. */ 1091117395Skan 109290075Sobrienstatic _Unwind_Reason_Code 109390075Sobrienuw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) 109490075Sobrien{ 1095132718Skan const struct dwarf_fde *fde; 1096132718Skan const struct dwarf_cie *cie; 109790075Sobrien const unsigned char *aug, *insn, *end; 109890075Sobrien 109990075Sobrien memset (fs, 0, sizeof (*fs)); 110090075Sobrien context->args_size = 0; 110190075Sobrien context->lsda = 0; 110290075Sobrien 1103122180Skan if (context->ra == 0) 1104122180Skan return _URC_END_OF_STACK; 1105122180Skan 1106169689Skan fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1, 1107169689Skan &context->bases); 110890075Sobrien if (fde == NULL) 110990075Sobrien { 1110169689Skan#ifdef MD_FALLBACK_FRAME_STATE_FOR 111190075Sobrien /* Couldn't find frame unwind info for this function. Try a 111290075Sobrien target-specific fallback mechanism. This will necessarily 111390075Sobrien not provide a personality routine or LSDA. */ 1114169689Skan return MD_FALLBACK_FRAME_STATE_FOR (context, fs); 111590075Sobrien#else 111690075Sobrien return _URC_END_OF_STACK; 111790075Sobrien#endif 111890075Sobrien } 111990075Sobrien 112090075Sobrien fs->pc = context->bases.func; 112190075Sobrien 112290075Sobrien cie = get_cie (fde); 112390075Sobrien insn = extract_cie_info (cie, context, fs); 112490075Sobrien if (insn == NULL) 112590075Sobrien /* CIE contained unknown augmentation. */ 112690075Sobrien return _URC_FATAL_PHASE1_ERROR; 112790075Sobrien 112890075Sobrien /* First decode all the insns in the CIE. */ 112990075Sobrien end = (unsigned char *) next_fde ((struct dwarf_fde *) cie); 113090075Sobrien execute_cfa_program (insn, end, context, fs); 113190075Sobrien 113290075Sobrien /* Locate augmentation for the fde. */ 113390075Sobrien aug = (unsigned char *) fde + sizeof (*fde); 113490075Sobrien aug += 2 * size_of_encoded_value (fs->fde_encoding); 113590075Sobrien insn = NULL; 113690075Sobrien if (fs->saw_z) 113790075Sobrien { 113890075Sobrien _Unwind_Word i; 113990075Sobrien aug = read_uleb128 (aug, &i); 114090075Sobrien insn = aug + i; 114190075Sobrien } 114290075Sobrien if (fs->lsda_encoding != DW_EH_PE_omit) 1143169689Skan { 1144169689Skan _Unwind_Ptr lsda; 1145169689Skan 1146169689Skan aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda); 1147169689Skan context->lsda = (void *) lsda; 1148169689Skan } 114990075Sobrien 115090075Sobrien /* Then the insns in the FDE up to our target PC. */ 115190075Sobrien if (insn == NULL) 115290075Sobrien insn = aug; 115390075Sobrien end = (unsigned char *) next_fde (fde); 115490075Sobrien execute_cfa_program (insn, end, context, fs); 115590075Sobrien 115690075Sobrien return _URC_NO_REASON; 115790075Sobrien} 115890075Sobrien 115990075Sobrientypedef struct frame_state 116090075Sobrien{ 116190075Sobrien void *cfa; 116290075Sobrien void *eh_ptr; 116390075Sobrien long cfa_offset; 116490075Sobrien long args_size; 116590075Sobrien long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1]; 116690075Sobrien unsigned short cfa_reg; 116790075Sobrien unsigned short retaddr_column; 116890075Sobrien char saved[PRE_GCC3_DWARF_FRAME_REGISTERS+1]; 116990075Sobrien} frame_state; 117090075Sobrien 117190075Sobrienstruct frame_state * __frame_state_for (void *, struct frame_state *); 117290075Sobrien 117390075Sobrien/* Called from pre-G++ 3.0 __throw to find the registers to restore for 117490075Sobrien a given PC_TARGET. The caller should allocate a local variable of 117590075Sobrien `struct frame_state' and pass its address to STATE_IN. */ 117690075Sobrien 117790075Sobrienstruct frame_state * 117890075Sobrien__frame_state_for (void *pc_target, struct frame_state *state_in) 117990075Sobrien{ 118090075Sobrien struct _Unwind_Context context; 118190075Sobrien _Unwind_FrameState fs; 118290075Sobrien int reg; 118390075Sobrien 118490075Sobrien memset (&context, 0, sizeof (struct _Unwind_Context)); 1185169689Skan context.flags = EXTENDED_CONTEXT_BIT; 118690075Sobrien context.ra = pc_target + 1; 118790075Sobrien 118890075Sobrien if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON) 118990075Sobrien return 0; 119090075Sobrien 119190075Sobrien /* We have no way to pass a location expression for the CFA to our 119290075Sobrien caller. It wouldn't understand it anyway. */ 119390075Sobrien if (fs.cfa_how == CFA_EXP) 119490075Sobrien return 0; 119590075Sobrien 119690075Sobrien for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++) 119790075Sobrien { 119890075Sobrien state_in->saved[reg] = fs.regs.reg[reg].how; 119990075Sobrien switch (state_in->saved[reg]) 120090075Sobrien { 120190075Sobrien case REG_SAVED_REG: 120290075Sobrien state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg; 120390075Sobrien break; 120490075Sobrien case REG_SAVED_OFFSET: 120590075Sobrien state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset; 120690075Sobrien break; 120790075Sobrien default: 120890075Sobrien state_in->reg_or_offset[reg] = 0; 120990075Sobrien break; 121090075Sobrien } 121190075Sobrien } 121290075Sobrien 121390075Sobrien state_in->cfa_offset = fs.cfa_offset; 121490075Sobrien state_in->cfa_reg = fs.cfa_reg; 121590075Sobrien state_in->retaddr_column = fs.retaddr_column; 121690075Sobrien state_in->args_size = context.args_size; 121790075Sobrien state_in->eh_ptr = fs.eh_ptr; 121890075Sobrien 121990075Sobrien return state_in; 122090075Sobrien} 122190075Sobrien 1222132718Skantypedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp; 1223132718Skan 1224132718Skanstatic inline void 1225132718Skan_Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa, 1226169689Skan _Unwind_SpTmp *tmp_sp) 1227132718Skan{ 1228132718Skan int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()]; 1229132718Skan 1230132718Skan if (size == sizeof(_Unwind_Ptr)) 1231132718Skan tmp_sp->ptr = (_Unwind_Ptr) cfa; 1232132718Skan else 1233169689Skan { 1234169689Skan gcc_assert (size == sizeof(_Unwind_Word)); 1235169689Skan tmp_sp->word = (_Unwind_Ptr) cfa; 1236169689Skan } 1237132718Skan _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), tmp_sp); 1238132718Skan} 1239132718Skan 124090075Sobrienstatic void 124190075Sobrienuw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs) 124290075Sobrien{ 124390075Sobrien struct _Unwind_Context orig_context = *context; 124490075Sobrien void *cfa; 124590075Sobrien long i; 124690075Sobrien 1247117395Skan#ifdef EH_RETURN_STACKADJ_RTX 1248117395Skan /* Special handling here: Many machines do not use a frame pointer, 1249117395Skan and track the CFA only through offsets from the stack pointer from 1250117395Skan one frame to the next. In this case, the stack pointer is never 1251117395Skan stored, so it has no saved address in the context. What we do 1252117395Skan have is the CFA from the previous stack frame. 1253117395Skan 1254117395Skan In very special situations (such as unwind info for signal return), 1255117395Skan there may be location expressions that use the stack pointer as well. 1256117395Skan 1257117395Skan Do this conditionally for one frame. This allows the unwind info 1258117395Skan for one frame to save a copy of the stack pointer from the previous 1259117395Skan frame, and be able to use much easier CFA mechanisms to do it. 1260117395Skan Always zap the saved stack pointer value for the next frame; carrying 1261117395Skan the value over from one frame to another doesn't make sense. */ 1262117395Skan 1263132718Skan _Unwind_SpTmp tmp_sp; 1264117395Skan 1265132718Skan if (!_Unwind_GetGRPtr (&orig_context, __builtin_dwarf_sp_column ())) 1266132718Skan _Unwind_SetSpColumn (&orig_context, context->cfa, &tmp_sp); 1267132718Skan _Unwind_SetGRPtr (context, __builtin_dwarf_sp_column (), NULL); 1268117395Skan#endif 1269117395Skan 127090075Sobrien /* Compute this frame's CFA. */ 127190075Sobrien switch (fs->cfa_how) 127290075Sobrien { 127390075Sobrien case CFA_REG_OFFSET: 1274132718Skan cfa = _Unwind_GetPtr (&orig_context, fs->cfa_reg); 127590075Sobrien cfa += fs->cfa_offset; 127690075Sobrien break; 127790075Sobrien 127890075Sobrien case CFA_EXP: 127990075Sobrien { 128090075Sobrien const unsigned char *exp = fs->cfa_exp; 128190075Sobrien _Unwind_Word len; 128290075Sobrien 128390075Sobrien exp = read_uleb128 (exp, &len); 128490075Sobrien cfa = (void *) (_Unwind_Ptr) 1285117395Skan execute_stack_op (exp, exp + len, &orig_context, 0); 128690075Sobrien break; 128790075Sobrien } 128890075Sobrien 128990075Sobrien default: 1290169689Skan gcc_unreachable (); 129190075Sobrien } 129290075Sobrien context->cfa = cfa; 129390075Sobrien 129490075Sobrien /* Compute the addresses of all registers saved in this frame. */ 129590075Sobrien for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i) 129690075Sobrien switch (fs->regs.reg[i].how) 129790075Sobrien { 129890075Sobrien case REG_UNSAVED: 129990075Sobrien break; 1300117395Skan 130190075Sobrien case REG_SAVED_OFFSET: 1302132718Skan _Unwind_SetGRPtr (context, i, 1303132718Skan (void *) (cfa + fs->regs.reg[i].loc.offset)); 130490075Sobrien break; 1305117395Skan 130690075Sobrien case REG_SAVED_REG: 1307169689Skan if (_Unwind_GRByValue (&orig_context, fs->regs.reg[i].loc.reg)) 1308169689Skan _Unwind_SetGRValue (context, i, 1309169689Skan _Unwind_GetGR (&orig_context, 1310169689Skan fs->regs.reg[i].loc.reg)); 1311169689Skan else 1312169689Skan _Unwind_SetGRPtr (context, i, 1313169689Skan _Unwind_GetGRPtr (&orig_context, 1314169689Skan fs->regs.reg[i].loc.reg)); 131590075Sobrien break; 1316117395Skan 131790075Sobrien case REG_SAVED_EXP: 131890075Sobrien { 131990075Sobrien const unsigned char *exp = fs->regs.reg[i].loc.exp; 132090075Sobrien _Unwind_Word len; 132190075Sobrien _Unwind_Ptr val; 132290075Sobrien 132390075Sobrien exp = read_uleb128 (exp, &len); 132490075Sobrien val = execute_stack_op (exp, exp + len, &orig_context, 132590075Sobrien (_Unwind_Ptr) cfa); 1326132718Skan _Unwind_SetGRPtr (context, i, (void *) val); 132790075Sobrien } 132890075Sobrien break; 1329169689Skan 1330169689Skan case REG_SAVED_VAL_OFFSET: 1331169689Skan _Unwind_SetGRValue (context, i, 1332169689Skan (_Unwind_Internal_Ptr) 1333169689Skan (cfa + fs->regs.reg[i].loc.offset)); 1334169689Skan break; 1335169689Skan 1336169689Skan case REG_SAVED_VAL_EXP: 1337169689Skan { 1338169689Skan const unsigned char *exp = fs->regs.reg[i].loc.exp; 1339169689Skan _Unwind_Word len; 1340169689Skan _Unwind_Ptr val; 1341169689Skan 1342169689Skan exp = read_uleb128 (exp, &len); 1343169689Skan val = execute_stack_op (exp, exp + len, &orig_context, 1344169689Skan (_Unwind_Ptr) cfa); 1345169689Skan _Unwind_SetGRValue (context, i, val); 1346169689Skan } 1347169689Skan break; 134890075Sobrien } 1349132718Skan 1350169689Skan _Unwind_SetSignalFrame (context, fs->signal_frame); 1351169689Skan 1352169689Skan#ifdef MD_FROB_UPDATE_CONTEXT 1353132718Skan MD_FROB_UPDATE_CONTEXT (context, fs); 1354169689Skan#endif 135590075Sobrien} 135690075Sobrien 1357117395Skan/* CONTEXT describes the unwind state for a frame, and FS describes the FDE 1358117395Skan of its caller. Update CONTEXT to refer to the caller as well. Note 1359117395Skan that the args_size and lsda members are not updated here, but later in 1360117395Skan uw_frame_state_for. */ 1361117395Skan 136290075Sobrienstatic void 136390075Sobrienuw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) 136490075Sobrien{ 136590075Sobrien uw_update_context_1 (context, fs); 136690075Sobrien 136790075Sobrien /* Compute the return address now, since the return address column 136890075Sobrien can change from frame to frame. */ 136990075Sobrien context->ra = __builtin_extract_return_addr 1370132718Skan (_Unwind_GetPtr (context, fs->retaddr_column)); 137190075Sobrien} 1372169689Skan 1373169689Skanstatic void 1374169689Skanuw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) 1375169689Skan{ 1376169689Skan uw_update_context (context, fs); 1377169689Skan} 137890075Sobrien 137990075Sobrien/* Fill in CONTEXT for top-of-stack. The only valid registers at this 138090075Sobrien level will be the return address and the CFA. */ 1381117395Skan 138290075Sobrien#define uw_init_context(CONTEXT) \ 138390075Sobrien do \ 138490075Sobrien { \ 138590075Sobrien /* Do any necessary initialization to access arbitrary stack frames. \ 138690075Sobrien On the SPARC, this means flushing the register windows. */ \ 138790075Sobrien __builtin_unwind_init (); \ 138890075Sobrien uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (), \ 138990075Sobrien __builtin_return_address (0)); \ 139090075Sobrien } \ 139190075Sobrien while (0) 139290075Sobrien 1393132718Skanstatic inline void 1394132718Skaninit_dwarf_reg_size_table (void) 1395132718Skan{ 1396132718Skan __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table); 1397132718Skan} 1398132718Skan 139990075Sobrienstatic void 140090075Sobrienuw_init_context_1 (struct _Unwind_Context *context, 140190075Sobrien void *outer_cfa, void *outer_ra) 140290075Sobrien{ 140390075Sobrien void *ra = __builtin_extract_return_addr (__builtin_return_address (0)); 140490075Sobrien _Unwind_FrameState fs; 1405132718Skan _Unwind_SpTmp sp_slot; 1406169689Skan _Unwind_Reason_Code code; 140790075Sobrien 140890075Sobrien memset (context, 0, sizeof (struct _Unwind_Context)); 140990075Sobrien context->ra = ra; 1410169689Skan context->flags = EXTENDED_CONTEXT_BIT; 141190075Sobrien 1412169689Skan code = uw_frame_state_for (context, &fs); 1413169689Skan gcc_assert (code == _URC_NO_REASON); 141490075Sobrien 1415132718Skan#if __GTHREADS 1416132718Skan { 1417132718Skan static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT; 1418132718Skan if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0 1419132718Skan || dwarf_reg_size_table[0] == 0) 1420132718Skan init_dwarf_reg_size_table (); 1421132718Skan } 1422132718Skan#else 1423132718Skan if (dwarf_reg_size_table[0] == 0) 1424132718Skan init_dwarf_reg_size_table (); 1425132718Skan#endif 1426132718Skan 142790075Sobrien /* Force the frame state to use the known cfa value. */ 1428132718Skan _Unwind_SetSpColumn (context, outer_cfa, &sp_slot); 142990075Sobrien fs.cfa_how = CFA_REG_OFFSET; 1430117395Skan fs.cfa_reg = __builtin_dwarf_sp_column (); 143190075Sobrien fs.cfa_offset = 0; 143290075Sobrien 143390075Sobrien uw_update_context_1 (context, &fs); 143490075Sobrien 143590075Sobrien /* If the return address column was saved in a register in the 143690075Sobrien initialization context, then we can't see it in the given 143790075Sobrien call frame data. So have the initialization context tell us. */ 143890075Sobrien context->ra = __builtin_extract_return_addr (outer_ra); 143990075Sobrien} 144090075Sobrien 144190075Sobrien 144290075Sobrien/* Install TARGET into CURRENT so that we can return to it. This is a 144390075Sobrien macro because __builtin_eh_return must be invoked in the context of 144490075Sobrien our caller. */ 144590075Sobrien 144690075Sobrien#define uw_install_context(CURRENT, TARGET) \ 144790075Sobrien do \ 144890075Sobrien { \ 144990075Sobrien long offset = uw_install_context_1 ((CURRENT), (TARGET)); \ 145090075Sobrien void *handler = __builtin_frob_return_addr ((TARGET)->ra); \ 145190075Sobrien __builtin_eh_return (offset, handler); \ 145290075Sobrien } \ 145390075Sobrien while (0) 145490075Sobrien 145590075Sobrienstatic long 145690075Sobrienuw_install_context_1 (struct _Unwind_Context *current, 145790075Sobrien struct _Unwind_Context *target) 145890075Sobrien{ 145990075Sobrien long i; 1460169689Skan _Unwind_SpTmp sp_slot; 146190075Sobrien 1462169689Skan /* If the target frame does not have a saved stack pointer, 1463169689Skan then set up the target's CFA. */ 1464169689Skan if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ())) 1465169689Skan _Unwind_SetSpColumn (target, target->cfa, &sp_slot); 1466169689Skan 146790075Sobrien for (i = 0; i < DWARF_FRAME_REGISTERS; ++i) 146890075Sobrien { 146990075Sobrien void *c = current->reg[i]; 147090075Sobrien void *t = target->reg[i]; 1471132718Skan 1472169689Skan gcc_assert (current->by_value[i] == 0); 1473169689Skan if (target->by_value[i] && c) 1474169689Skan { 1475169689Skan _Unwind_Word w; 1476169689Skan _Unwind_Ptr p; 1477169689Skan if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word)) 1478169689Skan { 1479169689Skan w = (_Unwind_Internal_Ptr) t; 1480169689Skan memcpy (c, &w, sizeof (_Unwind_Word)); 1481169689Skan } 1482169689Skan else 1483169689Skan { 1484169689Skan gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr)); 1485169689Skan p = (_Unwind_Internal_Ptr) t; 1486169689Skan memcpy (c, &p, sizeof (_Unwind_Ptr)); 1487169689Skan } 1488169689Skan } 1489169689Skan else if (t && c && t != c) 149090075Sobrien memcpy (c, t, dwarf_reg_size_table[i]); 149190075Sobrien } 149290075Sobrien 1493169689Skan /* If the current frame doesn't have a saved stack pointer, then we 1494169689Skan need to rely on EH_RETURN_STACKADJ_RTX to get our target stack 1495169689Skan pointer value reloaded. */ 1496169689Skan if (!_Unwind_GetGRPtr (current, __builtin_dwarf_sp_column ())) 1497169689Skan { 1498169689Skan void *target_cfa; 1499117395Skan 1500132718Skan target_cfa = _Unwind_GetPtr (target, __builtin_dwarf_sp_column ()); 1501117395Skan 1502169689Skan /* We adjust SP by the difference between CURRENT and TARGET's CFA. */ 1503169689Skan if (STACK_GROWS_DOWNWARD) 1504169689Skan return target_cfa - current->cfa + target->args_size; 1505169689Skan else 1506169689Skan return current->cfa - target_cfa - target->args_size; 1507169689Skan } 1508117395Skan return 0; 150990075Sobrien} 151090075Sobrien 151190075Sobrienstatic inline _Unwind_Ptr 151290075Sobrienuw_identify_context (struct _Unwind_Context *context) 151390075Sobrien{ 151490075Sobrien return _Unwind_GetIP (context); 151590075Sobrien} 151690075Sobrien 151790075Sobrien 151890075Sobrien#include "unwind.inc" 151990075Sobrien 1520146895Skan#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS) 1521146895Skanalias (_Unwind_Backtrace); 1522146895Skanalias (_Unwind_DeleteException); 1523146895Skanalias (_Unwind_FindEnclosingFunction); 1524146895Skanalias (_Unwind_ForcedUnwind); 1525146895Skanalias (_Unwind_GetDataRelBase); 1526146895Skanalias (_Unwind_GetTextRelBase); 1527146895Skanalias (_Unwind_GetCFA); 1528146895Skanalias (_Unwind_GetGR); 1529146895Skanalias (_Unwind_GetIP); 1530146895Skanalias (_Unwind_GetLanguageSpecificData); 1531146895Skanalias (_Unwind_GetRegionStart); 1532146895Skanalias (_Unwind_RaiseException); 1533146895Skanalias (_Unwind_Resume); 1534146895Skanalias (_Unwind_Resume_or_Rethrow); 1535146895Skanalias (_Unwind_SetGR); 1536146895Skanalias (_Unwind_SetIP); 1537146895Skan#endif 1538146895Skan 153990075Sobrien#endif /* !USING_SJLJ_EXCEPTIONS */ 1540