1252330Sjeff/* SJLJ exception handling and frame unwind runtime interface routines. 2252330Sjeff Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 3252330Sjeff Free Software Foundation, Inc. 4252330Sjeff 5252330Sjeff This file is part of GCC. 6252330Sjeff 7252330Sjeff GCC is free software; you can redistribute it and/or modify it 8252330Sjeff under the terms of the GNU General Public License as published by 9252330Sjeff the Free Software Foundation; either version 2, or (at your option) 10252330Sjeff any later version. 11252330Sjeff 12252330Sjeff In addition to the permissions in the GNU General Public License, the 13252330Sjeff Free Software Foundation gives you unlimited permission to link the 14252330Sjeff compiled version of this file into combinations with other programs, 15252330Sjeff and to distribute those combinations without any restriction coming 16252330Sjeff from the use of this file. (The General Public License restrictions 17252330Sjeff do apply in other respects; for example, they cover modification of 18252330Sjeff the file, and distribution when not linked into a combined 19252330Sjeff executable.) 20252330Sjeff 21252330Sjeff GCC is distributed in the hope that it will be useful, but WITHOUT 22252330Sjeff ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 23252330Sjeff or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 24252330Sjeff License for more details. 25252330Sjeff 26252330Sjeff You should have received a copy of the GNU General Public License 27252330Sjeff along with GCC; see the file COPYING. If not, write to the Free 28252330Sjeff Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 29252330Sjeff 02110-1301, USA. */ 30252330Sjeff 31252330Sjeff#include "tconfig.h" 32252330Sjeff#include "tsystem.h" 33252330Sjeff#include "coretypes.h" 34252330Sjeff#include "tm.h" 35252330Sjeff#include "unwind.h" 36252330Sjeff#include "gthr.h" 37252330Sjeff 38252330Sjeff#ifdef __USING_SJLJ_EXCEPTIONS__ 39252330Sjeff 40252330Sjeff#ifdef DONT_USE_BUILTIN_SETJMP 41252330Sjeff#ifndef inhibit_libc 42252330Sjeff#include <setjmp.h> 43252330Sjeff#else 44252330Sjefftypedef void *jmp_buf[JMP_BUF_SIZE]; 45252330Sjeffextern void longjmp(jmp_buf, int) __attribute__((noreturn)); 46252330Sjeff#endif 47252330Sjeff#else 48252330Sjeff#define longjmp __builtin_longjmp 49252330Sjeff#endif 50252330Sjeff 51252330Sjeff/* The setjmp side is dealt with in the except.c file. */ 52252330Sjeff#undef setjmp 53252330Sjeff#define setjmp setjmp_should_not_be_used_in_this_file 54252330Sjeff 55252330Sjeff 56252330Sjeff/* This structure is allocated on the stack of the target function. 57252330Sjeff This must match the definition created in except.c:init_eh. */ 58252330Sjeffstruct SjLj_Function_Context 59252330Sjeff{ 60254307Sjeff /* This is the chain through all registered contexts. It is 61254307Sjeff filled in by _Unwind_SjLj_Register. */ 62252330Sjeff struct SjLj_Function_Context *prev; 63252330Sjeff 64252330Sjeff /* This is assigned in by the target function before every call 65252330Sjeff to the index of the call site in the lsda. It is assigned by 66254025Sjeff the personality routine to the landing pad index. */ 67252330Sjeff int call_site; 68252330Sjeff 69252330Sjeff /* This is how data is returned from the personality routine to 70252330Sjeff the target function's handler. */ 71252330Sjeff _Unwind_Word data[4]; 72252330Sjeff 73252330Sjeff /* These are filled in once by the target function before any 74252330Sjeff exceptions are expected to be handled. */ 75252330Sjeff _Unwind_Personality_Fn personality; 76252330Sjeff void *lsda; 77252330Sjeff 78252330Sjeff#ifdef DONT_USE_BUILTIN_SETJMP 79252330Sjeff /* We don't know what sort of alignment requirements the system 80252330Sjeff jmp_buf has. We over estimated in except.c, and now we have 81252330Sjeff to match that here just in case the system *didn't* have more 82252330Sjeff restrictive requirements. */ 83252330Sjeff jmp_buf jbuf __attribute__((aligned)); 84252330Sjeff#else 85252330Sjeff void *jbuf[]; 86252330Sjeff#endif 87252330Sjeff}; 88252330Sjeff 89252330Sjeffstruct _Unwind_Context 90252330Sjeff{ 91252330Sjeff struct SjLj_Function_Context *fc; 92252330Sjeff}; 93252330Sjeff 94252330Sjefftypedef struct 95252330Sjeff{ 96252330Sjeff _Unwind_Personality_Fn personality; 97252330Sjeff} _Unwind_FrameState; 98252330Sjeff 99252330Sjeff 100252330Sjeff/* Manage the chain of registered function contexts. */ 101252330Sjeff 102252330Sjeff/* Single threaded fallback chain. */ 103252330Sjeffstatic struct SjLj_Function_Context *fc_static; 104252330Sjeff 105252330Sjeff#if __GTHREADS 106252330Sjeffstatic __gthread_key_t fc_key; 107252330Sjeffstatic int use_fc_key = -1; 108252330Sjeff 109252330Sjeffstatic void 110252330Sjefffc_key_init (void) 111252330Sjeff{ 112252330Sjeff use_fc_key = __gthread_key_create (&fc_key, 0) == 0; 113252330Sjeff} 114252330Sjeff 115252330Sjeffstatic void 116252330Sjefffc_key_init_once (void) 117252330Sjeff{ 118252330Sjeff static __gthread_once_t once = __GTHREAD_ONCE_INIT; 119252330Sjeff if (__gthread_once (&once, fc_key_init) != 0 || use_fc_key < 0) 120252330Sjeff use_fc_key = 0; 121252330Sjeff} 122252330Sjeff#endif 123252330Sjeff 124252330Sjeffvoid 125252330Sjeff_Unwind_SjLj_Register (struct SjLj_Function_Context *fc) 126252330Sjeff{ 127252330Sjeff#if __GTHREADS 128252330Sjeff if (use_fc_key < 0) 129252330Sjeff fc_key_init_once (); 130252330Sjeff 131252330Sjeff if (use_fc_key) 132252330Sjeff { 133252330Sjeff fc->prev = __gthread_getspecific (fc_key); 134252330Sjeff __gthread_setspecific (fc_key, fc); 135252330Sjeff } 136252330Sjeff else 137252330Sjeff#endif 138252330Sjeff { 139252330Sjeff fc->prev = fc_static; 140252330Sjeff fc_static = fc; 141252330Sjeff } 142252330Sjeff} 143252330Sjeff 144252330Sjeffstatic inline struct SjLj_Function_Context * 145252330Sjeff_Unwind_SjLj_GetContext (void) 146252330Sjeff{ 147252330Sjeff#if __GTHREADS 148252330Sjeff if (use_fc_key < 0) 149252330Sjeff fc_key_init_once (); 150252330Sjeff 151252330Sjeff if (use_fc_key) 152252330Sjeff return __gthread_getspecific (fc_key); 153252330Sjeff#endif 154252330Sjeff return fc_static; 155252330Sjeff} 156252330Sjeff 157252330Sjeffstatic inline void 158252330Sjeff_Unwind_SjLj_SetContext (struct SjLj_Function_Context *fc) 159252330Sjeff{ 160252330Sjeff#if __GTHREADS 161252330Sjeff if (use_fc_key < 0) 162252330Sjeff fc_key_init_once (); 163252330Sjeff 164252330Sjeff if (use_fc_key) 165252330Sjeff __gthread_setspecific (fc_key, fc); 166252330Sjeff else 167252330Sjeff#endif 168252330Sjeff fc_static = fc; 169252330Sjeff} 170252330Sjeff 171252330Sjeffvoid 172252330Sjeff_Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc) 173252330Sjeff{ 174252330Sjeff _Unwind_SjLj_SetContext (fc->prev); 175252330Sjeff} 176252330Sjeff 177252330Sjeff 178252330Sjeff/* Get/set the return data value at INDEX in CONTEXT. */ 179252330Sjeff 180252330Sjeff_Unwind_Word 181252330Sjeff_Unwind_GetGR (struct _Unwind_Context *context, int index) 182252330Sjeff{ 183252330Sjeff return context->fc->data[index]; 184252330Sjeff} 185252330Sjeff 186252330Sjeff/* Get the value of the CFA as saved in CONTEXT. */ 187252330Sjeff 188252330Sjeff_Unwind_Word 189252330Sjeff_Unwind_GetCFA (struct _Unwind_Context *context __attribute__((unused))) 190252330Sjeff{ 191252330Sjeff /* ??? Ideally __builtin_setjmp places the CFA in the jmpbuf. */ 192252330Sjeff 193252330Sjeff#ifndef DONT_USE_BUILTIN_SETJMP 194252330Sjeff /* This is a crude imitation of the CFA: the saved stack pointer. 195252330Sjeff This is roughly the CFA of the frame before CONTEXT. When using the 196252330Sjeff DWARF-2 unwinder _Unwind_GetCFA returns the CFA of the frame described 197252330Sjeff by CONTEXT instead; but for DWARF-2 the cleanups associated with 198252330Sjeff CONTEXT have already been run, and for SJLJ they have not yet been. */ 199252330Sjeff if (context->fc != NULL) 200252330Sjeff return (_Unwind_Word) context->fc->jbuf[2]; 201252330Sjeff#endif 202252330Sjeff 203252330Sjeff /* Otherwise we're out of luck for now. */ 204252330Sjeff return (_Unwind_Word) 0; 205252330Sjeff} 206252330Sjeff 207252330Sjeffvoid 208252330Sjeff_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val) 209252330Sjeff{ 210252330Sjeff context->fc->data[index] = val; 211252330Sjeff} 212252330Sjeff 213252330Sjeff/* Get the call-site index as saved in CONTEXT. */ 214252330Sjeff 215252330Sjeff_Unwind_Ptr 216252330Sjeff_Unwind_GetIP (struct _Unwind_Context *context) 217252330Sjeff{ 218252330Sjeff return context->fc->call_site + 1; 219254025Sjeff} 220254025Sjeff 221252330Sjeff_Unwind_Ptr 222252330Sjeff_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn) 223254025Sjeff{ 224254025Sjeff *ip_before_insn = 0; 225252330Sjeff return context->fc->call_site + 1; 226252330Sjeff} 227252330Sjeff 228254307Sjeff/* Set the return landing pad index in CONTEXT. */ 229254307Sjeff 230254307Sjeffvoid 231254307Sjeff_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val) 232254307Sjeff{ 233252330Sjeff context->fc->call_site = val - 1; 234252330Sjeff} 235252330Sjeff 236252330Sjeffvoid * 237252330Sjeff_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context) 238252330Sjeff{ 239252330Sjeff return context->fc->lsda; 240252330Sjeff} 241252330Sjeff 242252330Sjeff_Unwind_Ptr 243252330Sjeff_Unwind_GetRegionStart (struct _Unwind_Context *context __attribute__((unused)) ) 244252330Sjeff{ 245252330Sjeff return 0; 246254025Sjeff} 247254025Sjeff 248254025Sjeffvoid * 249254025Sjeff_Unwind_FindEnclosingFunction (void *pc __attribute__((unused))) 250254025Sjeff{ 251254025Sjeff return NULL; 252254025Sjeff} 253254025Sjeff 254252330Sjeff#ifndef __ia64__ 255252330Sjeff_Unwind_Ptr 256252330Sjeff_Unwind_GetDataRelBase (struct _Unwind_Context *context __attribute__((unused)) ) 257252330Sjeff{ 258252330Sjeff return 0; 259252330Sjeff} 260252330Sjeff 261252330Sjeff_Unwind_Ptr 262252330Sjeff_Unwind_GetTextRelBase (struct _Unwind_Context *context __attribute__((unused)) ) 263252330Sjeff{ 264252330Sjeff return 0; 265252330Sjeff} 266252330Sjeff#endif 267252330Sjeff 268252330Sjeffstatic inline _Unwind_Reason_Code 269252330Sjeffuw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) 270252330Sjeff{ 271252330Sjeff if (context->fc == NULL) 272252330Sjeff { 273252330Sjeff fs->personality = NULL; 274252330Sjeff return _URC_END_OF_STACK; 275252330Sjeff } 276252330Sjeff else 277252330Sjeff { 278252330Sjeff fs->personality = context->fc->personality; 279252330Sjeff return _URC_NO_REASON; 280252330Sjeff } 281252330Sjeff} 282252330Sjeff 283252330Sjeffstatic inline void 284252330Sjeffuw_update_context (struct _Unwind_Context *context, 285252330Sjeff _Unwind_FrameState *fs __attribute__((unused)) ) 286252330Sjeff{ 287252330Sjeff context->fc = context->fc->prev; 288252330Sjeff} 289252330Sjeff 290252330Sjeffstatic void 291252330Sjeffuw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) 292252330Sjeff{ 293252330Sjeff _Unwind_SjLj_Unregister (context->fc); 294252330Sjeff uw_update_context (context, fs); 295252330Sjeff} 296252330Sjeff 297252330Sjeffstatic inline void 298252330Sjeffuw_init_context (struct _Unwind_Context *context) 299252330Sjeff{ 300252330Sjeff context->fc = _Unwind_SjLj_GetContext (); 301252330Sjeff} 302252330Sjeff 303252330Sjeffstatic void __attribute__((noreturn)) 304252330Sjeffuw_install_context (struct _Unwind_Context *current __attribute__((unused)), 305252330Sjeff struct _Unwind_Context *target) 306252330Sjeff{ 307252330Sjeff _Unwind_SjLj_SetContext (target->fc); 308252330Sjeff longjmp (target->fc->jbuf, 1); 309252330Sjeff} 310252330Sjeff 311252330Sjeffstatic inline _Unwind_Ptr 312252330Sjeffuw_identify_context (struct _Unwind_Context *context) 313252330Sjeff{ 314252330Sjeff return (_Unwind_Ptr) context->fc; 315252330Sjeff} 316252330Sjeff 317252330Sjeff 318252330Sjeff/* Play games with unwind symbols so that we can have call frame 319252330Sjeff and sjlj symbols in the same shared library. Not that you can 320252330Sjeff use them simultaneously... */ 321252330Sjeff#define _Unwind_RaiseException _Unwind_SjLj_RaiseException 322252330Sjeff#define _Unwind_ForcedUnwind _Unwind_SjLj_ForcedUnwind 323252330Sjeff#define _Unwind_Resume _Unwind_SjLj_Resume 324252330Sjeff#define _Unwind_Resume_or_Rethrow _Unwind_SjLj_Resume_or_Rethrow 325252330Sjeff 326252330Sjeff#include "unwind.inc" 327252330Sjeff 328252330Sjeff#endif /* USING_SJLJ_EXCEPTIONS */ 329252330Sjeff