aboutsummaryrefslogtreecommitdiff
path: root/gdb/common/common-exceptions.h
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2016-09-23 16:42:24 +0100
committerPedro Alves <palves@redhat.com>2016-09-23 16:42:24 +0100
commit503b1c39dc801389f7ae510fb1f7ee1e533b67ac (patch)
tree3a5f71719f698d4789158f827c06dc0f8d2f5527 /gdb/common/common-exceptions.h
parent5025eb7c0d87b01507116353b5d63b163d7add3d (diff)
downloadgdb-503b1c39dc801389f7ae510fb1f7ee1e533b67ac.zip
gdb-503b1c39dc801389f7ae510fb1f7ee1e533b67ac.tar.gz
gdb-503b1c39dc801389f7ae510fb1f7ee1e533b67ac.tar.bz2
gdb: Replace operator new / operator new[]
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.
Diffstat (limited to 'gdb/common/common-exceptions.h')
-rw-r--r--gdb/common/common-exceptions.h20
1 files changed, 20 insertions, 0 deletions
diff --git a/gdb/common/common-exceptions.h b/gdb/common/common-exceptions.h
index c494de2..6bf7e40 100644
--- a/gdb/common/common-exceptions.h
+++ b/gdb/common/common-exceptions.h
@@ -21,6 +21,7 @@
#define COMMON_EXCEPTIONS_H
#include <setjmp.h>
+#include <new>
/* Reasons for calling throw_exceptions(). NOTE: all reason values
must be less than zero. enum value 0 is reserved for internal use
@@ -283,6 +284,25 @@ struct gdb_exception_RETURN_MASK_QUIT : public gdb_exception_RETURN_MASK_ALL
#endif /* GDB_XCPT_TRY || GDB_XCPT_RAW_TRY */
+/* An exception type that inherits from both std::bad_alloc and a gdb
+ exception. This is necessary because operator new can only throw
+ std::bad_alloc, and OTOH, we want exceptions thrown due to memory
+ allocation error to be caught by all the CATCH/RETURN_MASK_ALL
+ spread around the codebase. */
+
+struct gdb_quit_bad_alloc
+ : public gdb_exception_RETURN_MASK_QUIT,
+ public std::bad_alloc
+{
+ explicit gdb_quit_bad_alloc (gdb_exception ex)
+ : std::bad_alloc ()
+ {
+ gdb_exception *self = this;
+
+ *self = ex;
+ }
+};
+
/* *INDENT-ON* */
/* Throw an exception (as described by "struct gdb_exception"). When