]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/gcc/unwind-c.c
This commit was generated by cvs2svn to compensate for changes in r131962,
[FreeBSD/FreeBSD.git] / contrib / gcc / unwind-c.c
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.
5
6 This file is part of GCC.
7
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
11 version.
12
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
16 for more details.
17
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
21 02111-1307, USA.  */
22
23 #include "tconfig.h"
24 #include "tsystem.h"
25 #include "unwind.h"
26 #include "unwind-pe.h"
27
28 typedef struct
29 {
30   _Unwind_Ptr Start;
31   _Unwind_Ptr LPStart;
32   _Unwind_Ptr ttype_base;
33   const unsigned char *TType;
34   const unsigned char *action_table;
35   unsigned char ttype_encoding;
36   unsigned char call_site_encoding;
37 } lsda_header_info;
38
39 static const unsigned char *
40 parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
41                    lsda_header_info *info)
42 {
43   _Unwind_Word tmp;
44   unsigned char lpstart_encoding;
45
46   info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
47
48   /* Find @LPStart, the base to which landing pad offsets are relative.  */
49   lpstart_encoding = *p++;
50   if (lpstart_encoding != DW_EH_PE_omit)
51     p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
52   else
53     info->LPStart = info->Start;
54
55   /* Find @TType, the base of the handler and exception spec type data.  */
56   info->ttype_encoding = *p++;
57   if (info->ttype_encoding != DW_EH_PE_omit)
58     {
59       p = read_uleb128 (p, &tmp);
60       info->TType = p + tmp;
61     }
62   else
63     info->TType = 0;
64
65   /* The encoding and length of the call-site table; the action table
66      immediately follows.  */
67   info->call_site_encoding = *p++;
68   p = read_uleb128 (p, &tmp);
69   info->action_table = p + tmp;
70
71   return p;
72 }
73
74 #ifdef __USING_SJLJ_EXCEPTIONS__
75 #define PERSONALITY_FUNCTION    __gcc_personality_sj0
76 #define __builtin_eh_return_data_regno(x) x
77 #else
78 #define PERSONALITY_FUNCTION    __gcc_personality_v0
79 #endif
80
81 _Unwind_Reason_Code
82 PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
83                       struct _Unwind_Exception *, struct _Unwind_Context *);
84
85 _Unwind_Reason_Code
86 PERSONALITY_FUNCTION (int version,
87                       _Unwind_Action actions,
88                       _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED,
89                       struct _Unwind_Exception *ue_header,
90                       struct _Unwind_Context *context)
91 {
92   lsda_header_info info;
93   const unsigned char *language_specific_data, *p, *action_record;
94   _Unwind_Ptr landing_pad, ip;
95
96   if (version != 1)
97     return _URC_FATAL_PHASE1_ERROR;
98
99   /* Currently we only support cleanups for C.  */
100   if ((actions & _UA_CLEANUP_PHASE) == 0)
101     return _URC_CONTINUE_UNWIND;
102
103   language_specific_data = (const unsigned char *)
104     _Unwind_GetLanguageSpecificData (context);
105
106   /* If no LSDA, then there are no handlers or cleanups.  */
107   if (! language_specific_data)
108     return _URC_CONTINUE_UNWIND;
109
110   /* Parse the LSDA header.  */
111   p = parse_lsda_header (context, language_specific_data, &info);
112   ip = _Unwind_GetIP (context) - 1;
113   landing_pad = 0;
114
115 #ifdef __USING_SJLJ_EXCEPTIONS__
116   /* The given "IP" is an index into the call-site table, with two
117      exceptions -- -1 means no-action, and 0 means terminate.  But
118      since we're using uleb128 values, we've not got random access
119      to the array.  */
120   if ((int) ip <= 0)
121     return _URC_CONTINUE_UNWIND;
122   else
123     {
124       _Unwind_Word cs_lp, cs_action;
125       do
126         {
127           p = read_uleb128 (p, &cs_lp);
128           p = read_uleb128 (p, &cs_action);
129         }
130       while (--ip);
131
132       /* Can never have null landing pad for sjlj -- that would have
133          been indicated by a -1 call site index.  */
134       landing_pad = cs_lp + 1;
135       if (cs_action)
136         action_record = info.action_table + cs_action - 1;
137       goto found_something;
138     }
139 #else
140   /* Search the call-site table for the action associated with this IP.  */
141   while (p < info.action_table)
142     {
143       _Unwind_Ptr cs_start, cs_len, cs_lp;
144       _Unwind_Word cs_action;
145
146       /* Note that all call-site encodings are "absolute" displacements.  */
147       p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
148       p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
149       p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
150       p = read_uleb128 (p, &cs_action);
151
152       /* The table is sorted, so if we've passed the ip, stop.  */
153       if (ip < info.Start + cs_start)
154         p = info.action_table;
155       else if (ip < info.Start + cs_start + cs_len)
156         {
157           if (cs_lp)
158             landing_pad = info.LPStart + cs_lp;
159           if (cs_action)
160             action_record = info.action_table + cs_action - 1;
161           goto found_something;
162         }
163     }
164   
165 #endif
166
167   /* IP is not in table.  No associated cleanups.  */
168   /* ??? This is where C++ calls std::terminate to catch throw
169      from a destructor.  */
170   return _URC_CONTINUE_UNWIND;
171
172  found_something:
173   if (landing_pad == 0)
174     {
175       /* IP is present, but has a null landing pad.
176          No handler to be run.  */
177       return _URC_CONTINUE_UNWIND;
178     }
179
180   _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
181                  (_Unwind_Ptr) ue_header);
182   _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), 0);
183   _Unwind_SetIP (context, landing_pad);
184   return _URC_INSTALL_CONTEXT;
185 }