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
81 #define PERSONALITY_FUNCTION __gcc_personality_v0
84 PERSONALITY_FUNCTION (int, _Unwind_Action
, _Unwind_Exception_Class
,
85 struct _Unwind_Exception
*, struct _Unwind_Context
*);
88 PERSONALITY_FUNCTION (int version
,
89 _Unwind_Action actions
,
90 _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED
,
91 struct _Unwind_Exception
*ue_header
,
92 struct _Unwind_Context
*context
)
94 lsda_header_info info
;
95 const unsigned char *language_specific_data
, *p
, *action_record
;
96 _Unwind_Ptr landing_pad
, ip
;
99 return _URC_FATAL_PHASE1_ERROR
;
101 /* Currently we only support cleanups for C. */
102 if ((actions
& _UA_CLEANUP_PHASE
) == 0)
103 return _URC_CONTINUE_UNWIND
;
105 language_specific_data
= (const unsigned char *)
106 _Unwind_GetLanguageSpecificData (context
);
108 /* If no LSDA, then there are no handlers or cleanups. */
109 if (! language_specific_data
)
110 return _URC_CONTINUE_UNWIND
;
112 /* Parse the LSDA header. */
113 p
= parse_lsda_header (context
, language_specific_data
, &info
);
114 ip
= _Unwind_GetIP (context
) - 1;
117 #ifdef __USING_SJLJ_EXCEPTIONS__
118 /* The given "IP" is an index into the call-site table, with two
119 exceptions -- -1 means no-action, and 0 means terminate. But
120 since we're using uleb128 values, we've not got random access
123 return _URC_CONTINUE_UNWIND
;
126 _Unwind_Word cs_lp
, cs_action
;
129 p
= read_uleb128 (p
, &cs_lp
);
130 p
= read_uleb128 (p
, &cs_action
);
134 /* Can never have null landing pad for sjlj -- that would have
135 been indicated by a -1 call site index. */
136 landing_pad
= cs_lp
+ 1;
138 action_record
= info
.action_table
+ cs_action
- 1;
139 goto found_something
;
142 /* Search the call-site table for the action associated with this IP. */
143 while (p
< info
.action_table
)
145 _Unwind_Ptr cs_start
, cs_len
, cs_lp
;
146 _Unwind_Word cs_action
;
148 /* Note that all call-site encodings are "absolute" displacements. */
149 p
= read_encoded_value (0, info
.call_site_encoding
, p
, &cs_start
);
150 p
= read_encoded_value (0, info
.call_site_encoding
, p
, &cs_len
);
151 p
= read_encoded_value (0, info
.call_site_encoding
, p
, &cs_lp
);
152 p
= read_uleb128 (p
, &cs_action
);
154 /* The table is sorted, so if we've passed the ip, stop. */
155 if (ip
< info
.Start
+ cs_start
)
156 p
= info
.action_table
;
157 else if (ip
< info
.Start
+ cs_start
+ cs_len
)
160 landing_pad
= info
.LPStart
+ cs_lp
;
162 action_record
= info
.action_table
+ cs_action
- 1;
163 goto found_something
;
169 /* IP is not in table. No associated cleanups. */
170 /* ??? This is where C++ calls std::terminate to catch throw
171 from a destructor. */
172 return _URC_CONTINUE_UNWIND
;
175 if (landing_pad
== 0)
177 /* IP is present, but has a null landing pad.
178 No handler to be run. */
179 return _URC_CONTINUE_UNWIND
;
182 _Unwind_SetGR (context
, __builtin_eh_return_data_regno (0),
183 (_Unwind_Ptr
) ue_header
);
184 _Unwind_SetGR (context
, __builtin_eh_return_data_regno (1), 0);
185 _Unwind_SetIP (context
, landing_pad
);
186 return _URC_INSTALL_CONTEXT
;