]> granicus.if.org Git - strace/blob - tests/pc.c
Update copyright headers
[strace] / tests / pc.c
1 /*
2  * Copyright (c) 2015-2018 Dmitry V. Levin <ldv@altlinux.org>
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  */
7
8 #include "tests.h"
9 #include <assert.h>
10 #include <dlfcn.h>
11 #include <fcntl.h>
12 #include <unistd.h>
13 #include <sys/mman.h>
14 #include <sys/wait.h>
15 #include <sys/sendfile.h>
16
17 int main(void)
18 {
19         const unsigned long pagesize = get_page_size();
20
21 #ifdef __s390__
22         /*
23          * The si_addr field is unreliable:
24          * https://marc.info/?l=linux-s390&m=142515870124248&w=2
25          */
26         error_msg_and_skip("s390: si_addr is unreliable");
27 #endif
28
29         /* write instruction pointer length to the log */
30         assert(write(-1, NULL, 2 * sizeof(void *)) < 0);
31
32         /* just a noticeable line in the log */
33         assert(munmap(&main, 0) < 0);
34
35         int pid = fork();
36         if (pid < 0)
37                 perror_msg_and_fail("fork");
38
39         if (!pid) {
40                 const unsigned long mask = ~(pagesize - 1);
41                 unsigned long addr = (unsigned long) &main & mask;
42                 unsigned long size = pagesize << 1;
43
44 #ifdef HAVE_DLADDR
45                 Dl_info info;
46                 if (dladdr(&main, &info)) {
47                         const unsigned long base =
48                                 (unsigned long) info.dli_fbase & mask;
49                         if (base < addr) {
50                                 size += addr - base;
51                                 addr = base;
52                         }
53                 } else
54 #endif
55                 {
56                         addr -= size;
57                         size <<= 1;
58                 }
59
60                 /* SIGSEGV is expected */
61                 (void) munmap((void *) addr, size);
62                 (void) munmap((void *) addr, size);
63                 error_msg_and_skip("SIGSEGV did not happen");
64         }
65
66         int status;
67         assert(wait(&status) == pid);
68         assert(WIFSIGNALED(status));
69         assert(WTERMSIG(status) == SIGSEGV);
70
71         /* dump process map for debug purposes */
72         close(0);
73         if (!open("/proc/self/maps", O_RDONLY))
74                 (void) sendfile(1, 0, NULL, pagesize);
75
76         return 0;
77 }