Merge "Move scopeguard into android::base"
diff --git a/android-changes-for-ndk-developers.md b/android-changes-for-ndk-developers.md
index ebdae83..5279118 100644
--- a/android-changes-for-ndk-developers.md
+++ b/android-changes-for-ndk-developers.md
@@ -145,6 +145,12 @@
 temporarily support these libraries; so if you see a warning that means
 your code will not work in a future release -- please fix it now!
 
+In O and later, the system property `debug.ld.greylist_disabled` can be
+used to deny access to the greylist even to an app that would normally
+be allowed it. This allows you to test compatibility without bumping the
+app's `targetSdkVersion`. Use `setprop debug.ld.greylist_disabled true`
+to turn this on (any other value leaves the greylist enabled).
+
 ```
 $ readelf --dynamic libBroken.so | grep NEEDED
  0x00000001 (NEEDED)                     Shared library: [libnativehelper.so]
diff --git a/libc/Android.bp b/libc/Android.bp
index 1472bc9..8c6f596 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -622,6 +622,13 @@
                     "upstream-openbsd/lib/libc/string/strcat.c",
                 ],
             },
+            kryo: {
+                exclude_srcs: [
+                    "upstream-openbsd/lib/libc/string/memmove.c",
+                    "upstream-openbsd/lib/libc/string/stpcpy.c",
+                    "upstream-openbsd/lib/libc/string/strcat.c",
+                ],
+            },
         },
         arm64: {
             exclude_srcs: [
@@ -1008,7 +1015,32 @@
                     "bionic/__strcpy_chk.cpp",
                 ],
             },
+            kryo: {
+                srcs: [
+                    "arch-arm/krait/bionic/memcpy.S",
+                    "arch-arm/krait/bionic/memset.S",
+                    "arch-arm/krait/bionic/strcmp.S",
+                    "arch-arm/krait/bionic/__strcat_chk.S",
+                    "arch-arm/krait/bionic/__strcpy_chk.S",
 
+                    // Use cortex-a15 versions of strcat/strcpy/strlen.
+                    "arch-arm/cortex-a15/bionic/stpcpy.S",
+                    "arch-arm/cortex-a15/bionic/strcat.S",
+                    "arch-arm/cortex-a15/bionic/strcpy.S",
+                    "arch-arm/cortex-a15/bionic/strlen.S",
+
+                    "arch-arm/denver/bionic/memmove.S",
+                ],
+                exclude_srcs: [
+                    "arch-arm/generic/bionic/memcpy.S",
+                    "arch-arm/generic/bionic/memset.S",
+                    "arch-arm/generic/bionic/strcmp.S",
+                    "arch-arm/generic/bionic/strcpy.S",
+                    "arch-arm/generic/bionic/strlen.c",
+                    "bionic/__strcat_chk.cpp",
+                    "bionic/__strcpy_chk.cpp",
+                ],
+            },
         },
         arm64: {
             srcs: [
@@ -1862,28 +1894,10 @@
     },
 }
 
-// Android.mk:start
-// # crt obj files
-// # ========================================================
-// # crtbrand.c needs <stdint.h> and a #define for the platform SDK version.
-// libc_crt_target_cflags := \
-//    -I$(LOCAL_PATH)/include \
-//    -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) \
-//
-// my_2nd_arch_prefix :=
-// include $(LOCAL_PATH)/arch-$(TARGET_ARCH)/$(TARGET_ARCH).mk
-// include $(LOCAL_PATH)/crt.mk
-// ifdef TARGET_2ND_ARCH
-// my_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
-// include $(LOCAL_PATH)/arch-$(TARGET_2ND_ARCH)/$(TARGET_2ND_ARCH).mk
-// include $(LOCAL_PATH)/crt.mk
-// my_2nd_arch_prefix :=
-// endif
-//
-// include $(call all-makefiles-under,$(LOCAL_PATH))
-// Android.mk:end
+// crt obj files
 cc_object {
     name: "crtbrand",
+    // crtbrand.c needs <stdint.h> and a #define for the platform SDK version.
     local_include_dirs: ["include"],
     product_variables: {
         platform_sdk_version: {
@@ -1898,7 +1912,6 @@
     ],
 }
 
-// Android.mk:ignore
 cc_object {
     name: "crtbegin_so1",
     local_include_dirs: ["include"],
@@ -1910,7 +1923,6 @@
     ],
 }
 
-// Android.mk:ignore
 cc_object {
     name: "crtbegin_so",
 
@@ -1924,7 +1936,6 @@
     ],
 }
 
-// Android.mk:ignore
 cc_object {
     name: "crtend_so",
     local_include_dirs: ["include"],
@@ -1936,7 +1947,6 @@
     ],
 }
 
-// Android.mk:ignore
 cc_object {
     name: "crtbegin_static1",
     local_include_dirs: ["include"],
@@ -1972,7 +1982,6 @@
     defaults: ["crt_defaults"],
 }
 
-// Android.mk:ignore
 cc_object {
     name: "crtbegin_static",
 
@@ -1983,7 +1992,6 @@
     defaults: ["crt_defaults"],
 }
 
-// Android.mk:ignore
 cc_object {
     name: "crtbegin_dynamic1",
     local_include_dirs: ["include"],
@@ -2018,7 +2026,6 @@
     defaults: ["crt_defaults"],
 }
 
-// Android.mk:ignore
 cc_object {
     name: "crtbegin_dynamic",
 
@@ -2029,7 +2036,6 @@
     defaults: ["crt_defaults"],
 }
 
-// Android.mk:ignore
 cc_object {
     // We rename crtend.o to crtend_android.o to avoid a
     // name clash between gcc and bionic.
diff --git a/libc/NOTICE b/libc/NOTICE
index 2ce293f..3668dda 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -112,6 +112,25 @@
 
 -------------------------------------------------------------------
 
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright 2006, 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.
+
+-------------------------------------------------------------------
+
 ====================================================
 Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 
diff --git a/libc/bionic/fortify.cpp b/libc/bionic/fortify.cpp
index cf2d1c2..cfbfbc5 100644
--- a/libc/bionic/fortify.cpp
+++ b/libc/bionic/fortify.cpp
@@ -133,7 +133,7 @@
 
 void* __memchr_chk(const void* s, int c, size_t n, size_t actual_size) {
   __check_buffer_access("memchr", "read from", n, actual_size);
-  return memchr(s, c, n);
+  return const_cast<void*>(memchr(s, c, n));
 }
 
 // Runtime implementation of __builtin____memmove_chk (used directly by compiler, not in headers).
diff --git a/libc/bionic/memmem.cpp b/libc/bionic/memmem.cpp
index 61d681f..019e772 100644
--- a/libc/bionic/memmem.cpp
+++ b/libc/bionic/memmem.cpp
@@ -35,7 +35,7 @@
   if (n < m) return nullptr;
 
   if (m == 0) return const_cast<void*>(void_haystack);
-  if (m == 1) return memchr(haystack, needle[0], n);
+  if (m == 1) return const_cast<void*>(memchr(haystack, needle[0], n));
 
   // This uses the "Not So Naive" algorithm, a very simple but usually effective algorithm.
   // http://www-igm.univ-mlv.fr/~lecroq/string/
diff --git a/libc/bionic/ndk_cruft.cpp b/libc/bionic/ndk_cruft.cpp
index c042f9f..29565a2 100644
--- a/libc/bionic/ndk_cruft.cpp
+++ b/libc/bionic/ndk_cruft.cpp
@@ -322,7 +322,7 @@
 
 // This was removed from POSIX 2008.
 char* index(const char* str, int ch) {
-  return strchr(str, ch);
+  return const_cast<char*>(strchr(str, ch));
 }
 
 // This was removed from BSD.
diff --git a/libc/include/string.h b/libc/include/string.h
index 26bd93f..6520996 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -168,48 +168,47 @@
 // trickery...
 #if __ANDROID_API__ >= __ANDROID_API_J_MR1__
 __BIONIC_FORTIFY_INLINE
-void* memcpy(void* _Nonnull __restrict const dst __pass_object_size0,
-        const void* _Nonnull __restrict src, size_t copy_amount) __overloadable {
+void* memcpy(void* _Nonnull __restrict const dst __pass_object_size0, const void* _Nonnull __restrict src, size_t copy_amount)
+        __overloadable {
     return __builtin___memcpy_chk(dst, src, copy_amount, __bos0(dst));
 }
 
 __BIONIC_FORTIFY_INLINE
-void* memmove(void* const _Nonnull dst __pass_object_size0,
-        const void* _Nonnull src, size_t len) __overloadable {
+void* memmove(void* const _Nonnull dst __pass_object_size0, const void* _Nonnull src, size_t len)
+        __overloadable {
     return __builtin___memmove_chk(dst, src, len, __bos0(dst));
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
 
 #if __ANDROID_API__ >= __ANDROID_API_L__
 __BIONIC_FORTIFY_INLINE
-char* stpcpy(char* _Nonnull __restrict const dst __pass_object_size,
-        const char* _Nonnull __restrict src) __overloadable {
+char* stpcpy(char* _Nonnull __restrict const dst __pass_object_size, const char* _Nonnull __restrict src)
+        __overloadable {
     return __builtin___stpcpy_chk(dst, src, __bos(dst));
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_L__ */
 
 #if __ANDROID_API__ >= __ANDROID_API_J_MR1__
 __BIONIC_FORTIFY_INLINE
-char* strcpy(char* _Nonnull __restrict const dst __pass_object_size,
-        const char* _Nonnull __restrict src) __overloadable {
+char* strcpy(char* _Nonnull __restrict const dst __pass_object_size, const char* _Nonnull __restrict src)
+        __overloadable {
     return __builtin___strcpy_chk(dst, src, __bos(dst));
 }
 
 __BIONIC_FORTIFY_INLINE
-char* strcat(char* _Nonnull __restrict const dst __pass_object_size,
-        const char* _Nonnull __restrict src) __overloadable {
+char* strcat(char* _Nonnull __restrict const dst __pass_object_size, const char* _Nonnull __restrict src)
+        __overloadable {
     return __builtin___strcat_chk(dst, src, __bos(dst));
 }
 
 __BIONIC_FORTIFY_INLINE
-char* strncat(char* const _Nonnull __restrict dst __pass_object_size,
-        const char* _Nonnull __restrict src, size_t n) __overloadable {
+char* strncat(char* const _Nonnull __restrict dst __pass_object_size, const char* _Nonnull __restrict src, size_t n)
+        __overloadable {
     return __builtin___strncat_chk(dst, src, n, __bos(dst));
 }
 
 __BIONIC_FORTIFY_INLINE
-void* memset(void* const _Nonnull s __pass_object_size0, int c, size_t n)
-        __overloadable {
+void* memset(void* const _Nonnull s __pass_object_size0, int c, size_t n) __overloadable {
     return __builtin___memset_chk(s, c, n, __bos0(s));
 }
 #endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
@@ -274,9 +273,8 @@
 
 #if __ANDROID_API__ >= __ANDROID_API_L__
 __BIONIC_FORTIFY_INLINE
-char* stpncpy(char* __restrict const _Nonnull dst __pass_object_size,
-        const char* __restrict const _Nonnull src __pass_object_size,
-        size_t n) __overloadable {
+char* stpncpy(char* __restrict const _Nonnull dst __pass_object_size, const char* __restrict const _Nonnull src __pass_object_size, size_t n)
+        __overloadable {
     size_t bos_dst = __bos(dst);
     size_t bos_src = __bos(src);
 
@@ -289,9 +287,8 @@
 }
 
 __BIONIC_FORTIFY_INLINE
-char* strncpy(char* __restrict const _Nonnull dst __pass_object_size,
-        const char* __restrict const _Nonnull src __pass_object_size,
-        size_t n) __overloadable {
+char* strncpy(char* __restrict const _Nonnull dst __pass_object_size, const char* __restrict const _Nonnull src __pass_object_size, size_t n)
+        __overloadable {
     size_t bos_dst = __bos(dst);
     size_t bos_src = __bos(src);
 
@@ -306,8 +303,8 @@
 
 #if __ANDROID_API__ >= __ANDROID_API_J_MR1__
 __BIONIC_FORTIFY_INLINE
-size_t strlcpy(char* const _Nonnull __restrict dst __pass_object_size,
-        const char *_Nonnull __restrict src, size_t size) __overloadable {
+size_t strlcpy(char* const _Nonnull __restrict dst __pass_object_size, const char *_Nonnull __restrict src, size_t size)
+        __overloadable {
     size_t bos = __bos(dst);
 
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
@@ -318,8 +315,8 @@
 }
 
 __BIONIC_FORTIFY_INLINE
-size_t strlcat(char* const _Nonnull __restrict dst __pass_object_size,
-        const char* _Nonnull __restrict src, size_t size) __overloadable {
+size_t strlcat(char* const _Nonnull __restrict dst __pass_object_size, const char* _Nonnull __restrict src, size_t size)
+        __overloadable {
     size_t bos = __bos(dst);
 
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
@@ -358,15 +355,14 @@
 
 #if  __ANDROID_API__ >= __ANDROID_API_J_MR2__
 __BIONIC_FORTIFY_INLINE
-char* strchr(const char* const _Nonnull s __pass_object_size0, int c)
+char* strchr(const char* const _Nonnull s __pass_object_size, int c)
         __overloadable {
-    size_t bos = __bos0(s);
+    size_t bos = __bos(s);
 
     if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
         return __builtin_strchr(s, c);
     }
 
-    // return __builtin_strchr(s, c);
     return __strchr_chk(s, c, bos);
 }
 
@@ -390,14 +386,12 @@
  * but we should also provide a FORTIFY'ed escape hatch.
  */
 __BIONIC_ERROR_FUNCTION_VISIBILITY
-void* memset(void* _Nonnull s, int c, size_t n,
-             struct __bionic_zero_size_is_okay_t ok)
+void* memset(void* _Nonnull s, int c, size_t n, struct __bionic_zero_size_is_okay_t ok)
         __overloadable
         __error_if_overflows_dst(memset, s, n, "size");
 
 __BIONIC_FORTIFY_INLINE
-void* memset(void* const _Nonnull s __pass_object_size0, int c, size_t n,
-             struct __bionic_zero_size_is_okay_t ok __attribute__((unused)))
+void* memset(void* const _Nonnull s __pass_object_size0, int c, size_t n, struct __bionic_zero_size_is_okay_t ok __attribute__((unused)))
         __overloadable {
     return __builtin___memset_chk(s, c, n, __bos0(s));
 }
@@ -514,8 +508,7 @@
 
 #if __ANDROID_API__ >= __ANDROID_API_J_MR1__
 __BIONIC_FORTIFY_INLINE
-size_t strlcpy(char* _Nonnull __restrict dst __pass_object_size,
-        const char* _Nonnull __restrict src, size_t size) {
+size_t strlcpy(char* _Nonnull __restrict dst __pass_object_size, const char* _Nonnull __restrict src, size_t size) {
     size_t bos = __bos(dst);
 
     // Compiler doesn't know destination size. Don't call __strlcpy_chk
@@ -606,6 +599,92 @@
 #endif /* defined(__clang__) */
 #endif /* defined(__BIONIC_FORTIFY) */
 
+/* Const-correct overloads. Placed after FORTIFY so we call those functions, if possible. */
+#if defined(__cplusplus) && defined(__clang__)
+/*
+ * Use two enable_ifs so these overloads don't conflict with + are preferred over libcxx's. This can
+ * be reduced to 1 after libcxx recognizes that we have const-correct overloads.
+ */
+#define __prefer_this_overload __enable_if(true, "preferred overload") __enable_if(true, "")
+extern "C++" {
+inline __always_inline
+void* __bionic_memchr(const void* const _Nonnull s __pass_object_size, int c, size_t n) {
+    return memchr(s, c, n);
+}
+
+inline __always_inline
+const void* memchr(const void* const _Nonnull s __pass_object_size, int c, size_t n)
+        __prefer_this_overload {
+    return __bionic_memchr(s, c, n);
+}
+
+inline __always_inline
+void* memchr(void* const _Nonnull s __pass_object_size, int c, size_t n) __prefer_this_overload {
+    return __bionic_memchr(s, c, n);
+}
+
+inline __always_inline
+char* __bionic_strchr(const char* const _Nonnull s __pass_object_size, int c) {
+    return strchr(s, c);
+}
+
+inline __always_inline
+const char* strchr(const char* const _Nonnull s __pass_object_size, int c)
+        __prefer_this_overload {
+    return __bionic_strchr(s, c);
+}
+
+inline __always_inline
+char* strchr(char* const _Nonnull s __pass_object_size, int c)
+        __prefer_this_overload {
+    return __bionic_strchr(s, c);
+}
+
+inline __always_inline
+char* __bionic_strrchr(const char* const _Nonnull s __pass_object_size, int c) {
+    return strrchr(s, c);
+}
+
+inline __always_inline
+const char* strrchr(const char* const _Nonnull s __pass_object_size, int c) __prefer_this_overload {
+    return __bionic_strrchr(s, c);
+}
+
+inline __always_inline
+char* strrchr(char* const _Nonnull s __pass_object_size, int c) __prefer_this_overload {
+    return __bionic_strrchr(s, c);
+}
+
+/* Functions with no FORTIFY counterpart. */
+inline __always_inline
+char* __bionic_strstr(const char* _Nonnull h, const char* _Nonnull n) { return strstr(h, n); }
+
+inline __always_inline
+const char* strstr(const char* _Nonnull h, const char* _Nonnull n) __prefer_this_overload {
+    return __bionic_strstr(h, n);
+}
+
+inline __always_inline
+char* strstr(char* _Nonnull h, const char* _Nonnull n) __prefer_this_overload {
+    return __bionic_strstr(h, n);
+}
+
+inline __always_inline
+char* __bionic_strpbrk(const char* _Nonnull h, const char* _Nonnull n) { return strpbrk(h, n); }
+
+inline __always_inline
+char* strpbrk(char* _Nonnull h, const char* _Nonnull n) __prefer_this_overload {
+    return __bionic_strpbrk(h, n);
+}
+
+inline __always_inline
+const char* strpbrk(const char* _Nonnull h, const char* _Nonnull n) __prefer_this_overload {
+    return __bionic_strpbrk(h, n);
+}
+}
+#undef __prefer_this_overload
+#endif
+
 #if defined(__clang__)
 #pragma clang diagnostic pop
 #endif
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index dab252d..aa93c78 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -297,9 +297,12 @@
 /* __BIONIC_FORTIFY_NONSTATIC_INLINE is pointless in GCC's FORTIFY */
 #    define __BIONIC_FORTIFY_INLINE extern __inline__ __always_inline __attribute__((gnu_inline)) __attribute__((__artificial__))
 #  endif
-#  define __pass_object_size __pass_object_size_n(__bos_level)
-#  define __pass_object_size0 __pass_object_size_n(0)
+#else
+/* Further increase sharing for some inline functions */
+#  define __pass_object_size_n(n)
 #endif
+#define __pass_object_size __pass_object_size_n(__bos_level)
+#define __pass_object_size0 __pass_object_size_n(0)
 
 /* Used to support clangisms with FORTIFY. This isn't in the FORTIFY section
  * because these change how symbols are emitted. The linker must be kept happy.
diff --git a/libc/private/CachedProperty.h b/libc/private/CachedProperty.h
new file mode 100644
index 0000000..0a41abf
--- /dev/null
+++ b/libc/private/CachedProperty.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <string.h>
+
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
+#include "private/bionic_lock.h"
+
+class CachedProperty {
+ public:
+  CachedProperty(const char* property_name)
+    : property_name_(property_name),
+      prop_info_(nullptr),
+      cached_area_serial_(0),
+      cached_property_serial_(0) {
+    cached_value_[0] = '\0';
+  }
+
+  const char* Get() {
+    lock_.lock();
+
+    // Do we have a `struct prop_info` yet?
+    if (prop_info_ == nullptr) {
+      // `__system_property_find` is expensive, so only retry if a property
+      // has been created since last time we checked.
+      uint32_t property_area_serial = __system_property_area_serial();
+      if (property_area_serial != cached_area_serial_) {
+        prop_info_ = __system_property_find(property_name_);
+        cached_area_serial_ = property_area_serial;
+      }
+    }
+
+    if (prop_info_ != nullptr) {
+      // Only bother re-reading the property if it's actually changed since last time.
+      uint32_t property_serial = __system_property_serial(prop_info_);
+      if (property_serial != cached_property_serial_) {
+        __system_property_read_callback(prop_info_, &CachedProperty::Callback, this);
+      }
+    }
+
+    lock_.unlock();
+    return cached_value_;
+  }
+
+ private:
+  Lock lock_;
+  const char* property_name_;
+  const prop_info* prop_info_;
+  uint32_t cached_area_serial_;
+  uint32_t cached_property_serial_;
+  char cached_value_[PROP_VALUE_MAX];
+
+  static void Callback(void* data, const char*, const char* value, uint32_t serial) {
+    CachedProperty* instance = reinterpret_cast<CachedProperty*>(data);
+    instance->cached_property_serial_ = serial;
+    strcpy(instance->cached_value_, value);
+  }
+};
diff --git a/libc/zoneinfo/Android.mk b/libc/zoneinfo/Android.mk
index fe5099d..faa1f06 100644
--- a/libc/zoneinfo/Android.mk
+++ b/libc/zoneinfo/Android.mk
@@ -9,6 +9,15 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT)/usr/share/zoneinfo
 include $(BUILD_PREBUILT)
 
+include $(CLEAR_VARS)
+LOCAL_MODULE := tzlookup.xml
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT)/usr/share/zoneinfo
+include $(BUILD_PREBUILT)
+
 # The host build doesn't use bionic, but it does use bionic's zoneinfo data
 ifeq ($(WITH_HOST_DALVIK),true)
 
@@ -23,4 +32,15 @@
 LOCAL_MODULE_PATH := $(HOST_OUT)/usr/share/zoneinfo
 include $(BUILD_PREBUILT)
 
+include $(CLEAR_VARS)
+LOCAL_MODULE := tzlookup.xml-host
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_IS_HOST_MODULE := true
+LOCAL_SRC_FILES := tzlookup.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_STEM := $(LOCAL_SRC_FILES)
+LOCAL_MODULE_PATH := $(HOST_OUT)/usr/share/zoneinfo
+include $(BUILD_PREBUILT)
+
 endif
diff --git a/libc/zoneinfo/tzlookup.xml b/libc/zoneinfo/tzlookup.xml
new file mode 100644
index 0000000..5846f50
--- /dev/null
+++ b/libc/zoneinfo/tzlookup.xml
@@ -0,0 +1,1622 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2006, 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.
+*/
+-->
+<timezones>
+  <!-- Time zones by country.
+
+       Data in this file originates from IANA's zone.tab file.
+       The ordering of zones within each country is Android-specific and
+       affects Android behavior, see below for details.
+
+       The ordering of country elements is not important but is kept in ASCII
+       order by code for easier maintenance. There must only be one country
+       element per unique code. The code attribute is the (lower cased)
+       ISO 3166 2-character country code used in the IANA zones.tab file.
+
+       The <id> entries contain the IANA IDs for time zones used in a
+       country.
+
+       The file is used when picking a time zone for an Android device given
+       a known local time, offset from UTC and whether the local zone is
+       currently observing DST.
+
+       The ordering of <id> elements is important because it influence the
+       order that time zones in a country are considered.
+
+       Currently the <id> entries are mostly primarily ordered by raw (non-DST)
+       offset and then "desirability". This ordering is an historical artifact
+       that is likely to change in future.
+
+       The most sensible ordering for <id> entries for a country is by
+       population of users that observe the time zone to maximize the
+       probability of matching an arbitrary user. Then:
+
+       The first <id> entry for a given country should have the highest
+       likelihood of matching the user's needs when only the user's country
+       code is available.
+
+       The first zone that matches a user's country, offset and DST state
+       should have the highest likelihood of matching the user's needs when
+       country code, offset and DST state are available.
+    -->
+  <countryzones>
+
+    <!-- ANDORRA, 1:00 -->
+    <country code="ad">
+      <id>Europe/Andorra</id>
+    </country>
+
+    <!-- UNITED ARAB EMIRATES, 4:00 -->
+    <country code="ae">
+      <id>Asia/Dubai</id>
+    </country>
+
+    <!-- AFGHANISTAN, 4:30 -->
+    <country code="af">
+      <id>Asia/Kabul</id>
+    </country>
+
+    <!-- ANTIGUA AND BARBUDA, -4:00 -->
+    <country code="ag">
+      <id>America/Antigua</id>
+    </country>
+
+    <!-- ANGUILLA, -4:00 -->
+    <country code="ai">
+      <id>America/Anguilla</id>
+    </country>
+
+    <!-- ALBANIA, 1:00 -->
+    <country code="al">
+      <id>Europe/Tirane</id>
+    </country>
+
+    <!-- ARMENIA, 4:00 -->
+    <country code="am">
+      <id>Asia/Yerevan</id>
+    </country>
+
+    <!-- ANGOLA, 1:00 -->
+    <country code="ao">
+      <id>Africa/Luanda</id>
+    </country>
+
+    <!-- ANTARCTICA -->
+    <country code="aq">
+      <!-- 12:00 -->
+      <id>Antarctica/McMurdo</id>
+
+      <!-- 10:00 -->
+      <id>Antarctica/DumontDUrville</id>
+
+      <!-- 8:00 -->
+      <id>Antarctica/Casey</id>
+
+      <!-- 7:00 -->
+      <id>Antarctica/Davis</id>
+
+      <!-- 5:00 -->
+      <id>Antarctica/Mawson</id>
+
+      <!-- 6:00 -->
+      <id>Antarctica/Vostok</id>
+
+      <!-- 3:00 -->
+      <id>Antarctica/Syowa</id>
+
+      <!-- 0:00 -->
+      <id>Antarctica/Troll</id>
+
+      <!-- -3:00 -->
+      <id>Antarctica/Rothera</id>
+
+      <!-- -4:00 -->
+      <id>Antarctica/Palmer</id>
+    </country>
+
+    <!-- ARGENTINA, -3:00 -->
+    <country code="ar">
+      <id>America/Argentina/Buenos_Aires</id>
+      <id>America/Argentina/Cordoba</id>
+      <id>America/Argentina/Salta</id>
+      <id>America/Argentina/Jujuy</id>
+      <id>America/Argentina/Tucuman</id>
+      <id>America/Argentina/Catamarca</id>
+      <id>America/Argentina/La_Rioja</id>
+      <id>America/Argentina/San_Juan</id>
+      <id>America/Argentina/Mendoza</id>
+      <id>America/Argentina/San_Luis</id>
+      <id>America/Argentina/Rio_Gallegos</id>
+      <id>America/Argentina/Ushuaia</id>
+    </country>
+
+    <!-- AMERICAN SAMOA, -11:00 -->
+    <country code="as">
+      <id>Pacific/Pago_Pago</id>
+    </country>
+
+    <!-- AUSTRIA, 1:00 -->
+    <country code="at">
+      <id>Europe/Vienna</id>
+    </country>
+
+    <!-- AUSTRALIA -->
+    <country code="au">
+      <!-- 10:00 -->
+      <id>Australia/Sydney</id>
+      <id>Australia/Melbourne</id>
+      <id>Australia/Brisbane</id>
+      <id>Australia/Hobart</id>
+      <id>Australia/Currie</id>
+      <id>Australia/Lindeman</id>
+
+      <!-- 11:00 -->
+      <id>Antarctica/Macquarie</id>
+
+      <!-- 10:30 -->
+      <id>Australia/Lord_Howe</id>
+
+      <!-- 9:30 -->
+      <id>Australia/Adelaide</id>
+      <id>Australia/Broken_Hill</id>
+      <id>Australia/Darwin</id>
+
+      <!-- 8:00 -->
+      <id>Australia/Perth</id>
+
+      <!-- 8:45 -->
+      <id>Australia/Eucla</id>
+    </country>
+
+    <!-- ARUBA, -4:00 -->
+    <country code="aw">
+      <id>America/Aruba</id>
+    </country>
+
+    <!-- ALAND ISLANDS, 2:00 -->
+    <country code="ax">
+      <id>Europe/Mariehamn</id>
+    </country>
+
+    <!-- AZERBAIJAN, 4:00 -->
+    <country code="az">
+      <id>Asia/Baku</id>
+    </country>
+
+    <!-- BOSNIA AND HERZEGOVINA, 1:00 -->
+    <country code="ba">
+      <id>Europe/Sarajevo</id>
+    </country>
+
+    <!-- BARBADOS, -4:00 -->
+    <country code="bb">
+      <id>America/Barbados</id>
+    </country>
+
+    <!-- BANGLADESH, 6:00 -->
+    <country code="bd">
+      <id>Asia/Dhaka</id>
+    </country>
+
+    <!-- BELGIUM, 1:00 -->
+    <country code="be">
+      <id>Europe/Brussels</id>
+    </country>
+
+    <!-- BURKINA FASO, 0:00 -->
+    <country code="bf">
+      <id>Africa/Ouagadougou</id>
+    </country>
+
+    <!-- BULGARIA, 2:00 -->
+    <country code="bg">
+      <id>Europe/Sofia</id>
+    </country>
+
+    <!-- BAHRAIN, 3:00 -->
+    <country code="bh">
+      <id>Asia/Bahrain</id>
+    </country>
+
+    <!-- BURUNDI, 2:00 -->
+    <country code="bi">
+      <id>Africa/Bujumbura</id>
+    </country>
+
+    <!-- BENIN, 1:00 -->
+    <country code="bj">
+      <id>Africa/Porto-Novo</id>
+    </country>
+
+    <!-- Saint Barthélemy, -4:00 -->
+    <country code="bl">
+      <id>America/St_Barthelemy</id>
+    </country>
+
+    <!-- BERMUDA, -4:00 -->
+    <country code="bm">
+      <id>Atlantic/Bermuda</id>
+    </country>
+
+    <!-- BRUNEI DARUSSALAM, 8:00 -->
+    <country code="bn">
+      <id>Asia/Brunei</id>
+    </country>
+
+    <!-- BOLIVIA, -4:00 -->
+    <country code="bo">
+      <id>America/La_Paz</id>
+    </country>
+
+    <!-- Caribbean Netherlands, -4:00 -->
+    <country code="bq">
+      <id>America/Kralendijk</id>
+    </country>
+
+    <!-- BRAZIL -->
+    <country code="br">
+      <!-- -2:00 -->
+      <id>America/Noronha</id>
+
+      <!-- -3:00 -->
+      <id>America/Sao_Paulo</id>
+      <id>America/Belem</id>
+      <id>America/Fortaleza</id>
+      <id>America/Recife</id>
+      <id>America/Araguaina</id>
+      <id>America/Maceio</id>
+      <id>America/Bahia</id>
+      <id>America/Santarem</id>
+
+      <!-- -4:00 -->
+      <id>America/Manaus</id>
+      <id>America/Campo_Grande</id>
+      <id>America/Cuiaba</id>
+      <id>America/Porto_Velho</id>
+      <id>America/Boa_Vista</id>
+
+      <!-- -5:00 -->
+      <id>America/Eirunepe</id>
+      <id>America/Rio_Branco</id>
+    </country>
+
+    <!-- BAHAMAS, -5:00 -->
+    <country code="bs">
+      <id>America/Nassau</id>
+    </country>
+
+    <!-- BHUTAN, 6:00 -->
+    <country code="bt">
+      <id>Asia/Thimphu</id>
+    </country>
+
+    <!-- BOTSWANA, 2:00 -->
+    <country code="bw">
+      <id>Africa/Gaborone</id>
+    </country>
+
+    <!-- BELARUS, 3:00 -->
+    <country code="by">
+      <id>Europe/Minsk</id>
+    </country>
+
+    <!-- BELIZE, -6:00 -->
+    <country code="bz">
+      <id>America/Belize</id>
+    </country>
+
+    <!-- CANADA -->
+    <country code="ca">
+      <!-- -3:30 -->
+      <id>America/St_Johns</id>
+
+      <!-- -4:00 -->
+      <id>America/Halifax</id>
+      <id>America/Glace_Bay</id>
+      <id>America/Moncton</id>
+      <id>America/Goose_Bay</id>
+      <id>America/Blanc-Sablon</id>
+
+      <!-- -5:00 -->
+      <id>America/Toronto</id>
+      <id>America/Nipigon</id>
+      <id>America/Thunder_Bay</id>
+      <id>America/Iqaluit</id>
+      <id>America/Pangnirtung</id>
+      <id>America/Atikokan</id>
+
+      <!-- -6:00 -->
+      <id>America/Winnipeg</id>
+      <id>America/Regina</id>
+      <id>America/Rankin_Inlet</id>
+      <id>America/Rainy_River</id>
+      <id>America/Swift_Current</id>
+      <id>America/Resolute</id>
+
+      <!-- -7:00 -->
+      <id>America/Edmonton</id>
+      <id>America/Cambridge_Bay</id>
+      <id>America/Yellowknife</id>
+      <id>America/Inuvik</id>
+      <id>America/Dawson_Creek</id>
+      <id>America/Creston</id>
+      <id>America/Fort_Nelson</id>
+
+      <!-- -8:00 -->
+      <id>America/Vancouver</id>
+      <id>America/Whitehorse</id>
+      <id>America/Dawson</id>
+    </country>
+
+    <!-- COCOS (KEELING) ISLANDS, 6:30 -->
+    <country code="cc">
+      <id>Indian/Cocos</id>
+    </country>
+
+    <!-- CONGO, THE DEMOCRATIC REPUBLIC OF THE -->
+    <country code="cd">
+      <!-- 2:00 -->
+      <id>Africa/Lubumbashi</id>
+
+      <!-- 1:00 -->
+      <id>Africa/Kinshasa</id>
+    </country>
+
+    <!-- CENTRAL AFRICAN REPUBLIC, 1:00 -->
+    <country code="cf">
+      <id>Africa/Bangui</id>
+    </country>
+
+    <!-- CONGO, 1:00 -->
+    <country code="cg">
+      <id>Africa/Brazzaville</id>
+    </country>
+
+    <!-- SWITZERLAND, 1:00 -->
+    <country code="ch">
+      <id>Europe/Zurich</id>
+    </country>
+
+    <!-- COTE D'IVOIRE, 0:00 -->
+    <country code="ci">
+      <id>Africa/Abidjan</id>
+    </country>
+
+    <!-- COOK ISLANDS, -10:00 -->
+    <country code="ck">
+      <id>Pacific/Rarotonga</id>
+    </country>
+
+    <!-- CHILE -->
+    <country code="cl">
+      <!-- -3:00 -->
+      <id>America/Punta_Arenas</id>
+
+      <!-- -4:00 -->
+      <id>America/Santiago</id>
+
+      <!-- -6:00 -->
+      <id>Pacific/Easter</id>
+    </country>
+
+    <!-- CAMEROON, 1:00 -->
+    <country code="cm">
+      <id>Africa/Douala</id>
+    </country>
+
+    <!-- CHINA -->
+    <country code="cn">
+      <!-- 8:00 -->
+      <id>Asia/Shanghai</id>
+
+      <!-- 6:00 -->
+      <id>Asia/Urumqi</id>
+    </country>
+
+    <!-- COLOMBIA, -5:00 -->
+    <country code="co">
+      <id>America/Bogota</id>
+    </country>
+
+    <!-- COSTA RICA, -6:00 -->
+    <country code="cr">
+      <id>America/Costa_Rica</id>
+    </country>
+
+    <!-- CUBA, -5:00 -->
+    <country code="cu">
+      <id>America/Havana</id>
+    </country>
+
+    <!-- CAPE VERDE, -1:00 -->
+    <country code="cv">
+      <id>Atlantic/Cape_Verde</id>
+    </country>
+
+    <!-- Curaçao, -4:00 -->
+    <country code="cw">
+      <id>America/Curacao</id>
+    </country>
+
+    <!-- CHRISTMAS ISLAND, 7:00 -->
+    <country code="cx">
+      <id>Indian/Christmas</id>
+    </country>
+
+    <!-- CYPRUS -->
+    <country code="cy">
+      <!-- 2:00 -->
+      <id>Asia/Nicosia</id>
+
+      <!-- 3:00 -->
+      <id>Asia/Famagusta</id>
+    </country>
+
+    <!-- CZECH REPUBLIC, 1:00 -->
+    <country code="cz">
+      <id>Europe/Prague</id>
+    </country>
+
+    <!-- GERMANY, 1:00 -->
+    <country code="de">
+      <id>Europe/Berlin</id>
+      <id>Europe/Busingen</id>
+    </country>
+
+    <!-- DJIBOUTI, 3:00 -->
+    <country code="dj">
+      <id>Africa/Djibouti</id>
+    </country>
+
+    <!-- DENMARK, 1:00 -->
+    <country code="dk">
+      <id>Europe/Copenhagen</id>
+    </country>
+
+    <!-- DOMINICA, -4:00 -->
+    <country code="dm">
+      <id>America/Dominica</id>
+    </country>
+
+    <!-- DOMINICAN REPUBLIC, -4:00 -->
+    <country code="do">
+      <id>America/Santo_Domingo</id>
+    </country>
+
+    <!-- ALGERIA, 1:00 -->
+    <country code="dz">
+      <id>Africa/Algiers</id>
+    </country>
+
+    <!-- ECUADOR -->
+    <country code="ec">
+      <!-- -5:00 -->
+      <id>America/Guayaquil</id>
+
+      <!-- -6:00 -->
+      <id>Pacific/Galapagos</id>
+    </country>
+
+    <!-- ESTONIA, 2:00 -->
+    <country code="ee">
+      <id>Europe/Tallinn</id>
+    </country>
+
+    <!-- EGYPT, 2:00 -->
+    <country code="eg">
+      <id>Africa/Cairo</id>
+    </country>
+
+    <!-- WESTERN SAHARA, 0:00 -->
+    <country code="eh">
+      <id>Africa/El_Aaiun</id>
+    </country>
+
+    <!-- ERITREA, 3:00 -->
+    <country code="er">
+      <id>Africa/Asmara</id>
+    </country>
+
+    <!-- SPAIN -->
+    <country code="es">
+      <!-- 1:00 -->
+      <id>Europe/Madrid</id>
+      <id>Africa/Ceuta</id>
+
+      <!-- 0:00 -->
+      <id>Atlantic/Canary</id>
+    </country>
+
+    <!-- ETHIOPIA, 3:00 -->
+    <country code="et">
+      <id>Africa/Addis_Ababa</id>
+    </country>
+
+    <!-- FINLAND, 2:00 -->
+    <country code="fi">
+      <id>Europe/Helsinki</id>
+    </country>
+
+    <!-- FIJI, 12:00 -->
+    <country code="fj">
+      <id>Pacific/Fiji</id>
+    </country>
+
+    <!-- FALKLAND ISLANDS (MALVINAS), -3:00 -->
+    <country code="fk">
+      <id>Atlantic/Stanley</id>
+    </country>
+
+    <!-- MICRONESIA, FEDERATED STATES OF -->
+    <country code="fm">
+      <!-- 11:00 -->
+      <id>Pacific/Pohnpei</id>
+      <id>Pacific/Kosrae</id>
+
+      <!-- 10:00 -->
+      <id>Pacific/Chuuk</id>
+    </country>
+
+    <!-- FAROE ISLANDS, 0:00 -->
+    <country code="fo">
+      <id>Atlantic/Faroe</id>
+    </country>
+
+    <!-- FRANCE, 1:00 -->
+    <country code="fr">
+      <id>Europe/Paris</id>
+    </country>
+
+    <!-- GABON, 1:00 -->
+    <country code="ga">
+      <id>Africa/Libreville</id>
+    </country>
+
+    <!-- UNITED KINGDOM, 0:00 -->
+    <country code="gb">
+      <id>Europe/London</id>
+    </country>
+
+    <!-- GRENADA, -4:00 -->
+    <country code="gd">
+      <id>America/Grenada</id>
+    </country>
+
+    <!-- GEORGIA, 4:00 -->
+    <country code="ge">
+      <id>Asia/Tbilisi</id>
+    </country>
+
+    <!-- FRENCH GUIANA, -3:00 -->
+    <country code="gf">
+      <id>America/Cayenne</id>
+    </country>
+
+    <!-- GUERNSEY, 0:00 -->
+    <country code="gg">
+      <id>Europe/Guernsey</id>
+    </country>
+
+    <!-- GHANA, 0:00 -->
+    <country code="gh">
+      <id>Africa/Accra</id>
+    </country>
+
+    <!-- GIBRALTAR, 1:00 -->
+    <country code="gi">
+      <id>Europe/Gibraltar</id>
+    </country>
+
+    <!-- GREENLAND -->
+    <country code="gl">
+      <!-- 0:00 -->
+      <id>America/Danmarkshavn</id>
+
+      <!-- -1:00 -->
+      <id>America/Scoresbysund</id>
+
+      <!-- -3:00 -->
+      <id>America/Godthab</id>
+
+      <!-- -4:00 -->
+      <id>America/Thule</id>
+    </country>
+
+    <!-- GAMBIA, 0:00 -->
+    <country code="gm">
+      <id>Africa/Banjul</id>
+    </country>
+
+    <!-- GUINEA, 0:00 -->
+    <country code="gn">
+      <id>Africa/Conakry</id>
+    </country>
+
+    <!-- GUADELOUPE, -4:00 -->
+    <country code="gp">
+      <id>America/Guadeloupe</id>
+    </country>
+
+    <!-- EQUATORIAL GUINEA, 1:00 -->
+    <country code="gq">
+      <id>Africa/Malabo</id>
+    </country>
+
+    <!-- GREECE, 2:00 -->
+    <country code="gr">
+      <id>Europe/Athens</id>
+    </country>
+
+    <!-- SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS, -2:00 -->
+    <country code="gs">
+      <id>Atlantic/South_Georgia</id>
+    </country>
+
+    <!-- GUATEMALA, -6:00 -->
+    <country code="gt">
+      <id>America/Guatemala</id>
+    </country>
+
+    <!-- GUAM, 10:00 -->
+    <country code="gu">
+      <id>Pacific/Guam</id>
+    </country>
+
+    <!-- GUINEA-BISSAU, 0:00 -->
+    <country code="gw">
+      <id>Africa/Bissau</id>
+    </country>
+
+    <!-- GUYANA, -4:00 -->
+    <country code="gy">
+      <id>America/Guyana</id>
+    </country>
+
+    <!-- HONG KONG, 8:00 -->
+    <country code="hk">
+      <id>Asia/Hong_Kong</id>
+    </country>
+
+    <!-- HONDURAS, -6:00 -->
+    <country code="hn">
+      <id>America/Tegucigalpa</id>
+    </country>
+
+    <!-- CROATIA, 1:00 -->
+    <country code="hr">
+      <id>Europe/Zagreb</id>
+    </country>
+
+    <!-- HAITI, -5:00 -->
+    <country code="ht">
+      <id>America/Port-au-Prince</id>
+    </country>
+
+    <!-- HUNGARY, 1:00 -->
+    <country code="hu">
+      <id>Europe/Budapest</id>
+    </country>
+
+    <!-- INDONESIA -->
+    <country code="id">
+      <!-- 9:00 -->
+      <id>Asia/Jayapura</id>
+
+      <!-- 8:00 -->
+      <id>Asia/Makassar</id>
+
+      <!-- 7:00 -->
+      <id>Asia/Jakarta</id>
+      <id>Asia/Pontianak</id>
+    </country>
+
+    <!-- IRELAND, 0:00 -->
+    <country code="ie">
+      <id>Europe/Dublin</id>
+    </country>
+
+    <!-- ISRAEL, 2:00 -->
+    <country code="il">
+      <id>Asia/Jerusalem</id>
+    </country>
+
+    <!-- ISLE OF MAN, 0:00 -->
+    <country code="im">
+      <id>Europe/Isle_of_Man</id>
+    </country>
+
+    <!-- INDIA, 5:30 -->
+    <country code="in">
+      <id>Asia/Kolkata</id>
+    </country>
+
+    <!-- BRITISH INDIAN OCEAN TERRITORY, 6:00 -->
+    <country code="io">
+      <id>Indian/Chagos</id>
+    </country>
+
+    <!-- IRAQ, 3:00 -->
+    <country code="iq">
+      <id>Asia/Baghdad</id>
+    </country>
+
+    <!-- IRAN, ISLAMIC REPUBLIC OF, 3:30 -->
+    <country code="ir">
+      <id>Asia/Tehran</id>
+    </country>
+
+    <!-- ICELAND, 0:00 -->
+    <country code="is">
+      <id>Atlantic/Reykjavik</id>
+    </country>
+
+    <!-- ITALY, 1:00 -->
+    <country code="it">
+      <id>Europe/Rome</id>
+    </country>
+
+    <!-- JERSEY, 0:00 -->
+    <country code="je">
+      <id>Europe/Jersey</id>
+    </country>
+
+    <!-- JAMAICA, -5:00 -->
+    <country code="jm">
+      <id>America/Jamaica</id>
+    </country>
+
+    <!-- JORDAN, 2:00 -->
+    <country code="jo">
+      <id>Asia/Amman</id>
+    </country>
+
+    <!-- JAPAN, 9:00 -->
+    <country code="jp">
+      <id>Asia/Tokyo</id>
+    </country>
+
+    <!-- KENYA, 3:00 -->
+    <country code="ke">
+      <id>Africa/Nairobi</id>
+    </country>
+
+    <!-- KYRGYZSTAN, 6:00 -->
+    <country code="kg">
+      <id>Asia/Bishkek</id>
+    </country>
+
+    <!-- CAMBODIA, 7:00 -->
+    <country code="kh">
+      <id>Asia/Phnom_Penh</id>
+    </country>
+
+    <!-- KIRIBATI -->
+    <country code="ki">
+      <!-- 14:00 -->
+      <id>Pacific/Kiritimati</id>
+
+      <!-- 13:00 -->
+      <id>Pacific/Enderbury</id>
+
+      <!-- 12:00 -->
+      <id>Pacific/Tarawa</id>
+    </country>
+
+    <!-- COMOROS, 3:00 -->
+    <country code="km">
+      <id>Indian/Comoro</id>
+    </country>
+
+    <!-- SAINT KITTS AND NEVIS, -4:00 -->
+    <country code="kn">
+      <id>America/St_Kitts</id>
+    </country>
+
+    <!-- KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF, 8:30 -->
+    <country code="kp">
+      <id>Asia/Pyongyang</id>
+    </country>
+
+    <!-- KOREA, REPUBLIC OF, 9:00 -->
+    <country code="kr">
+      <id>Asia/Seoul</id>
+    </country>
+
+    <!-- KUWAIT, 3:00 -->
+    <country code="kw">
+      <id>Asia/Kuwait</id>
+    </country>
+
+    <!-- CAYMAN ISLANDS, -5:00 -->
+    <country code="ky">
+      <id>America/Cayman</id>
+    </country>
+
+    <!-- KAZAKHSTAN -->
+    <country code="kz">
+      <!-- 6:00 -->
+      <id>Asia/Almaty</id>
+      <id>Asia/Qyzylorda</id>
+
+      <!-- 5:00 -->
+      <id>Asia/Aqtau</id>
+      <id>Asia/Oral</id>
+      <id>Asia/Aqtobe</id>
+      <id>Asia/Atyrau</id>
+    </country>
+
+    <!-- LAO PEOPLE'S DEMOCRATIC REPUBLIC, 7:00 -->
+    <country code="la">
+      <id>Asia/Vientiane</id>
+    </country>
+
+    <!-- LEBANON, 2:00 -->
+    <country code="lb">
+      <id>Asia/Beirut</id>
+    </country>
+
+    <!-- SAINT LUCIA, -4:00 -->
+    <country code="lc">
+      <id>America/St_Lucia</id>
+    </country>
+
+    <!-- LIECHTENSTEIN, 1:00 -->
+    <country code="li">
+      <id>Europe/Vaduz</id>
+    </country>
+
+    <!-- SRI LANKA, 5:30 -->
+    <country code="lk">
+      <id>Asia/Colombo</id>
+    </country>
+
+    <!-- LIBERIA, 0:00 -->
+    <country code="lr">
+      <id>Africa/Monrovia</id>
+    </country>
+
+    <!-- LESOTHO, 2:00 -->
+    <country code="ls">
+      <id>Africa/Maseru</id>
+    </country>
+
+    <!-- LITHUANIA, 2:00 -->
+    <country code="lt">
+      <id>Europe/Vilnius</id>
+    </country>
+
+    <!-- LUXEMBOURG, 1:00 -->
+    <country code="lu">
+      <id>Europe/Luxembourg</id>
+    </country>
+
+    <!-- LATVIA, 2:00 -->
+    <country code="lv">
+      <id>Europe/Riga</id>
+    </country>
+
+    <!-- LIBYAN ARAB JAMAHIRIYA, 2:00 -->
+    <country code="ly">
+      <id>Africa/Tripoli</id>
+    </country>
+
+    <!-- MOROCCO, 0:00 -->
+    <country code="ma">
+      <id>Africa/Casablanca</id>
+    </country>
+
+    <!-- MONACO, 1:00 -->
+    <country code="mc">
+      <id>Europe/Monaco</id>
+    </country>
+
+    <!-- MOLDOVA, 2:00 -->
+    <country code="md">
+      <id>Europe/Chisinau</id>
+    </country>
+
+    <!-- MONTENEGRO, 1:00 -->
+    <country code="me">
+      <id>Europe/Podgorica</id>
+    </country>
+
+    <!-- Collectivity of Saint Martin, -4:00 -->
+    <country code="mf">
+      <id>America/Marigot</id>
+    </country>
+
+    <!-- MADAGASCAR, 3:00 -->
+    <country code="mg">
+      <id>Indian/Antananarivo</id>
+    </country>
+
+    <!-- MARSHALL ISLANDS, 12:00 -->
+    <country code="mh">
+      <id>Pacific/Majuro</id>
+      <id>Pacific/Kwajalein</id>
+    </country>
+
+    <!-- MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF, 1:00 -->
+    <country code="mk">
+      <id>Europe/Skopje</id>
+    </country>
+
+    <!-- MALI, 0:00 -->
+    <country code="ml">
+      <id>Africa/Bamako</id>
+    </country>
+
+    <!-- MYANMAR, 6:30 -->
+    <country code="mm">
+      <id>Asia/Yangon</id>
+    </country>
+
+    <!-- MONGOLIA -->
+    <country code="mn">
+      <!-- 8:00 -->
+      <id>Asia/Choibalsan</id>
+      <id>Asia/Ulaanbaatar</id>
+
+      <!-- 7:00 -->
+      <id>Asia/Hovd</id>
+    </country>
+
+    <!-- MACAO, 8:00 -->
+    <country code="mo">
+      <id>Asia/Macau</id>
+    </country>
+
+    <!-- NORTHERN MARIANA ISLANDS, 10:00 -->
+    <country code="mp">
+      <id>Pacific/Saipan</id>
+    </country>
+
+    <!-- MARTINIQUE, -4:00 -->
+    <country code="mq">
+      <id>America/Martinique</id>
+    </country>
+
+    <!-- MAURITANIA, 0:00 -->
+    <country code="mr">
+      <id>Africa/Nouakchott</id>
+    </country>
+
+    <!-- MONTSERRAT, -4:00 -->
+    <country code="ms">
+      <id>America/Montserrat</id>
+    </country>
+
+    <!-- MALTA, 1:00 -->
+    <country code="mt">
+      <id>Europe/Malta</id>
+    </country>
+
+    <!-- MAURITIUS, 4:00 -->
+    <country code="mu">
+      <id>Indian/Mauritius</id>
+    </country>
+
+    <!-- MALDIVES, 5:00 -->
+    <country code="mv">
+      <id>Indian/Maldives</id>
+    </country>
+
+    <!-- MALAWI, 2:00 -->
+    <country code="mw">
+      <id>Africa/Blantyre</id>
+    </country>
+
+    <!-- MEXICO -->
+    <country code="mx">
+      <!-- -6:00 -->
+      <id>America/Mexico_City</id>
+      <id>America/Merida</id>
+      <id>America/Monterrey</id>
+      <id>America/Matamoros</id>
+      <id>America/Bahia_Banderas</id>
+
+      <!-- -5:00 -->
+      <id>America/Cancun</id>
+
+      <!-- -7:00 -->
+      <id>America/Chihuahua</id>
+      <id>America/Hermosillo</id>
+      <id>America/Mazatlan</id>
+      <id>America/Ojinaga</id>
+
+      <!-- -8:00 -->
+      <id>America/Tijuana</id>
+    </country>
+
+    <!-- MALAYSIA, 8:00 -->
+    <country code="my">
+      <id>Asia/Kuala_Lumpur</id>
+      <id>Asia/Kuching</id>
+    </country>
+
+    <!-- MOZAMBIQUE, 2:00 -->
+    <country code="mz">
+      <id>Africa/Maputo</id>
+    </country>
+
+    <!-- NAMIBIA, 1:00 -->
+    <country code="na">
+      <id>Africa/Windhoek</id>
+    </country>
+
+    <!-- NEW CALEDONIA, 11:00 -->
+    <country code="nc">
+      <id>Pacific/Noumea</id>
+    </country>
+
+    <!-- NIGER, 1:00 -->
+    <country code="ne">
+      <id>Africa/Niamey</id>
+    </country>
+
+    <!-- NORFOLK ISLAND, 11:30 -->
+    <country code="nf">
+      <id>Pacific/Norfolk</id>
+    </country>
+
+    <!-- NIGERIA, 1:00 -->
+    <country code="ng">
+      <id>Africa/Lagos</id>
+    </country>
+
+    <!-- NICARAGUA, -6:00 -->
+    <country code="ni">
+      <id>America/Managua</id>
+    </country>
+
+    <!-- NETHERLANDS, 1:00 -->
+    <country code="nl">
+      <id>Europe/Amsterdam</id>
+    </country>
+
+    <!-- NORWAY, 1:00 -->
+    <country code="no">
+      <id>Europe/Oslo</id>
+    </country>
+
+    <!-- NEPAL, 5:45 -->
+    <country code="np">
+      <id>Asia/Kathmandu</id>
+    </country>
+
+    <!-- NAURU, 12:00 -->
+    <country code="nr">
+      <id>Pacific/Nauru</id>
+    </country>
+
+    <!-- NIUE, -11:00 -->
+    <country code="nu">
+      <id>Pacific/Niue</id>
+    </country>
+
+    <!-- NEW ZEALAND, 12:00 -->
+    <country code="nz">
+      <!-- 12:00 -->
+      <id>Pacific/Auckland</id>
+
+      <!-- 12:45 -->
+      <id>Pacific/Chatham</id>
+    </country>
+
+    <!-- OMAN, 4:00 -->
+    <country code="om">
+      <id>Asia/Muscat</id>
+    </country>
+
+    <!-- PANAMA, -5:00 -->
+    <country code="pa">
+      <id>America/Panama</id>
+    </country>
+
+    <!-- PERU, -5:00 -->
+    <country code="pe">
+      <id>America/Lima</id>
+    </country>
+
+    <!-- FRENCH POLYNESIA -->
+    <country code="pf">
+      <!-- -9:00 -->
+      <id>Pacific/Gambier</id>
+
+      <!-- -9:30 -->
+      <id>Pacific/Marquesas</id>
+
+      <!-- -10:00 -->
+      <id>Pacific/Tahiti</id>
+    </country>
+
+    <!-- PAPUA NEW GUINEA -->
+    <country code="pg">
+      <!-- 10:00 -->
+      <id>Pacific/Port_Moresby</id>
+
+      <!-- 11:00 -->
+      <id>Pacific/Bougainville</id>
+    </country>
+
+    <!-- PHILIPPINES, 8:00 -->
+    <country code="ph">
+      <id>Asia/Manila</id>
+    </country>
+
+    <!-- PAKISTAN, 5:00 -->
+    <country code="pk">
+      <id>Asia/Karachi</id>
+    </country>
+
+    <!-- POLAND, 1:00 -->
+    <country code="pl">
+      <id>Europe/Warsaw</id>
+    </country>
+
+    <!-- SAINT PIERRE AND MIQUELON, -3:00 -->
+    <country code="pm">
+      <id>America/Miquelon</id>
+    </country>
+
+    <!-- PITCAIRN, -8:00 -->
+    <country code="pn">
+      <id>Pacific/Pitcairn</id>
+    </country>
+
+    <!-- PUERTO RICO, -4:00 -->
+    <country code="pr">
+      <id>America/Puerto_Rico</id>
+    </country>
+
+    <!-- PALESTINE, 2:00 -->
+    <country code="ps">
+      <id>Asia/Gaza</id>
+      <id>Asia/Hebron</id>
+    </country>
+
+    <!-- PORTUGAL -->
+    <country code="pt">
+      <!-- 0:00 -->
+      <id>Europe/Lisbon</id>
+      <id>Atlantic/Madeira</id>
+
+      <!-- -1:00 -->
+      <id>Atlantic/Azores</id>
+    </country>
+
+    <!-- PALAU, 9:00 -->
+    <country code="pw">
+      <id>Pacific/Palau</id>
+    </country>
+
+    <!-- PARAGUAY, -4:00 -->
+    <country code="py">
+      <id>America/Asuncion</id>
+    </country>
+
+    <!-- QATAR, 3:00 -->
+    <country code="qa">
+      <id>Asia/Qatar</id>
+    </country>
+
+    <!-- REUNION, 4:00 -->
+    <country code="re">
+      <id>Indian/Reunion</id>
+    </country>
+
+    <!-- ROMANIA, 2:00 -->
+    <country code="ro">
+      <id>Europe/Bucharest</id>
+    </country>
+
+    <!-- SERBIA, 1:00 -->
+    <country code="rs">
+      <id>Europe/Belgrade</id>
+    </country>
+
+    <!-- RUSSIAN FEDERATION -->
+    <country code="ru">
+      <!-- 12:00 -->
+      <id>Asia/Kamchatka</id>
+      <id>Asia/Anadyr</id>
+
+      <!-- 11:00 -->
+      <id>Asia/Magadan</id>
+      <id>Asia/Sakhalin</id>
+      <id>Asia/Srednekolymsk</id>
+
+      <!-- 10:00 -->
+      <id>Asia/Vladivostok</id>
+      <id>Asia/Ust-Nera</id>
+
+      <!-- 9:00 -->
+      <id>Asia/Yakutsk</id>
+      <id>Asia/Chita</id>
+      <id>Asia/Khandyga</id>
+
+      <!-- 8:00 -->
+      <id>Asia/Irkutsk</id>
+
+      <!-- 7:00 -->
+      <id>Asia/Krasnoyarsk</id>
+      <id>Asia/Novosibirsk</id>
+      <id>Asia/Barnaul</id>
+      <id>Asia/Novokuznetsk</id>
+      <id>Asia/Tomsk</id>
+
+      <!-- 6:00 -->
+      <id>Asia/Omsk</id>
+
+      <!-- 5:00 -->
+      <id>Asia/Yekaterinburg</id>
+
+      <!-- 4:00 -->
+      <id>Europe/Samara</id>
+      <id>Europe/Astrakhan</id>
+      <id>Europe/Ulyanovsk</id>
+      <id>Europe/Saratov</id>
+
+      <!-- 3:00 -->
+      <id>Europe/Moscow</id>
+      <id>Europe/Volgograd</id>
+      <id>Europe/Kirov</id>
+      <id>Europe/Simferopol</id>
+
+      <!-- 2:00 -->
+      <id>Europe/Kaliningrad</id>
+    </country>
+
+    <!-- RWANDA, 2:00 -->
+    <country code="rw">
+      <id>Africa/Kigali</id>
+    </country>
+
+    <!-- SAUDI ARABIA, 3:00 -->
+    <country code="sa">
+      <id>Asia/Riyadh</id>
+    </country>
+
+    <!-- SOLOMON ISLANDS, 11:00 -->
+    <country code="sb">
+      <id>Pacific/Guadalcanal</id>
+    </country>
+
+    <!-- SEYCHELLES, 4:00 -->
+    <country code="sc">
+      <id>Indian/Mahe</id>
+    </country>
+
+    <!-- SUDAN, 3:00 -->
+    <country code="sd">
+      <id>Africa/Khartoum</id>
+    </country>
+
+    <!-- SWEDEN, 1:00 -->
+    <country code="se">
+      <id>Europe/Stockholm</id>
+    </country>
+
+    <!-- SINGAPORE, 8:00 -->
+    <country code="sg">
+      <id>Asia/Singapore</id>
+    </country>
+
+    <!-- SAINT HELENA, 0:00 -->
+    <country code="sh">
+      <id>Atlantic/St_Helena</id>
+    </country>
+
+    <!-- SLOVENIA, 1:00 -->
+    <country code="si">
+      <id>Europe/Ljubljana</id>
+    </country>
+
+    <!-- SVALBARD AND JAN MAYEN, 1:00 -->
+    <country code="sj">
+      <id>Arctic/Longyearbyen</id>
+    </country>
+
+    <!-- SLOVAKIA, 1:00 -->
+    <country code="sk">
+      <id>Europe/Bratislava</id>
+    </country>
+
+    <!-- SIERRA LEONE, 0:00 -->
+    <country code="sl">
+      <id>Africa/Freetown</id>
+    </country>
+
+    <!-- SAN MARINO, 1:00 -->
+    <country code="sm">
+      <id>Europe/San_Marino</id>
+    </country>
+
+    <!-- SENEGAL, 0:00 -->
+    <country code="sn">
+      <id>Africa/Dakar</id>
+    </country>
+
+    <!-- SOMALIA, 3:00 -->
+    <country code="so">
+      <id>Africa/Mogadishu</id>
+    </country>
+
+    <!-- SURINAME, -3:00 -->
+    <country code="sr">
+      <id>America/Paramaribo</id>
+    </country>
+
+    <!-- South Sudan, 3:00 -->
+    <country code="ss">
+      <id>Africa/Juba</id>
+    </country>
+
+    <!-- SAO TOME AND PRINCIPE, 0:00 -->
+    <country code="st">
+      <id>Africa/Sao_Tome</id>
+    </country>
+
+    <!-- EL SALVADOR, -6:00 -->
+    <country code="sv">
+      <id>America/El_Salvador</id>
+    </country>
+
+    <!-- Sint Maarten, -4:00 -->
+    <country code="sx">
+      <id>America/Lower_Princes</id>
+    </country>
+
+    <!-- SYRIAN ARAB REPUBLIC, 2:00 -->
+    <country code="sy">
+      <id>Asia/Damascus</id>
+    </country>
+
+    <!-- SWAZILAND, 2:00 -->
+    <country code="sz">
+      <id>Africa/Mbabane</id>
+    </country>
+
+    <!-- TURKS AND CAICOS ISLANDS, -4:00 -->
+    <country code="tc">
+      <id>America/Grand_Turk</id>
+    </country>
+
+    <!-- CHAD, 1:00 -->
+    <country code="td">
+      <id>Africa/Ndjamena</id>
+    </country>
+
+    <!-- FRENCH SOUTHERN TERRITORIES -->
+    <country code="tf">
+      <!-- 5:00 -->
+      <id>Indian/Kerguelen</id>
+    </country>
+
+    <!-- TOGO, 0:00 -->
+    <country code="tg">
+      <id>Africa/Lome</id>
+    </country>
+
+    <!-- THAILAND, 7:00 -->
+    <country code="th">
+      <id>Asia/Bangkok</id>
+    </country>
+
+    <!-- TAJIKISTAN, 5:00 -->
+    <country code="tj">
+      <id>Asia/Dushanbe</id>
+    </country>
+
+    <!-- TOKELAU, +13:00 -->
+    <country code="tk">
+      <id>Pacific/Fakaofo</id>
+    </country>
+
+    <!-- TIMOR-LESTE, 9:00 -->
+    <country code="tl">
+      <id>Asia/Dili</id>
+    </country>
+
+    <!-- TURKMENISTAN, 5:00 -->
+    <country code="tm">
+      <id>Asia/Ashgabat</id>
+    </country>
+
+    <!-- TUNISIA, 1:00 -->
+    <country code="tn">
+      <id>Africa/Tunis</id>
+    </country>
+
+    <!-- TONGA, 13:00 -->
+    <country code="to">
+      <id>Pacific/Tongatapu</id>
+    </country>
+
+    <!-- TURKEY, 3:00 -->
+    <country code="tr">
+      <id>Europe/Istanbul</id>
+    </country>
+
+    <!-- TRINIDAD AND TOBAGO, -4:00 -->
+    <country code="tt">
+      <id>America/Port_of_Spain</id>
+    </country>
+
+    <!-- TUVALU, 12:00 -->
+    <country code="tv">
+      <id>Pacific/Funafuti</id>
+    </country>
+
+    <!-- TAIWAN, PROVINCE OF CHINA, 8:00 -->
+    <country code="tw">
+      <id>Asia/Taipei</id>
+    </country>
+
+    <!-- TANZANIA, UNITED REPUBLIC OF, 3:00 -->
+    <country code="tz">
+      <id>Africa/Dar_es_Salaam</id>
+    </country>
+
+    <!-- UKRAINE, 2:00 -->
+    <country code="ua">
+      <id>Europe/Kiev</id>
+      <id>Europe/Uzhgorod</id>
+      <id>Europe/Zaporozhye</id>
+    </country>
+
+    <!-- UGANDA, 3:00 -->
+    <country code="ug">
+      <id>Africa/Kampala</id>
+    </country>
+
+    <!-- UNITED STATES MINOR OUTLYING ISLANDS -->
+    <country code="um">
+      <!-- 12:00 -->
+      <id>Pacific/Wake</id>
+
+      <!-- -11:00 -->
+      <id>Pacific/Midway</id>
+    </country>
+
+    <!-- UNITED STATES -->
+    <country code="us">
+      <!-- -5:00 -->
+      <id>America/New_York</id>
+      <id>America/Detroit</id>
+      <id>America/Kentucky/Louisville</id>
+      <id>America/Kentucky/Monticello</id>
+      <id>America/Indiana/Indianapolis</id>
+      <id>America/Indiana/Vincennes</id>
+      <id>America/Indiana/Winamac</id>
+      <id>America/Indiana/Marengo</id>
+      <id>America/Indiana/Petersburg</id>
+      <id>America/Indiana/Vevay</id>
+
+      <!-- -6:00 -->
+      <id>America/Chicago</id>
+      <id>America/Indiana/Knox</id>
+      <id>America/Menominee</id>
+      <id>America/North_Dakota/Center</id>
+      <id>America/North_Dakota/New_Salem</id>
+      <id>America/Indiana/Tell_City</id>
+      <id>America/North_Dakota/Beulah</id>
+
+      <!-- -7:00 -->
+      <id>America/Denver</id>
+      <id>America/Boise</id>
+      <id>America/Phoenix</id>
+
+      <!-- -8:00 -->
+      <id>America/Los_Angeles</id>
+
+      <!-- -9:00 -->
+      <id>America/Anchorage</id>
+      <id>America/Juneau</id>
+      <id>America/Yakutat</id>
+      <id>America/Nome</id>
+      <id>America/Metlakatla</id>
+      <id>America/Sitka</id>
+
+      <!-- -10:00 -->
+      <id>Pacific/Honolulu</id>
+      <id>America/Adak</id>
+    </country>
+
+    <!-- URUGUAY, -3:00 -->
+    <country code="uy">
+      <id>America/Montevideo</id>
+    </country>
+
+    <!-- UZBEKISTAN, 5:00 -->
+    <country code="uz">
+      <id>Asia/Tashkent</id>
+      <id>Asia/Samarkand</id>
+    </country>
+
+    <!-- HOLY SEE (VATICAN CITY STATE), 1:00 -->
+    <country code="va">
+      <id>Europe/Vatican</id>
+    </country>
+
+    <!-- SAINT VINCENT AND THE GRENADINES, -4:00 -->
+    <country code="vc">
+      <id>America/St_Vincent</id>
+    </country>
+
+    <!-- VENEZUELA, -4:00 -->
+    <country code="ve">
+      <id>America/Caracas</id>
+    </country>
+
+    <!-- VIRGIN ISLANDS, BRITISH, -4:00 -->
+    <country code="vg">
+      <id>America/Tortola</id>
+    </country>
+
+    <!-- VIRGIN ISLANDS, U.S., -4:00 -->
+    <country code="vi">
+      <id>America/St_Thomas</id>
+    </country>
+
+    <!-- VIET NAM, 7:00 -->
+    <country code="vn">
+      <id>Asia/Ho_Chi_Minh</id>
+    </country>
+
+    <!-- VANUATU, 11:00 -->
+    <country code="vu">
+      <id>Pacific/Efate</id>
+    </country>
+
+    <!-- WALLIS AND FUTUNA, 12:00 -->
+    <country code="wf">
+      <id>Pacific/Wallis</id>
+    </country>
+
+    <!-- SAMOA, 13:00 -->
+    <country code="ws">
+      <id>Pacific/Apia</id>
+    </country>
+
+    <!-- YEMEN, 3:00 -->
+    <country code="ye">
+      <id>Asia/Aden</id>
+    </country>
+
+    <!-- MAYOTTE, 3:00 -->
+    <country code="yt">
+      <id>Indian/Mayotte</id>
+    </country>
+
+    <!-- SOUTH AFRICA, 2:00 -->
+    <country code="za">
+      <id>Africa/Johannesburg</id>
+    </country>
+
+    <!-- ZAMBIA, 2:00 -->
+    <country code="zm">
+      <id>Africa/Lusaka</id>
+    </country>
+
+    <!-- ZIMBABWE, 2:00 -->
+    <country code="zw">
+      <id>Africa/Harare</id>
+    </country>
+  </countryzones>
+</timezones>
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 48e59c7..d31c652 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -186,7 +186,7 @@
   };
 
   // If you're targeting N, you don't get the greylist.
-  if (get_application_target_sdk_version() >= __ANDROID_API_N__) {
+  if (g_greylist_disabled || get_application_target_sdk_version() >= __ANDROID_API_N__) {
     return false;
   }
 
diff --git a/linker/linker_logger.cpp b/linker/linker_logger.cpp
index b2ea320..717667c 100644
--- a/linker/linker_logger.cpp
+++ b/linker/linker_logger.cpp
@@ -26,32 +26,21 @@
  * SUCH DAMAGE.
  */
 
+#include "linker_logger.h"
+
 #include <string.h>
 #include <sys/prctl.h>
-#include <sys/system_properties.h>
 #include <unistd.h>
 
 #include <string>
 #include <vector>
 
 #include "android-base/strings.h"
-#include "linker_logger.h"
+#include "private/CachedProperty.h"
 #include "private/libc_logging.h"
 
 LinkerLogger g_linker_logger;
-
-static const char* kSystemLdDebugProperty = "debug.ld.all";
-static const char* kLdDebugPropertyPrefix = "debug.ld.app.";
-
-static const char* kOptionErrors = "dlerror";
-static const char* kOptionDlopen = "dlopen";
-static const char* kOptionDlsym = "dlsym";
-
-static std::string property_get(const char* name) {
-  char value[PROP_VALUE_MAX] = {};
-  __system_property_get(name, value);
-  return value;
-}
+bool g_greylist_disabled = false;
 
 static uint32_t ParseProperty(const std::string& value) {
   if (value.empty()) {
@@ -63,38 +52,22 @@
   uint32_t flags = 0;
 
   for (const auto& o : options) {
-    if (o == kOptionErrors) {
+    if (o == "dlerror") {
       flags |= kLogErrors;
-    } else if (o == kOptionDlopen){
+    } else if (o == "dlopen") {
       flags |= kLogDlopen;
-    } else if (o == kOptionDlsym){
+    } else if (o == "dlsym") {
       flags |= kLogDlsym;
     } else {
-      __libc_format_log(ANDROID_LOG_WARN, "linker", "Unknown debug.ld option \"%s\", will ignore.", o.c_str());
+      __libc_format_log(ANDROID_LOG_WARN, "linker", "Ignoring unknown debug.ld option \"%s\"",
+                        o.c_str());
     }
   }
 
   return flags;
 }
 
-void LinkerLogger::ResetState() {
-  // the most likely scenario app is not debuggable and
-  // is running on user build - the logging is disabled.
-  if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) {
-    return;
-  }
-
-  flags_ = 0;
-
-  // Check flag applied to all processes first.
-  std::string value = property_get(kSystemLdDebugProperty);
-  flags_ |= ParseProperty(value);
-
-  // Ignore processes started without argv (http://b/33276926).
-  if (g_argv[0] == nullptr) {
-    return;
-  }
-
+static void GetAppSpecificProperty(char* buffer) {
   // Get process basename.
   const char* process_name_start = basename(g_argv[0]);
 
@@ -106,10 +79,42 @@
                              std::string(process_name_start, (process_name_end - process_name_start)) :
                              std::string(process_name_start);
 
-  std::string property_name = std::string(kLdDebugPropertyPrefix) + process_name;
+  std::string property_name = std::string("debug.ld.app.") + process_name;
+  __system_property_get(property_name.c_str(), buffer);
+}
 
-  value = property_get(property_name.c_str());
-  flags_ |= ParseProperty(value);
+void LinkerLogger::ResetState() {
+  // The most likely scenario app is not debuggable and
+  // is running on a user build, in which case logging is disabled.
+  if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) {
+    return;
+  }
+
+  // This is a convenient place to check whether the greylist should be disabled for testing.
+  static CachedProperty greylist_disabled("debug.ld.greylist_disabled");
+  bool old_value = g_greylist_disabled;
+  g_greylist_disabled = (strcmp(greylist_disabled.Get(), "true") == 0);
+  if (g_greylist_disabled != old_value) {
+    __libc_format_log(ANDROID_LOG_INFO, "linker", "%s greylist",
+                      g_greylist_disabled ? "Disabling" : "Enabling");
+  }
+
+  flags_ = 0;
+
+  // For logging, check the flag applied to all processes first.
+  static CachedProperty debug_ld_all("debug.ld.all");
+  flags_ |= ParseProperty(debug_ld_all.Get());
+
+  // Ignore processes started without argv (http://b/33276926).
+  if (g_argv[0] == nullptr) {
+    return;
+  }
+
+  // Otherwise check the app-specific property too.
+  // We can't easily cache the property here because argv[0] changes.
+  char debug_ld_app[PROP_VALUE_MAX] = {};
+  GetAppSpecificProperty(debug_ld_app);
+  flags_ |= ParseProperty(debug_ld_app);
 }
 
 void LinkerLogger::Log(uint32_t type, const char* format, ...) {
@@ -122,4 +127,3 @@
   __libc_format_log_va_list(ANDROID_LOG_DEBUG, "linker", format, ap);
   va_end(ap);
 }
-
diff --git a/linker/linker_logger.h b/linker/linker_logger.h
index f37b974..3e53f74 100644
--- a/linker/linker_logger.h
+++ b/linker/linker_logger.h
@@ -58,4 +58,8 @@
 extern LinkerLogger g_linker_logger;
 extern char** g_argv;
 
+// If the system property debug.ld.greylist_disabled is true, we'll not use the greylist
+// regardless of API level.
+extern bool g_greylist_disabled;
+
 #endif /* _LINKER_LOGGER_H_ */
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 86b282c..67103e1 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -58,71 +58,44 @@
   char b[10];
 };
 
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, stpncpy_fortified2) {
   foo myfoo;
   int copy_amt = atoi("11");
   ASSERT_FORTIFY(stpncpy(myfoo.a, "01234567890", copy_amt));
 }
-#endif
 
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, stpncpy2_fortified2) {
   foo myfoo;
   memset(&myfoo, 0, sizeof(myfoo));
   myfoo.one[0] = 'A'; // not null terminated string
   ASSERT_FORTIFY(stpncpy(myfoo.b, myfoo.one, sizeof(myfoo.b)));
 }
-#endif
 
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strncpy_fortified2) {
   foo myfoo;
   int copy_amt = atoi("11");
   ASSERT_FORTIFY(strncpy(myfoo.a, "01234567890", copy_amt));
 }
-#endif
 
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strncpy2_fortified2) {
   foo myfoo;
   memset(&myfoo, 0, sizeof(myfoo));
   myfoo.one[0] = 'A'; // not null terminated string
   ASSERT_FORTIFY(strncpy(myfoo.b, myfoo.one, sizeof(myfoo.b)));
 }
-#endif
 
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, sprintf_fortified2) {
   foo myfoo;
   char source_buf[15];
   memcpy(source_buf, "12345678901234", 15);
   ASSERT_FORTIFY(sprintf(myfoo.a, "%s", source_buf));
 }
-#endif
 
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, sprintf2_fortified2) {
   foo myfoo;
   ASSERT_FORTIFY(sprintf(myfoo.a, "0123456789"));
 }
-#endif
 
-#ifndef __clang__
-// These tests are disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 static int vsprintf_helper2(const char *fmt, ...) {
   foo myfoo;
   va_list va;
@@ -141,11 +114,7 @@
 TEST_F(DEATHTEST, vsprintf2_fortified2) {
   ASSERT_FORTIFY(vsprintf_helper2("0123456789"));
 }
-#endif
 
-#ifndef __clang__
-// These tests are disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 static int vsnprintf_helper2(const char *fmt, ...) {
   foo myfoo;
   va_list va;
@@ -165,12 +134,8 @@
 TEST_F(DEATHTEST, vsnprintf2_fortified2) {
   ASSERT_FORTIFY(vsnprintf_helper2("0123456789"));
 }
-#endif
 
-#ifndef __clang__
 // zero sized target with "\0" source (should fail)
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, stpcpy_fortified2) {
 #if defined(__BIONIC__)
   foo myfoo;
@@ -181,12 +146,8 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
-#endif
 
-#ifndef __clang__
 // zero sized target with "\0" source (should fail)
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strcpy_fortified2) {
 #if defined(__BIONIC__)
   foo myfoo;
@@ -197,12 +158,8 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
-#endif
 
-#ifndef __clang__
 // zero sized target with longer source (should fail)
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strcpy2_fortified2) {
 #if defined(__BIONIC__)
   foo myfoo;
@@ -213,12 +170,8 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
-#endif
 
-#ifndef __clang__
 // one byte target with longer source (should fail)
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strcpy3_fortified2) {
 #if defined(__BIONIC__)
   foo myfoo;
@@ -229,40 +182,43 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
-#endif
 
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strchr_fortified2) {
 #if defined(__BIONIC__)
   foo myfoo;
   memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
   myfoo.b[0] = '\0';
   ASSERT_FORTIFY(printf("%s", strchr(myfoo.a, 'a')));
+  ASSERT_FORTIFY(printf("%s", strchr(static_cast<const char*>(myfoo.a), 'a')));
 #else // __BIONIC__
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
-#endif
 
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strrchr_fortified2) {
 #if defined(__BIONIC__)
   foo myfoo;
   memcpy(myfoo.a, "0123456789", 10);
   memcpy(myfoo.b, "01234", 6);
   ASSERT_FORTIFY(printf("%s", strrchr(myfoo.a, 'a')));
+  ASSERT_FORTIFY(printf("%s", strrchr(static_cast<const char*>(myfoo.a), 'a')));
 #else // __BIONIC__
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
-#endif
 
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
+TEST_F(DEATHTEST, memchr_fortified2) {
+#if defined(__BIONIC__)
+  foo myfoo;
+  volatile int asize = sizeof(myfoo.a) + 1;
+  memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
+  ASSERT_FORTIFY(printf("%s", memchr(myfoo.a, 'a', asize)));
+  ASSERT_FORTIFY(printf("%s", memchr(static_cast<const void*>(myfoo.a), 'a', asize)));
+#else // __BIONIC__
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif // __BIONIC__
+}
+
 // this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strlcpy_fortified2) {
 #if defined(__BIONIC__)
@@ -274,10 +230,7 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
-#endif
 
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strlcat_fortified2) {
 #if defined(__BIONIC__)
@@ -290,29 +243,20 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
-#endif
 
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strncat_fortified2) {
   foo myfoo;
   size_t n = atoi("10"); // avoid compiler optimizations
   strncpy(myfoo.a, "012345678", n);
   ASSERT_FORTIFY(strncat(myfoo.a, "9", n));
 }
-#endif
 
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strncat2_fortified2) {
   foo myfoo;
   myfoo.a[0] = '\0';
   size_t n = atoi("10"); // avoid compiler optimizations
   ASSERT_FORTIFY(strncat(myfoo.a, "0123456789", n));
 }
-#endif
 
 TEST_F(DEATHTEST, strncat3_fortified2) {
   foo myfoo;
@@ -322,9 +266,6 @@
   ASSERT_FORTIFY(strncat(myfoo.b, myfoo.a, n));
 }
 
-#ifndef __clang__
-// This test is disabled in clang because clang doesn't properly detect
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strcat_fortified2) {
   char src[11];
   strcpy(src, "0123456789");
@@ -332,7 +273,6 @@
   myfoo.a[0] = '\0';
   ASSERT_FORTIFY(strcat(myfoo.a, src));
 }
-#endif
 
 TEST_F(DEATHTEST, strcat2_fortified2) {
   foo myfoo;
@@ -467,7 +407,12 @@
   ASSERT_FORTIFY(sprintf(buf, "%s", source_buf));
 }
 
-#ifndef __clang__
+#ifdef __clang__
+// Exists upstream, but hasn't been pulled in yet.
+#if __has_attribute(alloc_size)
+#error "Reenable this test"
+#endif
+#else
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, sprintf_malloc_fortified) {
diff --git a/tests/stdatomic_test.cpp b/tests/stdatomic_test.cpp
index 22e0c50..389b251 100644
--- a/tests/stdatomic_test.cpp
+++ b/tests/stdatomic_test.cpp
@@ -116,20 +116,34 @@
 
   atomic_store(&i, 123);
   expected = 123;
-  ASSERT_TRUE(atomic_compare_exchange_strong_explicit(&i, &expected, 456, memory_order_relaxed, memory_order_relaxed));
-  ASSERT_FALSE(atomic_compare_exchange_strong_explicit(&i, &expected, 456, memory_order_relaxed, memory_order_relaxed));
+  ASSERT_TRUE(atomic_compare_exchange_strong_explicit(&i, &expected, 456, memory_order_relaxed,
+          memory_order_relaxed));
+  ASSERT_FALSE(atomic_compare_exchange_strong_explicit(&i, &expected, 456, memory_order_relaxed,
+          memory_order_relaxed));
   ASSERT_EQ(456, expected);
 
   atomic_store(&i, 123);
   expected = 123;
-  ASSERT_TRUE(atomic_compare_exchange_weak(&i, &expected, 456));
+  int iter_count = 0;
+  do {
+    ++iter_count;
+    ASSERT_LT(iter_count, 100);  // Arbitrary limit on spurious compare_exchange failures.
+    ASSERT_EQ(expected, 123);
+  } while(!atomic_compare_exchange_weak(&i, &expected, 456));
   ASSERT_FALSE(atomic_compare_exchange_weak(&i, &expected, 456));
   ASSERT_EQ(456, expected);
 
   atomic_store(&i, 123);
   expected = 123;
-  ASSERT_TRUE(atomic_compare_exchange_weak_explicit(&i, &expected, 456, memory_order_relaxed, memory_order_relaxed));
-  ASSERT_FALSE(atomic_compare_exchange_weak_explicit(&i, &expected, 456, memory_order_relaxed, memory_order_relaxed));
+  iter_count = 0;
+  do {
+    ++iter_count;
+    ASSERT_LT(iter_count, 100);
+    ASSERT_EQ(expected, 123);
+  } while(!atomic_compare_exchange_weak_explicit(&i, &expected, 456, memory_order_relaxed,
+          memory_order_relaxed));
+  ASSERT_FALSE(atomic_compare_exchange_weak_explicit(&i, &expected, 456, memory_order_relaxed,
+          memory_order_relaxed));
   ASSERT_EQ(456, expected);
 }