annotate libgcc/unwind-c.c @ 131:84e7813d76e9

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