Merge "Take a getopt_long() patch from upstream FreeBSD."
diff --git a/libc/Android.bp b/libc/Android.bp
index 45c4569..e30abb7 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -854,20 +854,28 @@
         },
         arm64: {
             srcs: [
-                "arch-arm64/generic/bionic/memchr.S",
                 "arch-arm64/generic/bionic/memcmp.S",
                 "arch-arm64/generic/bionic/memcpy.S",
                 "arch-arm64/generic/bionic/memmove.S",
                 "arch-arm64/generic/bionic/memset.S",
                 "arch-arm64/generic/bionic/stpcpy.S",
-                "arch-arm64/generic/bionic/strchr.S",
-                "arch-arm64/generic/bionic/strcmp.S",
                 "arch-arm64/generic/bionic/strcpy.S",
-                "arch-arm64/generic/bionic/strlen.S",
-                "arch-arm64/generic/bionic/strncmp.S",
-                "arch-arm64/generic/bionic/strnlen.S",
                 "arch-arm64/generic/bionic/wmemmove.S",
 
+                "arch-arm64/default/bionic/memchr.S",
+                "arch-arm64/default/bionic/strchr.S",
+                "arch-arm64/default/bionic/strcmp.S",
+                "arch-arm64/default/bionic/strlen.S",
+                "arch-arm64/default/bionic/strncmp.S",
+                "arch-arm64/default/bionic/strnlen.S",
+
+                "arch-arm64/mte/bionic/memchr.c",
+                "arch-arm64/mte/bionic/strchr.cpp",
+                "arch-arm64/mte/bionic/strcmp.c",
+                "arch-arm64/mte/bionic/strlen.c",
+                "arch-arm64/mte/bionic/strncmp.c",
+                "arch-arm64/mte/bionic/strnlen.c",
+
                 "arch-arm64/bionic/__bionic_clone.S",
                 "arch-arm64/bionic/_exit_with_stack_teardown.S",
                 "arch-arm64/bionic/setjmp.S",
@@ -1494,6 +1502,9 @@
         arm: {
             srcs: ["arch-arm/static_function_dispatch.S"],
         },
+        arm64: {
+            srcs: ["arch-arm64/static_function_dispatch.S"],
+        },
     },
 
     whole_static_libs: [
@@ -1519,6 +1530,9 @@
         arm: {
             srcs: ["arch-arm/dynamic_function_dispatch.cpp"],
         },
+        arm64: {
+            srcs: ["arch-arm64/dynamic_function_dispatch.cpp"],
+        },
     },
 
     whole_static_libs: [
diff --git a/libc/arch-arm/dynamic_function_dispatch.cpp b/libc/arch-arm/dynamic_function_dispatch.cpp
index 75000a2..1d2f38f 100644
--- a/libc/arch-arm/dynamic_function_dispatch.cpp
+++ b/libc/arch-arm/dynamic_function_dispatch.cpp
@@ -149,7 +149,7 @@
 
 typedef void* memcpy_func(void*, const void*, size_t);
 DEFINE_IFUNC_FOR(memcpy) {
-    return memmove_resolver();
+    return memmove_resolver(hwcap);
 }
 
 typedef void* __memcpy_func(void*, const void*, size_t);
diff --git a/libc/arch-arm64/generic/bionic/memchr.S b/libc/arch-arm64/default/bionic/memchr.S
similarity index 98%
rename from libc/arch-arm64/generic/bionic/memchr.S
rename to libc/arch-arm64/default/bionic/memchr.S
index 7b7e699..7fbcc8f 100644
--- a/libc/arch-arm64/generic/bionic/memchr.S
+++ b/libc/arch-arm64/default/bionic/memchr.S
@@ -69,7 +69,7 @@
  * identify exactly which byte has matched.
  */
 
-ENTRY(memchr)
+ENTRY(memchr_default)
 	/*
 	 * Magic constant 0x40100401 allows us to identify which lane matches
 	 * the requested byte.
@@ -161,4 +161,4 @@
 .Lzero_length:
 	mov	result, xzr
 	ret
-END(memchr)
+END(memchr_default)
diff --git a/libc/arch-arm64/generic/bionic/strchr.S b/libc/arch-arm64/default/bionic/strchr.S
similarity index 98%
rename from libc/arch-arm64/generic/bionic/strchr.S
rename to libc/arch-arm64/default/bionic/strchr.S
index 2db0c76..f8cb724 100644
--- a/libc/arch-arm64/generic/bionic/strchr.S
+++ b/libc/arch-arm64/default/bionic/strchr.S
@@ -73,7 +73,7 @@
 
 /* Locals and temporaries.  */
 
-ENTRY(strchr)
+ENTRY(strchr_default)
 	/* Magic constant 0x40100401 to allow us to identify which lane
 	   matches the requested byte.  Magic constant 0x80200802 used
 	   similarly for NUL termination.  */
@@ -150,4 +150,4 @@
 	add	result, src, tmp1, lsr #1
 	csel	result, result, xzr, eq
 	ret
-END(strchr)
+END(strchr_default)
diff --git a/libc/arch-arm64/generic/bionic/strcmp.S b/libc/arch-arm64/default/bionic/strcmp.S
similarity index 99%
rename from libc/arch-arm64/generic/bionic/strcmp.S
rename to libc/arch-arm64/default/bionic/strcmp.S
index fbc215e..dfac7c4 100644
--- a/libc/arch-arm64/generic/bionic/strcmp.S
+++ b/libc/arch-arm64/default/bionic/strcmp.S
@@ -58,7 +58,7 @@
 #define pos		x11
 
 	/* Start of performance-critical section  -- one 64B cache line.  */
-ENTRY(strcmp)
+ENTRY(strcmp_default)
 .p2align  6
 	eor	tmp1, src1, src2
 	mov	zeroones, #REP8_01
@@ -189,4 +189,4 @@
 L(done):
 	sub	result, data1, data2
 	ret
-END(strcmp)
+END(strcmp_default)
diff --git a/libc/arch-arm64/generic/bionic/strlen.S b/libc/arch-arm64/default/bionic/strlen.S
similarity index 99%
rename from libc/arch-arm64/generic/bionic/strlen.S
rename to libc/arch-arm64/default/bionic/strlen.S
index 6e540fc..07c5294 100644
--- a/libc/arch-arm64/generic/bionic/strlen.S
+++ b/libc/arch-arm64/default/bionic/strlen.S
@@ -94,7 +94,7 @@
 	   whether the first fetch, which may be misaligned, crosses a page
 	   boundary.  */
 
-ENTRY(strlen)
+ENTRY(strlen_default)
 	and	tmp1, srcin, MIN_PAGE_SIZE - 1
 	mov	zeroones, REP8_01
 	cmp	tmp1, MIN_PAGE_SIZE - 16
@@ -224,4 +224,4 @@
 	csel	data2, data2, tmp2, eq
 	b	L(page_cross_entry)
 
-END(strlen)
+END(strlen_default)
diff --git a/libc/arch-arm64/generic/bionic/strncmp.S b/libc/arch-arm64/default/bionic/strncmp.S
similarity index 99%
rename from libc/arch-arm64/generic/bionic/strncmp.S
rename to libc/arch-arm64/default/bionic/strncmp.S
index b81f43a..5432b73 100644
--- a/libc/arch-arm64/generic/bionic/strncmp.S
+++ b/libc/arch-arm64/default/bionic/strncmp.S
@@ -65,7 +65,7 @@
 	.rep 7
 	nop	/* Pad so that the loop below fits a cache line.  */
 	.endr
-ENTRY(strncmp)
+ENTRY(strncmp_default)
 	cbz	limit, .Lret0
 	eor	tmp1, src1, src2
 	mov	zeroones, #REP8_01
@@ -277,4 +277,4 @@
 .Lret0:
 	mov	result, #0
 	ret
-END(strncmp)
+END(strncmp_default)
diff --git a/libc/arch-arm64/generic/bionic/strnlen.S b/libc/arch-arm64/default/bionic/strnlen.S
similarity index 98%
rename from libc/arch-arm64/generic/bionic/strnlen.S
rename to libc/arch-arm64/default/bionic/strnlen.S
index 0ad446e..1694532 100644
--- a/libc/arch-arm64/generic/bionic/strnlen.S
+++ b/libc/arch-arm64/default/bionic/strnlen.S
@@ -68,7 +68,7 @@
 	mov	len, limit
 	ret
 
-ENTRY(strnlen)
+ENTRY(strnlen_default)
 	cbz	limit, .Lhit_limit
 	mov	zeroones, #REP8_01
 	bic	src, srcin, #15
@@ -171,4 +171,4 @@
 	csinv	data1, data1, xzr, le
 	csel	data2, data2, data2a, le
 	b	.Lrealigned
-END(strnlen)
+END(strnlen_default)
diff --git a/libc/arch-arm64/dynamic_function_dispatch.cpp b/libc/arch-arm64/dynamic_function_dispatch.cpp
new file mode 100644
index 0000000..37abea4
--- /dev/null
+++ b/libc/arch-arm64/dynamic_function_dispatch.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 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 <platform/bionic/mte_kernel.h>
+#include <private/bionic_ifuncs.h>
+#include <stddef.h>
+#include <sys/auxv.h>
+
+extern "C" {
+
+static bool supports_mte(unsigned long hwcap2) {
+#ifdef ANDROID_EXPERIMENTAL_MTE
+    return hwcap2 & HWCAP2_MTE;
+#else
+    (void)hwcap2;
+    return false;
+#endif
+}
+
+typedef void* memchr_func(const void*, int, size_t);
+DEFINE_IFUNC_FOR(memchr) {
+    if (supports_mte(arg->_hwcap2)) {
+        RETURN_FUNC(memchr_func, memchr_mte);
+    } else {
+        RETURN_FUNC(memchr_func, memchr_default);
+    }
+}
+
+typedef char* strchr_func(const char*, int);
+DEFINE_IFUNC_FOR(strchr) {
+    if (supports_mte(arg->_hwcap2)) {
+        RETURN_FUNC(strchr_func, strchr_mte);
+    } else {
+        RETURN_FUNC(strchr_func, strchr_default);
+    }
+}
+
+typedef int strcmp_func(const char*, const char*);
+DEFINE_IFUNC_FOR(strcmp) {
+    if (supports_mte(arg->_hwcap2)) {
+        RETURN_FUNC(strcmp_func, strcmp_mte);
+    } else {
+        RETURN_FUNC(strcmp_func, strcmp_default);
+    }
+}
+
+typedef size_t strlen_func(const char*);
+DEFINE_IFUNC_FOR(strlen) {
+    if (supports_mte(arg->_hwcap2)) {
+        RETURN_FUNC(strlen_func, strlen_mte);
+    } else {
+        RETURN_FUNC(strlen_func, strlen_default);
+    }
+}
+
+typedef int strncmp_func(const char*, const char*, int);
+DEFINE_IFUNC_FOR(strncmp) {
+    if (supports_mte(arg->_hwcap2)) {
+        RETURN_FUNC(strncmp_func, strncmp_mte);
+    } else {
+        RETURN_FUNC(strncmp_func, strncmp_default);
+    }
+}
+
+typedef size_t strnlen_func(const char*, int);
+DEFINE_IFUNC_FOR(strnlen) {
+    if (supports_mte(arg->_hwcap2)) {
+        RETURN_FUNC(strnlen_func, strnlen_mte);
+    } else {
+        RETURN_FUNC(strnlen_func, strnlen_default);
+    }
+}
+
+}  // extern "C"
diff --git a/libc/arch-arm64/mte/bionic/memchr.c b/libc/arch-arm64/mte/bionic/memchr.c
new file mode 100644
index 0000000..33b2fc2
--- /dev/null
+++ b/libc/arch-arm64/mte/bionic/memchr.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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 memchr memchr_mte
+#include <upstream-openbsd/lib/libc/string/memchr.c>
diff --git a/libc/arch-arm64/mte/bionic/strchr.cpp b/libc/arch-arm64/mte/bionic/strchr.cpp
new file mode 100644
index 0000000..7d394df
--- /dev/null
+++ b/libc/arch-arm64/mte/bionic/strchr.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 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 strchr strchr_mte
+#include <bionic/strchr.cpp>
diff --git a/libc/arch-arm64/mte/bionic/strcmp.c b/libc/arch-arm64/mte/bionic/strcmp.c
new file mode 100644
index 0000000..0e134f0
--- /dev/null
+++ b/libc/arch-arm64/mte/bionic/strcmp.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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 strcmp strcmp_mte
+#include <upstream-openbsd/lib/libc/string/strcmp.c>
diff --git a/libc/arch-arm64/mte/bionic/strlen.c b/libc/arch-arm64/mte/bionic/strlen.c
new file mode 100644
index 0000000..de88320
--- /dev/null
+++ b/libc/arch-arm64/mte/bionic/strlen.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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 strlen strlen_mte
+#include <upstream-openbsd/lib/libc/string/strlen.c>
diff --git a/libc/arch-arm64/mte/bionic/strncmp.c b/libc/arch-arm64/mte/bionic/strncmp.c
new file mode 100644
index 0000000..54d08e9
--- /dev/null
+++ b/libc/arch-arm64/mte/bionic/strncmp.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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 strncmp strncmp_mte
+#include <upstream-openbsd/lib/libc/string/strncmp.c>
diff --git a/libc/arch-arm64/mte/bionic/strnlen.c b/libc/arch-arm64/mte/bionic/strnlen.c
new file mode 100644
index 0000000..3dc251d
--- /dev/null
+++ b/libc/arch-arm64/mte/bionic/strnlen.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 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 strnlen strnlen_mte
+#include <bionic/strnlen.c>
diff --git a/libc/arch-arm64/static_function_dispatch.S b/libc/arch-arm64/static_function_dispatch.S
new file mode 100644
index 0000000..8e3a4c1
--- /dev/null
+++ b/libc/arch-arm64/static_function_dispatch.S
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 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); \
+    b impl; \
+END(name)
+
+FUNCTION_DELEGATE(memchr, memchr_mte)
+FUNCTION_DELEGATE(strchr, strchr_mte)
+FUNCTION_DELEGATE(strcmp, strcmp_mte)
+FUNCTION_DELEGATE(strlen, strlen_mte)
+FUNCTION_DELEGATE(strncmp, strncmp_mte)
+FUNCTION_DELEGATE(strnlen, strnlen_mte)
diff --git a/libc/platform/bionic/mte_kernel.h b/libc/platform/bionic/mte_kernel.h
new file mode 100644
index 0000000..04f2bb6
--- /dev/null
+++ b/libc/platform/bionic/mte_kernel.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+// Defines constants used as part of the interface in an experimental MTE branch
+// of the Linux kernel, which may be found at:
+//
+// https://github.com/pcc/linux/tree/android-experimental-mte
+//
+// This interface should not be considered to be stable.
+
+#ifdef ANDROID_EXPERIMENTAL_MTE
+#define HWCAP2_MTE (1UL << 31)
+#define PROT_MTE 0x10
+#endif
diff --git a/libc/private/bionic_ifuncs.h b/libc/private/bionic_ifuncs.h
index 35961fb..f175bec 100644
--- a/libc/private/bionic_ifuncs.h
+++ b/libc/private/bionic_ifuncs.h
@@ -28,10 +28,22 @@
 
 #pragma once
 
+#include <stdint.h>
+#include <sys/ifunc.h>
+
+#if defined(__aarch64__)
+#define IFUNC_ARGS (uint64_t hwcap __attribute__((unused)), \
+                    __ifunc_arg_t* arg __attribute__((unused)))
+#elif defined(__arm__)
+#define IFUNC_ARGS (unsigned long hwcap __attribute__((unused)))
+#else
+#define IFUNC_ARGS ()
+#endif
+
 #define DEFINE_IFUNC_FOR(name) \
     name##_func name __attribute__((ifunc(#name "_resolver"))); \
     __attribute__((visibility("hidden"))) \
-    name##_func* name##_resolver()
+    name##_func* name##_resolver IFUNC_ARGS
 
 #define DECLARE_FUNC(type, name) \
     __attribute__((visibility("hidden"))) \
diff --git a/libc/upstream-freebsd/android/include/freebsd-compat.h b/libc/upstream-freebsd/android/include/freebsd-compat.h
index 6f7a3f0..3228701 100644
--- a/libc/upstream-freebsd/android/include/freebsd-compat.h
+++ b/libc/upstream-freebsd/android/include/freebsd-compat.h
@@ -47,4 +47,6 @@
 /* FreeBSD has this, but we can't really implement it correctly on Linux. */
 #define issetugid() 0
 
+#define __compiler_membar() __asm __volatile(" " : : : "memory")
+
 #endif
diff --git a/libc/upstream-freebsd/android/include/machine/atomic.h b/libc/upstream-freebsd/android/include/machine/atomic.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libc/upstream-freebsd/android/include/machine/atomic.h
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c b/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c
index ef8cdb1..9e4e79d 100644
--- a/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c
+++ b/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c
@@ -1,4 +1,6 @@
 /*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
  * Copyright (c) 2011 David Chisnall
  * All rights reserved.
  *
@@ -23,9 +25,11 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/lib/libc/stdlib/quick_exit.c 326193 2017-11-25 17:12:48Z pfg $
  */
 
+#include <sys/types.h>
+#include <machine/atomic.h>
 #include <stdlib.h>
 #include <pthread.h>
 
@@ -60,6 +64,7 @@
 	h->cleanup = func;
 	pthread_mutex_lock(&atexit_mutex);
 	h->next = handlers;
+	__compiler_membar();
 	handlers = h;
 	pthread_mutex_unlock(&atexit_mutex);
 	return (0);
@@ -74,7 +79,9 @@
 	 * XXX: The C++ spec requires us to call std::terminate if there is an
 	 * exception here.
 	 */
-	for (h = handlers; NULL != h; h = h->next)
+	for (h = handlers; NULL != h; h = h->next) {
+		__compiler_membar();
 		h->cleanup();
+	}
 	_Exit(status);
 }
diff --git a/libc/upstream-openbsd/lib/libc/string/strlen.c b/libc/upstream-openbsd/lib/libc/string/strlen.c
new file mode 100644
index 0000000..a5721d3
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/string/strlen.c
@@ -0,0 +1,44 @@
+/*	$OpenBSD: strlen.c,v 1.9 2015/08/31 02:53:57 guenther Exp $	*/
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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 <string.h>
+
+size_t
+strlen(const char *str)
+{
+	const char *s;
+
+	for (s = str; *s; ++s)
+		;
+	return (s - str);
+}
+
+DEF_STRONG(strlen);
diff --git a/linker/linker.cpp b/linker/linker.cpp
index f4fccac..c1bccfe 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -93,6 +93,7 @@
 static const char* const kLdConfigArchFilePath = "/system/etc/ld.config." ABI_STRING ".txt";
 
 static const char* const kLdConfigFilePath = "/system/etc/ld.config.txt";
+static const char* const kLdConfigVndkLiteFilePath = "/system/etc/ld.config.vndk_lite.txt";
 
 static const char* const kLdGeneratedConfigFilePath = "/dev/linkerconfig/ld.config.txt";
 
@@ -4052,13 +4053,30 @@
 }
 
 static std::string get_ld_config_file_vndk_path() {
-  if (!file_exists(kLdGeneratedConfigFilePath)) {
-    DL_WARN("Warning: failed to find generated linker configuration from \"%s\"",
-            kLdGeneratedConfigFilePath);
-    return "";
+  if (android::base::GetBoolProperty("ro.vndk.lite", false)) {
+    return kLdConfigVndkLiteFilePath;
   }
 
-  return kLdGeneratedConfigFilePath;
+  // Use generated linker config if flag is set
+  // TODO(b/138920271) Do not check property once it is confirmed as stable
+  // TODO(b/139638519) This file should also cover legacy or vndk-lite config
+  if (android::base::GetProperty("ro.vndk.version", "") != "" &&
+      android::base::GetBoolProperty("sys.linker.use_generated_config", true)) {
+    if (file_exists(kLdGeneratedConfigFilePath)) {
+      return kLdGeneratedConfigFilePath;
+    } else {
+      DL_WARN("Warning: failed to find generated linker configuration from \"%s\"",
+              kLdGeneratedConfigFilePath);
+    }
+  }
+
+  std::string ld_config_file_vndk = kLdConfigFilePath;
+  size_t insert_pos = ld_config_file_vndk.find_last_of('.');
+  if (insert_pos == std::string::npos) {
+    insert_pos = ld_config_file_vndk.length();
+  }
+  ld_config_file_vndk.insert(insert_pos, Config::get_vndk_version_string('.'));
+  return ld_config_file_vndk;
 }
 
 static std::string get_ld_config_file_path(const char* executable_path) {
@@ -4086,7 +4104,7 @@
   }
 
   path = get_ld_config_file_vndk_path();
-  if (!path.empty()) {
+  if (file_exists(path.c_str())) {
     return path;
   }