VirtualBox

source: vbox/trunk/src/recompiler/tests/test-mmap.c@ 76553

Last change on this file since 76553 was 62086, checked in by vboxsync, 8 years ago

Avoid arithmetic on void *

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.8 KB
Line 
1/*
2 * Small test program to verify simulated mmap behaviour.
3 *
4 * When running qemu-linux-user with the -p flag, you may need to tell
5 * this test program about the pagesize because getpagesize() will not reflect
6 * the -p choice. Simply pass one argument beeing the pagesize.
7 *
8 * Copyright (c) 2007 AXIS Communications AB
9 * Written by Edgar E. Iglesias.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 */
24
25/*
26 * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
27 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
28 * the General Public License version 2 (GPLv2) at this time for any software where
29 * a choice of GPL license versions is made available with the language indicating
30 * that GPLv2 or any later version may be used, or where a choice of which version
31 * of the GPL is applied is otherwise unspecified.
32 */
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <stdint.h>
37#include <string.h>
38#include <unistd.h>
39
40#include <sys/mman.h>
41
42#define D(x)
43
44#define fail_unless(x) \
45do \
46{ \
47 if (!(x)) { \
48 fprintf (stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \
49 exit (EXIT_FAILURE); \
50 } \
51} while (0);
52
53unsigned char *dummybuf;
54static unsigned int pagesize;
55static unsigned int pagemask;
56int test_fd;
57size_t test_fsize;
58
59void check_aligned_anonymous_unfixed_mmaps(void)
60{
61 void *p1;
62 void *p2;
63 void *p3;
64 void *p4;
65 void *p5;
66 uintptr_t p;
67 int i;
68
69 fprintf (stderr, "%s", __func__);
70 for (i = 0; i < 0x1fff; i++)
71 {
72 size_t len;
73
74 len = pagesize + (pagesize * i & 7);
75 p1 = mmap(NULL, len, PROT_READ,
76 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
77 p2 = mmap(NULL, len, PROT_READ,
78 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
79 p3 = mmap(NULL, len, PROT_READ,
80 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
81 p4 = mmap(NULL, len, PROT_READ,
82 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
83 p5 = mmap(NULL, len, PROT_READ,
84 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
85
86 /* Make sure we get pages aligned with the pagesize. The
87 target expects this. */
88 fail_unless (p1 != MAP_FAILED);
89 fail_unless (p2 != MAP_FAILED);
90 fail_unless (p3 != MAP_FAILED);
91 fail_unless (p4 != MAP_FAILED);
92 fail_unless (p5 != MAP_FAILED);
93 p = (uintptr_t) p1;
94 D(printf ("p=%x\n", p));
95 fail_unless ((p & pagemask) == 0);
96 p = (uintptr_t) p2;
97 fail_unless ((p & pagemask) == 0);
98 p = (uintptr_t) p3;
99 fail_unless ((p & pagemask) == 0);
100 p = (uintptr_t) p4;
101 fail_unless ((p & pagemask) == 0);
102 p = (uintptr_t) p5;
103 fail_unless ((p & pagemask) == 0);
104
105 /* Make sure we can read from the entire area. */
106 memcpy (dummybuf, p1, pagesize);
107 memcpy (dummybuf, p2, pagesize);
108 memcpy (dummybuf, p3, pagesize);
109 memcpy (dummybuf, p4, pagesize);
110 memcpy (dummybuf, p5, pagesize);
111
112 munmap (p1, len);
113 munmap (p2, len);
114 munmap (p3, len);
115 munmap (p4, len);
116 munmap (p5, len);
117 }
118 fprintf (stderr, " passed\n");
119}
120
121void check_large_anonymous_unfixed_mmap(void)
122{
123 void *p1;
124 uintptr_t p;
125 size_t len;
126
127 fprintf (stderr, "%s", __func__);
128
129 len = 0x02000000;
130 p1 = mmap(NULL, len, PROT_READ,
131 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
132
133 /* Make sure we get pages aligned with the pagesize. The
134 target expects this. */
135 fail_unless (p1 != MAP_FAILED);
136 p = (uintptr_t) p1;
137 fail_unless ((p & pagemask) == 0);
138
139 /* Make sure we can read from the entire area. */
140 memcpy (dummybuf, p1, pagesize);
141 munmap (p1, len);
142 fprintf (stderr, " passed\n");
143}
144
145void check_aligned_anonymous_unfixed_colliding_mmaps(void)
146{
147 char *p1;
148 char *p2;
149 char *p3;
150 uintptr_t p;
151 int i;
152
153 fprintf (stderr, "%s", __func__);
154 for (i = 0; i < 0x2fff; i++)
155 {
156 int nlen;
157 p1 = mmap(NULL, pagesize, PROT_READ,
158 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
159 fail_unless (p1 != MAP_FAILED);
160 p = (uintptr_t) p1;
161 fail_unless ((p & pagemask) == 0);
162 memcpy (dummybuf, p1, pagesize);
163
164 p2 = mmap(NULL, pagesize, PROT_READ,
165 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
166 fail_unless (p2 != MAP_FAILED);
167 p = (uintptr_t) p2;
168 fail_unless ((p & pagemask) == 0);
169 memcpy (dummybuf, p2, pagesize);
170
171
172 munmap (p1, pagesize);
173 nlen = pagesize * 8;
174 p3 = mmap(NULL, nlen, PROT_READ,
175 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
176
177 /* Check if the mmaped areas collide. */
178 if (p3 < p2
179 && (p3 + nlen) > p2)
180 fail_unless (0);
181
182 memcpy (dummybuf, p3, pagesize);
183
184 /* Make sure we get pages aligned with the pagesize. The
185 target expects this. */
186 fail_unless (p3 != MAP_FAILED);
187 p = (uintptr_t) p3;
188 fail_unless ((p & pagemask) == 0);
189 munmap (p2, pagesize);
190 munmap (p3, nlen);
191 }
192 fprintf (stderr, " passed\n");
193}
194
195void check_aligned_anonymous_fixed_mmaps(void)
196{
197 char *addr;
198 void *p1;
199 uintptr_t p;
200 int i;
201
202 /* Find a suitable address to start with. */
203 addr = mmap(NULL, pagesize * 40, PROT_READ | PROT_WRITE,
204 MAP_PRIVATE | MAP_ANONYMOUS,
205 -1, 0);
206 fprintf (stderr, "%s addr=%p", __func__, addr);
207 fail_unless (addr != MAP_FAILED);
208
209 for (i = 0; i < 40; i++)
210 {
211 /* Create submaps within our unfixed map. */
212 p1 = mmap(addr, pagesize, PROT_READ,
213 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
214 -1, 0);
215 /* Make sure we get pages aligned with the pagesize.
216 The target expects this. */
217 p = (uintptr_t) p1;
218 fail_unless (p1 == addr);
219 fail_unless ((p & pagemask) == 0);
220 memcpy (dummybuf, p1, pagesize);
221 munmap (p1, pagesize);
222 addr += pagesize;
223 }
224 fprintf (stderr, " passed\n");
225}
226
227void check_aligned_anonymous_fixed_mmaps_collide_with_host(void)
228{
229 char *addr;
230 void *p1;
231 uintptr_t p;
232 int i;
233
234 /* Find a suitable address to start with. Right were the x86 hosts
235 stack is. */
236 addr = ((void *)0x80000000);
237 fprintf (stderr, "%s addr=%p", __func__, addr);
238 fprintf (stderr, "FIXME: QEMU fails to track pages used by the host.");
239
240 for (i = 0; i < 20; i++)
241 {
242 /* Create submaps within our unfixed map. */
243 p1 = mmap(addr, pagesize, PROT_READ | PROT_WRITE,
244 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
245 -1, 0);
246 /* Make sure we get pages aligned with the pagesize.
247 The target expects this. */
248 p = (uintptr_t) p1;
249 fail_unless (p1 == addr);
250 fail_unless ((p & pagemask) == 0);
251 memcpy (p1, dummybuf, pagesize);
252 munmap (p1, pagesize);
253 addr += pagesize;
254 }
255 fprintf (stderr, " passed\n");
256}
257
258void check_file_unfixed_mmaps(void)
259{
260 unsigned int *p1, *p2, *p3;
261 uintptr_t p;
262 int i;
263
264 fprintf (stderr, "%s", __func__);
265 for (i = 0; i < 0x10; i++)
266 {
267 size_t len;
268
269 len = pagesize;
270 p1 = mmap(NULL, len, PROT_READ,
271 MAP_PRIVATE,
272 test_fd, 0);
273 p2 = mmap(NULL, len, PROT_READ,
274 MAP_PRIVATE,
275 test_fd, pagesize);
276 p3 = mmap(NULL, len, PROT_READ,
277 MAP_PRIVATE,
278 test_fd, pagesize * 2);
279
280 fail_unless (p1 != MAP_FAILED);
281 fail_unless (p2 != MAP_FAILED);
282 fail_unless (p3 != MAP_FAILED);
283
284 /* Make sure we get pages aligned with the pagesize. The
285 target expects this. */
286 p = (uintptr_t) p1;
287 fail_unless ((p & pagemask) == 0);
288 p = (uintptr_t) p2;
289 fail_unless ((p & pagemask) == 0);
290 p = (uintptr_t) p3;
291 fail_unless ((p & pagemask) == 0);
292
293 /* Verify that the file maps was made correctly. */
294 D(printf ("p1=%d p2=%d p3=%d\n", *p1, *p2, *p3));
295 fail_unless (*p1 == 0);
296 fail_unless (*p2 == (pagesize / sizeof *p2));
297 fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
298
299 memcpy (dummybuf, p1, pagesize);
300 memcpy (dummybuf, p2, pagesize);
301 memcpy (dummybuf, p3, pagesize);
302 munmap (p1, len);
303 munmap (p2, len);
304 munmap (p3, len);
305 }
306 fprintf (stderr, " passed\n");
307}
308
309void check_file_unfixed_eof_mmaps(void)
310{
311 char *cp;
312 unsigned int *p1;
313 uintptr_t p;
314 int i;
315
316 fprintf (stderr, "%s", __func__);
317 for (i = 0; i < 0x10; i++)
318 {
319 p1 = mmap(NULL, pagesize, PROT_READ,
320 MAP_PRIVATE,
321 test_fd,
322 (test_fsize - sizeof *p1) & ~pagemask);
323
324 fail_unless (p1 != MAP_FAILED);
325
326 /* Make sure we get pages aligned with the pagesize. The
327 target expects this. */
328 p = (uintptr_t) p1;
329 fail_unless ((p & pagemask) == 0);
330 /* Verify that the file maps was made correctly. */
331 fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
332 == ((test_fsize - sizeof *p1) / sizeof *p1));
333
334 /* Verify that the end of page is accessable and zeroed. */
335 cp = (void *) p1;
336 fail_unless (cp[pagesize - 4] == 0);
337 munmap (p1, pagesize);
338 }
339 fprintf (stderr, " passed\n");
340}
341
342void check_file_fixed_eof_mmaps(void)
343{
344 char *addr;
345 char *cp;
346 unsigned int *p1;
347 uintptr_t p;
348 int i;
349
350 /* Find a suitable address to start with. */
351 addr = mmap(NULL, pagesize * 44, PROT_READ,
352 MAP_PRIVATE | MAP_ANONYMOUS,
353 -1, 0);
354
355 fprintf (stderr, "%s addr=%p", __func__, (void *)addr);
356 fail_unless (addr != MAP_FAILED);
357
358 for (i = 0; i < 0x10; i++)
359 {
360 /* Create submaps within our unfixed map. */
361 p1 = mmap(addr, pagesize, PROT_READ,
362 MAP_PRIVATE | MAP_FIXED,
363 test_fd,
364 (test_fsize - sizeof *p1) & ~pagemask);
365
366 fail_unless (p1 != MAP_FAILED);
367
368 /* Make sure we get pages aligned with the pagesize. The
369 target expects this. */
370 p = (uintptr_t) p1;
371 fail_unless ((p & pagemask) == 0);
372
373 /* Verify that the file maps was made correctly. */
374 fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
375 == ((test_fsize - sizeof *p1) / sizeof *p1));
376
377 /* Verify that the end of page is accessable and zeroed. */
378 cp = (void *)p1;
379 fail_unless (cp[pagesize - 4] == 0);
380 munmap (p1, pagesize);
381 addr += pagesize;
382 }
383 fprintf (stderr, " passed\n");
384}
385
386void check_file_fixed_mmaps(void)
387{
388 unsigned char *addr;
389 unsigned int *p1, *p2, *p3, *p4;
390 int i;
391
392 /* Find a suitable address to start with. */
393 addr = mmap(NULL, pagesize * 40 * 4, PROT_READ,
394 MAP_PRIVATE | MAP_ANONYMOUS,
395 -1, 0);
396 fprintf (stderr, "%s addr=%p", __func__, (void *)addr);
397 fail_unless (addr != MAP_FAILED);
398
399 for (i = 0; i < 40; i++)
400 {
401 p1 = mmap(addr, pagesize, PROT_READ,
402 MAP_PRIVATE | MAP_FIXED,
403 test_fd, 0);
404 p2 = mmap(addr + pagesize, pagesize, PROT_READ,
405 MAP_PRIVATE | MAP_FIXED,
406 test_fd, pagesize);
407 p3 = mmap(addr + pagesize * 2, pagesize, PROT_READ,
408 MAP_PRIVATE | MAP_FIXED,
409 test_fd, pagesize * 2);
410 p4 = mmap(addr + pagesize * 3, pagesize, PROT_READ,
411 MAP_PRIVATE | MAP_FIXED,
412 test_fd, pagesize * 3);
413
414 /* Make sure we get pages aligned with the pagesize.
415 The target expects this. */
416 fail_unless (p1 == (void *)addr);
417 fail_unless (p2 == (void *)(addr + pagesize));
418 fail_unless (p3 == (void *)(addr + pagesize * 2));
419 fail_unless (p4 == (void *)(addr + pagesize * 3));
420
421 /* Verify that the file maps was made correctly. */
422 fail_unless (*p1 == 0);
423 fail_unless (*p2 == (pagesize / sizeof *p2));
424 fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
425 fail_unless (*p4 == ((pagesize * 3) / sizeof *p4));
426
427 memcpy (dummybuf, p1, pagesize);
428 memcpy (dummybuf, p2, pagesize);
429 memcpy (dummybuf, p3, pagesize);
430 memcpy (dummybuf, p4, pagesize);
431
432 munmap (p1, pagesize);
433 munmap (p2, pagesize);
434 munmap (p3, pagesize);
435 munmap (p4, pagesize);
436 addr += pagesize * 4;
437 }
438 fprintf (stderr, " passed\n");
439}
440
441int main(int argc, char **argv)
442{
443 char tempname[] = "/tmp/.cmmapXXXXXX";
444 unsigned int i;
445
446 /* Trust the first argument, otherwise probe the system for our
447 pagesize. */
448 if (argc > 1)
449 pagesize = strtoul(argv[1], NULL, 0);
450 else
451 pagesize = sysconf(_SC_PAGESIZE);
452
453 /* Assume pagesize is a power of two. */
454 pagemask = pagesize - 1;
455 dummybuf = malloc (pagesize);
456 printf ("pagesize=%u pagemask=%x\n", pagesize, pagemask);
457
458 test_fd = mkstemp(tempname);
459 unlink(tempname);
460
461 /* Fill the file with int's counting from zero and up. */
462 for (i = 0; i < (pagesize * 4) / sizeof i; i++)
463 write (test_fd, &i, sizeof i);
464 /* Append a few extra writes to make the file end at non
465 page boundary. */
466 write (test_fd, &i, sizeof i); i++;
467 write (test_fd, &i, sizeof i); i++;
468 write (test_fd, &i, sizeof i); i++;
469
470 test_fsize = lseek(test_fd, 0, SEEK_CUR);
471
472 /* Run the tests. */
473 check_aligned_anonymous_unfixed_mmaps();
474 check_aligned_anonymous_unfixed_colliding_mmaps();
475 check_aligned_anonymous_fixed_mmaps();
476 check_file_unfixed_mmaps();
477 check_file_fixed_mmaps();
478 check_file_fixed_eof_mmaps();
479 check_file_unfixed_eof_mmaps();
480
481 /* Fails at the moment. */
482 /* check_aligned_anonymous_fixed_mmaps_collide_with_host(); */
483
484 return EXIT_SUCCESS;
485}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use