Merge "Removing the kuser_helper elf note from building"
diff --git a/benchmarks/Android.bp b/benchmarks/Android.bp
index 12f4940..3f95aa1 100644
--- a/benchmarks/Android.bp
+++ b/benchmarks/Android.bp
@@ -25,6 +25,7 @@
         "-Wunused",
     ],
     srcs: [
+        "atomic_benchmark.cpp",
         "math_benchmark.cpp",
         "property_benchmark.cpp",
         "pthread_benchmark.cpp",
diff --git a/benchmarks/atomic_benchmark.cpp b/benchmarks/atomic_benchmark.cpp
new file mode 100644
index 0000000..66a0120
--- /dev/null
+++ b/benchmarks/atomic_benchmark.cpp
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+// Our goal is to measure the cost of various C++ atomic operations.
+// Android doesn't really control those. But since some of these operations can be quite
+// expensive, this may be useful input for development of higher level code.
+// Expected mappings from C++ atomics to hardware primitives can be found at
+// http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html .
+
+#include <benchmark/benchmark.h>
+#include <atomic>
+#include <mutex>
+
+// We time atomic operations separated by a volatile (not atomic!) increment.  This ensures
+// that the compiler emits memory instructions (e.g. load or store) prior to any fence or the
+// like.  That in turn ensures that the CPU has outstanding memory operations when the fence
+// is executed.
+
+// In most respects, we compute best case values. Since there is only one thread, there are no
+// coherence misses.
+
+// We assume that the compiler is not smart enough to optimize away fences in a single-threaded
+// program. If that changes, we'll need to add a second thread.
+
+volatile unsigned counter;
+
+std::atomic<int> test_loc(0);
+
+volatile unsigned sink;
+
+std::mutex mtx;
+
+void BM_empty(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    ++counter;
+  }
+}
+BENCHMARK(BM_empty);
+
+static void BM_load_relaxed(benchmark::State& state) {
+  unsigned result = 0;
+  while (state.KeepRunning()) {
+    result += test_loc.load(std::memory_order_relaxed);
+    ++counter;
+  }
+  sink = result;
+}
+BENCHMARK(BM_load_relaxed);
+
+static void BM_load_acquire(benchmark::State& state) {
+  unsigned result = 0;
+  while (state.KeepRunning()) {
+    result += test_loc.load(std::memory_order_acquire);
+    ++counter;
+  }
+  sink = result;
+}
+BENCHMARK(BM_load_acquire);
+
+static void BM_store_release(benchmark::State& state) {
+  int i = counter;
+  while (state.KeepRunning()) {
+    test_loc.store(++i, std::memory_order_release);
+    ++counter;
+  }
+}
+BENCHMARK(BM_store_release);
+
+static void BM_store_seq_cst(benchmark::State& state) {
+  int i = counter;
+  while (state.KeepRunning()) {
+    test_loc.store(++i, std::memory_order_seq_cst);
+    ++counter;
+  }
+}
+BENCHMARK(BM_store_seq_cst);
+
+static void BM_fetch_add_relaxed(benchmark::State& state) {
+  unsigned result = 0;
+  while (state.KeepRunning()) {
+    result += test_loc.fetch_add(1, std::memory_order_relaxed);
+    ++counter;
+  }
+  sink = result;
+}
+BENCHMARK(BM_fetch_add_relaxed);
+
+static void BM_fetch_add_seq_cst(benchmark::State& state) {
+  unsigned result = 0;
+  while (state.KeepRunning()) {
+    result += test_loc.fetch_add(1, std::memory_order_seq_cst);
+    ++counter;
+  }
+  sink = result;
+}
+BENCHMARK(BM_fetch_add_seq_cst);
+
+// The fence benchmarks include a relaxed load to make it much harder to optimize away
+// the fence.
+
+static void BM_acquire_fence(benchmark::State& state) {
+  unsigned result = 0;
+  while (state.KeepRunning()) {
+    result += test_loc.load(std::memory_order_relaxed);
+    std::atomic_thread_fence(std::memory_order_acquire);
+    ++counter;
+  }
+  sink = result;
+}
+BENCHMARK(BM_acquire_fence);
+
+static void BM_seq_cst_fence(benchmark::State& state) {
+  unsigned result = 0;
+  while (state.KeepRunning()) {
+    result += test_loc.load(std::memory_order_relaxed);
+    std::atomic_thread_fence(std::memory_order_seq_cst);
+    ++counter;
+  }
+  sink = result;
+}
+BENCHMARK(BM_seq_cst_fence);
+
+// For comparison, also throw in a critical section version:
+
+static void BM_fetch_add_cs(benchmark::State& state) {
+  unsigned result = 0;
+  while (state.KeepRunning()) {
+    {
+      std::lock_guard<std::mutex> _(mtx);
+      result += ++counter;
+    }
+  }
+  sink = result;
+}
+BENCHMARK(BM_fetch_add_cs);
diff --git a/libc/arch-arm/generic/bionic/strlen.c b/libc/arch-arm/generic/bionic/strlen.c
index b9f3a2a..f6b9209 100644
--- a/libc/arch-arm/generic/bionic/strlen.c
+++ b/libc/arch-arm/generic/bionic/strlen.c
@@ -29,7 +29,7 @@
 #include <string.h>
 #include <stdint.h>
 
-size_t strlen(const char *s)
+size_t strlen(const char *s) __overloadable
 {
     __builtin_prefetch(s);
     __builtin_prefetch(s+32);
diff --git a/libc/arch-mips/string/mips_strlen.c b/libc/arch-mips/string/mips_strlen.c
index 45fc4b4..f1465f2 100644
--- a/libc/arch-mips/string/mips_strlen.c
+++ b/libc/arch-mips/string/mips_strlen.c
@@ -49,7 +49,7 @@
 #endif
 
 size_t
-strlen (const char *_a)
+strlen (const char *_a) __overloadable
 {
   int cnt = 0;
   unsigned x;
diff --git a/libc/arch-mips/string/strlen.c b/libc/arch-mips/string/strlen.c
index 7e0e27b..488e3c8 100644
--- a/libc/arch-mips/string/strlen.c
+++ b/libc/arch-mips/string/strlen.c
@@ -32,7 +32,7 @@
 #include <string.h>
 
 size_t
-strlen(const char *str)
+strlen(const char *str) __overloadable
 {
 	const char *s;
 
diff --git a/libc/bionic/fortify.cpp b/libc/bionic/fortify.cpp
index cf50664..117de48 100644
--- a/libc/bionic/fortify.cpp
+++ b/libc/bionic/fortify.cpp
@@ -71,6 +71,8 @@
 
 #include "private/bionic_fortify.h"
 
+struct __bionic_zero_size_is_okay_t __bionic_zero_size_is_okay;
+
 //
 // For more details see:
 //   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
diff --git a/libc/bionic/getcwd.cpp b/libc/bionic/getcwd.cpp
index bcd6a57..c2a7e23 100644
--- a/libc/bionic/getcwd.cpp
+++ b/libc/bionic/getcwd.cpp
@@ -34,7 +34,7 @@
 
 extern "C" int __getcwd(char* buf, size_t size);
 
-char* getcwd(char* buf, size_t size) {
+char* getcwd(char* buf, size_t size) __overloadable {
   // You can't specify size 0 unless you're asking us to allocate for you.
   if (buf != NULL && size == 0) {
     errno = EINVAL;
diff --git a/libc/bionic/poll.cpp b/libc/bionic/poll.cpp
index 23ef90a..eded56a 100644
--- a/libc/bionic/poll.cpp
+++ b/libc/bionic/poll.cpp
@@ -37,7 +37,7 @@
 extern "C" int __ppoll(pollfd*, unsigned int, timespec*, const kernel_sigset_t*, size_t);
 extern "C" int __pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*);
 
-int poll(pollfd* fds, nfds_t fd_count, int ms) {
+int poll(pollfd* fds, nfds_t fd_count, int ms) __overloadable {
   timespec ts;
   timespec* ts_ptr = NULL;
   if (ms >= 0) {
@@ -47,7 +47,7 @@
   return __ppoll(fds, fd_count, ts_ptr, NULL, 0);
 }
 
-int ppoll(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset_t* ss) {
+int ppoll(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset_t* ss) __overloadable {
   timespec mutable_ts;
   timespec* mutable_ts_ptr = NULL;
   if (ts != NULL) {
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index 94ea153..88bcc78 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -67,9 +67,10 @@
 
 int creat(const char*, mode_t);
 int creat64(const char*, mode_t) __INTRODUCED_IN(21);
-int openat(int, const char*, int, ...);
+int openat(int, const char*, int, ...) __overloadable
+        __RENAME_CLANG(openat);
 int openat64(int, const char*, int, ...) __INTRODUCED_IN(21);
-int open(const char*, int, ...);
+int open(const char*, int, ...) __overloadable __RENAME_CLANG(open);
 int open64(const char*, int, ...) __INTRODUCED_IN(21);
 ssize_t splice(int, off64_t*, int, off64_t*, size_t, unsigned int) __INTRODUCED_IN(21);
 ssize_t tee(int, int, size_t, unsigned int) __INTRODUCED_IN(21);
@@ -94,15 +95,71 @@
 #endif
 
 int __open_2(const char*, int) __INTRODUCED_IN(17);
-int __open_real(const char*, int, ...) __RENAME(open);
 int __openat_2(int, const char*, int) __INTRODUCED_IN(17);
+/*
+ * These are the easiest way to call the real open even in clang FORTIFY.
+ */
+int __open_real(const char*, int, ...) __RENAME(open);
 int __openat_real(int, const char*, int, ...) __RENAME(openat);
-__errordecl(__creat_missing_mode, "called with O_CREAT, but missing mode");
-__errordecl(__creat_too_many_args, "too many arguments");
+
 
 #if defined(__BIONIC_FORTIFY)
+#define __open_too_many_args_error "too many arguments"
+#define __open_too_few_args_error "called with O_CREAT, but missing mode"
+#if defined(__clang__)
 
-#if !defined(__clang__)
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+int open(const char* pathname, int flags, mode_t modes, ...) __overloadable
+        __errorattr(__open_too_many_args_error);
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+int open(const char* pathname, int flags) __overloadable
+        __enable_if(flags & O_CREAT, __open_too_few_args_error)
+        __errorattr(__open_too_few_args_error);
+
+/*
+ * pass_object_size serves two purposes here, neither of which involve __bos: it
+ * disqualifies this function from having its address taken (so &open works),
+ * and it makes overload resolution prefer open(const char *, int) over
+ * open(const char *, int, ...).
+ */
+__BIONIC_FORTIFY_INLINE
+int open(const char* const __pass_object_size pathname,
+         int flags) __overloadable {
+    return __open_2(pathname, flags);
+}
+
+__BIONIC_FORTIFY_INLINE
+int open(const char* const __pass_object_size pathname, int flags, mode_t modes)
+        __overloadable {
+    return __open_real(pathname, flags, modes);
+}
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+int openat(int dirfd, const char* pathname, int flags) __overloadable
+        __enable_if(flags & O_CREAT, __open_too_few_args_error)
+        __errorattr(__open_too_few_args_error);
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+int openat(int dirfd, const char* pathname, int flags, mode_t modes, ...)
+        __overloadable
+        __errorattr(__open_too_many_args_error);
+
+__BIONIC_FORTIFY_INLINE
+int openat(int dirfd, const char* const __pass_object_size pathname,
+           int flags) __overloadable {
+    return __openat_2(dirfd, pathname, flags);
+}
+
+__BIONIC_FORTIFY_INLINE
+int openat(int dirfd, const char* const __pass_object_size pathname, int flags,
+           mode_t modes) __overloadable {
+    return __openat_real(dirfd, pathname, flags, modes);
+}
+
+#else /* defined(__clang__) */
+__errordecl(__creat_missing_mode, __open_too_few_args_error);
+__errordecl(__creat_too_many_args, __open_too_many_args_error);
 
 __BIONIC_FORTIFY_INLINE
 int open(const char* pathname, int flags, ...) {
@@ -142,8 +199,10 @@
     return __openat_real(dirfd, pathname, flags, __builtin_va_arg_pack());
 }
 
-#endif /* !defined(__clang__) */
+#endif /* defined(__clang__) */
 
+#undef __open_too_many_args_error
+#undef __open_too_few_args_error
 #endif /* defined(__BIONIC_FORTIFY) */
 
 __END_DECLS
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index 7452e53..752ee72 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -24,7 +24,12 @@
 __BEGIN_DECLS
 
 #if defined(__clang__)
-#define __BIONIC_ALLOC_SIZE(...) /* clang doesn't support attribute alloc_size. */
+/* clang should support alloc_size in the nearish future. */
+#if __has_attribute(alloc_size)
+#error "We should enable alloc_size for clang."
+#else
+#define __BIONIC_ALLOC_SIZE(...)
+#endif
 #else
 #define __BIONIC_ALLOC_SIZE(...) __attribute__((__alloc_size__(__VA_ARGS__)))
 #endif
diff --git a/libc/include/poll.h b/libc/include/poll.h
index c4e62f9..3287a0c 100644
--- a/libc/include/poll.h
+++ b/libc/include/poll.h
@@ -38,27 +38,65 @@
 
 typedef unsigned int nfds_t;
 
-int poll(struct pollfd*, nfds_t, int);
-int ppoll(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*) __INTRODUCED_IN(21);
+int poll(struct pollfd*, nfds_t, int) __overloadable __RENAME_CLANG(poll);
+int ppoll(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*)
+        __overloadable __RENAME_CLANG(ppoll) __INTRODUCED_IN(21);
 
 int __poll_chk(struct pollfd*, nfds_t, int, size_t) __INTRODUCED_IN(23);
+int __ppoll_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*, size_t)
+  __INTRODUCED_IN(23);
+
+#if defined(__BIONIC_FORTIFY)
+#if __ANDROID_API__ >= __ANDROID_API_M__
+#if defined(__clang__)
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+int poll(struct pollfd* fds, nfds_t fd_count, int timeout) __overloadable
+        __enable_if(__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                    __bos(fds) < sizeof(*fds) * fd_count,
+                    "selected when there aren't fd_count fds")
+        __errorattr("too many fds specified");
+
+__BIONIC_FORTIFY_INLINE
+int poll(struct pollfd* const fds __pass_object_size, nfds_t fd_count,
+        int timeout) __overloadable {
+  size_t bos_fds = __bos(fds);
+
+  if (bos_fds == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+      return __call_bypassing_fortify(poll)(fds, fd_count, timeout);
+  }
+
+  return __poll_chk(fds, fd_count, timeout, bos_fds);
+}
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+int ppoll(struct pollfd* fds, nfds_t fd_count, const struct timespec* timeout,
+          const sigset_t* mask)  __overloadable
+        __enable_if(__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                    __bos(fds) < sizeof(*fds) * fd_count,
+                    "selected when there aren't fd_count fds")
+        __errorattr("too many fds specified");
+
+__BIONIC_FORTIFY_INLINE
+int ppoll(struct pollfd* const fds __pass_object_size, nfds_t fd_count,
+          const struct timespec* timeout, const sigset_t* mask) __overloadable {
+  size_t bos_fds = __bos(fds);
+
+  if (bos_fds == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+      return __call_bypassing_fortify(ppoll)(fds, fd_count, timeout, mask);
+  }
+
+  return __ppoll_chk(fds, fd_count, timeout, mask, bos_fds);
+}
+#else /* defined(__clang__) */
 int __poll_real(struct pollfd*, nfds_t, int) __RENAME(poll);
 __errordecl(__poll_too_small_error, "poll: pollfd array smaller than fd count");
 
-int __ppoll_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*, size_t)
-  __INTRODUCED_IN(23);
 int __ppoll_real(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*) __RENAME(ppoll)
   __INTRODUCED_IN(21);
 __errordecl(__ppoll_too_small_error, "ppoll: pollfd array smaller than fd count");
 
-#if defined(__BIONIC_FORTIFY)
-
-#if __ANDROID_API__ >= __ANDROID_API_M__
 __BIONIC_FORTIFY_INLINE
 int poll(struct pollfd* fds, nfds_t fd_count, int timeout) {
-#if defined(__clang__)
-  return __poll_chk(fds, fd_count, timeout, __bos(fds));
-#else
   if (__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE) {
     if (!__builtin_constant_p(fd_count)) {
       return __poll_chk(fds, fd_count, timeout, __bos(fds));
@@ -67,14 +105,11 @@
     }
   }
   return __poll_real(fds, fd_count, timeout);
-#endif
 }
 
 __BIONIC_FORTIFY_INLINE
-int ppoll(struct pollfd* fds, nfds_t fd_count, const struct timespec* timeout, const sigset_t* mask) {
-#if defined(__clang__)
-  return __ppoll_chk(fds, fd_count, timeout, mask, __bos(fds));
-#else
+int ppoll(struct pollfd* fds, nfds_t fd_count, const struct timespec* timeout,
+          const sigset_t* mask) {
   if (__bos(fds) != __BIONIC_FORTIFY_UNKNOWN_SIZE) {
     if (!__builtin_constant_p(fd_count)) {
       return __ppoll_chk(fds, fd_count, timeout, mask, __bos(fds));
@@ -83,11 +118,11 @@
     }
   }
   return __ppoll_real(fds, fd_count, timeout, mask);
-#endif
 }
-#endif /* __ANDROID_API__ >= __ANDROID_API_M__ */
 
-#endif
+#endif /* defined(__clang__) */
+#endif /* __ANDROID_API__ >= __ANDROID_API_M__ */
+#endif /* defined(__BIONIC_FORTIFY) */
 
 __END_DECLS
 
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 9125e4c..6a76da6 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -121,13 +121,16 @@
 int	 ferror(FILE *);
 int	 fflush(FILE *);
 int	 fgetc(FILE *);
-char	*fgets(char * __restrict, int, FILE * __restrict);
+char	*fgets(char * __restrict, int, FILE * __restrict) __overloadable
+  __RENAME_CLANG(fgets);
 int	 fprintf(FILE * __restrict , const char * __restrict _Nonnull, ...) __printflike(2, 3);
 int	 fputc(int, FILE *);
 int	 fputs(const char * __restrict, FILE * __restrict);
-size_t	 fread(void * __restrict, size_t, size_t, FILE * __restrict);
+size_t	 fread(void * __restrict, size_t, size_t, FILE * __restrict)
+      __overloadable __RENAME_CLANG(fread);
 int	 fscanf(FILE * __restrict, const char * __restrict _Nonnull, ...) __scanflike(2, 3);
-size_t	 fwrite(const void * __restrict, size_t, size_t, FILE * __restrict);
+size_t	 fwrite(const void * __restrict, size_t, size_t, FILE * __restrict)
+    __overloadable __RENAME_CLANG(fwrite);
 int	 getc(FILE *);
 int	 getchar(void);
 ssize_t getdelim(char** __restrict, size_t* __restrict, int, FILE* __restrict) __INTRODUCED_IN(18);
@@ -155,12 +158,17 @@
     (defined(__cplusplus) && __cplusplus <= 201103L)
 char* gets(char*) __attribute__((deprecated("gets is unsafe, use fgets instead")));
 #endif
-int sprintf(char* __restrict, const char* __restrict _Nonnull, ...) __printflike(2, 3);
-int vsprintf(char* __restrict, const char* __restrict _Nonnull, __va_list) __printflike(2, 0);
-char* tmpnam(char*) __attribute__((deprecated("tmpnam is unsafe, use mkstemp or tmpfile instead")));
+int sprintf(char* __restrict, const char* __restrict _Nonnull, ...)
+    __printflike(2, 3) __warnattr_strict("sprintf is often misused; please use snprintf")
+    __overloadable __RENAME_CLANG(sprintf);
+int vsprintf(char* __restrict, const char* __restrict _Nonnull, __va_list)
+    __overloadable __printflike(2, 0) __RENAME_CLANG(vsprintf)
+    __warnattr_strict("vsprintf is often misused; please use vsnprintf");
+char* tmpnam(char*)
+    __warnattr("tempnam is unsafe, use mkstemp or tmpfile instead");
 #define P_tmpdir "/tmp/" /* deprecated */
 char* tempnam(const char*, const char*)
-    __attribute__((deprecated("tempnam is unsafe, use mkstemp or tmpfile instead")));
+    __warnattr("tempnam is unsafe, use mkstemp or tmpfile instead");
 
 int rename(const char*, const char*);
 int renameat(int, const char*, int, const char*);
@@ -210,10 +218,12 @@
 FILE* tmpfile(void);
 FILE* tmpfile64(void) __INTRODUCED_IN(24);
 
-int snprintf(char* __restrict, size_t, const char* __restrict _Nonnull, ...) __printflike(3, 4);
+int snprintf(char* __restrict, size_t, const char* __restrict _Nonnull, ...)
+    __printflike(3, 4) __overloadable __RENAME_CLANG(snprintf);
 int vfscanf(FILE* __restrict, const char* __restrict _Nonnull, __va_list) __scanflike(2, 0);
 int vscanf(const char* _Nonnull , __va_list) __scanflike(1, 0);
-int vsnprintf(char* __restrict, size_t, const char* __restrict _Nonnull, __va_list) __printflike(3, 0);
+int vsnprintf(char* __restrict, size_t, const char* __restrict _Nonnull, __va_list)
+    __printflike(3, 0) __overloadable __RENAME_CLANG(vsnprintf);
 int vsscanf(const char* __restrict _Nonnull, const char* __restrict _Nonnull, __va_list) __scanflike(2, 0);
 
 #define L_ctermid 1024 /* size for ctermid() */
@@ -250,66 +260,182 @@
 #endif /* __USE_BSD */
 
 char* __fgets_chk(char*, int, FILE*, size_t) __INTRODUCED_IN(17);
-char* __fgets_real(char*, int, FILE*) __RENAME(fgets);
-__errordecl(__fgets_too_big_error, "fgets called with size bigger than buffer");
-__errordecl(__fgets_too_small_error, "fgets called with size less than zero");
-
 size_t __fread_chk(void* __restrict, size_t, size_t, FILE* __restrict, size_t)
-  __INTRODUCED_IN(24);
-size_t __fread_real(void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fread);
-__errordecl(__fread_too_big_error, "fread called with size * count bigger than buffer");
-__errordecl(__fread_overflow, "fread called with overflowing size * count");
-
+    __INTRODUCED_IN(24);
 size_t __fwrite_chk(const void* __restrict, size_t, size_t, FILE* __restrict, size_t)
-  __INTRODUCED_IN(24);
-size_t __fwrite_real(const void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fwrite);
-__errordecl(__fwrite_too_big_error, "fwrite called with size * count bigger than buffer");
-__errordecl(__fwrite_overflow, "fwrite called with overflowing size * count");
+    __INTRODUCED_IN(24);
 
 #if defined(__BIONIC_FORTIFY) && !defined(__BIONIC_NO_STDIO_FORTIFY)
 
 #if __ANDROID_API__ >= __ANDROID_API_J_MR1__
-__BIONIC_FORTIFY_INLINE
-__printflike(3, 0) int vsnprintf(char* dest, size_t size, const char* _Nonnull format, __va_list ap) {
+__BIONIC_FORTIFY_INLINE __printflike(3, 0)
+int vsnprintf(char *const __pass_object_size dest, size_t size,
+              const char *_Nonnull format, __va_list ap) __overloadable {
     return __builtin___vsnprintf_chk(dest, size, 0, __bos(dest), format, ap);
 }
 
-__BIONIC_FORTIFY_INLINE
-__printflike(2, 0) int vsprintf(char* dest, const char* _Nonnull format, __va_list ap) {
+__BIONIC_FORTIFY_INLINE __printflike(2, 0)
+int vsprintf(char *const __pass_object_size dest, const char *_Nonnull format,
+             __va_list ap) __overloadable {
     return __builtin___vsprintf_chk(dest, 0, __bos(dest), format, ap);
 }
+#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
 
 #if defined(__clang__)
-  #if !defined(snprintf)
-    #define __wrap_snprintf(dest, size, ...) __builtin___snprintf_chk(dest, size, 0, __bos(dest), __VA_ARGS__)
-    #define snprintf(...) __wrap_snprintf(__VA_ARGS__)
-  #endif
-#else
-__BIONIC_FORTIFY_INLINE
-__printflike(3, 4) int snprintf(char* dest, size_t size, const char* _Nonnull format, ...) {
-    return __builtin___snprintf_chk(dest, size, 0, __bos(dest), format, __builtin_va_arg_pack());
-}
-#endif
+#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
+/*
+ * Simple case: `format` can't have format specifiers, so we can just compare
+ * its length to the length of `dest`
+ */
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+int snprintf(char *__restrict dest, size_t size, const char *__restrict format)
+    __overloadable
+    __enable_if(__bos(dest) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                __bos(dest) < __builtin_strlen(format),
+                "format string will always overflow destination buffer")
+    __errorattr("format string will always overflow destination buffer");
 
-#if defined(__clang__)
-  #if !defined(sprintf)
-    #define __wrap_sprintf(dest, ...) __builtin___sprintf_chk(dest, 0, __bos(dest), __VA_ARGS__)
-    #define sprintf(...) __wrap_sprintf(__VA_ARGS__)
-  #endif
-#else
 __BIONIC_FORTIFY_INLINE
-__printflike(2, 3) int sprintf(char* dest, const char* _Nonnull format, ...) {
-    return __builtin___sprintf_chk(dest, 0, __bos(dest), format, __builtin_va_arg_pack());
+__printflike(3, 4)
+int snprintf(char *__restrict const __pass_object_size dest,
+             size_t size, const char *__restrict format, ...) __overloadable {
+    va_list va;
+    va_start(va, format);
+    int result = __builtin___vsnprintf_chk(dest, size, 0, __bos(dest), format, va);
+    va_end(va);
+    return result;
 }
-#endif
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+int sprintf(char *__restrict dest, const char *__restrict format) __overloadable
+    __enable_if(__bos(dest) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                __bos(dest) < __builtin_strlen(format),
+                "format string will always overflow destination buffer")
+    __errorattr("format string will always overflow destination buffer");
+
+__BIONIC_FORTIFY_INLINE
+__printflike(2, 3)
+int sprintf(char *__restrict const __pass_object_size dest,
+        const char *__restrict format, ...) __overloadable {
+    va_list va;
+    va_start(va, format);
+    int result = __builtin___vsprintf_chk(dest, 0, __bos(dest), format, va);
+    va_end(va);
+    return result;
+}
 #endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
 
 #if __ANDROID_API__ >= __ANDROID_API_N__
 __BIONIC_FORTIFY_INLINE
-size_t fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict stream) {
+size_t fread(void *__restrict buf, size_t size, size_t count,
+             FILE *__restrict stream) __overloadable
+        __enable_if(__unsafe_check_mul_overflow(size, count), "size * count overflows")
+        __errorattr("size * count overflows");
+
+__BIONIC_FORTIFY_INLINE
+size_t fread(void *__restrict buf, size_t size, size_t count,
+             FILE *__restrict stream) __overloadable
+    __enable_if(!__unsafe_check_mul_overflow(size, count), "no overflow")
+    __enable_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                size * count > __bos(buf), "size * count is too large")
+    __errorattr("size * count is too large");
+
+__BIONIC_FORTIFY_INLINE
+size_t fread(void *__restrict const __pass_object_size buf, size_t size,
+             size_t count, FILE *__restrict stream) __overloadable {
     size_t bos = __bos0(buf);
 
-#if !defined(__clang__)
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __call_bypassing_fortify(fread)(buf, size, count, stream);
+    }
+
+    return __fread_chk(buf, size, count, stream, bos);
+}
+
+size_t fwrite(const void * __restrict buf, size_t size,
+              size_t count, FILE * __restrict stream) __overloadable
+    __enable_if(__unsafe_check_mul_overflow(size, count),
+                "size * count overflows")
+    __errorattr("size * count overflows");
+
+size_t fwrite(const void * __restrict buf, size_t size,
+              size_t count, FILE * __restrict stream) __overloadable
+    __enable_if(!__unsafe_check_mul_overflow(size, count), "no overflow")
+    __enable_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                size * count > __bos(buf), "size * count is too large")
+    __errorattr("size * count is too large");
+
+__BIONIC_FORTIFY_INLINE
+size_t fwrite(const void * __restrict const __pass_object_size buf, size_t size,
+              size_t count, FILE * __restrict stream) __overloadable {
+    size_t bos = __bos0(buf);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __call_bypassing_fortify(fwrite)(buf, size, count, stream);
+    }
+
+    return __fwrite_chk(buf, size, count, stream, bos);
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+char *fgets(char* __restrict dest, int size, FILE* stream) __overloadable
+    __enable_if(size < 0, "size is negative")
+    __errorattr("size is negative");
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+char *fgets(char* dest, int size, FILE* stream) __overloadable
+    __enable_if(size >= 0 && size > __bos(dest),
+                "size is larger than the destination buffer")
+    __errorattr("size is larger than the destination buffer");
+
+__BIONIC_FORTIFY_INLINE
+char *fgets(char* __restrict const __pass_object_size dest,
+        int size, FILE* stream) __overloadable {
+    size_t bos = __bos(dest);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __call_bypassing_fortify(fgets)(dest, size, stream);
+    }
+
+    return __fgets_chk(dest, size, stream, bos);
+}
+
+#else /* defined(__clang__) */
+
+size_t __fread_real(void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fread);
+__errordecl(__fread_too_big_error, "fread called with size * count bigger than buffer");
+__errordecl(__fread_overflow, "fread called with overflowing size * count");
+
+char* __fgets_real(char*, int, FILE*) __RENAME(fgets);
+__errordecl(__fgets_too_big_error, "fgets called with size bigger than buffer");
+__errordecl(__fgets_too_small_error, "fgets called with size less than zero");
+
+size_t __fwrite_real(const void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fwrite);
+__errordecl(__fwrite_too_big_error, "fwrite called with size * count bigger than buffer");
+__errordecl(__fwrite_overflow, "fwrite called with overflowing size * count");
+
+
+#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
+__BIONIC_FORTIFY_INLINE __printflike(3, 4)
+int snprintf(char *__restrict dest, size_t size, const char* _Nonnull format, ...)
+{
+    return __builtin___snprintf_chk(dest, size, 0, __bos(dest), format,
+                                    __builtin_va_arg_pack());
+}
+
+__BIONIC_FORTIFY_INLINE __printflike(2, 3)
+int sprintf(char *__restrict dest, const char* _Nonnull format, ...) {
+    return __builtin___sprintf_chk(dest, 0, __bos(dest), format,
+                                   __builtin_va_arg_pack());
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
+
+#if __ANDROID_API__ >= __ANDROID_API_N__
+__BIONIC_FORTIFY_INLINE
+size_t fread(void *__restrict buf, size_t size, size_t count, FILE * __restrict stream) {
+    size_t bos = __bos0(buf);
+
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __fread_real(buf, size, count, stream);
     }
@@ -326,7 +452,6 @@
 
         return __fread_real(buf, size, count, stream);
     }
-#endif
 
     return __fread_chk(buf, size, count, stream, bos);
 }
@@ -335,7 +460,6 @@
 size_t fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict stream) {
     size_t bos = __bos0(buf);
 
-#if !defined(__clang__)
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __fwrite_real(buf, size, count, stream);
     }
@@ -352,14 +476,11 @@
 
         return __fwrite_real(buf, size, count, stream);
     }
-#endif
 
     return __fwrite_chk(buf, size, count, stream, bos);
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
 
-#if !defined(__clang__)
-
 __BIONIC_FORTIFY_INLINE
 char *fgets(char* dest, int size, FILE* stream) {
     size_t bos = __bos(dest);
@@ -390,8 +511,7 @@
     return __fgets_chk(dest, size, stream, bos);
 }
 
-#endif /* !defined(__clang__) */
-
+#endif /* defined(__clang__) */
 #endif /* defined(__BIONIC_FORTIFY) */
 
 #if defined(__clang__)
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index d0c08e1..eefee13 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -83,8 +83,9 @@
 long atol(const char*) __attribute_pure__;
 long long atoll(const char*) __attribute_pure__;
 
-char* realpath(const char* path, char* resolved);
-int system(const char* string);
+char * realpath(const char *path, char *resolved) __overloadable
+        __RENAME_CLANG(realpath);
+int system(const char *string);
 
 void* bsearch(const void* key, const void* base0, size_t nmemb, size_t size,
               int (*compar)(const void*, const void*));
@@ -164,24 +165,44 @@
 #endif
 
 #if defined(__BIONIC_FORTIFY)
+#define __realpath_buf_too_small_str \
+    "realpath output parameter must be NULL or a >= PATH_MAX bytes buffer"
+
+/* PATH_MAX is unavailable without polluting the namespace, but it's always 4096 on Linux */
+#define __PATH_MAX 4096
+
+#if defined(__clang__)
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+char* realpath(const char* path, char* resolved) __overloadable
+    __enable_if(__bos(resolved) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                __bos(resolved) < __PATH_MAX, __realpath_buf_too_small_str)
+    __errorattr(__realpath_buf_too_small_str);
+
+/* No need for a FORTIFY version; the only things we can catch are at
+ * compile-time.
+ */
+
+#else /* defined(__clang__) */
 
 char* __realpath_real(const char*, char*) __RENAME(realpath);
-__errordecl(__realpath_size_error, "realpath output parameter must be NULL or a >= PATH_MAX bytes buffer");
+__errordecl(__realpath_size_error, __realpath_buf_too_small_str);
 
-#if !defined(__clang__)
 __BIONIC_FORTIFY_INLINE
 char* realpath(const char* path, char* resolved) {
     size_t bos = __bos(resolved);
 
-    /* PATH_MAX is unavailable without polluting the namespace, but it's always 4096 on Linux */
-    if (bos != __BIONIC_FORTIFY_UNKNOWN_SIZE && bos < 4096) {
+    if (bos != __BIONIC_FORTIFY_UNKNOWN_SIZE && bos < __PATH_MAX) {
         __realpath_size_error();
     }
 
     return __realpath_real(path, resolved);
 }
-#endif
 
+#endif /* defined(__clang__) */
+
+#undef __PATH_MAX
+#undef __realpath_buf_too_small_str
 #endif /* defined(__BIONIC_FORTIFY) */
 
 #if __ANDROID_API__ >= __ANDROID_API_L__
diff --git a/libc/include/string.h b/libc/include/string.h
index 3e52f48..38595b2 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -47,18 +47,23 @@
 #endif
 
 void* memccpy(void* _Nonnull __restrict, const void* _Nonnull __restrict, int, size_t);
-void* memchr(const void* _Nonnull, int, size_t) __attribute_pure__;
-void* memrchr(const void* _Nonnull, int, size_t) __attribute_pure__;
+void* memchr(const void* _Nonnull, int, size_t) __attribute_pure__ __overloadable
+        __RENAME_CLANG(memchr);
+void* memrchr(const void* _Nonnull, int, size_t) __attribute_pure__ __overloadable
+        __RENAME_CLANG(memrchr);
 int memcmp(const void* _Nonnull, const void* _Nonnull, size_t) __attribute_pure__;
-void* memcpy(void* _Nonnull __restrict, const void* _Nonnull __restrict, size_t);
+void* memcpy(void* _Nonnull __restrict, const void* _Nonnull __restrict, size_t)
+        __overloadable __RENAME_CLANG(memcpy);
 #if defined(__USE_GNU)
 void* mempcpy(void* _Nonnull __restrict, const void* _Nonnull __restrict, size_t) __INTRODUCED_IN(23);
 #endif
-void* memmove(void* _Nonnull, const void* _Nonnull, size_t);
-void* memset(void* _Nonnull, int, size_t);
+void* memmove(void* _Nonnull, const void* _Nonnull, size_t) __overloadable
+        __RENAME_CLANG(memmove);
+void* memset(void* _Nonnull, int, size_t) __overloadable __RENAME_CLANG(memset);
 void* memmem(const void* _Nonnull, size_t, const void* _Nonnull, size_t) __attribute_pure__;
 
-char* strchr(const char* _Nonnull, int) __attribute_pure__;
+char* strchr(const char* _Nonnull, int) __attribute_pure__ __overloadable
+        __RENAME_CLANG(strchr);
 char* __strchr_chk(const char* _Nonnull, int, size_t) __INTRODUCED_IN(18);
 #if defined(__USE_GNU)
 #if defined(__cplusplus)
@@ -69,16 +74,21 @@
 #endif
 #endif
 
-char* strrchr(const char* _Nonnull, int) __attribute_pure__;
+char* strrchr(const char* _Nonnull, int) __attribute_pure__ __overloadable
+        __RENAME_CLANG(strrchr);
 char* __strrchr_chk(const char* _Nonnull, int, size_t) __INTRODUCED_IN(18);
 
-size_t strlen(const char* _Nonnull) __attribute_pure__;
+size_t strlen(const char* _Nonnull) __attribute_pure__ __overloadable
+        __RENAME_CLANG(strlen);
 size_t __strlen_chk(const char* _Nonnull, size_t) __INTRODUCED_IN(17);
-int strcmp(const char* _Nonnull, const char* _Nonnull) __attribute_pure__;
-char* stpcpy(char* _Nonnull __restrict, const char* _Nonnull__restrict) __INTRODUCED_IN(21);
-char* strcpy(char* _Nonnull __restrict, const char* _Nonnull __restrict);
-char* strcat(char* _Nonnull __restrict, const char* _Nonnull __restrict);
 
+int strcmp(const char* _Nonnull, const char* _Nonnull) __attribute_pure__;
+char* stpcpy(char* _Nonnull __restrict, const char* _Nonnull __restrict)
+        __overloadable __RENAME_CLANG(stpcpy) __INTRODUCED_IN(21);
+char* strcpy(char* _Nonnull __restrict, const char* _Nonnull __restrict)
+        __overloadable __RENAME_CLANG(strcpy);
+char* strcat(char* _Nonnull __restrict, const char* _Nonnull __restrict)
+        __overloadable __RENAME_CLANG(strcat);
 char* strdup(const char* _Nonnull);
 
 char* strstr(const char* _Nonnull, const char* _Nonnull) __attribute_pure__;
@@ -95,14 +105,19 @@
 #endif
 
 size_t strnlen(const char* _Nonnull, size_t) __attribute_pure__;
-char* strncat(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t);
+char* strncat(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t)
+        __overloadable __RENAME_CLANG(strncat);
 char* strndup(const char* _Nonnull, size_t);
 int strncmp(const char* _Nonnull, const char* _Nonnull, size_t) __attribute_pure__;
-char* stpncpy(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t) __INTRODUCED_IN(21);
-char* strncpy(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t);
+char* stpncpy(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t)
+        __overloadable __RENAME_CLANG(stpncpy) __INTRODUCED_IN(21);
+char* strncpy(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t)
+        __overloadable __RENAME_CLANG(strncpy);
 
-size_t strlcat(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t);
-size_t strlcpy(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t);
+size_t strlcat(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t)
+        __overloadable __RENAME_CLANG(strlcat);
+size_t strlcpy(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t)
+        __overloadable __RENAME_CLANG(strlcpy);
 
 size_t strcspn(const char* _Nonnull, const char* _Nonnull) __attribute_pure__;
 char* strpbrk(const char* _Nonnull, const char* _Nonnull) __attribute_pure__;
@@ -135,29 +150,287 @@
 #endif
 
 void* __memchr_chk(const void* _Nonnull, int, size_t, size_t) __INTRODUCED_IN(23);
-__errordecl(__memchr_buf_size_error, "memchr called with size bigger than buffer");
-
 void* __memrchr_chk(const void* _Nonnull, int, size_t, size_t) __INTRODUCED_IN(23);
-__errordecl(__memrchr_buf_size_error, "memrchr called with size bigger than buffer");
-void* __memrchr_real(const void* _Nonnull, int, size_t) __RENAME(memrchr);
-
 char* __stpncpy_chk2(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t, size_t, size_t)
   __INTRODUCED_IN(21);
 char* __strncpy_chk2(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t, size_t, size_t)
   __INTRODUCED_IN(21);
-size_t __strlcpy_real(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t) __RENAME(strlcpy);
 size_t __strlcpy_chk(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t, size_t) __INTRODUCED_IN(17);
-size_t __strlcat_real(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t) __RENAME(strlcat);
 size_t __strlcat_chk(char* _Nonnull __restrict, const char* _Nonnull __restrict, size_t, size_t) __INTRODUCED_IN(17);
 
+/* Only used with FORTIFY, but some headers that need it undef FORTIFY, so we
+ * have the definition out here.
+ */
+struct __bionic_zero_size_is_okay_t {};
+
 #if defined(__BIONIC_FORTIFY)
+// These can share their implementation between gcc and clang with minimal
+// trickery...
+#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
+__BIONIC_FORTIFY_INLINE
+void* memcpy(void* _Nonnull __restrict const dst __pass_object_size,
+        const void* _Nonnull __restrict src, size_t copy_amount) __overloadable {
+    return __builtin___memcpy_chk(dst, src, copy_amount, __bos0(dst));
+}
+
+__BIONIC_FORTIFY_INLINE
+void* memmove(void* const _Nonnull dst __pass_object_size,
+        const void* _Nonnull src, size_t len) __overloadable {
+    return __builtin___memmove_chk(dst, src, len, __bos0(dst));
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
+
+#if __ANDROID_API__ >= __ANDROID_API_L__
+__BIONIC_FORTIFY_INLINE
+char* stpcpy(char* _Nonnull __restrict const dst __pass_object_size,
+        const char* _Nonnull __restrict src) __overloadable {
+    return __builtin___stpcpy_chk(dst, src, __bos(dst));
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_L__ */
+
+#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
+__BIONIC_FORTIFY_INLINE
+char* strcpy(char* _Nonnull __restrict const dst __pass_object_size,
+        const char* _Nonnull __restrict src) __overloadable {
+    return __builtin___strcpy_chk(dst, src, __bos(dst));
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
+
+__BIONIC_FORTIFY_INLINE
+char* strcat(char* _Nonnull __restrict const dst __pass_object_size,
+        const char* _Nonnull __restrict src) __overloadable {
+    return __builtin___strcat_chk(dst, src, __bos(dst));
+}
+
+__BIONIC_FORTIFY_INLINE
+char* strncat(char* const _Nonnull __restrict dst __pass_object_size,
+        const char* _Nonnull __restrict src, size_t n) __overloadable {
+    return __builtin___strncat_chk(dst, src, n, __bos(dst));
+}
+
+__BIONIC_FORTIFY_INLINE
+void* memset(void* const _Nonnull s __pass_object_size, int c, size_t n)
+        __overloadable {
+    return __builtin___memset_chk(s, c, n, __bos0(s));
+}
+
+
+#if defined(__clang__)
+
+#define __error_if_overflows_dst(name, dst, n, what) \
+    __enable_if(__bos0(dst) != __BIONIC_FORTIFY_UNKNOWN_SIZE && \
+                __bos0(dst) < (n), "selected when the buffer is too small") \
+    __errorattr(#name " called with " what " bigger than buffer")
+
+/*
+ * N.B. _Nonnull isn't necessary on params, since these functions just emit
+ * errors.
+ */
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+void* memcpy(void* dst, const void* src, size_t copy_amount) __overloadable
+        __error_if_overflows_dst(memcpy, dst, copy_amount, "size");
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+void* memmove(void *dst, const void* src, size_t len) __overloadable
+        __error_if_overflows_dst(memmove, dst, len, "size");
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+void* memset(void* s, int c, size_t n) __overloadable
+        __error_if_overflows_dst(memset, s, n, "size");
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+char* stpcpy(char* dst, const char* src) __overloadable
+        __error_if_overflows_dst(stpcpy, dst, __builtin_strlen(src), "string");
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+char* strcpy(char* dst, const char* src) __overloadable
+        __error_if_overflows_dst(strcpy, dst, __builtin_strlen(src), "string");
 
 #if __ANDROID_API__ >= __ANDROID_API_M__
 __BIONIC_FORTIFY_INLINE
-void* memchr(const void* s, int c, size_t n) {
+void* memchr(const void* const _Nonnull s __pass_object_size, int c, size_t n)
+        __overloadable {
     size_t bos = __bos(s);
 
-#if !defined(__clang__)
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __builtin_memchr(s, c, n);
+    }
+
+    return __memchr_chk(s, c, n, bos);
+}
+
+__BIONIC_FORTIFY_INLINE
+void* memrchr(const void* const _Nonnull s __pass_object_size, int c, size_t n)
+        __overloadable {
+    size_t bos = __bos(s);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __call_bypassing_fortify(memrchr)(s, c, n);
+    }
+
+    return __memrchr_chk(s, c, n, bos);
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_M__ */
+
+#if __ANDROID_API__ >= __ANDROID_API_L__
+__BIONIC_FORTIFY_INLINE
+char* stpncpy(char* __restrict const _Nonnull dst __pass_object_size,
+        const char* __restrict const _Nonnull src __pass_object_size,
+        size_t n) __overloadable {
+    size_t bos_dst = __bos(dst);
+    size_t bos_src = __bos(src);
+
+    /* Ignore dst size checks; they're handled in strncpy_chk */
+    if (bos_src == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __builtin___stpncpy_chk(dst, src, n, bos_dst);
+    }
+
+    return __stpncpy_chk2(dst, src, n, bos_dst, bos_src);
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_L__ */
+
+#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
+__BIONIC_FORTIFY_INLINE
+char* strncpy(char* __restrict const _Nonnull dst __pass_object_size,
+        const char* __restrict const _Nonnull src __pass_object_size,
+        size_t n) __overloadable {
+    size_t bos_dst = __bos(dst);
+    size_t bos_src = __bos(src);
+
+    /* Ignore dst size checks; they're handled in strncpy_chk */
+    if (bos_src == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __builtin___strncpy_chk(dst, src, n, bos_dst);
+    }
+
+    return __strncpy_chk2(dst, src, n, bos_dst, bos_src);
+}
+
+__BIONIC_FORTIFY_INLINE
+size_t strlcpy(char* const _Nonnull __restrict dst __pass_object_size,
+        const char *_Nonnull __restrict src, size_t size) __overloadable {
+    size_t bos = __bos(dst);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __call_bypassing_fortify(strlcpy)(dst, src, size);
+    }
+
+    return __strlcpy_chk(dst, src, size, bos);
+}
+
+__BIONIC_FORTIFY_INLINE
+size_t strlcat(char* const _Nonnull __restrict dst __pass_object_size,
+        const char* _Nonnull __restrict src, size_t size) __overloadable {
+    size_t bos = __bos(dst);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __call_bypassing_fortify(strlcat)(dst, src, size);
+    }
+
+    return __strlcat_chk(dst, src, size, bos);
+}
+
+/*
+ * If we can evaluate the size of s at compile-time, just call __builtin_strlen
+ * on it directly. This makes it way easier for compilers to fold things like
+ * strlen("Foo") into a constant, as users would expect. -1ULL is chosen simply
+ * because it's large.
+ */
+__BIONIC_FORTIFY_INLINE
+size_t strlen(const char* const _Nonnull s __pass_object_size)
+        __overloadable __enable_if(__builtin_strlen(s) != -1ULL,
+                                   "enabled if s is a known good string.") {
+    return __builtin_strlen(s);
+}
+
+__BIONIC_FORTIFY_INLINE
+size_t strlen(const char* const _Nonnull s __pass_object_size_n(0))
+        __overloadable {
+    size_t bos = __bos0(s);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __builtin_strlen(s);
+    }
+
+    // return __builtin_strlen(s);
+    return __strlen_chk(s, bos);
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
+
+#if  __ANDROID_API__ >= __ANDROID_API_J_MR2__
+__BIONIC_FORTIFY_INLINE
+char* strchr(const char* const _Nonnull s __pass_object_size_n(0), int c)
+        __overloadable {
+    size_t bos = __bos0(s);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __builtin_strchr(s, c);
+    }
+
+    // return __builtin_strchr(s, c);
+    return __strchr_chk(s, c, bos);
+}
+
+__BIONIC_FORTIFY_INLINE
+char* strrchr(const char* const _Nonnull s __pass_object_size, int c)
+        __overloadable {
+    size_t bos = __bos(s);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __builtin_strrchr(s, c);
+    }
+
+    return __strrchr_chk(s, c, bos);
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR2__ */
+
+/* In *many* cases, memset(foo, sizeof(foo), 0) is a mistake where the user has
+ * flipped the size + value arguments. However, there may be cases (e.g. with
+ * macros) where it's okay for the size to fold to zero. We should warn on this,
+ * but we should also provide a FORTIFY'ed escape hatch.
+ */
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+void* memset(void* _Nonnull s, int c, size_t n,
+             struct __bionic_zero_size_is_okay_t ok)
+        __overloadable
+        __error_if_overflows_dst(memset, s, n, "size");
+
+__BIONIC_FORTIFY_INLINE
+void* memset(void* const _Nonnull s __pass_object_size, int c, size_t n,
+             struct __bionic_zero_size_is_okay_t ok __attribute__((unused)))
+        __overloadable {
+    return __builtin___memset_chk(s, c, n, __bos0(s));
+}
+
+extern struct __bionic_zero_size_is_okay_t __bionic_zero_size_is_okay;
+/* We verify that `c` is non-zero, because as pointless as memset(foo, 0, 0) is,
+ * flipping size + count will do nothing.
+ */
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+void* memset(void* _Nonnull s, int c, size_t n) __overloadable
+        __enable_if(c && !n, "selected when we'll set zero bytes")
+        __RENAME_CLANG(memset)
+        __warnattr_real("will set 0 bytes; maybe the arguments got flipped? "
+                        "(Add __bionic_zero_size_is_okay as a fourth argument "
+                        "to silence this.)");
+
+#undef __error_zero_size
+#undef __error_if_overflows_dst
+#else // defined(__clang__)
+extern char* __strncpy_real(char* __restrict, const char*, size_t) __RENAME(strcpy);
+extern void* __memrchr_real(const void*, int, size_t) __RENAME(memrchr);
+extern size_t __strlcpy_real(char* __restrict, const char* __restrict, size_t)
+    __RENAME(strlcpy);
+extern size_t __strlcat_real(char* __restrict, const char* __restrict, size_t)
+    __RENAME(strlcat);
+
+__errordecl(__memchr_buf_size_error, "memchr called with size bigger than buffer");
+__errordecl(__memrchr_buf_size_error, "memrchr called with size bigger than buffer");
+
+#if __ANDROID_API__ >= __ANDROID_API_M__
+__BIONIC_FORTIFY_INLINE
+void* memchr(const void *_Nonnull s __pass_object_size, int c, size_t n) {
+    size_t bos = __bos(s);
+
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __builtin_memchr(s, c, n);
     }
@@ -169,7 +442,6 @@
     if (__builtin_constant_p(n) && (n <= bos)) {
         return __builtin_memchr(s, c, n);
     }
-#endif
 
     return __memchr_chk(s, c, n, bos);
 }
@@ -178,7 +450,6 @@
 void* memrchr(const void* s, int c, size_t n) {
     size_t bos = __bos(s);
 
-#if !defined(__clang__)
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __memrchr_real(s, c, n);
     }
@@ -190,38 +461,11 @@
     if (__builtin_constant_p(n) && (n <= bos)) {
         return __memrchr_real(s, c, n);
     }
-#endif
 
     return __memrchr_chk(s, c, n, bos);
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_M__ */
 
-#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
-__BIONIC_FORTIFY_INLINE
-void* memcpy(void* _Nonnull __restrict dst, const void* _Nonnull __restrict src, size_t copy_amount) {
-    return __builtin___memcpy_chk(dst, src, copy_amount, __bos0(dst));
-}
-
-__BIONIC_FORTIFY_INLINE
-void* memmove(void* _Nonnull dst, const void* _Nonnull src, size_t len) {
-    return __builtin___memmove_chk(dst, src, len, __bos0(dst));
-}
-#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
-
-#if __ANDROID_API__ >= __ANDROID_API_L__
-__BIONIC_FORTIFY_INLINE
-char* stpcpy(char* _Nonnull __restrict dst, const char* _Nonnull __restrict src) {
-    return __builtin___stpcpy_chk(dst, src, __bos(dst));
-}
-#endif /* __ANDROID_API__ >= __ANDROID_API_L__ */
-
-#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
-__BIONIC_FORTIFY_INLINE
-char* strcpy(char* _Nonnull __restrict dst, const char* _Nonnull __restrict src) {
-    return __builtin___strcpy_chk(dst, src, __bos(dst));
-}
-#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
-
 #if __ANDROID_API__ >= __ANDROID_API_L__
 __BIONIC_FORTIFY_INLINE
 char* stpncpy(char* _Nonnull __restrict dst, const char* _Nonnull __restrict src, size_t n) {
@@ -250,7 +494,7 @@
     size_t bos_src = __bos(src);
 
     if (bos_src == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
-        return __builtin___strncpy_chk(dst, src, n, bos_dst);
+        return __strncpy_real(dst, src, n);
     }
 
     if (__builtin_constant_p(n) && (n <= bos_src)) {
@@ -268,25 +512,10 @@
 
 #if __ANDROID_API__ >= __ANDROID_API_J_MR1__
 __BIONIC_FORTIFY_INLINE
-char* strcat(char* _Nonnull __restrict dst, const char* _Nonnull __restrict src) {
-    return __builtin___strcat_chk(dst, src, __bos(dst));
-}
-
-__BIONIC_FORTIFY_INLINE
-char *strncat(char* _Nonnull __restrict dst, const char* _Nonnull __restrict src, size_t n) {
-    return __builtin___strncat_chk(dst, src, n, __bos(dst));
-}
-
-__BIONIC_FORTIFY_INLINE
-void* memset(void* _Nonnull s, int c, size_t n) {
-    return __builtin___memset_chk(s, c, n, __bos0(s));
-}
-
-__BIONIC_FORTIFY_INLINE
-size_t strlcpy(char* _Nonnull __restrict dst, const char* _Nonnull __restrict src, size_t size) {
+size_t strlcpy(char* _Nonnull __restrict dst __pass_object_size,
+        const char* _Nonnull __restrict src, size_t size) {
     size_t bos = __bos(dst);
 
-#if !defined(__clang__)
     // Compiler doesn't know destination size. Don't call __strlcpy_chk
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __strlcpy_real(dst, src, size);
@@ -297,17 +526,14 @@
     if (__builtin_constant_p(size) && (size <= bos)) {
         return __strlcpy_real(dst, src, size);
     }
-#endif /* !defined(__clang__) */
 
     return __strlcpy_chk(dst, src, size, bos);
 }
 
-
 __BIONIC_FORTIFY_INLINE
 size_t strlcat(char* _Nonnull __restrict dst, const char* _Nonnull __restrict src, size_t size) {
     size_t bos = __bos(dst);
 
-#if !defined(__clang__)
     // Compiler doesn't know destination size. Don't call __strlcat_chk
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __strlcat_real(dst, src, size);
@@ -318,16 +544,14 @@
     if (__builtin_constant_p(size) && (size <= bos)) {
         return __strlcat_real(dst, src, size);
     }
-#endif /* !defined(__clang__) */
 
     return __strlcat_chk(dst, src, size, bos);
 }
 
 __BIONIC_FORTIFY_INLINE
-size_t strlen(const char* _Nonnull s) {
+size_t strlen(const char* _Nonnull s) __overloadable {
     size_t bos = __bos(s);
 
-#if !defined(__clang__)
     // Compiler doesn't know destination size. Don't call __strlen_chk
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __builtin_strlen(s);
@@ -337,7 +561,6 @@
     if (__builtin_constant_p(slen)) {
         return slen;
     }
-#endif /* !defined(__clang__) */
 
     return __strlen_chk(s, bos);
 }
@@ -348,7 +571,6 @@
 char* strchr(const char* _Nonnull s, int c) {
     size_t bos = __bos(s);
 
-#if !defined(__clang__)
     // Compiler doesn't know destination size. Don't call __strchr_chk
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __builtin_strchr(s, c);
@@ -358,7 +580,6 @@
     if (__builtin_constant_p(slen) && (slen < bos)) {
         return __builtin_strchr(s, c);
     }
-#endif /* !defined(__clang__) */
 
     return __strchr_chk(s, c, bos);
 }
@@ -367,7 +588,6 @@
 char* strrchr(const char* _Nonnull s, int c) {
     size_t bos = __bos(s);
 
-#if !defined(__clang__)
     // Compiler doesn't know destination size. Don't call __strrchr_chk
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __builtin_strrchr(s, c);
@@ -377,12 +597,11 @@
     if (__builtin_constant_p(slen) && (slen < bos)) {
         return __builtin_strrchr(s, c);
     }
-#endif /* !defined(__clang__) */
 
     return __strrchr_chk(s, c, bos);
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_J_MR2__ */
-
+#endif /* defined(__clang__) */
 #endif /* defined(__BIONIC_FORTIFY) */
 
 #if defined(__clang__)
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 63e782e..9492d92 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -181,12 +181,29 @@
 #define __wur __attribute__((__warn_unused_result__))
 
 #ifdef __clang__
-#define __errorattr(msg) __attribute__((unavailable(msg)))
+#  define __errorattr(msg) __attribute__((unavailable(msg)))
+#  define __warnattr(msg) __attribute__((deprecated(msg)))
+#  define __warnattr_real(msg) __attribute__((deprecated(msg)))
+#  define __enable_if(cond, msg) __attribute__((enable_if(cond, msg)))
 #else
-#define __errorattr(msg) __attribute__((__error__(msg)))
+#  define __errorattr(msg) __attribute__((__error__(msg)))
+#  define __warnattr(msg) __attribute__((__warning__(msg)))
+#  define __warnattr_real __warnattr
+/* enable_if doesn't exist on other compilers; give an error if it's used. */
+
+/* errordecls really don't work as well in clang as they do in GCC. */
+#  define __errordecl(name, msg) extern void name(void) __errorattr(msg)
 #endif
 
-#define __errordecl(name, msg) extern void name(void) __errorattr(msg)
+#if defined(ANDROID_STRICT)
+/*
+ * For things that are sketchy, but not necessarily an error. FIXME: Enable
+ * this.
+ */
+#  define __warnattr_strict(msg) /* __warnattr(msg) */
+#else
+#  define __warnattr_strict(msg)
+#endif
 
 /*
  * Some BSD source needs these macros.
@@ -242,21 +259,59 @@
  * See
  * http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html for details.
  */
+
+#define __BIONIC_FORTIFY_UNKNOWN_SIZE ((size_t) -1)
+
 #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0
 #  define __BIONIC_FORTIFY 1
 #  if _FORTIFY_SOURCE == 2
-#    define __bos(s) __builtin_object_size((s), 1)
+#    define __bos_level 1
 #  else
-#    define __bos(s) __builtin_object_size((s), 0)
+#    define __bos_level 0
 #  endif
-#  define __bos0(s) __builtin_object_size((s), 0)
+#  define __bosn(s, n) __builtin_object_size((s), (n))
+#  define __bos(s) __bosn((s), __bos_level)
+#  define __bos0(s) __bosn((s), 0)
 #  if defined(__clang__)
-#    define __BIONIC_FORTIFY_INLINE extern __inline__ __always_inline __attribute__((gnu_inline))
+#    define __pass_object_size_n(n) __attribute__((pass_object_size(n)))
+/*
+ * FORTIFY'ed functions all have either enable_if or pass_object_size, which
+ * makes taking their address impossible. Saying (&read)(foo, bar, baz); will
+ * therefore call the unFORTIFYed version of read.
+ */
+#    define __call_bypassing_fortify(fn) (&fn)
+/*
+ * Because clang-FORTIFY uses overloads, we can't mark functions as `extern
+ * inline` without making them available externally.
+ */
+#    define __BIONIC_FORTIFY_INLINE static __inline__ __always_inline
+/* Error functions don't have bodies, so they can just be static. */
+#    define __BIONIC_ERROR_FUNCTION_VISIBILITY static
 #  else
+/*
+ * Where they can, GCC and clang-style FORTIFY share implementations.
+ * So, make these nops in GCC.
+ */
+#    define __pass_object_size_n(n)
+#    define __call_bypassing_fortify(fn) (fn)
+/* __BIONIC_FORTIFY_NONSTATIC_INLINE is pointless in GCC's FORTIFY */
 #    define __BIONIC_FORTIFY_INLINE extern __inline__ __always_inline __attribute__((gnu_inline)) __attribute__((__artificial__))
 #  endif
+#  define __pass_object_size __pass_object_size_n(__bos_level)
 #endif
-#define __BIONIC_FORTIFY_UNKNOWN_SIZE __BIONIC_CAST(static_cast, size_t, -1)
+
+/* Used to support clangisms with FORTIFY. This isn't in the FORTIFY section
+ * because these change how symbols are emitted. The linker must be kept happy.
+ */
+#ifdef __clang__
+#  define __overloadable __attribute__((overloadable))
+// Don't use __RENAME directly because on gcc, this could result in a number of
+// unnecessary renames.
+#  define __RENAME_CLANG(x) __RENAME(x)
+#else
+#  define __overloadable
+#  define __RENAME_CLANG(x)
+#endif
 
 /* Used to tag non-static symbols that are private and never exposed by the shared library. */
 #define __LIBC_HIDDEN__ __attribute__((visibility("hidden")))
@@ -303,5 +358,15 @@
  * build working.
  */
 #define __NDK_FPABI__
+#if defined(__clang__)
+/*
+ * Used when we need to check for overflow when multiplying x and y. This
+ * should only be used where __size_mul_overflow can not work, because it makes
+ * assumptions that __size_mul_overflow doesn't (x and y are positive, ...),
+ * *and* doesn't make use of compiler intrinsics, so it's probably slower than
+ * __size_mul_overflow.
+ */
+#define __unsafe_check_mul_overflow(x, y) ((__SIZE_TYPE__)-1 / (x) < (y))
+#endif
 
 #endif /* !_SYS_CDEFS_H_ */
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index f9f6764..997191e 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -317,25 +317,59 @@
 __socketcall int socket(int, int, int);
 __socketcall int socketpair(int, int, int, int*);
 
-ssize_t recv(int, void*, size_t, int);
+ssize_t recv(int, void*, size_t, int) __overloadable __RENAME_CLANG(recv);
 ssize_t send(int, const void*, size_t, int);
 
 __socketcall ssize_t sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t);
-__socketcall ssize_t recvfrom(int, void*, size_t, int, struct sockaddr*, socklen_t*);
+__socketcall ssize_t recvfrom(int, void*, size_t, int, struct sockaddr*,
+        socklen_t*) __overloadable __RENAME_CLANG(recvfrom);
 
-__errordecl(__recvfrom_error, "recvfrom called with size bigger than buffer");
-ssize_t __recvfrom_chk(int, void*, size_t, size_t, int, struct sockaddr*, socklen_t*)
-  __INTRODUCED_IN(21);
-ssize_t __recvfrom_real(int, void*, size_t, int, struct sockaddr*, socklen_t*) __RENAME(recvfrom);
+ssize_t __recvfrom_chk(int, void*, size_t, size_t, int, struct sockaddr*,
+        socklen_t*) __INTRODUCED_IN(21);
 
 #if defined(__BIONIC_FORTIFY)
 
+#if defined(__clang__)
 #if __ANDROID_API__ >= __ANDROID_API_N__
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t recvfrom(int fd, void* const buf __pass_object_size, size_t len,
+                 int flags, struct sockaddr* src_addr, socklen_t* addr_len)
+        __overloadable
+        __enable_if(__bos(buf) != __BIONIC_FORTIFY_UNKNOWN_SIZE &&
+                    __bos(buf) < len, "selected when the buffer is too small")
+        __errorattr("size is larger than the destination buffer");
+
 __BIONIC_FORTIFY_INLINE
-ssize_t recvfrom(int fd, void* buf, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addr_len) {
+ssize_t recvfrom(int fd, void* const buf __pass_object_size, size_t len,
+                 int flags, struct sockaddr* src_addr, socklen_t* addr_len)
+      __overloadable {
   size_t bos = __bos0(buf);
 
-#if !defined(__clang__)
+  if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+    return __call_bypassing_fortify(recvfrom)(fd, buf, len, flags, src_addr,
+              addr_len);
+  }
+
+  return __recvfrom_chk(fd, buf, len, bos, flags, src_addr, addr_len);
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
+
+__BIONIC_FORTIFY_INLINE
+ssize_t recv(int socket, void* const buf __pass_object_size, size_t len,
+             int flags) __overloadable {
+  return recvfrom(socket, buf, len, flags, NULL, 0);
+}
+
+#else /* defined(__clang__) */
+ssize_t __recvfrom_real(int, void*, size_t, int, struct sockaddr*, socklen_t*) __RENAME(recvfrom);
+__errordecl(__recvfrom_error, "recvfrom called with size bigger than buffer");
+
+#if __ANDROID_API__ >= __ANDROID_API_N__
+__BIONIC_FORTIFY_INLINE
+ssize_t recvfrom(int fd, void* buf, size_t len, int flags,
+                 struct sockaddr* src_addr, socklen_t* addr_len) {
+  size_t bos = __bos0(buf);
+
   if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
     return __recvfrom_real(fd, buf, len, flags, src_addr, addr_len);
   }
@@ -347,7 +381,6 @@
   if (__builtin_constant_p(len) && (len > bos)) {
     __recvfrom_error();
   }
-#endif
 
   return __recvfrom_chk(fd, buf, len, bos, flags, src_addr, addr_len);
 }
@@ -358,6 +391,8 @@
   return recvfrom(socket, buf, len, flags, NULL, 0);
 }
 
+#endif /* defined(__clang__) */
+
 #endif /* __BIONIC_FORTIFY */
 
 #undef __socketcall
diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h
index f961cf8..f8d854d 100644
--- a/libc/include/sys/stat.h
+++ b/libc/include/sys/stat.h
@@ -161,29 +161,52 @@
 int stat64(const char*, struct stat64*) __INTRODUCED_IN(21);
 
 int mknod(const char*, mode_t, dev_t);
-mode_t umask(mode_t);
+mode_t umask(mode_t) __overloadable __RENAME_CLANG(umask);
 
 mode_t __umask_chk(mode_t) __INTRODUCED_IN(18);
-mode_t __umask_real(mode_t) __RENAME(umask);
-__errordecl(__umask_invalid_mode, "umask called with invalid mode");
 
 #if defined(__BIONIC_FORTIFY)
+#define __umask_invalid_mode_str "umask called with invalid mode"
+
+#if defined(__clang__)
+
+#if __ANDROID_API__ >= __ANDROID_API_J_MR2__
+/*
+ * Abuse enable_if to make these be seen as overloads of umask, rather than
+ * definitions.
+ */
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+mode_t umask(mode_t mode) __overloadable
+        __enable_if(1, "")
+        __enable_if(mode & ~0777, __umask_invalid_mode_str)
+        __errorattr(__umask_invalid_mode_str);
+
+__BIONIC_FORTIFY_INLINE
+mode_t umask(mode_t mode) __enable_if(1, "") __overloadable {
+  return __umask_chk(mode);
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR2__ */
+
+#else /* defined(__clang__) */
+__errordecl(__umask_invalid_mode, __umask_invalid_mode_str);
+extern mode_t __umask_real(mode_t) __RENAME(umask);
 
 #if __ANDROID_API__ >= __ANDROID_API_J_MR2__
 __BIONIC_FORTIFY_INLINE
 mode_t umask(mode_t mode) {
-#if !defined(__clang__)
   if (__builtin_constant_p(mode)) {
     if ((mode & 0777) != mode) {
       __umask_invalid_mode();
     }
     return __umask_real(mode);
   }
-#endif
   return __umask_chk(mode);
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_J_MR2__ */
 
+#endif /* defined(__clang__) */
+#undef __umask_invalid_mode_str
+
 #endif /* defined(__BIONIC_FORTIFY) */
 
 #if __ANDROID_API__ >= __ANDROID_API_L__
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index cbdb438..b3f8c11 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -139,21 +139,25 @@
 int chroot(const char* __path);
 int symlink(const char* __oldpath, const char* __newpath);
 int symlinkat(const char* __oldpath, int __newdirfd, const char* __newpath) __INTRODUCED_IN(21);
-ssize_t readlink(const char* __path, char* __buf, size_t __bufsiz);
+ssize_t readlink(const char* __path, char* __buf, size_t __bufsiz)
+    __overloadable __RENAME_CLANG(readlink);
 ssize_t readlinkat(int __dirfd, const char* __path, char* __buf,
-                   size_t __bufsiz) __INTRODUCED_IN(21);
+                   size_t __bufsiz)
+    __INTRODUCED_IN(21) __overloadable __RENAME_CLANG(readlinkat);
 int chown(const char* __path, uid_t __owner, gid_t __group);
 int fchown(int __fd, uid_t __owner, gid_t __group);
 int fchownat(int __dirfd, const char* __path, uid_t __owner, gid_t __group, int __flags);
 int lchown(const char* __path, uid_t __owner, gid_t __group);
-char* getcwd(char* __buf, size_t __size);
+char* getcwd(char* __buf, size_t __size) __overloadable __RENAME_CLANG(getcwd);
 
 void sync(void);
 
 int close(int __fd);
 
-ssize_t read(int __fd, void* __buf, size_t __count);
-ssize_t write(int __fd, const void* __buf, size_t __count);
+ssize_t read(int __fd, void* __buf, size_t __count) __overloadable
+    __RENAME_CLANG(read);
+ssize_t write(int __fd, const void* __buf, size_t __count) __overloadable
+    __RENAME_CLANG(write);
 
 int dup(int __oldfd);
 int dup2(int __oldfd, int __newfd);
@@ -171,22 +175,25 @@
 
 #if defined(__USE_FILE_OFFSET64) && __ANDROID_API__ >= __ANDROID_API_L__
 int truncate(const char* __path, off_t __length) __RENAME(truncate64) __INTRODUCED_IN(21);
-ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset) __RENAME(pread64)
-  __INTRODUCED_IN(12);
+ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset)
+  __overloadable __RENAME(pread64) __INTRODUCED_IN(12);
 ssize_t pwrite(int __fd, const void* __buf, size_t __count, off_t __offset)
-  __RENAME(pwrite64) __INTRODUCED_IN(12);
+  __overloadable __RENAME(pwrite64) __INTRODUCED_IN(12);
 int ftruncate(int __fd, off_t __length) __RENAME(ftruncate64) __INTRODUCED_IN(12);
 #else
 int truncate(const char* __path, off_t __length);
-ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset);
-ssize_t pwrite(int __fd, const void* __buf, size_t __count, off_t __offset);
+ssize_t pread(int __fd, void* __buf, size_t __count, off_t __offset)
+    __overloadable __RENAME_CLANG(pread);
+ssize_t pwrite(int __fd, const void* __buf, size_t __count, off_t __offset)
+    __overloadable __RENAME_CLANG(pwrite);
 int ftruncate(int __fd, off_t __length);
 #endif
 
 int truncate64(const char* __path, off64_t __length) __INTRODUCED_IN(21);
-ssize_t pread64(int __fd, void* __buf, size_t __count, off64_t __offset) __INTRODUCED_IN(12);
+ssize_t pread64(int __fd, void* __buf, size_t __count, off64_t __offset)
+    __INTRODUCED_IN(12) __overloadable __RENAME_CLANG(pread64);
 ssize_t pwrite64(int __fd, const void* __buf, size_t __count, off64_t __offset)
-  __INTRODUCED_IN(12);
+    __INTRODUCED_IN(12) __overloadable __RENAME_CLANG(pwrite64);
 int ftruncate64(int __fd, off64_t __length) __INTRODUCED_IN(12);
 
 int pause(void);
@@ -236,70 +243,288 @@
 
 /* TODO(unified-headers): Factor out all the FORTIFY features. */
 char* __getcwd_chk(char*, size_t, size_t) __INTRODUCED_IN(24);
-__errordecl(__getcwd_dest_size_error, "getcwd called with size bigger than destination");
-char* __getcwd_real(char*, size_t) __RENAME(getcwd);
 
 ssize_t __pread_chk(int, void*, size_t, off_t, size_t) __INTRODUCED_IN(23);
-__errordecl(__pread_dest_size_error, "pread called with size bigger than destination");
-__errordecl(__pread_count_toobig_error, "pread called with count > SSIZE_MAX");
 ssize_t __pread_real(int, void*, size_t, off_t) __RENAME(pread);
 
 ssize_t __pread64_chk(int, void*, size_t, off64_t, size_t) __INTRODUCED_IN(23);
-__errordecl(__pread64_dest_size_error, "pread64 called with size bigger than destination");
-__errordecl(__pread64_count_toobig_error, "pread64 called with count > SSIZE_MAX");
 ssize_t __pread64_real(int, void*, size_t, off64_t) __RENAME(pread64) __INTRODUCED_IN(12);
 
 ssize_t __pwrite_chk(int, const void*, size_t, off_t, size_t) __INTRODUCED_IN(24);
-__errordecl(__pwrite_dest_size_error, "pwrite called with size bigger than destination");
-__errordecl(__pwrite_count_toobig_error, "pwrite called with count > SSIZE_MAX");
 ssize_t __pwrite_real(int, const void*, size_t, off_t) __RENAME(pwrite);
 
 ssize_t __pwrite64_chk(int, const void*, size_t, off64_t, size_t) __INTRODUCED_IN(24);
-__errordecl(__pwrite64_dest_size_error, "pwrite64 called with size bigger than destination");
-__errordecl(__pwrite64_count_toobig_error, "pwrite64 called with count > SSIZE_MAX");
-ssize_t __pwrite64_real(int, const void*, size_t, off64_t) __RENAME(pwrite64) __INTRODUCED_IN(12);
+ssize_t __pwrite64_real(int, const void*, size_t, off64_t) __RENAME(pwrite64)
+  __INTRODUCED_IN(12);
 
 ssize_t __read_chk(int, void*, size_t, size_t) __INTRODUCED_IN(21);
-__errordecl(__read_dest_size_error, "read called with size bigger than destination");
-__errordecl(__read_count_toobig_error, "read called with count > SSIZE_MAX");
-ssize_t __read_real(int, void*, size_t) __RENAME(read);
-
 ssize_t __write_chk(int, const void*, size_t, size_t) __INTRODUCED_IN(24);
-__errordecl(__write_dest_size_error, "write called with size bigger than destination");
-__errordecl(__write_count_toobig_error, "write called with count > SSIZE_MAX");
-ssize_t __write_real(int, const void*, size_t) __RENAME(write);
-
 ssize_t __readlink_chk(const char*, char*, size_t, size_t) __INTRODUCED_IN(23);
-__errordecl(__readlink_dest_size_error, "readlink called with size bigger than destination");
-__errordecl(__readlink_size_toobig_error, "readlink called with size > SSIZE_MAX");
-ssize_t __readlink_real(const char*, char*, size_t) __RENAME(readlink);
-
 ssize_t __readlinkat_chk(int dirfd, const char*, char*, size_t, size_t) __INTRODUCED_IN(23);
-__errordecl(__readlinkat_dest_size_error, "readlinkat called with size bigger than destination");
-__errordecl(__readlinkat_size_toobig_error, "readlinkat called with size > SSIZE_MAX");
-ssize_t __readlinkat_real(int dirfd, const char*, char*, size_t) __RENAME(readlinkat) __INTRODUCED_IN(21);
 
 int getdomainname(char*, size_t) __INTRODUCED_IN_FUTURE;
 int setdomainname(const char*, size_t) __INTRODUCED_IN_FUTURE;
 
 #if defined(__BIONIC_FORTIFY)
 
-#if __ANDROID_API__ >= __ANDROID_API_N__
-__BIONIC_FORTIFY_INLINE
-char* getcwd(char* buf, size_t size) {
-    size_t bos = __bos(buf);
+#if defined(__USE_FILE_OFFSET64)
+#define __PREAD_PREFIX(x) __pread64_ ## x
+#define __PWRITE_PREFIX(x) __pwrite64_ ## x
+#else
+#define __PREAD_PREFIX(x) __pread_ ## x
+#define __PWRITE_PREFIX(x) __pwrite_ ## x
+#endif
 
 #if defined(__clang__)
+#define __error_if_overflows_ssizet(what) \
+    __enable_if(what > SSIZE_MAX, #what " must be <= SSIZE_MAX") \
+    __errorattr(#what " must be <= SSIZE_MAX")
+
+#define __enable_if_no_overflow_ssizet(what) \
+    __enable_if((what) <= SSIZE_MAX, "enabled if " #what " <= SSIZE_MAX")
+
+#define __error_if_overflows_objectsize(what, objsize) \
+    __enable_if((objsize) != __BIONIC_FORTIFY_UNKNOWN_SIZE && \
+                    (what) > (objsize), \
+                "'" #what "' bytes overflows the given object") \
+    __errorattr("'" #what "' bytes overflows the given object")
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+char* getcwd(char* buf, size_t size) __overloadable
+        __error_if_overflows_objectsize(size, __bos(buf));
+
+#if __ANDROID_API__ >= __ANDROID_API_N__
+__BIONIC_FORTIFY_INLINE
+char* getcwd(char* const __pass_object_size buf, size_t size) __overloadable {
+    size_t bos = __bos(buf);
+
     /*
-     * Work around LLVM's incorrect __builtin_object_size implementation here
-     * to avoid needing the workaround in the __getcwd_chk ABI forever.
-     *
-     * https://llvm.org/bugs/show_bug.cgi?id=23277
+     * Clang responds bos==0 if buf==NULL
+     * (https://llvm.org/bugs/show_bug.cgi?id=23277). Given that NULL is a valid
+     * value, we need to handle that.
      */
-    if (buf == NULL) {
-        bos = __BIONIC_FORTIFY_UNKNOWN_SIZE;
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE || buf == NULL) {
+        return __call_bypassing_fortify(getcwd)(buf, size);
     }
-#else
+
+    return __getcwd_chk(buf, size, bos);
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
+
+#if __ANDROID_API__ >= __ANDROID_API_M__
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t pread(int fd, void* buf, size_t count, off_t offset) __overloadable
+        __error_if_overflows_ssizet(count);
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t pread(int fd, void* buf, size_t count, off_t offset) __overloadable
+        __enable_if_no_overflow_ssizet(count)
+        __error_if_overflows_objectsize(count, __bos0(buf));
+
+__BIONIC_FORTIFY_INLINE
+ssize_t pread(int fd, void* const __pass_object_size buf, size_t count,
+              off_t offset) __overloadable {
+    size_t bos = __bos0(buf);
+
+    if (count == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __PREAD_PREFIX(real)(fd, buf, count, offset);
+    }
+
+    return __PREAD_PREFIX(chk)(fd, buf, count, offset, bos);
+}
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t pread64(int fd, void* buf, size_t count, off64_t offset) __overloadable
+        __error_if_overflows_ssizet(count);
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t pread64(int fd, void* buf, size_t count, off64_t offset) __overloadable
+        __enable_if_no_overflow_ssizet(count)
+        __error_if_overflows_objectsize(count, __bos0(buf));
+
+__BIONIC_FORTIFY_INLINE
+ssize_t pread64(int fd, void* const __pass_object_size buf, size_t count,
+                off64_t offset) __overloadable {
+    size_t bos = __bos0(buf);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __pread64_real(fd, buf, count, offset);
+    }
+
+    return __pread64_chk(fd, buf, count, offset, bos);
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_M__ */
+
+#if __ANDROID_API__ >= __ANDROID_API_N__
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset)
+        __overloadable
+        __error_if_overflows_ssizet(count);
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset)
+        __overloadable
+        __enable_if_no_overflow_ssizet(count)
+        __error_if_overflows_objectsize(count, __bos0(buf));
+
+__BIONIC_FORTIFY_INLINE
+ssize_t pwrite(int fd, const void* const __pass_object_size buf, size_t count,
+               off_t offset) __overloadable {
+    size_t bos = __bos0(buf);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __PWRITE_PREFIX(real)(fd, buf, count, offset);
+    }
+
+    return __PWRITE_PREFIX(chk)(fd, buf, count, offset, bos);
+}
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t pwrite64(int fd, const void* buf, size_t count, off64_t offset)
+        __overloadable
+        __error_if_overflows_ssizet(count);
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t pwrite64(int fd, const void* buf, size_t count, off64_t offset)
+        __overloadable
+        __enable_if_no_overflow_ssizet(count)
+        __error_if_overflows_objectsize(count, __bos0(buf));
+
+__BIONIC_FORTIFY_INLINE
+ssize_t pwrite64(int fd, const void* const __pass_object_size buf, size_t count,
+                 off64_t offset) __overloadable {
+    size_t bos = __bos0(buf);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __pwrite64_real(fd, buf, count, offset);
+    }
+
+    return __pwrite64_chk(fd, buf, count, offset, bos);
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t read(int fd, void* buf, size_t count) __overloadable
+        __error_if_overflows_ssizet(count);
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t read(int fd, void* buf, size_t count) __overloadable
+        __enable_if_no_overflow_ssizet(count)
+        __error_if_overflows_objectsize(count, __bos0(buf));
+
+__BIONIC_FORTIFY_INLINE
+ssize_t read(int fd, void* const __pass_object_size buf, size_t count)
+        __overloadable {
+    size_t bos = __bos0(buf);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __call_bypassing_fortify(read)(fd, buf, count);
+    }
+
+    return __read_chk(fd, buf, count, bos);
+}
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t write(int fd, const void* buf, size_t count) __overloadable
+        __error_if_overflows_ssizet(count);
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t write(int fd, const void* buf, size_t count) __overloadable
+        __enable_if_no_overflow_ssizet(count)
+        __error_if_overflows_objectsize(count, __bos0(buf));
+
+__BIONIC_FORTIFY_INLINE
+ssize_t write(int fd, const void* const __pass_object_size buf, size_t count)
+        __overloadable {
+    size_t bos = __bos0(buf);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __call_bypassing_fortify(write)(fd, buf, count);
+    }
+
+    return __write_chk(fd, buf, count, bos);
+}
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t readlink(const char* path, char* buf, size_t size) __overloadable
+        __error_if_overflows_ssizet(size);
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t readlink(const char* path, char* buf, size_t size) __overloadable
+        __enable_if_no_overflow_ssizet(size)
+        __error_if_overflows_objectsize(size, __bos(buf));
+
+__BIONIC_FORTIFY_INLINE
+ssize_t readlink(const char* path, char* const __pass_object_size buf,
+                 size_t size) __overloadable {
+    size_t bos = __bos(buf);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __call_bypassing_fortify(readlink)(path, buf, size);
+    }
+
+    return __readlink_chk(path, buf, size, bos);
+}
+
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t readlinkat(int dirfd, const char* path, char* buf, size_t size)
+        __overloadable
+        __error_if_overflows_ssizet(size);
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+ssize_t readlinkat(int dirfd, const char* path, char* buf, size_t size)
+        __overloadable
+        __enable_if_no_overflow_ssizet(size)
+        __error_if_overflows_objectsize(size, __bos(buf));
+
+__BIONIC_FORTIFY_INLINE
+ssize_t readlinkat(int dirfd, const char* path,
+                   char* const __pass_object_size buf, size_t size)
+        __overloadable {
+    size_t bos = __bos(buf);
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __call_bypassing_fortify(readlinkat)(dirfd, path, buf, size);
+    }
+
+    return __readlinkat_chk(dirfd, path, buf, size, bos);
+}
+
+#undef __enable_if_no_overflow_ssizet
+#undef __error_if_overflows_objectsize
+#undef __error_if_overflows_ssizet
+#else /* defined(__clang__) */
+
+char* __getcwd_real(char*, size_t) __RENAME(getcwd);
+ssize_t __read_real(int, void*, size_t) __RENAME(read);
+ssize_t __write_real(int, const void*, size_t) __RENAME(write);
+ssize_t __readlink_real(const char*, char*, size_t) __RENAME(readlink);
+ssize_t __readlinkat_real(int dirfd, const char*, char*, size_t) __RENAME(readlinkat);
+
+__errordecl(__getcwd_dest_size_error, "getcwd called with size bigger than destination");
+__errordecl(__pread_dest_size_error, "pread called with size bigger than destination");
+__errordecl(__pread_count_toobig_error, "pread called with count > SSIZE_MAX");
+__errordecl(__pread64_dest_size_error, "pread64 called with size bigger than destination");
+__errordecl(__pread64_count_toobig_error, "pread64 called with count > SSIZE_MAX");
+__errordecl(__pwrite_dest_size_error, "pwrite called with size bigger than destination");
+__errordecl(__pwrite_count_toobig_error, "pwrite called with count > SSIZE_MAX");
+__errordecl(__pwrite64_dest_size_error, "pwrite64 called with size bigger than destination");
+__errordecl(__pwrite64_count_toobig_error, "pwrite64 called with count > SSIZE_MAX");
+__errordecl(__read_dest_size_error, "read called with size bigger than destination");
+__errordecl(__read_count_toobig_error, "read called with count > SSIZE_MAX");
+__errordecl(__write_dest_size_error, "write called with size bigger than destination");
+__errordecl(__write_count_toobig_error, "write called with count > SSIZE_MAX");
+__errordecl(__readlink_dest_size_error, "readlink called with size bigger than destination");
+__errordecl(__readlink_size_toobig_error, "readlink called with size > SSIZE_MAX");
+__errordecl(__readlinkat_dest_size_error, "readlinkat called with size bigger than destination");
+__errordecl(__readlinkat_size_toobig_error, "readlinkat called with size > SSIZE_MAX");
+
+#if __ANDROID_API__ >= __ANDROID_API_N__
+__BIONIC_FORTIFY_INLINE
+char* getcwd(char* buf, size_t size) __overloadable {
+    size_t bos = __bos(buf);
+
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __getcwd_real(buf, size);
     }
@@ -311,24 +536,16 @@
     if (__builtin_constant_p(size) && (size <= bos)) {
         return __getcwd_real(buf, size);
     }
-#endif
 
     return __getcwd_chk(buf, size, bos);
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_N__ */
 
-#if defined(__USE_FILE_OFFSET64)
-#define __PREAD_PREFIX(x) __pread64_ ## x
-#else
-#define __PREAD_PREFIX(x) __pread_ ## x
-#endif
-
 #if __ANDROID_API__ >= __ANDROID_API_M__
 __BIONIC_FORTIFY_INLINE
 ssize_t pread(int fd, void* buf, size_t count, off_t offset) {
     size_t bos = __bos0(buf);
 
-#if !defined(__clang__)
     if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
         __PREAD_PREFIX(count_toobig_error)();
     }
@@ -344,7 +561,6 @@
     if (__builtin_constant_p(count) && (count <= bos)) {
         return __PREAD_PREFIX(real)(fd, buf, count, offset);
     }
-#endif
 
     return __PREAD_PREFIX(chk)(fd, buf, count, offset, bos);
 }
@@ -353,7 +569,6 @@
 ssize_t pread64(int fd, void* buf, size_t count, off64_t offset) {
     size_t bos = __bos0(buf);
 
-#if !defined(__clang__)
     if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
         __pread64_count_toobig_error();
     }
@@ -369,24 +584,16 @@
     if (__builtin_constant_p(count) && (count <= bos)) {
         return __pread64_real(fd, buf, count, offset);
     }
-#endif
 
     return __pread64_chk(fd, buf, count, offset, bos);
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_M__ */
 
-#if defined(__USE_FILE_OFFSET64)
-#define __PWRITE_PREFIX(x) __pwrite64_ ## x
-#else
-#define __PWRITE_PREFIX(x) __pwrite_ ## x
-#endif
-
 #if __ANDROID_API__ >= __ANDROID_API_N__
 __BIONIC_FORTIFY_INLINE
 ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset) {
     size_t bos = __bos0(buf);
 
-#if !defined(__clang__)
     if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
         __PWRITE_PREFIX(count_toobig_error)();
     }
@@ -402,7 +609,6 @@
     if (__builtin_constant_p(count) && (count <= bos)) {
         return __PWRITE_PREFIX(real)(fd, buf, count, offset);
     }
-#endif
 
     return __PWRITE_PREFIX(chk)(fd, buf, count, offset, bos);
 }
@@ -411,7 +617,6 @@
 ssize_t pwrite64(int fd, const void* buf, size_t count, off64_t offset) {
     size_t bos = __bos0(buf);
 
-#if !defined(__clang__)
     if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
         __pwrite64_count_toobig_error();
     }
@@ -427,7 +632,6 @@
     if (__builtin_constant_p(count) && (count <= bos)) {
         return __pwrite64_real(fd, buf, count, offset);
     }
-#endif
 
     return __pwrite64_chk(fd, buf, count, offset, bos);
 }
@@ -438,7 +642,6 @@
 ssize_t read(int fd, void* buf, size_t count) {
     size_t bos = __bos0(buf);
 
-#if !defined(__clang__)
     if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
         __read_count_toobig_error();
     }
@@ -454,7 +657,6 @@
     if (__builtin_constant_p(count) && (count <= bos)) {
         return __read_real(fd, buf, count);
     }
-#endif
 
     return __read_chk(fd, buf, count, bos);
 }
@@ -465,13 +667,6 @@
 ssize_t write(int fd, const void* buf, size_t count) {
     size_t bos = __bos0(buf);
 
-#if !defined(__clang__)
-#if 0 /* work around a false positive due to a missed optimization */
-    if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
-        __write_count_toobig_error();
-    }
-#endif
-
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __write_real(fd, buf, count);
     }
@@ -483,7 +678,6 @@
     if (__builtin_constant_p(count) && (count <= bos)) {
         return __write_real(fd, buf, count);
     }
-#endif
 
     return __write_chk(fd, buf, count, bos);
 }
@@ -494,7 +688,6 @@
 ssize_t readlink(const char* path, char* buf, size_t size) {
     size_t bos = __bos(buf);
 
-#if !defined(__clang__)
     if (__builtin_constant_p(size) && (size > SSIZE_MAX)) {
         __readlink_size_toobig_error();
     }
@@ -510,7 +703,6 @@
     if (__builtin_constant_p(size) && (size <= bos)) {
         return __readlink_real(path, buf, size);
     }
-#endif
 
     return __readlink_chk(path, buf, size, bos);
 }
@@ -519,7 +711,6 @@
 ssize_t readlinkat(int dirfd, const char* path, char* buf, size_t size) {
     size_t bos = __bos(buf);
 
-#if !defined(__clang__)
     if (__builtin_constant_p(size) && (size > SSIZE_MAX)) {
         __readlinkat_size_toobig_error();
     }
@@ -535,12 +726,13 @@
     if (__builtin_constant_p(size) && (size <= bos)) {
         return __readlinkat_real(dirfd, path, buf, size);
     }
-#endif
 
     return __readlinkat_chk(dirfd, path, buf, size, bos);
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_M__ */
-
+#endif /* defined(__clang__) */
+#undef __PREAD_PREFIX
+#undef __PWRITE_PREFIX
 #endif /* defined(__BIONIC_FORTIFY) */
 
 __END_DECLS
diff --git a/libc/stdio/fread.c b/libc/stdio/fread.c
index f3f0127..7b858ae 100644
--- a/libc/stdio/fread.c
+++ b/libc/stdio/fread.c
@@ -41,7 +41,7 @@
 #define MUL_NO_OVERFLOW	(1UL << (sizeof(size_t) * 4))
 
 size_t
-fread(void *buf, size_t size, size_t count, FILE *fp)
+fread(void *buf, size_t size, size_t count, FILE *fp) __overloadable
 {
 	/*
 	 * Extension:  Catch integer overflow.
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/realpath.c b/libc/upstream-freebsd/lib/libc/stdlib/realpath.c
index c4bd953..914ecc9 100644
--- a/libc/upstream-freebsd/lib/libc/stdlib/realpath.c
+++ b/libc/upstream-freebsd/lib/libc/stdlib/realpath.c
@@ -48,7 +48,7 @@
  * in which case the path which caused trouble is left in (resolved).
  */
 char *
-realpath(const char * __restrict path, char * __restrict resolved)
+realpath(const char * __restrict path, char * __restrict resolved) __overloadable
 {
 	struct stat sb;
 	char *p, *q, *s;
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fgets.c b/libc/upstream-openbsd/lib/libc/stdio/fgets.c
index 0ba8770..345884a 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fgets.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fgets.c
@@ -43,7 +43,7 @@
  * Do not return NULL if n == 1.
  */
 char *
-fgets(char *buf, int n, FILE *fp)
+fgets(char *buf, int n, FILE *fp) __overloadable
 {
 	size_t len;
 	char *s;
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fwrite.c b/libc/upstream-openbsd/lib/libc/stdio/fwrite.c
index f0a17bf..c72d968 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fwrite.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fwrite.c
@@ -45,7 +45,7 @@
  * Return the number of whole objects written.
  */
 size_t
-fwrite(const void *buf, size_t size, size_t count, FILE *fp)
+fwrite(const void *buf, size_t size, size_t count, FILE *fp) __overloadable
 {
 	size_t n;
 	struct __suio uio;
diff --git a/libc/upstream-openbsd/lib/libc/string/memchr.c b/libc/upstream-openbsd/lib/libc/string/memchr.c
index 4573e3c..05a1197 100644
--- a/libc/upstream-openbsd/lib/libc/string/memchr.c
+++ b/libc/upstream-openbsd/lib/libc/string/memchr.c
@@ -34,8 +34,7 @@
 #include <string.h>
 
 void *
-memchr(const void *s, int c, size_t n)
-{
+memchr(const void *s, int c, size_t n) __overloadable {
 	if (n != 0) {
 		const unsigned char *p = s;
 
diff --git a/libc/upstream-openbsd/lib/libc/string/memmove.c b/libc/upstream-openbsd/lib/libc/string/memmove.c
index 1baad53..910f48c 100644
--- a/libc/upstream-openbsd/lib/libc/string/memmove.c
+++ b/libc/upstream-openbsd/lib/libc/string/memmove.c
@@ -46,7 +46,7 @@
  * Copy a block of memory, handling overlap.
  */
 void *
-memmove(void *dst0, const void *src0, size_t length)
+memmove(void *dst0, const void *src0, size_t length) __overloadable
 {
 	char *dst = dst0;
 	const char *src = src0;
diff --git a/libc/upstream-openbsd/lib/libc/string/memrchr.c b/libc/upstream-openbsd/lib/libc/string/memrchr.c
index bd27ebc..1cce809 100644
--- a/libc/upstream-openbsd/lib/libc/string/memrchr.c
+++ b/libc/upstream-openbsd/lib/libc/string/memrchr.c
@@ -23,7 +23,7 @@
  * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
  */
 void *
-memrchr(const void *s, int c, size_t n)
+memrchr(const void *s, int c, size_t n) __overloadable
 {
 	const unsigned char *cp;
 
diff --git a/libc/upstream-openbsd/lib/libc/string/stpcpy.c b/libc/upstream-openbsd/lib/libc/string/stpcpy.c
index d88afac..3ed5782 100644
--- a/libc/upstream-openbsd/lib/libc/string/stpcpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/stpcpy.c
@@ -37,7 +37,7 @@
 #endif
 
 char *
-stpcpy(char *to, const char *from)
+stpcpy(char *to, const char *from) __overloadable
 {
 	for (; (*to = *from) != '\0'; ++from, ++to);
 	return(to);
diff --git a/libc/upstream-openbsd/lib/libc/string/stpncpy.c b/libc/upstream-openbsd/lib/libc/string/stpncpy.c
index c7c2a57..661a4fd 100644
--- a/libc/upstream-openbsd/lib/libc/string/stpncpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/stpncpy.c
@@ -35,7 +35,7 @@
 #include <string.h>
 
 char *
-stpncpy(char *dst, const char *src, size_t n)
+stpncpy(char *dst, const char *src, size_t n) __overloadable
 {
 	if (n != 0) {
 		char *d = dst;
diff --git a/libc/upstream-openbsd/lib/libc/string/strcat.c b/libc/upstream-openbsd/lib/libc/string/strcat.c
index 646c9c2..7872a2d 100644
--- a/libc/upstream-openbsd/lib/libc/string/strcat.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcat.c
@@ -37,7 +37,7 @@
 #endif
 
 char *
-strcat(char *s, const char *append)
+strcat(char *s, const char *append) __overloadable
 {
 	char *save = s;
 
diff --git a/libc/upstream-openbsd/lib/libc/string/strcpy.c b/libc/upstream-openbsd/lib/libc/string/strcpy.c
index 5a9001e..1b1169c 100644
--- a/libc/upstream-openbsd/lib/libc/string/strcpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcpy.c
@@ -37,7 +37,7 @@
 #endif
 
 char *
-strcpy(char *to, const char *from)
+strcpy(char *to, const char *from) __overloadable
 {
 	char *save = to;
 
diff --git a/libc/upstream-openbsd/lib/libc/string/strlcat.c b/libc/upstream-openbsd/lib/libc/string/strlcat.c
index 073b0d4..7bf98aa 100644
--- a/libc/upstream-openbsd/lib/libc/string/strlcat.c
+++ b/libc/upstream-openbsd/lib/libc/string/strlcat.c
@@ -27,7 +27,7 @@
  * If retval >= dsize, truncation occurred.
  */
 size_t
-strlcat(char *dst, const char *src, size_t dsize)
+strlcat(char *dst, const char *src, size_t dsize) __overloadable
 {
 	const char *odst = dst;
 	const char *osrc = src;
diff --git a/libc/upstream-openbsd/lib/libc/string/strlcpy.c b/libc/upstream-openbsd/lib/libc/string/strlcpy.c
index 5fcf084..a5343b8 100644
--- a/libc/upstream-openbsd/lib/libc/string/strlcpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/strlcpy.c
@@ -25,7 +25,7 @@
  * Returns strlen(src); if retval >= dsize, truncation occurred.
  */
 size_t
-strlcpy(char *dst, const char *src, size_t dsize)
+strlcpy(char *dst, const char *src, size_t dsize) __overloadable
 {
 	const char *osrc = src;
 	size_t nleft = dsize;
diff --git a/libc/upstream-openbsd/lib/libc/string/strncat.c b/libc/upstream-openbsd/lib/libc/string/strncat.c
index c4df4f2..32334b3 100644
--- a/libc/upstream-openbsd/lib/libc/string/strncat.c
+++ b/libc/upstream-openbsd/lib/libc/string/strncat.c
@@ -38,7 +38,7 @@
  * are written at dst (at most n+1 bytes being appended).  Return dst.
  */
 char *
-strncat(char *dst, const char *src, size_t n)
+strncat(char *dst, const char *src, size_t n) __overloadable
 {
 	if (n != 0) {
 		char *d = dst;
diff --git a/libc/upstream-openbsd/lib/libc/string/strncpy.c b/libc/upstream-openbsd/lib/libc/string/strncpy.c
index 5003a19..e83c7e5 100644
--- a/libc/upstream-openbsd/lib/libc/string/strncpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/strncpy.c
@@ -39,7 +39,7 @@
  * Return dst.
  */
 char *
-strncpy(char *dst, const char *src, size_t n)
+strncpy(char *dst, const char *src, size_t n) __overloadable
 {
 	if (n != 0) {
 		char *d = dst;
diff --git a/linker/linker_allocator.cpp b/linker/linker_allocator.cpp
index dc6dfc1..f81f78d 100644
--- a/linker/linker_allocator.cpp
+++ b/linker/linker_allocator.cpp
@@ -196,8 +196,6 @@
 
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, PAGE_SIZE, "linker_alloc_small_objects");
 
-  memset(map_ptr, 0, PAGE_SIZE);
-
   page_info* info = reinterpret_cast<page_info*>(map_ptr);
   memcpy(info->signature, kSignature, sizeof(kSignature));
   info->type = type_;
@@ -243,8 +241,6 @@
 
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, allocated_size, "linker_alloc_lob");
 
-  memset(map_ptr, 0, allocated_size);
-
   page_info* info = reinterpret_cast<page_info*>(map_ptr);
   memcpy(info->signature, kSignature, sizeof(kSignature));
   info->type = kLargeObject;
diff --git a/linker/linker_block_allocator.cpp b/linker/linker_block_allocator.cpp
index 23298a4..1211b98 100644
--- a/linker/linker_block_allocator.cpp
+++ b/linker/linker_block_allocator.cpp
@@ -113,8 +113,6 @@
 
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, PAGE_SIZE, "linker_alloc");
 
-  memset(page, 0, PAGE_SIZE);
-
   FreeBlockInfo* first_block = reinterpret_cast<FreeBlockInfo*>(page->bytes);
   first_block->next_block = free_block_list_;
   first_block->num_free_blocks = (PAGE_SIZE - sizeof(LinkerBlockAllocatorPage*))/block_size_;
diff --git a/tests/Android.mk b/tests/Android.mk
index b65b456..24ff7f2 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -77,7 +77,7 @@
 LOCAL_MODULE := bionic-compile-time-tests-g++
 LOCAL_CPPFLAGS := -Wall
 # Disable color diagnostics so the warnings output matches the source
-LOCAL_CPPFLAGS +=  -fdiagnostics-color=never
+LOCAL_CPPFLAGS += -fdiagnostics-color=never
 LOCAL_SRC_FILES := fortify_compilation_test.cpp
 include $(BUILD_STATIC_LIBRARY)
 
@@ -95,11 +95,8 @@
 LOCAL_CLANG := true
 LOCAL_MODULE := bionic-compile-time-tests-clang++
 LOCAL_CPPFLAGS := -Wall
-# Disable color diagnostics so the warnings output matches the source
-LOCAL_CPPFLAGS += -fno-color-diagnostics
-# FileCheck will error if there aren't any CLANG: lines in the file, but there
-# don't appear to be any cases where clang _does_ emit warnings for sn?printf :(
-LOCAL_SRC_FILES :=
+LOCAL_CPPFLAGS += -fno-color-diagnostics -ferror-limit=10000
+LOCAL_SRC_FILES := fortify_compilation_test.cpp
 include $(BUILD_STATIC_LIBRARY)
 
 endif # linux-x86
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index a56e3a7..3e9e85e 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1136,6 +1136,28 @@
 #endif
 }
 
+static std::string g_fini_call_order_str;
+
+static void register_fini_call(const char* s) {
+  g_fini_call_order_str += s;
+}
+
+TEST(dlfcn, init_fini_call_order) {
+  void* handle = dlopen("libtest_init_fini_order_root.so", RTLD_NOW);
+  ASSERT_TRUE(handle != nullptr) << dlerror();
+  typedef int (*get_init_order_number_t)();
+  get_init_order_number_t get_init_order_number =
+          reinterpret_cast<get_init_order_number_t>(dlsym(handle, "get_init_order_number"));
+  ASSERT_EQ(321, get_init_order_number());
+
+  typedef void (*set_fini_callback_t)(void (*f)(const char*));
+  set_fini_callback_t set_fini_callback =
+          reinterpret_cast<set_fini_callback_t>(dlsym(handle, "set_fini_callback"));
+  set_fini_callback(register_fini_call);
+  dlclose(handle);
+  ASSERT_EQ("(root)(child)(grandchild)", g_fini_call_order_str);
+}
+
 TEST(dlfcn, symbol_versioning_use_v1) {
   void* handle = dlopen("libtest_versioned_uselibv1.so", RTLD_NOW);
   ASSERT_TRUE(handle != nullptr) << dlerror();
diff --git a/tests/fortify_compilation_test.cpp b/tests/fortify_compilation_test.cpp
index 1326597..1b02d4e 100644
--- a/tests/fortify_compilation_test.cpp
+++ b/tests/fortify_compilation_test.cpp
@@ -33,7 +33,7 @@
 
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: warning: call to int __builtin___sprintf_chk(char*, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'sprintf': format string will always overflow destination buffer
   sprintf(buf, "foobar");  // NOLINT(runtime/printf)
 
   // NOLINTNEXTLINE(whitespace/line_length)
@@ -47,7 +47,7 @@
 
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: warning: call to int __builtin___snprintf_chk(char*, {{(long )?}}unsigned int, int, {{(long )?}}unsigned int, const char*, ...) will always overflow destination buffer
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'snprintf': format string will always overflow destination buffer
   snprintf(buf, 5, "foobar");  // NOLINT(runtime/printf)
 
   // NOLINTNEXTLINE(whitespace/line_length)
@@ -71,8 +71,8 @@
 
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: warning: call to void* __builtin___memcpy_chk(void*, const void*, {{(long )?}}unsigned int, {{(long )?}}unsigned int) will always overflow destination buffer
-  // clang should emit a warning, but doesn't
-  memcpy(buf, "foobar", sizeof("foobar"));
+  // CLANG: error: call to unavailable function 'memcpy': memcpy called with size bigger than buffer
+  memcpy(buf, "foobar", sizeof("foobar") + 100);
 }
 
 void test_memmove() {
@@ -80,7 +80,7 @@
 
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: warning: call to void* __builtin___memmove_chk(void*, const void*, {{(long )?}}unsigned int, {{(long )?}}unsigned int) will always overflow destination buffer
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'memmove': memmove called with size bigger than buffer
   memmove(buf, "foobar", sizeof("foobar"));
 }
 
@@ -89,7 +89,7 @@
 
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: warning: call to void* __builtin___memset_chk(void*, int, {{(long )?}}unsigned int, {{(long )?}}unsigned int) will always overflow destination buffer
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'memset': memset called with size bigger than buffer
   memset(buf, 0, 6);
 }
 
@@ -98,7 +98,7 @@
 
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: warning: call to {{(char\* __builtin___strcpy_chk\(char\*, const char\*, unsigned int\))|(void\* __builtin___memcpy_chk\(void\*, const void\*, (long )?unsigned int, (long )?unsigned int\))}} will always overflow destination buffer
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'strcpy': strcpy called with string bigger than buffer
   strcpy(buf, "foobar");  // NOLINT(runtime/printf)
 }
 
@@ -107,7 +107,7 @@
 
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: warning: call to char* __builtin___stpcpy_chk(char*, const char*, {{(long )?}}unsigned int) will always overflow destination buffer
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'stpcpy': stpcpy called with string bigger than buffer
   stpcpy(buf, "foobar");
 }
 
@@ -169,12 +169,12 @@
 
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__fgets_too_small_error' declared with attribute error: fgets called with size less than zero
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'fgets': size is negative
   fgets(buf, -1, stdin);
 
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__fgets_too_big_error' declared with attribute error: fgets called with size bigger than buffer
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'fgets': size is larger than the destination buffer
   fgets(buf, 6, stdin);
 }
 
@@ -184,14 +184,14 @@
 
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__recvfrom_error' declared with attribute error: recvfrom called with size bigger than buffer
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'recvfrom': size is larger than the destination buffer
   recvfrom(0, buf, 6, 0, reinterpret_cast<sockaddr*>(&addr), NULL);
 }
 
 void test_umask() {
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__umask_invalid_mode' declared with attribute error: umask called with invalid mode
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'umask': umask called with invalid mode
   umask(01777);
 }
 
@@ -199,19 +199,19 @@
   char buf[4];
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__read_dest_size_error' declared with attribute error: read called with size bigger than destination
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'read': 'count' bytes overflows the given object
   read(0, buf, 6);
 }
 
 void test_open() {
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__creat_missing_mode' declared with attribute error: called with O_CREAT, but missing mode
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'open': called with O_CREAT, but missing mode
   open("/dev/null", O_CREAT);
 
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__creat_too_many_args' declared with attribute error: too many arguments
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'open': too many arguments
   open("/dev/null", O_CREAT, 0, 0);
 }
 
@@ -219,7 +219,7 @@
   pollfd fds[1];
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__poll_too_small_error' declared with attribute error: poll: pollfd array smaller than fd count
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'poll': too many fds specified
   poll(fds, 2, 0);
 }
 
@@ -228,7 +228,7 @@
   timespec timeout;
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__ppoll_too_small_error' declared with attribute error: ppoll: pollfd array smaller than fd count
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'ppoll': too many fds specified
   ppoll(fds, 2, &timeout, NULL);
 }
 
@@ -236,7 +236,7 @@
   char buf[4];
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__fread_overflow' declared with attribute error: fread called with overflowing size * count
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'fread': size * count overflows
   fread(buf, 2, (size_t)-1, stdin);
 }
 
@@ -244,7 +244,7 @@
   char buf[4];
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__fread_too_big_error' declared with attribute error: fread called with size * count bigger than buffer
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'fread': size * count is too large
   fread(buf, 1, 5, stdin);
 }
 
@@ -252,7 +252,7 @@
   char buf[4] = {0};
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__fwrite_overflow' declared with attribute error: fwrite called with overflowing size * count
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'fwrite': size * count overflows
   fwrite(buf, 2, (size_t)-1, stdout);
 }
 
@@ -260,7 +260,7 @@
   char buf[4] = {0};
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__fwrite_too_big_error' declared with attribute error: fwrite called with size * count bigger than buffer
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'fwrite': size * count is too large
   fwrite(buf, 1, 5, stdout);
 }
 
@@ -268,7 +268,7 @@
   char buf[4];
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__getcwd_dest_size_error' declared with attribute error: getcwd called with size bigger than destination
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'getcwd': 'size' bytes overflows the given object
   getcwd(buf, 5);
 }
 
@@ -276,15 +276,23 @@
   char buf[4] = {0};
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__pwrite64_dest_size_error' declared with attribute error: pwrite64 called with size bigger than destination
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'pwrite64': 'count' bytes overflows the given object
   pwrite64(STDOUT_FILENO, buf, 5, 0);
 }
 
-void test_pwrite64_too_big() {
+void test_pwrite64_too_big_malloc() {
   void *buf = calloc(atoi("5"), 1);
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__pwrite64_count_toobig_error' declared with attribute error: pwrite64 called with count > SSIZE_MAX
-  // clang should emit a warning, but doesn't
+  // clang should emit a warning, but probably never will.
+  pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0);
+}
+
+void test_pwrite64_too_big() {
+  char buf[4] = {0};
+  // NOLINTNEXTLINE(whitespace/line_length)
+  // GCC: error: call to '__pwrite64_count_toobig_error' declared with attribute error: pwrite64 called with count > SSIZE_MAX
+  // CLANG: error: call to unavailable function 'pwrite64': count must be <= SSIZE_MAX
   pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0);
 }
 
@@ -292,6 +300,13 @@
   char buf[4] = {0};
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__write_dest_size_error' declared with attribute error: write called with size bigger than destination
-  // clang should emit a warning, but doesn't
+  // CLANG: error: call to unavailable function 'write': 'count' bytes overflows the given object
   write(STDOUT_FILENO, buf, 5);
 }
+
+void test_memset_args_flipped() {
+  char from[4] = {0};
+  // NOLINTNEXTLINE(whitespace/line_length)
+  // CLANG: 'memset' is deprecated: will set 0 bytes; maybe the arguments got flipped? (Add __bionic_zero_size_is_okay as a fourth argument to silence this.)
+  memset(from, sizeof(from), 0);
+}
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 7802727..31a0916 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -448,6 +448,29 @@
 }
 
 // -----------------------------------------------------------------------------
+// Library used to check init/fini call order
+// -----------------------------------------------------------------------------
+cc_test_library {
+    name: "libtest_init_fini_order_root",
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["dlopen_check_init_fini_root.cpp"],
+    shared_libs: ["libtest_init_fini_order_child"],
+}
+
+cc_test_library {
+    name: "libtest_init_fini_order_child",
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["dlopen_check_init_fini_child.cpp"],
+    shared_libs: ["libtest_init_fini_order_grand_child"],
+}
+
+cc_test_library {
+    name: "libtest_init_fini_order_grand_child",
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["dlopen_check_init_fini_grand_child.cpp"],
+}
+
+// -----------------------------------------------------------------------------
 // Library that depends on the library with constructor that calls dlopen() b/7941716
 // -----------------------------------------------------------------------------
 cc_test_library {
diff --git a/tests/libs/dlopen_check_init_fini_child.cpp b/tests/libs/dlopen_check_init_fini_child.cpp
new file mode 100644
index 0000000..bdb5f06
--- /dev/null
+++ b/tests/libs/dlopen_check_init_fini_child.cpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+#include <string>
+
+// These two function are called by local group's constructors and destructors
+extern "C" __attribute__((weak)) void record_init(int digit);
+extern "C" __attribute__((weak)) void record_fini(const char* s);
+
+static void __attribute__((constructor)) init() {
+  record_init(2);
+}
+
+static void __attribute__((destructor)) fini() {
+  record_fini("(child)");
+}
diff --git a/tests/libs/dlopen_check_init_fini_grand_child.cpp b/tests/libs/dlopen_check_init_fini_grand_child.cpp
new file mode 100644
index 0000000..7900f39
--- /dev/null
+++ b/tests/libs/dlopen_check_init_fini_grand_child.cpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+#include <string>
+
+// These two function are called by local group's constructors and destructors
+extern "C" __attribute__((weak)) void record_init(int digit);
+extern "C" __attribute__((weak)) void record_fini(const char* s);
+
+static void __attribute__((constructor)) init() {
+  record_init(3);
+}
+
+static void __attribute__((destructor)) fini() {
+  record_fini("(grandchild)");
+}
diff --git a/tests/libs/dlopen_check_init_fini_root.cpp b/tests/libs/dlopen_check_init_fini_root.cpp
new file mode 100644
index 0000000..45394ec
--- /dev/null
+++ b/tests/libs/dlopen_check_init_fini_root.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+#include <string>
+
+static int volatile g_initialization_order_code;
+
+void (*g_fini_callback)(const char*) = nullptr;
+
+// These two function are called by local group's constructors and destructors
+extern "C" void record_init(int digit) {
+  g_initialization_order_code = g_initialization_order_code*10 + digit;
+}
+
+extern "C" void record_fini(const char* s) {
+  g_fini_callback(s);
+}
+
+// these 2 functions are used by the test
+extern "C" int get_init_order_number() {
+  return g_initialization_order_code;
+}
+
+extern "C" void set_fini_callback(void (*f)(const char*)) {
+  g_fini_callback = f;
+}
+
+static void __attribute__((constructor)) init() {
+  record_init(1);
+}
+
+static void __attribute__((destructor)) fini() {
+  record_fini("(root)");
+}