syscall_emul: extend mmap system call to support file backed mmaps

For O3, which has a stat that counts reg reads, there is an additional
reg read per mmap() call since there's an arg we no longer ignore.
Otherwise, stats should not be affected.
This commit is contained in:
Brandon Potter 2016-03-17 10:24:17 -07:00
parent 3fa311e5ac
commit a04fac976f
19 changed files with 595 additions and 95 deletions

View file

@ -28,10 +28,11 @@
* Authors: Korey Sewell
*/
#include <fcntl.h>
#include "arch/alpha/linux/linux.hh"
#include <fcntl.h>
#include <sys/mman.h>
// open(2) flags translation table
SyscallFlagTransTable AlphaLinux::openFlagTable[] = {
#ifdef _MSC_VER
@ -99,3 +100,28 @@ SyscallFlagTransTable AlphaLinux::openFlagTable[] = {
const int AlphaLinux::NUM_OPEN_FLAGS =
(sizeof(AlphaLinux::openFlagTable)/sizeof(AlphaLinux::openFlagTable[0]));
// mmap(2) flags translation table
SyscallFlagTransTable AlphaLinux::mmapFlagTable[] = {
{ AlphaLinux::TGT_MAP_SHARED, MAP_SHARED },
{ AlphaLinux::TGT_MAP_PRIVATE, MAP_PRIVATE },
{ AlphaLinux::TGT_MAP_ANON, MAP_ANON },
{ AlphaLinux::TGT_MAP_DENYWRITE, MAP_DENYWRITE },
{ AlphaLinux::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
{ AlphaLinux::TGT_MAP_FILE, MAP_FILE },
{ AlphaLinux::TGT_MAP_GROWSDOWN, MAP_GROWSDOWN },
{ AlphaLinux::TGT_MAP_HUGETLB, MAP_HUGETLB },
{ AlphaLinux::TGT_MAP_LOCKED, MAP_LOCKED },
{ AlphaLinux::TGT_MAP_NONBLOCK, MAP_NONBLOCK },
{ AlphaLinux::TGT_MAP_NORESERVE, MAP_NORESERVE },
{ AlphaLinux::TGT_MAP_POPULATE, MAP_POPULATE },
#ifdef MAP_STACK
{ AlphaLinux::TGT_MAP_STACK, MAP_STACK },
#endif
{ AlphaLinux::TGT_MAP_ANONYMOUS, MAP_ANONYMOUS },
{ AlphaLinux::TGT_MAP_FIXED, MAP_FIXED },
};
const unsigned AlphaLinux::NUM_MMAP_FLAGS =
sizeof(AlphaLinux::mmapFlagTable) /
sizeof(AlphaLinux::mmapFlagTable[0]);

View file

@ -104,8 +104,25 @@ class AlphaLinux : public Linux
//@}
/// For mmap().
static const unsigned TGT_MAP_ANONYMOUS = 0x10;
static const unsigned TGT_MAP_FIXED = 0x100;
static SyscallFlagTransTable mmapFlagTable[];
static const unsigned TGT_MAP_SHARED = 0x000001;
static const unsigned TGT_MAP_PRIVATE = 0x000002;
static const unsigned TGT_MAP_ANON = 0x000010;
static const unsigned TGT_MAP_DENYWRITE = 0x002000;
static const unsigned TGT_MAP_EXECUTABLE = 0x004000;
static const unsigned TGT_MAP_FILE = 0x000000;
static const unsigned TGT_MAP_GROWSDOWN = 0x001000;
static const unsigned TGT_MAP_HUGETLB = 0x100000;
static const unsigned TGT_MAP_LOCKED = 0x008000;
static const unsigned TGT_MAP_NONBLOCK = 0x040000;
static const unsigned TGT_MAP_NORESERVE = 0x010000;
static const unsigned TGT_MAP_POPULATE = 0x020000;
static const unsigned TGT_MAP_STACK = 0x080000;
static const unsigned TGT_MAP_ANONYMOUS = 0x000010;
static const unsigned TGT_MAP_FIXED = 0x000100;
static const unsigned NUM_MMAP_FLAGS;
//@{
/// For getsysinfo().

View file

@ -68,5 +68,27 @@ SyscallFlagTransTable AlphaTru64::openFlagTable[] = {
const int AlphaTru64::NUM_OPEN_FLAGS =
(sizeof(AlphaTru64::openFlagTable)/sizeof(AlphaTru64::openFlagTable[0]));
// mmap(2) flags translation table
SyscallFlagTransTable AlphaTru64::mmapFlagTable[] = {
{ TGT_MAP_SHARED, MAP_SHARED },
{ TGT_MAP_PRIVATE, MAP_PRIVATE },
{ TGT_MAP_32BIT, MAP_32BIT},
{ TGT_MAP_ANON, MAP_ANON },
{ TGT_MAP_DENYWRITE, MAP_DENYWRITE },
{ TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
{ TGT_MAP_FILE, MAP_FILE },
{ TGT_MAP_GROWSDOWN, MAP_GROWSDOWN },
{ TGT_MAP_HUGETLB, MAP_HUGETLB },
{ TGT_MAP_LOCKED, MAP_LOCKED },
{ TGT_MAP_NONBLOCK, MAP_NONBLOCK },
{ TGT_MAP_NORESERVE, MAP_NORESERVE },
{ TGT_MAP_POPULATE, MAP_POPULATE },
{ TGT_MAP_STACK, MAP_STACK },
{ TGT_MAP_ANONYMOUS, MAP_ANONYMOUS },
{ TGT_MAP_FIXED, MAP_FIXED },
};
const unsigned AlphaTru64::NUM_MMAP_FLAGS =
sizeof(AlphaTru64::mmapFlagTable) /
sizeof(AlphaTru64::mmapFlagTable[0]);

View file

@ -63,8 +63,28 @@ class AlphaTru64 : public Tru64
//@}
/// For mmap().
static const unsigned TGT_MAP_ANONYMOUS = 0x10;
static const unsigned TGT_MAP_FIXED = 0x100;
static SyscallFlagTransTable mmapFlagTable[];
static const unsigned TGT_MAP_SHARED = 0x00001;
static const unsigned TGT_MAP_PRIVATE = 0x00002;
static const unsigned TGT_MAP_32BIT = 0x00040;
static const unsigned TGT_MAP_ANON = 0x00020;
static const unsigned TGT_MAP_DENYWRITE = 0x00800;
static const unsigned TGT_MAP_EXECUTABLE = 0x01000;
static const unsigned TGT_MAP_FILE = 0x00000;
static const unsigned TGT_MAP_GROWSDOWN = 0x00100;
static const unsigned TGT_MAP_HUGETLB = 0x40000;
static const unsigned TGT_MAP_LOCKED = 0x02000;
static const unsigned TGT_MAP_NONBLOCK = 0x10000;
static const unsigned TGT_MAP_NORESERVE = 0x04000;
static const unsigned TGT_MAP_POPULATE = 0x08000;
static const unsigned TGT_MAP_STACK = 0x20000;
static const unsigned TGT_MAP_ANONYMOUS = 0x00020;
static const unsigned TGT_MAP_FIXED = 0x00010;
static const unsigned NUM_MMAP_FLAGS;
//@{
//@{
/// For getsysinfo().

View file

@ -74,6 +74,8 @@ class ArmFreebsd32 : public FreeBSD
//@}
/// For mmap().
static const unsigned TGT_MAP_SHARED = 0x0001;
static const unsigned TGT_MAP_PRIVATE = 0x0002;
static const unsigned TGT_MAP_ANONYMOUS = 0x1000;
static const unsigned TGT_MAP_FIXED = 0x0010;
@ -229,6 +231,8 @@ class ArmFreebsd64 : public FreeBSD
//@}
/// For mmap().
static const unsigned TGT_MAP_SHARED = 0x0001;
static const unsigned TGT_MAP_PRIVATE = 0x0002;
static const unsigned TGT_MAP_ANONYMOUS = 0x1000;
static const unsigned TGT_MAP_FIXED = 0x0010;

View file

@ -41,10 +41,11 @@
* Authors: Stephen Hines
*/
#include <fcntl.h>
#include "arch/arm/linux/linux.hh"
#include <fcntl.h>
#include <sys/mman.h>
// open(2) flags translation table
SyscallFlagTransTable ArmLinux32::openFlagTable[] = {
#ifdef _MSC_VER
@ -121,6 +122,31 @@ SyscallFlagTransTable ArmLinux32::openFlagTable[] = {
const int ArmLinux32::NUM_OPEN_FLAGS = sizeof(ArmLinux32::openFlagTable) /
sizeof(ArmLinux32::openFlagTable[0]);
// mmap(2) flags translation table
SyscallFlagTransTable ArmLinux32::mmapFlagTable[] = {
{ ArmLinux32::TGT_MAP_SHARED, MAP_SHARED },
{ ArmLinux32::TGT_MAP_PRIVATE, MAP_PRIVATE },
{ ArmLinux32::TGT_MAP_ANON, MAP_ANON },
{ ArmLinux32::TGT_MAP_DENYWRITE, MAP_DENYWRITE },
{ ArmLinux32::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
{ ArmLinux32::TGT_MAP_FILE, MAP_FILE },
{ ArmLinux32::TGT_MAP_GROWSDOWN, MAP_GROWSDOWN },
{ ArmLinux32::TGT_MAP_HUGETLB, MAP_HUGETLB },
{ ArmLinux32::TGT_MAP_LOCKED, MAP_LOCKED },
{ ArmLinux32::TGT_MAP_NONBLOCK, MAP_NONBLOCK },
{ ArmLinux32::TGT_MAP_NORESERVE, MAP_NORESERVE },
{ ArmLinux32::TGT_MAP_POPULATE, MAP_POPULATE },
#ifdef MAP_STACK
{ ArmLinux32::TGT_MAP_STACK, MAP_STACK },
#endif
{ ArmLinux32::TGT_MAP_ANONYMOUS, MAP_ANONYMOUS },
{ ArmLinux32::TGT_MAP_FIXED, MAP_FIXED },
};
const unsigned ArmLinux32::NUM_MMAP_FLAGS =
sizeof(ArmLinux32::mmapFlagTable) /
sizeof(ArmLinux32::mmapFlagTable[0]);
// open(2) flags translation table
SyscallFlagTransTable ArmLinux64::openFlagTable[] = {
#ifdef _MSC_VER
@ -197,3 +223,28 @@ SyscallFlagTransTable ArmLinux64::openFlagTable[] = {
const int ArmLinux64::NUM_OPEN_FLAGS = sizeof(ArmLinux64::openFlagTable) /
sizeof(ArmLinux64::openFlagTable[0]);
// mmap(2) flags translation table
SyscallFlagTransTable ArmLinux64::mmapFlagTable[] = {
{ ArmLinux64::TGT_MAP_SHARED, MAP_SHARED },
{ ArmLinux64::TGT_MAP_PRIVATE, MAP_PRIVATE },
{ ArmLinux64::TGT_MAP_ANON, MAP_ANON },
{ ArmLinux64::TGT_MAP_DENYWRITE, MAP_DENYWRITE },
{ ArmLinux64::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
{ ArmLinux64::TGT_MAP_FILE, MAP_FILE },
{ ArmLinux64::TGT_MAP_GROWSDOWN, MAP_GROWSDOWN },
{ ArmLinux64::TGT_MAP_HUGETLB, MAP_HUGETLB },
{ ArmLinux64::TGT_MAP_LOCKED, MAP_LOCKED },
{ ArmLinux64::TGT_MAP_NONBLOCK, MAP_NONBLOCK },
{ ArmLinux64::TGT_MAP_NORESERVE, MAP_NORESERVE },
{ ArmLinux64::TGT_MAP_POPULATE, MAP_POPULATE },
#ifdef MAP_STACK
{ ArmLinux64::TGT_MAP_STACK, MAP_STACK },
#endif
{ ArmLinux64::TGT_MAP_ANONYMOUS, MAP_ANONYMOUS },
{ ArmLinux64::TGT_MAP_FIXED, MAP_FIXED },
};
const unsigned ArmLinux64::NUM_MMAP_FLAGS =
sizeof(ArmLinux64::mmapFlagTable) /
sizeof(ArmLinux64::mmapFlagTable[0]);

View file

@ -125,8 +125,25 @@ class ArmLinux32 : public Linux
//@}
/// For mmap().
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
static const unsigned TGT_MAP_FIXED = 0x10;
static SyscallFlagTransTable mmapFlagTable[];
static const unsigned TGT_MAP_SHARED = 0x00001;
static const unsigned TGT_MAP_PRIVATE = 0x00002;
static const unsigned TGT_MAP_ANON = 0x00020;
static const unsigned TGT_MAP_DENYWRITE = 0x00800;
static const unsigned TGT_MAP_EXECUTABLE = 0x01000;
static const unsigned TGT_MAP_FILE = 0x00000;
static const unsigned TGT_MAP_GROWSDOWN = 0x00100;
static const unsigned TGT_MAP_HUGETLB = 0x40000;
static const unsigned TGT_MAP_LOCKED = 0x02000;
static const unsigned TGT_MAP_NONBLOCK = 0x10000;
static const unsigned TGT_MAP_NORESERVE = 0x04000;
static const unsigned TGT_MAP_POPULATE = 0x08000;
static const unsigned TGT_MAP_STACK = 0x20000;
static const unsigned TGT_MAP_ANONYMOUS = 0x00020;
static const unsigned TGT_MAP_FIXED = 0x00010;
static const unsigned NUM_MMAP_FLAGS;
/// For table().
static const int TBL_SYSINFO = 12;
@ -320,8 +337,25 @@ class ArmLinux64 : public Linux
//@}
/// For mmap().
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
static const unsigned TGT_MAP_FIXED = 0x10;
static SyscallFlagTransTable mmapFlagTable[];
static const unsigned TGT_MAP_SHARED = 0x00001;
static const unsigned TGT_MAP_PRIVATE = 0x00002;
static const unsigned TGT_MAP_ANON = 0x00020;
static const unsigned TGT_MAP_DENYWRITE = 0x00800;
static const unsigned TGT_MAP_EXECUTABLE = 0x01000;
static const unsigned TGT_MAP_FILE = 0x00000;
static const unsigned TGT_MAP_GROWSDOWN = 0x00100;
static const unsigned TGT_MAP_HUGETLB = 0x40000;
static const unsigned TGT_MAP_LOCKED = 0x02000;
static const unsigned TGT_MAP_NONBLOCK = 0x10000;
static const unsigned TGT_MAP_NORESERVE = 0x04000;
static const unsigned TGT_MAP_POPULATE = 0x08000;
static const unsigned TGT_MAP_STACK = 0x20000;
static const unsigned TGT_MAP_ANONYMOUS = 0x00020;
static const unsigned TGT_MAP_FIXED = 0x00010;
static const unsigned NUM_MMAP_FLAGS;
//@{
/// For getrusage().

View file

@ -28,10 +28,11 @@
* Authors: Korey Sewell
*/
#include <fcntl.h>
#include "arch/mips/linux/linux.hh"
#include <fcntl.h>
#include <sys/mman.h>
// open(2) flags translation table
SyscallFlagTransTable MipsLinux::openFlagTable[] = {
#ifdef _MSC_VER
@ -97,3 +98,29 @@ SyscallFlagTransTable MipsLinux::openFlagTable[] = {
const int MipsLinux::NUM_OPEN_FLAGS =
(sizeof(MipsLinux::openFlagTable)/sizeof(MipsLinux::openFlagTable[0]));
// mmap(2) flags translation table
SyscallFlagTransTable MipsLinux::mmapFlagTable[] = {
{ MipsLinux::TGT_MAP_SHARED, MAP_SHARED },
{ MipsLinux::TGT_MAP_PRIVATE, MAP_PRIVATE },
{ MipsLinux::TGT_MAP_ANON, MAP_ANON },
{ MipsLinux::TGT_MAP_DENYWRITE, MAP_DENYWRITE },
{ MipsLinux::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
{ MipsLinux::TGT_MAP_FILE, MAP_FILE },
{ MipsLinux::TGT_MAP_GROWSDOWN, MAP_GROWSDOWN },
{ MipsLinux::TGT_MAP_HUGETLB, MAP_HUGETLB },
{ MipsLinux::TGT_MAP_LOCKED, MAP_LOCKED },
{ MipsLinux::TGT_MAP_NONBLOCK, MAP_NONBLOCK },
{ MipsLinux::TGT_MAP_NORESERVE, MAP_NORESERVE },
{ MipsLinux::TGT_MAP_POPULATE, MAP_POPULATE },
#ifdef MAP_STACK
{ MipsLinux::TGT_MAP_STACK, MAP_STACK },
#endif
{ MipsLinux::TGT_MAP_ANONYMOUS, MAP_ANONYMOUS },
{ MipsLinux::TGT_MAP_FIXED, MAP_FIXED },
};
const unsigned MipsLinux::NUM_MMAP_FLAGS =
sizeof(MipsLinux::mmapFlagTable) /
sizeof(MipsLinux::mmapFlagTable[0]);

View file

@ -102,8 +102,25 @@ class MipsLinux : public Linux
//@}
/// For mmap().
static const unsigned TGT_MAP_ANONYMOUS = 0x800;
static const unsigned TGT_MAP_FIXED = 0x10;
static SyscallFlagTransTable mmapFlagTable[];
static const unsigned TGT_MAP_SHARED = 0x00001;
static const unsigned TGT_MAP_PRIVATE = 0x00002;
static const unsigned TGT_MAP_ANON = 0x00800;
static const unsigned TGT_MAP_DENYWRITE = 0x02000;
static const unsigned TGT_MAP_EXECUTABLE = 0x04000;
static const unsigned TGT_MAP_FILE = 0x00000;
static const unsigned TGT_MAP_GROWSDOWN = 0x01000;
static const unsigned TGT_MAP_HUGETLB = 0x80000;
static const unsigned TGT_MAP_LOCKED = 0x08000;
static const unsigned TGT_MAP_NONBLOCK = 0x20000;
static const unsigned TGT_MAP_NORESERVE = 0x00400;
static const unsigned TGT_MAP_POPULATE = 0x10000;
static const unsigned TGT_MAP_STACK = 0x40000;
static const unsigned TGT_MAP_ANONYMOUS = 0x00800;
static const unsigned TGT_MAP_FIXED = 0x00010;
static const unsigned NUM_MMAP_FLAGS;
//@{
/// For getsysinfo().

View file

@ -29,10 +29,11 @@
* Authors: Timothy M. Jones
*/
#include <fcntl.h>
#include "arch/power/linux/linux.hh"
#include <fcntl.h>
#include <sys/mman.h>
// open(2) flags translation table
SyscallFlagTransTable PowerLinux::openFlagTable[] = {
#ifdef _MSC_VER
@ -105,3 +106,28 @@ SyscallFlagTransTable PowerLinux::openFlagTable[] = {
const int PowerLinux::NUM_OPEN_FLAGS =
(sizeof(PowerLinux::openFlagTable)/sizeof(PowerLinux::openFlagTable[0]));
// mmap(2) flags translation table
SyscallFlagTransTable PowerLinux::mmapFlagTable[] = {
{ PowerLinux::TGT_MAP_SHARED, MAP_SHARED },
{ PowerLinux::TGT_MAP_PRIVATE, MAP_PRIVATE },
{ PowerLinux::TGT_MAP_ANON, MAP_ANON },
{ PowerLinux::TGT_MAP_DENYWRITE, MAP_DENYWRITE },
{ PowerLinux::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
{ PowerLinux::TGT_MAP_FILE, MAP_FILE },
{ PowerLinux::TGT_MAP_GROWSDOWN, MAP_GROWSDOWN },
{ PowerLinux::TGT_MAP_HUGETLB, MAP_HUGETLB },
{ PowerLinux::TGT_MAP_LOCKED, MAP_LOCKED },
{ PowerLinux::TGT_MAP_NONBLOCK, MAP_NONBLOCK },
{ PowerLinux::TGT_MAP_NORESERVE, MAP_NORESERVE },
{ PowerLinux::TGT_MAP_POPULATE, MAP_POPULATE },
#ifdef MAP_STACK
{ PowerLinux::TGT_MAP_STACK, MAP_STACK },
#endif
{ PowerLinux::TGT_MAP_ANONYMOUS, MAP_ANONYMOUS },
{ PowerLinux::TGT_MAP_FIXED, MAP_FIXED },
};
const unsigned PowerLinux::NUM_MMAP_FLAGS =
sizeof(PowerLinux::mmapFlagTable) /
sizeof(PowerLinux::mmapFlagTable[0]);

View file

@ -164,8 +164,25 @@ class PowerLinux : public Linux
//@}
/// For mmap().
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
static const unsigned TGT_MAP_FIXED = 0x10;
static SyscallFlagTransTable mmapFlagTable[];
static const unsigned TGT_MAP_SHARED = 0x00001;
static const unsigned TGT_MAP_PRIVATE = 0x00002;
static const unsigned TGT_MAP_ANON = 0x00020;
static const unsigned TGT_MAP_DENYWRITE = 0x00800;
static const unsigned TGT_MAP_EXECUTABLE = 0x01000;
static const unsigned TGT_MAP_FILE = 0x00000;
static const unsigned TGT_MAP_GROWSDOWN = 0x00100;
static const unsigned TGT_MAP_HUGETLB = 0x40000;
static const unsigned TGT_MAP_LOCKED = 0x00080;
static const unsigned TGT_MAP_NONBLOCK = 0x10000;
static const unsigned TGT_MAP_NORESERVE = 0x00040;
static const unsigned TGT_MAP_POPULATE = 0x08000;
static const unsigned TGT_MAP_STACK = 0x20000;
static const unsigned TGT_MAP_ANONYMOUS = 0x00020;
static const unsigned TGT_MAP_FIXED = 0x00010;
static const unsigned NUM_MMAP_FLAGS;
//@{
/// ioctl() command codes.

View file

@ -28,10 +28,11 @@
* Authors: Gabe Black
*/
#include <fcntl.h>
#include "arch/sparc/linux/linux.hh"
#include <fcntl.h>
#include <sys/mman.h>
// open(2) flags translation table
SyscallFlagTransTable SparcLinux::openFlagTable[] = {
#ifdef _MSC_VER
@ -95,3 +96,32 @@ SyscallFlagTransTable SparcLinux::openFlagTable[] = {
const int SparcLinux::NUM_OPEN_FLAGS =
(sizeof(SparcLinux::openFlagTable)/sizeof(SparcLinux::openFlagTable[0]));
// mmap(2) flags translation table
SyscallFlagTransTable SparcLinux::mmapFlagTable[] = {
{ SparcLinux::TGT_MAP_SHARED, MAP_SHARED },
{ SparcLinux::TGT_MAP_PRIVATE, MAP_PRIVATE },
{ SparcLinux::TGT_MAP_ANON, MAP_ANON },
{ SparcLinux::TGT_MAP_DENYWRITE, MAP_DENYWRITE },
{ SparcLinux::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
{ SparcLinux::TGT_MAP_FILE, MAP_FILE },
{ SparcLinux::TGT_MAP_GROWSDOWN, MAP_GROWSDOWN },
{ SparcLinux::TGT_MAP_HUGETLB, MAP_HUGETLB },
{ SparcLinux::TGT_MAP_LOCKED, MAP_LOCKED },
{ SparcLinux::TGT_MAP_NONBLOCK, MAP_NONBLOCK },
{ SparcLinux::TGT_MAP_NORESERVE, MAP_NORESERVE },
{ SparcLinux::TGT_MAP_POPULATE, MAP_POPULATE },
#ifdef MAP_STACK
{ SparcLinux::TGT_MAP_STACK, MAP_STACK },
#endif
{ SparcLinux::TGT_MAP_ANONYMOUS, MAP_ANONYMOUS },
{ SparcLinux::TGT_MAP_FIXED, MAP_FIXED },
#ifdef MAP_INHERIT
{ SparcLinux::TGT_MAP_INHERIT, MAP_INHERIT },
#endif
{ SparcLinux::TGT_MAP_POPULATE, MAP_POPULATE },
};
const unsigned SparcLinux::NUM_MMAP_FLAGS =
sizeof(SparcLinux::mmapFlagTable) /
sizeof(SparcLinux::mmapFlagTable[0]);

View file

@ -118,8 +118,27 @@ class SparcLinux : public Linux
static const int NUM_OPEN_FLAGS;
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
static const unsigned TGT_MAP_FIXED = 0x10;
/// For mmap().
static SyscallFlagTransTable mmapFlagTable[];
static const unsigned TGT_MAP_SHARED = 0x00001;
static const unsigned TGT_MAP_PRIVATE = 0x00002;
static const unsigned TGT_MAP_ANON = 0x00020;
static const unsigned TGT_MAP_DENYWRITE = 0x00800;
static const unsigned TGT_MAP_EXECUTABLE = 0x01000;
static const unsigned TGT_MAP_FILE = 0x00000;
static const unsigned TGT_MAP_GROWSDOWN = 0x00200;
static const unsigned TGT_MAP_HUGETLB = 0x40000;
static const unsigned TGT_MAP_LOCKED = 0x00100;
static const unsigned TGT_MAP_NONBLOCK = 0x10000;
static const unsigned TGT_MAP_NORESERVE = 0x00040;
static const unsigned TGT_MAP_POPULATE = 0x08000;
static const unsigned TGT_MAP_STACK = 0x20000;
static const unsigned TGT_MAP_ANONYMOUS = 0x00020;
static const unsigned TGT_MAP_FIXED = 0x00010;
static const unsigned TGT_MAP_INHERIT = 0x00080;
static const unsigned NUM_MMAP_FLAGS;
typedef struct {
int64_t uptime; /* Seconds since boot */

View file

@ -28,10 +28,11 @@
* Authors: Ali Saidi
*/
#include <fcntl.h>
#include "arch/sparc/solaris/solaris.hh"
#include <fcntl.h>
#include <sys/mman.h>
// open(2) flags translation table
SyscallFlagTransTable SparcSolaris::openFlagTable[] = {
#ifdef _MSC_VER
@ -76,3 +77,27 @@ SyscallFlagTransTable SparcSolaris::openFlagTable[] = {
const int SparcSolaris::NUM_OPEN_FLAGS =
(sizeof(SparcSolaris::openFlagTable)/sizeof(SparcSolaris::openFlagTable[0]));
// mmap(2) flags translation table
SyscallFlagTransTable SparcSolaris::mmapFlagTable[] = {
{ TGT_MAP_SHARED, MAP_SHARED },
{ TGT_MAP_PRIVATE, MAP_PRIVATE },
{ TGT_MAP_32BIT, MAP_32BIT},
{ TGT_MAP_ANON, MAP_ANON },
{ TGT_MAP_DENYWRITE, MAP_DENYWRITE },
{ TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
{ TGT_MAP_FILE, MAP_FILE },
{ TGT_MAP_GROWSDOWN, MAP_GROWSDOWN },
{ TGT_MAP_HUGETLB, MAP_HUGETLB },
{ TGT_MAP_LOCKED, MAP_LOCKED },
{ TGT_MAP_NONBLOCK, MAP_NONBLOCK },
{ TGT_MAP_NORESERVE, MAP_NORESERVE },
{ TGT_MAP_POPULATE, MAP_POPULATE },
{ TGT_MAP_STACK, MAP_STACK },
{ TGT_MAP_ANONYMOUS, MAP_ANONYMOUS },
{ TGT_MAP_FIXED, MAP_FIXED },
};
const unsigned SparcSolaris::NUM_MMAP_FLAGS =
sizeof(SparcSolaris::mmapFlagTable) /
sizeof(SparcSolaris::mmapFlagTable[0]);

View file

@ -58,8 +58,27 @@ class SparcSolaris : public Solaris
static const int NUM_OPEN_FLAGS;
static const unsigned TGT_MAP_ANONYMOUS = 0x100;
static const unsigned TGT_MAP_FIXED = 0x10;
/// For mmap().
static SyscallFlagTransTable mmapFlagTable[];
static const unsigned TGT_MAP_SHARED = 0x00001;
static const unsigned TGT_MAP_PRIVATE = 0x00002;
static const unsigned TGT_MAP_32BIT = 0x00040;
static const unsigned TGT_MAP_ANON = 0x00020;
static const unsigned TGT_MAP_DENYWRITE = 0x00800;
static const unsigned TGT_MAP_EXECUTABLE = 0x01000;
static const unsigned TGT_MAP_FILE = 0x00000;
static const unsigned TGT_MAP_GROWSDOWN = 0x00100;
static const unsigned TGT_MAP_HUGETLB = 0x40000;
static const unsigned TGT_MAP_LOCKED = 0x02000;
static const unsigned TGT_MAP_NONBLOCK = 0x10000;
static const unsigned TGT_MAP_NORESERVE = 0x04000;
static const unsigned TGT_MAP_POPULATE = 0x08000;
static const unsigned TGT_MAP_STACK = 0x20000;
static const unsigned TGT_MAP_ANONYMOUS = 0x00020;
static const unsigned TGT_MAP_FIXED = 0x00010;
static const unsigned NUM_MMAP_FLAGS;
};
#endif

View file

@ -37,10 +37,11 @@
* Authors: Gabe Black
*/
#include <fcntl.h>
#include "arch/x86/linux/linux.hh"
#include <fcntl.h>
#include <sys/mman.h>
// open(2) flags translation table
SyscallFlagTransTable X86Linux64::openFlagTable[] = {
#ifdef _MSC_VER
@ -110,6 +111,34 @@ const int X86Linux64::NUM_OPEN_FLAGS =
sizeof(X86Linux64::openFlagTable) /
sizeof(X86Linux64::openFlagTable[0]);
// mmap(2) flags translation table
SyscallFlagTransTable X86Linux64::mmapFlagTable[] = {
{ X86Linux64::TGT_MAP_SHARED, MAP_SHARED },
{ X86Linux64::TGT_MAP_PRIVATE, MAP_PRIVATE },
{ X86Linux64::TGT_MAP_32BIT, MAP_32BIT},
{ X86Linux64::TGT_MAP_ANON, MAP_ANON },
{ X86Linux64::TGT_MAP_DENYWRITE, MAP_DENYWRITE },
{ X86Linux64::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
{ X86Linux64::TGT_MAP_FILE, MAP_FILE },
{ X86Linux64::TGT_MAP_GROWSDOWN, MAP_GROWSDOWN },
#ifdef MAP_HUGETLB
{ X86Linux64::TGT_MAP_HUGETLB, MAP_HUGETLB },
#endif
{ X86Linux64::TGT_MAP_LOCKED, MAP_LOCKED },
{ X86Linux64::TGT_MAP_NONBLOCK, MAP_NONBLOCK },
{ X86Linux64::TGT_MAP_NORESERVE, MAP_NORESERVE },
{ X86Linux64::TGT_MAP_POPULATE, MAP_POPULATE },
#ifdef MAP_STACK
{ X86Linux64::TGT_MAP_STACK, MAP_STACK },
#endif
{ X86Linux64::TGT_MAP_ANONYMOUS, MAP_ANONYMOUS },
{ X86Linux64::TGT_MAP_FIXED, MAP_FIXED },
};
const unsigned X86Linux64::NUM_MMAP_FLAGS =
sizeof(X86Linux64::mmapFlagTable) /
sizeof(X86Linux64::mmapFlagTable[0]);
// open(2) flags translation table
SyscallFlagTransTable X86Linux32::openFlagTable[] = {
#ifdef _MSC_VER
@ -179,3 +208,30 @@ const int X86Linux32::NUM_OPEN_FLAGS =
sizeof(X86Linux32::openFlagTable) /
sizeof(X86Linux32::openFlagTable[0]);
// mmap(2) flags translation table
SyscallFlagTransTable X86Linux32::mmapFlagTable[] = {
{ X86Linux32::TGT_MAP_SHARED, MAP_SHARED },
{ X86Linux32::TGT_MAP_PRIVATE, MAP_PRIVATE },
{ X86Linux32::TGT_MAP_32BIT, MAP_32BIT},
{ X86Linux32::TGT_MAP_ANON, MAP_ANON },
{ X86Linux32::TGT_MAP_DENYWRITE, MAP_DENYWRITE },
{ X86Linux32::TGT_MAP_EXECUTABLE, MAP_EXECUTABLE },
{ X86Linux32::TGT_MAP_FILE, MAP_FILE },
{ X86Linux32::TGT_MAP_GROWSDOWN, MAP_GROWSDOWN },
#ifdef MAP_HUGETLB
{ X86Linux32::TGT_MAP_HUGETLB, MAP_HUGETLB },
#endif
{ X86Linux32::TGT_MAP_LOCKED, MAP_LOCKED },
{ X86Linux32::TGT_MAP_NONBLOCK, MAP_NONBLOCK },
{ X86Linux32::TGT_MAP_NORESERVE, MAP_NORESERVE },
{ X86Linux32::TGT_MAP_POPULATE, MAP_POPULATE },
#ifdef MAP_STACK
{ X86Linux32::TGT_MAP_STACK, MAP_STACK },
#endif
{ X86Linux32::TGT_MAP_ANONYMOUS, MAP_ANONYMOUS },
{ X86Linux32::TGT_MAP_FIXED, MAP_FIXED },
};
const unsigned X86Linux32::NUM_MMAP_FLAGS =
sizeof(X86Linux32::mmapFlagTable) /
sizeof(X86Linux32::mmapFlagTable[0]);

View file

@ -126,8 +126,27 @@ class X86Linux64 : public Linux
static const int NUM_OPEN_FLAGS;
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
static const unsigned TGT_MAP_FIXED = 0x10;
/// For mmap().
static SyscallFlagTransTable mmapFlagTable[];
static const unsigned TGT_MAP_SHARED = 0x00001;
static const unsigned TGT_MAP_PRIVATE = 0x00002;
static const unsigned TGT_MAP_32BIT = 0x00040;
static const unsigned TGT_MAP_ANON = 0x00020;
static const unsigned TGT_MAP_DENYWRITE = 0x00800;
static const unsigned TGT_MAP_EXECUTABLE = 0x01000;
static const unsigned TGT_MAP_FILE = 0x00000;
static const unsigned TGT_MAP_GROWSDOWN = 0x00100;
static const unsigned TGT_MAP_HUGETLB = 0x40000;
static const unsigned TGT_MAP_LOCKED = 0x02000;
static const unsigned TGT_MAP_NONBLOCK = 0x10000;
static const unsigned TGT_MAP_NORESERVE = 0x04000;
static const unsigned TGT_MAP_POPULATE = 0x08000;
static const unsigned TGT_MAP_STACK = 0x20000;
static const unsigned TGT_MAP_ANONYMOUS = 0x00020;
static const unsigned TGT_MAP_FIXED = 0x00010;
static const unsigned NUM_MMAP_FLAGS;
typedef struct {
uint64_t iov_base; // void *
@ -147,7 +166,7 @@ class X86Linux64 : public Linux
uint64_t totalhigh; /* Total high memory size */
uint64_t freehigh; /* Available high memory size */
uint64_t mem_unit; /* Memory unit size in bytes */
} tgt_sysinfo;
} tgt_sysinfo;
};
@ -236,8 +255,26 @@ class X86Linux32 : public Linux
static const int NUM_OPEN_FLAGS;
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
static const unsigned TGT_MAP_FIXED = 0x10;
static SyscallFlagTransTable mmapFlagTable[];
static const unsigned TGT_MAP_SHARED = 0x00001;
static const unsigned TGT_MAP_PRIVATE = 0x00002;
static const unsigned TGT_MAP_32BIT = 0x00040;
static const unsigned TGT_MAP_ANON = 0x00020;
static const unsigned TGT_MAP_DENYWRITE = 0x00800;
static const unsigned TGT_MAP_EXECUTABLE = 0x01000;
static const unsigned TGT_MAP_FILE = 0x00000;
static const unsigned TGT_MAP_GROWSDOWN = 0x00100;
static const unsigned TGT_MAP_HUGETLB = 0x40000;
static const unsigned TGT_MAP_LOCKED = 0x02000;
static const unsigned TGT_MAP_NONBLOCK = 0x10000;
static const unsigned TGT_MAP_NORESERVE = 0x04000;
static const unsigned TGT_MAP_POPULATE = 0x08000;
static const unsigned TGT_MAP_STACK = 0x20000;
static const unsigned TGT_MAP_ANONYMOUS = 0x00020;
static const unsigned TGT_MAP_FIXED = 0x00010;
static const unsigned NUM_MMAP_FLAGS;
typedef struct {
int32_t uptime; /* Seconds since boot */

View file

@ -324,7 +324,9 @@ _llseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
SyscallReturn
munmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
// given that we don't really implement mmap, munmap is really easy
// With mmap more fully implemented, it might be worthwhile to bite
// the bullet and implement munmap. Should allow us to reuse simulated
// memory.
return 0;
}

View file

@ -58,6 +58,7 @@
#ifdef __CYGWIN32__
#include <sys/fcntl.h> // for O_BINARY
#endif
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/uio.h>
@ -1224,12 +1225,6 @@ writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
/// Target mmap() handler.
///
/// We don't really handle mmap(). If the target is mmaping an
/// anonymous region or /dev/zero, we can get away with doing basically
/// nothing (since memory is initialized to zero and the simulator
/// doesn't really check addresses anyway).
///
template <class OS>
SyscallReturn
mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
@ -1237,78 +1232,134 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
int index = 0;
Addr start = p->getSyscallArg(tc, index);
uint64_t length = p->getSyscallArg(tc, index);
index++; // int prot = p->getSyscallArg(tc, index);
int flags = p->getSyscallArg(tc, index);
int prot = p->getSyscallArg(tc, index);
int tgt_flags = p->getSyscallArg(tc, index);
int tgt_fd = p->getSyscallArg(tc, index);
int offset = p->getSyscallArg(tc, index);
if (length > 0x100000000ULL)
warn("mmap length argument %#x is unreasonably large.\n", length);
DPRINTF_SYSCALL(Verbose, "mmap(0x%x, len %d, prot %d, flags %d, fd %d, "
"offs %d)\n", start, length, prot, tgt_flags, tgt_fd,
offset);
if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
FDEntry *fde = p->getFDEntry(tgt_fd);
if (!fde || fde->fd < 0) {
warn("mmap failing: target fd %d is not valid\n", tgt_fd);
return -EBADF;
}
if (start & (TheISA::PageBytes - 1) ||
offset & (TheISA::PageBytes - 1) ||
(tgt_flags & OS::TGT_MAP_PRIVATE &&
tgt_flags & OS::TGT_MAP_SHARED) ||
(!(tgt_flags & OS::TGT_MAP_PRIVATE) &&
!(tgt_flags & OS::TGT_MAP_SHARED)) ||
!length) {
return -EINVAL;
}
if (fde->filename != "/dev/zero") {
// This is very likely broken, but leave a warning here
// (rather than panic) in case /dev/zero is known by
// another name on some platform
warn("allowing mmap of file %s; mmap not supported on files"
" other than /dev/zero\n", fde->filename);
}
if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) {
// With shared mmaps, there are two cases to consider:
// 1) anonymous: writes should modify the mapping and this should be
// visible to observers who share the mapping. Currently, it's
// difficult to update the shared mapping because there's no
// structure which maintains information about the which virtual
// memory areas are shared. If that structure existed, it would be
// possible to make the translations point to the same frames.
// 2) file-backed: writes should modify the mapping and the file
// which is backed by the mapping. The shared mapping problem is the
// same as what was mentioned about the anonymous mappings. For
// file-backed mappings, the writes to the file are difficult
// because it requires syncing what the mapping holds with the file
// that resides on the host system. So, any write on a real system
// would cause the change to be propagated to the file mapping at
// some point in the future (the inode is tracked along with the
// mapping). This isn't guaranteed to always happen, but it usually
// works well enough. The guarantee is provided by the msync system
// call. We could force the change through with shared mappings with
// a call to msync, but that again would require more information
// than we currently maintain.
warn("mmap: writing to shared mmap region is currently "
"unsupported. The write succeeds on the target, but it "
"will not be propagated to the host or shared mappings");
}
length = roundUp(length, TheISA::PageBytes);
if ((start % TheISA::PageBytes) != 0 ||
(offset % TheISA::PageBytes) != 0) {
warn("mmap failing: arguments not page-aligned: "
"start 0x%x offset 0x%x",
start, offset);
return -EINVAL;
}
int sim_fd = -1;
uint8_t *pmap = nullptr;
if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) {
sim_fd = p->getSimFD(tgt_fd);
if (sim_fd < 0)
return -EBADF;
// are we ok with clobbering existing mappings? only set this to
// true if the user has been warned.
bool clobber = false;
pmap = (decltype(pmap))mmap(NULL, length, PROT_READ, MAP_PRIVATE,
sim_fd, offset);
// try to use the caller-provided address if there is one
bool use_provided_address = (start != 0);
if (use_provided_address) {
// check to see if the desired address is already in use
if (!p->pTable->isUnmapped(start, length)) {
// there are existing mappings in the desired range
// whether we clobber them or not depends on whether the caller
// specified MAP_FIXED
if (flags & OS::TGT_MAP_FIXED) {
// MAP_FIXED specified: map attempt fails
return -EINVAL;
} else {
// MAP_FIXED not specified: ignore suggested start address
warn("mmap: ignoring suggested map address 0x%x\n", start);
use_provided_address = false;
}
if (pmap == (decltype(pmap))-1) {
warn("mmap: failed to map file into host address space");
return -errno;
}
}
if (!use_provided_address) {
// no address provided, or provided address unusable:
// pick next address from our "mmap region"
if (OS::mmapGrowsDown()) {
start = p->mmap_end - length;
p->mmap_end = start;
} else {
start = p->mmap_end;
p->mmap_end += length;
// Extend global mmap region if necessary. Note that we ignore the
// start address unless MAP_FIXED is specified.
if (!(tgt_flags & OS::TGT_MAP_FIXED)) {
start = (OS::mmapGrowsDown()) ? p->mmap_end - length : p->mmap_end;
p->mmap_end = (OS::mmapGrowsDown()) ? start : p->mmap_end + length;
}
DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n",
start, start + length - 1);
// We only allow mappings to overwrite existing mappings if
// TGT_MAP_FIXED is set. Otherwise it shouldn't be a problem
// because we ignore the start hint if TGT_MAP_FIXED is not set.
int clobber = tgt_flags & OS::TGT_MAP_FIXED;
if (clobber) {
for (auto tc : p->system->threadContexts) {
// If we might be overwriting old mappings, we need to
// invalidate potentially stale mappings out of the TLBs.
tc->getDTBPtr()->flushAll();
tc->getITBPtr()->flushAll();
}
}
// Allocate physical memory and map it in. If the page table is already
// mapped and clobber is not set, the simulator will issue throw a
// fatal and bail out of the simulation.
p->allocateMem(start, length, clobber);
// Transfer content into target address space.
SETranslatingPortProxy &tp = tc->getMemProxy();
if (tgt_flags & OS::TGT_MAP_ANONYMOUS) {
// In general, we should zero the mapped area for anonymous mappings,
// with something like:
// tp.memsetBlob(start, 0, length);
// However, given that we don't support sparse mappings, and
// some applications can map a couple of gigabytes of space
// (intending sparse usage), that can get painfully expensive.
// Fortunately, since we don't properly implement munmap either,
// there's no danger of remapping used memory, so for now all
// newly mapped memory should already be zeroed so we can skip it.
} else {
// It is possible to mmap an area larger than a file, however
// accessing unmapped portions the system triggers a "Bus error"
// on the host. We must know when to stop copying the file from
// the host into the target address space.
struct stat file_stat;
if (fstat(sim_fd, &file_stat) > 0)
fatal("mmap: cannot stat file");
// Copy the portion of the file that is resident. This requires
// checking both the mmap size and the filesize that we are
// trying to mmap into this space; the mmap size also depends
// on the specified offset into the file.
uint64_t size = std::min((uint64_t)file_stat.st_size - offset,
length);
tp.writeBlob(start, pmap, size);
// Cleanup the mmap region before exiting this function.
munmap(pmap, length);
// Note that we do not zero out the remainder of the mapping. This
// is done by a real system, but it probably will not affect
// execution (hopefully).
}
return start;
}