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