eh_call.cc revision 169691
1// -*- C++ -*- Helpers for calling unextected and terminate
2// Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
3//
4// This file is part of GCC.
5//
6// GCC is free software; you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 2, or (at your option)
9// any later version.
10//
11// GCC is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with GCC; see the file COPYING.  If not, write to
18// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19// Boston, MA 02110-1301, USA.
20
21// As a special exception, you may use this file as part of a free software
22// library without restriction.  Specifically, if other files instantiate
23// templates or use macros or inline functions from this file, or you compile
24// this file and link it with other files to produce an executable, this
25// file does not by itself cause the resulting executable to be covered by
26// the GNU General Public License.  This exception does not however
27// invalidate any other reasons why the executable file might be covered by
28// the GNU General Public License.
29
30#include <bits/c++config.h>
31#include <cstdlib>
32#include <exception_defines.h>
33#include "unwind-cxx.h"
34
35using namespace __cxxabiv1;
36
37#include "unwind-pe.h"
38
39
40// Helper routine for when the exception handling code needs to call
41// terminate.
42
43extern "C" void
44__cxa_call_terminate(_Unwind_Exception* ue_header)
45{
46
47  if (ue_header)
48    {
49      // terminate is classed as a catch handler.
50      __cxa_begin_catch(ue_header);
51
52      // Call the terminate handler that was in effect when we threw this
53      // exception.  */
54      if (__is_gxx_exception_class(ue_header->exception_class))
55	{
56	  __cxa_exception* xh;
57
58	  xh = __get_exception_header_from_ue(ue_header);
59	  __terminate(xh->terminateHandler);
60	}
61    }
62  /* Call the global routine if we don't have anything better.  */
63  std::terminate();
64}
65
66
67#ifdef __ARM_EABI_UNWINDER__
68// The ARM EABI __cxa_call_unexpected has the same semantics as the generic
69// routine, but the exception specification has a different format.
70extern "C" void
71__cxa_call_unexpected(void* exc_obj_in)
72{
73  _Unwind_Exception* exc_obj
74    = reinterpret_cast<_Unwind_Exception*>(exc_obj_in);
75
76  int rtti_count = 0;
77  _Unwind_Word rtti_stride = 0;
78  _Unwind_Word* rtti_list = NULL;
79  bool foreign_exception;
80  std::unexpected_handler unexpectedHandler = NULL;
81  std::terminate_handler terminateHandler = NULL;
82  __cxa_exception* xh;
83  if (__is_gxx_exception_class(exc_obj->exception_class))
84    {
85      // Save data from the EO, which may be clobbered by _cxa_begin_catch.
86      xh = __get_exception_header_from_ue(exc_obj);
87      unexpectedHandler = xh->unexpectedHandler;
88      terminateHandler = xh->terminateHandler;
89      rtti_count = exc_obj->barrier_cache.bitpattern[1];
90
91      rtti_stride = exc_obj->barrier_cache.bitpattern[3];
92      rtti_list = (_Unwind_Word*) exc_obj->barrier_cache.bitpattern[4];
93      foreign_exception = false;
94    }
95  else
96    foreign_exception = true;
97
98  /* This must be called after extracting data from the EO, but before
99     calling unexpected().   */
100  __cxa_begin_catch(exc_obj);
101
102  // This function is a handler for our exception argument.  If we exit
103  // by throwing a different exception, we'll need the original cleaned up.
104  struct end_catch_protect
105  {
106    end_catch_protect() { }
107    ~end_catch_protect() { __cxa_end_catch(); }
108  } end_catch_protect_obj;
109
110
111  try
112    {
113      if (foreign_exception)
114	std::unexpected();
115      else
116	__unexpected(unexpectedHandler);
117    }
118  catch(...)
119    {
120      /* See if the new exception matches the rtti list.  */
121      if (foreign_exception)
122	std::terminate();
123
124      // Get the exception thrown from unexpected.
125
126      __cxa_eh_globals* globals = __cxa_get_globals_fast();
127      __cxa_exception* new_xh = globals->caughtExceptions;
128      void* new_ptr = new_xh + 1;
129      const std::type_info* catch_type;
130      int n;
131      bool bad_exception_allowed = false;
132      const std::type_info& bad_exc = typeid(std::bad_exception);
133
134      // Check the new exception against the rtti list
135      for (n = 0; n < rtti_count; n++)
136	{
137	  _Unwind_Word offset;
138
139	  offset = (_Unwind_Word) &rtti_list[n * (rtti_stride >> 2)];
140	  offset = _Unwind_decode_target2(offset);
141	  catch_type = (const std::type_info*) (offset);
142
143	  if (__cxa_type_match(&new_xh->unwindHeader, catch_type, false,
144			       &new_ptr) != ctm_failed)
145	    __throw_exception_again;
146
147	  if (catch_type->__do_catch(&bad_exc, 0, 1))
148	    bad_exception_allowed = true;
149	}
150
151      // If the exception spec allows std::bad_exception, throw that.
152#ifdef __EXCEPTIONS
153      if (bad_exception_allowed)
154	throw std::bad_exception();
155#endif
156
157      // Otherwise, die.
158      __terminate(terminateHandler);
159    }
160}
161#endif // __ARM_EABI_UNWINDER__
162