simplify mmap2 handling

Instead of forcing every arch that doesn't implement __NR_mmap2 to
opt-out of this code path, move the special cases first, and then
change this fallback to rely upon the existence of __NR_mmap2.

Change-Id: Ib2167e5fdfa3302dcef7e98c26c8e02f177be658
Reviewed-on: https://chromium-review.googlesource.com/c/linux-syscall-support/+/1237435
Reviewed-by: Ian Barkley-Yeung <iby@chromium.org>
diff --git a/linux_syscall_support.h b/linux_syscall_support.h
index aab95e6..620383c 100644
--- a/linux_syscall_support.h
+++ b/linux_syscall_support.h
@@ -4637,7 +4637,7 @@
       LSS_REG(2, buf);
       LSS_BODY(void*, mmap2, "0"(__r2));
     }
-#else
+#elif defined(__NR_mmap2)
     #define __NR__mmap2 __NR_mmap2
     LSS_INLINE _syscall6(void*, _mmap2,            void*, s,
                          size_t,                   l, int,               p,
@@ -4745,21 +4745,7 @@
       return rc;
     }
   #endif
-  #if defined(__i386__) ||                                                    \
-      defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) ||                     \
-     (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) ||                   \
-      defined(__PPC__) ||                                                     \
-     (defined(__s390__) && !defined(__s390x__))
-    /* On these architectures, implement mmap() with mmap2(). */
-    LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
-                                    int64_t o) {
-      if (o % 4096) {
-        LSS_ERRNO = EINVAL;
-        return (void *) -1;
-      }
-      return LSS_NAME(_mmap2)(s, l, p, f, d, (o / 4096));
-    }
-  #elif defined(__s390x__)
+  #if defined(__s390x__)
     /* On s390x, mmap() arguments are passed in memory. */
     LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
                                     int64_t o) {
@@ -4777,6 +4763,16 @@
                                LSS_SYSCALL_ARG(p), LSS_SYSCALL_ARG(f),
                                LSS_SYSCALL_ARG(d), (uint64_t)(o));
     }
+  #elif defined(__NR_mmap2)
+    /* On these architectures, implement mmap() with mmap2(). */
+    LSS_INLINE void* LSS_NAME(mmap)(void *s, size_t l, int p, int f, int d,
+                                    int64_t o) {
+      if (o % 4096) {
+        LSS_ERRNO = EINVAL;
+        return (void *) -1;
+      }
+      return LSS_NAME(_mmap2)(s, l, p, f, d, (o / 4096));
+    }
   #else
     /* Remaining 64-bit architectures. */
     LSS_INLINE _syscall6(void*, mmap, void*, addr, size_t, length, int, prot,
diff --git a/tests/Makefile b/tests/Makefile
index a4e2f38..8f4d217 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -44,6 +44,7 @@
 	getitimer \
 	getrandom \
 	lstat \
+	mmap \
 	setitimer \
 	sigaction \
 	sigtimedwait \
diff --git a/tests/mmap.c b/tests/mmap.c
new file mode 100644
index 0000000..8a4e520
--- /dev/null
+++ b/tests/mmap.c
@@ -0,0 +1,49 @@
+/* Copyright 2018, Google Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "test_skel.h"
+
+int main(int argc, char *argv[]) {
+  int fd;
+  void *ptr;
+
+  fd = sys_open("/dev/zero", O_RDONLY, 0);
+  assert(fd != -1);
+
+  ptr = sys_mmap(NULL, 0x1000, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+  assert(ptr != MAP_FAILED);
+
+  assert(*(unsigned long *)ptr == 0);
+
+  assert(sys_munmap(ptr, 0x1000) == 0);
+
+  assert(sys_close(fd) == 0);
+
+  return 0;
+}