aboutsummaryrefslogtreecommitdiffstats
path: root/libtest/libtest_stack_on_signal.c
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2026-05-10 13:37:34 +0200
committerMattias Andrée <m@maandree.se>2026-05-10 13:37:34 +0200
commitb7e8928005079171c7595fd336a76f655daed48a (patch)
tree9fa87ba8ada6cc52e343c32789ff7225d817e4fa /libtest/libtest_stack_on_signal.c
parentMisc (diff)
downloadlibrecrypt-b7e8928005079171c7595fd336a76f655daed48a.tar.gz
librecrypt-b7e8928005079171c7595fd336a76f655daed48a.tar.bz2
librecrypt-b7e8928005079171c7595fd336a76f655daed48a.tar.xz
Improvements to libtest
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to 'libtest/libtest_stack_on_signal.c')
-rw-r--r--libtest/libtest_stack_on_signal.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/libtest/libtest_stack_on_signal.c b/libtest/libtest_stack_on_signal.c
new file mode 100644
index 0000000..0f92972
--- /dev/null
+++ b/libtest/libtest_stack_on_signal.c
@@ -0,0 +1,102 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+# ifdef WITH_BACKTRACE
+
+
+static void
+stack_dumper(int sig, siginfo_t *info, void *ucontext)
+{
+ (void) sig;
+ (void) info;
+ libtest_print_backtrace(stderr, "crashed at ", " by ", 0u, NULL, ucontext);
+}
+
+
+static stack_t ss;
+static size_t have_ss = 0u;
+
+
+static void
+create_altstack(void)
+{
+ if (have_ss++)
+ return;
+ ss.ss_sp = libtest_real_mmap(NULL, (size_t)SIGSTKSZ, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ assert(ss.ss_sp != MAP_FAILED);
+ ss.ss_size = (size_t)SIGSTKSZ;
+ ss.ss_flags = 0;
+ assert(!sigaltstack(&ss, NULL));
+}
+
+
+static void
+destroy_altstack(void)
+{
+ if (--have_ss)
+ return;
+ assert(!libtest_real_munmap(ss.ss_sp, ss.ss_size));
+}
+
+
+void
+libtest_stack_on_signal(int signo, struct sigaction *old_out)
+{
+ struct sigaction sa;
+
+ create_altstack();
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_sigaction = &stack_dumper;
+ sa.sa_flags = (int)(SA_RESETHAND | SA_SIGINFO);
+ if (have_ss)
+ sa.sa_flags |= SA_ONSTACK;
+ sigfillset(&sa.sa_mask);
+
+ assert(!sigaction(signo, &sa, old_out));
+}
+
+
+void
+libtest_stop_stack_on_signal(int signo, const struct sigaction *old)
+{
+ assert(!sigaction(signo, old, NULL));
+ destroy_altstack();
+}
+
+
+#else
+
+
+void
+libtest_stack_on_signal(int signo, struct sigaction *old_out)
+{
+ (void) signo;
+ (void) old_out;
+}
+
+void
+libtest_stop_stack_on_signal(int signo, const struct sigaction *old)
+{
+ (void) signo;
+ (void) old;
+}
+
+
+# endif
+
+
+#else
+
+
+CONST int
+main(void)
+{
+ /* How would one even test this, and what would be the point? */
+ return 0;
+}
+
+
+#endif