aboutsummaryrefslogtreecommitdiff
path: root/gdb/common/common-exceptions.h
AgeCommit message (Collapse)AuthorFilesLines
2017-01-01update copyright year range in GDB filesJoel Brobecker1-1/+1
This applies the second part of GDB's End of Year Procedure, which updates the copyright year range in all of GDB's files. gdb/ChangeLog: Update copyright year range in all GDB files.
2016-10-06gdb: Remove some C compiler support leftoversPedro Alves1-15/+8
Remove some __cplusplus checks, inline EXPORTED_CONST, and update some comments. gdb/ChangeLog: 2016-10-06 Pedro Alves <palves@redhat.com> * cp-valprint.c (vtbl_ptr_name): Write "extern const" instead of EXPORTED_CONST. * stub-termcap.c: Remove __cplusplus checks. * common/common-defs.h [!__cplusplus] (EXTERN_C, EXTERN_C_PUSH, EXTERN_C_POP): Delete. * common/common-exceptions.h (GDB_XCPT_SJMP): Update comments. (GDB_XCPT) [!__cplusplus]: Delete. (throw_exception, throw_exception_sjlj): Update comments. * guile/guile-internal.h (as_a_scm_t_subr) [!__cplusplus]: Delete. * guile/guile.c (extension_language_guile): Write "extern const" instead of EXPORTED_CONST. * features/feature_to_c.sh: Don't emit !__cplusplus code. Write "extern const" instead of EXPORTED_CONST.
2016-09-23gdb: Replace operator new / operator new[]Pedro Alves1-0/+20
If xmalloc fails allocating memory, usually because something tried a huge allocation, like xmalloc(-1) or some such, GDB asks the user what to do: .../src/gdb/utils.c:1079: internal-error: virtual memory exhausted. A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n) If the user says "n", that throws a QUIT exception, which is caught by one of the multiple CATCH(RETURN_MASK_ALL) blocks somewhere up the stack. The default implementations of operator new / operator new[] call malloc directly, and on memory allocation failure throw std::bad_alloc. Currently, if that happens, since nothing catches it, the exception escapes out of main, and GDB aborts from unhandled exception. This patch replaces the default operator new variants with versions that, just like xmalloc: #1 - Raise an internal-error on memory allocation failure. #2 - Throw a QUIT gdb_exception, so that the exact same CATCH blocks continue handling memory allocation problems. A minor complication of #2 is that operator new can _only_ throw std::bad_alloc, or something that extends it: void* operator new (std::size_t size) throw (std::bad_alloc); That means that if we let a gdb QUIT exception escape from within operator new, the C++ runtime aborts due to unexpected exception thrown. So to bridge the gap, this patch adds a new gdb_quit_bad_alloc exception type that inherits both std::bad_alloc and gdb_exception, and throws _that_. If we decide that we should be catching memory allocation errors in fewer places than all the places we currently catch them (everywhere we use RETURN_MASK_ALL currently), then we could change operator new to throw plain std::bad_alloc then. But I'm considering such a change as separate matter from this one -- it'd make sense to do the same to xmalloc at the same time, for instance. Meanwhile, this allows using new/new[] instead of xmalloc/XNEW/etc. without losing the "virtual memory exhausted" internal-error safeguard. Tested on x86_64 Fedora 23. gdb/ChangeLog: 2016-09-23 Pedro Alves <palves@redhat.com> * Makefile.in (SFILES): Add common/new-op.c. (COMMON_OBS): Add common/new-op.o. (new-op.o): New rule. * common/common-exceptions.h: Include <new>. (struct gdb_quit_bad_alloc): New type. * common/new-op.c: New file. gdb/gdbserver/ChangeLog: 2016-09-23 Pedro Alves <palves@redhat.com> * Makefile.in (SFILES): Add common/new-op.c. (OBS): Add common/new-op.o. (new-op.o): New rule.
2016-04-22Switch gdb's TRY/CATCH to C++ try/catchPedro Alves1-5/+6
The exceptions-across-readline issue was fixed by the previous commit. Let's try this again. gdb/ChangeLog: 2016-04-22 Pedro Alves <palves@redhat.com> * common/common-exceptions.h (GDB_XCPT_TRY): Remove mention of the foreign frames issue. [__cplusplus] (GDB_XCPT): Define as GDB_XCPT_TRY.
2016-04-22Propagate GDB/C++ exceptions across readline using sj/lj-based TRY/CATCHPedro Alves1-23/+41
If we map GDB'S TRY/CATCH macros to C++ try/catch, GDB breaks on systems where readline isn't built with exceptions support. The problem is that readline calls into GDB through the callback interface, and if GDB's callback throws a C++ exception/error, the system unwinder won't manage to unwind past the readline frame, and ends up calling std::terminate(), which aborts the process: (gdb) whatever-command-that-causes-an-error terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR' Aborted $ This went unnoticed for so long because: - the x86-64 ABI requires -fasynchronous-unwind-tables, making it possible for exceptions to cross readline with no special handling. But e.g., on ARM or AIX, unless you build readline with -fexceptions, you trip on the problem. - TRY/CATCH was mapped to setjmp/longjmp, even in C++ mode, until quite recently. The fix is to catch and save any GDB exception that is thrown inside the GDB readline callback, and then once the callback returns back to the GDB code that called into readline in the first place, rethrow the saved GDB exception. This is similar in spirit to how we catch/map GDB exceptions at the GDB/Python and GDB/Guile API boundaries. The next question is then: if we intercept all exceptions within GDB's readline callback, should we simply return normally to readline? The callback prototype has no way to signal an error back to readline (*). The answer is no -- if we return normally, we'll be returning to a loop inside rl_callback_read_char that continues processing pending input, calling into GDB again, redisplaying the prompt, etc. Thus if we want to error out of rl_callback_read_char, we need to long jump across it, just like we always did before TRY/CATCH were ever mapped to C++ exceptions. My first approach built a specialized API to handle this, with a couple macros to hide the setjmp/longjmp and the struct gdb_exception saving/rethrowing. However, I realized that we need to: - Handle multiple active rl_callback_read_char invocations. If, while processing input something triggers a secondary prompt, we end up in a nested rl_callback_read_char call, through gdb_readline_wrapper. - Propagate a struct gdb_exception along with the longjmp. ... and that this is exactly what the setjmp/longjmp-based TRY/CATCH does. So the fix makes the setjmp/longjmp TRY/CATCH always available under new TRY_SJLJ/CATCH_SJLJ aliases, even when TRY/CATCH is mapped to C++ try/catch, and then uses TRY_SJLJ/CATCH_SJLJ to propagate GDB exceptions across the readline callback. This turns out to be a much better looking fix than my bespoke API attempt, even. We'll probably be able to simplify TRY_SJLJ/CATCH_SJLJ when we finally get rid of TRY/CATCH all over the tree, but until then, this reuse seems quite nice for avoiding a second parallel setjmp/longjmp mechanism. (*) - maybe we could propose a readline API change, but we still need to handle current readline, anyway. gdb/ChangeLog: 2016-04-22 Pedro Alves <palves@redhat.com> * common/common-exceptions.c (enum catcher_state, struct catcher) (current_catcher): Define in C++ mode too. (exceptions_state_mc_catch): Call throw_exception_sjlj instead of throw_exception. (throw_exception_sjlj, throw_exception_cxx): New functions, factored out from throw_exception. (throw_exception): Reimplement. * common/common-exceptions.h (exceptions_state_mc_init) (exceptions_state_mc_action_iter) (exceptions_state_mc_action_iter_1, exceptions_state_mc_catch): Declare in C++ mode too. (TRY): Rename to ... (TRY_SJLJ): ... this. (CATCH): Rename to ... (CATCH_SJLJ): ... this. (END_CATCH): Rename to ... (END_CATCH_SJLJ): ... this. [GDB_XCPT == GDB_XCPT_SJMP] (TRY, CATCH, END_CATCH): Map to SJLJ equivalents. (throw_exception): Update comments. (throw_exception_sjlj): Declare. * event-top.c (gdb_rl_callback_read_char_wrapper): Extend intro comment. Wrap body in TRY_SJLJ/CATCH_SJLJ and rethrow any intercepted exception. (gdb_rl_callback_handler): New function. (gdb_rl_callback_handler_install): Always install gdb_rl_callback_handler as readline callback.
2016-04-21Switch gdb's TRY/CATCH to sjlj againPedro Alves1-6/+5
We don't currently handle the case of gdb's readline callback throwing gdb C++ exceptions across a readline that wasn't built with -fexceptions. The end result is: (gdb) whatever-command-that-causes-an-error terminate called after throwing an instance of 'gdb_exception_RETURN_MASK_ERROR' Aborted $ Until that is fixed, revert back to sjlj-based exceptions again. gdb/ChangeLog: 2016-04-21 Pedro Alves <palves@redhat.com> * common/common-exceptions.h (GDB_XCPT_TRY): Add comment. (GDB_XCPT): Always define as GDB_XCPT_SJMP.
2016-04-12[C++] Switch TRY/CATCH to real C++ try/catch by default againPedro Alves1-5/+6
Now that we don't ever throw GDB exceptions from signal handlers [1], we can switch back to having TRY/CATCH implemented in terms of C++ try/catch instead of sigjmp/longjmp. [1] - https://sourceware.org/ml/gdb-patches/2016-03/msg00351.html Tested on x86_64 Fedora 23, native and gdbserver. gdb/ChangeLog: 2016-04-12 Pedro Alves <palves@redhat.com> * common/common-exceptions.h (GDB_XCPT_TRY): Update comment. [__cplusplus] (GDB_XCPT): Define as GDB_XCPT_TRY.
2016-04-12Use setjmp/longjmp for TRY/CATCH instead of sigsetjmp/siglongjmpPedro Alves1-4/+4
Now that we don't ever throw GDB exceptions from signal handlers [1], we can switch to have TRY/CATCH implemented in terms of plain setjmp/longjmp instead of sigsetjmp/siglongjmp. In https://sourceware.org/ml/gdb-patches/2015-02/msg00114.html, Yichun Zhang mentions a 11%/14%+ speedup in his GDB python scripts with a patch that did something similar to only a specific set of TRY/CATCH calls. [1] - https://sourceware.org/ml/gdb-patches/2016-03/msg00351.html Tested on x86_64 Fedora 23, native and gdbserver. gdb/ChangeLog: 2016-04-12 Pedro Alves <palves@redhat.com> * common/common-exceptions.c (struct catcher) <buf>: Now a 'jmp_buf' instead of SIGJMP_BUF. (exceptions_state_mc_init): Change return type to 'jmp_buf'. (throw_exception): Use longjmp instead of SIGLONGJMP. * common/common-exceptions.h: Include <setjmp.h> instead of "gdb_setjmp.h". (exceptions_state_mc_init): Change return type to 'jmp_buf'. [GDB_XCPT == GDB_XCPT_SJMP] (TRY): Use setjmp instead of SIGSETJMP. * cp-support.c: Include "gdb_setjmp.h".
2016-04-12Eliminate prepare_to_throw_exceptionPedro Alves1-6/+0
No longer necessary. gdb/ChangeLog: 2016-04-12 Pedro Alves <palves@redhat.com> * common/common-exceptions.c (exception_rethrow): Remove prepare_to_throw_exception call. * common/common-exceptions.h (prepare_to_throw_exception): Delete declaration. * exceptions.c (prepare_to_throw_exception): Delete. gdb/gdbserver/ChangeLog: 2016-04-12 Pedro Alves <palves@redhat.com> * utils.c (prepare_to_throw_exception): Delete.
2016-01-01GDB copyright headers update after running GDB's copyright.py script.Joel Brobecker1-1/+1
gdb/ChangeLog: Update year range in copyright notice of all files.
2015-11-17[C++] Always use setjmp/longjmp for exceptionsPedro Alves1-11/+28
We currently throw exceptions from signal handlers (e.g., for Quit/ctrl-c). But throwing C++ exceptions from signal handlers is undefined. (That doesn't restore signal masks, like siglongjmp does, and, because asynchronous signals can arrive at any instruction, we'd have to build _everything_ with -fasync-unwind-tables to make it reliable.) It happens to work on x86_64 GNU/Linux at least, but it's likely broken on other ports. Until we stop throwing from signal handlers, use setjmp/longjmp based exceptions in C++ mode as well. gdb/ChangeLog: 2015-11-17 Pedro Alves <palves@redhat.com> * common/common-exceptions.h (GDB_XCPT_SJMP, GDB_XCPT_TRY) (GDB_XCPT_RAW_TRY, GDB_XCPT): Define. Replace __cplusplus checks with GDB_XCPT checks throughout. * common/common-exceptions.c: Replace __cplusplus checks with GDB_XCPT checks throughout.
2015-10-29Don't assume break/continue inside a TRY block worksPedro Alves1-0/+16
In C++, this: try { break; } catch (..) {} is invalid. However, because our TRY/CATCH macros support it in C, the C++ version of those macros support it too. To catch such assumptions, this adds a (disabled) hack that maps TRY/CATCH to raw C++ try/catch. Then it goes through all instances that building on x86_64 GNU/Linux trips on, fixing them. This isn't strictly necessary yet, but I think it's nicer to try to keep the tree in a state where it's easier to eliminate the TRY/CATCH macros. gdb/ChangeLog: 2015-10-29 Pedro Alves <palves@redhat.com> * dwarf2-frame-tailcall.c (dwarf2_tailcall_sniffer_first): Don't assume that "break" breaks out of a TRY/CATCH. * python/py-framefilter.c (py_print_single_arg): Don't assume "continue" breaks out of a TRY/CATCH. * python/py-value.c (valpy_binop_throw): New function, factored out from ... (valpy_binop): ... this. (valpy_richcompare_throw): New function, factored out from ... (valpy_richcompare): ... this. * solib.c (solib_read_symbols): Don't assume "break" breaks out of a TRY/CATCH. * common/common-exceptions.h [USE_RAW_CXX_TRY] <TRY/CATCH/END_CATCH>: Define as 1-1 wrappers around try/catch.
2015-03-07Make TRY/CATCH use real C++ try/catch in C++ modePedro Alves1-0/+67
Although the current TRY/CATCH implementation works in C++ mode too, it relies on setjmp/longjmp, and longjmp bypasses calling the destructors of objects on the stack, which is obviously bad for C++. This patch fixes this by makes TRY/CATCH use real try/catch in C++ mode behind the scenes. The way this is done allows RAII and cleanups to coexist while we phase out cleanups, instead of requiring a flag day. This patch is not strictly necessary until we require a C++ compiler and start actually using RAII, though I'm all for baby steps, and it shows my proposed way forward. Putting it in now, allows for easier experimentation and exposure of potential problems with real C++ exceptions. gdb/ChangeLog: 2015-03-07 Pedro Alves <palves@redhat.com> * common/common-exceptions.c [!__cplusplus] (enum catcher_state) (exceptions_state_mc_action_iter) (exceptions_state_mc_action_iter_1, exceptions_state_mc_catch): Don't define. [__cplusplus] (try_scope_depth): New global. [__cplusplus] (exception_try_scope_entry) (exception_try_scope_exit, gdb_exception_sliced_copy) (exception_rethrow): New functions. (throw_exception): In C++ mode, throw gdb_exception_RETURN_MASK_QUIT for RETURN_QUIT and gdb_exception_RETURN_MASK_ERROR for RETURN_ERROR. (throw_it): In C++ mode, use try_scope_depth. * common/common-exceptions.h [!__cplusplus] (exceptions_state_mc_action_iter) (exceptions_state_mc_action_iter_1, exceptions_state_mc_catch): Don't declare. [__cplusplus] (exception_try_scope_entry) (exception_try_scope_exit, exception_rethrow): Declare. [__cplusplus] (struct exception_try_scope): New struct. [__cplusplus] (TRY, CATCH, END_CATCH): Reimplement on top of real C++ exceptions. (struct gdb_exception_RETURN_MASK_ALL) (struct gdb_exception_RETURN_MASK_ERROR) (struct gdb_exception_RETURN_MASK_QUIT): New types.
2015-03-07Split TRY_CATCH into TRY + CATCHPedro Alves1-11/+21
This patch splits the TRY_CATCH macro into three, so that we go from this: ~~~ volatile gdb_exception ex; TRY_CATCH (ex, RETURN_MASK_ERROR) { } if (ex.reason < 0) { } ~~~ to this: ~~~ TRY { } CATCH (ex, RETURN_MASK_ERROR) { } END_CATCH ~~~ Thus, we'll be getting rid of the local volatile exception object, and declaring the caught exception in the catch block. This allows reimplementing TRY/CATCH in terms of C++ exceptions when building in C++ mode, while still allowing to build GDB in C mode (using setjmp/longjmp), as a transition step. TBC, after this patch, is it _not_ valid to have code between the TRY and the CATCH blocks, like: TRY { } // some code here. CATCH (ex, RETURN_MASK_ERROR) { } END_CATCH Just like it isn't valid to do that with C++'s native try/catch. By switching to creating the exception object inside the CATCH block scope, we can get rid of all the explicitly allocated volatile exception objects all over the tree, and map the CATCH block more directly to C++'s catch blocks. The majority of the TRY_CATCH -> TRY+CATCH+END_CATCH conversion was done with a script, rerun from scratch at every rebase, no manual editing involved. After the mechanical conversion, a few places needed manual intervention, to fix preexisting cases where we were using the exception object outside of the TRY_CATCH block, and cases where we were using "else" after a 'if (ex.reason) < 0)' [a CATCH after this patch]. The result was folded into this patch so that GDB still builds at each incremental step. END_CATCH is necessary for two reasons: First, because we name the exception object in the CATCH block, which requires creating a scope, which in turn must be closed somewhere. Declaring the exception variable in the initializer field of a for block, like: #define CATCH(EXCEPTION, mask) \ for (struct gdb_exception EXCEPTION; \ exceptions_state_mc_catch (&EXCEPTION, MASK); \ EXCEPTION = exception_none) would avoid needing END_CATCH, but alas, in C mode, we build with C90, which doesn't allow mixed declarations and code. Second, because when TRY/CATCH are wired to real C++ try/catch, as long as we need to handle cleanup chains, even if there's no CATCH block that wants to catch the exception, we need for stop at every frame in the unwind chain and run cleanups, then rethrow. That will be done in END_CATCH. After we require C++, we'll still need TRY/CATCH/END_CATCH until cleanups are completely phased out -- TRY/CATCH in C++ mode will save/restore the current cleanup chain, like in C mode, and END_CATCH catches otherwise uncaugh exceptions, runs cleanups and rethrows, so that C++ cleanups and exceptions can coexist. IMO, this still makes the TRY/CATCH code look a bit more like a newcomer would expect, so IMO worth it even if we weren't considering C++. gdb/ChangeLog. 2015-03-07 Pedro Alves <palves@redhat.com> * common/common-exceptions.c (struct catcher) <exception>: No longer a pointer to volatile exception. Now an exception value. <mask>: Delete field. (exceptions_state_mc_init): Remove all parameters. Adjust. (exceptions_state_mc): No longer pop the catcher here. (exceptions_state_mc_catch): New function. (throw_exception): Adjust. * common/common-exceptions.h (exceptions_state_mc_init): Remove all parameters. (exceptions_state_mc_catch): Declare. (TRY_CATCH): Rename to ... (TRY): ... this. Remove EXCEPTION and MASK parameters. (CATCH, END_CATCH): New. All callers adjusted. gdb/gdbserver/ChangeLog: 2015-03-07 Pedro Alves <palves@redhat.com> Adjust all callers of TRY_CATCH to use TRY/CATCH/END_CATCH instead.
2015-02-27Move exception_none to common code, and use itPedro Alves1-0/+3
gdb/ChangeLog: 2015-02-27 Pedro Alves <palves@redhat.com> * common/common-exceptions.h (exception_none): Declare. * common/common-exceptions.c (exception_none): Moved from exceptions.c. (exceptions_state_mc_init): Use exception_none. * exceptions.c (exception_none): Move to common/common-exceptions.c. * exceptions.h (exception_none): Move to common/common-exceptions.h.
2015-01-31Add max-completions parameter, and implement tab-completion limiting.Gary Benson1-0/+6
This commit adds a new exception, MAX_COMPLETIONS_REACHED_ERROR, to be thrown whenever the completer has generated too many candidates to be useful. A new user-settable variable, "max_completions", is added to control this behaviour. A top-level completion limit is added to complete_line_internal, as the final check to ensure the user never sees too many completions. An additional limit is added to default_make_symbol_completion_list_break_on, to halt time-consuming symbol table expansions. gdb/ChangeLog: PR cli/9007 PR cli/11920 PR cli/15548 * cli/cli-cmds.c (complete_command): Notify user if max-completions reached. * common/common-exceptions.h (enum errors) <MAX_COMPLETIONS_REACHED_ERROR>: New value. * completer.h (get_max_completions_reached_message): New declaration. (max_completions): Likewise. (completion_tracker_t): New typedef. (new_completion_tracker): New declaration. (make_cleanup_free_completion_tracker): Likewise. (maybe_add_completion_enum): New enum. (maybe_add_completion): New declaration. (throw_max_completions_reached_error): Likewise. * completer.c (max_completions): New global variable. (new_completion_tracker): New function. (free_completion_tracker): Likewise. (make_cleanup_free_completion_tracker): Likewise. (maybe_add_completions): Likewise. (throw_max_completions_reached_error): Likewise. (complete_line): Remove duplicates and limit result to max_completions entries. (get_max_completions_reached_message): New function. (gdb_display_match_list): Handle max_completions. (_initialize_completer): New declaration and function. * symtab.c: Include completer.h. (completion_tracker): New static variable. (completion_list_add_name): Call maybe_add_completion. (default_make_symbol_completion_list_break_on_1): Renamed from default_make_symbol_completion_list_break_on. Maintain completion_tracker across calls to completion_list_add_name. (default_make_symbol_completion_list_break_on): New function. * top.c (init_main): Set rl_completion_display_matches_hook. * tui/tui-io.c: Include completer.h. (tui_old_rl_display_matches_hook): New static global. (tui_rl_display_match_list): Notify user if max-completions reached. (tui_setup_io): Save/restore rl_completion_display_matches_hook. * NEWS (New Options): Mention set/show max-completions. gdb/doc/ChangeLog: * gdb.texinfo (Command Completion): Document new "set/show max-completions" option. gdb/testsuite/ChangeLog: * gdb.base/completion.exp: Disable completion limiting for existing tests. Add new tests to check completion limiting. * gdb.linespec/ls-errs.exp: Disable completion limiting.
2015-01-01Update year range in copyright notice of all files owned by the GDB project.Joel Brobecker1-1/+1
gdb/ChangeLog: Update year range in copyright notice of all files.
2014-08-29Introduce common/common-exceptions.[ch]Gary Benson1-0/+185
This commit moves the exception throwing and catching code into gdb/common/. All exception printing code remains in gdb/exceptions.[ch]. gdb/ChangeLog: * common/common-exceptions.h: New file. * common/common-exceptions.c: Likewise. * Makefile.in (SFILES): Add common/common-exceptions.c. (HFILES_NO_SRCDIR): Add common/common-exceptions.h. (COMMON_OBS): Add common-exceptions.o. (common-exceptions.o): New rule. * exceptions.h (common-exceptions.h): Include. (gdb_setjmp.h): Do not include. (return_reason): Moved to common-exceptions.h. (enum return_reason): Likewise. (RETURN_MASK): Likewise. (typedef return_mask): Likewise. (enum errors): Likewise. (struct gdb_exception): Likewise. (exceptions_state_mc_init): Likewise. (exceptions_state_mc_action_iter): Likewise. (exceptions_state_mc_action_iter_1): Likewise. (TRY_CATCH): Likewise. (throw_exception): Likewise. (throw_verror): Likewise. (throw_vquit): Likewise. (throw_error): Likewise. (throw_quit): Likewise. * exceptions.c (enum catcher_state): Moved to common-exceptions.c. (enum catcher_action): Likewise. (struct catcher): Likewise. (current_catcher): Likewise. (catcher_list_size): Likewise. (exceptions_state_mc_init): Likewise. (catcher_pop): Likewise. (exceptions_state_mc): Likewise. (exceptions_state_mc_action_iter): Likewise. (exceptions_state_mc_action_iter_1): Likewise. (throw_exception): Likewise. (exception_messages): Likewise. (exception_messages_size): Likewise. (throw_it): Likewise. (throw_verror): Likewise. (throw_vquit): Likewise. (throw_error): Likewise. (throw_quit): Likewise. (prepare_to_throw_exception): New function. gdb/gdbserver/ChangeLog: * Makefile.in (SFILES): Add common/common-exceptions.c. (OBS): Add common-exceptions.o. (common-exceptions.o): New rule. * utils.c (prepare_to_throw_exception): New function.