syscall emulation: Clean up ioctl handling, and implement for x86.
authorMarc Orr <marc.orr@gmail.com>
Mon, 6 Aug 2012 23:52:40 +0000 (16:52 -0700)
committerMarc Orr <marc.orr@gmail.com>
Mon, 6 Aug 2012 23:52:40 +0000 (16:52 -0700)
Enable different whitelists for different OS/arch combinations,
since some use the generic Linux definitions only, and others
use definitions inherited from earlier Unix flavors on those
architectures.

Also update x86 function pointers so ioctl is no longer
unimplemented on that platform.

This patch is a revised version of Vince Weaver's earlier patch.

src/arch/alpha/linux/linux.hh
src/arch/alpha/tru64/tru64.hh
src/arch/arm/linux/linux.hh
src/arch/mips/linux/linux.hh
src/arch/power/linux/linux.hh
src/arch/sparc/linux/linux.hh
src/arch/x86/linux/syscalls.cc
src/kern/linux/linux.hh
src/sim/syscall_emul.hh

index 6197b8d456a2707b8483d27c5cc6edbe25b5dbb3..443f70d81eee28e49cad717d8926316aefacf4c4 100644 (file)
@@ -97,18 +97,35 @@ class AlphaLinux : public Linux
 
     //@{
     /// ioctl() command codes.
-    static const unsigned TIOCGETP_   = 0x40067408;
-    static const unsigned TIOCSETP_   = 0x80067409;
-    static const unsigned TIOCSETN_   = 0x8006740a;
-    static const unsigned TIOCSETC_   = 0x80067411;
-    static const unsigned TIOCGETC_   = 0x40067412;
-    static const unsigned FIONREAD_   = 0x4004667f;
-    static const unsigned TIOCISATTY_ = 0x2000745e;
-    static const unsigned TIOCGETS_   = 0x402c7413;
-    static const unsigned TIOCGETA_   = 0x40127417;
-    static const unsigned TCSETAW_    = 0x80147419; // 2.6.15 kernel
+    static const unsigned TGT_TIOCGETP   = 0x40067408;
+    static const unsigned TGT_TIOCSETP   = 0x80067409;
+    static const unsigned TGT_TIOCSETN   = 0x8006740a;
+    static const unsigned TGT_TIOCSETC   = 0x80067411;
+    static const unsigned TGT_TIOCGETC   = 0x40067412;
+    static const unsigned TGT_FIONREAD   = 0x4004667f;
+    static const unsigned TGT_TCGETS     = 0x402c7413;
+    static const unsigned TGT_TCGETA     = 0x40127417;
+    static const unsigned TGT_TCSETAW    = 0x80147419; // 2.6.15 kernel
     //@}
 
+    static bool
+    isTtyReq(unsigned req)
+    {
+        switch (req) {
+          case TGT_TIOCGETP:
+          case TGT_TIOCSETP:
+          case TGT_TIOCSETN:
+          case TGT_TIOCSETC:
+          case TGT_TIOCGETC:
+          case TGT_TCGETS:
+          case TGT_TCGETA:
+          case TGT_TCSETAW:
+            return true;
+          default:
+            return false;
+        }
+    }
+
     /// For table().
     static const int TBL_SYSINFO = 12;
 
index f0cad82896df583bac644e29d5955767196a1805..5751da8d42886bf44e010aeae7d999962130155b 100644 (file)
@@ -91,18 +91,38 @@ class AlphaTru64 : public Tru64
 
     //@{
     /// ioctl() command codes.
-    static const unsigned TIOCGETP_   = 0x40067408;
-    static const unsigned TIOCSETP_   = 0x80067409;
-    static const unsigned TIOCSETN_   = 0x8006740a;
-    static const unsigned TIOCSETC_   = 0x80067411;
-    static const unsigned TIOCGETC_   = 0x40067412;
-    static const unsigned FIONREAD_   = 0x4004667f;
-    static const unsigned TIOCISATTY_ = 0x2000745e;
-    static const unsigned TIOCGETS_   = 0x402c7413;
-    static const unsigned TIOCGETA_   = 0x40127417;
-    static const unsigned TCSETAW_    = 0x80147419;
+    static const unsigned TGT_TIOCGETP   = 0x40067408;
+    static const unsigned TGT_TIOCSETP   = 0x80067409;
+    static const unsigned TGT_TIOCSETN   = 0x8006740a;
+    static const unsigned TGT_TIOCSETC   = 0x80067411;
+    static const unsigned TGT_TIOCGETC   = 0x40067412;
+    static const unsigned TGT_FIONREAD   = 0x4004667f;
+    static const unsigned TGT_TIOCISATTY = 0x2000745e;
+    static const unsigned TGT_TCGETS     = 0x402c7413;
+    static const unsigned TGT_TCGETA     = 0x40127417;
+    static const unsigned TGT_TCSETAW    = 0x80147419; // 2.6.15 kernel
     //@}
 
+    static bool
+    isTtyReq(unsigned req)
+    {
+        switch (req) {
+          case TGT_TIOCGETP:
+          case TGT_TIOCSETP:
+          case TGT_TIOCSETN:
+          case TGT_TIOCSETC:
+          case TGT_TIOCGETC:
+          case TGT_FIONREAD:
+          case TGT_TIOCISATTY:
+          case TGT_TCGETS:
+          case TGT_TCGETA:
+          case TGT_TCSETAW:
+            return true;
+          default:
+            return false;
+        }
+    }
+
     //@{
     /// For table().
     static const int TBL_SYSINFO = 12;
index 40d586aaffdf5b523752537a08681ce7f80efad9..55af574d38f93d5d24da849e9265cb51bbdd0c3f 100644 (file)
@@ -100,20 +100,6 @@ class ArmLinux : public Linux
     static const int TGT_RUSAGE_BOTH = -2;
     //@}
 
-    //@{
-    /// ioctl() command codes.
-    static const unsigned TIOCGETP_   = 0x5401;
-    static const unsigned TIOCSETP_   = 0x80067409;
-    static const unsigned TIOCSETN_   = 0x8006740a;
-    static const unsigned TIOCSETC_   = 0x80067411;
-    static const unsigned TIOCGETC_   = 0x40067412;
-    static const unsigned FIONREAD_   = 0x4004667f;
-    static const unsigned TIOCISATTY_ = 0x2000745e;
-    static const unsigned TIOCGETS_   = 0x402c7413;
-    static const unsigned TIOCGETA_   = 0x5405;
-    static const unsigned TCSETAW_    = 0x5407;     // 2.6.15 kernel
-    //@}
-
     /// For table().
     static const int TBL_SYSINFO = 12;
 
index 949cce8aac32d2028f0d66be59c77fa9dfe9f47a..85a647e3d79b9742bb606c38939904b50183d260 100644 (file)
@@ -92,18 +92,32 @@ class MipsLinux : public Linux
 
     //@{
     /// ioctl() command codes.
-    static const unsigned TIOCGETP_   = 0x7408;
-    static const unsigned TIOCSETP_   = 0x7409;
-    static const unsigned TIOCSETN_   = 0x740a;
-    static const unsigned TIOCSETC_   = 0x7411;
-    static const unsigned TIOCGETC_   = 0x7412;
-    static const unsigned FIONREAD_   = 0x467f;
-    static const unsigned TIOCISATTY_ = 0x5480;
-    static const unsigned TIOCGETS_   = 0x540d;
-    static const unsigned TIOCGETA_   = 0x7417;
-    static const unsigned TCSETAW_    = 0x5403; // 2.6.15 kernel
+    static const unsigned TGT_TCGETA     = 0x5401;
+    static const unsigned TGT_TCSETAW    = 0x5403;
+    static const unsigned TGT_TCGETS     = 0x540d;
+    static const unsigned TGT_FIONREAD   = 0x467f;
+    static const unsigned TGT_TIOCGETP   = 0x7408;
+    static const unsigned TGT_TIOCSETP   = 0x7409;
+    static const unsigned TGT_TIOCSETN   = 0x740a;
     //@}
 
+    static bool
+    isTtyReq(unsigned req)
+    {
+        switch (req) {
+          case TGT_TIOCGETP:
+          case TGT_TIOCSETP:
+          case TGT_TIOCSETN:
+          case TGT_FIONREAD:
+          case TGT_TCGETS:
+          case TGT_TCGETA:
+          case TGT_TCSETAW:
+            return true;
+          default:
+            return false;
+        }
+    }
+
     /// For table().
     static const int TBL_SYSINFO = 12;
 
index 45ca048a043ddb85335277c26b68e5659e659464..effb39277b1329b29b192fcfeedbcac2016efc69 100644 (file)
@@ -131,19 +131,34 @@ class PowerLinux : public Linux
 
     //@{
     /// ioctl() command codes.
-    /// These are for the 2.6.15 kernel. Some have changed for
-    /// later versions.
-    static const unsigned TIOCGETP_   = 0x40067408;
-    static const unsigned TIOCSETP_   = 0x80067409;
-    static const unsigned TIOCSETN_   = 0x8006740a;
-    static const unsigned TIOCSETC_   = 0x80067411;
-    static const unsigned TIOCGETC_   = 0x40067412;
-    static const unsigned FIONREAD_   = 0x4004667f;
-    static const unsigned TIOCISATTY_ = 0x2000745e;
-    static const unsigned TIOCGETS_   = 0x402c7413;
-    static const unsigned TIOCGETA_   = 0x40147417;
-    static const unsigned TCSETAW_    = 0x80147419;
+    static const unsigned TGT_TIOCGETP   = 0x40067408;
+    static const unsigned TGT_TIOCSETP   = 0x80067409;
+    static const unsigned TGT_TIOCSETN   = 0x8006740a;
+    static const unsigned TGT_TIOCSETC   = 0x80067411;
+    static const unsigned TGT_TIOCGETC   = 0x40067412;
+    static const unsigned TGT_FIONREAD   = 0x4004667f;
+    static const unsigned TGT_TCGETS     = 0x402c7413;
+    static const unsigned TGT_TCGETA     = 0x40127417;
+    static const unsigned TGT_TCSETAW    = 0x80147419; // 2.6.15 kernel
     //@}
+
+    static bool
+    isTtyReq(unsigned req)
+    {
+        switch (req) {
+          case TGT_TIOCGETP:
+          case TGT_TIOCSETP:
+          case TGT_TIOCSETN:
+          case TGT_TIOCSETC:
+          case TGT_TIOCGETC:
+          case TGT_TCGETS:
+          case TGT_TCGETA:
+          case TGT_TCSETAW:
+            return true;
+          default:
+            return false;
+        }
+    }
 };
 
 #endif // __ARCH_POWER_LINUX_LINUX_HH__
index 8ac4088126b82597d942f79f11bc77cff2032f3d..7b708cbcb2eea4e7d11ec41e2e67776c71bd112b 100644 (file)
@@ -94,6 +94,35 @@ class SparcLinux : public Linux
         uint64_t mem_unit;  /* Memory unit size in bytes */
     } tgt_sysinfo;
 
+    //@{
+    /// ioctl() command codes.
+    /// These were calculated using the SPARC Linux headers on an x86
+    /// machine and thus may not be correct.  It would be good to
+    /// verify/update these values on an actual SPARC Linux machine.
+    static const unsigned TGT_TCGETA    = 0x40125401;
+    static const unsigned TGT_TCSETAW   = 0x80125403;
+    static const unsigned TGT_TCGETS    = 0x40385408;
+    static const unsigned TGT_FIONREAD  = 0x4004667f;
+    static const unsigned TGT_TIOCGETP  = 0x40067408;
+    static const unsigned TGT_TIOCSETP  = 0x80067409;
+    static const unsigned TGT_TIOCSETN  = 0x8006740a;
+    //@}
+
+    static bool
+    isTtyReq(unsigned req)
+    {
+        switch (req) {
+          case TGT_TIOCGETP:
+          case TGT_TIOCSETP:
+          case TGT_TIOCSETN:
+          case TGT_TCGETS:
+          case TGT_TCGETA:
+          case TGT_TCSETAW:
+            return true;
+          default:
+            return false;
+        }
+    }
 };
 
 class Sparc32Linux : public SparcLinux
index e9322f5eb775307762d247523a5b16d0cbf5d86c..322868ee1cfa3a9d71d2fe887bea192039a53872 100644 (file)
@@ -229,7 +229,7 @@ SyscallDesc X86_64LinuxProcess::syscallDescs[] = {
     /*  13 */ SyscallDesc("rt_sigaction", ignoreFunc),
     /*  14 */ SyscallDesc("rt_sigprocmask", ignoreFunc),
     /*  15 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
-    /*  16 */ SyscallDesc("ioctl", unimplementedFunc),
+    /*  16 */ SyscallDesc("ioctl", ioctlFunc<X86Linux64>),
     /*  17 */ SyscallDesc("pread64", unimplementedFunc),
     /*  18 */ SyscallDesc("pwrite64", unimplementedFunc),
     /*  19 */ SyscallDesc("readv", unimplementedFunc),
@@ -546,7 +546,7 @@ SyscallDesc I386LinuxProcess::syscallDescs[] = {
     /*  51 */ SyscallDesc("acct", unimplementedFunc),
     /*  52 */ SyscallDesc("umount2", unimplementedFunc),
     /*  53 */ SyscallDesc("lock", unimplementedFunc),
-    /*  54 */ SyscallDesc("ioctl", unimplementedFunc),
+    /*  54 */ SyscallDesc("ioctl", ioctlFunc<X86Linux32>),
     /*  55 */ SyscallDesc("fcntl", unimplementedFunc),
     /*  56 */ SyscallDesc("mpx", unimplementedFunc),
     /*  57 */ SyscallDesc("setpgid", unimplementedFunc),
index 5721e5a58c6f5230b5866f97157db85988387565..bc3da60e4f7a856d7c0bc82b3eff1fc76d16f2ae 100644 (file)
@@ -147,6 +147,32 @@ class Linux : public OperatingSystem
         uint64_t iov_len;
     };
 
+    //@{
+    /// ioctl() command codes.
+    static const unsigned TGT_TCGETS     = 0x5401;
+    static const unsigned TGT_TCGETA     = 0x5405;
+    static const unsigned TGT_TCSETAW    = 0x5407;
+    static const unsigned TGT_FIONREAD   = 0x541B;
+    //@}
+
+    /// Return true for the ioctl codes for which we return ENOTTY
+    /// *without* printing a warning, since we know that ENOTTY is the
+    /// correct thing to return (and not just a sign that we don't
+    /// recognize the ioctl code.
+    static bool
+    isTtyReq(unsigned req)
+    {
+        switch (req) {
+          case TGT_FIONREAD:
+          case TGT_TCSETAW:
+          case TGT_TCGETS:
+          case TGT_TCGETA:
+            return true;
+          default:
+            return false;
+        }
+    }
+
 
     /// For getrusage().
     struct rusage {
index c174fde576ce4252f04379d66a89572ad48fa044..0627d8d91f22f69513385a4da085e28d87eced89 100644 (file)
@@ -567,7 +567,8 @@ copyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr,
 
 /// Target ioctl() handler.  For the most part, programs call ioctl()
 /// only to find out if their stdout is a tty, to determine whether to
-/// do line or block buffering.
+/// do line or block buffering.  We always claim that output fds are
+/// not TTYs to provide repeatable results.
 template <class OS>
 SyscallReturn
 ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
@@ -584,22 +585,13 @@ ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
         return -EBADF;
     }
 
-    switch (req) {
-      case OS::TIOCISATTY_:
-      case OS::TIOCGETP_:
-      case OS::TIOCSETP_:
-      case OS::TIOCSETN_:
-      case OS::TIOCSETC_:
-      case OS::TIOCGETC_:
-      case OS::TIOCGETS_:
-      case OS::TIOCGETA_:
-      case OS::TCSETAW_:
+    if (OS::isTtyReq(req)) {
         return -ENOTTY;
-
-      default:
-        fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n",
-              fd, req, tc->pcState());
     }
+
+    warn("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n",
+         fd, req, tc->pcState());
+    return -ENOTTY;
 }
 
 /// Target open() handler.