Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2005-11-30 18:05:48 +0300
committerCorinna Vinschen <corinna@vinschen.de>2005-11-30 18:05:48 +0300
commitb0c3293ecc3400c81a110eff22cf1d56ac000e6d (patch)
tree0ff71954f9a4fabf48a50c38c41dac554f9e360e /winsup/cygwin/mmap.cc
parente4809ddd202f9fa37381a7a0099977002a5e0045 (diff)
* mmap.cc (list::try_map): New method, implementing trying to map
within another already existing map, moved from mmap64 here. (mmap64): Just call try_map now. (fhandler_dev_zero::fixup_mmap_after_fork): Always create new private map with PAGE_READWRITE protection. (fixup_mmaps_after_fork): Fix comment.
Diffstat (limited to 'winsup/cygwin/mmap.cc')
-rw-r--r--winsup/cygwin/mmap.cc103
1 files changed, 59 insertions, 44 deletions
diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc
index cee48547b..e523d260e 100644
--- a/winsup/cygwin/mmap.cc
+++ b/winsup/cygwin/mmap.cc
@@ -453,6 +453,7 @@ class list
mmap_record *search_record (_off64_t off, DWORD len);
long search_record (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len,
long start);
+ caddr_t try_map (void *addr, size_t len, int flags, _off64_t off);
};
class map
@@ -726,6 +727,52 @@ list::del_record (int i)
return !nrecs;
}
+caddr_t
+list::try_map (void *addr, size_t len, int flags, _off64_t off)
+{
+ mmap_record *rec;
+
+ if (off == 0 && !fixed (flags))
+ {
+ /* If MAP_FIXED isn't given, check if this mapping matches into the
+ chunk of another already performed mapping. */
+ if ((rec = search_record (off, len)) != NULL
+ && rec->compatible_flags (flags))
+ {
+ if ((off = rec->map_pages (off, len)) == (_off64_t)-1)
+ return (caddr_t) MAP_FAILED;
+ return (caddr_t) rec->get_address () + off;
+ }
+ }
+ else if (fixed (flags))
+ {
+ /* If MAP_FIXED is given, test if the requested area is in an
+ unmapped part of an still active mapping. This can happen
+ if a memory region is unmapped and remapped with MAP_FIXED. */
+ caddr_t u_addr;
+ DWORD u_len;
+ long record_idx = -1;
+ if ((record_idx = search_record ((caddr_t) addr, len, u_addr, u_len,
+ record_idx)) >= 0)
+ {
+ rec = get_record (record_idx);
+ if (u_addr > (caddr_t) addr || u_addr + len < (caddr_t) addr + len
+ || !rec->compatible_flags (flags))
+ {
+ /* Partial match only, or access mode doesn't match. */
+ /* FIXME: Handle partial mappings gracefully if adjacent
+ memory is available. */
+ set_errno (EINVAL);
+ return (caddr_t) MAP_FAILED;
+ }
+ if (!rec->map_pages ((caddr_t) addr, len))
+ return (caddr_t) MAP_FAILED;
+ return (caddr_t) addr;
+ }
+ }
+ return NULL;
+}
+
list *
map::get_list_by_fd (int fd)
{
@@ -890,46 +937,13 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, _off64_t off)
/* Test if an existing anonymous mapping can be recycled. */
if (map_list && anonymous (flags))
{
- if (off == 0 && !fixed (flags))
- {
- /* If MAP_FIXED isn't given, check if this mapping matches into the
- chunk of another already performed mapping. */
- if ((rec = map_list->search_record (off, len)) != NULL
- && rec->compatible_flags (flags))
- {
- if ((off = rec->map_pages (off, len)) == (_off64_t)-1)
- goto out;
- ret = rec->get_address () + off;
- goto out;
- }
- }
- else if (fixed (flags))
- {
- /* If MAP_FIXED is given, test if the requested area is in an
- unmapped part of an still active mapping. This can happen
- if a memory region is unmapped and remapped with MAP_FIXED. */
- caddr_t u_addr;
- DWORD u_len;
- long record_idx = -1;
- if ((record_idx = map_list->search_record ((caddr_t)addr, len,
- u_addr, u_len,
- record_idx)) >= 0)
- {
- rec = map_list->get_record (record_idx);
- if (u_addr > (caddr_t)addr || u_addr + len < (caddr_t)addr + len
- || !rec->compatible_flags (flags))
- {
- /* Partial match only, or access mode doesn't match. */
- /* FIXME: Handle partial mappings gracefully if adjacent
- memory is available. */
- set_errno (EINVAL);
- goto out;
- }
- if (!rec->map_pages ((caddr_t)addr, len))
- goto out;
- ret = (caddr_t)addr;
- goto out;
- }
+ caddr_t tried = map_list->try_map (addr, len, flags, off);
+ /* try_map returns NULL if no map matched, otherwise it returns
+ a valid address, of MAP_FAILED in case of a fatal error. */
+ if (tried)
+ {
+ ret = tried;
+ goto out;
}
}
@@ -1434,9 +1448,11 @@ fhandler_dev_zero::fixup_mmap_after_fork (HANDLE h, int prot, int flags,
void *base;
if (priv (flags))
{
- DWORD protect = gen_protect (prot, flags);
DWORD alloc_type = MEM_RESERVE | (noreserve (flags) ? 0 : MEM_COMMIT);
- base = VirtualAlloc (address, size, alloc_type, protect);
+ /* Always allocate R/W so that ReadProcessMemory doesn't fail
+ due to a non-writable target address. The protection is
+ set to the correct one anyway in the fixup loop. */
+ base = VirtualAlloc (address, size, alloc_type, PAGE_READWRITE);
}
else
base = mmap_func->MapView (h, address, size, prot, flags, offset);
@@ -1719,8 +1735,7 @@ fixup_mmaps_after_fork (HANDLE parent)
return -1;
}
}
- /* Set child page protection to parent protection if
- protection differs from original protection. */
+ /* Set child page protection to parent protection */
if (!VirtualProtect (address, mbi.RegionSize,
mbi.Protect, &old_prot))
{