1*38fd1498Szrj // -*- C++ -*- Exception handling routines for catching.
2*38fd1498Szrj // Copyright (C) 2001-2018 Free Software Foundation, Inc.
3*38fd1498Szrj //
4*38fd1498Szrj // This file is part of GCC.
5*38fd1498Szrj //
6*38fd1498Szrj // GCC is free software; you can redistribute it and/or modify
7*38fd1498Szrj // it under the terms of the GNU General Public License as published by
8*38fd1498Szrj // the Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj // any later version.
10*38fd1498Szrj //
11*38fd1498Szrj // GCC is distributed in the hope that it will be useful,
12*38fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*38fd1498Szrj // GNU General Public License for more details.
15*38fd1498Szrj //
16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
18*38fd1498Szrj // 3.1, as published by the Free Software Foundation.
19*38fd1498Szrj
20*38fd1498Szrj // You should have received a copy of the GNU General Public License and
21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23*38fd1498Szrj // <http://www.gnu.org/licenses/>.
24*38fd1498Szrj
25*38fd1498Szrj #include <cstdlib>
26*38fd1498Szrj #include "unwind-cxx.h"
27*38fd1498Szrj
28*38fd1498Szrj using namespace __cxxabiv1;
29*38fd1498Szrj
30*38fd1498Szrj extern "C" void *
__cxa_get_exception_ptr(void * exc_obj_in)31*38fd1498Szrj __cxxabiv1::__cxa_get_exception_ptr(void *exc_obj_in) _GLIBCXX_NOTHROW
32*38fd1498Szrj {
33*38fd1498Szrj _Unwind_Exception *exceptionObject
34*38fd1498Szrj = reinterpret_cast <_Unwind_Exception *>(exc_obj_in);
35*38fd1498Szrj
36*38fd1498Szrj return __gxx_caught_object(exceptionObject);
37*38fd1498Szrj }
38*38fd1498Szrj
39*38fd1498Szrj extern "C" void *
__cxa_begin_catch(void * exc_obj_in)40*38fd1498Szrj __cxxabiv1::__cxa_begin_catch (void *exc_obj_in) _GLIBCXX_NOTHROW
41*38fd1498Szrj {
42*38fd1498Szrj _Unwind_Exception *exceptionObject
43*38fd1498Szrj = reinterpret_cast <_Unwind_Exception *>(exc_obj_in);
44*38fd1498Szrj __cxa_eh_globals *globals = __cxa_get_globals ();
45*38fd1498Szrj __cxa_exception *prev = globals->caughtExceptions;
46*38fd1498Szrj __cxa_exception *header = __get_exception_header_from_ue (exceptionObject);
47*38fd1498Szrj void* objectp;
48*38fd1498Szrj
49*38fd1498Szrj // Foreign exceptions can't be stacked here. If the exception stack is
50*38fd1498Szrj // empty, then fine. Otherwise we really have no choice but to terminate.
51*38fd1498Szrj // Note that this use of "header" is a lie. It's fine so long as we only
52*38fd1498Szrj // examine header->unwindHeader though.
53*38fd1498Szrj if (!__is_gxx_exception_class(header->unwindHeader.exception_class))
54*38fd1498Szrj {
55*38fd1498Szrj if (prev != 0)
56*38fd1498Szrj std::terminate ();
57*38fd1498Szrj
58*38fd1498Szrj // Remember for end_catch and rethrow.
59*38fd1498Szrj globals->caughtExceptions = header;
60*38fd1498Szrj
61*38fd1498Szrj // ??? No sensible value to return; we don't know what the
62*38fd1498Szrj // object is, much less where it is in relation to the header.
63*38fd1498Szrj return 0;
64*38fd1498Szrj }
65*38fd1498Szrj
66*38fd1498Szrj int count = header->handlerCount;
67*38fd1498Szrj // Count is less than zero if this exception was rethrown from an
68*38fd1498Szrj // immediately enclosing region.
69*38fd1498Szrj if (count < 0)
70*38fd1498Szrj count = -count + 1;
71*38fd1498Szrj else
72*38fd1498Szrj count += 1;
73*38fd1498Szrj header->handlerCount = count;
74*38fd1498Szrj globals->uncaughtExceptions -= 1;
75*38fd1498Szrj
76*38fd1498Szrj if (header != prev)
77*38fd1498Szrj {
78*38fd1498Szrj header->nextException = prev;
79*38fd1498Szrj globals->caughtExceptions = header;
80*38fd1498Szrj }
81*38fd1498Szrj
82*38fd1498Szrj objectp = __gxx_caught_object(exceptionObject);
83*38fd1498Szrj
84*38fd1498Szrj PROBE2 (catch, objectp, header->exceptionType);
85*38fd1498Szrj
86*38fd1498Szrj #ifdef __ARM_EABI_UNWINDER__
87*38fd1498Szrj _Unwind_Complete(exceptionObject);
88*38fd1498Szrj #endif
89*38fd1498Szrj return objectp;
90*38fd1498Szrj }
91*38fd1498Szrj
92*38fd1498Szrj
93*38fd1498Szrj extern "C" void
__cxa_end_catch()94*38fd1498Szrj __cxxabiv1::__cxa_end_catch ()
95*38fd1498Szrj {
96*38fd1498Szrj __cxa_eh_globals *globals = __cxa_get_globals_fast ();
97*38fd1498Szrj __cxa_exception *header = globals->caughtExceptions;
98*38fd1498Szrj
99*38fd1498Szrj // A rethrow of a foreign exception will be removed from the
100*38fd1498Szrj // the exception stack immediately by __cxa_rethrow.
101*38fd1498Szrj if (!header)
102*38fd1498Szrj return;
103*38fd1498Szrj
104*38fd1498Szrj // A foreign exception couldn't have been stacked (see above),
105*38fd1498Szrj // so by definition processing must be complete.
106*38fd1498Szrj if (!__is_gxx_exception_class(header->unwindHeader.exception_class))
107*38fd1498Szrj {
108*38fd1498Szrj globals->caughtExceptions = 0;
109*38fd1498Szrj _Unwind_DeleteException (&header->unwindHeader);
110*38fd1498Szrj return;
111*38fd1498Szrj }
112*38fd1498Szrj
113*38fd1498Szrj int count = header->handlerCount;
114*38fd1498Szrj if (count < 0)
115*38fd1498Szrj {
116*38fd1498Szrj // This exception was rethrown. Decrement the (inverted) catch
117*38fd1498Szrj // count and remove it from the chain when it reaches zero.
118*38fd1498Szrj if (++count == 0)
119*38fd1498Szrj globals->caughtExceptions = header->nextException;
120*38fd1498Szrj }
121*38fd1498Szrj else if (--count == 0)
122*38fd1498Szrj {
123*38fd1498Szrj // Handling for this exception is complete. Destroy the object.
124*38fd1498Szrj globals->caughtExceptions = header->nextException;
125*38fd1498Szrj _Unwind_DeleteException (&header->unwindHeader);
126*38fd1498Szrj return;
127*38fd1498Szrj }
128*38fd1498Szrj else if (count < 0)
129*38fd1498Szrj // A bug in the exception handling library or compiler.
130*38fd1498Szrj std::terminate ();
131*38fd1498Szrj
132*38fd1498Szrj header->handlerCount = count;
133*38fd1498Szrj }
134*38fd1498Szrj
135*38fd1498Szrj
136*38fd1498Szrj bool
uncaught_exception()137*38fd1498Szrj std::uncaught_exception() throw()
138*38fd1498Szrj {
139*38fd1498Szrj #if __cpp_exceptions
140*38fd1498Szrj __cxa_eh_globals *globals = __cxa_get_globals ();
141*38fd1498Szrj return globals->uncaughtExceptions != 0;
142*38fd1498Szrj #else
143*38fd1498Szrj return false;
144*38fd1498Szrj #endif
145*38fd1498Szrj }
146*38fd1498Szrj
147*38fd1498Szrj int
uncaught_exceptions()148*38fd1498Szrj std::uncaught_exceptions() throw()
149*38fd1498Szrj {
150*38fd1498Szrj #if __cpp_exceptions
151*38fd1498Szrj __cxa_eh_globals *globals = __cxa_get_globals ();
152*38fd1498Szrj return globals->uncaughtExceptions;
153*38fd1498Szrj #else
154*38fd1498Szrj return 0;
155*38fd1498Szrj #endif
156*38fd1498Szrj }
157