• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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