Consolidate Linux mmap implementation (BZ#21270)

This patch consolidates all Linux mmap implementations on default
sysdeps/unix/sysv/linux/mmap{64}.c one.  To accomodate all required
architecture specific requeriments a new internal header is created
(mmap_internal.h) where each architecture add its specific code
requirements.  Currently only x86_64 (to define MMAP_PREPARE to add
MAP_32BITS), s390 (which have a different kernel ABI for mmap), m68k
(which have variable minimum page sizes), and MIPS n32 (which zero
extend the offset to handle negative one correctly) redefine the new
header.

The patch also fixes BZ#21270 where default mmap64 on architectures
which uses mmap2 silent truncates large offsets value (larger than
1 << (page shift + 8 * sizeof (off_t)) or 1<<44 on architectures with
4096 bytes page size).  The new consolidate implementation returns
EINVAL as allowed by POSIX.

It also adds a tests for on current tst-mmap-offset one.  I have run
a full make check on x86_64, x86_64-32, i686, aarch64, armhf, powerpc,
powerpc64le, sparc64, and sparcv9 without any regressions.  I also ran
some basic tests (tst-mmap-offset) on sh4, m68k, and on qemu simulated
MIPS32 and MIPS64.

	[BZ #21270]
	* posix/tst-mmap-offset.c (do_prepare): New function.
	(do_test): Rename to do_test_bz18877 and use FAIL_RET.
	(do_test_bz21270): New function.
	* sysdeps/unix/sysv/linux/aarch64/mmap.c: Remove file.
	* sysdeps/unix/sysv/linux/arm/mmap.c: Remove file.
	* sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/hppa/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/m68k/mmap.S: Likewise.
	* sysdeps/unix/sysv/linux/m68k/mmap64.c: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/mmap.S: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/mmap64.c: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/mmap.S: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/mmap64.S: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/mmap.S: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/mmap64.c: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/mmap_internal.h: New file.
	* sysdeps/unix/sysv/linux/m68k/mmap_internal.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/mmap_internal.h: Likewise.
	* sysdeps/unix/sysv/linux/s390/mmap_internal.h: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list: Remove mmap
	from auto-generation list.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/syscalls.list: Likewise.
	* sysdeps/unix/sysv/linux/mmap.c: New file.
	* sysdeps/unix/sysv/linux/mmap64.c (__mmap64): Add check for invalid
	offsets and support for mmap2 syscall.
This commit is contained in:
Adhemerval Zanella 2017-04-06 17:01:56 -03:00
parent 4fee33f8c1
commit 158d5fa0e1
25 changed files with 276 additions and 585 deletions

View File

@ -1,5 +1,39 @@
2017-04-11 Adhemerval Zanella <adhemerval.zanella@linaro.org>
[BZ #21270]
* posix/tst-mmap-offset.c (do_prepare): New function.
(do_test): Rename to do_test_bz18877 and use FAIL_RET.
(do_test_bz21270): New function.
* sysdeps/unix/sysv/linux/aarch64/mmap.c: Remove file.
* sysdeps/unix/sysv/linux/arm/mmap.c: Remove file.
* sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c: Likewise.
* sysdeps/unix/sysv/linux/hppa/mmap.c: Likewise.
* sysdeps/unix/sysv/linux/i386/mmap.c: Likewise.
* sysdeps/unix/sysv/linux/m68k/mmap.S: Likewise.
* sysdeps/unix/sysv/linux/m68k/mmap64.c: Likewise.
* sysdeps/unix/sysv/linux/microblaze/mmap.S: Likewise.
* sysdeps/unix/sysv/linux/mips/mips32/mmap.c: Likewise.
* sysdeps/unix/sysv/linux/mips/mips64/n32/mmap.c: Likewise.
* sysdeps/unix/sysv/linux/mips/mips64/n64/mmap64.c: Likewise.
* sysdeps/unix/sysv/linux/s390/s390-32/mmap.S: Likewise.
* sysdeps/unix/sysv/linux/s390/s390-32/mmap64.S: Likewise.
* sysdeps/unix/sysv/linux/s390/s390-64/mmap.S: Likewise.
* sysdeps/unix/sysv/linux/wordsize-64/mmap.c: Likewise.
* sysdeps/unix/sysv/linux/wordsize-64/mmap64.c: Likewise.
* sysdeps/unix/sysv/linux/x86_64/64/mmap.c: Likewise.
* sysdeps/unix/sysv/linux/mmap_internal.h: New file.
* sysdeps/unix/sysv/linux/m68k/mmap_internal.h: Likewise.
* sysdeps/unix/sysv/linux/mips/mips64/n32/mmap_internal.h: Likewise.
* sysdeps/unix/sysv/linux/s390/mmap_internal.h: Likewise.
* sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h: Likewise.
* sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list: Remove mmap
from auto-generation list.
* sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list: Likewise.
* sysdeps/unix/sysv/linux/wordsize-64/syscalls.list: Likewise.
* sysdeps/unix/sysv/linux/mmap.c: New file.
* sysdeps/unix/sysv/linux/mmap64.c (__mmap64): Add check for invalid
offsets and support for mmap2 syscall.
* posix/globtest.sh: Add cleanup routine on trap 0.
2017-04-11 Wainer dos Santos Moschetta <wainersm@linux.vnet.ibm.com>

View File

@ -1,4 +1,4 @@
/* BZ #18877 mmap offset test.
/* BZ #18877 and #21270 mmap offset test.
Copyright (C) 2015-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@ -21,18 +21,37 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
static int
printmsg (int rc, const char *msg)
#include <support/check.h>
static int fd;
static long int page_shift;
static char fname[] = "tst-mmap-offset-XXXXXX";
static void
do_prepare (int argc, char **argv)
{
printf ("%s failed: %m\n", msg);
return rc;
fd = mkstemp64 (fname);
if (fd < 0)
FAIL_EXIT1 ("mkstemp failed");
if (unlink (fname))
FAIL_EXIT1 ("unlink failed");
long sz = sysconf(_SC_PAGESIZE);
if (sz == -1)
sz = 4096L;
page_shift = ffs (sz) - 1;
}
#define PREPARE do_prepare
/* Check if negative offsets are handled correctly by mmap. */
static int
do_test (void)
do_test_bz18877 (void)
{
const int prot = PROT_READ | PROT_WRITE;
const int flags = MAP_SHARED;
@ -40,22 +59,13 @@ do_test (void)
const unsigned long offset = 0xace00000;
const unsigned long size = offset + length;
void *addr;
int fd;
char fname[] = "tst-mmap-offset-XXXXXX";
fd = mkstemp64 (fname);
if (fd < 0)
return printmsg (1, "mkstemp");
if (unlink (fname))
return printmsg (1, "unlink");
if (ftruncate64 (fd, size))
return printmsg (0, "ftruncate64");
FAIL_RET ("ftruncate64 failed");
addr = mmap (NULL, length, prot, flags, fd, offset);
if (MAP_FAILED == addr)
return printmsg (1, "mmap");
FAIL_RET ("mmap failed");
/* This memcpy is likely to SIGBUS if mmap has messed up with offset. */
memcpy (addr, fname, sizeof (fname));
@ -63,5 +73,45 @@ do_test (void)
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
/* Check if invalid offset are handled correctly by mmap. */
static int
do_test_bz21270 (void)
{
/* For architectures with sizeof (off_t) < sizeof (off64_t) mmap is
implemented with __SYS_mmap2 syscall and the offset is represented in
multiples of page size. For offset larger than
'1 << (page_shift + 8 * sizeof (off_t))' (that is, 1<<44 on system with
page size of 4096 bytes) the system call silently truncates the offset.
For this case glibc mmap implementation returns EINVAL. */
const int prot = PROT_READ | PROT_WRITE;
const int flags = MAP_SHARED;
const int64_t offset = 1ULL << (page_shift + 8 * sizeof (uint32_t));
const size_t length = 4096;
void *addr = mmap64 (NULL, length, prot, flags, fd, offset);
if (sizeof (off_t) < sizeof (off64_t))
{
if ((addr != MAP_FAILED) && (errno != EINVAL))
FAIL_RET ("mmap succeed");
}
else
{
if (addr == MAP_FAILED)
FAIL_RET ("mmap failed");
}
return 0;
}
int
do_test (void)
{
int ret = 0;
ret += do_test_bz18877 ();
ret += do_test_bz21270 ();
return ret;
}
#include <support/test-driver.c>

View File

@ -1,34 +0,0 @@
/* Copyright (C) 2009-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <sys/syscall.h>
#include <sysdep.h>
#include <unistd.h>
__ptr_t
__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
{
return (__ptr_t) INLINE_SYSCALL (mmap, 6, addr, len, prot, flags, fd, offset);
}
weak_alias (__mmap, mmap)
weak_alias (__mmap, mmap64)
weak_alias (__mmap, __mmap64)

View File

@ -1,40 +0,0 @@
/* Copyright (C) 2011-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <sysdep.h>
#ifndef MMAP_PAGE_UNIT
# define MMAP_PAGE_UNIT 4096UL
#endif
__ptr_t
__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
{
if (offset & (MMAP_PAGE_UNIT - 1))
{
__set_errno (EINVAL);
return MAP_FAILED;
}
return (__ptr_t) INLINE_SYSCALL (mmap2, 6, addr, len, prot, flags, fd,
offset / MMAP_PAGE_UNIT);
}
weak_alias (__mmap, mmap)

View File

@ -1,49 +0,0 @@
/* Copyright (C) 1994-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
/* Map addresses starting near ADDR and extending for LEN bytes. From
OFFSET into the file FD describes according to PROT and FLAGS. If ADDR
is nonzero, it is the desired mapping address. If the MAP_FIXED bit is
set in FLAGS, the mapping will be at ADDR exactly (which must be
page-aligned); otherwise the system chooses a convenient nearby address.
The return value is the actual mapping address chosen or MAP_FAILED
for errors (in which case `errno' is set). A successful `mmap' call
deallocates any previous mapping for the affected region. */
#include <sysdep.h>
__ptr_t
__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
{
__ptr_t ret;
ret = (__ptr_t) INLINE_SYSCALL (mmap, 6, addr, len, prot, flags, fd, offset);
/* check if it's really a negative number */
if(((unsigned long)ret & 0xfffff000) == 0xfffff000)
return MAP_FAILED;
return ret;
}
weak_alias (__mmap, mmap)

View File

@ -1,42 +0,0 @@
/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#include <sysdep.h>
.text
ENTRY (__mmap)
move.l #SYS_ify (mmap), %d0 /* System call number in %d0. */
lea 4(%sp), %a0 /* Address of args is 1st arg. */
move.l %a0, %d1
/* Do the system call trap. */
trap #0
/* Kludge: negative numbers are among the legal return values.
If %d0 is between -4096 and 0 then there was an error. */
cmp.l #-4096, %d0
jhi SYSCALL_ERROR_LABEL
/* Successful; return the syscall's value. Copy it to %a0 because
mmap is declared to return a pointer. */
move.l %d0, %a0
rts
PSEUDO_END (__mmap)
weak_alias (__mmap, mmap)

View File

@ -1,5 +0,0 @@
/* ColdFire and Sun 3 kernels have PAGE_SHIFT set to 13 and expect
mmap2 offset to be provided in 8K pages. Determine the shift
dynamically with getpagesize. */
#define MMAP2_PAGE_SHIFT -1
#include <sysdeps/unix/sysv/linux/mmap64.c>

View File

@ -1,4 +1,5 @@
/* Copyright (C) 2015-2017 Free Software Foundation, Inc.
/* Common mmap definition for Linux implementation. Linux/m68k version.
Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -15,4 +16,14 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c>
#ifndef MMAP_M68K_INTERNAL_LINUX_H
#define MMAP_M68K_INTERNAL_LINUX_H
/* ColdFire and Sun 3 kernels have PAGE_SHIFT set to 13 and expect
mmap2 offset to be provided in 8K pages. Determine the shift
dynamically with getpagesize. */
#define MMAP2_PAGE_SHIFT -1
#include_next <mmap_internal.h>
#endif

View File

@ -1,50 +0,0 @@
/* Copyright (C) 2009-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <sysdep.h>
#define EINVAL 22
.text
ENTRY (__mmap)
addik r3,r0,-EINVAL
andi r4,r10,0xfff
bnei r4,L(skip)
addik r12,r0,SYS_ify(mmap2)
sra r10,r10
sra r10,r10
sra r10,r10
sra r10,r10
sra r10,r10
sra r10,r10
sra r10,r10
sra r10,r10
sra r10,r10
sra r10,r10
sra r10,r10
sra r10,r10 ; /* mmap2 takes the offset in pages. */
brki r14,8
nop
L(skip):
addik r4,r0,-4095
cmpu r4,r4,r3
bgei r4,SYSCALL_ERROR_LABEL
rtsd r15,8
nop
PSEUDO_END (__mmap)
weak_alias (__mmap, mmap)

View File

@ -1 +0,0 @@
#include <sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c>

View File

@ -1,4 +1,4 @@
/* mmap for MIPS n32.
/* Common mmap definition for Linux implementation. MIPS n32 version.
Copyright (C) 2016-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@ -16,20 +16,13 @@
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdint.h>
#include <sysdep.h>
#ifndef MMAP_MIPS_N32_INTERNAL_H
#define MMAP_MIPS_N32_INTERNAL_H
__ptr_t
__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
{
/* To handle negative offsets consistently with other architectures,
the offset must be zero-extended to 64-bit. */
uint64_t offset_adj = (uint64_t) (uint32_t) offset;
return (__ptr_t) INLINE_SYSCALL (mmap, 6, addr, len, prot, flags, fd,
offset_adj);
}
/* To handle negative offsets consistently with other architectures,
the offset must be zero-extended to 64-bit. */
#define MMAP_ADJUST_OFFSET(offset) (uint64_t) (uint32_t) offset
weak_alias (__mmap, mmap)
#include_next <mmap_internal.h>
#endif

View File

@ -4,8 +4,6 @@
# return value.
lseek64 - lseek i:iii __lseek64 __libc_lseek64 lseek64 llseek
mmap64 - mmap b:aniiii __mmap64 mmap64
readahead - readahead i:iii __readahead readahead
prlimit64 EXTRA prlimit64 i:iipp prlimit64

View File

@ -1 +0,0 @@
/* mmap64 is the same as mmap. */

View File

@ -1,7 +1,5 @@
# File name Caller Syscall name # args Strong name Weak names
mmap - mmap b:aniiii __mmap mmap __mmap64 mmap64
readahead - readahead i:iii __readahead readahead
prlimit EXTRA prlimit64 i:iipp prlimit prlimit64

View File

@ -0,0 +1,51 @@
/* mmap - map files or devices into memory. Linux version.
Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sysdep.h>
#include <stdint.h>
#include <mmap_internal.h>
#ifndef __OFF_T_MATCHES_OFF64_T
/* An architecture may override this. */
# ifndef MMAP_ADJUST_OFFSET
# define MMAP_ADJUST_OFFSET(offset) offset
# endif
void *
__mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
{
MMAP_CHECK_PAGE_UNIT ();
if (offset & MMAP_OFF_LOW_MASK)
return (__ptr_t) INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
#ifdef __NR_mmap2
return (void *) MMAP_CALL (mmap2, addr, len, prot, flags, fd,
offset / (uint32_t) MMAP2_PAGE_UNIT);
#else
return (void *) MMAP_CALL (mmap, addr, len, prot, flags, fd,
MMAP_ADJUST_OFFSET (offset));
#endif
}
weak_alias (__mmap, mmap)
#endif /* __OFF_T_MATCHES_OFF64_T */

View File

@ -1,4 +1,5 @@
/* Copyright (C) 1999-2017 Free Software Foundation, Inc.
/* mmap - map files or devices into memory. Linux version.
Copyright (C) 1999-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 1999.
@ -19,39 +20,41 @@
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <sysdep.h>
#include <sys/syscall.h>
#include <mmap_internal.h>
/* This is always 12, even on architectures where PAGE_SHIFT != 12. */
#ifndef MMAP2_PAGE_SHIFT
# define MMAP2_PAGE_SHIFT 12
#endif
#if MMAP2_PAGE_SHIFT == -1
static int page_shift;
#else
#define page_shift MMAP2_PAGE_SHIFT
#endif
/* To avoid silent truncation of offset when using mmap2, do not accept
offset larger than 1 << (page_shift + off_t bits). For archictures with
32 bits off_t and page size of 4096 it would be 1^44. */
#define MMAP_OFF_HIGH_MASK \
((-(MMAP2_PAGE_UNIT << 1) << (8 * sizeof (off_t) - 1)))
#define MMAP_OFF_MASK (MMAP_OFF_HIGH_MASK | MMAP_OFF_LOW_MASK)
/* An architecture may override this. */
#ifndef MMAP_PREPARE
# define MMAP_PREPARE(addr, len, prot, flags, fd, offset)
#endif
void *
__mmap64 (void *addr, size_t len, int prot, int flags, int fd, off64_t offset)
{
#if MMAP2_PAGE_SHIFT == -1
if (page_shift == 0)
{
int page_size = __getpagesize ();
page_shift = __ffs (page_size) - 1;
}
#endif
if (offset & ((1 << page_shift) - 1))
MMAP_CHECK_PAGE_UNIT ();
if (offset & MMAP_OFF_MASK)
return (void *) INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
void *result;
result = (void *)
INLINE_SYSCALL (mmap2, 6, addr,
len, prot, flags, fd,
(off_t) (offset >> page_shift));
return result;
MMAP_PREPARE (addr, len, prot, flags, fd, offset);
#ifdef __NR_mmap2
return (void *) MMAP_CALL (mmap2, addr, len, prot, flags, fd,
(off_t) (offset / MMAP2_PAGE_UNIT));
#else
return (void *) MMAP_CALL (mmap, addr, len, prot, flags, fd, offset);
#endif
}
weak_alias (__mmap64, mmap64)
#ifdef __OFF_T_MATCHES_OFF64_T
weak_alias (__mmap64, mmap)
weak_alias (__mmap64, __mmap)
#endif

View File

@ -0,0 +1,49 @@
/* Common mmap definition for Linux implementation.
Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef MMAP_INTERNAL_LINUX_H
#define MMAP_INTERNAL_LINUX_H 1
/* This is the minimum mmap2 unit size accept by the kernel. An architecture
with multiple minimum page sizes (such as m68k) might define it as -1 and
thus it will queried at runtime. */
#ifndef MMAP2_PAGE_UNIT
# define MMAP2_PAGE_UNIT 4096ULL
#endif
#if MMAP2_PAGE_UNIT == -1
static int page_unit;
# define MMAP_CHECK_PAGE_UNIT() \
if (page_unit == 0) \
page_unit = __getpagesize ();
#else
# define page_unit MMAP2_PAGE_UNIT
# define MMAP_CHECK_PAGE_UNIT()
#endif
/* Do not accept offset not multiple of page size. */
#define MMAP_OFF_LOW_MASK (MMAP2_PAGE_UNIT - 1)
/* An architecture may override this. */
#ifndef MMAP_CALL
# define MMAP_CALL(__nr, __addr, __len, __prot, __flags, __fd, __offset) \
INLINE_SYSCALL_CALL (__nr, __addr, __len, __prot, __flags, __fd, __offset)
#endif
#endif /* MMAP_INTERNAL_LINUX_H */

View File

@ -1,4 +1,5 @@
/* Copyright (C) 2015-2017 Free Software Foundation, Inc.
/* mmap - map files or devices into memory. Linux/s390 version.
Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -15,22 +16,17 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <sysdep.h>
#ifndef MMAP_S390_INTERNAL_H
# define MMAP_S390_INTERNAL_H
#define MMAP_CALL(__nr, __addr, __len, __prot, __flags, __fd, __offset) \
({ \
long int __args[6] = { (long int) (__addr), (long int) (__len), \
(long int) (__prot), (long int) (__flags), \
(long int) (__fd), (long int) (__offset) }; \
INLINE_SYSCALL_CALL (__nr, __args); \
})
#include_next <mmap_internal.h>
#ifndef MMAP_PAGE_UNIT
# define MMAP_PAGE_UNIT 4096UL
#endif
__ptr_t
__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
{
if (offset & (MMAP_PAGE_UNIT - 1))
return (__ptr_t) INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
return (__ptr_t) INLINE_SYSCALL (mmap2, 6, addr, len, prot, flags, fd,
offset / MMAP_PAGE_UNIT);
}
weak_alias (__mmap, mmap)

View File

@ -1,74 +0,0 @@
/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <sysdep.h>
#define EINVAL 22
.text
ENTRY(__mmap)
/* Save registers and setup stack frame. */
stm %r6,%r15,24(%r15)
cfi_offset (%r15, -36)
cfi_offset (%r14, -40)
cfi_offset (%r13, -44)
cfi_offset (%r12, -48)
cfi_offset (%r11, -52)
cfi_offset (%r10, -56)
cfi_offset (%r9, -60)
cfi_offset (%r8, -64)
cfi_offset (%r7, -68)
cfi_offset (%r6, -72)
lr %r1,%r15
ahi %r15,-120 /* buy stack space */
cfi_adjust_cfa_offset (120)
st %r1,0(%r15) /* store back chain */
/* Store parameters on stack, because mmap2
* takes only one parameter: a pointer to the parameter area
*/
st %r6,0x70(%r15) /* Store 'fd'. */
st %r5,0x6C(%r15) /* Store 'flags'. */
st %r4,0x68(%r15) /* Store 'prot'. */
st %r3,0x64(%r15) /* Store 'length'. */
st %r2,0x60(%r15) /* Store 'start'. */
l %r1,216(%r15) /* Load offset. */
tml %r1,0x0fff /* Offset page aligned ? */
lhi %r2,-EINVAL
jnz 1f /* No -> EINVAL. */
srl %r1,12 /* mmap2 takes the offset in pages. */
st %r1,0x74(%r15) /* Store page offset. */
la %r2,0x60(%r15) /* Load address of parameter list. */
svc SYS_ify(mmap2) /* Do the system call trap. */
1: l %r15,0(%r15) /* Load back chain. */
cfi_adjust_cfa_offset (-120)
lm %r6,%r15,24(%r15) /* Load registers. */
/* check gpr 2 for error */
lhi %r0,-4096
clr %r2,%r0
jnl SYSCALL_ERROR_LABEL
/* Successful; return the syscall's value. */
br %r14
PSEUDO_END (__mmap)
weak_alias (__mmap, mmap)

View File

@ -1,81 +0,0 @@
/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <sysdep.h>
#define EINVAL 22
#define ENOSYS 38
.text
ENTRY(__mmap64)
/* Save registers and setup stack frame. */
stm %r6,%r15,24(%r15)
cfi_offset (%r15, -36)
cfi_offset (%r14, -40)
cfi_offset (%r13, -44)
cfi_offset (%r12, -48)
cfi_offset (%r11, -52)
cfi_offset (%r10, -56)
cfi_offset (%r9, -60)
cfi_offset (%r8, -64)
cfi_offset (%r7, -68)
cfi_offset (%r6, -72)
lr %r1,%r15
ahi %r15,-120 /* Buy stack space. */
cfi_adjust_cfa_offset (120)
st %r1,0(%r15) /* Store back chain. */
/* Store parameters on stack, because mmap2
* takes only one parameter: a pointer to the parameter area. */
st %r6,0x70(%r15) /* Store 'fd'. */
st %r5,0x6C(%r15) /* Store 'flags'. */
st %r4,0x68(%r15) /* Store 'prot'. */
st %r3,0x64(%r15) /* Store 'length'. */
st %r2,0x60(%r15) /* Store 'start'. */
lm %r0,%r1,216(%r15) /* Load 64 bit offset. */
tml %r1,0x0fff /* Offset page aligned ? */
jnz 2f /* No -> EINVAL. */
srdl %r0,12 /* mmap2 takes the offset in pages. */
ltr %r0,%r0 /* Offset > 2^44 ? */
jnz 2f
st %r1,0x74(%r15) /* Store page offset. */
la %r2,0x60(%r15) /* Load address of parameter list. */
svc SYS_ify(mmap2) /* Do the system call trap. */
l %r15,0(%r15) /* Load back chain. */
cfi_adjust_cfa_offset (-120)
lm %r6,%r15,24(%r15) /* Load registers. */
/* Check gpr 2 for error. */
lhi %r0,-4096
clr %r2,%r0
jnl SYSCALL_ERROR_LABEL
/* Successful; return the syscall's value. */
br %r14
2: lhi %r2,-EINVAL
l %r15,0(%r15) /* Load back chain. */
lm %r6,%r15,24(%r15) /* Load registers. */
j SYSCALL_ERROR_LABEL
PSEUDO_END (__mmap64)
weak_alias (__mmap64, mmap64)

View File

@ -1,78 +0,0 @@
/* Wrapper around mmap system call. 64 bit S/390 version.
Copyright (C) 2001-2017 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <sysdep.h>
#define EINVAL 22
.text
ENTRY(__mmap)
/* Save registers and setup stack frame. */
stmg %r6,%r15,48(%r15)
cfi_offset (%r15,-40)
cfi_offset (%r14,-48)
cfi_offset (%r13,-56)
cfi_offset (%r12,-64)
cfi_offset (%r11,-72)
cfi_offset (%r10,-80)
cfi_offset (%r9,-88)
cfi_offset (%r8,-96)
cfi_offset (%r7,-104)
cfi_offset (%r6,-112)
lgr %r1,%r15
lg %r0,8(%r15) /* Load eos. */
aghi %r15,-208 /* Buy stack space. */
cfi_adjust_cfa_offset (208)
stg %r1,0(%r15) /* Store back chain. */
stg %r0,8(%r15) /* Store eos. */
/* Store parameters on stack, because old_mmap
takes only one parameter: a pointer to the parameter area. */
mvc 200(8,%r15),368(%r15) /* Move 'offset'. */
lgfr %r6,%r6
stg %r6,192(%r15) /* Store 'fd'. */
lgfr %r5,%r5
stg %r5,184(%r15) /* Store 'flags'. */
lgfr %r4,%r4
stg %r4,176(%r15) /* Store 'prot'. */
stg %r3,168(%r15) /* Store 'length'. */
stg %r2,160(%r15) /* Store 'start'. */
la %r2,160(%r15) /* Load address of parameter list. */
/* Do the system call trap. */
svc SYS_ify(mmap)
lg %r15,0(%r15) /* Load back chain. */
cfi_adjust_cfa_offset (-208)
lmg %r6,%r15,48(%r15) /* Load registers. */
/* Check gpr 2 for error. */
lghi %r0,-4096
clgr %r2,%r0
jgnl SYSCALL_ERROR_LABEL
/* Successful; return the syscall's value. */
br %r14
PSEUDO_END (__mmap)
weak_alias (__mmap, mmap)
weak_alias (__mmap, mmap64)
weak_alias (__mmap, __mmap64)

View File

@ -1,40 +0,0 @@
/* Linux mmap system call. 64-bit version.
Copyright (C) 2015-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <sysdep.h>
/* An architecture may override this. */
#ifndef MMAP_PREPARE
# define MMAP_PREPARE(addr, len, prot, flags, fd, offset)
#endif
__ptr_t
__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
{
MMAP_PREPARE (addr, len, prot, flags, fd, offset);
return (__ptr_t) INLINE_SYSCALL (mmap, 6, addr, len, prot, flags,
fd, offset);
}
weak_alias (__mmap, mmap)
weak_alias (__mmap, mmap64)
weak_alias (__mmap, __mmap64)

View File

@ -1 +0,0 @@
/* mmap64 is the same as mmap. */

View File

@ -2,7 +2,6 @@
fstatfs - fstatfs i:ip __fstatfs fstatfs fstatfs64 __fstatfs64
statfs - statfs i:sp __statfs statfs statfs64
mmap - mmap b:aniiii __mmap mmap __mmap64 mmap64
readahead - readahead i:iii __readahead readahead
sendfile - sendfile i:iipi sendfile sendfile64
sync_file_range - sync_file_range Ci:iiii sync_file_range

View File

@ -17,6 +17,9 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef MMAP_X86_64_INTERNAL_H
#define MMAP_X86_64_INTERNAL_H
#include <ldsodefs.h>
/* If the Prefer_MAP_32BIT_EXEC bit is set, try to map executable pages
@ -26,7 +29,7 @@
&& ((prot) & PROT_EXEC) != 0 \
&& HAS_ARCH_FEATURE (Prefer_MAP_32BIT_EXEC)) \
{ \
__ptr_t ret = (__ptr_t) INLINE_SYSCALL (mmap, 6, (addr), (len), \
void *ret = (void*) INLINE_SYSCALL_CALL (mmap, (addr), (len), \
(prot), \
(flags) | MAP_32BIT, \
(fd), (offset)); \
@ -34,4 +37,6 @@
return ret; \
}
#include <sysdeps/unix/sysv/linux/wordsize-64/mmap.c>
#include_next <mmap_internal.h>
#endif