1*404b540aSrobert // -*- C++ -*- The GNU C++ exception personality routine.
2*404b540aSrobert // Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
3*404b540aSrobert //
4*404b540aSrobert // This file is part of GCC.
5*404b540aSrobert //
6*404b540aSrobert // GCC is free software; you can redistribute it and/or modify
7*404b540aSrobert // it under the terms of the GNU General Public License as published by
8*404b540aSrobert // the Free Software Foundation; either version 2, or (at your option)
9*404b540aSrobert // any later version.
10*404b540aSrobert //
11*404b540aSrobert // GCC is distributed in the hope that it will be useful,
12*404b540aSrobert // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*404b540aSrobert // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*404b540aSrobert // GNU General Public License for more details.
15*404b540aSrobert //
16*404b540aSrobert // You should have received a copy of the GNU General Public License
17*404b540aSrobert // along with GCC; see the file COPYING. If not, write to
18*404b540aSrobert // the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19*404b540aSrobert // Boston, MA 02110-1301, USA.
20*404b540aSrobert
21*404b540aSrobert // As a special exception, you may use this file as part of a free software
22*404b540aSrobert // library without restriction. Specifically, if other files instantiate
23*404b540aSrobert // templates or use macros or inline functions from this file, or you compile
24*404b540aSrobert // this file and link it with other files to produce an executable, this
25*404b540aSrobert // file does not by itself cause the resulting executable to be covered by
26*404b540aSrobert // the GNU General Public License. This exception does not however
27*404b540aSrobert // invalidate any other reasons why the executable file might be covered by
28*404b540aSrobert // the GNU General Public License.
29*404b540aSrobert
30*404b540aSrobert #include <bits/c++config.h>
31*404b540aSrobert #include <cstdlib>
32*404b540aSrobert #include <exception_defines.h>
33*404b540aSrobert #include "unwind-cxx.h"
34*404b540aSrobert
35*404b540aSrobert using namespace __cxxabiv1;
36*404b540aSrobert
37*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
38*404b540aSrobert #define NO_SIZE_OF_ENCODED_VALUE
39*404b540aSrobert #endif
40*404b540aSrobert
41*404b540aSrobert #include "unwind-pe.h"
42*404b540aSrobert
43*404b540aSrobert
44*404b540aSrobert struct lsda_header_info
45*404b540aSrobert {
46*404b540aSrobert _Unwind_Ptr Start;
47*404b540aSrobert _Unwind_Ptr LPStart;
48*404b540aSrobert _Unwind_Ptr ttype_base;
49*404b540aSrobert const unsigned char *TType;
50*404b540aSrobert const unsigned char *action_table;
51*404b540aSrobert unsigned char ttype_encoding;
52*404b540aSrobert unsigned char call_site_encoding;
53*404b540aSrobert };
54*404b540aSrobert
55*404b540aSrobert static const unsigned char *
parse_lsda_header(_Unwind_Context * context,const unsigned char * p,lsda_header_info * info)56*404b540aSrobert parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
57*404b540aSrobert lsda_header_info *info)
58*404b540aSrobert {
59*404b540aSrobert _Unwind_Word tmp;
60*404b540aSrobert unsigned char lpstart_encoding;
61*404b540aSrobert
62*404b540aSrobert info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
63*404b540aSrobert
64*404b540aSrobert // Find @LPStart, the base to which landing pad offsets are relative.
65*404b540aSrobert lpstart_encoding = *p++;
66*404b540aSrobert if (lpstart_encoding != DW_EH_PE_omit)
67*404b540aSrobert p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
68*404b540aSrobert else
69*404b540aSrobert info->LPStart = info->Start;
70*404b540aSrobert
71*404b540aSrobert // Find @TType, the base of the handler and exception spec type data.
72*404b540aSrobert info->ttype_encoding = *p++;
73*404b540aSrobert if (info->ttype_encoding != DW_EH_PE_omit)
74*404b540aSrobert {
75*404b540aSrobert p = read_uleb128 (p, &tmp);
76*404b540aSrobert info->TType = p + tmp;
77*404b540aSrobert }
78*404b540aSrobert else
79*404b540aSrobert info->TType = 0;
80*404b540aSrobert
81*404b540aSrobert // The encoding and length of the call-site table; the action table
82*404b540aSrobert // immediately follows.
83*404b540aSrobert info->call_site_encoding = *p++;
84*404b540aSrobert p = read_uleb128 (p, &tmp);
85*404b540aSrobert info->action_table = p + tmp;
86*404b540aSrobert
87*404b540aSrobert return p;
88*404b540aSrobert }
89*404b540aSrobert
90*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
91*404b540aSrobert
92*404b540aSrobert // Return an element from a type table.
93*404b540aSrobert
94*404b540aSrobert static const std::type_info*
get_ttype_entry(lsda_header_info * info,_Unwind_Word i)95*404b540aSrobert get_ttype_entry(lsda_header_info* info, _Unwind_Word i)
96*404b540aSrobert {
97*404b540aSrobert _Unwind_Ptr ptr;
98*404b540aSrobert
99*404b540aSrobert ptr = (_Unwind_Ptr) (info->TType - (i * 4));
100*404b540aSrobert ptr = _Unwind_decode_target2(ptr);
101*404b540aSrobert
102*404b540aSrobert return reinterpret_cast<const std::type_info *>(ptr);
103*404b540aSrobert }
104*404b540aSrobert
105*404b540aSrobert // The ABI provides a routine for matching exception object types.
106*404b540aSrobert typedef _Unwind_Control_Block _throw_typet;
107*404b540aSrobert #define get_adjusted_ptr(catch_type, throw_type, thrown_ptr_p) \
108*404b540aSrobert (__cxa_type_match (throw_type, catch_type, false, thrown_ptr_p) \
109*404b540aSrobert != ctm_failed)
110*404b540aSrobert
111*404b540aSrobert // Return true if THROW_TYPE matches one if the filter types.
112*404b540aSrobert
113*404b540aSrobert static bool
check_exception_spec(lsda_header_info * info,_throw_typet * throw_type,void * thrown_ptr,_Unwind_Sword filter_value)114*404b540aSrobert check_exception_spec(lsda_header_info* info, _throw_typet* throw_type,
115*404b540aSrobert void* thrown_ptr, _Unwind_Sword filter_value)
116*404b540aSrobert {
117*404b540aSrobert const _Unwind_Word* e = ((const _Unwind_Word*) info->TType)
118*404b540aSrobert - filter_value - 1;
119*404b540aSrobert
120*404b540aSrobert while (1)
121*404b540aSrobert {
122*404b540aSrobert const std::type_info* catch_type;
123*404b540aSrobert _Unwind_Word tmp;
124*404b540aSrobert
125*404b540aSrobert tmp = *e;
126*404b540aSrobert
127*404b540aSrobert // Zero signals the end of the list. If we've not found
128*404b540aSrobert // a match by now, then we've failed the specification.
129*404b540aSrobert if (tmp == 0)
130*404b540aSrobert return false;
131*404b540aSrobert
132*404b540aSrobert tmp = _Unwind_decode_target2((_Unwind_Word) e);
133*404b540aSrobert
134*404b540aSrobert // Match a ttype entry.
135*404b540aSrobert catch_type = reinterpret_cast<const std::type_info*>(tmp);
136*404b540aSrobert
137*404b540aSrobert // ??? There is currently no way to ask the RTTI code about the
138*404b540aSrobert // relationship between two types without reference to a specific
139*404b540aSrobert // object. There should be; then we wouldn't need to mess with
140*404b540aSrobert // thrown_ptr here.
141*404b540aSrobert if (get_adjusted_ptr(catch_type, throw_type, &thrown_ptr))
142*404b540aSrobert return true;
143*404b540aSrobert
144*404b540aSrobert // Advance to the next entry.
145*404b540aSrobert e++;
146*404b540aSrobert }
147*404b540aSrobert }
148*404b540aSrobert
149*404b540aSrobert
150*404b540aSrobert // Save stage1 handler information in the exception object
151*404b540aSrobert
152*404b540aSrobert static inline void
save_caught_exception(struct _Unwind_Exception * ue_header,struct _Unwind_Context * context,void * thrown_ptr,int handler_switch_value,const unsigned char * language_specific_data,_Unwind_Ptr landing_pad,const unsigned char * action_record)153*404b540aSrobert save_caught_exception(struct _Unwind_Exception* ue_header,
154*404b540aSrobert struct _Unwind_Context* context,
155*404b540aSrobert void* thrown_ptr,
156*404b540aSrobert int handler_switch_value,
157*404b540aSrobert const unsigned char* language_specific_data,
158*404b540aSrobert _Unwind_Ptr landing_pad,
159*404b540aSrobert const unsigned char* action_record
160*404b540aSrobert __attribute__((__unused__)))
161*404b540aSrobert {
162*404b540aSrobert ue_header->barrier_cache.sp = _Unwind_GetGR(context, 13);
163*404b540aSrobert ue_header->barrier_cache.bitpattern[0] = (_uw) thrown_ptr;
164*404b540aSrobert ue_header->barrier_cache.bitpattern[1]
165*404b540aSrobert = (_uw) handler_switch_value;
166*404b540aSrobert ue_header->barrier_cache.bitpattern[2]
167*404b540aSrobert = (_uw) language_specific_data;
168*404b540aSrobert ue_header->barrier_cache.bitpattern[3] = (_uw) landing_pad;
169*404b540aSrobert }
170*404b540aSrobert
171*404b540aSrobert
172*404b540aSrobert // Restore the catch handler data saved during phase1.
173*404b540aSrobert
174*404b540aSrobert static inline void
restore_caught_exception(struct _Unwind_Exception * ue_header,int & handler_switch_value,const unsigned char * & language_specific_data,_Unwind_Ptr & landing_pad)175*404b540aSrobert restore_caught_exception(struct _Unwind_Exception* ue_header,
176*404b540aSrobert int& handler_switch_value,
177*404b540aSrobert const unsigned char*& language_specific_data,
178*404b540aSrobert _Unwind_Ptr& landing_pad)
179*404b540aSrobert {
180*404b540aSrobert handler_switch_value = (int) ue_header->barrier_cache.bitpattern[1];
181*404b540aSrobert language_specific_data =
182*404b540aSrobert (const unsigned char*) ue_header->barrier_cache.bitpattern[2];
183*404b540aSrobert landing_pad = (_Unwind_Ptr) ue_header->barrier_cache.bitpattern[3];
184*404b540aSrobert }
185*404b540aSrobert
186*404b540aSrobert #define CONTINUE_UNWINDING \
187*404b540aSrobert do \
188*404b540aSrobert { \
189*404b540aSrobert if (__gnu_unwind_frame(ue_header, context) != _URC_OK) \
190*404b540aSrobert return _URC_FAILURE; \
191*404b540aSrobert return _URC_CONTINUE_UNWIND; \
192*404b540aSrobert } \
193*404b540aSrobert while (0)
194*404b540aSrobert
195*404b540aSrobert #else
196*404b540aSrobert typedef const std::type_info _throw_typet;
197*404b540aSrobert
198*404b540aSrobert
199*404b540aSrobert // Return an element from a type table.
200*404b540aSrobert
201*404b540aSrobert static const std::type_info *
get_ttype_entry(lsda_header_info * info,_Unwind_Word i)202*404b540aSrobert get_ttype_entry (lsda_header_info *info, _Unwind_Word i)
203*404b540aSrobert {
204*404b540aSrobert _Unwind_Ptr ptr;
205*404b540aSrobert
206*404b540aSrobert i *= size_of_encoded_value (info->ttype_encoding);
207*404b540aSrobert read_encoded_value_with_base (info->ttype_encoding, info->ttype_base,
208*404b540aSrobert info->TType - i, &ptr);
209*404b540aSrobert
210*404b540aSrobert return reinterpret_cast<const std::type_info *>(ptr);
211*404b540aSrobert }
212*404b540aSrobert
213*404b540aSrobert // Given the thrown type THROW_TYPE, pointer to a variable containing a
214*404b540aSrobert // pointer to the exception object THROWN_PTR_P and a type CATCH_TYPE to
215*404b540aSrobert // compare against, return whether or not there is a match and if so,
216*404b540aSrobert // update *THROWN_PTR_P.
217*404b540aSrobert
218*404b540aSrobert static bool
get_adjusted_ptr(const std::type_info * catch_type,const std::type_info * throw_type,void ** thrown_ptr_p)219*404b540aSrobert get_adjusted_ptr (const std::type_info *catch_type,
220*404b540aSrobert const std::type_info *throw_type,
221*404b540aSrobert void **thrown_ptr_p)
222*404b540aSrobert {
223*404b540aSrobert void *thrown_ptr = *thrown_ptr_p;
224*404b540aSrobert
225*404b540aSrobert // Pointer types need to adjust the actual pointer, not
226*404b540aSrobert // the pointer to pointer that is the exception object.
227*404b540aSrobert // This also has the effect of passing pointer types
228*404b540aSrobert // "by value" through the __cxa_begin_catch return value.
229*404b540aSrobert if (throw_type->__is_pointer_p ())
230*404b540aSrobert thrown_ptr = *(void **) thrown_ptr;
231*404b540aSrobert
232*404b540aSrobert if (catch_type->__do_catch (throw_type, &thrown_ptr, 1))
233*404b540aSrobert {
234*404b540aSrobert *thrown_ptr_p = thrown_ptr;
235*404b540aSrobert return true;
236*404b540aSrobert }
237*404b540aSrobert
238*404b540aSrobert return false;
239*404b540aSrobert }
240*404b540aSrobert
241*404b540aSrobert // Return true if THROW_TYPE matches one if the filter types.
242*404b540aSrobert
243*404b540aSrobert static bool
check_exception_spec(lsda_header_info * info,_throw_typet * throw_type,void * thrown_ptr,_Unwind_Sword filter_value)244*404b540aSrobert check_exception_spec(lsda_header_info* info, _throw_typet* throw_type,
245*404b540aSrobert void* thrown_ptr, _Unwind_Sword filter_value)
246*404b540aSrobert {
247*404b540aSrobert const unsigned char *e = info->TType - filter_value - 1;
248*404b540aSrobert
249*404b540aSrobert while (1)
250*404b540aSrobert {
251*404b540aSrobert const std::type_info *catch_type;
252*404b540aSrobert _Unwind_Word tmp;
253*404b540aSrobert
254*404b540aSrobert e = read_uleb128 (e, &tmp);
255*404b540aSrobert
256*404b540aSrobert // Zero signals the end of the list. If we've not found
257*404b540aSrobert // a match by now, then we've failed the specification.
258*404b540aSrobert if (tmp == 0)
259*404b540aSrobert return false;
260*404b540aSrobert
261*404b540aSrobert // Match a ttype entry.
262*404b540aSrobert catch_type = get_ttype_entry (info, tmp);
263*404b540aSrobert
264*404b540aSrobert // ??? There is currently no way to ask the RTTI code about the
265*404b540aSrobert // relationship between two types without reference to a specific
266*404b540aSrobert // object. There should be; then we wouldn't need to mess with
267*404b540aSrobert // thrown_ptr here.
268*404b540aSrobert if (get_adjusted_ptr (catch_type, throw_type, &thrown_ptr))
269*404b540aSrobert return true;
270*404b540aSrobert }
271*404b540aSrobert }
272*404b540aSrobert
273*404b540aSrobert
274*404b540aSrobert // Save stage1 handler information in the exception object
275*404b540aSrobert
276*404b540aSrobert static inline void
save_caught_exception(struct _Unwind_Exception * ue_header,struct _Unwind_Context * context,void * thrown_ptr,int handler_switch_value,const unsigned char * language_specific_data,_Unwind_Ptr landing_pad,const unsigned char * action_record)277*404b540aSrobert save_caught_exception(struct _Unwind_Exception* ue_header,
278*404b540aSrobert struct _Unwind_Context* context
279*404b540aSrobert __attribute__((__unused__)),
280*404b540aSrobert void* thrown_ptr,
281*404b540aSrobert int handler_switch_value,
282*404b540aSrobert const unsigned char* language_specific_data,
283*404b540aSrobert _Unwind_Ptr landing_pad __attribute__((__unused__)),
284*404b540aSrobert const unsigned char* action_record)
285*404b540aSrobert {
286*404b540aSrobert __cxa_exception* xh = __get_exception_header_from_ue(ue_header);
287*404b540aSrobert
288*404b540aSrobert xh->handlerSwitchValue = handler_switch_value;
289*404b540aSrobert xh->actionRecord = action_record;
290*404b540aSrobert xh->languageSpecificData = language_specific_data;
291*404b540aSrobert xh->adjustedPtr = thrown_ptr;
292*404b540aSrobert
293*404b540aSrobert // ??? Completely unknown what this field is supposed to be for.
294*404b540aSrobert // ??? Need to cache TType encoding base for call_unexpected.
295*404b540aSrobert xh->catchTemp = landing_pad;
296*404b540aSrobert }
297*404b540aSrobert
298*404b540aSrobert
299*404b540aSrobert // Restore the catch handler information saved during phase1.
300*404b540aSrobert
301*404b540aSrobert static inline void
restore_caught_exception(struct _Unwind_Exception * ue_header,int & handler_switch_value,const unsigned char * & language_specific_data,_Unwind_Ptr & landing_pad)302*404b540aSrobert restore_caught_exception(struct _Unwind_Exception* ue_header,
303*404b540aSrobert int& handler_switch_value,
304*404b540aSrobert const unsigned char*& language_specific_data,
305*404b540aSrobert _Unwind_Ptr& landing_pad)
306*404b540aSrobert {
307*404b540aSrobert __cxa_exception* xh = __get_exception_header_from_ue(ue_header);
308*404b540aSrobert handler_switch_value = xh->handlerSwitchValue;
309*404b540aSrobert language_specific_data = xh->languageSpecificData;
310*404b540aSrobert landing_pad = (_Unwind_Ptr) xh->catchTemp;
311*404b540aSrobert }
312*404b540aSrobert
313*404b540aSrobert #define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
314*404b540aSrobert
315*404b540aSrobert #endif // !__ARM_EABI_UNWINDER__
316*404b540aSrobert
317*404b540aSrobert // Return true if the filter spec is empty, ie throw().
318*404b540aSrobert
319*404b540aSrobert static bool
empty_exception_spec(lsda_header_info * info,_Unwind_Sword filter_value)320*404b540aSrobert empty_exception_spec (lsda_header_info *info, _Unwind_Sword filter_value)
321*404b540aSrobert {
322*404b540aSrobert const unsigned char *e = info->TType - filter_value - 1;
323*404b540aSrobert _Unwind_Word tmp;
324*404b540aSrobert
325*404b540aSrobert e = read_uleb128 (e, &tmp);
326*404b540aSrobert return tmp == 0;
327*404b540aSrobert }
328*404b540aSrobert
329*404b540aSrobert namespace __cxxabiv1
330*404b540aSrobert {
331*404b540aSrobert
332*404b540aSrobert // Using a different personality function name causes link failures
333*404b540aSrobert // when trying to mix code using different exception handling models.
334*404b540aSrobert #ifdef _GLIBCXX_SJLJ_EXCEPTIONS
335*404b540aSrobert #define PERSONALITY_FUNCTION __gxx_personality_sj0
336*404b540aSrobert #define __builtin_eh_return_data_regno(x) x
337*404b540aSrobert #else
338*404b540aSrobert #define PERSONALITY_FUNCTION __gxx_personality_v0
339*404b540aSrobert #endif
340*404b540aSrobert
341*404b540aSrobert extern "C" _Unwind_Reason_Code
342*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
PERSONALITY_FUNCTION(_Unwind_State state,struct _Unwind_Exception * ue_header,struct _Unwind_Context * context)343*404b540aSrobert PERSONALITY_FUNCTION (_Unwind_State state,
344*404b540aSrobert struct _Unwind_Exception* ue_header,
345*404b540aSrobert struct _Unwind_Context* context)
346*404b540aSrobert #else
347*404b540aSrobert PERSONALITY_FUNCTION (int version,
348*404b540aSrobert _Unwind_Action actions,
349*404b540aSrobert _Unwind_Exception_Class exception_class,
350*404b540aSrobert struct _Unwind_Exception *ue_header,
351*404b540aSrobert struct _Unwind_Context *context)
352*404b540aSrobert #endif
353*404b540aSrobert {
354*404b540aSrobert enum found_handler_type
355*404b540aSrobert {
356*404b540aSrobert found_nothing,
357*404b540aSrobert found_terminate,
358*404b540aSrobert found_cleanup,
359*404b540aSrobert found_handler
360*404b540aSrobert } found_type;
361*404b540aSrobert
362*404b540aSrobert lsda_header_info info;
363*404b540aSrobert const unsigned char *language_specific_data;
364*404b540aSrobert const unsigned char *action_record;
365*404b540aSrobert const unsigned char *p;
366*404b540aSrobert _Unwind_Ptr landing_pad, ip;
367*404b540aSrobert int handler_switch_value;
368*404b540aSrobert void* thrown_ptr = ue_header + 1;
369*404b540aSrobert bool foreign_exception;
370*404b540aSrobert int ip_before_insn = 0;
371*404b540aSrobert
372*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
373*404b540aSrobert _Unwind_Action actions;
374*404b540aSrobert
375*404b540aSrobert switch (state & _US_ACTION_MASK)
376*404b540aSrobert {
377*404b540aSrobert case _US_VIRTUAL_UNWIND_FRAME:
378*404b540aSrobert actions = _UA_SEARCH_PHASE;
379*404b540aSrobert break;
380*404b540aSrobert
381*404b540aSrobert case _US_UNWIND_FRAME_STARTING:
382*404b540aSrobert actions = _UA_CLEANUP_PHASE;
383*404b540aSrobert if (!(state & _US_FORCE_UNWIND)
384*404b540aSrobert && ue_header->barrier_cache.sp == _Unwind_GetGR(context, 13))
385*404b540aSrobert actions |= _UA_HANDLER_FRAME;
386*404b540aSrobert break;
387*404b540aSrobert
388*404b540aSrobert case _US_UNWIND_FRAME_RESUME:
389*404b540aSrobert CONTINUE_UNWINDING;
390*404b540aSrobert break;
391*404b540aSrobert
392*404b540aSrobert default:
393*404b540aSrobert std::abort();
394*404b540aSrobert }
395*404b540aSrobert actions |= state & _US_FORCE_UNWIND;
396*404b540aSrobert
397*404b540aSrobert // We don't know which runtime we're working with, so can't check this.
398*404b540aSrobert // However the ABI routines hide this from us, and we don't actually need
399*404b540aSrobert // to know.
400*404b540aSrobert foreign_exception = false;
401*404b540aSrobert
402*404b540aSrobert // The dwarf unwinder assumes the context structure holds things like the
403*404b540aSrobert // function and LSDA pointers. The ARM implementation caches these in
404*404b540aSrobert // the exception header (UCB). To avoid rewriting everything we make the
405*404b540aSrobert // virtual IP register point at the UCB.
406*404b540aSrobert ip = (_Unwind_Ptr) ue_header;
407*404b540aSrobert _Unwind_SetGR(context, 12, ip);
408*404b540aSrobert #else
409*404b540aSrobert __cxa_exception* xh = __get_exception_header_from_ue(ue_header);
410*404b540aSrobert
411*404b540aSrobert // Interface version check.
412*404b540aSrobert if (version != 1)
413*404b540aSrobert return _URC_FATAL_PHASE1_ERROR;
414*404b540aSrobert foreign_exception = !__is_gxx_exception_class(exception_class);
415*404b540aSrobert #endif
416*404b540aSrobert
417*404b540aSrobert // Shortcut for phase 2 found handler for domestic exception.
418*404b540aSrobert if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME)
419*404b540aSrobert && !foreign_exception)
420*404b540aSrobert {
421*404b540aSrobert restore_caught_exception(ue_header, handler_switch_value,
422*404b540aSrobert language_specific_data, landing_pad);
423*404b540aSrobert found_type = (landing_pad == 0 ? found_terminate : found_handler);
424*404b540aSrobert goto install_context;
425*404b540aSrobert }
426*404b540aSrobert
427*404b540aSrobert language_specific_data = (const unsigned char *)
428*404b540aSrobert _Unwind_GetLanguageSpecificData (context);
429*404b540aSrobert
430*404b540aSrobert // If no LSDA, then there are no handlers or cleanups.
431*404b540aSrobert if (! language_specific_data)
432*404b540aSrobert CONTINUE_UNWINDING;
433*404b540aSrobert
434*404b540aSrobert // Parse the LSDA header.
435*404b540aSrobert p = parse_lsda_header (context, language_specific_data, &info);
436*404b540aSrobert info.ttype_base = base_of_encoded_value (info.ttype_encoding, context);
437*404b540aSrobert #ifdef HAVE_GETIPINFO
438*404b540aSrobert ip = _Unwind_GetIPInfo (context, &ip_before_insn);
439*404b540aSrobert #else
440*404b540aSrobert ip = _Unwind_GetIP (context);
441*404b540aSrobert #endif
442*404b540aSrobert if (! ip_before_insn)
443*404b540aSrobert --ip;
444*404b540aSrobert landing_pad = 0;
445*404b540aSrobert action_record = 0;
446*404b540aSrobert handler_switch_value = 0;
447*404b540aSrobert
448*404b540aSrobert #ifdef _GLIBCXX_SJLJ_EXCEPTIONS
449*404b540aSrobert // The given "IP" is an index into the call-site table, with two
450*404b540aSrobert // exceptions -- -1 means no-action, and 0 means terminate. But
451*404b540aSrobert // since we're using uleb128 values, we've not got random access
452*404b540aSrobert // to the array.
453*404b540aSrobert if ((int) ip < 0)
454*404b540aSrobert return _URC_CONTINUE_UNWIND;
455*404b540aSrobert else if (ip == 0)
456*404b540aSrobert {
457*404b540aSrobert // Fall through to set found_terminate.
458*404b540aSrobert }
459*404b540aSrobert else
460*404b540aSrobert {
461*404b540aSrobert _Unwind_Word cs_lp, cs_action;
462*404b540aSrobert do
463*404b540aSrobert {
464*404b540aSrobert p = read_uleb128 (p, &cs_lp);
465*404b540aSrobert p = read_uleb128 (p, &cs_action);
466*404b540aSrobert }
467*404b540aSrobert while (--ip);
468*404b540aSrobert
469*404b540aSrobert // Can never have null landing pad for sjlj -- that would have
470*404b540aSrobert // been indicated by a -1 call site index.
471*404b540aSrobert landing_pad = cs_lp + 1;
472*404b540aSrobert if (cs_action)
473*404b540aSrobert action_record = info.action_table + cs_action - 1;
474*404b540aSrobert goto found_something;
475*404b540aSrobert }
476*404b540aSrobert #else
477*404b540aSrobert // Search the call-site table for the action associated with this IP.
478*404b540aSrobert while (p < info.action_table)
479*404b540aSrobert {
480*404b540aSrobert _Unwind_Ptr cs_start, cs_len, cs_lp;
481*404b540aSrobert _Unwind_Word cs_action;
482*404b540aSrobert
483*404b540aSrobert // Note that all call-site encodings are "absolute" displacements.
484*404b540aSrobert p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
485*404b540aSrobert p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
486*404b540aSrobert p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
487*404b540aSrobert p = read_uleb128 (p, &cs_action);
488*404b540aSrobert
489*404b540aSrobert // The table is sorted, so if we've passed the ip, stop.
490*404b540aSrobert if (ip < info.Start + cs_start)
491*404b540aSrobert p = info.action_table;
492*404b540aSrobert else if (ip < info.Start + cs_start + cs_len)
493*404b540aSrobert {
494*404b540aSrobert if (cs_lp)
495*404b540aSrobert landing_pad = info.LPStart + cs_lp;
496*404b540aSrobert if (cs_action)
497*404b540aSrobert action_record = info.action_table + cs_action - 1;
498*404b540aSrobert goto found_something;
499*404b540aSrobert }
500*404b540aSrobert }
501*404b540aSrobert #endif // _GLIBCXX_SJLJ_EXCEPTIONS
502*404b540aSrobert
503*404b540aSrobert // If ip is not present in the table, call terminate. This is for
504*404b540aSrobert // a destructor inside a cleanup, or a library routine the compiler
505*404b540aSrobert // was not expecting to throw.
506*404b540aSrobert found_type = found_terminate;
507*404b540aSrobert goto do_something;
508*404b540aSrobert
509*404b540aSrobert found_something:
510*404b540aSrobert if (landing_pad == 0)
511*404b540aSrobert {
512*404b540aSrobert // If ip is present, and has a null landing pad, there are
513*404b540aSrobert // no cleanups or handlers to be run.
514*404b540aSrobert found_type = found_nothing;
515*404b540aSrobert }
516*404b540aSrobert else if (action_record == 0)
517*404b540aSrobert {
518*404b540aSrobert // If ip is present, has a non-null landing pad, and a null
519*404b540aSrobert // action table offset, then there are only cleanups present.
520*404b540aSrobert // Cleanups use a zero switch value, as set above.
521*404b540aSrobert found_type = found_cleanup;
522*404b540aSrobert }
523*404b540aSrobert else
524*404b540aSrobert {
525*404b540aSrobert // Otherwise we have a catch handler or exception specification.
526*404b540aSrobert
527*404b540aSrobert _Unwind_Sword ar_filter, ar_disp;
528*404b540aSrobert const std::type_info* catch_type;
529*404b540aSrobert _throw_typet* throw_type;
530*404b540aSrobert bool saw_cleanup = false;
531*404b540aSrobert bool saw_handler = false;
532*404b540aSrobert
533*404b540aSrobert // During forced unwinding, we only run cleanups. With a foreign
534*404b540aSrobert // exception class, there's no exception type.
535*404b540aSrobert // ??? What to do about GNU Java and GNU Ada exceptions.
536*404b540aSrobert
537*404b540aSrobert if ((actions & _UA_FORCE_UNWIND)
538*404b540aSrobert || foreign_exception)
539*404b540aSrobert throw_type = 0;
540*404b540aSrobert else
541*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
542*404b540aSrobert throw_type = ue_header;
543*404b540aSrobert #else
544*404b540aSrobert throw_type = xh->exceptionType;
545*404b540aSrobert #endif
546*404b540aSrobert
547*404b540aSrobert while (1)
548*404b540aSrobert {
549*404b540aSrobert p = action_record;
550*404b540aSrobert p = read_sleb128 (p, &ar_filter);
551*404b540aSrobert read_sleb128 (p, &ar_disp);
552*404b540aSrobert
553*404b540aSrobert if (ar_filter == 0)
554*404b540aSrobert {
555*404b540aSrobert // Zero filter values are cleanups.
556*404b540aSrobert saw_cleanup = true;
557*404b540aSrobert }
558*404b540aSrobert else if (ar_filter > 0)
559*404b540aSrobert {
560*404b540aSrobert // Positive filter values are handlers.
561*404b540aSrobert catch_type = get_ttype_entry (&info, ar_filter);
562*404b540aSrobert
563*404b540aSrobert // Null catch type is a catch-all handler; we can catch foreign
564*404b540aSrobert // exceptions with this. Otherwise we must match types.
565*404b540aSrobert if (! catch_type
566*404b540aSrobert || (throw_type
567*404b540aSrobert && get_adjusted_ptr (catch_type, throw_type,
568*404b540aSrobert &thrown_ptr)))
569*404b540aSrobert {
570*404b540aSrobert saw_handler = true;
571*404b540aSrobert break;
572*404b540aSrobert }
573*404b540aSrobert }
574*404b540aSrobert else
575*404b540aSrobert {
576*404b540aSrobert // Negative filter values are exception specifications.
577*404b540aSrobert // ??? How do foreign exceptions fit in? As far as I can
578*404b540aSrobert // see we can't match because there's no __cxa_exception
579*404b540aSrobert // object to stuff bits in for __cxa_call_unexpected to use.
580*404b540aSrobert // Allow them iff the exception spec is non-empty. I.e.
581*404b540aSrobert // a throw() specification results in __unexpected.
582*404b540aSrobert if (throw_type
583*404b540aSrobert ? ! check_exception_spec (&info, throw_type, thrown_ptr,
584*404b540aSrobert ar_filter)
585*404b540aSrobert : empty_exception_spec (&info, ar_filter))
586*404b540aSrobert {
587*404b540aSrobert saw_handler = true;
588*404b540aSrobert break;
589*404b540aSrobert }
590*404b540aSrobert }
591*404b540aSrobert
592*404b540aSrobert if (ar_disp == 0)
593*404b540aSrobert break;
594*404b540aSrobert action_record = p + ar_disp;
595*404b540aSrobert }
596*404b540aSrobert
597*404b540aSrobert if (saw_handler)
598*404b540aSrobert {
599*404b540aSrobert handler_switch_value = ar_filter;
600*404b540aSrobert found_type = found_handler;
601*404b540aSrobert }
602*404b540aSrobert else
603*404b540aSrobert found_type = (saw_cleanup ? found_cleanup : found_nothing);
604*404b540aSrobert }
605*404b540aSrobert
606*404b540aSrobert do_something:
607*404b540aSrobert if (found_type == found_nothing)
608*404b540aSrobert CONTINUE_UNWINDING;
609*404b540aSrobert
610*404b540aSrobert if (actions & _UA_SEARCH_PHASE)
611*404b540aSrobert {
612*404b540aSrobert if (found_type == found_cleanup)
613*404b540aSrobert CONTINUE_UNWINDING;
614*404b540aSrobert
615*404b540aSrobert // For domestic exceptions, we cache data from phase 1 for phase 2.
616*404b540aSrobert if (!foreign_exception)
617*404b540aSrobert {
618*404b540aSrobert save_caught_exception(ue_header, context, thrown_ptr,
619*404b540aSrobert handler_switch_value, language_specific_data,
620*404b540aSrobert landing_pad, action_record);
621*404b540aSrobert }
622*404b540aSrobert return _URC_HANDLER_FOUND;
623*404b540aSrobert }
624*404b540aSrobert
625*404b540aSrobert install_context:
626*404b540aSrobert
627*404b540aSrobert // We can't use any of the cxa routines with foreign exceptions,
628*404b540aSrobert // because they all expect ue_header to be a struct __cxa_exception.
629*404b540aSrobert // So in that case, call terminate or unexpected directly.
630*404b540aSrobert if ((actions & _UA_FORCE_UNWIND)
631*404b540aSrobert || foreign_exception)
632*404b540aSrobert {
633*404b540aSrobert if (found_type == found_terminate)
634*404b540aSrobert std::terminate ();
635*404b540aSrobert else if (handler_switch_value < 0)
636*404b540aSrobert {
637*404b540aSrobert try
638*404b540aSrobert { std::unexpected (); }
639*404b540aSrobert catch(...)
640*404b540aSrobert { std::terminate (); }
641*404b540aSrobert }
642*404b540aSrobert }
643*404b540aSrobert else
644*404b540aSrobert {
645*404b540aSrobert if (found_type == found_terminate)
646*404b540aSrobert __cxa_call_terminate(ue_header);
647*404b540aSrobert
648*404b540aSrobert // Cache the TType base value for __cxa_call_unexpected, as we won't
649*404b540aSrobert // have an _Unwind_Context then.
650*404b540aSrobert if (handler_switch_value < 0)
651*404b540aSrobert {
652*404b540aSrobert parse_lsda_header (context, language_specific_data, &info);
653*404b540aSrobert
654*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
655*404b540aSrobert const _Unwind_Word* e;
656*404b540aSrobert _Unwind_Word n;
657*404b540aSrobert
658*404b540aSrobert e = ((const _Unwind_Word*) info.TType) - handler_switch_value - 1;
659*404b540aSrobert // Count the number of rtti objects.
660*404b540aSrobert n = 0;
661*404b540aSrobert while (e[n] != 0)
662*404b540aSrobert n++;
663*404b540aSrobert
664*404b540aSrobert // Count.
665*404b540aSrobert ue_header->barrier_cache.bitpattern[1] = n;
666*404b540aSrobert // Base (obsolete)
667*404b540aSrobert ue_header->barrier_cache.bitpattern[2] = 0;
668*404b540aSrobert // Stride.
669*404b540aSrobert ue_header->barrier_cache.bitpattern[3] = 4;
670*404b540aSrobert // List head.
671*404b540aSrobert ue_header->barrier_cache.bitpattern[4] = (_Unwind_Word) e;
672*404b540aSrobert #else
673*404b540aSrobert xh->catchTemp = base_of_encoded_value (info.ttype_encoding, context);
674*404b540aSrobert #endif
675*404b540aSrobert }
676*404b540aSrobert }
677*404b540aSrobert
678*404b540aSrobert /* For targets with pointers smaller than the word size, we must extend the
679*404b540aSrobert pointer, and this extension is target dependent. */
680*404b540aSrobert _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
681*404b540aSrobert __builtin_extend_pointer (ue_header));
682*404b540aSrobert _Unwind_SetGR (context, __builtin_eh_return_data_regno (1),
683*404b540aSrobert handler_switch_value);
684*404b540aSrobert _Unwind_SetIP (context, landing_pad);
685*404b540aSrobert #ifdef __ARM_EABI_UNWINDER__
686*404b540aSrobert if (found_type == found_cleanup)
687*404b540aSrobert __cxa_begin_cleanup(ue_header);
688*404b540aSrobert #endif
689*404b540aSrobert return _URC_INSTALL_CONTEXT;
690*404b540aSrobert }
691*404b540aSrobert
692*404b540aSrobert /* The ARM EABI implementation of __cxa_call_unexpected is in a
693*404b540aSrobert different file so that the personality routine (PR) can be used
694*404b540aSrobert standalone. The generic routine shared datastructures with the PR
695*404b540aSrobert so it is most convenient to implement it here. */
696*404b540aSrobert #ifndef __ARM_EABI_UNWINDER__
697*404b540aSrobert extern "C" void
__cxa_call_unexpected(void * exc_obj_in)698*404b540aSrobert __cxa_call_unexpected (void *exc_obj_in)
699*404b540aSrobert {
700*404b540aSrobert _Unwind_Exception *exc_obj
701*404b540aSrobert = reinterpret_cast <_Unwind_Exception *>(exc_obj_in);
702*404b540aSrobert
703*404b540aSrobert __cxa_begin_catch (exc_obj);
704*404b540aSrobert
705*404b540aSrobert // This function is a handler for our exception argument. If we exit
706*404b540aSrobert // by throwing a different exception, we'll need the original cleaned up.
707*404b540aSrobert struct end_catch_protect
708*404b540aSrobert {
709*404b540aSrobert end_catch_protect() { }
710*404b540aSrobert ~end_catch_protect() { __cxa_end_catch(); }
711*404b540aSrobert } end_catch_protect_obj;
712*404b540aSrobert
713*404b540aSrobert lsda_header_info info;
714*404b540aSrobert __cxa_exception *xh = __get_exception_header_from_ue (exc_obj);
715*404b540aSrobert const unsigned char *xh_lsda;
716*404b540aSrobert _Unwind_Sword xh_switch_value;
717*404b540aSrobert std::terminate_handler xh_terminate_handler;
718*404b540aSrobert
719*404b540aSrobert // If the unexpectedHandler rethrows the exception (e.g. to categorize it),
720*404b540aSrobert // it will clobber data about the current handler. So copy the data out now.
721*404b540aSrobert xh_lsda = xh->languageSpecificData;
722*404b540aSrobert xh_switch_value = xh->handlerSwitchValue;
723*404b540aSrobert xh_terminate_handler = xh->terminateHandler;
724*404b540aSrobert info.ttype_base = (_Unwind_Ptr) xh->catchTemp;
725*404b540aSrobert
726*404b540aSrobert try
727*404b540aSrobert { __unexpected (xh->unexpectedHandler); }
728*404b540aSrobert catch(...)
729*404b540aSrobert {
730*404b540aSrobert // Get the exception thrown from unexpected.
731*404b540aSrobert
732*404b540aSrobert __cxa_eh_globals *globals = __cxa_get_globals_fast ();
733*404b540aSrobert __cxa_exception *new_xh = globals->caughtExceptions;
734*404b540aSrobert void *new_ptr = new_xh + 1;
735*404b540aSrobert
736*404b540aSrobert // We don't quite have enough stuff cached; re-parse the LSDA.
737*404b540aSrobert parse_lsda_header (0, xh_lsda, &info);
738*404b540aSrobert
739*404b540aSrobert // If this new exception meets the exception spec, allow it.
740*404b540aSrobert if (check_exception_spec (&info, new_xh->exceptionType,
741*404b540aSrobert new_ptr, xh_switch_value))
742*404b540aSrobert __throw_exception_again;
743*404b540aSrobert
744*404b540aSrobert // If the exception spec allows std::bad_exception, throw that.
745*404b540aSrobert // We don't have a thrown object to compare against, but since
746*404b540aSrobert // bad_exception doesn't have virtual bases, that's OK; just pass 0.
747*404b540aSrobert #ifdef __EXCEPTIONS
748*404b540aSrobert const std::type_info &bad_exc = typeid (std::bad_exception);
749*404b540aSrobert if (check_exception_spec (&info, &bad_exc, 0, xh_switch_value))
750*404b540aSrobert throw std::bad_exception();
751*404b540aSrobert #endif
752*404b540aSrobert
753*404b540aSrobert // Otherwise, die.
754*404b540aSrobert __terminate (xh_terminate_handler);
755*404b540aSrobert }
756*404b540aSrobert }
757*404b540aSrobert #endif
758*404b540aSrobert
759*404b540aSrobert } // namespace __cxxabiv1
760