summaryrefslogtreecommitdiff
path: root/gdbsupport/alt-stack.h
diff options
context:
space:
mode:
Diffstat (limited to 'gdbsupport/alt-stack.h')
-rw-r--r--gdbsupport/alt-stack.h70
1 files changed, 70 insertions, 0 deletions
diff --git a/gdbsupport/alt-stack.h b/gdbsupport/alt-stack.h
new file mode 100644
index 00000000000..e7c6b2f8c5b
--- /dev/null
+++ b/gdbsupport/alt-stack.h
@@ -0,0 +1,70 @@
+/* Temporarily install an alternate signal stack
+
+ Copyright (C) 2019-2020 Free Software Foundation, Inc.
+
+ 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/>. */
+
+#ifndef GDBSUPPORT_ALT_STACK_H
+#define GDBSUPPORT_ALT_STACK_H
+
+#include <signal.h>
+
+namespace gdb
+{
+
+/* Try to set up an alternate signal stack for SIGSEGV handlers.
+ This allows us to handle SIGSEGV signals generated when the
+ normal process stack is exhausted. If this stack is not set
+ up (sigaltstack is unavailable or fails) and a SIGSEGV is
+ generated when the normal stack is exhausted then the program
+ will behave as though no SIGSEGV handler was installed. */
+class alternate_signal_stack
+{
+public:
+ alternate_signal_stack ()
+ {
+#ifdef HAVE_SIGALTSTACK
+ m_stack.reset ((char *) xmalloc (SIGSTKSZ));
+
+ stack_t stack;
+ stack.ss_sp = m_stack.get ();
+ stack.ss_size = SIGSTKSZ;
+ stack.ss_flags = 0;
+
+ sigaltstack (&stack, &m_old_stack);
+#endif
+ }
+
+ ~alternate_signal_stack ()
+ {
+#ifdef HAVE_SIGALTSTACK
+ sigaltstack (&m_old_stack, nullptr);
+#endif
+ }
+
+ DISABLE_COPY_AND_ASSIGN (alternate_signal_stack);
+
+private:
+
+#ifdef HAVE_SIGALTSTACK
+ gdb::unique_xmalloc_ptr<char> m_stack;
+ stack_t m_old_stack;
+#endif
+};
+
+}
+
+#endif /* GDBSUPPORT_ALT_STACK_H */