blob: 4f12701a9633f34cb6e5c68fadb7e2ac1ebd49c7 [file] [log] [blame]
Dmitry V. Levin977550d2015-02-27 04:09:56 +00001#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4#include <dlfcn.h>
Dmitry V. Levin1c5fead2015-02-23 22:37:40 +00005#include <fcntl.h>
Dmitry V. Levine96cb622015-02-15 15:52:02 +00006#include <unistd.h>
7#include <sys/mman.h>
8#include <sys/wait.h>
Dmitry V. Levin1c5fead2015-02-23 22:37:40 +00009#include <sys/sendfile.h>
Dmitry V. Levine96cb622015-02-15 15:52:02 +000010
11int main(void)
12{
Dmitry V. Levin977550d2015-02-27 04:09:56 +000013 const unsigned long pagesize = sysconf(_SC_PAGESIZE);
Dmitry V. Levine96cb622015-02-15 15:52:02 +000014
Mike Frysingereb202ba2015-03-02 20:04:34 -050015#ifdef __s390__
16 /*
17 * The si_addr field is unreliable:
18 * https://marc.info/?l=linux-s390&m=142515870124248&w=2
19 */
20 return 77;
21#endif
22
Dmitry V. Levine96cb622015-02-15 15:52:02 +000023 /* write instruction pointer length to the log */
24 if (write(-1, NULL, 2 * sizeof(void *)) >= 0)
25 return 77;
Dmitry V. Levin1c5fead2015-02-23 22:37:40 +000026
Dmitry V. Levine96cb622015-02-15 15:52:02 +000027 /* just a noticeable line in the log */
Dmitry V. Levin1c5fead2015-02-23 22:37:40 +000028 if (munmap(&main, 0) >= 0)
Dmitry V. Levine96cb622015-02-15 15:52:02 +000029 return 77;
30
31 int pid = fork();
32 if (pid < 0)
33 return 77;
34
35 if (!pid) {
Dmitry V. Levin977550d2015-02-27 04:09:56 +000036 const unsigned long mask = ~(pagesize - 1);
37 unsigned long addr = (unsigned long) &main & mask;
38 unsigned long size = pagesize << 1;
39
40#ifdef HAVE_DLADDR
41 Dl_info info;
42 if (dladdr(&main, &info)) {
43 const unsigned long base =
44 (unsigned long) info.dli_fbase & mask;
45 if (base < addr) {
46 size += addr - base;
47 addr = base;
48 }
49 } else
50#endif
51 {
52 addr -= size;
53 size <<= 1;
54 }
Dmitry V. Levin1c5fead2015-02-23 22:37:40 +000055
Dmitry V. Levine96cb622015-02-15 15:52:02 +000056 /* SIGSEGV is expected */
Dmitry V. Levin977550d2015-02-27 04:09:56 +000057 (void) munmap((void *) addr, size);
58 (void) munmap((void *) addr, size);
Dmitry V. Levine96cb622015-02-15 15:52:02 +000059 return 77;
60 }
61
62 int status;
63 if (wait(&status) != pid ||
64 !WIFSIGNALED(status) ||
65 WTERMSIG(status) != SIGSEGV)
66 return 77;
67
Dmitry V. Levin1c5fead2015-02-23 22:37:40 +000068 /* dump process map for debug purposes */
69 close(0);
70 if (!open("/proc/self/maps", O_RDONLY))
Dmitry V. Levin977550d2015-02-27 04:09:56 +000071 (void) sendfile(1, 0, NULL, pagesize);
Dmitry V. Levin1c5fead2015-02-23 22:37:40 +000072
Dmitry V. Levine96cb622015-02-15 15:52:02 +000073 return 0;
74}