1df1ea588SDmitry Chagin /*-
2df1ea588SDmitry Chagin * Copyright (c) 2023 Dmitry Chagin <dchagin@FreeBSD.org>
3df1ea588SDmitry Chagin *
4df1ea588SDmitry Chagin * SPDX-License-Identifier: BSD-2-Clause
5df1ea588SDmitry Chagin */
6*a2f733abSWarner Losh
7df1ea588SDmitry Chagin #include <sys/param.h>
8df1ea588SDmitry Chagin #include <sys/wait.h>
9df1ea588SDmitry Chagin
10df1ea588SDmitry Chagin #include <execinfo.h>
11df1ea588SDmitry Chagin #include <signal.h>
12df1ea588SDmitry Chagin #include <stdio.h>
13df1ea588SDmitry Chagin #include <string.h>
14df1ea588SDmitry Chagin #include <unistd.h>
15df1ea588SDmitry Chagin
16df1ea588SDmitry Chagin #include <atf-c.h>
17df1ea588SDmitry Chagin
18df1ea588SDmitry Chagin #define BT_FUNCTIONS 10
19df1ea588SDmitry Chagin
20df1ea588SDmitry Chagin void handler(int);
21df1ea588SDmitry Chagin
22df1ea588SDmitry Chagin __noinline void
handler(int signum __unused)23df1ea588SDmitry Chagin handler(int signum __unused)
24df1ea588SDmitry Chagin {
25df1ea588SDmitry Chagin void *addresses[BT_FUNCTIONS];
26df1ea588SDmitry Chagin char **symbols;
27df1ea588SDmitry Chagin size_t n, i, match;
28df1ea588SDmitry Chagin
29df1ea588SDmitry Chagin n = backtrace(addresses, nitems(addresses));
30df1ea588SDmitry Chagin ATF_REQUIRE(n > 1);
31df1ea588SDmitry Chagin symbols = backtrace_symbols(addresses, n);
32df1ea588SDmitry Chagin ATF_REQUIRE(symbols != NULL);
33df1ea588SDmitry Chagin
34df1ea588SDmitry Chagin match = -1;
35df1ea588SDmitry Chagin for (i = 0; i < n; i++) {
36df1ea588SDmitry Chagin printf("%zu: %p, %s\n", i, addresses[i], symbols[i]);
37df1ea588SDmitry Chagin if (strstr(symbols[i], "<main+") != NULL)
38df1ea588SDmitry Chagin match = i;
39df1ea588SDmitry Chagin }
40df1ea588SDmitry Chagin ATF_REQUIRE(match > 0);
41df1ea588SDmitry Chagin printf("match at %zu, symbols %zu\n", match, n);
42df1ea588SDmitry Chagin
43df1ea588SDmitry Chagin }
44df1ea588SDmitry Chagin
45df1ea588SDmitry Chagin ATF_TC_WITHOUT_HEAD(test_backtrace_sigtramp);
ATF_TC_BODY(test_backtrace_sigtramp,tc)46df1ea588SDmitry Chagin ATF_TC_BODY(test_backtrace_sigtramp, tc)
47df1ea588SDmitry Chagin {
48df1ea588SDmitry Chagin struct sigaction act;
49df1ea588SDmitry Chagin pid_t child;
50df1ea588SDmitry Chagin int status;
51df1ea588SDmitry Chagin
52df1ea588SDmitry Chagin memset(&act, 0, sizeof(act));
53df1ea588SDmitry Chagin act.sa_handler = handler;
54df1ea588SDmitry Chagin sigemptyset(&act.sa_mask);
55df1ea588SDmitry Chagin sigaction(SIGUSR1, &act, NULL);
56df1ea588SDmitry Chagin
57df1ea588SDmitry Chagin child = fork();
58df1ea588SDmitry Chagin ATF_REQUIRE(child != -1);
59df1ea588SDmitry Chagin
60df1ea588SDmitry Chagin if (child == 0) {
61df1ea588SDmitry Chagin kill(getppid(), SIGUSR1);
62df1ea588SDmitry Chagin _exit(0);
63df1ea588SDmitry Chagin } else
64df1ea588SDmitry Chagin wait(&status);
65df1ea588SDmitry Chagin }
66df1ea588SDmitry Chagin
ATF_TP_ADD_TCS(tp)67df1ea588SDmitry Chagin ATF_TP_ADD_TCS(tp)
68df1ea588SDmitry Chagin {
69df1ea588SDmitry Chagin
70df1ea588SDmitry Chagin ATF_TP_ADD_TC(tp, test_backtrace_sigtramp);
71df1ea588SDmitry Chagin
72df1ea588SDmitry Chagin return (atf_no_error());
73df1ea588SDmitry Chagin }
74