11debfc3dSmrg /* Supporting functions for C exception handling.
2*8feb0f0bSmrg Copyright (C) 2002-2020 Free Software Foundation, Inc.
31debfc3dSmrg Contributed by Aldy Hernandez <aldy@quesejoda.com>.
41debfc3dSmrg Shamelessly stolen from the Java front end.
51debfc3dSmrg
61debfc3dSmrg This file is part of GCC.
71debfc3dSmrg
81debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
91debfc3dSmrg the terms of the GNU General Public License as published by the Free
101debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
111debfc3dSmrg version.
121debfc3dSmrg
131debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
141debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
151debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
161debfc3dSmrg for more details.
171debfc3dSmrg
181debfc3dSmrg Under Section 7 of GPL version 3, you are granted additional
191debfc3dSmrg permissions described in the GCC Runtime Library Exception, version
201debfc3dSmrg 3.1, as published by the Free Software Foundation.
211debfc3dSmrg
221debfc3dSmrg You should have received a copy of the GNU General Public License and
231debfc3dSmrg a copy of the GCC Runtime Library Exception along with this program;
241debfc3dSmrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
251debfc3dSmrg <http://www.gnu.org/licenses/>. */
261debfc3dSmrg
271debfc3dSmrg #include "tconfig.h"
281debfc3dSmrg #include "tsystem.h"
291debfc3dSmrg #include "auto-target.h"
301debfc3dSmrg #include "unwind.h"
311debfc3dSmrg #define NO_SIZE_OF_ENCODED_VALUE
321debfc3dSmrg #include "unwind-pe.h"
331debfc3dSmrg
341debfc3dSmrg typedef struct
351debfc3dSmrg {
361debfc3dSmrg _Unwind_Ptr Start;
371debfc3dSmrg _Unwind_Ptr LPStart;
381debfc3dSmrg _Unwind_Ptr ttype_base;
391debfc3dSmrg const unsigned char *TType;
401debfc3dSmrg const unsigned char *action_table;
411debfc3dSmrg unsigned char ttype_encoding;
421debfc3dSmrg unsigned char call_site_encoding;
431debfc3dSmrg } lsda_header_info;
441debfc3dSmrg
451debfc3dSmrg static const unsigned char *
parse_lsda_header(struct _Unwind_Context * context,const unsigned char * p,lsda_header_info * info)461debfc3dSmrg parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
471debfc3dSmrg lsda_header_info *info)
481debfc3dSmrg {
491debfc3dSmrg _uleb128_t tmp;
501debfc3dSmrg unsigned char lpstart_encoding;
511debfc3dSmrg
521debfc3dSmrg info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
531debfc3dSmrg
541debfc3dSmrg /* Find @LPStart, the base to which landing pad offsets are relative. */
551debfc3dSmrg lpstart_encoding = *p++;
561debfc3dSmrg if (lpstart_encoding != DW_EH_PE_omit)
571debfc3dSmrg p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
581debfc3dSmrg else
591debfc3dSmrg info->LPStart = info->Start;
601debfc3dSmrg
611debfc3dSmrg /* Find @TType, the base of the handler and exception spec type data. */
621debfc3dSmrg info->ttype_encoding = *p++;
631debfc3dSmrg if (info->ttype_encoding != DW_EH_PE_omit)
641debfc3dSmrg {
651debfc3dSmrg p = read_uleb128 (p, &tmp);
661debfc3dSmrg info->TType = p + tmp;
671debfc3dSmrg }
681debfc3dSmrg else
691debfc3dSmrg info->TType = 0;
701debfc3dSmrg
711debfc3dSmrg /* The encoding and length of the call-site table; the action table
721debfc3dSmrg immediately follows. */
731debfc3dSmrg info->call_site_encoding = *p++;
741debfc3dSmrg p = read_uleb128 (p, &tmp);
751debfc3dSmrg info->action_table = p + tmp;
761debfc3dSmrg
771debfc3dSmrg return p;
781debfc3dSmrg }
791debfc3dSmrg
801debfc3dSmrg #ifdef __ARM_EABI_UNWINDER__
811debfc3dSmrg /* ARM EABI personality routines must also unwind the stack. */
821debfc3dSmrg #define CONTINUE_UNWINDING \
831debfc3dSmrg do \
841debfc3dSmrg { \
851debfc3dSmrg if (__gnu_unwind_frame (ue_header, context) != _URC_OK) \
861debfc3dSmrg return _URC_FAILURE; \
871debfc3dSmrg return _URC_CONTINUE_UNWIND; \
881debfc3dSmrg } \
891debfc3dSmrg while (0)
901debfc3dSmrg #else
911debfc3dSmrg #define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
921debfc3dSmrg #endif
931debfc3dSmrg
941debfc3dSmrg #ifdef __USING_SJLJ_EXCEPTIONS__
951debfc3dSmrg #define PERSONALITY_FUNCTION __gcc_personality_sj0
961debfc3dSmrg #define __builtin_eh_return_data_regno(x) x
971debfc3dSmrg #elif defined(__SEH__)
981debfc3dSmrg #define PERSONALITY_FUNCTION __gcc_personality_imp
991debfc3dSmrg #else
1001debfc3dSmrg #define PERSONALITY_FUNCTION __gcc_personality_v0
1011debfc3dSmrg #endif
1021debfc3dSmrg
1031debfc3dSmrg #ifdef __ARM_EABI_UNWINDER__
1041debfc3dSmrg _Unwind_Reason_Code
1051debfc3dSmrg PERSONALITY_FUNCTION (_Unwind_State, struct _Unwind_Exception *,
1061debfc3dSmrg struct _Unwind_Context *);
1071debfc3dSmrg
1081debfc3dSmrg _Unwind_Reason_Code
109c0a68be4Smrg __attribute__((target ("general-regs-only")))
PERSONALITY_FUNCTION(_Unwind_State state,struct _Unwind_Exception * ue_header,struct _Unwind_Context * context)1101debfc3dSmrg PERSONALITY_FUNCTION (_Unwind_State state,
1111debfc3dSmrg struct _Unwind_Exception * ue_header,
1121debfc3dSmrg struct _Unwind_Context * context)
1131debfc3dSmrg #else
1141debfc3dSmrg #if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__)
1151debfc3dSmrg static
1161debfc3dSmrg #endif
1171debfc3dSmrg _Unwind_Reason_Code
1181debfc3dSmrg PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
1191debfc3dSmrg struct _Unwind_Exception *, struct _Unwind_Context *);
1201debfc3dSmrg
1211debfc3dSmrg _Unwind_Reason_Code
1221debfc3dSmrg PERSONALITY_FUNCTION (int version,
1231debfc3dSmrg _Unwind_Action actions,
1241debfc3dSmrg _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED,
1251debfc3dSmrg struct _Unwind_Exception *ue_header,
1261debfc3dSmrg struct _Unwind_Context *context)
1271debfc3dSmrg #endif
1281debfc3dSmrg {
1291debfc3dSmrg lsda_header_info info;
1301debfc3dSmrg const unsigned char *language_specific_data, *p;
1311debfc3dSmrg _Unwind_Ptr landing_pad, ip;
1321debfc3dSmrg int ip_before_insn = 0;
1331debfc3dSmrg
1341debfc3dSmrg #ifdef __ARM_EABI_UNWINDER__
1351debfc3dSmrg if ((state & _US_ACTION_MASK) != _US_UNWIND_FRAME_STARTING)
1361debfc3dSmrg CONTINUE_UNWINDING;
1371debfc3dSmrg
1381debfc3dSmrg /* The dwarf unwinder assumes the context structure holds things like the
1391debfc3dSmrg function and LSDA pointers. The ARM implementation caches these in
1401debfc3dSmrg the exception header (UCB). To avoid rewriting everything we make a
1411debfc3dSmrg virtual scratch register point at the UCB. */
1421debfc3dSmrg ip = (_Unwind_Ptr) ue_header;
1431debfc3dSmrg _Unwind_SetGR (context, UNWIND_POINTER_REG, ip);
1441debfc3dSmrg #else
1451debfc3dSmrg if (version != 1)
1461debfc3dSmrg return _URC_FATAL_PHASE1_ERROR;
1471debfc3dSmrg
1481debfc3dSmrg /* Currently we only support cleanups for C. */
1491debfc3dSmrg if ((actions & _UA_CLEANUP_PHASE) == 0)
1501debfc3dSmrg CONTINUE_UNWINDING;
1511debfc3dSmrg #endif
1521debfc3dSmrg
1531debfc3dSmrg language_specific_data = (const unsigned char *)
1541debfc3dSmrg _Unwind_GetLanguageSpecificData (context);
1551debfc3dSmrg
1561debfc3dSmrg /* If no LSDA, then there are no handlers or cleanups. */
1571debfc3dSmrg if (! language_specific_data)
1581debfc3dSmrg CONTINUE_UNWINDING;
1591debfc3dSmrg
1601debfc3dSmrg /* Parse the LSDA header. */
1611debfc3dSmrg p = parse_lsda_header (context, language_specific_data, &info);
1621debfc3dSmrg #ifdef HAVE_GETIPINFO
1631debfc3dSmrg ip = _Unwind_GetIPInfo (context, &ip_before_insn);
1641debfc3dSmrg #else
1651debfc3dSmrg ip = _Unwind_GetIP (context);
1661debfc3dSmrg #endif
1671debfc3dSmrg if (! ip_before_insn)
1681debfc3dSmrg --ip;
1691debfc3dSmrg landing_pad = 0;
1701debfc3dSmrg
1711debfc3dSmrg #ifdef __USING_SJLJ_EXCEPTIONS__
1721debfc3dSmrg /* The given "IP" is an index into the call-site table, with two
1731debfc3dSmrg exceptions -- -1 means no-action, and 0 means terminate. But
1741debfc3dSmrg since we're using uleb128 values, we've not got random access
1751debfc3dSmrg to the array. */
1761debfc3dSmrg if ((int) ip <= 0)
1771debfc3dSmrg return _URC_CONTINUE_UNWIND;
1781debfc3dSmrg else
1791debfc3dSmrg {
1801debfc3dSmrg _uleb128_t cs_lp, cs_action;
1811debfc3dSmrg do
1821debfc3dSmrg {
1831debfc3dSmrg p = read_uleb128 (p, &cs_lp);
1841debfc3dSmrg p = read_uleb128 (p, &cs_action);
1851debfc3dSmrg }
1861debfc3dSmrg while (--ip);
1871debfc3dSmrg
1881debfc3dSmrg /* Can never have null landing pad for sjlj -- that would have
1891debfc3dSmrg been indicated by a -1 call site index. */
1901debfc3dSmrg landing_pad = (_Unwind_Ptr)cs_lp + 1;
1911debfc3dSmrg goto found_something;
1921debfc3dSmrg }
1931debfc3dSmrg #else
1941debfc3dSmrg /* Search the call-site table for the action associated with this IP. */
1951debfc3dSmrg while (p < info.action_table)
1961debfc3dSmrg {
1971debfc3dSmrg _Unwind_Ptr cs_start, cs_len, cs_lp;
1981debfc3dSmrg _uleb128_t cs_action;
1991debfc3dSmrg
2001debfc3dSmrg /* Note that all call-site encodings are "absolute" displacements. */
2011debfc3dSmrg p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
2021debfc3dSmrg p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
2031debfc3dSmrg p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
2041debfc3dSmrg p = read_uleb128 (p, &cs_action);
2051debfc3dSmrg
2061debfc3dSmrg /* The table is sorted, so if we've passed the ip, stop. */
2071debfc3dSmrg if (ip < info.Start + cs_start)
2081debfc3dSmrg p = info.action_table;
2091debfc3dSmrg else if (ip < info.Start + cs_start + cs_len)
2101debfc3dSmrg {
2111debfc3dSmrg if (cs_lp)
2121debfc3dSmrg landing_pad = info.LPStart + cs_lp;
2131debfc3dSmrg goto found_something;
2141debfc3dSmrg }
2151debfc3dSmrg }
2161debfc3dSmrg #endif
2171debfc3dSmrg
2181debfc3dSmrg /* IP is not in table. No associated cleanups. */
2191debfc3dSmrg /* ??? This is where C++ calls std::terminate to catch throw
2201debfc3dSmrg from a destructor. */
2211debfc3dSmrg CONTINUE_UNWINDING;
2221debfc3dSmrg
2231debfc3dSmrg found_something:
2241debfc3dSmrg if (landing_pad == 0)
2251debfc3dSmrg {
2261debfc3dSmrg /* IP is present, but has a null landing pad.
2271debfc3dSmrg No handler to be run. */
2281debfc3dSmrg CONTINUE_UNWINDING;
2291debfc3dSmrg }
2301debfc3dSmrg
2311debfc3dSmrg _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
2321debfc3dSmrg (_Unwind_Ptr) ue_header);
2331debfc3dSmrg _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), 0);
2341debfc3dSmrg _Unwind_SetIP (context, landing_pad);
2351debfc3dSmrg return _URC_INSTALL_CONTEXT;
2361debfc3dSmrg }
2371debfc3dSmrg
2381debfc3dSmrg #if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__)
2391debfc3dSmrg EXCEPTION_DISPOSITION
__gcc_personality_seh0(PEXCEPTION_RECORD ms_exc,void * this_frame,PCONTEXT ms_orig_context,PDISPATCHER_CONTEXT ms_disp)2401debfc3dSmrg __gcc_personality_seh0 (PEXCEPTION_RECORD ms_exc, void *this_frame,
2411debfc3dSmrg PCONTEXT ms_orig_context, PDISPATCHER_CONTEXT ms_disp)
2421debfc3dSmrg {
2431debfc3dSmrg return _GCC_specific_handler (ms_exc, this_frame, ms_orig_context,
2441debfc3dSmrg ms_disp, __gcc_personality_imp);
2451debfc3dSmrg }
2461debfc3dSmrg #endif /* SEH */
247