Merge "Move API levels from `uint32_t` to `int`."
diff --git a/libc/Android.bp b/libc/Android.bp
index 22678f1..6209374 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -268,23 +268,11 @@
                 "upstream-freebsd/lib/libc/string/wcscmp.c",
                 "upstream-freebsd/lib/libc/string/wcslen.c",
                 "upstream-freebsd/lib/libc/string/wcsrchr.c",
+                "upstream-freebsd/lib/libc/string/wmemcmp.c",
+                "upstream-freebsd/lib/libc/string/wcscat.c",
+                "upstream-freebsd/lib/libc/string/wcscpy.c",
+                "upstream-freebsd/lib/libc/string/wmemcmp.c",
             ],
-            atom: {
-                exclude_srcs: [
-                    "upstream-freebsd/lib/libc/string/wmemcmp.c",
-                ],
-            },
-            ssse3: {
-                exclude_srcs: [
-                    "upstream-freebsd/lib/libc/string/wcscat.c",
-                    "upstream-freebsd/lib/libc/string/wcscpy.c",
-                ],
-            },
-            sse4: {
-                exclude_srcs: [
-                    "upstream-freebsd/lib/libc/string/wmemcmp.c",
-                ],
-            },
         },
     },
 
@@ -603,14 +591,10 @@
                 "upstream-openbsd/lib/libc/string/strcpy.c",
                 "upstream-openbsd/lib/libc/string/strncmp.c",
                 "upstream-openbsd/lib/libc/string/strncpy.c",
+                "upstream-openbsd/lib/libc/string/strlcat.c",
+                "upstream-openbsd/lib/libc/string/strlcpy.c",
+                "upstream-openbsd/lib/libc/string/strncat.c",
             ],
-            ssse3: {
-                exclude_srcs: [
-                    "upstream-openbsd/lib/libc/string/strlcat.c",
-                    "upstream-openbsd/lib/libc/string/strlcpy.c",
-                    "upstream-openbsd/lib/libc/string/strncat.c",
-                ],
-            },
         },
 
         x86_64: {
@@ -1136,6 +1120,14 @@
                 "arch-x86/generic/string/strcmp.S",
                 "arch-x86/generic/string/strncmp.S",
                 "arch-x86/generic/string/strcat.S",
+
+                "arch-x86/generic/string/strlcat.c",
+                "arch-x86/generic/string/strlcpy.c",
+                "arch-x86/generic/string/strncat.c",
+                "arch-x86/generic/string/wcscat.c",
+                "arch-x86/generic/string/wcscpy.c",
+                "arch-x86/generic/string/wmemcmp.c",
+
                 "arch-x86/atom/string/sse2-memchr-atom.S",
                 "arch-x86/atom/string/sse2-memrchr-atom.S",
                 "arch-x86/atom/string/sse2-strchr-atom.S",
@@ -1160,6 +1152,29 @@
                 "arch-x86/bionic/setjmp.S",
                 "arch-x86/bionic/syscall.S",
                 "arch-x86/bionic/vfork.S",
+
+                // ssse3 functions
+                "arch-x86/atom/string/ssse3-strcat-atom.S",
+                "arch-x86/atom/string/ssse3-strcmp-atom.S",
+                "arch-x86/atom/string/ssse3-strlcat-atom.S",
+                "arch-x86/atom/string/ssse3-strlcpy-atom.S",
+                "arch-x86/atom/string/ssse3-strncat-atom.S",
+                "arch-x86/atom/string/ssse3-strncmp-atom.S",
+                "arch-x86/atom/string/ssse3-wcscat-atom.S",
+                "arch-x86/atom/string/ssse3-wcscpy-atom.S",
+
+                // sse4 functions
+                "arch-x86/silvermont/string/sse4-memcmp-slm.S",
+                "arch-x86/silvermont/string/sse4-wmemcmp-slm.S",
+
+                // atom functions
+                "arch-x86/atom/string/sse2-memset-atom.S",
+                "arch-x86/atom/string/sse2-strlen-atom.S",
+                "arch-x86/atom/string/ssse3-memcmp-atom.S",
+                "arch-x86/atom/string/ssse3-memmove-atom.S",
+                "arch-x86/atom/string/ssse3-strcpy-atom.S",
+                "arch-x86/atom/string/ssse3-strncpy-atom.S",
+                "arch-x86/atom/string/ssse3-wmemcmp-atom.S",
             ],
 
             exclude_srcs: [
@@ -1167,51 +1182,6 @@
                 "bionic/strnlen.c",
                 "bionic/strrchr.cpp",
             ],
-            atom: {
-                srcs: [
-                    "arch-x86/atom/string/sse2-memset-atom.S",
-                    "arch-x86/atom/string/sse2-strlen-atom.S",
-                    "arch-x86/atom/string/ssse3-memcmp-atom.S",
-                    "arch-x86/atom/string/ssse3-memcpy-atom.S",
-                    "arch-x86/atom/string/ssse3-strcpy-atom.S",
-                    "arch-x86/atom/string/ssse3-strncpy-atom.S",
-                    "arch-x86/atom/string/ssse3-wmemcmp-atom.S",
-                ],
-                exclude_srcs: [
-                    "arch-x86/generic/string/memcmp.S",
-                    "arch-x86/silvermont/string/sse2-memmove-slm.S",
-                    "arch-x86/silvermont/string/sse2-memset-slm.S",
-                    "arch-x86/silvermont/string/sse2-strcpy-slm.S",
-                    "arch-x86/silvermont/string/sse2-strlen-slm.S",
-                    "arch-x86/silvermont/string/sse2-strncpy-slm.S",
-                ],
-            },
-            ssse3: {
-                srcs: [
-                    "arch-x86/atom/string/ssse3-strncat-atom.S",
-                    "arch-x86/atom/string/ssse3-strlcat-atom.S",
-                    "arch-x86/atom/string/ssse3-strlcpy-atom.S",
-                    "arch-x86/atom/string/ssse3-strcat-atom.S",
-                    "arch-x86/atom/string/ssse3-strcmp-atom.S",
-                    "arch-x86/atom/string/ssse3-strncmp-atom.S",
-                    "arch-x86/atom/string/ssse3-wcscat-atom.S",
-                    "arch-x86/atom/string/ssse3-wcscpy-atom.S",
-                ],
-                exclude_srcs: [
-                    "arch-x86/generic/string/strcmp.S",
-                    "arch-x86/generic/string/strncmp.S",
-                    "arch-x86/generic/string/strcat.S",
-                ],
-            },
-            sse4: {
-                srcs: [
-                    "arch-x86/silvermont/string/sse4-memcmp-slm.S",
-                    "arch-x86/silvermont/string/sse4-wmemcmp-slm.S",
-                ],
-                exclude_srcs: [
-                    "arch-x86/generic/string/memcmp.S",
-                ],
-            },
         },
         x86_64: {
             srcs: [
@@ -1662,6 +1632,12 @@
     defaults: ["libc_defaults"],
     name: "libc_common_static",
 
+    arch: {
+        x86: {
+            srcs: ["arch-x86/static_function_dispatch.S"],
+        },
+    },
+
     whole_static_libs: [
         "libc_common",
     ],
@@ -1674,6 +1650,16 @@
     defaults: ["libc_defaults"],
     name: "libc_common_shared",
 
+    cflags: [
+        "-fno-stack-protector",
+        "-fno-jump-tables",
+    ],
+    arch: {
+        x86: {
+            srcs: ["arch-x86/dynamic_function_dispatch.cpp"],
+        },
+    },
+
     whole_static_libs: [
         "libc_common",
     ],
diff --git a/libc/arch-x86/atom/string/sse2-memset-atom.S b/libc/arch-x86/atom/string/sse2-memset-atom.S
index 4e211ca..016c49e 100644
--- a/libc/arch-x86/atom/string/sse2-memset-atom.S
+++ b/libc/arch-x86/atom/string/sse2-memset-atom.S
@@ -86,7 +86,7 @@
 	movl	(%esp), %ebx
 	ret
 
-ENTRY(__memset_chk)
+ENTRY(__memset_chk_atom)
   ENTRANCE
 
   movl LEN(%esp), %ecx
@@ -95,11 +95,11 @@
 
   POP(%ebx) // Undo ENTRANCE without returning.
   jmp __memset_chk_fail
-END(__memset_chk)
+END(__memset_chk_atom)
 
 	.section .text.sse2,"ax",@progbits
 	ALIGN(4)
-ENTRY(memset)
+ENTRY(memset_atom)
 	ENTRANCE
 
 	movl	LEN(%esp), %ecx
@@ -839,4 +839,4 @@
 	SETRTNVAL
 	RETURN_END
 
-END(memset)
+END(memset_atom)
diff --git a/libc/arch-x86/atom/string/sse2-strlen-atom.S b/libc/arch-x86/atom/string/sse2-strlen-atom.S
index 81768fb..6a1acfb 100644
--- a/libc/arch-x86/atom/string/sse2-strlen-atom.S
+++ b/libc/arch-x86/atom/string/sse2-strlen-atom.S
@@ -31,7 +31,7 @@
 #ifndef USE_AS_STRCAT
 
 # ifndef STRLEN
-#  define STRLEN strlen
+#  define STRLEN strlen_atom
 # endif
 
 # ifndef L
diff --git a/libc/arch-x86/atom/string/ssse3-memcmp-atom.S b/libc/arch-x86/atom/string/ssse3-memcmp-atom.S
index 0387084..be2c4f6 100644
--- a/libc/arch-x86/atom/string/ssse3-memcmp-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-memcmp-atom.S
@@ -76,7 +76,7 @@
 #endif
 
 #ifndef MEMCMP
-# define MEMCMP	memcmp
+# define MEMCMP	memcmp_atom
 #endif
 
 #define CFI_PUSH(REG)	\
diff --git a/libc/arch-x86/atom/string/ssse3-memcpy-atom.S b/libc/arch-x86/atom/string/ssse3-memcpy-atom.S
index 2b3b7a5..5532e2e 100644
--- a/libc/arch-x86/atom/string/ssse3-memcpy-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-memcpy-atom.S
@@ -31,11 +31,7 @@
 #include "cache.h"
 
 #ifndef MEMCPY
-# define MEMCPY	memcpy
-#endif
-
-#ifndef USE_AS_MEMMOVE
-# define USE_AS_MEMMOVE
+# define MEMCPY	memcpy_atom
 #endif
 
 #ifndef L
@@ -71,12 +67,6 @@
 	cfi_startproc
 #endif
 
-#ifndef ALIAS_SYMBOL
-# define ALIAS_SYMBOL(alias, original) \
-	.globl alias; \
-	.equ alias, original
-#endif
-
 #ifndef END
 # define END(name)		\
 	cfi_endproc;		\
@@ -3132,5 +3122,3 @@
 #endif
 
 END (MEMCPY)
-
-ALIAS_SYMBOL(memmove, MEMCPY)
diff --git a/libc/arch-x86/atom/string/ssse3-memmove-atom.S b/libc/arch-x86/atom/string/ssse3-memmove-atom.S
new file mode 100644
index 0000000..3572eac
--- /dev/null
+++ b/libc/arch-x86/atom/string/ssse3-memmove-atom.S
@@ -0,0 +1,34 @@
+/*
+Copyright (c) 2010, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+    * this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+    * this list of conditions and the following disclaimer in the documentation
+    * and/or other materials provided with the distribution.
+
+    * Neither the name of Intel Corporation nor the names of its contributors
+    * may be used to endorse or promote products derived from this software
+    * without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#define MEMCPY memmove_atom
+#define USE_AS_MEMMOVE
+#include "ssse3-memcpy-atom.S"
diff --git a/libc/arch-x86/atom/string/ssse3-strcat-atom.S b/libc/arch-x86/atom/string/ssse3-strcat-atom.S
index d9b6129..8d8e89d 100644
--- a/libc/arch-x86/atom/string/ssse3-strcat-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strcat-atom.S
@@ -87,7 +87,7 @@
 #define POP(REG)	popl REG; CFI_POP (REG)
 
 #ifndef STRCAT
-# define STRCAT	strcat
+# define STRCAT	strcat_ssse3
 #endif
 
 #define PARMS	4
@@ -617,4 +617,4 @@
 	RETURN1
 
 #endif
-END (STRCAT)
+END (STRCAT_ssse3)
diff --git a/libc/arch-x86/atom/string/ssse3-strcmp-atom.S b/libc/arch-x86/atom/string/ssse3-strcmp-atom.S
index ee253b9..08f6d4a 100644
--- a/libc/arch-x86/atom/string/ssse3-strcmp-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strcmp-atom.S
@@ -108,7 +108,7 @@
 #endif
 
 #ifndef STRCMP
-# define STRCMP strcmp
+# define STRCMP strcmp_ssse3
 #endif
 
 	.section .text.ssse3,"ax",@progbits
diff --git a/libc/arch-x86/atom/string/ssse3-strcpy-atom.S b/libc/arch-x86/atom/string/ssse3-strcpy-atom.S
index 3690b0d..45b0c02 100644
--- a/libc/arch-x86/atom/string/ssse3-strcpy-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strcpy-atom.S
@@ -81,7 +81,7 @@
 # define POP(REG)	popl REG; CFI_POP (REG)
 
 # ifndef STRCPY
-#  define STRCPY  strcpy
+#  define STRCPY  strcpy_atom
 # endif
 
 # ifdef USE_AS_STRNCPY
diff --git a/libc/arch-x86/atom/string/ssse3-strlcat-atom.S b/libc/arch-x86/atom/string/ssse3-strlcat-atom.S
index daaf254..055b489 100644
--- a/libc/arch-x86/atom/string/ssse3-strlcat-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strlcat-atom.S
@@ -82,7 +82,7 @@
 #define LEN	SRC+4
 
 	.text
-ENTRY (strlcat)
+ENTRY (strlcat_ssse3)
 	mov	DST(%esp), %edx
 	PUSH	(%ebx)
 	mov	LEN(%esp), %ebx
diff --git a/libc/arch-x86/atom/string/ssse3-strlcpy-atom.S b/libc/arch-x86/atom/string/ssse3-strlcpy-atom.S
index cdb17cc..1671da6 100644
--- a/libc/arch-x86/atom/string/ssse3-strlcpy-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strlcpy-atom.S
@@ -29,8 +29,8 @@
 */
 
 #define USE_AS_STRNCPY
-#define STRCPY strlcpy
-#define STRLEN strlcpy
+#define STRCPY strlcpy_ssse3
+#define STRLEN strlcpy_ssse3
 #define USE_AS_STRLCPY
 #include "ssse3-strcpy-atom.S"
 
diff --git a/libc/arch-x86/atom/string/ssse3-strncat-atom.S b/libc/arch-x86/atom/string/ssse3-strncat-atom.S
index 5618771..ccb08a7 100644
--- a/libc/arch-x86/atom/string/ssse3-strncat-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strncat-atom.S
@@ -28,7 +28,7 @@
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#define STRCAT  strncat
+#define STRCAT  strncat_ssse3
 #define USE_AS_STRNCAT
 
 #include "ssse3-strcat-atom.S"
diff --git a/libc/arch-x86/atom/string/ssse3-strncmp-atom.S b/libc/arch-x86/atom/string/ssse3-strncmp-atom.S
index 4762d7e..2bf5002 100644
--- a/libc/arch-x86/atom/string/ssse3-strncmp-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strncmp-atom.S
@@ -30,6 +30,6 @@
 
 
 #define USE_AS_STRNCMP
-#define STRCMP  strncmp
+#define STRCMP  strncmp_ssse3
 #include "ssse3-strcmp-atom.S"
 
diff --git a/libc/arch-x86/atom/string/ssse3-strncpy-atom.S b/libc/arch-x86/atom/string/ssse3-strncpy-atom.S
index 0948b6d..0c27ffe 100644
--- a/libc/arch-x86/atom/string/ssse3-strncpy-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-strncpy-atom.S
@@ -29,5 +29,5 @@
 */
 
 #define USE_AS_STRNCPY
-#define STRCPY strncpy
+#define STRCPY strncpy_atom
 #include "ssse3-strcpy-atom.S"
diff --git a/libc/arch-x86/atom/string/ssse3-wcscat-atom.S b/libc/arch-x86/atom/string/ssse3-wcscat-atom.S
index 8a389a3..a307983 100644
--- a/libc/arch-x86/atom/string/ssse3-wcscat-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-wcscat-atom.S
@@ -85,7 +85,7 @@
 #define USE_AS_WCSCAT
 
 .text
-ENTRY (wcscat)
+ENTRY (wcscat_ssse3)
 	PUSH    (%edi)
 	mov	STR1(%esp), %edi
 	mov	%edi, %edx
@@ -111,4 +111,4 @@
 #define RETURN  POP(%edi);	ret;	CFI_PUSH(%edi)
 #include "ssse3-wcscpy-atom.S"
 
-END (wcscat)
+END (wcscat_ssse3)
diff --git a/libc/arch-x86/atom/string/ssse3-wcscpy-atom.S b/libc/arch-x86/atom/string/ssse3-wcscpy-atom.S
index 27cb61e..80aa15f 100644
--- a/libc/arch-x86/atom/string/ssse3-wcscpy-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-wcscpy-atom.S
@@ -88,7 +88,7 @@
 # define LEN	STR2+4
 
 .text
-ENTRY (wcscpy)
+ENTRY (wcscpy_ssse3)
 	mov	STR1(%esp), %edx
 	mov	STR2(%esp), %ecx
 
@@ -648,5 +648,5 @@
 	ret
 
 #ifndef USE_AS_WCSCAT
-END (wcscpy)
+END (wcscpy_ssse3)
 #endif
diff --git a/libc/arch-x86/atom/string/ssse3-wmemcmp-atom.S b/libc/arch-x86/atom/string/ssse3-wmemcmp-atom.S
index 2c3fa02..a81b78b 100644
--- a/libc/arch-x86/atom/string/ssse3-wmemcmp-atom.S
+++ b/libc/arch-x86/atom/string/ssse3-wmemcmp-atom.S
@@ -28,7 +28,7 @@
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#define MEMCMP  wmemcmp
+#define MEMCMP  wmemcmp_atom
 
 #define USE_WCHAR
 #define USE_AS_WMEMCMP 1
diff --git a/libc/arch-x86/dynamic_function_dispatch.cpp b/libc/arch-x86/dynamic_function_dispatch.cpp
new file mode 100644
index 0000000..6624385
--- /dev/null
+++ b/libc/arch-x86/dynamic_function_dispatch.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+
+extern "C" {
+
+struct __processor_model {
+    unsigned int __cpu_vendor;
+    unsigned int __cpu_type;
+    unsigned int __cpu_subtype;
+    unsigned int __cpu_features[1];
+};
+
+__attribute__((visibility("hidden")))
+extern struct __processor_model __cpu_model;
+
+// These definitions have to match the values in
+// llvm/include/llvm/Support/X86TargetParser.def
+static constexpr int SSSE3  = 6;
+static constexpr int SSE4_1 = 7;
+static constexpr int ATOM   = 1;
+
+// __builtin_cpu_supports and __builtin_cpu_is can not be used here. They
+// don't access __cpu_model directly but use GOT.
+// See https://reviews.llvm.org/D53850
+static bool cpu_supports(unsigned int feature) {
+    return (__cpu_model.__cpu_features[0] & (1U << feature)) != 0;
+}
+
+static bool cpu_is(unsigned int type) {
+    return (__cpu_model.__cpu_type == type);
+}
+
+#define DEFINE_IFUNC_FOR(name) \
+    name##_func name __attribute__((ifunc(#name "_resolver"))); \
+    __attribute__((visibility("hidden"))) \
+    name##_func* name##_resolver()
+
+#define DECLARE_FUNC(type, name) \
+    __attribute__((visibility("hidden"))) \
+    type name
+
+#define RETURN_FUNC(type, name) { \
+        DECLARE_FUNC(type, name); \
+        return name; \
+    }
+
+typedef int memcmp_func(const void* __lhs, const void* __rhs, size_t __n);
+DEFINE_IFUNC_FOR(memcmp) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(memcmp_func, memcmp_atom);
+    if (cpu_supports(SSE4_1)) RETURN_FUNC(memcmp_func, memcmp_sse4);
+    RETURN_FUNC(memcmp_func, memcmp_generic);
+}
+
+typedef void* memset_func(void* __dst, int __ch, size_t __n);
+DEFINE_IFUNC_FOR(memset) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(memset_func, memset_atom);
+    RETURN_FUNC(memset_func, memset_generic);
+}
+
+typedef void* __memset_chk_func(void *s, int c, size_t n, size_t n2);
+DEFINE_IFUNC_FOR(__memset_chk) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(__memset_chk_func, __memset_chk_atom);
+    RETURN_FUNC(__memset_chk_func, __memset_chk_generic);
+}
+
+typedef void* memmove_func(void* __dst, const void* __src, size_t __n);
+DEFINE_IFUNC_FOR(memmove) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(memmove_func, memmove_atom);
+    RETURN_FUNC(memmove_func, memmove_generic);
+}
+
+typedef void* memcpy_func(void*, const void*, size_t);
+DEFINE_IFUNC_FOR(memcpy) {
+    return memmove_resolver();
+}
+
+typedef char* strcpy_func(char* __dst, const char* __src);
+DEFINE_IFUNC_FOR(strcpy) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(strcpy_func, strcpy_atom);
+    RETURN_FUNC(strcpy_func, strcpy_generic);
+}
+
+typedef char* strncpy_func(char* __dst, const char* __src, size_t __n);
+DEFINE_IFUNC_FOR(strncpy) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(strncpy_func, strncpy_atom);
+    RETURN_FUNC(strncpy_func, strncpy_generic);
+}
+
+typedef size_t strlen_func(const char* __s);
+DEFINE_IFUNC_FOR(strlen) {
+    __builtin_cpu_init();
+    if (cpu_is(ATOM)) RETURN_FUNC(strlen_func, strlen_atom);
+    RETURN_FUNC(strlen_func, strlen_generic);
+}
+
+typedef int wmemcmp_func(const wchar_t* __lhs, const wchar_t* __rhs, size_t __n);
+DEFINE_IFUNC_FOR(wmemcmp) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSE4_1)) RETURN_FUNC(wmemcmp_func, wmemcmp_sse4);
+    if (cpu_is(ATOM)) RETURN_FUNC(wmemcmp_func, wmemcmp_atom);
+    RETURN_FUNC(wmemcmp_func, wmemcmp_freebsd);
+}
+
+typedef int strcmp_func(const char* __lhs, const char* __rhs);
+DEFINE_IFUNC_FOR(strcmp) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(strcmp_func, strcmp_ssse3);
+    RETURN_FUNC(strcmp_func, strcmp_generic);
+}
+
+typedef int strncmp_func(const char* __lhs, const char* __rhs, size_t __n);
+DEFINE_IFUNC_FOR(strncmp) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(strncmp_func, strncmp_ssse3);
+    RETURN_FUNC(strncmp_func, strncmp_generic);
+}
+
+typedef char* strcat_func(char* __dst, const char* __src);
+DEFINE_IFUNC_FOR(strcat) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(strcat_func, strcat_ssse3);
+    RETURN_FUNC(strcat_func, strcat_generic);
+}
+
+typedef char* strncat_func(char* __dst, const char* __src, size_t __n);
+DEFINE_IFUNC_FOR(strncat) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(strncat_func, strncat_ssse3);
+    RETURN_FUNC(strncat_func, strncat_openbsd);
+}
+
+typedef size_t strlcat_func(char *dst, const char *src, size_t dsize);
+DEFINE_IFUNC_FOR(strlcat) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(strlcat_func, strlcat_ssse3);
+    RETURN_FUNC(strlcat_func, strlcat_openbsd);
+}
+
+typedef size_t strlcpy_func(char *dst, const char *src, size_t dsize);
+DEFINE_IFUNC_FOR(strlcpy) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(strlcpy_func, strlcpy_ssse3);
+    RETURN_FUNC(strlcpy_func, strlcpy_openbsd);
+}
+
+typedef wchar_t* wcscat_func(wchar_t *s1, const wchar_t *s2);
+DEFINE_IFUNC_FOR(wcscat) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(wcscat_func, wcscat_ssse3);
+    RETURN_FUNC(wcscat_func, wcscat_freebsd);
+}
+
+typedef wchar_t* wcscpy_func(wchar_t *s1, const wchar_t *s2);
+DEFINE_IFUNC_FOR(wcscpy) {
+    __builtin_cpu_init();
+    if (cpu_supports(SSSE3)) RETURN_FUNC(wcscpy_func, wcscpy_ssse3);
+    RETURN_FUNC(wcscpy_func, wcscpy_freebsd);
+}
+
+}  // extern "C"
diff --git a/libc/arch-x86/generic/string/memcmp.S b/libc/arch-x86/generic/string/memcmp.S
index ef36b4f..1d327c7 100644
--- a/libc/arch-x86/generic/string/memcmp.S
+++ b/libc/arch-x86/generic/string/memcmp.S
@@ -6,7 +6,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(memcmp)
+ENTRY(memcmp_generic)
 	pushl	%edi
 	pushl	%esi
 	movl	12(%esp),%edi
@@ -41,4 +41,4 @@
 	popl	%esi
 	popl	%edi
 	ret
-END(memcmp)
+END(memcmp_generic)
diff --git a/libc/arch-x86/generic/string/strcat.S b/libc/arch-x86/generic/string/strcat.S
index 49e8eee..e2e9623 100644
--- a/libc/arch-x86/generic/string/strcat.S
+++ b/libc/arch-x86/generic/string/strcat.S
@@ -19,7 +19,7 @@
  * cache.
  */
 
-ENTRY(strcat)
+ENTRY(strcat_generic)
 	pushl	%edi			/* save edi */
 	movl	8(%esp),%edi		/* dst address */
 	movl	12(%esp),%edx		/* src address */
@@ -71,4 +71,4 @@
 L2:	popl	%eax			/* pop destination address */
 	popl	%edi			/* restore edi */
 	ret
-END(strcat)
+END(strcat_generic)
diff --git a/libc/arch-x86/generic/string/strcmp.S b/libc/arch-x86/generic/string/strcmp.S
index 580f4d5..7b003e8 100644
--- a/libc/arch-x86/generic/string/strcmp.S
+++ b/libc/arch-x86/generic/string/strcmp.S
@@ -12,7 +12,7 @@
  * cache.
  */
 
-ENTRY(strcmp)
+ENTRY(strcmp_generic)
 	movl	0x04(%esp),%eax
 	movl	0x08(%esp),%edx
 	jmp	L2			/* Jump into the loop! */
@@ -79,4 +79,4 @@
 	movzbl	(%edx),%edx
 	subl	%edx,%eax
 	ret
-END(strcmp)
+END(strcmp_generic)
diff --git a/libc/arch-x86/generic/string/strlcat.c b/libc/arch-x86/generic/string/strlcat.c
new file mode 100644
index 0000000..95c34a3
--- /dev/null
+++ b/libc/arch-x86/generic/string/strlcat.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <upstream-openbsd/android/include/openbsd-compat.h>
+
+#define strlcat strlcat_openbsd
+#include <upstream-openbsd/lib/libc/string/strlcat.c>
diff --git a/libc/arch-x86/generic/string/strlcpy.c b/libc/arch-x86/generic/string/strlcpy.c
new file mode 100644
index 0000000..8d4047c
--- /dev/null
+++ b/libc/arch-x86/generic/string/strlcpy.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <upstream-openbsd/android/include/openbsd-compat.h>
+
+#define strlcpy strlcpy_openbsd
+#include <upstream-openbsd/lib/libc/string/strlcpy.c>
diff --git a/libc/arch-x86/generic/string/strncat.c b/libc/arch-x86/generic/string/strncat.c
new file mode 100644
index 0000000..687e560
--- /dev/null
+++ b/libc/arch-x86/generic/string/strncat.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <upstream-openbsd/android/include/openbsd-compat.h>
+
+#define strncat strncat_openbsd
+#include <upstream-openbsd/lib/libc/string/strncat.c>
diff --git a/libc/arch-x86/generic/string/strncmp.S b/libc/arch-x86/generic/string/strncmp.S
index 9ba83a1..6d9f23c 100644
--- a/libc/arch-x86/generic/string/strncmp.S
+++ b/libc/arch-x86/generic/string/strncmp.S
@@ -12,7 +12,7 @@
  * cache.
  */
 
-ENTRY(strncmp)
+ENTRY(strncmp_generic)
 	pushl	%ebx
 	movl	8(%esp),%eax
 	movl	12(%esp),%ecx
@@ -111,4 +111,4 @@
 L4:	xorl	%eax,%eax
 	popl	%ebx
 	ret
-END(strncmp)
+END(strncmp_generic)
diff --git a/libc/arch-x86/generic/string/wcscat.c b/libc/arch-x86/generic/string/wcscat.c
new file mode 100644
index 0000000..a102551
--- /dev/null
+++ b/libc/arch-x86/generic/string/wcscat.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define wcscat wcscat_freebsd
+#include <upstream-freebsd/lib/libc/string/wcscat.c>
diff --git a/libc/arch-x86/generic/string/wcscpy.c b/libc/arch-x86/generic/string/wcscpy.c
new file mode 100644
index 0000000..10fb66d
--- /dev/null
+++ b/libc/arch-x86/generic/string/wcscpy.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define wcscpy wcscpy_freebsd
+#include <upstream-freebsd/lib/libc/string/wcscpy.c>
diff --git a/libc/arch-x86/generic/string/wmemcmp.c b/libc/arch-x86/generic/string/wmemcmp.c
new file mode 100644
index 0000000..9d5e929
--- /dev/null
+++ b/libc/arch-x86/generic/string/wmemcmp.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define wmemcmp wmemcmp_freebsd
+#include <upstream-freebsd/lib/libc/string/wmemcmp.c>
diff --git a/libc/arch-x86/silvermont/string/sse2-memmove-slm.S b/libc/arch-x86/silvermont/string/sse2-memmove-slm.S
index ceada1b..da6456c 100644
--- a/libc/arch-x86/silvermont/string/sse2-memmove-slm.S
+++ b/libc/arch-x86/silvermont/string/sse2-memmove-slm.S
@@ -31,7 +31,7 @@
 #include "cache.h"
 
 #ifndef MEMMOVE
-# define MEMMOVE	memmove
+# define MEMMOVE	memmove_generic
 #endif
 
 #ifndef L
@@ -67,12 +67,6 @@
 	cfi_startproc
 #endif
 
-#ifndef ALIAS_SYMBOL
-# define ALIAS_SYMBOL(alias, original) \
-	.globl alias; \
-	.equ alias, original
-#endif
-
 #ifndef END
 # define END(name)		\
 	cfi_endproc;		\
@@ -543,5 +537,3 @@
 	jmp	L(mm_recalc_len)
 
 END (MEMMOVE)
-
-ALIAS_SYMBOL(memcpy, MEMMOVE)
diff --git a/libc/arch-x86/silvermont/string/sse2-memset-slm.S b/libc/arch-x86/silvermont/string/sse2-memset-slm.S
index 03a552d..adaccae 100644
--- a/libc/arch-x86/silvermont/string/sse2-memset-slm.S
+++ b/libc/arch-x86/silvermont/string/sse2-memset-slm.S
@@ -86,7 +86,7 @@
 	movl	(%esp), %ebx
 	ret
 
-ENTRY(__memset_chk)
+ENTRY(__memset_chk_generic)
   ENTRANCE
 
   movl LEN(%esp), %ecx
@@ -95,11 +95,11 @@
 
   POP(%ebx) // Undo ENTRANCE without returning.
   jmp __memset_chk_fail
-END(__memset_chk)
+END(__memset_chk_generic)
 
 	.section .text.sse2,"ax",@progbits
 	ALIGN(4)
-ENTRY(memset)
+ENTRY(memset_generic)
 	ENTRANCE
 
 	movl	LEN(%esp), %ecx
@@ -758,4 +758,4 @@
 	SETRTNVAL
 	RETURN_END
 
-END(memset)
+END(memset_generic)
diff --git a/libc/arch-x86/silvermont/string/sse2-strcpy-slm.S b/libc/arch-x86/silvermont/string/sse2-strcpy-slm.S
index b5d84b5..22ceeab 100755
--- a/libc/arch-x86/silvermont/string/sse2-strcpy-slm.S
+++ b/libc/arch-x86/silvermont/string/sse2-strcpy-slm.S
@@ -79,7 +79,7 @@
 #define POP(REG) popl REG; CFI_POP (REG)
 
 #ifndef STRCPY
-# define STRCPY  strcpy
+# define STRCPY  strcpy_generic
 #endif
 
 #ifdef USE_AS_STPNCPY
diff --git a/libc/arch-x86/silvermont/string/sse2-strlen-slm.S b/libc/arch-x86/silvermont/string/sse2-strlen-slm.S
index 27cc025..b805ad6 100755
--- a/libc/arch-x86/silvermont/string/sse2-strlen-slm.S
+++ b/libc/arch-x86/silvermont/string/sse2-strlen-slm.S
@@ -29,7 +29,7 @@
 */
 
 #ifndef STRLEN
-# define STRLEN strlen
+# define STRLEN strlen_generic
 #endif
 
 #ifndef L
diff --git a/libc/arch-x86/silvermont/string/sse2-strncpy-slm.S b/libc/arch-x86/silvermont/string/sse2-strncpy-slm.S
index 591419f..aff7fb9 100755
--- a/libc/arch-x86/silvermont/string/sse2-strncpy-slm.S
+++ b/libc/arch-x86/silvermont/string/sse2-strncpy-slm.S
@@ -29,5 +29,5 @@
 */

 

 #define USE_AS_STRNCPY

-#define STRCPY strncpy

+#define STRCPY strncpy_generic

 #include "sse2-strcpy-slm.S"

diff --git a/libc/arch-x86/silvermont/string/sse4-memcmp-slm.S b/libc/arch-x86/silvermont/string/sse4-memcmp-slm.S
index e5028ff..f151168 100755
--- a/libc/arch-x86/silvermont/string/sse4-memcmp-slm.S
+++ b/libc/arch-x86/silvermont/string/sse4-memcmp-slm.S
@@ -76,7 +76,7 @@
 #endif
 
 #ifndef MEMCMP
-# define MEMCMP	memcmp
+# define MEMCMP	memcmp_sse4
 #endif
 
 #define CFI_PUSH(REG)	\
diff --git a/libc/arch-x86/silvermont/string/sse4-wmemcmp-slm.S b/libc/arch-x86/silvermont/string/sse4-wmemcmp-slm.S
index 2c350bb..2bf92f5 100755
--- a/libc/arch-x86/silvermont/string/sse4-wmemcmp-slm.S
+++ b/libc/arch-x86/silvermont/string/sse4-wmemcmp-slm.S
@@ -29,5 +29,5 @@
 */
 
 #define USE_AS_WMEMCMP
-#define MEMCMP wmemcmp
+#define MEMCMP wmemcmp_sse4
 #include "sse4-memcmp-slm.S"
diff --git a/libc/arch-x86/static_function_dispatch.S b/libc/arch-x86/static_function_dispatch.S
new file mode 100644
index 0000000..7e8e63d
--- /dev/null
+++ b/libc/arch-x86/static_function_dispatch.S
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+
+#define FUNCTION_DELEGATE(name, impl) \
+ENTRY(name); \
+    jmp impl; \
+END(name)
+
+FUNCTION_DELEGATE(memcmp, memcmp_generic)
+FUNCTION_DELEGATE(memset, memset_generic)
+FUNCTION_DELEGATE(__memset_chk, __memset_chk_generic)
+FUNCTION_DELEGATE(memcpy, memmove_generic)
+FUNCTION_DELEGATE(memmove, memmove_generic)
+FUNCTION_DELEGATE(strcpy, strcpy_generic)
+FUNCTION_DELEGATE(strncpy, strncpy_generic)
+FUNCTION_DELEGATE(strlen, strlen_generic)
+FUNCTION_DELEGATE(strcmp, strcmp_generic)
+FUNCTION_DELEGATE(strncmp, strncmp_generic)
+FUNCTION_DELEGATE(strcat, strcat_generic)
+FUNCTION_DELEGATE(wmemcmp, wmemcmp_freebsd)
+FUNCTION_DELEGATE(wcscat, wcscat_freebsd)
+FUNCTION_DELEGATE(strncat, strncat_openbsd)
+FUNCTION_DELEGATE(strlcat, strlcat_openbsd)
+FUNCTION_DELEGATE(strlcpy, strlcpy_openbsd)
+FUNCTION_DELEGATE(wcscpy, wcscpy_freebsd)
diff --git a/tests/TemporaryFile.h b/tests/TemporaryFile.h
deleted file mode 100644
index 7853781..0000000
--- a/tests/TemporaryFile.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2013 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 <fcntl.h>
-#include <unistd.h>
-
-#include <android-base/macros.h>
-
-template <typename T = int (*)(char*)>
-class GenericTemporaryFile {
- public:
-  explicit GenericTemporaryFile(T mk_fn = mkstemp) : mk_fn(mk_fn) {
-    // Since we might be running on the host or the target, and if we're
-    // running on the host we might be running under bionic or glibc,
-    // let's just try both possible temporary directories and take the
-    // first one that works.
-    init("/data/local/tmp");
-    if (fd == -1) {
-      init("/tmp");
-    }
-  }
-
-  explicit GenericTemporaryFile(const char* dirpath, T mk_fn = mkstemp) : mk_fn(mk_fn) {
-    init(dirpath);
-  }
-
-  ~GenericTemporaryFile() {
-    close(fd);
-    unlink(filename);
-  }
-
-  void reopen() {
-    close(fd);
-    fd = open(filename, O_RDWR);
-  }
-
-  int fd;
-  char filename[1024];
-
- private:
-  T mk_fn;
-
-  void init(const char* tmp_dir) {
-    snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir);
-    fd = mk_fn(filename);
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(GenericTemporaryFile);
-};
-
-typedef GenericTemporaryFile<> TemporaryFile;
-
-class TemporaryDir {
- public:
-  TemporaryDir() {
-    if (!init("/data/local/tmp")) {
-      init("/tmp");
-    }
-  }
-
-  ~TemporaryDir() {
-    rmdir(dirname);
-  }
-
-  char dirname[1024];
-
- private:
-  bool init(const char* tmp_dir) {
-    snprintf(dirname, sizeof(dirname), "%s/TemporaryDir-XXXXXX", tmp_dir);
-    return (mkdtemp(dirname) != nullptr);
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(TemporaryDir);
-};
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index c1681ea..18ba011 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -31,7 +31,7 @@
 #include <fstream>
 
 #include "gtest_globals.h"
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 #include "utils.h"
 
 extern "C" int main_global_default_serial() {
@@ -247,8 +247,8 @@
   std::string helper = GetTestlibRoot() +
       "/ld_config_test_helper/ld_config_test_helper";
   TemporaryFile config_file;
-  create_ld_config_file(config_file.filename);
-  std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
+  create_ld_config_file(config_file.path);
+  std::string env = std::string("LD_CONFIG_FILE=") + config_file.path;
   chmod(helper.c_str(), 0755);
   ExecTestHelper eth;
   eth.SetArgs({ helper.c_str(), nullptr });
@@ -270,8 +270,8 @@
   std::string helper = GetTestlibRoot() +
       "/ld_config_test_helper/ld_config_test_helper";
   TemporaryFile config_file;
-  create_ld_config_file(config_file.filename);
-  std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
+  create_ld_config_file(config_file.path);
+  std::string env = std::string("LD_CONFIG_FILE=") + config_file.path;
   std::string env2 = std::string("LD_PRELOAD=") + GetTestlibRoot() + "/ld_config_test_helper_lib3.so";
   chmod(helper.c_str(), 0755);
   ExecTestHelper eth;
@@ -300,8 +300,8 @@
   std::string helper = GetTestlibRoot() +
       "/ld_config_test_helper/ld_config_test_helper";
   TemporaryFile config_file;
-  create_ld_config_file(config_file.filename);
-  std::string env = std::string("LD_CONFIG_FILE=") + config_file.filename;
+  create_ld_config_file(config_file.path);
+  std::string env = std::string("LD_CONFIG_FILE=") + config_file.path;
   chmod(helper.c_str(), 0755);
   ExecTestHelper eth;
   eth.SetArgs({ helper.c_str(), nullptr });
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index bea18e5..34013a7 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -40,7 +40,6 @@
 #include <ziparchive/zip_archive.h>
 
 #include "gtest_globals.h"
-#include "TemporaryFile.h"
 #include "utils.h"
 #include "dlext_private.h"
 #include "dlfcn_symlink_support.h"
@@ -435,7 +434,7 @@
   TemporaryFile tf; // Use tf to get an unique filename.
   ASSERT_NOERROR(close(tf.fd));
 
-  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.filename));
+  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path));
   ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibName));
 
   // Use destructor of tf to close and unlink the file.
@@ -446,7 +445,7 @@
   TemporaryFile tf; // // Use tf to get an unique filename.
   ASSERT_NOERROR(close(tf.fd));
 
-  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.filename));
+  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibNameNoRelro, tf.path));
   ASSERT_NO_FATAL_FAILURE(TryUsingRelro(kLibNameNoRelro));
 
   // Use destructor of tf to close and unlink the file.
@@ -466,14 +465,14 @@
   TemporaryFile tf; // Use tf to get an unique filename.
   ASSERT_NOERROR(close(tf.fd));
 
-  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.filename));
+  ASSERT_NO_FATAL_FAILURE(CreateRelroFile(kLibName, tf.path));
 
   int pipefd[2];
   ASSERT_NOERROR(pipe(pipefd));
 
   size_t without_sharing, with_sharing;
-  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.filename, false, &without_sharing));
-  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.filename, true, &with_sharing));
+  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, false, &without_sharing));
+  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.path, true, &with_sharing));
   ASSERT_LT(with_sharing, without_sharing);
 
   // We expect the sharing to save at least 50% of the library's total PSS.
diff --git a/tests/fcntl_test.cpp b/tests/fcntl_test.cpp
index da44fee..d7dce31 100644
--- a/tests/fcntl_test.cpp
+++ b/tests/fcntl_test.cpp
@@ -22,8 +22,7 @@
 #include <sys/utsname.h>
 #include <sys/vfs.h>
 
-#include "TemporaryFile.h"
-
+#include <android-base/file.h>
 #include <android-base/stringprintf.h>
 
 // Glibc v2.19 doesn't include these in fcntl.h so host builds will fail without.
@@ -307,7 +306,7 @@
   // Without O_EXCL, we're allowed to give this a name later.
   // (This is unrelated to the O_CREAT interaction with O_EXCL.)
   const mode_t perms = S_IRUSR | S_IWUSR;
-  int fd = open(dir.dirname, O_TMPFILE | O_RDWR, perms);
+  int fd = open(dir.path, O_TMPFILE | O_RDWR, perms);
 
   // Ignore kernels without O_TMPFILE support (< 3.11).
   if (fd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) return;
@@ -322,7 +321,7 @@
   // On Android if we're not root, we won't be able to create links anyway...
   if (getuid() != 0) return;
 
-  std::string final_path = android::base::StringPrintf("%s/named_now", dir.dirname);
+  std::string final_path = android::base::StringPrintf("%s/named_now", dir.path);
   ASSERT_EQ(0, linkat(AT_FDCWD, android::base::StringPrintf("/proc/self/fd/%d", fd).c_str(),
                       AT_FDCWD, final_path.c_str(),
                       AT_SYMLINK_FOLLOW));
@@ -333,11 +332,11 @@
   ASSERT_EQ(perms, (sb.st_mode & ~S_IFMT));
 
   // With O_EXCL, you're not allowed to add a name later.
-  fd = open(dir.dirname, O_TMPFILE | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
+  fd = open(dir.path, O_TMPFILE | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
   ASSERT_TRUE(fd != -1) << strerror(errno);
   errno = 0;
   ASSERT_EQ(-1, linkat(AT_FDCWD, android::base::StringPrintf("/proc/self/fd/%d", fd).c_str(),
-                       AT_FDCWD, android::base::StringPrintf("%s/no_chance", dir.dirname).c_str(),
+                       AT_FDCWD, android::base::StringPrintf("%s/no_chance", dir.path).c_str(),
                        AT_SYMLINK_FOLLOW));
   ASSERT_EQ(ENOENT, errno);
   ASSERT_EQ(0, close(fd));
diff --git a/tests/ftw_test.cpp b/tests/ftw_test.cpp
index 22ab399..dfc4d72 100644
--- a/tests/ftw_test.cpp
+++ b/tests/ftw_test.cpp
@@ -16,6 +16,7 @@
 
 #include <ftw.h>
 
+#include <fcntl.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -23,8 +24,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "TemporaryFile.h"
-
+#include <android-base/file.h>
 #include <android-base/stringprintf.h>
 #include <gtest/gtest.h>
 
@@ -102,26 +102,26 @@
 
 TEST(ftw, ftw) {
   TemporaryDir root;
-  MakeTree(root.dirname);
-  ASSERT_EQ(0, ftw(root.dirname, check_ftw, 128));
+  MakeTree(root.path);
+  ASSERT_EQ(0, ftw(root.path, check_ftw, 128));
 }
 
 TEST(ftw, ftw64) {
   TemporaryDir root;
-  MakeTree(root.dirname);
-  ASSERT_EQ(0, ftw64(root.dirname, check_ftw64, 128));
+  MakeTree(root.path);
+  ASSERT_EQ(0, ftw64(root.path, check_ftw64, 128));
 }
 
 TEST(ftw, nftw) {
   TemporaryDir root;
-  MakeTree(root.dirname);
-  ASSERT_EQ(0, nftw(root.dirname, check_nftw, 128, 0));
+  MakeTree(root.path);
+  ASSERT_EQ(0, nftw(root.path, check_nftw, 128, 0));
 }
 
 TEST(ftw, nftw64) {
   TemporaryDir root;
-  MakeTree(root.dirname);
-  ASSERT_EQ(0, nftw64(root.dirname, check_nftw64, 128, 0));
+  MakeTree(root.path);
+  ASSERT_EQ(0, nftw64(root.path, check_nftw64, 128, 0));
 }
 
 template <typename StatT>
@@ -145,13 +145,13 @@
 
   TemporaryDir root;
 
-  std::string path = android::base::StringPrintf("%s/unreadable-directory", root.dirname);
+  std::string path = android::base::StringPrintf("%s/unreadable-directory", root.path);
   ASSERT_EQ(0, mkdir(path.c_str(), 0000)) << path;
 
-  ASSERT_EQ(0, ftw(root.dirname, bug_28197840_ftw<struct stat>, 128));
-  ASSERT_EQ(0, ftw64(root.dirname, bug_28197840_ftw<struct stat64>, 128));
-  ASSERT_EQ(0, nftw(root.dirname, bug_28197840_nftw<struct stat>, 128, FTW_PHYS));
-  ASSERT_EQ(0, nftw64(root.dirname, bug_28197840_nftw<struct stat64>, 128, FTW_PHYS));
+  ASSERT_EQ(0, ftw(root.path, bug_28197840_ftw<struct stat>, 128));
+  ASSERT_EQ(0, ftw64(root.path, bug_28197840_ftw<struct stat64>, 128));
+  ASSERT_EQ(0, nftw(root.path, bug_28197840_nftw<struct stat>, 128, FTW_PHYS));
+  ASSERT_EQ(0, nftw64(root.path, bug_28197840_nftw<struct stat64>, 128, FTW_PHYS));
 }
 
 template <typename StatT>
diff --git a/tests/glob_test.cpp b/tests/glob_test.cpp
index 623a2a3..b48f2af 100644
--- a/tests/glob_test.cpp
+++ b/tests/glob_test.cpp
@@ -22,7 +22,7 @@
 #include <string>
 #include <vector>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 
 #if defined(__BIONIC__)
 #define ASSERT_MATCH_COUNT(n_,g_) ASSERT_EQ(n_, g_.gl_matchc)
@@ -140,22 +140,22 @@
 TEST(glob, glob_GLOB_MARK) {
   TemporaryDir td;
   // The pattern we're about to pass doesn't have a trailing '/'...
-  ASSERT_NE('/', std::string(td.dirname).back());
+  ASSERT_NE('/', std::string(td.path).back());
 
   glob_t g = {};
   // Using GLOB_MARK gets you a trailing '/' on a directory...
-  ASSERT_EQ(0, glob(td.dirname, GLOB_MARK, nullptr, &g));
+  ASSERT_EQ(0, glob(td.path, GLOB_MARK, nullptr, &g));
   ASSERT_EQ(1U, g.gl_pathc);
   ASSERT_MATCH_COUNT(1U, g);
-  ASSERT_EQ(std::string(td.dirname) + "/", g.gl_pathv[0]);
+  ASSERT_EQ(std::string(td.path) + "/", g.gl_pathv[0]);
   ASSERT_EQ(nullptr, g.gl_pathv[1]);
 
   TemporaryFile tf;
   // But not on a file...
-  ASSERT_EQ(0, glob(tf.filename, GLOB_MARK, nullptr, &g));
+  ASSERT_EQ(0, glob(tf.path, GLOB_MARK, nullptr, &g));
   ASSERT_EQ(1U, g.gl_pathc);
   ASSERT_MATCH_COUNT(1U, g);
-  ASSERT_STREQ(tf.filename, g.gl_pathv[0]);
+  ASSERT_STREQ(tf.path, g.gl_pathv[0]);
   ASSERT_EQ(nullptr, g.gl_pathv[1]);
 
   globfree(&g);
diff --git a/tests/grp_pwd_file_test.cpp b/tests/grp_pwd_file_test.cpp
index 8721805..2cbad62 100644
--- a/tests/grp_pwd_file_test.cpp
+++ b/tests/grp_pwd_file_test.cpp
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 
 #if defined(__BIONIC__)
 #include "../libc/bionic/grp_pwd_file.cpp"
@@ -94,7 +94,7 @@
   static const char test_string[] = "name:password:1:2:user_info:dir:shell\n";
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  PasswdFile passwd_file(file.filename, nullptr);
+  PasswdFile passwd_file(file.path, nullptr);
   FileUnmapper unmapper(passwd_file);
 
   FindAndCheckPasswdEntry(&passwd_file, "name", 1, 2, "dir", "shell");
@@ -114,7 +114,7 @@
   static const char test_string[] = "name:password:1:one,two,three\n";
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  GroupFile group_file(file.filename, nullptr);
+  GroupFile group_file(file.path, nullptr);
   FileUnmapper unmapper(group_file);
 
   FindAndCheckGroupEntry(&group_file, "name", 1);
@@ -150,7 +150,7 @@
 
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  PasswdFile passwd_file(file.filename, nullptr);
+  PasswdFile passwd_file(file.path, nullptr);
   FileUnmapper unmapper(passwd_file);
 
   FindAndCheckPasswdEntry(&passwd_file, "first", 1, 2, "dir", "shell");
@@ -186,7 +186,7 @@
 
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  GroupFile group_file(file.filename, nullptr);
+  GroupFile group_file(file.path, nullptr);
   FileUnmapper unmapper(group_file);
 
   FindAndCheckGroupEntry(&group_file, "first", 1);
@@ -210,7 +210,7 @@
       "vendor_name:password:3:4:user_info:dir:shell\n";
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  PasswdFile passwd_file(file.filename, "vendor_");
+  PasswdFile passwd_file(file.path, "vendor_");
   FileUnmapper unmapper(passwd_file);
 
   EXPECT_FALSE(passwd_file.FindByName("name", nullptr));
@@ -232,7 +232,7 @@
       "vendor_name:password:2:one,two,three\n";
   write(file.fd, test_string, sizeof(test_string) - 1);
 
-  GroupFile group_file(file.filename, "vendor_");
+  GroupFile group_file(file.path, "vendor_");
   FileUnmapper unmapper(group_file);
 
   EXPECT_FALSE(group_file.FindByName("name", nullptr));
diff --git a/tests/stdio_ext_test.cpp b/tests/stdio_ext_test.cpp
index d4616ef..d84fda0 100644
--- a/tests/stdio_ext_test.cpp
+++ b/tests/stdio_ext_test.cpp
@@ -29,7 +29,8 @@
 #include <wchar.h>
 #include <locale.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
+
 #include "utils.h"
 
 TEST(stdio_ext, __fbufsize) {
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 54b913a..e9ec499 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -31,8 +31,9 @@
 #include <string>
 #include <vector>
 
+#include <android-base/file.h>
+
 #include "BionicDeathTest.h"
-#include "TemporaryFile.h"
 #include "utils.h"
 
 #if defined(NOFORTIFY)
@@ -1412,7 +1413,7 @@
   fflush(fp);
   fclose(fp);
 
-  fp = fopen(tf.filename, "r");
+  fp = fopen(tf.path, "r");
   ASSERT_TRUE(fp != nullptr);
 
   // Store a valid position.
@@ -2041,7 +2042,7 @@
 TEST(STDIO_TEST, fread_after_fseek) {
   TemporaryFile tf;
 
-  FILE* fp = fopen(tf.filename, "w+");
+  FILE* fp = fopen(tf.path, "w+");
   ASSERT_TRUE(fp != nullptr);
 
   char file_data[12288];
@@ -2051,7 +2052,7 @@
   ASSERT_EQ(12288U, fwrite(file_data, 1, 12288, fp));
   fclose(fp);
 
-  fp = fopen(tf.filename, "r");
+  fp = fopen(tf.path, "r");
   ASSERT_TRUE(fp != nullptr);
 
   char buffer[8192];
@@ -2080,10 +2081,10 @@
   TemporaryFile tf;
   char buf[6] = {0};
 
-  FILE* fw = fopen(tf.filename, "w");
+  FILE* fw = fopen(tf.path, "w");
   ASSERT_TRUE(fw != nullptr);
 
-  FILE* fr = fopen(tf.filename, "r");
+  FILE* fr = fopen(tf.path, "r");
   ASSERT_TRUE(fr != nullptr);
 
   fwrite("a", 1, 1, fw);
@@ -2197,7 +2198,7 @@
   for (size_t i = 0; i < 256; ++i) {
     TemporaryFile* tf = new TemporaryFile;
     tfs.push_back(tf);
-    FILE* fp = fopen(tf->filename, "w+");
+    FILE* fp = fopen(tf->path, "w+");
     fps.push_back(fp);
     fprintf(fp, "hello %zu!\n", i);
     fflush(fp);
@@ -2313,21 +2314,21 @@
   struct stat sb;
 
   TemporaryFile tf;
-  ASSERT_EQ(0, remove(tf.filename));
-  ASSERT_EQ(-1, lstat(tf.filename, &sb));
+  ASSERT_EQ(0, remove(tf.path));
+  ASSERT_EQ(-1, lstat(tf.path, &sb));
   ASSERT_EQ(ENOENT, errno);
 
   TemporaryDir td;
-  ASSERT_EQ(0, remove(td.dirname));
-  ASSERT_EQ(-1, lstat(td.dirname, &sb));
+  ASSERT_EQ(0, remove(td.path));
+  ASSERT_EQ(-1, lstat(td.path, &sb));
   ASSERT_EQ(ENOENT, errno);
 
   errno = 0;
-  ASSERT_EQ(-1, remove(tf.filename));
+  ASSERT_EQ(-1, remove(tf.path));
   ASSERT_EQ(ENOENT, errno);
 
   errno = 0;
-  ASSERT_EQ(-1, remove(td.dirname));
+  ASSERT_EQ(-1, remove(td.path));
   ASSERT_EQ(ENOENT, errno);
 }
 
@@ -2404,8 +2405,8 @@
 
 TEST(STDIO_TEST, fopen_append_mode_and_ftell) {
   TemporaryFile tf;
-  SetFileTo(tf.filename, "0123456789");
-  FILE* fp = fopen(tf.filename, "a");
+  SetFileTo(tf.path, "0123456789");
+  FILE* fp = fopen(tf.path, "a");
   EXPECT_EQ(10, ftell(fp));
   ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
   EXPECT_EQ(2, ftell(fp));
@@ -2415,13 +2416,13 @@
   ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
   EXPECT_EQ(13, ftell(fp));
   ASSERT_EQ(0, fclose(fp));
-  AssertFileIs(tf.filename, "0123456789xxx");
+  AssertFileIs(tf.path, "0123456789xxx");
 }
 
 TEST(STDIO_TEST, fdopen_append_mode_and_ftell) {
   TemporaryFile tf;
-  SetFileTo(tf.filename, "0123456789");
-  int fd = open(tf.filename, O_RDWR);
+  SetFileTo(tf.path, "0123456789");
+  int fd = open(tf.path, O_RDWR);
   ASSERT_NE(-1, fd);
   // POSIX: "The file position indicator associated with the new stream is set to the position
   // indicated by the file offset associated with the file descriptor."
@@ -2436,14 +2437,14 @@
   ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
   EXPECT_EQ(13, ftell(fp));
   ASSERT_EQ(0, fclose(fp));
-  AssertFileIs(tf.filename, "0123456789xxx");
+  AssertFileIs(tf.path, "0123456789xxx");
 }
 
 TEST(STDIO_TEST, freopen_append_mode_and_ftell) {
   TemporaryFile tf;
-  SetFileTo(tf.filename, "0123456789");
+  SetFileTo(tf.path, "0123456789");
   FILE* other_fp = fopen("/proc/version", "r");
-  FILE* fp = freopen(tf.filename, "a", other_fp);
+  FILE* fp = freopen(tf.path, "a", other_fp);
   EXPECT_EQ(10, ftell(fp));
   ASSERT_EQ(0, fseek(fp, 2, SEEK_SET));
   EXPECT_EQ(2, ftell(fp));
@@ -2453,7 +2454,7 @@
   ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
   EXPECT_EQ(13, ftell(fp));
   ASSERT_EQ(0, fclose(fp));
-  AssertFileIs(tf.filename, "0123456789xxx");
+  AssertFileIs(tf.path, "0123456789xxx");
 }
 
 TEST(STDIO_TEST, constants) {
@@ -2476,7 +2477,7 @@
 TEST(STDIO_TEST, unlocked) {
   TemporaryFile tf;
 
-  FILE* fp = fopen(tf.filename, "w+");
+  FILE* fp = fopen(tf.path, "w+");
   ASSERT_TRUE(fp != nullptr);
 
   clearerr_unlocked(fp);
@@ -2521,7 +2522,7 @@
 
 TEST(STDIO_TEST, fseek_64bit) {
   TemporaryFile tf;
-  FILE* fp = fopen64(tf.filename, "w+");
+  FILE* fp = fopen64(tf.path, "w+");
   ASSERT_TRUE(fp != nullptr);
   ASSERT_EQ(0, fseeko64(fp, 0x2'0000'0000, SEEK_SET));
   ASSERT_EQ(0x2'0000'0000, ftello64(fp));
@@ -2534,7 +2535,7 @@
 // isn't representable in long/off_t.
 TEST(STDIO_TEST, fseek_overflow_32bit) {
   TemporaryFile tf;
-  FILE* fp = fopen64(tf.filename, "w+");
+  FILE* fp = fopen64(tf.path, "w+");
   ASSERT_EQ(0, ftruncate64(fileno(fp), 0x2'0000'0000));
 
   // Bionic implements overflow checking for SEEK_CUR, but glibc doesn't.
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 14848ae..00850f6 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -14,13 +14,6 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
-#include "BionicDeathTest.h"
-#include "math_data_test.h"
-#include "TemporaryFile.h"
-#include "utils.h"
-
 #include <errno.h>
 #include <fcntl.h>
 #include <libgen.h>
@@ -31,10 +24,16 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
 #include <limits>
 #include <string>
 
+#include <android-base/macros.h>
+#include <gtest/gtest.h>
+
+#include "BionicDeathTest.h"
+#include "math_data_test.h"
 #include "utils.h"
 
 #if defined(__BIONIC__)
@@ -45,6 +44,41 @@
   #endif
 #endif
 
+template <typename T = int (*)(char*)>
+class GenericTemporaryFile {
+ public:
+  explicit GenericTemporaryFile(T mk_fn = mkstemp) : mk_fn_(mk_fn) {
+    // Since we might be running on the host or the target, and if we're
+    // running on the host we might be running under bionic or glibc,
+    // let's just try both possible temporary directories and take the
+    // first one that works.
+    init("/data/local/tmp");
+    if (fd == -1) {
+      init("/tmp");
+    }
+  }
+
+  ~GenericTemporaryFile() {
+    close(fd);
+    unlink(path);
+  }
+
+  int fd;
+  char path[1024];
+
+ private:
+  T mk_fn_;
+
+  void init(const char* tmp_dir) {
+    snprintf(path, sizeof(path), "%s/TemporaryFile-XXXXXX", tmp_dir);
+    fd = mk_fn_(path);
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(GenericTemporaryFile);
+};
+
+typedef GenericTemporaryFile<> MyTemporaryFile;
+
 // The random number generator tests all set the seed, get four values, reset the seed and check
 // that they get the first two values repeated, and then reset the seed and check two more values
 // to rule out the possibility that we're just going round a cycle of four values.
@@ -386,24 +420,24 @@
 }
 
 TEST(stdlib, mkostemp64) {
-  TemporaryFile tf([](char* path) { return mkostemp64(path, O_CLOEXEC); });
+  MyTemporaryFile tf([](char* path) { return mkostemp64(path, O_CLOEXEC); });
   AssertCloseOnExec(tf.fd, true);
 }
 
 TEST(stdlib, mkostemp) {
-  TemporaryFile tf([](char* path) { return mkostemp(path, O_CLOEXEC); });
+  MyTemporaryFile tf([](char* path) { return mkostemp(path, O_CLOEXEC); });
   AssertCloseOnExec(tf.fd, true);
 }
 
 TEST(stdlib, mkstemp64) {
-  TemporaryFile tf(mkstemp64);
+  MyTemporaryFile tf(mkstemp64);
   struct stat64 sb;
   ASSERT_EQ(0, fstat64(tf.fd, &sb));
   ASSERT_EQ(O_LARGEFILE, fcntl(tf.fd, F_GETFL) & O_LARGEFILE);
 }
 
 TEST(stdlib, mkstemp) {
-  TemporaryFile tf;
+  MyTemporaryFile tf(mkstemp);
   struct stat sb;
   ASSERT_EQ(0, fstat(tf.fd, &sb));
 }
diff --git a/tests/sys_mman_test.cpp b/tests/sys_mman_test.cpp
index 22dc383..0b98198 100644
--- a/tests/sys_mman_test.cpp
+++ b/tests/sys_mman_test.cpp
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
+#include <fcntl.h>
 #include <sys/mman.h>
 #include <sys/user.h>
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
+#include <gtest/gtest.h>
 
 TEST(sys_mman, mmap_std) {
   void* map = mmap(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
@@ -82,7 +82,7 @@
 
   ASSERT_EQ(0, munmap(map, sizeof(STRING_MSG)));
 
-  tf.reopen();
+  tf.fd = open(tf.path, O_RDWR);
   char buf[sizeof(STRING_MSG)];
   memset(buf, 0, sizeof(STRING_MSG));
   ASSERT_EQ(STR_SSIZE(STRING_MSG), read(tf.fd, buf, sizeof(STRING_MSG)));
@@ -153,7 +153,7 @@
   memcpy(map, NEWPAGE1_MSG, sizeof(NEWPAGE1_MSG));
   ASSERT_EQ(0, munmap(map, pagesize));
 
-  tf.reopen();
+  tf.fd = open(tf.path, O_RDWR);
   map = mmap(nullptr, pagesize, PROT_WRITE, MAP_SHARED, tf.fd, 2 * pagesize);
   ASSERT_NE(MAP_FAILED, map);
   close(tf.fd);
@@ -161,7 +161,7 @@
   memcpy(map, NEWPAGE2_MSG, sizeof(NEWPAGE2_MSG));
   ASSERT_EQ(0, munmap(map, pagesize));
 
-  tf.reopen();
+  tf.fd = open(tf.path, O_RDWR);
   char buf[pagesize];
   ASSERT_EQ(static_cast<ssize_t>(pagesize), read(tf.fd, buf, pagesize));
   ASSERT_STREQ(PAGE0_MSG, buf);
diff --git a/tests/sys_msg_test.cpp b/tests/sys_msg_test.cpp
index 4eb5a14..8b3623e 100644
--- a/tests/sys_msg_test.cpp
+++ b/tests/sys_msg_test.cpp
@@ -31,7 +31,7 @@
 #include <errno.h>
 #include <sys/msg.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 
 TEST(sys_msg, smoke) {
   if (msgctl(-1, IPC_STAT, nullptr) == -1 && errno == ENOSYS) {
@@ -41,7 +41,7 @@
 
   // Create a queue.
   TemporaryDir dir;
-  key_t key = ftok(dir.dirname, 1);
+  key_t key = ftok(dir.path, 1);
   int id = msgget(key, IPC_CREAT|0666);
   ASSERT_NE(id, -1);
 
diff --git a/tests/sys_sem_test.cpp b/tests/sys_sem_test.cpp
index eaf2b8f..dff34c8 100644
--- a/tests/sys_sem_test.cpp
+++ b/tests/sys_sem_test.cpp
@@ -31,7 +31,7 @@
 #include <errno.h>
 #include <sys/sem.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 
 TEST(sys_sem, smoke) {
   if (semctl(-1, 0, IPC_RMID) == -1 && errno == ENOSYS) {
@@ -41,7 +41,7 @@
 
   // Create a semaphore.
   TemporaryDir dir;
-  key_t key = ftok(dir.dirname, 1);
+  key_t key = ftok(dir.path, 1);
   int id = semget(key, 1, IPC_CREAT|0666);
   ASSERT_NE(id, -1);
 
diff --git a/tests/sys_sendfile_test.cpp b/tests/sys_sendfile_test.cpp
index 3d6b5cc..4cddd0d 100644
--- a/tests/sys_sendfile_test.cpp
+++ b/tests/sys_sendfile_test.cpp
@@ -14,14 +14,15 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-#include "TemporaryFile.h"
 
-#include <sys/sendfile.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <sys/sendfile.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <android-base/file.h>
+#include <gtest/gtest.h>
 
 TEST(sys_sendfile, sendfile) {
   TemporaryFile src_file;
diff --git a/tests/sys_shm_test.cpp b/tests/sys_shm_test.cpp
index ca2d01a..15abe05 100644
--- a/tests/sys_shm_test.cpp
+++ b/tests/sys_shm_test.cpp
@@ -26,12 +26,11 @@
  * SUCH DAMAGE.
  */
 
-#include <gtest/gtest.h>
-
 #include <errno.h>
 #include <sys/shm.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
+#include <gtest/gtest.h>
 
 TEST(sys_shm, smoke) {
   if (shmctl(-1, IPC_STAT, nullptr) == -1 && errno == ENOSYS) {
@@ -41,7 +40,7 @@
 
   // Create a segment.
   TemporaryDir dir;
-  key_t key = ftok(dir.dirname, 1);
+  key_t key = ftok(dir.path, 1);
   int id = shmget(key, 1234, IPC_CREAT|0666);
   ASSERT_NE(id, -1);
 
diff --git a/tests/sys_stat_test.cpp b/tests/sys_stat_test.cpp
index c0a576d..70ad451 100644
--- a/tests/sys_stat_test.cpp
+++ b/tests/sys_stat_test.cpp
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
 #include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
+#include <gtest/gtest.h>
 
 TEST(sys_stat, futimens) {
   FILE* fp = tmpfile();
@@ -73,7 +72,7 @@
     std::string path;
     {
       TemporaryFile tf;
-      path = tf.filename;
+      path = tf.path;
     }
 
     ASSERT_EQ(0, mkfifo(path.c_str(), 0666));
@@ -148,19 +147,19 @@
 TEST(sys_stat, fchmodat_file) {
   TemporaryFile tf;
 
-  ASSERT_EQ(0, fchmodat(AT_FDCWD, tf.filename, 0751, 0));
-  AssertFileModeEquals(0751, tf.filename);
+  ASSERT_EQ(0, fchmodat(AT_FDCWD, tf.path, 0751, 0));
+  AssertFileModeEquals(0751, tf.path);
 }
 
 TEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_file) {
   TemporaryFile tf;
   errno = 0;
-  int result = fchmodat(AT_FDCWD, tf.filename, 0751, AT_SYMLINK_NOFOLLOW);
+  int result = fchmodat(AT_FDCWD, tf.path, 0751, AT_SYMLINK_NOFOLLOW);
 
 #if defined(__BIONIC__)
   ASSERT_EQ(0, result);
   ASSERT_EQ(0, errno);
-  AssertFileModeEquals(0751, tf.filename);
+  AssertFileModeEquals(0751, tf.path);
 #else
   // glibc 2.19 does not implement AT_SYMLINK_NOFOLLOW and always
   // returns ENOTSUP
@@ -173,11 +172,11 @@
   TemporaryFile tf;
   char linkname[255];
 
-  snprintf(linkname, sizeof(linkname), "%s.link", tf.filename);
+  snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
 
-  ASSERT_EQ(0, symlink(tf.filename, linkname));
+  ASSERT_EQ(0, symlink(tf.path, linkname));
   ASSERT_EQ(0, fchmodat(AT_FDCWD, linkname, 0751, 0));
-  AssertFileModeEquals(0751, tf.filename);
+  AssertFileModeEquals(0751, tf.path);
   unlink(linkname);
 }
 
@@ -186,8 +185,8 @@
   char linkname[255];
   char target[255];
 
-  snprintf(linkname, sizeof(linkname), "%s.link", tf.filename);
-  snprintf(target, sizeof(target), "%s.doesnotexist", tf.filename);
+  snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
+  snprintf(target, sizeof(target), "%s.doesnotexist", tf.path);
 
   ASSERT_EQ(0, symlink(target, linkname));
   ASSERT_EQ(-1, fchmodat(AT_FDCWD, linkname, 0751, 0));
@@ -205,12 +204,12 @@
 TEST(sys_stat, fchmodat_AT_SYMLINK_NOFOLLOW_with_symlink) {
   TemporaryFile tf;
   struct stat tf_sb;
-  ASSERT_EQ(0, stat(tf.filename, &tf_sb));
+  ASSERT_EQ(0, stat(tf.path, &tf_sb));
 
   char linkname[255];
-  snprintf(linkname, sizeof(linkname), "%s.link", tf.filename);
+  snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
 
-  ASSERT_EQ(0, symlink(tf.filename, linkname));
+  ASSERT_EQ(0, symlink(tf.path, linkname));
   int result = fchmodat(AT_FDCWD, linkname, 0751, AT_SYMLINK_NOFOLLOW);
   // It depends on the kernel whether chmod operation on symlink is allowed.
   if (result == 0) {
@@ -221,7 +220,7 @@
   }
 
   // Target file mode shouldn't be modified.
-  AssertFileModeEquals(tf_sb.st_mode, tf.filename);
+  AssertFileModeEquals(tf_sb.st_mode, tf.path);
   unlink(linkname);
 }
 
@@ -230,8 +229,8 @@
 
   char linkname[255];
   char target[255];
-  snprintf(linkname, sizeof(linkname), "%s.link", tf.filename);
-  snprintf(target, sizeof(target), "%s.doesnotexist", tf.filename);
+  snprintf(linkname, sizeof(linkname), "%s.link", tf.path);
+  snprintf(target, sizeof(target), "%s.doesnotexist", tf.path);
 
   ASSERT_EQ(0, symlink(target, linkname));
   int result = fchmodat(AT_FDCWD, linkname, 0751, AT_SYMLINK_NOFOLLOW);
diff --git a/tests/sys_time_test.cpp b/tests/sys_time_test.cpp
index b3ec161..16187eb 100644
--- a/tests/sys_time_test.cpp
+++ b/tests/sys_time_test.cpp
@@ -17,15 +17,16 @@
 #include <gtest/gtest.h>
 
 #include <errno.h>
+#include <fcntl.h>
 #include <sys/syscall.h>
 #include <sys/time.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 
 // http://b/11383777
 TEST(sys_time, utimes_nullptr) {
   TemporaryFile tf;
-  ASSERT_EQ(0, utimes(tf.filename, nullptr));
+  ASSERT_EQ(0, utimes(tf.path, nullptr));
 }
 
 TEST(sys_time, utimes_EINVAL) {
@@ -34,19 +35,19 @@
   timeval tv[2] = {};
 
   tv[0].tv_usec = -123;
-  ASSERT_EQ(-1, utimes(tf.filename, tv));
+  ASSERT_EQ(-1, utimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[0].tv_usec = 1234567;
-  ASSERT_EQ(-1, utimes(tf.filename, tv));
+  ASSERT_EQ(-1, utimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
 
   tv[0].tv_usec = 0;
 
   tv[1].tv_usec = -123;
-  ASSERT_EQ(-1, utimes(tf.filename, tv));
+  ASSERT_EQ(-1, utimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[1].tv_usec = 1234567;
-  ASSERT_EQ(-1, utimes(tf.filename, tv));
+  ASSERT_EQ(-1, utimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
 }
 
@@ -79,7 +80,7 @@
 
 TEST(sys_time, futimesat_nullptr) {
   TemporaryFile tf;
-  ASSERT_EQ(0, futimesat(AT_FDCWD, tf.filename, nullptr));
+  ASSERT_EQ(0, futimesat(AT_FDCWD, tf.path, nullptr));
 }
 
 TEST(sys_time, futimesat_EINVAL) {
@@ -88,25 +89,25 @@
   timeval tv[2] = {};
 
   tv[0].tv_usec = -123;
-  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.filename, tv));
+  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[0].tv_usec = 1234567;
-  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.filename, tv));
+  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
 
   tv[0].tv_usec = 0;
 
   tv[1].tv_usec = -123;
-  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.filename, tv));
+  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[1].tv_usec = 1234567;
-  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.filename, tv));
+  ASSERT_EQ(-1, futimesat(AT_FDCWD, tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
 }
 
 TEST(sys_time, lutimes_nullptr) {
   TemporaryFile tf;
-  ASSERT_EQ(0, lutimes(tf.filename, nullptr));
+  ASSERT_EQ(0, lutimes(tf.path, nullptr));
 }
 
 TEST(sys_time, lutimes_EINVAL) {
@@ -115,19 +116,19 @@
   timeval tv[2] = {};
 
   tv[0].tv_usec = -123;
-  ASSERT_EQ(-1, lutimes(tf.filename, tv));
+  ASSERT_EQ(-1, lutimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[0].tv_usec = 1234567;
-  ASSERT_EQ(-1, lutimes(tf.filename, tv));
+  ASSERT_EQ(-1, lutimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
 
   tv[0].tv_usec = 0;
 
   tv[1].tv_usec = -123;
-  ASSERT_EQ(-1, lutimes(tf.filename, tv));
+  ASSERT_EQ(-1, lutimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
   tv[1].tv_usec = 1234567;
-  ASSERT_EQ(-1, lutimes(tf.filename, tv));
+  ASSERT_EQ(-1, lutimes(tf.path, tv));
   ASSERT_EQ(EINVAL, errno);
 }
 
diff --git a/tests/sys_uio_test.cpp b/tests/sys_uio_test.cpp
index 60bd224..8460041 100644
--- a/tests/sys_uio_test.cpp
+++ b/tests/sys_uio_test.cpp
@@ -18,7 +18,7 @@
 
 #include <sys/uio.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
 
 TEST(sys_uio, readv_writev) {
   TemporaryFile tf;
diff --git a/tests/sys_xattr_test.cpp b/tests/sys_xattr_test.cpp
index 006e840..8f4a336 100644
--- a/tests/sys_xattr_test.cpp
+++ b/tests/sys_xattr_test.cpp
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/xattr.h>
 
-#include "TemporaryFile.h"
+#include <android-base/file.h>
+#include <gtest/gtest.h>
 
 TEST(sys_xattr, setxattr) {
   TemporaryFile tf;
   char buf[10];
-  ASSERT_EQ(0, setxattr(tf.filename, "user.foo", "bar", 4, 0));
-  ASSERT_EQ(4, getxattr(tf.filename, "user.foo", buf, sizeof(buf)));
+  ASSERT_EQ(0, setxattr(tf.path, "user.foo", "bar", 4, 0));
+  ASSERT_EQ(4, getxattr(tf.path, "user.foo", buf, sizeof(buf)));
   ASSERT_STREQ("bar", buf);
   buf[0] = '\0';
-  ASSERT_EQ(4, lgetxattr(tf.filename, "user.foo", buf, sizeof(buf)));
+  ASSERT_EQ(4, lgetxattr(tf.path, "user.foo", buf, sizeof(buf)));
   ASSERT_STREQ("bar", buf);
 }
 
@@ -67,7 +67,7 @@
 
 TEST(sys_xattr, fsetxattr_with_opath) {
   TemporaryFile tf;
-  int fd = open(tf.filename, O_PATH);
+  int fd = open(tf.path, O_PATH);
   ASSERT_NE(-1, fd);
 
   int res = fsetxattr(fd, "user.foo", "bar", 4, 0);
@@ -85,7 +85,7 @@
 
 TEST(sys_xattr, fsetxattr_with_opath_toosmall) {
   TemporaryFile tf;
-  int fd = open(tf.filename, O_PATH);
+  int fd = open(tf.path, O_PATH);
   ASSERT_NE(-1, fd);
 
   int res = fsetxattr(fd, "user.foo", "01234567890123456789", 21, 0);
@@ -114,7 +114,7 @@
   TemporaryFile tf;
   char buf[65536];  // 64kB is max possible xattr list size. See "man 7 xattr".
   ASSERT_EQ(0, fsetxattr(tf.fd, "user.foo", "bar", 4, 0));
-  int fd = open(tf.filename, O_PATH);
+  int fd = open(tf.path, O_PATH);
   ASSERT_NE(-1, fd);
   ssize_t res = flistxattr(fd, buf, sizeof(buf));
 #if defined(__BIONIC__)
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index da083de..f4a7f1f 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -18,7 +18,6 @@
 
 #include "BionicDeathTest.h"
 #include "SignalUtils.h"
-#include "TemporaryFile.h"
 #include "utils.h"
 
 #include <errno.h>
@@ -166,20 +165,20 @@
 TEST(UNISTD_TEST, truncate) {
   TemporaryFile tf;
   ASSERT_EQ(0, close(tf.fd));
-  ASSERT_EQ(0, truncate(tf.filename, 123));
+  ASSERT_EQ(0, truncate(tf.path, 123));
 
   struct stat sb;
-  ASSERT_EQ(0, stat(tf.filename, &sb));
+  ASSERT_EQ(0, stat(tf.path, &sb));
   ASSERT_EQ(123, sb.st_size);
 }
 
 TEST(UNISTD_TEST, truncate64) {
   TemporaryFile tf;
   ASSERT_EQ(0, close(tf.fd));
-  ASSERT_EQ(0, truncate64(tf.filename, 123));
+  ASSERT_EQ(0, truncate64(tf.path, 123));
 
   struct stat sb;
-  ASSERT_EQ(0, stat(tf.filename, &sb));
+  ASSERT_EQ(0, stat(tf.path, &sb));
   ASSERT_EQ(123, sb.st_size);
 }
 
@@ -189,7 +188,7 @@
   ASSERT_EQ(0, close(tf.fd));
 
   struct stat sb;
-  ASSERT_EQ(0, stat(tf.filename, &sb));
+  ASSERT_EQ(0, stat(tf.path, &sb));
   ASSERT_EQ(123, sb.st_size);
 }
 
@@ -199,7 +198,7 @@
   ASSERT_EQ(0, close(tf.fd));
 
   struct stat sb;
-  ASSERT_EQ(0, stat(tf.filename, &sb));
+  ASSERT_EQ(0, stat(tf.path, &sb));
   ASSERT_EQ(123, sb.st_size);
 }
 
@@ -389,11 +388,11 @@
 
   EXPECT_EQ(0, fn(tf.fd));
 
-  ASSERT_NE(-1, fd = open(tf.filename, O_RDONLY));
+  ASSERT_NE(-1, fd = open(tf.path, O_RDONLY));
   EXPECT_EQ(0, fn(fd));
   close(fd);
 
-  ASSERT_NE(-1, fd = open(tf.filename, O_RDWR));
+  ASSERT_NE(-1, fd = open(tf.path, O_RDWR));
   EXPECT_EQ(0, fn(fd));
   close(fd);
 
@@ -671,11 +670,11 @@
   long rc = 0L;
   // As a file system's block size is always power of 2, the configure values
   // for ALLOC and XFER should be power of 2 as well.
-  rc = pathconf(tf.filename, _PC_ALLOC_SIZE_MIN);
+  rc = pathconf(tf.path, _PC_ALLOC_SIZE_MIN);
   ASSERT_TRUE(rc > 0 && powerof2(rc));
-  rc = pathconf(tf.filename, _PC_REC_MIN_XFER_SIZE);
+  rc = pathconf(tf.path, _PC_REC_MIN_XFER_SIZE);
   ASSERT_TRUE(rc > 0 && powerof2(rc));
-  rc = pathconf(tf.filename, _PC_REC_XFER_ALIGN);
+  rc = pathconf(tf.path, _PC_REC_XFER_ALIGN);
   ASSERT_TRUE(rc > 0 && powerof2(rc));
 
   rc = fpathconf(tf.fd, _PC_ALLOC_SIZE_MIN);
@@ -1343,38 +1342,38 @@
 TEST(UNISTD_TEST, execvpe_ENOEXEC) {
   // Create a shell script with #!.
   TemporaryFile tf;
-  ASSERT_TRUE(android::base::WriteStringToFile("#!" BIN_DIR "sh\necho script\n", tf.filename));
+  ASSERT_TRUE(android::base::WriteStringToFile("#!" BIN_DIR "sh\necho script\n", tf.path));
 
   // Set $PATH so we can find it.
-  setenv("PATH", dirname(tf.filename), 1);
+  setenv("PATH", dirname(tf.path), 1);
 
   ExecTestHelper eth;
-  eth.SetArgs({basename(tf.filename), nullptr});
+  eth.SetArgs({basename(tf.path), nullptr});
 
   // It's not inherently executable.
   errno = 0;
-  ASSERT_EQ(-1, execvpe(basename(tf.filename), eth.GetArgs(), eth.GetEnv()));
+  ASSERT_EQ(-1, execvpe(basename(tf.path), eth.GetArgs(), eth.GetEnv()));
   ASSERT_EQ(EACCES, errno);
 
   // Make it executable (and keep it writable because we're going to rewrite it below).
-  ASSERT_EQ(0, chmod(tf.filename, 0777));
+  ASSERT_EQ(0, chmod(tf.path, 0777));
 
   // TemporaryFile will have a writable fd, so we can test ETXTBSY while we're here...
   errno = 0;
-  ASSERT_EQ(-1, execvpe(basename(tf.filename), eth.GetArgs(), eth.GetEnv()));
+  ASSERT_EQ(-1, execvpe(basename(tf.path), eth.GetArgs(), eth.GetEnv()));
   ASSERT_EQ(ETXTBSY, errno);
 
   // 1. The simplest test: the kernel should handle this.
   ASSERT_EQ(0, close(tf.fd));
-  eth.Run([&]() { execvpe(basename(tf.filename), eth.GetArgs(), eth.GetEnv()); }, 0, "script\n");
+  eth.Run([&]() { execvpe(basename(tf.path), eth.GetArgs(), eth.GetEnv()); }, 0, "script\n");
 
   // 2. Try again without a #!. We should have to handle this ourselves.
-  ASSERT_TRUE(android::base::WriteStringToFile("echo script\n", tf.filename));
-  eth.Run([&]() { execvpe(basename(tf.filename), eth.GetArgs(), eth.GetEnv()); }, 0, "script\n");
+  ASSERT_TRUE(android::base::WriteStringToFile("echo script\n", tf.path));
+  eth.Run([&]() { execvpe(basename(tf.path), eth.GetArgs(), eth.GetEnv()); }, 0, "script\n");
 
   // 3. Again without a #!, but also with a leading '/', since that's a special case in the
   // implementation.
-  eth.Run([&]() { execvpe(tf.filename, eth.GetArgs(), eth.GetEnv()); }, 0, "script\n");
+  eth.Run([&]() { execvpe(tf.path, eth.GetArgs(), eth.GetEnv()); }, 0, "script\n");
 }
 
 TEST(UNISTD_TEST, execvp_libcore_test_55017) {