Revision 54c5a2ae linux-user/mmap.c

b/linux-user/mmap.c
24 24
#include <string.h>
25 25
#include <unistd.h>
26 26
#include <errno.h>
27
#include <sys/types.h>
28
#include <sys/stat.h>
27 29
#include <sys/mman.h>
28 30
#include <linux/mman.h>
29 31
#include <linux/unistd.h>
......
366 368
        goto the_end;
367 369
    real_start = start & qemu_host_page_mask;
368 370

  
371
    /* When mapping files into a memory area larger than the file, accesses
372
       to pages beyond the file size will cause a SIGBUS. 
373

  
374
       For example, if mmaping a file of 100 bytes on a host with 4K pages
375
       emulating a target with 8K pages, the target expects to be able to
376
       access the first 8K. But the host will trap us on any access beyond
377
       4K.  
378

  
379
       When emulating a target with a larger page-size than the hosts, we
380
       may need to truncate file maps at EOF and add extra anonymous pages
381
       up to the targets page boundary.  */
382

  
383
    if ((qemu_real_host_page_size < TARGET_PAGE_SIZE)
384
        && !(flags & MAP_ANONYMOUS)) {
385
       struct stat sb;
386

  
387
       if (fstat (fd, &sb) == -1)
388
           goto fail;
389

  
390
       /* Are we trying to create a map beyond EOF?.  */
391
       if (offset + len > sb.st_size) {
392
           /* If so, truncate the file map at eof aligned with 
393
              the hosts real pagesize. Additional anonymous maps
394
              will be created beyond EOF.  */
395
           len = (sb.st_size - offset);
396
           len += qemu_real_host_page_size - 1;
397
           len &= ~(qemu_real_host_page_size - 1);
398
       }
399
    }
400

  
369 401
    if (!(flags & MAP_FIXED)) {
370 402
        abi_ulong mmap_start;
371 403
        void *p;
......
381 413
           especially important if qemu_host_page_size >
382 414
           qemu_real_host_page_size */
383 415
        p = mmap(g2h(mmap_start),
384
                 host_len, prot, flags | MAP_FIXED, fd, host_offset);
416
                 host_len, prot, flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
385 417
        if (p == MAP_FAILED)
386 418
            goto fail;
387 419
        /* update start so that it points to the file position at 'offset' */
388 420
        host_start = (unsigned long)p;
389
        if (!(flags & MAP_ANONYMOUS))
421
        if (!(flags & MAP_ANONYMOUS)) {
422
            p = mmap(g2h(mmap_start), len, prot, 
423
                     flags | MAP_FIXED, fd, host_offset);
390 424
            host_start += offset - host_offset;
425
        }
391 426
        start = h2g(host_start);
392 427
    } else {
393 428
        int flg;

Also available in: Unified diff