unwind-c.c revision 119256
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
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING.  If not, write to the Free
20Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2102111-1307, USA.  */
22
23#include "tconfig.h"
24#include "tsystem.h"
25#include "unwind.h"
26#include "unwind-pe.h"
27
28typedef 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
39static const unsigned char *
40parse_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
82PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
83		      struct _Unwind_Exception *, struct _Unwind_Context *);
84
85_Unwind_Reason_Code
86PERSONALITY_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}
186