blob: a450c0d15129eec2c3044cf00bb757b11c519a3d [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
15 /* write instruction pointer length to the log */
16 if (write(-1, NULL, 2 * sizeof(void *)) >= 0)
17 return 77;
Dmitry V. Levin1c5fead2015-02-23 22:37:40 +000018
Dmitry V. Levine96cb622015-02-15 15:52:02 +000019 /* just a noticeable line in the log */
Dmitry V. Levin1c5fead2015-02-23 22:37:40 +000020 if (munmap(&main, 0) >= 0)
Dmitry V. Levine96cb622015-02-15 15:52:02 +000021 return 77;
22
23 int pid = fork();
24 if (pid < 0)
25 return 77;
26
27 if (!pid) {
Dmitry V. Levin977550d2015-02-27 04:09:56 +000028 const unsigned long mask = ~(pagesize - 1);
29 unsigned long addr = (unsigned long) &main & mask;
30 unsigned long size = pagesize << 1;
31
32#ifdef HAVE_DLADDR
33 Dl_info info;
34 if (dladdr(&main, &info)) {
35 const unsigned long base =
36 (unsigned long) info.dli_fbase & mask;
37 if (base < addr) {
38 size += addr - base;
39 addr = base;
40 }
41 } else
42#endif
43 {
44 addr -= size;
45 size <<= 1;
46 }
Dmitry V. Levin1c5fead2015-02-23 22:37:40 +000047
Dmitry V. Levine96cb622015-02-15 15:52:02 +000048 /* SIGSEGV is expected */
Dmitry V. Levin977550d2015-02-27 04:09:56 +000049 (void) munmap((void *) addr, size);
50 (void) munmap((void *) addr, size);
Dmitry V. Levine96cb622015-02-15 15:52:02 +000051 return 77;
52 }
53
54 int status;
55 if (wait(&status) != pid ||
56 !WIFSIGNALED(status) ||
57 WTERMSIG(status) != SIGSEGV)
58 return 77;
59
Dmitry V. Levin1c5fead2015-02-23 22:37:40 +000060 /* dump process map for debug purposes */
61 close(0);
62 if (!open("/proc/self/maps", O_RDONLY))
Dmitry V. Levin977550d2015-02-27 04:09:56 +000063 (void) sendfile(1, 0, NULL, pagesize);
Dmitry V. Levin1c5fead2015-02-23 22:37:40 +000064
Dmitry V. Levine96cb622015-02-15 15:52:02 +000065 return 0;
66}