* mmap.cc (list::match): Add parameters to return valid address and
length back to munmap(). Evaluate intersection between given area and mapped area and return it, if any. (mmap64): On regular files, don't allow mappings beginning beyond EOF. Return with errno set to ENXIO instead. (munmap): Rewrite SUSv3 conformant. Check if given memory area is valid. Unmap all maps inside given memory area. Don't return error if no mapping has been unmapped.
This commit is contained in:
parent
4b2cbaeefd
commit
f2d3c47b14
@ -1,4 +1,15 @@
|
||||
2003-07-04 N Stephens <nigel@mips.com>
|
||||
2003-07-05 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* mmap.cc (list::match): Add parameters to return valid address and
|
||||
length back to munmap(). Evaluate intersection between given
|
||||
area and mapped area and return it, if any.
|
||||
(mmap64): On regular files, don't allow mappings beginning beyond
|
||||
EOF. Return with errno set to ENXIO instead.
|
||||
(munmap): Rewrite SUSv3 conformant. Check if given memory area is
|
||||
valid. Unmap all maps inside given memory area. Don't return error
|
||||
if no mapping has been unmapped.
|
||||
|
||||
2003-07-05 N Stephens <nigel@mips.com>
|
||||
|
||||
* fhandler.h (fhandler_socket::get_connect_state): New method to
|
||||
return socket connection state.
|
||||
|
@ -270,7 +270,8 @@ public:
|
||||
void erase (int i);
|
||||
void erase ();
|
||||
mmap_record *match (_off64_t off, DWORD len);
|
||||
long match (caddr_t addr, DWORD len, long start);
|
||||
long match (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len,
|
||||
long start);
|
||||
};
|
||||
|
||||
list::list ()
|
||||
@ -323,13 +324,24 @@ list::match (_off64_t off, DWORD len)
|
||||
|
||||
/* Used in munmap() */
|
||||
long
|
||||
list::match (caddr_t addr, DWORD len, _off_t start)
|
||||
list::match (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len,
|
||||
_off_t start)
|
||||
{
|
||||
caddr_t low, high;
|
||||
|
||||
for (int i = start + 1; i < nrecs; ++i)
|
||||
if (addr >= recs[i].get_address ()
|
||||
&& addr + len <= recs[i].get_address ()
|
||||
+ (PAGE_CNT (recs[i].get_size ()) * getpagesize ()))
|
||||
return i;
|
||||
{
|
||||
low = (addr >= recs[i].get_address ()) ? addr : recs[i].get_address ();
|
||||
high = recs[i].get_address ()
|
||||
+ (PAGE_CNT (recs[i].get_size ()) * getpagesize ());
|
||||
high = (addr + len < high) ? addr + len : high;
|
||||
if (low < high)
|
||||
{
|
||||
m_addr = low;
|
||||
m_len = high - low;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -486,6 +498,16 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
|
||||
DWORD high;
|
||||
DWORD low = GetFileSize (fh->get_handle (), &high);
|
||||
_off64_t fsiz = ((_off64_t)high << 32) + low;
|
||||
/* Don't allow mappings beginning beyond EOF since Windows can't
|
||||
handle that POSIX like. FIXME: Still looking for a good idea
|
||||
to allow that nevertheless. */
|
||||
if (gran_off >= fsiz)
|
||||
{
|
||||
set_errno (ENXIO);
|
||||
ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK,
|
||||
"mmap");
|
||||
return MAP_FAILED;
|
||||
}
|
||||
fsiz -= gran_off;
|
||||
if (gran_len > fsiz)
|
||||
gran_len = fsiz;
|
||||
@ -591,16 +613,16 @@ mmap (caddr_t addr, size_t len, int prot, int flags, int fd, _off_t off)
|
||||
return mmap64 (addr, len, prot, flags, fd, (_off64_t)off);
|
||||
}
|
||||
|
||||
/* munmap () removes an mmapped area. It insists that base area
|
||||
requested is the same as that mmapped, error if not. */
|
||||
/* munmap () removes all mmapped pages between addr and addr+len. */
|
||||
|
||||
extern "C" int
|
||||
munmap (caddr_t addr, size_t len)
|
||||
{
|
||||
syscall_printf ("munmap (addr %x, len %d)", addr, len);
|
||||
|
||||
/* Error conditions according to SUSv2 */
|
||||
if (((DWORD)addr % getpagesize ()) || !len)
|
||||
/* Error conditions according to SUSv3 */
|
||||
if (!addr || ((DWORD)addr % getpagesize ()) || !len
|
||||
|| IsBadReadPtr (addr, len))
|
||||
{
|
||||
set_errno (EINVAL);
|
||||
syscall_printf ("-1 = munmap(): Invalid parameters");
|
||||
@ -608,17 +630,15 @@ munmap (caddr_t addr, size_t len)
|
||||
}
|
||||
|
||||
SetResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
|
||||
/* Check if a mmap'ed area was ever created */
|
||||
if (mmapped_areas == NULL)
|
||||
{
|
||||
syscall_printf ("-1 = munmap(): mmapped_areas == NULL");
|
||||
set_errno (EINVAL);
|
||||
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Iterate through the map, looking for the mmapped area.
|
||||
Error if not found. */
|
||||
/* Iterate through the map, unmap pages between addr and addr+len
|
||||
in all maps. */
|
||||
|
||||
for (int it = 0; it < mmapped_areas->nlists; ++it)
|
||||
{
|
||||
@ -626,10 +646,13 @@ munmap (caddr_t addr, size_t len)
|
||||
if (map_list)
|
||||
{
|
||||
long li = -1;
|
||||
if ((li = map_list->match(addr, len, li)) >= 0)
|
||||
caddr_t u_addr;
|
||||
DWORD u_len;
|
||||
|
||||
while ((li = map_list->match(addr, len, u_addr, u_len, li)) >= 0)
|
||||
{
|
||||
mmap_record *rec = map_list->recs + li;
|
||||
if (rec->unmap_map (addr, len))
|
||||
if (rec->unmap_map (u_addr, u_len))
|
||||
{
|
||||
fhandler_base *fh = rec->alloc_fh ();
|
||||
fh->munmap (rec->get_handle (), addr, len);
|
||||
@ -638,18 +661,13 @@ munmap (caddr_t addr, size_t len)
|
||||
/* Delete the entry. */
|
||||
map_list->erase (li);
|
||||
}
|
||||
syscall_printf ("0 = munmap(): %x", addr);
|
||||
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_errno (EINVAL);
|
||||
syscall_printf ("-1 = munmap(): EINVAL");
|
||||
|
||||
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
|
||||
return -1;
|
||||
syscall_printf ("0 = munmap(): %x", addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sync file with memory. Ignore flags for now. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user