unwind-sjlj.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. /* SJLJ exception handling and frame unwind runtime interface routines.
  2. Copyright (C) 1997-2015 Free Software Foundation, Inc.
  3. This file is part of GCC.
  4. GCC is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3, or (at your option)
  7. any later version.
  8. GCC is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  11. License for more details.
  12. Under Section 7 of GPL version 3, you are granted additional
  13. permissions described in the GCC Runtime Library Exception, version
  14. 3.1, as published by the Free Software Foundation.
  15. You should have received a copy of the GNU General Public License and
  16. a copy of the GCC Runtime Library Exception along with this program;
  17. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  18. <http://www.gnu.org/licenses/>. */
  19. #include "tconfig.h"
  20. #include "tsystem.h"
  21. #include "coretypes.h"
  22. #include "tm.h"
  23. #include "libgcc_tm.h"
  24. #include "unwind.h"
  25. #include "gthr.h"
  26. #ifdef __USING_SJLJ_EXCEPTIONS__
  27. #ifdef __LIBGCC_DONT_USE_BUILTIN_SETJMP__
  28. #ifndef inhibit_libc
  29. #include <setjmp.h>
  30. #else
  31. typedef void *jmp_buf[__LIBGCC_JMP_BUF_SIZE__];
  32. extern void longjmp(jmp_buf, int) __attribute__((noreturn));
  33. #endif
  34. #else
  35. #define longjmp __builtin_longjmp
  36. #endif
  37. /* The setjmp side is dealt with in the except.c file. */
  38. #undef setjmp
  39. #define setjmp setjmp_should_not_be_used_in_this_file
  40. /* This structure is allocated on the stack of the target function.
  41. This must match the definition created in except.c:init_eh. */
  42. struct SjLj_Function_Context
  43. {
  44. /* This is the chain through all registered contexts. It is
  45. filled in by _Unwind_SjLj_Register. */
  46. struct SjLj_Function_Context *prev;
  47. /* This is assigned in by the target function before every call
  48. to the index of the call site in the lsda. It is assigned by
  49. the personality routine to the landing pad index. */
  50. int call_site;
  51. /* This is how data is returned from the personality routine to
  52. the target function's handler. */
  53. _Unwind_Word data[4];
  54. /* These are filled in once by the target function before any
  55. exceptions are expected to be handled. */
  56. _Unwind_Personality_Fn personality;
  57. void *lsda;
  58. #ifdef __LIBGCC_DONT_USE_BUILTIN_SETJMP__
  59. /* We don't know what sort of alignment requirements the system
  60. jmp_buf has. We over estimated in except.c, and now we have
  61. to match that here just in case the system *didn't* have more
  62. restrictive requirements. */
  63. jmp_buf jbuf __attribute__((aligned));
  64. #else
  65. void *jbuf[];
  66. #endif
  67. };
  68. struct _Unwind_Context
  69. {
  70. struct SjLj_Function_Context *fc;
  71. };
  72. typedef struct
  73. {
  74. _Unwind_Personality_Fn personality;
  75. } _Unwind_FrameState;
  76. /* Manage the chain of registered function contexts. */
  77. /* Single threaded fallback chain. */
  78. static struct SjLj_Function_Context *fc_static;
  79. #if __GTHREADS
  80. static __gthread_key_t fc_key;
  81. static int use_fc_key = -1;
  82. static void
  83. fc_key_init (void)
  84. {
  85. use_fc_key = __gthread_key_create (&fc_key, 0) == 0;
  86. }
  87. static void
  88. fc_key_init_once (void)
  89. {
  90. static __gthread_once_t once = __GTHREAD_ONCE_INIT;
  91. if (__gthread_once (&once, fc_key_init) != 0 || use_fc_key < 0)
  92. use_fc_key = 0;
  93. }
  94. #endif
  95. void
  96. _Unwind_SjLj_Register (struct SjLj_Function_Context *fc)
  97. {
  98. #if __GTHREADS
  99. if (use_fc_key < 0)
  100. fc_key_init_once ();
  101. if (use_fc_key)
  102. {
  103. fc->prev = __gthread_getspecific (fc_key);
  104. __gthread_setspecific (fc_key, fc);
  105. }
  106. else
  107. #endif
  108. {
  109. fc->prev = fc_static;
  110. fc_static = fc;
  111. }
  112. }
  113. static inline struct SjLj_Function_Context *
  114. _Unwind_SjLj_GetContext (void)
  115. {
  116. #if __GTHREADS
  117. if (use_fc_key < 0)
  118. fc_key_init_once ();
  119. if (use_fc_key)
  120. return __gthread_getspecific (fc_key);
  121. #endif
  122. return fc_static;
  123. }
  124. static inline void
  125. _Unwind_SjLj_SetContext (struct SjLj_Function_Context *fc)
  126. {
  127. #if __GTHREADS
  128. if (use_fc_key < 0)
  129. fc_key_init_once ();
  130. if (use_fc_key)
  131. __gthread_setspecific (fc_key, fc);
  132. else
  133. #endif
  134. fc_static = fc;
  135. }
  136. void
  137. _Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc)
  138. {
  139. _Unwind_SjLj_SetContext (fc->prev);
  140. }
  141. /* Get/set the return data value at INDEX in CONTEXT. */
  142. _Unwind_Word
  143. _Unwind_GetGR (struct _Unwind_Context *context, int index)
  144. {
  145. return context->fc->data[index];
  146. }
  147. /* Get the value of the CFA as saved in CONTEXT. */
  148. _Unwind_Word
  149. _Unwind_GetCFA (struct _Unwind_Context *context __attribute__((unused)))
  150. {
  151. /* ??? Ideally __builtin_setjmp places the CFA in the jmpbuf. */
  152. #ifndef __LIBGCC_DONT_USE_BUILTIN_SETJMP__
  153. /* This is a crude imitation of the CFA: the saved stack pointer.
  154. This is roughly the CFA of the frame before CONTEXT. When using the
  155. DWARF-2 unwinder _Unwind_GetCFA returns the CFA of the frame described
  156. by CONTEXT instead; but for DWARF-2 the cleanups associated with
  157. CONTEXT have already been run, and for SJLJ they have not yet been. */
  158. if (context->fc != NULL)
  159. return (_Unwind_Word) context->fc->jbuf[2];
  160. #endif
  161. /* Otherwise we're out of luck for now. */
  162. return (_Unwind_Word) 0;
  163. }
  164. void
  165. _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
  166. {
  167. context->fc->data[index] = val;
  168. }
  169. /* Get the call-site index as saved in CONTEXT. */
  170. _Unwind_Ptr
  171. _Unwind_GetIP (struct _Unwind_Context *context)
  172. {
  173. return context->fc->call_site + 1;
  174. }
  175. _Unwind_Ptr
  176. _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
  177. {
  178. *ip_before_insn = 0;
  179. if (context->fc != NULL)
  180. return context->fc->call_site + 1;
  181. else
  182. return 0;
  183. }
  184. /* Set the return landing pad index in CONTEXT. */
  185. void
  186. _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
  187. {
  188. context->fc->call_site = val - 1;
  189. }
  190. void *
  191. _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
  192. {
  193. return context->fc->lsda;
  194. }
  195. _Unwind_Ptr
  196. _Unwind_GetRegionStart (struct _Unwind_Context *context __attribute__((unused)) )
  197. {
  198. return 0;
  199. }
  200. void *
  201. _Unwind_FindEnclosingFunction (void *pc __attribute__((unused)))
  202. {
  203. return NULL;
  204. }
  205. #ifndef __ia64__
  206. _Unwind_Ptr
  207. _Unwind_GetDataRelBase (struct _Unwind_Context *context __attribute__((unused)) )
  208. {
  209. return 0;
  210. }
  211. _Unwind_Ptr
  212. _Unwind_GetTextRelBase (struct _Unwind_Context *context __attribute__((unused)) )
  213. {
  214. return 0;
  215. }
  216. #endif
  217. static inline _Unwind_Reason_Code
  218. uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
  219. {
  220. if (context->fc == NULL)
  221. {
  222. fs->personality = NULL;
  223. return _URC_END_OF_STACK;
  224. }
  225. else
  226. {
  227. fs->personality = context->fc->personality;
  228. return _URC_NO_REASON;
  229. }
  230. }
  231. static inline void
  232. uw_update_context (struct _Unwind_Context *context,
  233. _Unwind_FrameState *fs __attribute__((unused)) )
  234. {
  235. context->fc = context->fc->prev;
  236. }
  237. static void
  238. uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
  239. {
  240. _Unwind_SjLj_Unregister (context->fc);
  241. uw_update_context (context, fs);
  242. }
  243. static inline void
  244. uw_init_context (struct _Unwind_Context *context)
  245. {
  246. context->fc = _Unwind_SjLj_GetContext ();
  247. }
  248. static void __attribute__((noreturn))
  249. uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
  250. struct _Unwind_Context *target)
  251. {
  252. _Unwind_SjLj_SetContext (target->fc);
  253. longjmp (target->fc->jbuf, 1);
  254. }
  255. static inline _Unwind_Ptr
  256. uw_identify_context (struct _Unwind_Context *context)
  257. {
  258. return (_Unwind_Ptr) context->fc;
  259. }
  260. /* Play games with unwind symbols so that we can have call frame
  261. and sjlj symbols in the same shared library. Not that you can
  262. use them simultaneously... */
  263. #define _Unwind_RaiseException _Unwind_SjLj_RaiseException
  264. #define _Unwind_ForcedUnwind _Unwind_SjLj_ForcedUnwind
  265. #define _Unwind_Resume _Unwind_SjLj_Resume
  266. #define _Unwind_Resume_or_Rethrow _Unwind_SjLj_Resume_or_Rethrow
  267. #include "unwind.inc"
  268. #endif /* USING_SJLJ_EXCEPTIONS */