• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #define _GNU_SOURCE
2 
3 #include <stdio.h>
4 
5 #include "tests/sys_mman.h"
6 #include <assert.h>
7 #include <stdlib.h>
8 #include <sys/types.h>
9 #include <unistd.h>
10 #include <errno.h>
11 #include <syscall.h>
12 
13 
14 #ifndef REMAP_FIXED
15 #define MREMAP_FIXED 2
16 #endif
17 
18 
19 static int PAGE;
20 
mapanon_fixed(void * start,size_t length)21 void mapanon_fixed ( void* start, size_t length )
22 {
23   void* r = mmap(start, length, PROT_NONE,
24                  MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0,0);
25   assert(r != MAP_FAILED);
26   assert(r == start);
27 }
28 
unmap_and_check(void * start,size_t length)29 void unmap_and_check ( void* start, size_t length )
30 {
31    int r = munmap( start, length );
32    assert(r == 0);
33 }
34 
35 char* workingarea = NULL;
36 char* try_dst     = NULL;
37 
38 // set up working area so expansion limit is 20*PAGE
39 //
40 //   |   10   |   20   |   10   |   60   |
41 //   |  pre   |  src   |  FREE  |  post  |
42 //
43 //  A suitable attempted fixed dst is workingarea + 150*PAGE.
44 
setup(void * other_stuff,int other_len)45 char* setup ( void* other_stuff, int other_len )
46 {
47   if (!workingarea) {
48      workingarea = mmap(0, 200*PAGE, PROT_NONE,
49                            MAP_ANONYMOUS|MAP_PRIVATE, 0,0);
50      assert(workingarea);
51      try_dst = workingarea + 150*PAGE;
52      unmap_and_check(workingarea, 200*PAGE);
53   }
54 
55   if (other_stuff) {
56     unmap_and_check(other_stuff, other_len);
57   }
58 
59   // get rid of the old working area
60   unmap_and_check( workingarea, 200*PAGE);
61 
62   // pre block
63   mapanon_fixed( workingarea + 0*PAGE, 9*PAGE);
64 
65   // the area
66   mapanon_fixed( workingarea + 10*PAGE, 20*PAGE );
67 
68   // upper half
69   mapanon_fixed( workingarea + 40*PAGE, 60*PAGE );
70 
71   return workingarea + 10*PAGE;
72 }
73 
74 /* show the working area */
show(void)75 void show ( void )
76 {
77   int i,r __attribute__((unused));
78   for (i = 0; i < 200; i++) {
79     r = mprotect( workingarea + i * PAGE, PAGE, PROT_NONE );
80     // We used to print 'X' or '.' according to the mprotect result, but the
81     // results are too variable and the test was never reliable.  So now we
82     // just always print '.'.  At least this test gives mremap a thorough
83     // working out and so will detect egregious problems like crashes.
84     //printf("%c", r == 0 ? 'X' : '.');
85     printf(".");
86     if (i == 49 || i == 99 || i == 149) printf("\n");
87   }
88   printf("\n");
89 }
90 
91 
92 char* dst = NULL;
93 char* src = NULL;
94 char* dst_impossible = NULL;
95 
96 
identify(char * p)97 char* identify ( char* p )
98 {
99   if (p == dst)            return "dst";
100   if (p == src)            return "src";
101   if (p == dst_impossible) return "dst_imp!";
102   if (p == try_dst)        return "dst_poss";
103   return "other";
104 }
105 
main(void)106 int main ( void )
107 {
108   int alocal, maymove, fixed, nsi, dstpossible;
109   int newsizes[6] = { 19, 20, 21, 29, 30, 31 };
110 
111   char* tidythis = NULL;
112   int  tidylen = 0;
113   int firsttime = 1;
114   char buf[100];
115 
116   dst_impossible = (char*)(&alocal) + 500 * 1000 * 1000;
117 
118   PAGE = sysconf(_SC_PAGESIZE);
119 
120   for (maymove = 0; maymove <= 1 ; maymove++) {
121   for (fixed = 0; fixed <= 1; fixed++) {
122     printf("\n");
123   for (nsi = 0; nsi < 6; nsi++) {
124   for (dstpossible = 0; dstpossible <= 1; dstpossible++) {
125 
126     char* r;
127     int newsize = newsizes[nsi] * PAGE;
128     int flags = (maymove ? MREMAP_MAYMOVE : 0)  |
129                 (fixed ? MREMAP_FIXED : 0);
130     dst = dstpossible ? try_dst : dst_impossible;
131     src = setup( tidythis, tidylen );
132 
133     if (firsttime) {
134        printf("dst_possible   = %p\n", try_dst );
135        printf("dst_impossible = %p\n", dst_impossible );
136        printf("           src = %p\n", src);
137        printf("\n");
138        sprintf(buf, "cat /proc/%d/maps", getpid());
139        if (0) system(buf);
140        firsttime = 0;
141     }
142 
143     printf("maymv %d   fixed %d   newsz %2d   dstpo %d  dst %p ->  ",
144 	   maymove, fixed, newsizes[nsi], dstpossible, dst );
145     r = (char*)
146         syscall(__NR_mremap, src, 20*PAGE, newsize, flags, dst, 0 );
147     // We used to print the address or error, but that was also unreliable.
148     //if (r == MAP_FAILED)
149     //  printf("error %d\n", errno);
150     //else
151     //  printf("%p (== %s)\n", r, identify(r));
152     printf("\n");
153 
154     if (1) {
155        show();
156        printf("\n");
157     }
158 
159     if (r != MAP_FAILED) {
160       if (r != src && r != try_dst && r != dst_impossible) {
161 	tidythis = r;
162 	tidylen = newsize;
163       }
164     }
165 
166   }
167   }
168   }
169   }
170   return 0;
171 }
172