1*38fd1498Szrj /* Supporting functions for C exception handling.
2*38fd1498Szrj Copyright (C) 2002-2018 Free Software Foundation, Inc.
3*38fd1498Szrj Contributed by Aldy Hernandez <aldy@quesejoda.com>.
4*38fd1498Szrj Shamelessly stolen from the Java front end.
5*38fd1498Szrj
6*38fd1498Szrj This file is part of GCC.
7*38fd1498Szrj
8*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
9*38fd1498Szrj the terms of the GNU General Public License as published by the Free
10*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
11*38fd1498Szrj version.
12*38fd1498Szrj
13*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16*38fd1498Szrj for more details.
17*38fd1498Szrj
18*38fd1498Szrj Under Section 7 of GPL version 3, you are granted additional
19*38fd1498Szrj permissions described in the GCC Runtime Library Exception, version
20*38fd1498Szrj 3.1, as published by the Free Software Foundation.
21*38fd1498Szrj
22*38fd1498Szrj You should have received a copy of the GNU General Public License and
23*38fd1498Szrj a copy of the GCC Runtime Library Exception along with this program;
24*38fd1498Szrj see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25*38fd1498Szrj <http://www.gnu.org/licenses/>. */
26*38fd1498Szrj
27*38fd1498Szrj #include "tconfig.h"
28*38fd1498Szrj #include "tsystem.h"
29*38fd1498Szrj #include "auto-target.h"
30*38fd1498Szrj #include "unwind.h"
31*38fd1498Szrj #define NO_SIZE_OF_ENCODED_VALUE
32*38fd1498Szrj #include "unwind-pe.h"
33*38fd1498Szrj
34*38fd1498Szrj typedef struct
35*38fd1498Szrj {
36*38fd1498Szrj _Unwind_Ptr Start;
37*38fd1498Szrj _Unwind_Ptr LPStart;
38*38fd1498Szrj _Unwind_Ptr ttype_base;
39*38fd1498Szrj const unsigned char *TType;
40*38fd1498Szrj const unsigned char *action_table;
41*38fd1498Szrj unsigned char ttype_encoding;
42*38fd1498Szrj unsigned char call_site_encoding;
43*38fd1498Szrj } lsda_header_info;
44*38fd1498Szrj
45*38fd1498Szrj static const unsigned char *
parse_lsda_header(struct _Unwind_Context * context,const unsigned char * p,lsda_header_info * info)46*38fd1498Szrj parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
47*38fd1498Szrj lsda_header_info *info)
48*38fd1498Szrj {
49*38fd1498Szrj _uleb128_t tmp;
50*38fd1498Szrj unsigned char lpstart_encoding;
51*38fd1498Szrj
52*38fd1498Szrj info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
53*38fd1498Szrj
54*38fd1498Szrj /* Find @LPStart, the base to which landing pad offsets are relative. */
55*38fd1498Szrj lpstart_encoding = *p++;
56*38fd1498Szrj if (lpstart_encoding != DW_EH_PE_omit)
57*38fd1498Szrj p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
58*38fd1498Szrj else
59*38fd1498Szrj info->LPStart = info->Start;
60*38fd1498Szrj
61*38fd1498Szrj /* Find @TType, the base of the handler and exception spec type data. */
62*38fd1498Szrj info->ttype_encoding = *p++;
63*38fd1498Szrj if (info->ttype_encoding != DW_EH_PE_omit)
64*38fd1498Szrj {
65*38fd1498Szrj p = read_uleb128 (p, &tmp);
66*38fd1498Szrj info->TType = p + tmp;
67*38fd1498Szrj }
68*38fd1498Szrj else
69*38fd1498Szrj info->TType = 0;
70*38fd1498Szrj
71*38fd1498Szrj /* The encoding and length of the call-site table; the action table
72*38fd1498Szrj immediately follows. */
73*38fd1498Szrj info->call_site_encoding = *p++;
74*38fd1498Szrj p = read_uleb128 (p, &tmp);
75*38fd1498Szrj info->action_table = p + tmp;
76*38fd1498Szrj
77*38fd1498Szrj return p;
78*38fd1498Szrj }
79*38fd1498Szrj
80*38fd1498Szrj #ifdef __ARM_EABI_UNWINDER__
81*38fd1498Szrj /* ARM EABI personality routines must also unwind the stack. */
82*38fd1498Szrj #define CONTINUE_UNWINDING \
83*38fd1498Szrj do \
84*38fd1498Szrj { \
85*38fd1498Szrj if (__gnu_unwind_frame (ue_header, context) != _URC_OK) \
86*38fd1498Szrj return _URC_FAILURE; \
87*38fd1498Szrj return _URC_CONTINUE_UNWIND; \
88*38fd1498Szrj } \
89*38fd1498Szrj while (0)
90*38fd1498Szrj #else
91*38fd1498Szrj #define CONTINUE_UNWINDING return _URC_CONTINUE_UNWIND
92*38fd1498Szrj #endif
93*38fd1498Szrj
94*38fd1498Szrj #ifdef __USING_SJLJ_EXCEPTIONS__
95*38fd1498Szrj #define PERSONALITY_FUNCTION __gcc_personality_sj0
96*38fd1498Szrj #define __builtin_eh_return_data_regno(x) x
97*38fd1498Szrj #elif defined(__SEH__)
98*38fd1498Szrj #define PERSONALITY_FUNCTION __gcc_personality_imp
99*38fd1498Szrj #else
100*38fd1498Szrj #define PERSONALITY_FUNCTION __gcc_personality_v0
101*38fd1498Szrj #endif
102*38fd1498Szrj
103*38fd1498Szrj #ifdef __ARM_EABI_UNWINDER__
104*38fd1498Szrj _Unwind_Reason_Code
105*38fd1498Szrj PERSONALITY_FUNCTION (_Unwind_State, struct _Unwind_Exception *,
106*38fd1498Szrj struct _Unwind_Context *);
107*38fd1498Szrj
108*38fd1498Szrj _Unwind_Reason_Code
PERSONALITY_FUNCTION(_Unwind_State state,struct _Unwind_Exception * ue_header,struct _Unwind_Context * context)109*38fd1498Szrj PERSONALITY_FUNCTION (_Unwind_State state,
110*38fd1498Szrj struct _Unwind_Exception * ue_header,
111*38fd1498Szrj struct _Unwind_Context * context)
112*38fd1498Szrj #else
113*38fd1498Szrj #if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__)
114*38fd1498Szrj static
115*38fd1498Szrj #endif
116*38fd1498Szrj _Unwind_Reason_Code
117*38fd1498Szrj PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
118*38fd1498Szrj struct _Unwind_Exception *, struct _Unwind_Context *);
119*38fd1498Szrj
120*38fd1498Szrj _Unwind_Reason_Code
121*38fd1498Szrj PERSONALITY_FUNCTION (int version,
122*38fd1498Szrj _Unwind_Action actions,
123*38fd1498Szrj _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED,
124*38fd1498Szrj struct _Unwind_Exception *ue_header,
125*38fd1498Szrj struct _Unwind_Context *context)
126*38fd1498Szrj #endif
127*38fd1498Szrj {
128*38fd1498Szrj lsda_header_info info;
129*38fd1498Szrj const unsigned char *language_specific_data, *p;
130*38fd1498Szrj _Unwind_Ptr landing_pad, ip;
131*38fd1498Szrj int ip_before_insn = 0;
132*38fd1498Szrj
133*38fd1498Szrj #ifdef __ARM_EABI_UNWINDER__
134*38fd1498Szrj if ((state & _US_ACTION_MASK) != _US_UNWIND_FRAME_STARTING)
135*38fd1498Szrj CONTINUE_UNWINDING;
136*38fd1498Szrj
137*38fd1498Szrj /* The dwarf unwinder assumes the context structure holds things like the
138*38fd1498Szrj function and LSDA pointers. The ARM implementation caches these in
139*38fd1498Szrj the exception header (UCB). To avoid rewriting everything we make a
140*38fd1498Szrj virtual scratch register point at the UCB. */
141*38fd1498Szrj ip = (_Unwind_Ptr) ue_header;
142*38fd1498Szrj _Unwind_SetGR (context, UNWIND_POINTER_REG, ip);
143*38fd1498Szrj #else
144*38fd1498Szrj if (version != 1)
145*38fd1498Szrj return _URC_FATAL_PHASE1_ERROR;
146*38fd1498Szrj
147*38fd1498Szrj /* Currently we only support cleanups for C. */
148*38fd1498Szrj if ((actions & _UA_CLEANUP_PHASE) == 0)
149*38fd1498Szrj CONTINUE_UNWINDING;
150*38fd1498Szrj #endif
151*38fd1498Szrj
152*38fd1498Szrj language_specific_data = (const unsigned char *)
153*38fd1498Szrj _Unwind_GetLanguageSpecificData (context);
154*38fd1498Szrj
155*38fd1498Szrj /* If no LSDA, then there are no handlers or cleanups. */
156*38fd1498Szrj if (! language_specific_data)
157*38fd1498Szrj CONTINUE_UNWINDING;
158*38fd1498Szrj
159*38fd1498Szrj /* Parse the LSDA header. */
160*38fd1498Szrj p = parse_lsda_header (context, language_specific_data, &info);
161*38fd1498Szrj #ifdef HAVE_GETIPINFO
162*38fd1498Szrj ip = _Unwind_GetIPInfo (context, &ip_before_insn);
163*38fd1498Szrj #else
164*38fd1498Szrj ip = _Unwind_GetIP (context);
165*38fd1498Szrj #endif
166*38fd1498Szrj if (! ip_before_insn)
167*38fd1498Szrj --ip;
168*38fd1498Szrj landing_pad = 0;
169*38fd1498Szrj
170*38fd1498Szrj #ifdef __USING_SJLJ_EXCEPTIONS__
171*38fd1498Szrj /* The given "IP" is an index into the call-site table, with two
172*38fd1498Szrj exceptions -- -1 means no-action, and 0 means terminate. But
173*38fd1498Szrj since we're using uleb128 values, we've not got random access
174*38fd1498Szrj to the array. */
175*38fd1498Szrj if ((int) ip <= 0)
176*38fd1498Szrj return _URC_CONTINUE_UNWIND;
177*38fd1498Szrj else
178*38fd1498Szrj {
179*38fd1498Szrj _uleb128_t cs_lp, cs_action;
180*38fd1498Szrj do
181*38fd1498Szrj {
182*38fd1498Szrj p = read_uleb128 (p, &cs_lp);
183*38fd1498Szrj p = read_uleb128 (p, &cs_action);
184*38fd1498Szrj }
185*38fd1498Szrj while (--ip);
186*38fd1498Szrj
187*38fd1498Szrj /* Can never have null landing pad for sjlj -- that would have
188*38fd1498Szrj been indicated by a -1 call site index. */
189*38fd1498Szrj landing_pad = (_Unwind_Ptr)cs_lp + 1;
190*38fd1498Szrj goto found_something;
191*38fd1498Szrj }
192*38fd1498Szrj #else
193*38fd1498Szrj /* Search the call-site table for the action associated with this IP. */
194*38fd1498Szrj while (p < info.action_table)
195*38fd1498Szrj {
196*38fd1498Szrj _Unwind_Ptr cs_start, cs_len, cs_lp;
197*38fd1498Szrj _uleb128_t cs_action;
198*38fd1498Szrj
199*38fd1498Szrj /* Note that all call-site encodings are "absolute" displacements. */
200*38fd1498Szrj p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
201*38fd1498Szrj p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
202*38fd1498Szrj p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
203*38fd1498Szrj p = read_uleb128 (p, &cs_action);
204*38fd1498Szrj
205*38fd1498Szrj /* The table is sorted, so if we've passed the ip, stop. */
206*38fd1498Szrj if (ip < info.Start + cs_start)
207*38fd1498Szrj p = info.action_table;
208*38fd1498Szrj else if (ip < info.Start + cs_start + cs_len)
209*38fd1498Szrj {
210*38fd1498Szrj if (cs_lp)
211*38fd1498Szrj landing_pad = info.LPStart + cs_lp;
212*38fd1498Szrj goto found_something;
213*38fd1498Szrj }
214*38fd1498Szrj }
215*38fd1498Szrj #endif
216*38fd1498Szrj
217*38fd1498Szrj /* IP is not in table. No associated cleanups. */
218*38fd1498Szrj /* ??? This is where C++ calls std::terminate to catch throw
219*38fd1498Szrj from a destructor. */
220*38fd1498Szrj CONTINUE_UNWINDING;
221*38fd1498Szrj
222*38fd1498Szrj found_something:
223*38fd1498Szrj if (landing_pad == 0)
224*38fd1498Szrj {
225*38fd1498Szrj /* IP is present, but has a null landing pad.
226*38fd1498Szrj No handler to be run. */
227*38fd1498Szrj CONTINUE_UNWINDING;
228*38fd1498Szrj }
229*38fd1498Szrj
230*38fd1498Szrj _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
231*38fd1498Szrj (_Unwind_Ptr) ue_header);
232*38fd1498Szrj _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), 0);
233*38fd1498Szrj _Unwind_SetIP (context, landing_pad);
234*38fd1498Szrj return _URC_INSTALL_CONTEXT;
235*38fd1498Szrj }
236*38fd1498Szrj
237*38fd1498Szrj #if defined (__SEH__) && !defined (__USING_SJLJ_EXCEPTIONS__)
238*38fd1498Szrj EXCEPTION_DISPOSITION
__gcc_personality_seh0(PEXCEPTION_RECORD ms_exc,void * this_frame,PCONTEXT ms_orig_context,PDISPATCHER_CONTEXT ms_disp)239*38fd1498Szrj __gcc_personality_seh0 (PEXCEPTION_RECORD ms_exc, void *this_frame,
240*38fd1498Szrj PCONTEXT ms_orig_context, PDISPATCHER_CONTEXT ms_disp)
241*38fd1498Szrj {
242*38fd1498Szrj return _GCC_specific_handler (ms_exc, this_frame, ms_orig_context,
243*38fd1498Szrj ms_disp, __gcc_personality_imp);
244*38fd1498Szrj }
245*38fd1498Szrj #endif /* SEH */
246