binutils-gdb/gdbsupport/new-op.cc

143 lines
3.9 KiB
C++
Raw Normal View History

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.
2016-09-23 23:42:24 +08:00
/* Replace operator new/new[], for GDB, the GNU debugger.
Copyright (C) 2016-2024 Free Software Foundation, Inc.
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.
2016-09-23 23:42:24 +08:00
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
Don't override operator new if GDB is built with -fsanitize=address Nowadays, if we build GDB with -fsanitize=address, we can get the asan error below, (gdb) quit ================================================================= ==9723==ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs operator delete) on 0x60200003bf70 #0 0x7f88f3837527 in operator delete(void*) (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x55527) #1 0xac8e13 in __gnu_cxx::new_allocator<void (*)()>::deallocate(void (**)(), unsigned long) /usr/include/c++/4.9/ext/new_allocator.h:110 #2 0xac8cc2 in __gnu_cxx::__alloc_traits<std::allocator<void (*)()> >::deallocate(std::allocator<void (*)()>&, void (**)(), unsigned long) /usr/include/c++/4.9/ext/alloc_traits.h:185 .... 0x60200003bf70 is located 0 bytes inside of 8-byte region [0x60200003bf70,0x60200003bf78) allocated by thread T0 here: #0 0x7f88f38367ef in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x547ef) #1 0xbd2762 in operator new(unsigned long) /home/yao/SourceCode/gnu/gdb/git/gdb/common/new-op.c:42 #2 0xac8edc in __gnu_cxx::new_allocator<void (*)()>::allocate(unsigned long, void const*) /usr/include/c++/4.9/ext/new_allocator.h:104 #3 0xac8d81 in __gnu_cxx::__alloc_traits<std::allocator<void (*)()> >::allocate(std::allocator<void (*)()>&, unsigned long) /usr/include/c++/4.9/ext/alloc_traits.h:182 The reason for this is that we override operator new but don't override operator delete. This patch does the override if the code is NOT compiled with asan. gdb: 2016-10-25 Yao Qi <yao.qi@linaro.org> PR gdb/20716 * common/new-op.c (__has_feature): New macro. Don't override operator new if asan is used.
2016-10-25 18:13:00 +08:00
/* GCC does not understand __has_feature. */
#if !defined(__has_feature)
# define __has_feature(x) 0
#endif
#if !__has_feature(address_sanitizer) && !defined(__SANITIZE_ADDRESS__)
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.
2016-09-23 23:42:24 +08:00
#include "common-defs.h"
#include "host-defs.h"
#include <new>
/* These are declared in <new> starting C++14, but removing them
caused a build failure with clang. See PR build/31141. */
extern void operator delete (void *p, std::size_t) noexcept;
extern void operator delete[] (void *p, std::size_t) noexcept;
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.
2016-09-23 23:42:24 +08:00
/* Override operator new / operator new[], in order to internal_error
on allocation failure and thus query the user for abort/core
dump/continue, just like xmalloc does. We don't do this from a
new-handler function instead (std::set_new_handler) because we want
to catch allocation errors from within global constructors too.
Skip overriding if building with -fsanitize=address though.
Address sanitizer wants to override operator new/delete too in
order to detect malloc+delete and new+free mismatches. Our
versions would mask out ASan's, with the result of losing that
useful mismatch detection.
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.
2016-09-23 23:42:24 +08:00
Note that C++ implementations could either have their throw
versions call the nothrow versions (libstdc++), or the other way
around (clang/libc++). For that reason, we replace both throw and
nothrow variants and call malloc directly. */
void *
operator new (std::size_t sz)
{
/* malloc (0) is unpredictable; avoid it. */
if (sz == 0)
sz = 1;
void *p = malloc (sz); /* ARI: malloc */
if (p == NULL)
{
/* If the user decides to continue debugging, throw a
gdb_quit_bad_alloc exception instead of a regular QUIT
gdb_exception. The former extends both std::bad_alloc and a
QUIT gdb_exception. This is necessary because operator new
can only ever throw std::bad_alloc, or something that extends
it. */
Rewrite TRY/CATCH This rewrites gdb's TRY/CATCH to plain C++ try/catch. The patch was largely written by script, though one change (to a comment in common-exceptions.h) was reverted by hand. gdb/ChangeLog 2019-04-08 Tom Tromey <tom@tromey.com> * xml-support.c: Use C++ exception handling. * x86-linux-nat.c: Use C++ exception handling. * windows-nat.c: Use C++ exception handling. * varobj.c: Use C++ exception handling. * value.c: Use C++ exception handling. * valprint.c: Use C++ exception handling. * valops.c: Use C++ exception handling. * unittests/parse-connection-spec-selftests.c: Use C++ exception handling. * unittests/cli-utils-selftests.c: Use C++ exception handling. * typeprint.c: Use C++ exception handling. * tui/tui.c: Use C++ exception handling. * tracefile-tfile.c: Use C++ exception handling. * top.c: Use C++ exception handling. * thread.c: Use C++ exception handling. * target.c: Use C++ exception handling. * symmisc.c: Use C++ exception handling. * symfile-mem.c: Use C++ exception handling. * stack.c: Use C++ exception handling. * sparc64-linux-tdep.c: Use C++ exception handling. * solib.c: Use C++ exception handling. * solib-svr4.c: Use C++ exception handling. * solib-spu.c: Use C++ exception handling. * solib-frv.c: Use C++ exception handling. * solib-dsbt.c: Use C++ exception handling. * selftest-arch.c: Use C++ exception handling. * s390-tdep.c: Use C++ exception handling. * rust-lang.c: Use C++ exception handling. * rust-exp.y: Use C++ exception handling. * rs6000-tdep.c: Use C++ exception handling. * rs6000-aix-tdep.c: Use C++ exception handling. * riscv-tdep.c: Use C++ exception handling. * remote.c: Use C++ exception handling. * remote-fileio.c: Use C++ exception handling. * record-full.c: Use C++ exception handling. * record-btrace.c: Use C++ exception handling. * python/python.c: Use C++ exception handling. * python/py-value.c: Use C++ exception handling. * python/py-utils.c: Use C++ exception handling. * python/py-unwind.c: Use C++ exception handling. * python/py-type.c: Use C++ exception handling. * python/py-symbol.c: Use C++ exception handling. * python/py-record.c: Use C++ exception handling. * python/py-record-btrace.c: Use C++ exception handling. * python/py-progspace.c: Use C++ exception handling. * python/py-prettyprint.c: Use C++ exception handling. * python/py-param.c: Use C++ exception handling. * python/py-objfile.c: Use C++ exception handling. * python/py-linetable.c: Use C++ exception handling. * python/py-lazy-string.c: Use C++ exception handling. * python/py-infthread.c: Use C++ exception handling. * python/py-inferior.c: Use C++ exception handling. * python/py-gdb-readline.c: Use C++ exception handling. * python/py-framefilter.c: Use C++ exception handling. * python/py-frame.c: Use C++ exception handling. * python/py-finishbreakpoint.c: Use C++ exception handling. * python/py-cmd.c: Use C++ exception handling. * python/py-breakpoint.c: Use C++ exception handling. * python/py-arch.c: Use C++ exception handling. * printcmd.c: Use C++ exception handling. * ppc-linux-tdep.c: Use C++ exception handling. * parse.c: Use C++ exception handling. * p-valprint.c: Use C++ exception handling. * objc-lang.c: Use C++ exception handling. * mi/mi-main.c: Use C++ exception handling. * mi/mi-interp.c: Use C++ exception handling. * mi/mi-cmd-stack.c: Use C++ exception handling. * mi/mi-cmd-break.c: Use C++ exception handling. * main.c: Use C++ exception handling. * linux-thread-db.c: Use C++ exception handling. * linux-tdep.c: Use C++ exception handling. * linux-nat.c: Use C++ exception handling. * linux-fork.c: Use C++ exception handling. * linespec.c: Use C++ exception handling. * language.c: Use C++ exception handling. * jit.c: Use C++ exception handling. * infrun.c: Use C++ exception handling. * infcmd.c: Use C++ exception handling. * infcall.c: Use C++ exception handling. * inf-loop.c: Use C++ exception handling. * i386-tdep.c: Use C++ exception handling. * i386-linux-tdep.c: Use C++ exception handling. * guile/scm-value.c: Use C++ exception handling. * guile/scm-type.c: Use C++ exception handling. * guile/scm-symtab.c: Use C++ exception handling. * guile/scm-symbol.c: Use C++ exception handling. * guile/scm-pretty-print.c: Use C++ exception handling. * guile/scm-ports.c: Use C++ exception handling. * guile/scm-param.c: Use C++ exception handling. * guile/scm-math.c: Use C++ exception handling. * guile/scm-lazy-string.c: Use C++ exception handling. * guile/scm-frame.c: Use C++ exception handling. * guile/scm-disasm.c: Use C++ exception handling. * guile/scm-cmd.c: Use C++ exception handling. * guile/scm-breakpoint.c: Use C++ exception handling. * guile/scm-block.c: Use C++ exception handling. * guile/guile-internal.h: Use C++ exception handling. * gnu-v3-abi.c: Use C++ exception handling. * gdbtypes.c: Use C++ exception handling. * frame.c: Use C++ exception handling. * frame-unwind.c: Use C++ exception handling. * fbsd-tdep.c: Use C++ exception handling. * f-valprint.c: Use C++ exception handling. * exec.c: Use C++ exception handling. * event-top.c: Use C++ exception handling. * event-loop.c: Use C++ exception handling. * eval.c: Use C++ exception handling. * dwarf2read.c: Use C++ exception handling. * dwarf2loc.c: Use C++ exception handling. * dwarf2-frame.c: Use C++ exception handling. * dwarf2-frame-tailcall.c: Use C++ exception handling. * dwarf-index-write.c: Use C++ exception handling. * dwarf-index-cache.c: Use C++ exception handling. * dtrace-probe.c: Use C++ exception handling. * disasm-selftests.c: Use C++ exception handling. * darwin-nat.c: Use C++ exception handling. * cp-valprint.c: Use C++ exception handling. * cp-support.c: Use C++ exception handling. * cp-abi.c: Use C++ exception handling. * corelow.c: Use C++ exception handling. * completer.c: Use C++ exception handling. * compile/compile-object-run.c: Use C++ exception handling. * compile/compile-object-load.c: Use C++ exception handling. * compile/compile-cplus-symbols.c: Use C++ exception handling. * compile/compile-c-symbols.c: Use C++ exception handling. * common/selftest.c: Use C++ exception handling. * common/new-op.c: Use C++ exception handling. * cli/cli-script.c: Use C++ exception handling. * cli/cli-interp.c: Use C++ exception handling. * cli/cli-cmds.c: Use C++ exception handling. * c-varobj.c: Use C++ exception handling. * btrace.c: Use C++ exception handling. * breakpoint.c: Use C++ exception handling. * break-catch-throw.c: Use C++ exception handling. * arch-utils.c: Use C++ exception handling. * amd64-tdep.c: Use C++ exception handling. * ada-valprint.c: Use C++ exception handling. * ada-typeprint.c: Use C++ exception handling. * ada-lang.c: Use C++ exception handling. * aarch64-tdep.c: Use C++ exception handling. gdb/gdbserver/ChangeLog 2019-04-08 Tom Tromey <tom@tromey.com> * server.c: Use C++ exception handling. * linux-low.c: Use C++ exception handling. * gdbreplay.c: Use C++ exception handling.
2019-04-04 06:02:42 +08:00
try
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.
2016-09-23 23:42:24 +08:00
{
malloc_failure (sz);
}
Make exception handling more efficient This makes exception handling more efficient in a few spots, through the use of const- and rvalue-references. I wrote this patch by commenting out the gdb_exception copy constructor and then examining the resulting error messages one by one, introducing the use of std::move where appropriate. gdb/ChangeLog 2019-04-25 Tom Tromey <tromey@adacore.com> * xml-support.c (struct gdb_xml_parser) <set_error>: Take an rvalue reference. (gdb_xml_start_element_wrapper, gdb_xml_end_element_wrapper) (gdb_xml_parser::parse): Use std::move. * python/python-internal.h (gdbpy_convert_exception): Take a const reference. * python/py-value.c (valpy_getitem, valpy_nonzero): Use std::move. * python/py-utils.c (gdbpy_convert_exception): Take a const reference. * python/py-inferior.c (infpy_write_memory, infpy_search_memory): Use std::move. * python/py-breakpoint.c (bppy_set_condition, bppy_set_commands): Use std::move. * mi/mi-main.c (mi_print_exception): Take a const reference. * main.c (handle_command_errors): Take a const reference. * linespec.c (parse_linespec): Use std::move. * infcall.c (run_inferior_call): Use std::move. (call_function_by_hand_dummy): Use std::move. * exec.c (try_open_exec_file): Use std::move. * exceptions.h (exception_print, exception_fprintf) (exception_print_same): Update. * exceptions.c (print_exception, exception_print) (exception_fprintf, exception_print_same): Change parameters to const reference. * event-top.c (gdb_rl_callback_read_char_wrapper): Update. * common/new-op.c: Use std::move. * common/common-exceptions.h (struct gdb_exception): Add move constructor. (struct gdb_exception_error, struct gdb_exception_quit, struct gdb_quit_bad_alloc): Change constructor to move constructor. (throw_exception): Change parameter to rvalue reference. * common/common-exceptions.c (throw_exception): Take rvalue reference. * cli/cli-interp.c (safe_execute_command): Use std::move. * breakpoint.c (insert_bp_location, location_to_sals): Use std::move.
2019-04-24 20:50:06 +08:00
catch (gdb_exception &ex)
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.
2016-09-23 23:42:24 +08:00
{
Make exception handling more efficient This makes exception handling more efficient in a few spots, through the use of const- and rvalue-references. I wrote this patch by commenting out the gdb_exception copy constructor and then examining the resulting error messages one by one, introducing the use of std::move where appropriate. gdb/ChangeLog 2019-04-25 Tom Tromey <tromey@adacore.com> * xml-support.c (struct gdb_xml_parser) <set_error>: Take an rvalue reference. (gdb_xml_start_element_wrapper, gdb_xml_end_element_wrapper) (gdb_xml_parser::parse): Use std::move. * python/python-internal.h (gdbpy_convert_exception): Take a const reference. * python/py-value.c (valpy_getitem, valpy_nonzero): Use std::move. * python/py-utils.c (gdbpy_convert_exception): Take a const reference. * python/py-inferior.c (infpy_write_memory, infpy_search_memory): Use std::move. * python/py-breakpoint.c (bppy_set_condition, bppy_set_commands): Use std::move. * mi/mi-main.c (mi_print_exception): Take a const reference. * main.c (handle_command_errors): Take a const reference. * linespec.c (parse_linespec): Use std::move. * infcall.c (run_inferior_call): Use std::move. (call_function_by_hand_dummy): Use std::move. * exec.c (try_open_exec_file): Use std::move. * exceptions.h (exception_print, exception_fprintf) (exception_print_same): Update. * exceptions.c (print_exception, exception_print) (exception_fprintf, exception_print_same): Change parameters to const reference. * event-top.c (gdb_rl_callback_read_char_wrapper): Update. * common/new-op.c: Use std::move. * common/common-exceptions.h (struct gdb_exception): Add move constructor. (struct gdb_exception_error, struct gdb_exception_quit, struct gdb_quit_bad_alloc): Change constructor to move constructor. (throw_exception): Change parameter to rvalue reference. * common/common-exceptions.c (throw_exception): Take rvalue reference. * cli/cli-interp.c (safe_execute_command): Use std::move. * breakpoint.c (insert_bp_location, location_to_sals): Use std::move.
2019-04-24 20:50:06 +08:00
throw gdb_quit_bad_alloc (std::move (ex));
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.
2016-09-23 23:42:24 +08:00
}
}
return p;
}
void *
operator new (std::size_t sz, const std::nothrow_t&) noexcept
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.
2016-09-23 23:42:24 +08:00
{
/* malloc (0) is unpredictable; avoid it. */
if (sz == 0)
sz = 1;
return malloc (sz); /* ARI: malloc */
}
void *
operator new[] (std::size_t sz)
{
return ::operator new (sz);
}
void*
operator new[] (std::size_t sz, const std::nothrow_t&) noexcept
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.
2016-09-23 23:42:24 +08:00
{
return ::operator new (sz, std::nothrow);
}
Fix LD_PRELOAD=/usr/lib64/libasan.so.6 gdb Currently for a binary compiled normally (without -fsanitize=address) but with LD_PRELOAD of ASAN one gets: $ ASAN_OPTIONS=detect_leaks=0:alloc_dealloc_mismatch=1:abort_on_error=1:fast_unwind_on_malloc=0 LD_PRELOAD=/usr/lib64/libasan.so.6 gdb ================================================================= ==1909567==ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs operator delete []) on 0x602000001570 #0 0x7f1c98e5efa7 in operator delete[](void*) (/usr/lib64/libasan.so.6+0xb0fa7) ... 0x602000001570 is located 0 bytes inside of 2-byte region [0x602000001570,0x602000001572) allocated by thread T0 here: #0 0x7f1c98e5cd1f in __interceptor_malloc (/usr/lib64/libasan.so.6+0xaed1f) #1 0x557ee4a42e81 in operator new(unsigned long) (/usr/libexec/gdb+0x74ce81) SUMMARY: AddressSanitizer: alloc-dealloc-mismatch (/usr/lib64/libasan.so.6+0xb0fa7) in operator delete[](void*) ==1909567==HINT: if you don't care about these errors you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0 ==1909567==ABORTING Despite the code called properly operator new[] and operator delete[]. But GDB's new-op.cc provides its own operator new[] which gets translated into malloc() (which gets recogized as operatore new(size_t)) but as it does not translate also operators delete[] Address Sanitizer gets confused. The question is how many variants of the delete operator need to be provided. There could be 14 operators new but there are only 4, GDB uses 3 of them. There could be 16 operators delete but there are only 6, GDB uses 2 of them. It depends on libraries and compiler which of the operators will get used. Currently being used: U operator new[](unsigned long) U operator new(unsigned long) U operator new(unsigned long, std::nothrow_t const&) U operator delete[](void*) U operator delete(void*, unsigned long) Tested on x86_64-linux.
2021-11-03 18:29:18 +08:00
/* Define also operators delete as one can LD_PRELOAD=libasan.so.*
without recompiling the program with -fsanitize=address and then one would
get false positive alloc-dealloc-mismatch (malloc vs operator delete [])
errors from AddressSanitizers. */
void
operator delete (void *p) noexcept
Fix LD_PRELOAD=/usr/lib64/libasan.so.6 gdb Currently for a binary compiled normally (without -fsanitize=address) but with LD_PRELOAD of ASAN one gets: $ ASAN_OPTIONS=detect_leaks=0:alloc_dealloc_mismatch=1:abort_on_error=1:fast_unwind_on_malloc=0 LD_PRELOAD=/usr/lib64/libasan.so.6 gdb ================================================================= ==1909567==ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs operator delete []) on 0x602000001570 #0 0x7f1c98e5efa7 in operator delete[](void*) (/usr/lib64/libasan.so.6+0xb0fa7) ... 0x602000001570 is located 0 bytes inside of 2-byte region [0x602000001570,0x602000001572) allocated by thread T0 here: #0 0x7f1c98e5cd1f in __interceptor_malloc (/usr/lib64/libasan.so.6+0xaed1f) #1 0x557ee4a42e81 in operator new(unsigned long) (/usr/libexec/gdb+0x74ce81) SUMMARY: AddressSanitizer: alloc-dealloc-mismatch (/usr/lib64/libasan.so.6+0xb0fa7) in operator delete[](void*) ==1909567==HINT: if you don't care about these errors you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0 ==1909567==ABORTING Despite the code called properly operator new[] and operator delete[]. But GDB's new-op.cc provides its own operator new[] which gets translated into malloc() (which gets recogized as operatore new(size_t)) but as it does not translate also operators delete[] Address Sanitizer gets confused. The question is how many variants of the delete operator need to be provided. There could be 14 operators new but there are only 4, GDB uses 3 of them. There could be 16 operators delete but there are only 6, GDB uses 2 of them. It depends on libraries and compiler which of the operators will get used. Currently being used: U operator new[](unsigned long) U operator new(unsigned long) U operator new(unsigned long, std::nothrow_t const&) U operator delete[](void*) U operator delete(void*, unsigned long) Tested on x86_64-linux.
2021-11-03 18:29:18 +08:00
{
free (p);
}
void
operator delete (void *p, const std::nothrow_t&) noexcept
{
return ::operator delete (p);
}
void
operator delete (void *p, std::size_t) noexcept
{
return ::operator delete (p, std::nothrow);
}
void
operator delete[] (void *p) noexcept
Fix LD_PRELOAD=/usr/lib64/libasan.so.6 gdb Currently for a binary compiled normally (without -fsanitize=address) but with LD_PRELOAD of ASAN one gets: $ ASAN_OPTIONS=detect_leaks=0:alloc_dealloc_mismatch=1:abort_on_error=1:fast_unwind_on_malloc=0 LD_PRELOAD=/usr/lib64/libasan.so.6 gdb ================================================================= ==1909567==ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs operator delete []) on 0x602000001570 #0 0x7f1c98e5efa7 in operator delete[](void*) (/usr/lib64/libasan.so.6+0xb0fa7) ... 0x602000001570 is located 0 bytes inside of 2-byte region [0x602000001570,0x602000001572) allocated by thread T0 here: #0 0x7f1c98e5cd1f in __interceptor_malloc (/usr/lib64/libasan.so.6+0xaed1f) #1 0x557ee4a42e81 in operator new(unsigned long) (/usr/libexec/gdb+0x74ce81) SUMMARY: AddressSanitizer: alloc-dealloc-mismatch (/usr/lib64/libasan.so.6+0xb0fa7) in operator delete[](void*) ==1909567==HINT: if you don't care about these errors you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0 ==1909567==ABORTING Despite the code called properly operator new[] and operator delete[]. But GDB's new-op.cc provides its own operator new[] which gets translated into malloc() (which gets recogized as operatore new(size_t)) but as it does not translate also operators delete[] Address Sanitizer gets confused. The question is how many variants of the delete operator need to be provided. There could be 14 operators new but there are only 4, GDB uses 3 of them. There could be 16 operators delete but there are only 6, GDB uses 2 of them. It depends on libraries and compiler which of the operators will get used. Currently being used: U operator new[](unsigned long) U operator new(unsigned long) U operator new(unsigned long, std::nothrow_t const&) U operator delete[](void*) U operator delete(void*, unsigned long) Tested on x86_64-linux.
2021-11-03 18:29:18 +08:00
{
return ::operator delete (p);
}
void
operator delete[] (void *p, const std::nothrow_t&) noexcept
{
return ::operator delete (p, std::nothrow);
}
void
operator delete[] (void *p, std::size_t) noexcept
{
return ::operator delete[] (p, std::nothrow);
}
Don't override operator new if GDB is built with -fsanitize=address Nowadays, if we build GDB with -fsanitize=address, we can get the asan error below, (gdb) quit ================================================================= ==9723==ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs operator delete) on 0x60200003bf70 #0 0x7f88f3837527 in operator delete(void*) (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x55527) #1 0xac8e13 in __gnu_cxx::new_allocator<void (*)()>::deallocate(void (**)(), unsigned long) /usr/include/c++/4.9/ext/new_allocator.h:110 #2 0xac8cc2 in __gnu_cxx::__alloc_traits<std::allocator<void (*)()> >::deallocate(std::allocator<void (*)()>&, void (**)(), unsigned long) /usr/include/c++/4.9/ext/alloc_traits.h:185 .... 0x60200003bf70 is located 0 bytes inside of 8-byte region [0x60200003bf70,0x60200003bf78) allocated by thread T0 here: #0 0x7f88f38367ef in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x547ef) #1 0xbd2762 in operator new(unsigned long) /home/yao/SourceCode/gnu/gdb/git/gdb/common/new-op.c:42 #2 0xac8edc in __gnu_cxx::new_allocator<void (*)()>::allocate(unsigned long, void const*) /usr/include/c++/4.9/ext/new_allocator.h:104 #3 0xac8d81 in __gnu_cxx::__alloc_traits<std::allocator<void (*)()> >::allocate(std::allocator<void (*)()>&, unsigned long) /usr/include/c++/4.9/ext/alloc_traits.h:182 The reason for this is that we override operator new but don't override operator delete. This patch does the override if the code is NOT compiled with asan. gdb: 2016-10-25 Yao Qi <yao.qi@linaro.org> PR gdb/20716 * common/new-op.c (__has_feature): New macro. Don't override operator new if asan is used.
2016-10-25 18:13:00 +08:00
#endif