1 /* Exception (throw catch) mechanism, for GDB, the GNU debugger.
3 Copyright (C) 1986-2019 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #include "common-defs.h"
21 #include "common-exceptions.h"
22 #include <forward_list>
24 const struct gdb_exception exception_none;
26 /* Possible catcher states. */
28 /* Initial state, a new catcher has just been created. */
30 /* The catch code is running. */
33 /* The catch code threw an exception. */
37 /* Possible catcher actions. */
46 enum catcher_state state = CATCHER_CREATED;
47 /* Jump buffer pointing back at the exception handler. */
49 /* Status buffer belonging to the exception handler. */
50 struct gdb_exception exception = exception_none;
53 /* Where to go for throw_exception(). */
54 static std::forward_list<struct catcher> catchers;
57 exceptions_state_mc_init ()
59 catchers.emplace_front ();
60 return &catchers.front ().buf;
63 /* Catcher state machine. Returns non-zero if the m/c should be run
64 again, zero if it should abort. */
67 exceptions_state_mc (enum catcher_action action)
69 switch (catchers.front ().state)
75 /* Allow the code to run the catcher. */
76 catchers.front ().state = CATCHER_RUNNING;
79 internal_error (__FILE__, __LINE__, _("bad state"));
85 /* No error/quit has occured. */
88 catchers.front ().state = CATCHER_RUNNING_1;
91 catchers.front ().state = CATCHER_ABORTING;
92 /* See also throw_exception. */
95 internal_error (__FILE__, __LINE__, _("bad switch"));
97 case CATCHER_RUNNING_1:
101 /* The did a "break" from the inner while loop. */
104 catchers.front ().state = CATCHER_RUNNING;
107 catchers.front ().state = CATCHER_ABORTING;
108 /* See also throw_exception. */
111 internal_error (__FILE__, __LINE__, _("bad switch"));
113 case CATCHER_ABORTING:
118 /* Exit normally if this catcher can handle this
119 exception. The caller analyses the func return
124 internal_error (__FILE__, __LINE__, _("bad state"));
127 internal_error (__FILE__, __LINE__, _("bad switch"));
132 exceptions_state_mc_catch (struct gdb_exception *exception,
135 *exception = std::move (catchers.front ().exception);
136 catchers.pop_front ();
138 if (exception->reason < 0)
140 if (mask & RETURN_MASK (exception->reason))
142 /* Exit normally and let the caller handle the
147 /* The caller didn't request that the event be caught, relay the
148 event to the next exception_catch/CATCH_SJLJ. */
149 throw_exception_sjlj (*exception);
152 /* No exception was thrown. */
157 exceptions_state_mc_action_iter (void)
159 return exceptions_state_mc (CATCH_ITER);
163 exceptions_state_mc_action_iter_1 (void)
165 return exceptions_state_mc (CATCH_ITER_1);
168 /* Called by the default catch block. IOW, we'll get here before
169 jumping out to the next outermost scope an exception if a GDB
170 exception is not caught. */
173 exception_rethrow (void)
178 /* Return EXCEPTION to the nearest containing CATCH_SJLJ block. */
181 throw_exception_sjlj (struct gdb_exception exception)
183 /* Jump to the nearest CATCH_SJLJ block, communicating REASON to
184 that call via setjmp's return value. Note that REASON can't be
185 zero, by definition in common-exceptions.h. */
186 exceptions_state_mc (CATCH_THROWING);
187 catchers.front ().exception = exception;
188 longjmp (catchers.front ().buf, exception.reason);
191 /* Implementation of throw_exception that uses C++ try/catch. */
193 static ATTRIBUTE_NORETURN void
194 throw_exception_cxx (struct gdb_exception exception)
196 if (exception.reason == RETURN_QUIT)
198 gdb_exception_quit ex (exception);
201 else if (exception.reason == RETURN_ERROR)
203 gdb_exception_error ex (exception);
207 gdb_assert_not_reached ("invalid return reason");
211 throw_exception (struct gdb_exception exception)
213 throw_exception_cxx (exception);
216 static void ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 0)
217 throw_it (enum return_reason reason, enum errors error, const char *fmt,
220 struct gdb_exception e;
222 /* Create the exception. */
225 e.message.reset (new std::string (string_vprintf (fmt, ap)));
227 /* Throw the exception. */
232 throw_verror (enum errors error, const char *fmt, va_list ap)
234 throw_it (RETURN_ERROR, error, fmt, ap);
238 throw_vquit (const char *fmt, va_list ap)
240 throw_it (RETURN_QUIT, GDB_NO_ERROR, fmt, ap);
244 throw_error (enum errors error, const char *fmt, ...)
248 va_start (args, fmt);
249 throw_verror (error, fmt, args);
254 throw_quit (const char *fmt, ...)
258 va_start (args, fmt);
259 throw_vquit (fmt, args);