* 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.
This commit is contained in:
parent
e4809ddd20
commit
b0c3293ecc
@ -1,3 +1,12 @@
|
||||
2005-11-30 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* 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.
|
||||
|
||||
2005-11-29 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* include/cygwin/version.h: Bump API minor version.
|
||||
|
@ -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))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user