-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.
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 ()
/* 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;
}
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;
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");
}
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)
{
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);
/* 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. */