Merge "Remove some legacy declarations from <math.h>."
diff --git a/docs/status.md b/docs/status.md
index c119439..cd40e2c 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -9,6 +9,7 @@
 New libc functions in P:
   * `__freading`/`__fwriting` (completing <stdio_ext.h>)
   * `endhostent`/endnetent`/`endprotoent`/`getnetent`/`getprotoent`/`sethostent`/`setnetent`/`setprotoent` (completing <netdb.h>)
+  * `fexecve`
   * `getentropy`/`getrandom` (adding <sys/random.h>)
   * `getlogin_r`
   * `glob`/`globfree` (adding <glob.h>)
@@ -16,6 +17,7 @@
   * `iconv`/`iconv_close`/`iconv_open` (adding <iconv.h>)
   * `pthread_setschedprio`
   * <spawn.h>
+  * `swab`
   * `syncfs`
 
 New libc functions in O:
@@ -71,10 +73,6 @@
 aio_return
 aio_suspend
 aio_write
-fexecve
-fmtmsg
-getdate
-getdate_err
 lio_listio
 pthread_attr_getinheritsched
 pthread_attr_setinheritsched
@@ -91,8 +89,6 @@
 pthread_setcancelstate
 pthread_setcanceltype
 pthread_testcancel
-sockatmark
-swab
 wordexp
 wordfree
 ```
diff --git a/libc/Android.bp b/libc/Android.bp
index 81135ea..2e5ec00 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1534,6 +1534,7 @@
         "bionic/strings_l.cpp",
         "bionic/strsignal.cpp",
         "bionic/strtold.cpp",
+        "bionic/swab.cpp",
         "bionic/symlink.cpp",
         "bionic/sync_file_range.cpp",
         "bionic/sys_msg.cpp",
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
index 9cbff11..d7581dd 100644
--- a/libc/bionic/__libc_init_main_thread.cpp
+++ b/libc/bionic/__libc_init_main_thread.cpp
@@ -31,6 +31,7 @@
 #include "private/KernelArgumentBlock.h"
 #include "private/bionic_arc4random.h"
 #include "private/bionic_auxv.h"
+#include "private/bionic_defs.h"
 #include "private/bionic_globals.h"
 #include "private/bionic_ssp.h"
 #include "pthread_internal.h"
@@ -58,6 +59,7 @@
 // -fno-stack-protector because it's responsible for setting up the main
 // thread's TLS (which stack protector relies on).
 
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
 void __libc_init_main_thread(KernelArgumentBlock& args) {
   __libc_auxv = args.auxv;
 #if defined(__i386__)
diff --git a/libc/bionic/android_set_abort_message.cpp b/libc/bionic/android_set_abort_message.cpp
index 8c80c5a..268c4f3 100644
--- a/libc/bionic/android_set_abort_message.cpp
+++ b/libc/bionic/android_set_abort_message.cpp
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <sys/mman.h>
 
+#include "private/bionic_defs.h"
 #include "private/ScopedPthreadMutexLocker.h"
 
 static pthread_mutex_t g_abort_msg_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -43,6 +44,7 @@
 
 abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common.
 
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
 void android_set_abort_message(const char* msg) {
   ScopedPthreadMutexLocker locker(&g_abort_msg_lock);
 
diff --git a/libc/bionic/exec.cpp b/libc/bionic/exec.cpp
index 2001106..1cf3a58 100644
--- a/libc/bionic/exec.cpp
+++ b/libc/bionic/exec.cpp
@@ -39,6 +39,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#include "private/FdPath.h"
+
 extern "C" char** environ;
 
 enum ExecVariant { kIsExecL, kIsExecLE, kIsExecLP };
@@ -170,3 +172,10 @@
   if (saw_EACCES) errno = EACCES;
   return -1;
 }
+
+int fexecve(int fd, char* const* argv, char* const* envp) {
+  // execveat with AT_EMPTY_PATH (>= 3.19) seems to offer no advantages.
+  execve(FdPath(fd).c_str(), argv, envp);
+  if (errno == ENOENT) errno = EBADF;
+  return -1;
+}
diff --git a/libc/bionic/fchmod.cpp b/libc/bionic/fchmod.cpp
index ace8c6b..a486aae 100644
--- a/libc/bionic/fchmod.cpp
+++ b/libc/bionic/fchmod.cpp
@@ -33,13 +33,14 @@
 #include <unistd.h>
 #include <stdio.h>
 
+#include "private/FdPath.h"
+
 extern "C" int ___fchmod(int, mode_t);
 
 int fchmod(int fd, mode_t mode) {
   int saved_errno = errno;
   int result = ___fchmod(fd, mode);
-
-  if ((result == 0) || (errno != EBADF)) {
+  if (result == 0 || errno != EBADF) {
     return result;
   }
 
@@ -52,16 +53,14 @@
   // on an O_PATH file descriptor, and "man open" documents fchmod
   // on O_PATH file descriptors as returning EBADF.
   int fd_flag = fcntl(fd, F_GETFL);
-  if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
+  if (fd_flag == -1 || (fd_flag & O_PATH) == 0) {
     errno = EBADF;
     return -1;
   }
 
-  char buf[40];
-  snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
   errno = saved_errno;
-  result = chmod(buf, mode);
-  if ((result == -1) && (errno == ELOOP)) {
+  result = chmod(FdPath(fd).c_str(), mode);
+  if (result == -1 && errno == ELOOP) {
     // Linux does not support changing the mode of a symlink.
     // For fchmodat(AT_SYMLINK_NOFOLLOW), POSIX requires a return
     // value of ENOTSUP. Assume that's true here too.
diff --git a/libc/bionic/fgetxattr.cpp b/libc/bionic/fgetxattr.cpp
index 6d999bf..38b7ac3 100644
--- a/libc/bionic/fgetxattr.cpp
+++ b/libc/bionic/fgetxattr.cpp
@@ -33,13 +33,15 @@
 #include <fcntl.h>
 #include <stdio.h>
 
+#include "private/FdPath.h"
+
 extern "C" ssize_t ___fgetxattr(int, const char*, void*, size_t);
 
 ssize_t fgetxattr(int fd, const char *name, void *value, size_t size) {
   int saved_errno = errno;
   ssize_t result = ___fgetxattr(fd, name, value, size);
 
-  if ((result != -1) || (errno != EBADF)) {
+  if (result != -1 || errno != EBADF) {
     return result;
   }
 
@@ -47,13 +49,11 @@
   // may not directly support fgetxattr() on such a file descriptor.
   // Use /proc/self/fd instead to emulate this support.
   int fd_flag = fcntl(fd, F_GETFL);
-  if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
+  if (fd_flag == -1 || (fd_flag & O_PATH) == 0) {
     errno = EBADF;
     return -1;
   }
 
-  char buf[40];
-  snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
   errno = saved_errno;
-  return getxattr(buf, name, value, size);
+  return getxattr(FdPath(fd).c_str(), name, value, size);
 }
diff --git a/libc/bionic/flistxattr.cpp b/libc/bionic/flistxattr.cpp
index 05a96d2..8ad9b85 100644
--- a/libc/bionic/flistxattr.cpp
+++ b/libc/bionic/flistxattr.cpp
@@ -33,13 +33,14 @@
 #include <fcntl.h>
 #include <stdio.h>
 
+#include "private/FdPath.h"
+
 extern "C" ssize_t ___flistxattr(int, char*, size_t);
 
 ssize_t flistxattr(int fd, char *list, size_t size) {
   int saved_errno = errno;
   ssize_t result = ___flistxattr(fd, list, size);
-
-  if ((result != -1) || (errno != EBADF)) {
+  if (result != -1 || errno != EBADF) {
     return result;
   }
 
@@ -47,13 +48,11 @@
   // may not directly support fgetxattr() on such a file descriptor.
   // Use /proc/self/fd instead to emulate this support.
   int fd_flag = fcntl(fd, F_GETFL);
-  if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
+  if (fd_flag == -1 || (fd_flag & O_PATH) == 0) {
     errno = EBADF;
     return -1;
   }
 
-  char buf[40];
-  snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
   errno = saved_errno;
-  return listxattr(buf, list, size);
+  return listxattr(FdPath(fd).c_str(), list, size);
 }
diff --git a/libc/bionic/fsetxattr.cpp b/libc/bionic/fsetxattr.cpp
index 6d2e868..9ad0c76 100644
--- a/libc/bionic/fsetxattr.cpp
+++ b/libc/bionic/fsetxattr.cpp
@@ -33,13 +33,14 @@
 #include <fcntl.h>
 #include <stdio.h>
 
+#include "private/FdPath.h"
+
 extern "C" int ___fsetxattr(int, const char*, const void*, size_t, int);
 
 int fsetxattr(int fd, const char* name, const void* value, size_t size, int flags) {
   int saved_errno = errno;
   int result = ___fsetxattr(fd, name, value, size, flags);
-
-  if ((result == 0) || (errno != EBADF)) {
+  if (result == 0 || errno != EBADF) {
     return result;
   }
 
@@ -47,13 +48,11 @@
   // may not directly support fsetxattr() on such a file descriptor.
   // Use /proc/self/fd instead to emulate this support.
   int fd_flag = fcntl(fd, F_GETFL);
-  if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
+  if (fd_flag == -1 || (fd_flag & O_PATH) == 0) {
     errno = EBADF;
     return -1;
   }
 
-  char buf[40];
-  snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
   errno = saved_errno;
-  return setxattr(buf, name, value, size, flags);
+  return setxattr(FdPath(fd).c_str(), name, value, size, flags);
 }
diff --git a/libc/bionic/pty.cpp b/libc/bionic/pty.cpp
index bdabf36..599cbd2 100644
--- a/libc/bionic/pty.cpp
+++ b/libc/bionic/pty.cpp
@@ -37,6 +37,7 @@
 #include <utmp.h>
 
 #include "bionic/pthread_internal.h"
+#include "private/FdPath.h"
 
 int getpt() {
   return posix_openpt(O_RDWR|O_NOCTTY);
@@ -94,10 +95,7 @@
     return errno;
   }
 
-  char path[64];
-  snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
-
-  ssize_t count = readlink(path, buf, len);
+  ssize_t count = readlink(FdPath(fd).c_str(), buf, len);
   if (count == -1) {
     return errno;
   }
diff --git a/libc/bionic/swab.cpp b/libc/bionic/swab.cpp
new file mode 100644
index 0000000..bc53ba4
--- /dev/null
+++ b/libc/bionic/swab.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * 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.
+ *
+ * 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 <unistd.h>
+
+void swab(const void* void_src, void* void_dst, ssize_t byte_count) {
+  const uint8_t* src = static_cast<const uint8_t*>(void_src);
+  uint8_t* dst = static_cast<uint8_t*>(void_dst);
+  while (byte_count > 1) {
+    uint8_t x = *src++;
+    uint8_t y = *src++;
+    *dst++ = y;
+    *dst++ = x;
+    byte_count -= 2;
+  }
+}
diff --git a/libc/include/bits/posix_limits.h b/libc/include/bits/posix_limits.h
index e5846d6..2688cc5 100644
--- a/libc/include/bits/posix_limits.h
+++ b/libc/include/bits/posix_limits.h
@@ -70,7 +70,7 @@
 #define _POSIX_SHELL 1 /* system. */
 #define _POSIX_SPAWN __BIONIC_POSIX_FEATURE_SINCE(28) /* <spawn.h> */
 #define _POSIX_SPIN_LOCKS __BIONIC_POSIX_FEATURE_SINCE(24) /* pthread_spin_*. */
-#define _POSIX_SPORADIC_SERVER _POSIX_VERSION /* sched_setparam/sched_setscheduler. */
+#define _POSIX_SPORADIC_SERVER __BIONIC_POSIX_FEATURE_MISSING /* No SCHED_SPORADIC. */
 #define _POSIX_SYNCHRONIZED_IO _POSIX_VERSION
 #define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION /* Strictly, we're missing the deprecated pthread_attr_getstackaddr/pthread_attr_setstackaddr, but we do have pthread_attr_getstack/pthread_attr_setstack. */
 #define _POSIX_THREAD_ATTR_STACKSIZE _POSIX_VERSION /* pthread_attr_getstack/pthread_attr_getstacksize/pthread_attr_setstack/pthread_attr_setstacksize. */
@@ -82,7 +82,7 @@
 #define _POSIX_THREAD_ROBUST_PRIO_INHERIT __BIONIC_POSIX_FEATURE_MISSING
 #define _POSIX_THREAD_ROBUST_PRIO_PROTECT __BIONIC_POSIX_FEATURE_MISSING
 #define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION
-#define _POSIX_THREAD_SPORADIC_SERVER _POSIX_VERSION /* sched_setparam/sched_setscheduler. */
+#define _POSIX_THREAD_SPORADIC_SERVER __BIONIC_POSIX_FEATURE_MISSING /* No SCHED_SPORADIC. */
 #define _POSIX_THREADS _POSIX_VERSION /* Strictly, pthread_cancel/pthread_testcancel are missing. */
 #define _POSIX_TIMEOUTS __BIONIC_POSIX_FEATURE_SINCE(21) /* pthread_mutex_timedlock arrived late. */
 #define _POSIX_TIMERS _POSIX_VERSION /* clock_getres/clock_gettime/clock_settime/nanosleep/timer_create/timer_delete/timer_gettime/timer_getoverrun/timer_settime. */
@@ -94,6 +94,15 @@
 
 #define _POSIX_VDISABLE             '\0'
 
+#define _POSIX2_C_BIND              _POSIX_VERSION
+#define _POSIX2_C_DEV               __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_CHAR_TERM           _POSIX_VERSION
+#define _POSIX2_FORT_DEV            __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_FORT_RUN            __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_LOCALEDEF           __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_SW_DEV              __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX2_UPE                 __BIONIC_POSIX_FEATURE_MISSING
+
 #if defined(__LP64__)
 #define _POSIX_V7_ILP32_OFF32       -1
 #define _POSIX_V7_ILP32_OFFBIG      -1
@@ -106,16 +115,26 @@
 #define _POSIX_V7_LPBIG_OFFBIG      -1
 #endif
 
+#define _XOPEN_CRYPT                __BIONIC_POSIX_FEATURE_MISSING
+#define _XOPEN_ENH_I18N             1
+#define _XOPEN_LEGACY               __BIONIC_POSIX_FEATURE_MISSING
+#define _XOPEN_REALTIME             1
+#define _XOPEN_REALTIME_THREADS     1
+#define _XOPEN_SHM                  1
+#define _XOPEN_STREAMS              __BIONIC_POSIX_FEATURE_MISSING
+#define _XOPEN_UNIX                 1
+
 /* Minimum values for other maxima. These numbers are simply lower bounds mandated by POSIX. */
-/* Any constant values here other than -1 or 200809L are explicitly specified by POSIX.1-2008. */
+/* The constant values here are explicitly specified by POSIX, not implementation dependent. */
 #define _POSIX_AIO_LISTIO_MAX       2
 #define _POSIX_AIO_MAX              1
 #define _POSIX_ARG_MAX              4096
 #define _POSIX_CHILD_MAX            25
+#define _POSIX_CLOCKRES_MIN         20000000
 #define _POSIX_DELAYTIMER_MAX       32
 #define _POSIX_HOST_NAME_MAX        255
 #define _POSIX_LINK_MAX             8
-#define _POSIX_LOGIN_NAME_MAX       9  /* includes trailing NUL */
+#define _POSIX_LOGIN_NAME_MAX       9
 #define _POSIX_MAX_CANON            255
 #define _POSIX_MAX_INPUT            255
 #define _POSIX_MQ_OPEN_MAX          8
@@ -126,45 +145,36 @@
 #define _POSIX_PATH_MAX             256
 #define _POSIX_PIPE_BUF             512
 #define _POSIX_RE_DUP_MAX           255
+#define _POSIX_RTSIG_MAX            8
 #define _POSIX_SEM_NSEMS_MAX        256
 #define _POSIX_SEM_VALUE_MAX        32767
 #define _POSIX_SIGQUEUE_MAX         32
 #define _POSIX_SSIZE_MAX            32767
 #define _POSIX_STREAM_MAX           8
+#define _POSIX_SS_REPL_MAX          4
 #define _POSIX_SYMLINK_MAX          255
 #define _POSIX_SYMLOOP_MAX          8
 #define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
 #define _POSIX_THREAD_KEYS_MAX      128
 #define _POSIX_THREAD_THREADS_MAX   64
 #define _POSIX_TIMER_MAX            32
+#define _POSIX_TRACE_EVENT_NAME_MAX 30
 #define _POSIX_TRACE_NAME_MAX       8
 #define _POSIX_TRACE_SYS_MAX        8
 #define _POSIX_TRACE_USER_EVENT_MAX 32
-#define _POSIX_TTY_NAME_MAX         9  /* includes trailing NUL */
+#define _POSIX_TTY_NAME_MAX         9
 #define _POSIX_TZNAME_MAX           6
 #define _POSIX2_BC_BASE_MAX         99
 #define _POSIX2_BC_DIM_MAX          2048
 #define _POSIX2_BC_SCALE_MAX        99
 #define _POSIX2_BC_STRING_MAX       1000
 #define _POSIX2_CHARCLASS_NAME_MAX  14
-#define _POSIX2_CHAR_TERM           -1  /* not implemented */
 #define _POSIX2_COLL_WEIGHTS_MAX    2
-#define _POSIX2_C_BIND              _POSIX_VERSION
-#define _POSIX2_C_DEV               -1  /* c dev utilities not implemented */
 #define _POSIX2_EXPR_NEST_MAX       32
 #define _POSIX2_LINE_MAX            2048
-#define _POSIX2_LOCALEDEF           -1  /* localedef utilitiy not implemented */
-#define _POSIX2_RE_DUP_MAX          _POSIX_RE_DUP_MAX
-#define _POSIX2_SW_DEV              -1  /* software dev utilities not implemented */
-#define _POSIX2_UPE                 -1  /* user portability utilities not implemented */
-
-#define _XOPEN_ENH_I18N             -1  /* we don't support internationalization in the C library */
-#define _XOPEN_CRYPT                -1  /* don't support X/Open Encryption */
+#define _POSIX2_RE_DUP_MAX          255
 #define _XOPEN_IOV_MAX              16
-#define _XOPEN_LEGACY               -1  /* not support all */
-#define _XOPEN_REALTIME             -1 /* we don't support all these functions */
-#define _XOPEN_REALTIME_THREADS     -1  /* same here */
-#define _XOPEN_SHM                  -1
-#define _XOPEN_UNIX                 1
+#define _XOPEN_NAME_MAX             255
+#define _XOPEN_PATH_MAX             1024
 
 #endif
diff --git a/libc/include/limits.h b/libc/include/limits.h
index 4384f6f..48e7ea9 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -61,6 +61,7 @@
 #else
 # define LONG_BIT 32
 #endif
+#define WORD_BIT 32
 
 #define	SCHAR_MAX	0x7f		/* max value for a signed char */
 #define SCHAR_MIN	(-0x7f-1)	/* min value for a signed char */
@@ -130,6 +131,8 @@
 
 #define MB_LEN_MAX 4
 
+#define NZERO 20
+
 #define IOV_MAX 1024
 #define SEM_VALUE_MAX 0x3fffffff
 
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 9cfb918..c60cf80 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -98,6 +98,7 @@
 int execlp(const char* __file, const char* __arg0, ...) __attribute__((__sentinel__));
 int execle(const char* __path, const char* __arg0, ... /*,  char* const* __envp */)
     __attribute__((__sentinel__(1)));
+int fexecve(int __fd, char* const* __argv, char* const* __envp) __INTRODUCED_IN_FUTURE;
 
 int nice(int __incr);
 
@@ -246,6 +247,8 @@
 int getdomainname(char* __buf, size_t __buf_size) __INTRODUCED_IN(26);
 int setdomainname(const char* __name, size_t __n) __INTRODUCED_IN(26);
 
+void swab(const void* __src, void* __dst, ssize_t __byte_count) __INTRODUCED_IN_FUTURE;
+
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
 #include <bits/fortify/unistd.h>
 #endif
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 981dd59..6e1015a 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1325,6 +1325,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    fexecve;
     getentropy;
     getnetent;
     getprotoent;
@@ -1366,6 +1367,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    swab;
     syncfs;
 } LIBC_O;
 
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 29c5235..b88ecd0 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1245,6 +1245,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    fexecve;
     getentropy;
     getnetent;
     getprotoent;
@@ -1286,6 +1287,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    swab;
     syncfs;
 } LIBC_O;
 
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index eafbbd7..4fc6535 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1350,6 +1350,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    fexecve;
     getentropy;
     getnetent;
     getprotoent;
@@ -1391,6 +1392,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    swab;
     syncfs;
 } LIBC_O;
 
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index a32131f..360af09 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1309,6 +1309,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    fexecve;
     getentropy;
     getnetent;
     getprotoent;
@@ -1350,6 +1351,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    swab;
     syncfs;
 } LIBC_O;
 
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 29c5235..b88ecd0 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1245,6 +1245,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    fexecve;
     getentropy;
     getnetent;
     getprotoent;
@@ -1286,6 +1287,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    swab;
     syncfs;
 } LIBC_O;
 
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index f1308ea..04ff514 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1307,6 +1307,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    fexecve;
     getentropy;
     getnetent;
     getprotoent;
@@ -1348,6 +1349,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    swab;
     syncfs;
 } LIBC_O;
 
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 29c5235..b88ecd0 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1245,6 +1245,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    fexecve;
     getentropy;
     getnetent;
     getprotoent;
@@ -1286,6 +1287,7 @@
     sethostent;
     setnetent;
     setprotoent;
+    swab;
     syncfs;
 } LIBC_O;
 
diff --git a/libc/private/CachedProperty.h b/libc/private/CachedProperty.h
index 417a855..84ead01 100644
--- a/libc/private/CachedProperty.h
+++ b/libc/private/CachedProperty.h
@@ -42,7 +42,9 @@
     : property_name_(property_name),
       prop_info_(nullptr),
       cached_area_serial_(0),
-      cached_property_serial_(0) {
+      cached_property_serial_(0),
+      is_read_only_(strncmp(property_name, "ro.", 3) == 0),
+      read_only_property_(nullptr) {
     cached_value_[0] = '\0';
   }
 
@@ -76,7 +78,9 @@
         __system_property_read_callback(prop_info_, &CachedProperty::Callback, this);
       }
     }
-
+    if (is_read_only_ && read_only_property_ != nullptr) {
+      return read_only_property_;
+    }
     return cached_value_;
   }
 
@@ -86,10 +90,18 @@
   uint32_t cached_area_serial_;
   uint32_t cached_property_serial_;
   char cached_value_[PROP_VALUE_MAX];
+  bool is_read_only_;
+  const char* read_only_property_;
 
   static void Callback(void* data, const char*, const char* value, uint32_t serial) {
     CachedProperty* instance = reinterpret_cast<CachedProperty*>(data);
     instance->cached_property_serial_ = serial;
-    strcpy(instance->cached_value_, value);
+    // Read only properties can be larger than PROP_VALUE_MAX, but also never change value or
+    // location, thus we return the pointer from the shared memory directly.
+    if (instance->is_read_only_) {
+      instance->read_only_property_ = value;
+    } else {
+      strlcpy(instance->cached_value_, value, PROP_VALUE_MAX);
+    }
   }
 };
diff --git a/libc/private/FdPath.h b/libc/private/FdPath.h
new file mode 100644
index 0000000..4a6a2d5
--- /dev/null
+++ b/libc/private/FdPath.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+class FdPath {
+ public:
+  explicit FdPath(int fd) {
+    snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
+  }
+
+  const char* c_str() {
+    return buf;
+  }
+
+ private:
+  char buf[40];
+};
diff --git a/libc/private/bionic_defs.h b/libc/private/bionic_defs.h
new file mode 100644
index 0000000..d9e016c
--- /dev/null
+++ b/libc/private/bionic_defs.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+
+#ifndef __BIONIC_PRIVATE_BIONIC_DEFS_H_
+#define __BIONIC_PRIVATE_BIONIC_DEFS_H_
+
+/*
+ * This label is used to mark libc/libdl symbols that may need to be replaced
+ * by native bridge implementation.
+ */
+#define __BIONIC_WEAK_FOR_NATIVE_BRIDGE __attribute__((__weak__, __noinline__))
+
+#endif /* __BIONIC_PRIVATE_BIONIC_DEFS_H_ */
diff --git a/libc/tools/check-symbols-glibc.py b/libc/tools/check-symbols-glibc.py
index 7657925..4de0181 100755
--- a/libc/tools/check-symbols-glibc.py
+++ b/libc/tools/check-symbols-glibc.py
@@ -184,20 +184,24 @@
 ])
 # POSIX has some stuff that's too stupid for words (a64l) or not actually
 # implemented in glibc unless you count always failing with ENOSYS as
-# being implemented (fattach).
+# being implemented (fattach). Other stuff (fmtmsg) isn't used in any
+# codebase I have access to, internal or external.
 in_posix_and_glibc_but_dead_or_useless = set([
   'a64l', # obsolete
   'confstr', # obsolete
   'endutxent', # no utmp on Android
-  'fattach', # obsolete
-  'fdetach', # obsolete
+  'fattach', # <stropts.h> marked obsolescent
+  'fdetach', # <stropts.h> marked obsolescent
+  'fmtmsg', # unused
+  'getdate', # unused
+  'getdate_err', # unused
   'gethostid', # obsolete
-  'getmsg', # obsolete
-  'getpmsg', # obsolete
+  'getmsg', # <stropts.h> marked obsolescent
+  'getpmsg', # <stropts.h> marked obsolescent
   'getutxent', # no utmp on Android
   'getutxid', # no utmp on Android
   'getutxline', # no utmp on Android
-  'isastream', # obsolete
+  'isastream', # <stropts.h> marked obsolescent
   'l64a', # obsolete
   'mq_close', # disallowed by SELinux
   'mq_getattr', # disallowed by SELinux
@@ -211,15 +215,16 @@
   'mq_unlink', # disallowed by SELinux
   'pthread_getconcurrency', # marked obsolescent
   'pthread_setconcurrency', # marked obsolescent
-  'putmsg', # obsolete
-  'putpmsg', # obsolete
+  'putmsg', # <stropts.h> marked obsolescent
+  'putpmsg', # <stropts.h> marked obsolescent
   'pututxline', # no utmp on Android
   'shm_open', # disallowed by SELinux
   'shm_unlink', # disallowed by SELinux
   'setutxent', # no utmp on Android
+  'sockatmark', # obsolete (https://tools.ietf.org/html/rfc6093)
   'strfmon', # icu4c
   'strfmon_l', # icu4c
-  'ulimit', # obsolete
+  'ulimit', # <ulimit.h> marked obsolescent
 ])
 
 posix = posix - in_posix_and_glibc_but_dead_or_useless
diff --git a/libdl/libdl.cpp b/libdl/libdl.cpp
index 97cdeb4..c834088 100644
--- a/libdl/libdl.cpp
+++ b/libdl/libdl.cpp
@@ -17,7 +17,6 @@
 #include <dlfcn.h>
 #include <link.h>
 #include <stdlib.h>
-#include <stdbool.h>
 #include <android/dlext.h>
 
 // These functions are exported by the loader
diff --git a/linker/linker.cpp b/linker/linker.cpp
index f6ca430..ec92c92 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1621,11 +1621,13 @@
   }
 
   // Step 4-3: Add the new global group members to all the linked namespaces
-  for (auto si : new_global_group_members) {
+  if (namespaces != nullptr) {
     for (auto linked_ns : *namespaces) {
-      if (si->get_primary_namespace() != linked_ns) {
-        linked_ns->add_soinfo(si);
-        si->add_secondary_namespace(linked_ns);
+      for (auto si : new_global_group_members) {
+        if (si->get_primary_namespace() != linked_ns) {
+          linked_ns->add_soinfo(si);
+          si->add_secondary_namespace(linked_ns);
+        }
       }
     }
   }
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 4799739..46cd60c 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -129,9 +129,8 @@
   if (path != nullptr) {
     // We have historically supported ':' as well as ' ' in LD_PRELOAD.
     g_ld_preload_names = android::base::Split(path, " :");
-    std::remove_if(g_ld_preload_names.begin(),
-                   g_ld_preload_names.end(),
-                   [] (const std::string& s) { return s.empty(); });
+    g_ld_preload_names.erase(std::remove_if(g_ld_preload_names.begin(), g_ld_preload_names.end(),
+                                            [](const std::string& s) { return s.empty(); }));
   }
 }
 
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index 2133a2c..d56b017 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -181,12 +181,8 @@
 #endif
 
 #if defined(__BIONIC__)
-static bool is_user_build() {
-  std::string build_type = android::base::GetProperty("ro.build.type", "user");
-  if (build_type == "userdebug" || build_type == "eng") {
-    return false;
-  }
-  return true;
+static bool is_debuggable_build() {
+  return android::base::GetBoolProperty("ro.debuggable", false);
 }
 #endif
 
@@ -194,7 +190,7 @@
 // whose search paths include the 'ns2/' subdir.
 TEST(dl, exec_with_ld_config_file) {
 #if defined(__BIONIC__)
-  if (is_user_build()) {
+  if (!is_debuggable_build()) {
     // LD_CONFIG_FILE is not supported on user build
     return;
   }
@@ -216,7 +212,7 @@
 // additional namespaces other than the default namespace.
 TEST(dl, exec_with_ld_config_file_with_ld_preload) {
 #if defined(__BIONIC__)
-  if (is_user_build()) {
+  if (!is_debuggable_build()) {
     // LD_CONFIG_FILE is not supported on user build
     return;
   }
@@ -244,7 +240,7 @@
     // This test is only for CTS.
     return;
   }
-  if (!is_user_build()) {
+  if (is_debuggable_build()) {
     // Skip the test for non production devices
     return;
   }
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index adc5ee4..697b84a 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1496,4 +1496,9 @@
   ASSERT_SUBSTR(expected_dlerror.c_str(), dlerror());
 }
 
+TEST(dlfcn, dlopen_df_1_global) {
+  void* handle = dlopen("libtest_dlopen_df_1_global.so", RTLD_NOW);
+  ASSERT_TRUE(handle != nullptr) << dlerror();
+}
+
 #endif
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 858f2b1..ba0b1aa 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -377,6 +377,26 @@
 }
 
 // -----------------------------------------------------------------------------
+// Library with DF_1_GLOBAL which will be dlopened
+// (note: libdl_test_df_1_global above will be included in DT_NEEDED)
+// -----------------------------------------------------------------------------
+cc_test_library {
+    name: "libtest_dlopen_df_1_global",
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["dl_df_1_global_dummy.cpp"],
+    ldflags: ["-Wl,-z,global"],
+
+    target: {
+        host: {
+            // TODO (dimitry): host ld.gold does not yet support -z global
+            // remove this line once it is updated.
+            ldflags: ["-fuse-ld=bfd"],
+        },
+    },
+}
+
+
+// -----------------------------------------------------------------------------
 // Library with weak function
 // -----------------------------------------------------------------------------
 cc_test_library {
diff --git a/tests/libs/dl_df_1_global_dummy.cpp b/tests/libs/dl_df_1_global_dummy.cpp
new file mode 100644
index 0000000..423247c
--- /dev/null
+++ b/tests/libs/dl_df_1_global_dummy.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+extern "C" int foo() {
+  return 1;
+}
diff --git a/tests/limits_test.cpp b/tests/limits_test.cpp
index 1d48ffe..ed42dbb 100644
--- a/tests/limits_test.cpp
+++ b/tests/limits_test.cpp
@@ -19,9 +19,9 @@
 #include <limits.h>
 
 TEST(limits, macros) {
-#if CHAR_BIT != 8
-#error Insane CHAR_BIT
-#endif
+  ASSERT_EQ(8, CHAR_BIT);
+  ASSERT_EQ(static_cast<int>(sizeof(int)), WORD_BIT);
+  ASSERT_EQ(20, NZERO);
 #if !defined(MB_LEN_MAX)
 #error MB_LEN_MAX
 #endif
diff --git a/tests/linux_swab_test.cpp b/tests/linux_swab_test.cpp
index 6b964dc..ffd4072 100644
--- a/tests/linux_swab_test.cpp
+++ b/tests/linux_swab_test.cpp
@@ -21,7 +21,7 @@
 // This test makes sure that references to all of the kernel swab
 // macros/inline functions that are exported work properly.
 // Verifies that any kernel header updates do not break these macros.
-TEST(swab, fswa) {
+TEST(linux_swab, smoke) {
   EXPECT_EQ(0x3412U, __swab16(0x1234));
   EXPECT_EQ(0x78563412U, __swab32(0x12345678U));
   EXPECT_EQ(0xbaefcdab78563412ULL, __swab64(0x12345678abcdefbaULL));
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index ced0315..3143c50 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -686,104 +686,131 @@
   ASSERT_TRUE(rc > 0 && powerof2(rc));
 }
 
-
-TEST(UNISTD_TEST, _POSIX_macros_smoke) {
+TEST(UNISTD_TEST, _POSIX_constants) {
   // Make a tight verification of _POSIX_* / _POSIX2_* / _XOPEN_* macros, to prevent change by mistake.
   // Verify according to POSIX.1-2008.
   EXPECT_EQ(200809L, _POSIX_VERSION);
 
+  EXPECT_EQ(2, _POSIX_AIO_LISTIO_MAX);
+  EXPECT_EQ(1, _POSIX_AIO_MAX);
+  EXPECT_EQ(4096, _POSIX_ARG_MAX);
+  EXPECT_EQ(25, _POSIX_CHILD_MAX);
+  EXPECT_EQ(20000000, _POSIX_CLOCKRES_MIN);
+  EXPECT_EQ(32, _POSIX_DELAYTIMER_MAX);
+  EXPECT_EQ(255, _POSIX_HOST_NAME_MAX);
+  EXPECT_EQ(8, _POSIX_LINK_MAX);
+  EXPECT_EQ(9, _POSIX_LOGIN_NAME_MAX);
+  EXPECT_EQ(255, _POSIX_MAX_CANON);
+  EXPECT_EQ(255, _POSIX_MAX_INPUT);
+  EXPECT_EQ(8, _POSIX_MQ_OPEN_MAX);
+  EXPECT_EQ(32, _POSIX_MQ_PRIO_MAX);
+  EXPECT_EQ(14, _POSIX_NAME_MAX);
+  EXPECT_EQ(8, _POSIX_NGROUPS_MAX);
+  EXPECT_EQ(20, _POSIX_OPEN_MAX);
+  EXPECT_EQ(256, _POSIX_PATH_MAX);
+  EXPECT_EQ(512, _POSIX_PIPE_BUF);
+  EXPECT_EQ(255, _POSIX_RE_DUP_MAX);
+  EXPECT_EQ(8, _POSIX_RTSIG_MAX);
+  EXPECT_EQ(256, _POSIX_SEM_NSEMS_MAX);
+  EXPECT_EQ(32767, _POSIX_SEM_VALUE_MAX);
+  EXPECT_EQ(32, _POSIX_SIGQUEUE_MAX);
+  EXPECT_EQ(32767, _POSIX_SSIZE_MAX);
+  EXPECT_EQ(8, _POSIX_STREAM_MAX);
+#if !defined(__GLIBC__)
+  EXPECT_EQ(4, _POSIX_SS_REPL_MAX);
+#endif
+  EXPECT_EQ(255, _POSIX_SYMLINK_MAX);
+  EXPECT_EQ(8, _POSIX_SYMLOOP_MAX);
+  EXPECT_EQ(4, _POSIX_THREAD_DESTRUCTOR_ITERATIONS);
+  EXPECT_EQ(128, _POSIX_THREAD_KEYS_MAX);
+  EXPECT_EQ(64, _POSIX_THREAD_THREADS_MAX);
+  EXPECT_EQ(32, _POSIX_TIMER_MAX);
+#if !defined(__GLIBC__)
+  EXPECT_EQ(30, _POSIX_TRACE_EVENT_NAME_MAX);
+  EXPECT_EQ(8, _POSIX_TRACE_NAME_MAX);
+  EXPECT_EQ(8, _POSIX_TRACE_SYS_MAX);
+  EXPECT_EQ(32, _POSIX_TRACE_USER_EVENT_MAX);
+#endif
+  EXPECT_EQ(9, _POSIX_TTY_NAME_MAX);
+  EXPECT_EQ(6, _POSIX_TZNAME_MAX);
+  EXPECT_EQ(99, _POSIX2_BC_BASE_MAX);
+  EXPECT_EQ(2048, _POSIX2_BC_DIM_MAX);
+  EXPECT_EQ(99, _POSIX2_BC_SCALE_MAX);
+  EXPECT_EQ(1000, _POSIX2_BC_STRING_MAX);
+  EXPECT_EQ(14, _POSIX2_CHARCLASS_NAME_MAX);
+  EXPECT_EQ(2, _POSIX2_COLL_WEIGHTS_MAX);
+  EXPECT_EQ(32, _POSIX2_EXPR_NEST_MAX);
+  EXPECT_EQ(2048, _POSIX2_LINE_MAX);
+  EXPECT_EQ(255, _POSIX2_RE_DUP_MAX);
+
+  EXPECT_EQ(16, _XOPEN_IOV_MAX);
+#if !defined(__GLIBC__)
+  EXPECT_EQ(255, _XOPEN_NAME_MAX);
+  EXPECT_EQ(1024, _XOPEN_PATH_MAX);
+#endif
+}
+
+TEST(UNISTD_TEST, _POSIX_options) {
   EXPECT_EQ(_POSIX_VERSION, _POSIX_ADVISORY_INFO);
-  EXPECT_GT(_POSIX_AIO_LISTIO_MAX, 0);
-  EXPECT_GT(_POSIX_AIO_MAX, 0);
-  EXPECT_GT(_POSIX_ARG_MAX, 0);
   EXPECT_GT(_POSIX_BARRIERS, 0);
   EXPECT_GT(_POSIX_SPIN_LOCKS, 0);
-  EXPECT_GT(_POSIX_CHILD_MAX, 0);
   EXPECT_NE(_POSIX_CHOWN_RESTRICTED, -1);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_CLOCK_SELECTION);
+#if !defined(__GLIBC__) // glibc supports ancient kernels.
   EXPECT_EQ(_POSIX_VERSION, _POSIX_CPUTIME);
-  EXPECT_GT(_POSIX_DELAYTIMER_MAX, 0);
+#endif
   EXPECT_EQ(_POSIX_VERSION, _POSIX_FSYNC);
-  EXPECT_GT(_POSIX_HOST_NAME_MAX, 0);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_IPV6);
   EXPECT_GT(_POSIX_JOB_CONTROL, 0);
-  EXPECT_GT(_POSIX_LINK_MAX, 0);
-  EXPECT_GT(_POSIX_LOGIN_NAME_MAX, 0);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_MAPPED_FILES);
-  EXPECT_GT(_POSIX_MAX_CANON, 0);
-  EXPECT_GT(_POSIX_MAX_INPUT, 0);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_MEMLOCK);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_MEMLOCK_RANGE);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_MEMORY_PROTECTION);
+#if !defined(__GLIBC__) // glibc supports ancient kernels.
   EXPECT_EQ(_POSIX_VERSION, _POSIX_MONOTONIC_CLOCK);
-  EXPECT_GT(_POSIX_MQ_OPEN_MAX, 0);
-  EXPECT_GT(_POSIX_MQ_PRIO_MAX, 0);
-  EXPECT_GT(_POSIX_NAME_MAX, 0);
-  EXPECT_GT(_POSIX_NGROUPS_MAX, 0);
+#endif
   EXPECT_GT(_POSIX_NO_TRUNC, 0);
-  EXPECT_GT(_POSIX_OPEN_MAX, 0);
-  EXPECT_GT(_POSIX_PATH_MAX, 0);
-  EXPECT_GT(_POSIX_PIPE_BUF, 0);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_PRIORITY_SCHEDULING);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_RAW_SOCKETS);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_READER_WRITER_LOCKS);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_REALTIME_SIGNALS);
   EXPECT_GT(_POSIX_REGEXP, 0);
-  EXPECT_GT(_POSIX_RE_DUP_MAX, 0);
   EXPECT_GT(_POSIX_SAVED_IDS, 0);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_SEMAPHORES);
-  EXPECT_GT(_POSIX_SEM_NSEMS_MAX, 0);
-  EXPECT_GT(_POSIX_SEM_VALUE_MAX, 0);
   EXPECT_GT(_POSIX_SHELL, 0);
-  EXPECT_GT(_POSIX_SIGQUEUE_MAX, 0);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_SPAWN);
-  EXPECT_EQ(_POSIX_VERSION, _POSIX_SPORADIC_SERVER);
-  EXPECT_GT(_POSIX_SSIZE_MAX, 0);
-  EXPECT_GT(_POSIX_STREAM_MAX, 0);
-  EXPECT_GT(_POSIX_SYMLINK_MAX, 0);
-  EXPECT_GT(_POSIX_SYMLOOP_MAX, 0);
+  EXPECT_EQ(-1, _POSIX_SPORADIC_SERVER);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_SYNCHRONIZED_IO);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_THREADS);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_ATTR_STACKADDR);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_ATTR_STACKSIZE);
+#if !defined(__GLIBC__) // glibc supports ancient kernels.
   EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_CPUTIME);
-  EXPECT_GT(_POSIX_THREAD_DESTRUCTOR_ITERATIONS, 0);
-  EXPECT_EQ(_POSIX_THREAD_KEYS_MAX, 128);
+#endif
   EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIORITY_SCHEDULING);
-  EXPECT_EQ(-1, _POSIX_THREAD_PRIO_INHERIT);
-  EXPECT_EQ(-1, _POSIX_THREAD_PRIO_PROTECT);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PROCESS_SHARED);
   EXPECT_EQ(-1, _POSIX_THREAD_ROBUST_PRIO_PROTECT);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_SAFE_FUNCTIONS);
-  EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_SPORADIC_SERVER);
-  EXPECT_GT(_POSIX_THREAD_THREADS_MAX, 0);
+  EXPECT_EQ(-1, _POSIX_THREAD_SPORADIC_SERVER);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_TIMEOUTS);
   EXPECT_EQ(_POSIX_VERSION, _POSIX_TIMERS);
-  EXPECT_GT(_POSIX_TIMER_MAX, 0);
   EXPECT_EQ(-1, _POSIX_TRACE);
   EXPECT_EQ(-1, _POSIX_TRACE_EVENT_FILTER);
   EXPECT_EQ(-1, _POSIX_TRACE_INHERIT);
   EXPECT_EQ(-1, _POSIX_TRACE_LOG);
-  EXPECT_GT(_POSIX_TTY_NAME_MAX, 0);
   EXPECT_EQ(-1, _POSIX_TYPED_MEMORY_OBJECTS);
-  EXPECT_GT(_POSIX_TZNAME_MAX, 0);
   EXPECT_NE(-1, _POSIX_VDISABLE);
 
   EXPECT_EQ(_POSIX_VERSION, _POSIX2_VERSION);
-  EXPECT_GT(_POSIX2_BC_BASE_MAX, 0);
-  EXPECT_GT(_POSIX2_BC_DIM_MAX, 0);
-  EXPECT_GT(_POSIX2_BC_SCALE_MAX, 0);
-  EXPECT_GT(_POSIX2_BC_STRING_MAX, 0);
-  EXPECT_GT(_POSIX2_CHARCLASS_NAME_MAX, 0);
-  EXPECT_GT(_POSIX2_COLL_WEIGHTS_MAX, 0);
   EXPECT_EQ(_POSIX_VERSION, _POSIX2_C_BIND);
-  EXPECT_GT(_POSIX2_EXPR_NEST_MAX, 0);
-  EXPECT_GT(_POSIX2_LINE_MAX, 0);
-  EXPECT_GT(_POSIX2_RE_DUP_MAX, 0);
+  EXPECT_EQ(_POSIX_VERSION, _POSIX2_CHAR_TERM);
 
   EXPECT_EQ(700, _XOPEN_VERSION);
-  EXPECT_GT(_XOPEN_IOV_MAX, 0);
-  EXPECT_GT(_XOPEN_UNIX, 0);
+  EXPECT_EQ(1, _XOPEN_ENH_I18N);
+  EXPECT_EQ(1, _XOPEN_REALTIME);
+  EXPECT_EQ(1, _XOPEN_REALTIME_THREADS);
+  EXPECT_EQ(1, _XOPEN_SHM);
+  EXPECT_EQ(1, _XOPEN_UNIX);
 
 #if defined(__BIONIC__)
   // These tests only pass on bionic, as bionic and glibc has different support on these macros.
@@ -792,21 +819,20 @@
   EXPECT_EQ(-1, _POSIX_MESSAGE_PASSING);
   EXPECT_EQ(-1, _POSIX_PRIORITIZED_IO);
   EXPECT_EQ(-1, _POSIX_SHARED_MEMORY_OBJECTS);
+  EXPECT_EQ(-1, _POSIX_THREAD_PRIO_INHERIT);
+  EXPECT_EQ(-1, _POSIX_THREAD_PRIO_PROTECT);
   EXPECT_EQ(-1, _POSIX_THREAD_ROBUST_PRIO_INHERIT);
 
-  EXPECT_EQ(-1, _POSIX2_CHAR_TERM);
   EXPECT_EQ(-1, _POSIX2_C_DEV);
+  EXPECT_EQ(-1, _POSIX2_FORT_DEV);
+  EXPECT_EQ(-1, _POSIX2_FORT_RUN);
   EXPECT_EQ(-1, _POSIX2_LOCALEDEF);
   EXPECT_EQ(-1, _POSIX2_SW_DEV);
   EXPECT_EQ(-1, _POSIX2_UPE);
 
-  EXPECT_EQ(-1, _XOPEN_ENH_I18N);
   EXPECT_EQ(-1, _XOPEN_CRYPT);
   EXPECT_EQ(-1, _XOPEN_LEGACY);
-  EXPECT_EQ(-1, _XOPEN_REALTIME);
-  EXPECT_EQ(-1, _XOPEN_REALTIME_THREADS);
-  EXPECT_EQ(-1, _XOPEN_SHM);
-
+  EXPECT_EQ(-1, _XOPEN_STREAMS);
 #endif // defined(__BIONIC__)
 }
 
@@ -916,11 +942,11 @@
   VERIFY_SYSCONF_POSITIVE(_SC_REGEXP);
   VERIFY_SYSCONF_POSITIVE(_SC_SHELL);
   VERIFY_SYSCONF_POSIX_VERSION(_SC_SPAWN);
-  VERIFY_SYSCONF_POSIX_VERSION(_SC_SPORADIC_SERVER);
+  VERIFY_SYSCONF_UNSUPPORTED(_SC_SPORADIC_SERVER);
   VERIFY_SYSCONF_POSITIVE(_SC_SYMLOOP_MAX);
   VERIFY_SYSCONF_POSIX_VERSION(_SC_THREAD_CPUTIME);
   VERIFY_SYSCONF_POSIX_VERSION(_SC_THREAD_PROCESS_SHARED);
-  VERIFY_SYSCONF_POSIX_VERSION(_SC_THREAD_SPORADIC_SERVER);
+  VERIFY_SYSCONF_UNSUPPORTED(_SC_THREAD_SPORADIC_SERVER);
   VERIFY_SYSCONF_POSIX_VERSION(_SC_TIMEOUTS);
   VERIFY_SYSCONF_UNSUPPORTED(_SC_TRACE);
   VERIFY_SYSCONF_UNSUPPORTED(_SC_TRACE_EVENT_FILTER);
@@ -1376,9 +1402,87 @@
               "<unknown>: usage: run-as");
 }
 
+TEST(UNISTD_TEST, fexecve_failure) {
+  ExecTestHelper eth;
+  errno = 0;
+  int fd = open("/", O_RDONLY);
+  ASSERT_NE(-1, fd);
+  ASSERT_EQ(-1, fexecve(fd, eth.GetArgs(), eth.GetEnv()));
+  ASSERT_EQ(EACCES, errno);
+  close(fd);
+}
+
+TEST(UNISTD_TEST, fexecve_bad_fd) {
+  ExecTestHelper eth;
+  errno = 0;
+  ASSERT_EQ(-1, fexecve(-1, eth.GetArgs(), eth.GetEnv()));
+  ASSERT_EQ(EBADF, errno);
+}
+
+TEST(UNISTD_TEST, fexecve_args) {
+  // Test basic argument passing.
+  int echo_fd = open(BIN_DIR "echo", O_RDONLY | O_CLOEXEC);
+  ASSERT_NE(-1, echo_fd);
+  ExecTestHelper eth;
+  eth.SetArgs({"echo", "hello", "world", nullptr});
+  eth.Run([&]() { fexecve(echo_fd, eth.GetArgs(), eth.GetEnv()); }, 0, "hello world\n");
+  close(echo_fd);
+
+  // Test environment variable setting too.
+  int printenv_fd = open(BIN_DIR "printenv", O_RDONLY | O_CLOEXEC);
+  ASSERT_NE(-1, printenv_fd);
+  eth.SetArgs({"printenv", nullptr});
+  eth.SetEnv({"A=B", nullptr});
+  eth.Run([&]() { fexecve(printenv_fd, eth.GetArgs(), eth.GetEnv()); }, 0, "A=B\n");
+  close(printenv_fd);
+}
+
 TEST(UNISTD_TEST, getlogin_r) {
   char buf[LOGIN_NAME_MAX] = {};
   EXPECT_EQ(ERANGE, getlogin_r(buf, 0));
   EXPECT_EQ(0, getlogin_r(buf, sizeof(buf)));
   EXPECT_STREQ(getlogin(), buf);
 }
+
+TEST(UNISTD_TEST, swab) {
+  // POSIX: "The swab() function shall copy nbytes bytes, which are pointed to by src,
+  // to the object pointed to by dest, exchanging adjacent bytes."
+  char buf[BUFSIZ];
+  memset(buf, 'x', sizeof(buf));
+  swab("ehll oowlr\0d", buf, 12);
+  ASSERT_STREQ("hello world", buf);
+}
+
+TEST(UNISTD_TEST, swab_odd_byte_count) {
+  // POSIX: "If nbytes is odd, swab() copies and exchanges nbytes-1 bytes and the disposition
+  // of the last byte is unspecified."
+  // ...but it seems unreasonable to not just leave the last byte alone.
+  char buf[BUFSIZ];
+  memset(buf, 'x', sizeof(buf));
+  swab("012345", buf, 3);
+  ASSERT_EQ('1', buf[0]);
+  ASSERT_EQ('0', buf[1]);
+  ASSERT_EQ('x', buf[2]);
+}
+
+TEST(UNISTD_TEST, swab_overlap) {
+  // POSIX: "If copying takes place between objects that overlap, the behavior is undefined."
+  // ...but it seems unreasonable to not just do the right thing.
+  char buf[] = "012345";
+  swab(buf, buf, 4);
+  ASSERT_EQ('1', buf[0]);
+  ASSERT_EQ('0', buf[1]);
+  ASSERT_EQ('3', buf[2]);
+  ASSERT_EQ('2', buf[3]);
+  ASSERT_EQ('4', buf[4]);
+  ASSERT_EQ('5', buf[5]);
+  ASSERT_EQ(0, buf[6]);
+}
+
+TEST(UNISTD_TEST, swab_negative_byte_count) {
+  // POSIX: "If nbytes is negative, swab() does nothing."
+  char buf[BUFSIZ];
+  memset(buf, 'x', sizeof(buf));
+  swab("hello", buf, -1);
+  ASSERT_EQ('x', buf[0]);
+}