xref: /dflybsd-src/contrib/gcc-8.0/libgcc/unwind-c.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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