1 /* Supporting functions for C exception handling.
2 Copyright (C) 2002, 2003 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez <aldy@quesejoda.com>.
4 Shamelessly stolen from the Java front end.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26 #define NO_SIZE_OF_ENCODED_VALUE
27 #include "unwind-pe.h"
33 _Unwind_Ptr ttype_base
;
34 const unsigned char *TType
;
35 const unsigned char *action_table
;
36 unsigned char ttype_encoding
;
37 unsigned char call_site_encoding
;
40 static const unsigned char *
41 parse_lsda_header (struct _Unwind_Context
*context
, const unsigned char *p
,
42 lsda_header_info
*info
)
45 unsigned char lpstart_encoding
;
47 info
->Start
= (context
? _Unwind_GetRegionStart (context
) : 0);
49 /* Find @LPStart, the base to which landing pad offsets are relative. */
50 lpstart_encoding
= *p
++;
51 if (lpstart_encoding
!= DW_EH_PE_omit
)
52 p
= read_encoded_value (context
, lpstart_encoding
, p
, &info
->LPStart
);
54 info
->LPStart
= info
->Start
;
56 /* Find @TType, the base of the handler and exception spec type data. */
57 info
->ttype_encoding
= *p
++;
58 if (info
->ttype_encoding
!= DW_EH_PE_omit
)
60 p
= read_uleb128 (p
, &tmp
);
61 info
->TType
= p
+ tmp
;
66 /* The encoding and length of the call-site table; the action table
67 immediately follows. */
68 info
->call_site_encoding
= *p
++;
69 p
= read_uleb128 (p
, &tmp
);
70 info
->action_table
= p
+ tmp
;
75 #ifdef __USING_SJLJ_EXCEPTIONS__
76 #define PERSONALITY_FUNCTION __gcc_personality_sj0
77 #define __builtin_eh_return_data_regno(x) x
79 #define PERSONALITY_FUNCTION __gcc_personality_v0
83 PERSONALITY_FUNCTION (int, _Unwind_Action
, _Unwind_Exception_Class
,
84 struct _Unwind_Exception
*, struct _Unwind_Context
*);
87 PERSONALITY_FUNCTION (int version
,
88 _Unwind_Action actions
,
89 _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED
,
90 struct _Unwind_Exception
*ue_header
,
91 struct _Unwind_Context
*context
)
93 lsda_header_info info
;
94 const unsigned char *language_specific_data
, *p
, *action_record
;
95 _Unwind_Ptr landing_pad
, ip
;
98 return _URC_FATAL_PHASE1_ERROR
;
100 /* Currently we only support cleanups for C. */
101 if ((actions
& _UA_CLEANUP_PHASE
) == 0)
102 return _URC_CONTINUE_UNWIND
;
104 language_specific_data
= (const unsigned char *)
105 _Unwind_GetLanguageSpecificData (context
);
107 /* If no LSDA, then there are no handlers or cleanups. */
108 if (! language_specific_data
)
109 return _URC_CONTINUE_UNWIND
;
111 /* Parse the LSDA header. */
112 p
= parse_lsda_header (context
, language_specific_data
, &info
);
113 ip
= _Unwind_GetIP (context
) - 1;
116 #ifdef __USING_SJLJ_EXCEPTIONS__
117 /* The given "IP" is an index into the call-site table, with two
118 exceptions -- -1 means no-action, and 0 means terminate. But
119 since we're using uleb128 values, we've not got random access
122 return _URC_CONTINUE_UNWIND
;
125 _Unwind_Word cs_lp
, cs_action
;
128 p
= read_uleb128 (p
, &cs_lp
);
129 p
= read_uleb128 (p
, &cs_action
);
133 /* Can never have null landing pad for sjlj -- that would have
134 been indicated by a -1 call site index. */
135 landing_pad
= cs_lp
+ 1;
137 action_record
= info
.action_table
+ cs_action
- 1;
138 goto found_something
;
141 /* Search the call-site table for the action associated with this IP. */
142 while (p
< info
.action_table
)
144 _Unwind_Ptr cs_start
, cs_len
, cs_lp
;
145 _Unwind_Word cs_action
;
147 /* Note that all call-site encodings are "absolute" displacements. */
148 p
= read_encoded_value (0, info
.call_site_encoding
, p
, &cs_start
);
149 p
= read_encoded_value (0, info
.call_site_encoding
, p
, &cs_len
);
150 p
= read_encoded_value (0, info
.call_site_encoding
, p
, &cs_lp
);
151 p
= read_uleb128 (p
, &cs_action
);
153 /* The table is sorted, so if we've passed the ip, stop. */
154 if (ip
< info
.Start
+ cs_start
)
155 p
= info
.action_table
;
156 else if (ip
< info
.Start
+ cs_start
+ cs_len
)
159 landing_pad
= info
.LPStart
+ cs_lp
;
161 action_record
= info
.action_table
+ cs_action
- 1;
162 goto found_something
;
168 /* IP is not in table. No associated cleanups. */
169 /* ??? This is where C++ calls std::terminate to catch throw
170 from a destructor. */
171 return _URC_CONTINUE_UNWIND
;
174 if (landing_pad
== 0)
176 /* IP is present, but has a null landing pad.
177 No handler to be run. */
178 return _URC_CONTINUE_UNWIND
;
181 _Unwind_SetGR (context
, __builtin_eh_return_data_regno (0),
182 (_Unwind_Ptr
) ue_header
);
183 _Unwind_SetGR (context
, __builtin_eh_return_data_regno (1), 0);
184 _Unwind_SetIP (context
, landing_pad
);
185 return _URC_INSTALL_CONTEXT
;