1 /* Maps several pages with or without MAP_NORESEVE.
2 Mappings with MAP_NORESEVE do not show in /proc/self/xmap
3 (only in /proc/self/rmap) until they actually materialize.
4 Very nice from Solaris kernel :-(
5 */
6
7 #include <dlfcn.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <wait.h>
12 #include <sys/mman.h>
13 #include <sys/param.h>
14
do_map(int flags)15 static void *do_map(int flags)
16 {
17 flags |= MAP_PRIVATE | MAP_ANON;
18 void *addr = mmap(0, PAGESIZE, PROT_READ | PROT_WRITE, flags, -1, 0);
19 if (addr == NULL) {
20 perror("mmap");
21 exit(1);
22 } else {
23 return addr;
24 }
25 }
26
do_dlopen(const char * pathname)27 static void *do_dlopen(const char *pathname)
28 {
29 int mode = RTLD_LAZY | RTLD_LOCAL;
30 void *handle = dlopen(pathname, mode);
31 if (handle == NULL) {
32 fprintf(stderr, "dlopen failed for %s: %s",
33 pathname, dlerror());
34 exit(1);
35 } else {
36 return handle;
37 }
38 }
39
main(int argc,const char * argv[])40 int main(int argc, const char *argv[])
41 {
42 do_map(MAP_NORESERVE);
43 do_dlopen("libm.so");
44 do_map(0);
45 do_map(0);
46 do_map(MAP_NORESERVE);
47 do_dlopen("liby.so");
48 do_map(MAP_NORESERVE);
49 do_map(0);
50 do_map(0);
51 do_map(MAP_NORESERVE);
52 do_map(MAP_NORESERVE);
53 do_dlopen("libz.so");
54 do_map(MAP_NORESERVE);
55 do_map(MAP_NORESERVE);
56 do_map(0);
57
58 pid_t pid = fork();
59 if (pid == -1) {
60 perror("fork");
61 exit(1);
62 }
63
64 if (pid == 0) {
65 do_map(MAP_NORESERVE);
66 do_map(0);
67 do_map(0);
68 do_dlopen("libw.so");
69 do_map(0);
70 do_map(MAP_NORESERVE);
71 do_map(MAP_NORESERVE);
72 do_map(0);
73 printf("CHILD: PASSED\n");
74 fflush(stdout);
75 return 0;
76 }
77
78 int status;
79 if (waitpid(pid, &status, 0) != pid) {
80 perror("waitpid");
81 } else if ((WIFEXITED(status) != 0) && (WEXITSTATUS(status) == 0)) {
82 printf("PASSED\n");
83 } else {
84 fprintf(stderr, "FAILED: child exited with unexpected status %s %d\n",
85 WIFEXITED(status) ? "exit" : "signal",
86 WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status));
87 }
88
89 return 0;
90 }
91