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