|
|
1.1 ! root 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 being 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: #include <stdio.h> ! 26: #include <stdlib.h> ! 27: #include <stdint.h> ! 28: #include <string.h> ! 29: #include <unistd.h> ! 30: ! 31: #include <sys/mman.h> ! 32: ! 33: #define D(x) ! 34: ! 35: #define fail_unless(x) \ ! 36: do \ ! 37: { \ ! 38: if (!(x)) { \ ! 39: fprintf (stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \ ! 40: exit (EXIT_FAILURE); \ ! 41: } \ ! 42: } while (0); ! 43: ! 44: unsigned char *dummybuf; ! 45: static unsigned int pagesize; ! 46: static unsigned int pagemask; ! 47: int test_fd; ! 48: size_t test_fsize; ! 49: ! 50: void check_aligned_anonymous_unfixed_mmaps(void) ! 51: { ! 52: void *p1; ! 53: void *p2; ! 54: void *p3; ! 55: void *p4; ! 56: void *p5; ! 57: uintptr_t p; ! 58: int i; ! 59: ! 60: fprintf (stderr, "%s", __func__); ! 61: for (i = 0; i < 0x1fff; i++) ! 62: { ! 63: size_t len; ! 64: ! 65: len = pagesize + (pagesize * i & 7); ! 66: p1 = mmap(NULL, len, PROT_READ, ! 67: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ! 68: p2 = mmap(NULL, len, PROT_READ, ! 69: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ! 70: p3 = mmap(NULL, len, PROT_READ, ! 71: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ! 72: p4 = mmap(NULL, len, PROT_READ, ! 73: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ! 74: p5 = mmap(NULL, len, PROT_READ, ! 75: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ! 76: ! 77: /* Make sure we get pages aligned with the pagesize. The ! 78: target expects this. */ ! 79: fail_unless (p1 != MAP_FAILED); ! 80: fail_unless (p2 != MAP_FAILED); ! 81: fail_unless (p3 != MAP_FAILED); ! 82: fail_unless (p4 != MAP_FAILED); ! 83: fail_unless (p5 != MAP_FAILED); ! 84: p = (uintptr_t) p1; ! 85: D(printf ("p=%x\n", p)); ! 86: fail_unless ((p & pagemask) == 0); ! 87: p = (uintptr_t) p2; ! 88: fail_unless ((p & pagemask) == 0); ! 89: p = (uintptr_t) p3; ! 90: fail_unless ((p & pagemask) == 0); ! 91: p = (uintptr_t) p4; ! 92: fail_unless ((p & pagemask) == 0); ! 93: p = (uintptr_t) p5; ! 94: fail_unless ((p & pagemask) == 0); ! 95: ! 96: /* Make sure we can read from the entire area. */ ! 97: memcpy (dummybuf, p1, pagesize); ! 98: memcpy (dummybuf, p2, pagesize); ! 99: memcpy (dummybuf, p3, pagesize); ! 100: memcpy (dummybuf, p4, pagesize); ! 101: memcpy (dummybuf, p5, pagesize); ! 102: ! 103: munmap (p1, len); ! 104: munmap (p2, len); ! 105: munmap (p3, len); ! 106: munmap (p4, len); ! 107: munmap (p5, len); ! 108: } ! 109: fprintf (stderr, " passed\n"); ! 110: } ! 111: ! 112: void check_large_anonymous_unfixed_mmap(void) ! 113: { ! 114: void *p1; ! 115: uintptr_t p; ! 116: size_t len; ! 117: ! 118: fprintf (stderr, "%s", __func__); ! 119: ! 120: len = 0x02000000; ! 121: p1 = mmap(NULL, len, PROT_READ, ! 122: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ! 123: ! 124: /* Make sure we get pages aligned with the pagesize. The ! 125: target expects this. */ ! 126: fail_unless (p1 != MAP_FAILED); ! 127: p = (uintptr_t) p1; ! 128: fail_unless ((p & pagemask) == 0); ! 129: ! 130: /* Make sure we can read from the entire area. */ ! 131: memcpy (dummybuf, p1, pagesize); ! 132: munmap (p1, len); ! 133: fprintf (stderr, " passed\n"); ! 134: } ! 135: ! 136: void check_aligned_anonymous_unfixed_colliding_mmaps(void) ! 137: { ! 138: char *p1; ! 139: char *p2; ! 140: char *p3; ! 141: uintptr_t p; ! 142: int i; ! 143: ! 144: fprintf (stderr, "%s", __func__); ! 145: for (i = 0; i < 0x2fff; i++) ! 146: { ! 147: int nlen; ! 148: p1 = mmap(NULL, pagesize, PROT_READ, ! 149: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ! 150: fail_unless (p1 != MAP_FAILED); ! 151: p = (uintptr_t) p1; ! 152: fail_unless ((p & pagemask) == 0); ! 153: memcpy (dummybuf, p1, pagesize); ! 154: ! 155: p2 = mmap(NULL, pagesize, PROT_READ, ! 156: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ! 157: fail_unless (p2 != MAP_FAILED); ! 158: p = (uintptr_t) p2; ! 159: fail_unless ((p & pagemask) == 0); ! 160: memcpy (dummybuf, p2, pagesize); ! 161: ! 162: ! 163: munmap (p1, pagesize); ! 164: nlen = pagesize * 8; ! 165: p3 = mmap(NULL, nlen, PROT_READ, ! 166: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ! 167: fail_unless (p3 != MAP_FAILED); ! 168: ! 169: /* Check if the mmaped areas collide. */ ! 170: if (p3 < p2 ! 171: && (p3 + nlen) > p2) ! 172: fail_unless (0); ! 173: ! 174: memcpy (dummybuf, p3, pagesize); ! 175: ! 176: /* Make sure we get pages aligned with the pagesize. The ! 177: target expects this. */ ! 178: p = (uintptr_t) p3; ! 179: fail_unless ((p & pagemask) == 0); ! 180: munmap (p2, pagesize); ! 181: munmap (p3, nlen); ! 182: } ! 183: fprintf (stderr, " passed\n"); ! 184: } ! 185: ! 186: void check_aligned_anonymous_fixed_mmaps(void) ! 187: { ! 188: char *addr; ! 189: void *p1; ! 190: uintptr_t p; ! 191: int i; ! 192: ! 193: /* Find a suitable address to start with. */ ! 194: addr = mmap(NULL, pagesize * 40, PROT_READ | PROT_WRITE, ! 195: MAP_PRIVATE | MAP_ANONYMOUS, ! 196: -1, 0); ! 197: fprintf (stderr, "%s addr=%p", __func__, addr); ! 198: fail_unless (addr != MAP_FAILED); ! 199: ! 200: for (i = 0; i < 40; i++) ! 201: { ! 202: /* Create submaps within our unfixed map. */ ! 203: p1 = mmap(addr, pagesize, PROT_READ, ! 204: MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, ! 205: -1, 0); ! 206: /* Make sure we get pages aligned with the pagesize. ! 207: The target expects this. */ ! 208: p = (uintptr_t) p1; ! 209: fail_unless (p1 == addr); ! 210: fail_unless ((p & pagemask) == 0); ! 211: memcpy (dummybuf, p1, pagesize); ! 212: munmap (p1, pagesize); ! 213: addr += pagesize; ! 214: } ! 215: fprintf (stderr, " passed\n"); ! 216: } ! 217: ! 218: void check_aligned_anonymous_fixed_mmaps_collide_with_host(void) ! 219: { ! 220: char *addr; ! 221: void *p1; ! 222: uintptr_t p; ! 223: int i; ! 224: ! 225: /* Find a suitable address to start with. Right were the x86 hosts ! 226: stack is. */ ! 227: addr = ((void *)0x80000000); ! 228: fprintf (stderr, "%s addr=%p", __func__, addr); ! 229: fprintf (stderr, "FIXME: QEMU fails to track pages used by the host."); ! 230: ! 231: for (i = 0; i < 20; i++) ! 232: { ! 233: /* Create submaps within our unfixed map. */ ! 234: p1 = mmap(addr, pagesize, PROT_READ | PROT_WRITE, ! 235: MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, ! 236: -1, 0); ! 237: /* Make sure we get pages aligned with the pagesize. ! 238: The target expects this. */ ! 239: p = (uintptr_t) p1; ! 240: fail_unless (p1 == addr); ! 241: fail_unless ((p & pagemask) == 0); ! 242: memcpy (p1, dummybuf, pagesize); ! 243: munmap (p1, pagesize); ! 244: addr += pagesize; ! 245: } ! 246: fprintf (stderr, " passed\n"); ! 247: } ! 248: ! 249: void check_file_unfixed_mmaps(void) ! 250: { ! 251: unsigned int *p1, *p2, *p3; ! 252: uintptr_t p; ! 253: int i; ! 254: ! 255: fprintf (stderr, "%s", __func__); ! 256: for (i = 0; i < 0x10; i++) ! 257: { ! 258: size_t len; ! 259: ! 260: len = pagesize; ! 261: p1 = mmap(NULL, len, PROT_READ, ! 262: MAP_PRIVATE, ! 263: test_fd, 0); ! 264: p2 = mmap(NULL, len, PROT_READ, ! 265: MAP_PRIVATE, ! 266: test_fd, pagesize); ! 267: p3 = mmap(NULL, len, PROT_READ, ! 268: MAP_PRIVATE, ! 269: test_fd, pagesize * 2); ! 270: ! 271: fail_unless (p1 != MAP_FAILED); ! 272: fail_unless (p2 != MAP_FAILED); ! 273: fail_unless (p3 != MAP_FAILED); ! 274: ! 275: /* Make sure we get pages aligned with the pagesize. The ! 276: target expects this. */ ! 277: p = (uintptr_t) p1; ! 278: fail_unless ((p & pagemask) == 0); ! 279: p = (uintptr_t) p2; ! 280: fail_unless ((p & pagemask) == 0); ! 281: p = (uintptr_t) p3; ! 282: fail_unless ((p & pagemask) == 0); ! 283: ! 284: /* Verify that the file maps was made correctly. */ ! 285: D(printf ("p1=%d p2=%d p3=%d\n", *p1, *p2, *p3)); ! 286: fail_unless (*p1 == 0); ! 287: fail_unless (*p2 == (pagesize / sizeof *p2)); ! 288: fail_unless (*p3 == ((pagesize * 2) / sizeof *p3)); ! 289: ! 290: memcpy (dummybuf, p1, pagesize); ! 291: memcpy (dummybuf, p2, pagesize); ! 292: memcpy (dummybuf, p3, pagesize); ! 293: munmap (p1, len); ! 294: munmap (p2, len); ! 295: munmap (p3, len); ! 296: } ! 297: fprintf (stderr, " passed\n"); ! 298: } ! 299: ! 300: void check_file_unfixed_eof_mmaps(void) ! 301: { ! 302: char *cp; ! 303: unsigned int *p1; ! 304: uintptr_t p; ! 305: int i; ! 306: ! 307: fprintf (stderr, "%s", __func__); ! 308: for (i = 0; i < 0x10; i++) ! 309: { ! 310: p1 = mmap(NULL, pagesize, PROT_READ, ! 311: MAP_PRIVATE, ! 312: test_fd, ! 313: (test_fsize - sizeof *p1) & ~pagemask); ! 314: ! 315: fail_unless (p1 != MAP_FAILED); ! 316: ! 317: /* Make sure we get pages aligned with the pagesize. The ! 318: target expects this. */ ! 319: p = (uintptr_t) p1; ! 320: fail_unless ((p & pagemask) == 0); ! 321: /* Verify that the file maps was made correctly. */ ! 322: fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1] ! 323: == ((test_fsize - sizeof *p1) / sizeof *p1)); ! 324: ! 325: /* Verify that the end of page is accessible and zeroed. */ ! 326: cp = (void *) p1; ! 327: fail_unless (cp[pagesize - 4] == 0); ! 328: munmap (p1, pagesize); ! 329: } ! 330: fprintf (stderr, " passed\n"); ! 331: } ! 332: ! 333: void check_file_fixed_eof_mmaps(void) ! 334: { ! 335: char *addr; ! 336: char *cp; ! 337: unsigned int *p1; ! 338: uintptr_t p; ! 339: int i; ! 340: ! 341: /* Find a suitable address to start with. */ ! 342: addr = mmap(NULL, pagesize * 44, PROT_READ, ! 343: MAP_PRIVATE | MAP_ANONYMOUS, ! 344: -1, 0); ! 345: ! 346: fprintf (stderr, "%s addr=%p", __func__, (void *)addr); ! 347: fail_unless (addr != MAP_FAILED); ! 348: ! 349: for (i = 0; i < 0x10; i++) ! 350: { ! 351: /* Create submaps within our unfixed map. */ ! 352: p1 = mmap(addr, pagesize, PROT_READ, ! 353: MAP_PRIVATE | MAP_FIXED, ! 354: test_fd, ! 355: (test_fsize - sizeof *p1) & ~pagemask); ! 356: ! 357: fail_unless (p1 != MAP_FAILED); ! 358: ! 359: /* Make sure we get pages aligned with the pagesize. The ! 360: target expects this. */ ! 361: p = (uintptr_t) p1; ! 362: fail_unless ((p & pagemask) == 0); ! 363: ! 364: /* Verify that the file maps was made correctly. */ ! 365: fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1] ! 366: == ((test_fsize - sizeof *p1) / sizeof *p1)); ! 367: ! 368: /* Verify that the end of page is accessible and zeroed. */ ! 369: cp = (void *)p1; ! 370: fail_unless (cp[pagesize - 4] == 0); ! 371: munmap (p1, pagesize); ! 372: addr += pagesize; ! 373: } ! 374: fprintf (stderr, " passed\n"); ! 375: } ! 376: ! 377: void check_file_fixed_mmaps(void) ! 378: { ! 379: unsigned char *addr; ! 380: unsigned int *p1, *p2, *p3, *p4; ! 381: int i; ! 382: ! 383: /* Find a suitable address to start with. */ ! 384: addr = mmap(NULL, pagesize * 40 * 4, PROT_READ, ! 385: MAP_PRIVATE | MAP_ANONYMOUS, ! 386: -1, 0); ! 387: fprintf (stderr, "%s addr=%p", __func__, (void *)addr); ! 388: fail_unless (addr != MAP_FAILED); ! 389: ! 390: for (i = 0; i < 40; i++) ! 391: { ! 392: p1 = mmap(addr, pagesize, PROT_READ, ! 393: MAP_PRIVATE | MAP_FIXED, ! 394: test_fd, 0); ! 395: p2 = mmap(addr + pagesize, pagesize, PROT_READ, ! 396: MAP_PRIVATE | MAP_FIXED, ! 397: test_fd, pagesize); ! 398: p3 = mmap(addr + pagesize * 2, pagesize, PROT_READ, ! 399: MAP_PRIVATE | MAP_FIXED, ! 400: test_fd, pagesize * 2); ! 401: p4 = mmap(addr + pagesize * 3, pagesize, PROT_READ, ! 402: MAP_PRIVATE | MAP_FIXED, ! 403: test_fd, pagesize * 3); ! 404: ! 405: /* Make sure we get pages aligned with the pagesize. ! 406: The target expects this. */ ! 407: fail_unless (p1 == (void *)addr); ! 408: fail_unless (p2 == (void *)addr + pagesize); ! 409: fail_unless (p3 == (void *)addr + pagesize * 2); ! 410: fail_unless (p4 == (void *)addr + pagesize * 3); ! 411: ! 412: /* Verify that the file maps was made correctly. */ ! 413: fail_unless (*p1 == 0); ! 414: fail_unless (*p2 == (pagesize / sizeof *p2)); ! 415: fail_unless (*p3 == ((pagesize * 2) / sizeof *p3)); ! 416: fail_unless (*p4 == ((pagesize * 3) / sizeof *p4)); ! 417: ! 418: memcpy (dummybuf, p1, pagesize); ! 419: memcpy (dummybuf, p2, pagesize); ! 420: memcpy (dummybuf, p3, pagesize); ! 421: memcpy (dummybuf, p4, pagesize); ! 422: ! 423: munmap (p1, pagesize); ! 424: munmap (p2, pagesize); ! 425: munmap (p3, pagesize); ! 426: munmap (p4, pagesize); ! 427: addr += pagesize * 4; ! 428: } ! 429: fprintf (stderr, " passed\n"); ! 430: } ! 431: ! 432: int main(int argc, char **argv) ! 433: { ! 434: char tempname[] = "/tmp/.cmmapXXXXXX"; ! 435: unsigned int i; ! 436: ! 437: /* Trust the first argument, otherwise probe the system for our ! 438: pagesize. */ ! 439: if (argc > 1) ! 440: pagesize = strtoul(argv[1], NULL, 0); ! 441: else ! 442: pagesize = sysconf(_SC_PAGESIZE); ! 443: ! 444: /* Assume pagesize is a power of two. */ ! 445: pagemask = pagesize - 1; ! 446: dummybuf = malloc (pagesize); ! 447: printf ("pagesize=%u pagemask=%x\n", pagesize, pagemask); ! 448: ! 449: test_fd = mkstemp(tempname); ! 450: unlink(tempname); ! 451: ! 452: /* Fill the file with int's counting from zero and up. */ ! 453: for (i = 0; i < (pagesize * 4) / sizeof i; i++) ! 454: write (test_fd, &i, sizeof i); ! 455: /* Append a few extra writes to make the file end at non ! 456: page boundary. */ ! 457: write (test_fd, &i, sizeof i); i++; ! 458: write (test_fd, &i, sizeof i); i++; ! 459: write (test_fd, &i, sizeof i); i++; ! 460: ! 461: test_fsize = lseek(test_fd, 0, SEEK_CUR); ! 462: ! 463: /* Run the tests. */ ! 464: check_aligned_anonymous_unfixed_mmaps(); ! 465: check_aligned_anonymous_unfixed_colliding_mmaps(); ! 466: check_aligned_anonymous_fixed_mmaps(); ! 467: check_file_unfixed_mmaps(); ! 468: check_file_fixed_mmaps(); ! 469: check_file_fixed_eof_mmaps(); ! 470: check_file_unfixed_eof_mmaps(); ! 471: ! 472: /* Fails at the moment. */ ! 473: /* check_aligned_anonymous_fixed_mmaps_collide_with_host(); */ ! 474: ! 475: return EXIT_SUCCESS; ! 476: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.