Merge "Update timezone data to 2015f"
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..ea19538
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,14 @@
+BasedOnStyle: Google
+AllowShortBlocksOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 2
+ContinuationIndentWidth: 2
+PointerAlignment: Left
+TabWidth: 2
+UseTab: Never
+PenaltyExcessCharacter: 32
+
+Cpp11BracedListStyle: false
diff --git a/benchmarks/math_benchmark.cpp b/benchmarks/math_benchmark.cpp
index 2e0c962..ed5b56c 100644
--- a/benchmarks/math_benchmark.cpp
+++ b/benchmarks/math_benchmark.cpp
@@ -258,3 +258,29 @@
 
   StopBenchmarkTiming();
 }
+
+BENCHMARK_WITH_ARG(BM_math_fabs_macro, double)->AT_COMMON_VALS;
+void BM_math_fabs_macro::Run(int iters, double value) {
+  StartBenchmarkTiming();
+
+  d = 0.0;
+  v = value;
+  for (int i = 0; i < iters; ++i) {
+    d += fabs(v);
+  }
+
+  StopBenchmarkTiming();
+}
+
+BENCHMARK_WITH_ARG(BM_math_fabs, double)->AT_COMMON_VALS;
+void BM_math_fabs::Run(int iters, double value) {
+  StartBenchmarkTiming();
+
+  d = 0.0;
+  v = value;
+  for (int i = 0; i < iters; ++i) {
+    d += (fabs)(v);
+  }
+
+  StopBenchmarkTiming();
+}
diff --git a/libc/Android.mk b/libc/Android.mk
index 74ac33b..ca20d3d 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -79,6 +79,8 @@
     bionic/__poll_chk.cpp \
     bionic/__pread64_chk.cpp \
     bionic/__pread_chk.cpp \
+    bionic/__pwrite64_chk.cpp \
+    bionic/__pwrite_chk.cpp \
     bionic/__read_chk.cpp \
     bionic/__readlink_chk.cpp \
     bionic/__readlinkat_chk.cpp \
@@ -95,6 +97,7 @@
     bionic/__umask_chk.cpp \
     bionic/__vsnprintf_chk.cpp \
     bionic/__vsprintf_chk.cpp \
+    bionic/__write_chk.cpp
 
 libc_bionic_ndk_src_files := \
     bionic/abort.cpp \
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index b5283f6..58c5eb6 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -39,6 +39,7 @@
     arch-arm/bionic/__bionic_clone.S \
     arch-arm/bionic/_exit_with_stack_teardown.S \
     arch-arm/bionic/libgcc_compat.c \
+    arch-arm/bionic/popcount_tab.c \
     arch-arm/bionic/__restore.S \
     arch-arm/bionic/setjmp.S \
     arch-arm/bionic/syscall.S \
diff --git a/libc/arch-arm/bionic/popcount_tab.c b/libc/arch-arm/bionic/popcount_tab.c
new file mode 100644
index 0000000..eb2faa9
--- /dev/null
+++ b/libc/arch-arm/bionic/popcount_tab.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+// Export this to maintain ABI compatibilty with libgcc, since compiler-rt
+// doesn't use a table-driven implementation of __popcount.
+const unsigned char __popcount_tab[256] = {
+  0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3,
+  3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4,
+  3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4,
+  4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5,
+  3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2,
+  2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,
+  4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5,
+  5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+  3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5,
+  5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+};
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S b/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
index a2e9c22..3692f04 100644
--- a/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
+++ b/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,191 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#include <private/bionic_asm.h>
-#include <private/libc_events.h>
+// Indicate which memcpy base file to include.
+#define MEMCPY_BASE "memcpy_base.S"
 
-    .syntax unified
-
-    .thumb
-    .thumb_func
-
-// Get the length of src string, then get the source of the dst string.
-// Check that the two lengths together don't exceed the threshold, then
-// do a memcpy of the data.
-ENTRY(__strcat_chk)
-    pld     [r0, #0]
-    push    {r0, lr}
-    .cfi_def_cfa_offset 8
-    .cfi_rel_offset r0, 0
-    .cfi_rel_offset lr, 4
-    push    {r4, r5}
-    .cfi_adjust_cfa_offset 8
-    .cfi_rel_offset r4, 0
-    .cfi_rel_offset r5, 4
-
-    mov     lr, r2
-
-    // Save the dst register to r5
-    mov     r5, r0
-
-    // Zero out r4
-    eor     r4, r4, r4
-
-    // r1 contains the address of the string to count.
-.L_strlen_start:
-    mov     r0, r1
-    ands    r3, r1, #7
-    beq     .L_mainloop
-
-    // Align to a double word (64 bits).
-    rsb     r3, r3, #8
-    lsls    ip, r3, #31
-    beq     .L_align_to_32
-
-    ldrb    r2, [r1], #1
-    cbz     r2, .L_update_count_and_finish
-
-.L_align_to_32:
-    bcc     .L_align_to_64
-    ands    ip, r3, #2
-    beq     .L_align_to_64
-
-    ldrb    r2, [r1], #1
-    cbz     r2, .L_update_count_and_finish
-    ldrb    r2, [r1], #1
-    cbz     r2, .L_update_count_and_finish
-
-.L_align_to_64:
-    tst     r3, #4
-    beq     .L_mainloop
-    ldr     r3, [r1], #4
-
-    sub     ip, r3, #0x01010101
-    bic     ip, ip, r3
-    ands    ip, ip, #0x80808080
-    bne     .L_zero_in_second_register
-
-    .p2align 2
-.L_mainloop:
-    ldrd    r2, r3, [r1], #8
-
-    pld     [r1, #64]
-
-    sub     ip, r2, #0x01010101
-    bic     ip, ip, r2
-    ands    ip, ip, #0x80808080
-    bne     .L_zero_in_first_register
-
-    sub     ip, r3, #0x01010101
-    bic     ip, ip, r3
-    ands    ip, ip, #0x80808080
-    bne     .L_zero_in_second_register
-    b       .L_mainloop
-
-.L_update_count_and_finish:
-    sub     r3, r1, r0
-    sub     r3, r3, #1
-    b       .L_finish
-
-.L_zero_in_first_register:
-    sub     r3, r1, r0
-    lsls    r2, ip, #17
-    bne     .L_sub8_and_finish
-    bcs     .L_sub7_and_finish
-    lsls    ip, ip, #1
-    bne     .L_sub6_and_finish
-
-    sub     r3, r3, #5
-    b       .L_finish
-
-.L_sub8_and_finish:
-    sub     r3, r3, #8
-    b       .L_finish
-
-.L_sub7_and_finish:
-    sub     r3, r3, #7
-    b       .L_finish
-
-.L_sub6_and_finish:
-    sub     r3, r3, #6
-    b       .L_finish
-
-.L_zero_in_second_register:
-    sub     r3, r1, r0
-    lsls    r2, ip, #17
-    bne     .L_sub4_and_finish
-    bcs     .L_sub3_and_finish
-    lsls    ip, ip, #1
-    bne     .L_sub2_and_finish
-
-    sub     r3, r3, #1
-    b       .L_finish
-
-.L_sub4_and_finish:
-    sub     r3, r3, #4
-    b       .L_finish
-
-.L_sub3_and_finish:
-    sub     r3, r3, #3
-    b       .L_finish
-
-.L_sub2_and_finish:
-    sub     r3, r3, #2
-
-.L_finish:
-    cmp     r4, #0
-    bne     .L_strlen_done
-
-    // Time to get the dst string length.
-    mov     r1, r5
-
-    // Save the original source address to r5.
-    mov     r5, r0
-
-    // Save the current length (adding 1 for the terminator).
-    add     r4, r3, #1
-    b       .L_strlen_start
-
-    // r0 holds the pointer to the dst string.
-    // r3 holds the dst string length.
-    // r4 holds the src string length + 1.
-.L_strlen_done:
-    add     r2, r3, r4
-    cmp     r2, lr
-    bhi     __strcat_chk_failed
-
-    // Set up the registers for the memcpy code.
-    mov     r1, r5
-    pld     [r1, #64]
-    mov     r2, r4
-    add     r0, r0, r3
-    pop     {r4, r5}
-END(__strcat_chk)
-
-#define MEMCPY_BASE         __strcat_chk_memcpy_base
-#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
-
-#include "memcpy_base.S"
-
-ENTRY_PRIVATE(__strcat_chk_failed)
-    .cfi_def_cfa_offset 8
-    .cfi_rel_offset r0, 0
-    .cfi_rel_offset lr, 4
-    .cfi_adjust_cfa_offset 8
-    .cfi_rel_offset r4, 0
-    .cfi_rel_offset r5, 4
-
-    ldr     r0, error_message
-    ldr     r1, error_code
-1:
-    add     r0, pc
-    bl      __fortify_chk_fail
-error_code:
-    .word   BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
-error_message:
-    .word   error_string-(1b+4)
-END(__strcat_chk_failed)
-
-    .data
-error_string:
-    .string "strcat: prevented write past end of buffer"
+#include "__strcat_chk_common.S"
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcat_chk_common.S b/libc/arch-arm/cortex-a15/bionic/__strcat_chk_common.S
new file mode 100644
index 0000000..de66967
--- /dev/null
+++ b/libc/arch-arm/cortex-a15/bionic/__strcat_chk_common.S
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2013 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>
+#include <private/libc_events.h>
+
+    .syntax unified
+
+    .thumb
+    .thumb_func
+
+// Get the length of src string, then get the source of the dst string.
+// Check that the two lengths together don't exceed the threshold, then
+// do a memcpy of the data.
+ENTRY(__strcat_chk)
+    pld     [r0, #0]
+    push    {r0, lr}
+    .cfi_def_cfa_offset 8
+    .cfi_rel_offset r0, 0
+    .cfi_rel_offset lr, 4
+    push    {r4, r5}
+    .cfi_adjust_cfa_offset 8
+    .cfi_rel_offset r4, 0
+    .cfi_rel_offset r5, 4
+
+    mov     lr, r2
+
+    // Save the dst register to r5
+    mov     r5, r0
+
+    // Zero out r4
+    eor     r4, r4, r4
+
+    // r1 contains the address of the string to count.
+.L_strlen_start:
+    mov     r0, r1
+    ands    r3, r1, #7
+    beq     .L_mainloop
+
+    // Align to a double word (64 bits).
+    rsb     r3, r3, #8
+    lsls    ip, r3, #31
+    beq     .L_align_to_32
+
+    ldrb    r2, [r1], #1
+    cbz     r2, .L_update_count_and_finish
+
+.L_align_to_32:
+    bcc     .L_align_to_64
+    ands    ip, r3, #2
+    beq     .L_align_to_64
+
+    ldrb    r2, [r1], #1
+    cbz     r2, .L_update_count_and_finish
+    ldrb    r2, [r1], #1
+    cbz     r2, .L_update_count_and_finish
+
+.L_align_to_64:
+    tst     r3, #4
+    beq     .L_mainloop
+    ldr     r3, [r1], #4
+
+    sub     ip, r3, #0x01010101
+    bic     ip, ip, r3
+    ands    ip, ip, #0x80808080
+    bne     .L_zero_in_second_register
+
+    .p2align 2
+.L_mainloop:
+    ldrd    r2, r3, [r1], #8
+
+    pld     [r1, #64]
+
+    sub     ip, r2, #0x01010101
+    bic     ip, ip, r2
+    ands    ip, ip, #0x80808080
+    bne     .L_zero_in_first_register
+
+    sub     ip, r3, #0x01010101
+    bic     ip, ip, r3
+    ands    ip, ip, #0x80808080
+    bne     .L_zero_in_second_register
+    b       .L_mainloop
+
+.L_update_count_and_finish:
+    sub     r3, r1, r0
+    sub     r3, r3, #1
+    b       .L_finish
+
+.L_zero_in_first_register:
+    sub     r3, r1, r0
+    lsls    r2, ip, #17
+    bne     .L_sub8_and_finish
+    bcs     .L_sub7_and_finish
+    lsls    ip, ip, #1
+    bne     .L_sub6_and_finish
+
+    sub     r3, r3, #5
+    b       .L_finish
+
+.L_sub8_and_finish:
+    sub     r3, r3, #8
+    b       .L_finish
+
+.L_sub7_and_finish:
+    sub     r3, r3, #7
+    b       .L_finish
+
+.L_sub6_and_finish:
+    sub     r3, r3, #6
+    b       .L_finish
+
+.L_zero_in_second_register:
+    sub     r3, r1, r0
+    lsls    r2, ip, #17
+    bne     .L_sub4_and_finish
+    bcs     .L_sub3_and_finish
+    lsls    ip, ip, #1
+    bne     .L_sub2_and_finish
+
+    sub     r3, r3, #1
+    b       .L_finish
+
+.L_sub4_and_finish:
+    sub     r3, r3, #4
+    b       .L_finish
+
+.L_sub3_and_finish:
+    sub     r3, r3, #3
+    b       .L_finish
+
+.L_sub2_and_finish:
+    sub     r3, r3, #2
+
+.L_finish:
+    cmp     r4, #0
+    bne     .L_strlen_done
+
+    // Time to get the dst string length.
+    mov     r1, r5
+
+    // Save the original source address to r5.
+    mov     r5, r0
+
+    // Save the current length (adding 1 for the terminator).
+    add     r4, r3, #1
+    b       .L_strlen_start
+
+    // r0 holds the pointer to the dst string.
+    // r3 holds the dst string length.
+    // r4 holds the src string length + 1.
+.L_strlen_done:
+    add     r2, r3, r4
+    cmp     r2, lr
+    bhi     .L_strcat_chk_failed
+
+    // Set up the registers for the memcpy code.
+    mov     r1, r5
+    pld     [r1, #64]
+    mov     r2, r4
+    add     r0, r0, r3
+    pop     {r4, r5}
+    .cfi_adjust_cfa_offset -8
+    .cfi_restore r4
+    .cfi_restore r5
+
+#include MEMCPY_BASE
+
+    // Undo the above cfi directives
+    .cfi_adjust_cfa_offset 8
+    .cfi_rel_offset r4, 0
+    .cfi_rel_offset r5, 4
+.L_strcat_chk_failed:
+    ldr     r0, error_message
+    ldr     r1, error_code
+1:
+    add     r0, pc
+    bl      __fortify_chk_fail
+error_code:
+    .word   BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
+error_message:
+    .word   error_string-(1b+4)
+END(__strcat_chk)
+
+    .data
+error_string:
+    .string "strcat: prevented write past end of buffer"
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
index db76686..d8cb3d9 100644
--- a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
+++ b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,155 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#include <private/bionic_asm.h>
-#include <private/libc_events.h>
+// Indicate which memcpy base file to include.
+#define MEMCPY_BASE "memcpy_base.S"
 
-    .syntax unified
-
-    .thumb
-    .thumb_func
-
-// Get the length of the source string first, then do a memcpy of the data
-// instead of a strcpy.
-ENTRY(__strcpy_chk)
-    pld     [r0, #0]
-    push    {r0, lr}
-    .cfi_def_cfa_offset 8
-    .cfi_rel_offset r0, 0
-    .cfi_rel_offset lr, 4
-
-    mov     lr, r2
-    mov     r0, r1
-
-    ands    r3, r1, #7
-    beq     .L_mainloop
-
-    // Align to a double word (64 bits).
-    rsb     r3, r3, #8
-    lsls    ip, r3, #31
-    beq     .L_align_to_32
-
-    ldrb    r2, [r0], #1
-    cbz     r2, .L_update_count_and_finish
-
-.L_align_to_32:
-    bcc     .L_align_to_64
-    ands    ip, r3, #2
-    beq     .L_align_to_64
-
-    ldrb    r2, [r0], #1
-    cbz     r2, .L_update_count_and_finish
-    ldrb    r2, [r0], #1
-    cbz     r2, .L_update_count_and_finish
-
-.L_align_to_64:
-    tst     r3, #4
-    beq     .L_mainloop
-    ldr     r3, [r0], #4
-
-    sub     ip, r3, #0x01010101
-    bic     ip, ip, r3
-    ands    ip, ip, #0x80808080
-    bne     .L_zero_in_second_register
-
-    .p2align 2
-.L_mainloop:
-    ldrd    r2, r3, [r0], #8
-
-    pld     [r0, #64]
-
-    sub     ip, r2, #0x01010101
-    bic     ip, ip, r2
-    ands    ip, ip, #0x80808080
-    bne     .L_zero_in_first_register
-
-    sub     ip, r3, #0x01010101
-    bic     ip, ip, r3
-    ands    ip, ip, #0x80808080
-    bne     .L_zero_in_second_register
-    b       .L_mainloop
-
-.L_update_count_and_finish:
-    sub     r3, r0, r1
-    sub     r3, r3, #1
-    b       .L_check_size
-
-.L_zero_in_first_register:
-    sub     r3, r0, r1
-    lsls    r2, ip, #17
-    bne     .L_sub8_and_finish
-    bcs     .L_sub7_and_finish
-    lsls    ip, ip, #1
-    bne     .L_sub6_and_finish
-
-    sub     r3, r3, #5
-    b       .L_check_size
-
-.L_sub8_and_finish:
-    sub     r3, r3, #8
-    b       .L_check_size
-
-.L_sub7_and_finish:
-    sub     r3, r3, #7
-    b       .L_check_size
-
-.L_sub6_and_finish:
-    sub     r3, r3, #6
-    b       .L_check_size
-
-.L_zero_in_second_register:
-    sub     r3, r0, r1
-    lsls    r2, ip, #17
-    bne     .L_sub4_and_finish
-    bcs     .L_sub3_and_finish
-    lsls    ip, ip, #1
-    bne     .L_sub2_and_finish
-
-    sub     r3, r3, #1
-    b       .L_check_size
-
-.L_sub4_and_finish:
-    sub     r3, r3, #4
-    b       .L_check_size
-
-.L_sub3_and_finish:
-    sub     r3, r3, #3
-    b       .L_check_size
-
-.L_sub2_and_finish:
-    sub     r3, r3, #2
-
-.L_check_size:
-    pld     [r1, #0]
-    pld     [r1, #64]
-    ldr     r0, [sp]
-    cmp     r3, lr
-    bhs     __strcpy_chk_failed
-
-    // Add 1 for copy length to get the string terminator.
-    add     r2, r3, #1
-END(__strcpy_chk)
-
-#define MEMCPY_BASE         __strcpy_chk_memcpy_base
-#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
-#include "memcpy_base.S"
-
-ENTRY_PRIVATE(__strcpy_chk_failed)
-    .cfi_def_cfa_offset 8
-    .cfi_rel_offset r0, 0
-    .cfi_rel_offset lr, 4
-
-    ldr     r0, error_message
-    ldr     r1, error_code
-1:
-    add     r0, pc
-    bl      __fortify_chk_fail
-error_code:
-    .word   BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
-error_message:
-    .word   error_string-(1b+4)
-END(__strcpy_chk_failed)
-
-    .data
-error_string:
-    .string "strcpy: prevented write past end of buffer"
+#include "__strcpy_chk_common.S"
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk_common.S b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk_common.S
new file mode 100644
index 0000000..69ebcb4
--- /dev/null
+++ b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk_common.S
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2013 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>
+#include <private/libc_events.h>
+
+    .syntax unified
+
+    .thumb
+    .thumb_func
+
+// Get the length of the source string first, then do a memcpy of the data
+// instead of a strcpy.
+ENTRY(__strcpy_chk)
+    pld     [r0, #0]
+    push    {r0, lr}
+    .cfi_def_cfa_offset 8
+    .cfi_rel_offset r0, 0
+    .cfi_rel_offset lr, 4
+
+    mov     lr, r2
+    mov     r0, r1
+
+    ands    r3, r1, #7
+    beq     .L_mainloop
+
+    // Align to a double word (64 bits).
+    rsb     r3, r3, #8
+    lsls    ip, r3, #31
+    beq     .L_align_to_32
+
+    ldrb    r2, [r0], #1
+    cbz     r2, .L_update_count_and_finish
+
+.L_align_to_32:
+    bcc     .L_align_to_64
+    ands    ip, r3, #2
+    beq     .L_align_to_64
+
+    ldrb    r2, [r0], #1
+    cbz     r2, .L_update_count_and_finish
+    ldrb    r2, [r0], #1
+    cbz     r2, .L_update_count_and_finish
+
+.L_align_to_64:
+    tst     r3, #4
+    beq     .L_mainloop
+    ldr     r3, [r0], #4
+
+    sub     ip, r3, #0x01010101
+    bic     ip, ip, r3
+    ands    ip, ip, #0x80808080
+    bne     .L_zero_in_second_register
+
+    .p2align 2
+.L_mainloop:
+    ldrd    r2, r3, [r0], #8
+
+    pld     [r0, #64]
+
+    sub     ip, r2, #0x01010101
+    bic     ip, ip, r2
+    ands    ip, ip, #0x80808080
+    bne     .L_zero_in_first_register
+
+    sub     ip, r3, #0x01010101
+    bic     ip, ip, r3
+    ands    ip, ip, #0x80808080
+    bne     .L_zero_in_second_register
+    b       .L_mainloop
+
+.L_update_count_and_finish:
+    sub     r3, r0, r1
+    sub     r3, r3, #1
+    b       .L_check_size
+
+.L_zero_in_first_register:
+    sub     r3, r0, r1
+    lsls    r2, ip, #17
+    bne     .L_sub8_and_finish
+    bcs     .L_sub7_and_finish
+    lsls    ip, ip, #1
+    bne     .L_sub6_and_finish
+
+    sub     r3, r3, #5
+    b       .L_check_size
+
+.L_sub8_and_finish:
+    sub     r3, r3, #8
+    b       .L_check_size
+
+.L_sub7_and_finish:
+    sub     r3, r3, #7
+    b       .L_check_size
+
+.L_sub6_and_finish:
+    sub     r3, r3, #6
+    b       .L_check_size
+
+.L_zero_in_second_register:
+    sub     r3, r0, r1
+    lsls    r2, ip, #17
+    bne     .L_sub4_and_finish
+    bcs     .L_sub3_and_finish
+    lsls    ip, ip, #1
+    bne     .L_sub2_and_finish
+
+    sub     r3, r3, #1
+    b       .L_check_size
+
+.L_sub4_and_finish:
+    sub     r3, r3, #4
+    b       .L_check_size
+
+.L_sub3_and_finish:
+    sub     r3, r3, #3
+    b       .L_check_size
+
+.L_sub2_and_finish:
+    sub     r3, r3, #2
+
+.L_check_size:
+    pld     [r1, #0]
+    pld     [r1, #64]
+    ldr     r0, [sp]
+    cmp     r3, lr
+    bhs     .L_strcpy_chk_failed
+
+    // Add 1 for copy length to get the string terminator.
+    add     r2, r3, #1
+
+#include MEMCPY_BASE
+
+.L_strcpy_chk_failed:
+    ldr     r0, error_message
+    ldr     r1, error_code
+1:
+    add     r0, pc
+    bl      __fortify_chk_fail
+error_code:
+    .word   BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
+error_message:
+    .word   error_string-(1b+4)
+END(__strcpy_chk)
+
+    .data
+error_string:
+    .string "strcpy: prevented write past end of buffer"
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy.S b/libc/arch-arm/cortex-a15/bionic/memcpy.S
index 410b663..537f3de 100644
--- a/libc/arch-arm/cortex-a15/bionic/memcpy.S
+++ b/libc/arch-arm/cortex-a15/bionic/memcpy.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,79 +25,8 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-/*
- * Copyright (c) 2013 ARM Ltd
- * 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. The name of the company may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- *
- * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
- */
 
-// Prototype: void *memcpy (void *dst, const void *src, size_t count).
+// Indicate which memcpy base file to include.
+#define MEMCPY_BASE "memcpy_base.S"
 
-#include <private/bionic_asm.h>
-#include <private/libc_events.h>
-
-        .text
-        .syntax unified
-        .fpu    neon
-
-ENTRY(__memcpy_chk)
-        cmp     r2, r3
-        bhi     __memcpy_chk_fail
-
-        // Fall through to memcpy...
-END(__memcpy_chk)
-
-ENTRY(memcpy)
-        pld     [r1, #64]
-        push    {r0, lr}
-        .cfi_def_cfa_offset 8
-        .cfi_rel_offset r0, 0
-        .cfi_rel_offset lr, 4
-END(memcpy)
-
-#define MEMCPY_BASE         __memcpy_base
-#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
-#include "memcpy_base.S"
-
-ENTRY_PRIVATE(__memcpy_chk_fail)
-        // Preserve lr for backtrace.
-        push    {lr}
-        .cfi_def_cfa_offset 4
-        .cfi_rel_offset lr, 0
-
-        ldr     r0, error_message
-        ldr     r1, error_code
-1:
-        add     r0, pc
-        bl      __fortify_chk_fail
-error_code:
-        .word   BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
-error_message:
-        .word   error_string-(1b+8)
-END(__memcpy_chk_fail)
-
-        .data
-error_string:
-        .string "memcpy: prevented write past end of buffer"
+#include "memcpy_common.S"
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy_base.S b/libc/arch-arm/cortex-a15/bionic/memcpy_base.S
index 2a73852..aac737d 100644
--- a/libc/arch-arm/cortex-a15/bionic/memcpy_base.S
+++ b/libc/arch-arm/cortex-a15/bionic/memcpy_base.S
@@ -53,11 +53,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-ENTRY_PRIVATE(MEMCPY_BASE)
-        .cfi_def_cfa_offset 8
-        .cfi_rel_offset r0, 0
-        .cfi_rel_offset lr, 4
-
+.L_memcpy_base:
         // Assumes that n >= 0, and dst, src are valid pointers.
         // For any sizes less than 832 use the neon code that doesn't
         // care about the src alignment. This avoids any checks
@@ -168,12 +164,6 @@
         eor     r3, r0, r1
         ands    r3, r3, #0x3
         bne     .L_copy_unknown_alignment
-END(MEMCPY_BASE)
-
-ENTRY_PRIVATE(MEMCPY_BASE_ALIGNED)
-        .cfi_def_cfa_offset 8
-        .cfi_rel_offset r0, 0
-        .cfi_rel_offset lr, 4
 
         // To try and improve performance, stack layout changed,
         // i.e., not keeping the stack looking like users expect
@@ -185,7 +175,7 @@
         strd    r6, r7, [sp, #-8]!
         .cfi_adjust_cfa_offset 8
         .cfi_rel_offset r6, 0
-        .cfi_rel_offset r7, 0
+        .cfi_rel_offset r7, 4
         strd    r8, r9, [sp, #-8]!
         .cfi_adjust_cfa_offset 8
         .cfi_rel_offset r8, 0
@@ -291,10 +281,28 @@
 
         // Restore registers: optimized pop {r0, pc}
         ldrd    r8, r9, [sp], #8
+        .cfi_adjust_cfa_offset -8
+        .cfi_restore r8
+        .cfi_restore r9
         ldrd    r6, r7, [sp], #8
+        .cfi_adjust_cfa_offset -8
+        .cfi_restore r6
+        .cfi_restore r7
         ldrd    r4, r5, [sp], #8
+        .cfi_adjust_cfa_offset -8
+        .cfi_restore r4
+        .cfi_restore r5
         pop     {r0, pc}
 
+        // Put the cfi directives back for the below instructions.
+        .cfi_adjust_cfa_offset 24
+        .cfi_rel_offset r4, 0
+        .cfi_rel_offset r5, 4
+        .cfi_rel_offset r6, 8
+        .cfi_rel_offset r7, 12
+        .cfi_rel_offset r8, 16
+        .cfi_rel_offset r9, 20
+
 .L_dst_not_word_aligned:
         // Align dst to word.
         rsb     ip, ip, #4
@@ -315,4 +323,12 @@
 
         // Src is guaranteed to be at least word aligned by this point.
         b       .L_word_aligned
-END(MEMCPY_BASE_ALIGNED)
+
+        // Undo any cfi directives from above.
+        .cfi_adjust_cfa_offset -24
+        .cfi_restore r4
+        .cfi_restore r5
+        .cfi_restore r6
+        .cfi_restore r7
+        .cfi_restore r8
+        .cfi_restore r9
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy_common.S b/libc/arch-arm/cortex-a15/bionic/memcpy_common.S
new file mode 100644
index 0000000..464fb46
--- /dev/null
+++ b/libc/arch-arm/cortex-a15/bionic/memcpy_common.S
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 2013 ARM Ltd
+ * 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. The name of the company may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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>
+#include <private/libc_events.h>
+
+        .text
+        .syntax unified
+        .fpu    neon
+
+ENTRY(__memcpy_chk)
+        cmp     r2, r3
+        bhi     .L_memcpy_chk_fail
+
+        // Fall through to memcpy...
+END(__memcpy_chk)
+
+// Prototype: void *memcpy (void *dst, const void *src, size_t count).
+ENTRY(memcpy)
+        pld     [r1, #64]
+        push    {r0, lr}
+        .cfi_def_cfa_offset 8
+        .cfi_rel_offset r0, 0
+        .cfi_rel_offset lr, 4
+
+#include MEMCPY_BASE
+
+        // Undo the cfi instructions from above.
+        .cfi_def_cfa_offset 0
+        .cfi_restore r0
+        .cfi_restore lr
+.L_memcpy_chk_fail:
+        // Preserve lr for backtrace.
+        push    {lr}
+        .cfi_adjust_cfa_offset 4
+        .cfi_rel_offset lr, 0
+
+        ldr     r0, error_message
+        ldr     r1, error_code
+1:
+        add     r0, pc
+        bl      __fortify_chk_fail
+error_code:
+        .word   BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
+error_message:
+        .word   error_string-(1b+8)
+END(memcpy)
+
+        .data
+error_string:
+        .string "memcpy: prevented write past end of buffer"
diff --git a/libc/arch-arm/cortex-a53/bionic/__strcat_chk.S b/libc/arch-arm/cortex-a53/bionic/__strcat_chk.S
new file mode 100644
index 0000000..c5bc98a
--- /dev/null
+++ b/libc/arch-arm/cortex-a53/bionic/__strcat_chk.S
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+// Indicate which memcpy base file to include.
+#define MEMCPY_BASE "arch-arm/cortex-a53/bionic/memcpy_base.S"
+
+#include "arch-arm/cortex-a15/bionic/__strcat_chk_common.S"
diff --git a/libc/arch-arm/cortex-a53/bionic/__strcpy_chk.S b/libc/arch-arm/cortex-a53/bionic/__strcpy_chk.S
new file mode 100644
index 0000000..1f8945d
--- /dev/null
+++ b/libc/arch-arm/cortex-a53/bionic/__strcpy_chk.S
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+// Indicate which memcpy base file to include.
+#define MEMCPY_BASE "arch-arm/cortex-a53/bionic/memcpy_base.S"
+
+#include "arch-arm/cortex-a15/bionic/__strcpy_chk_common.S"
diff --git a/libc/arch-arm/cortex-a53/bionic/memcpy.S b/libc/arch-arm/cortex-a53/bionic/memcpy.S
new file mode 100644
index 0000000..664f574
--- /dev/null
+++ b/libc/arch-arm/cortex-a53/bionic/memcpy.S
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+// Indicate which memcpy base file to include.
+#define MEMCPY_BASE "arch-arm/cortex-a53/bionic/memcpy_base.S"
+
+#include "arch-arm/cortex-a15/bionic/memcpy_common.S"
diff --git a/libc/arch-arm/cortex-a53/bionic/memcpy_base.S b/libc/arch-arm/cortex-a53/bionic/memcpy_base.S
new file mode 100644
index 0000000..2749fc8
--- /dev/null
+++ b/libc/arch-arm/cortex-a53/bionic/memcpy_base.S
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 2013 ARM Ltd
+ * 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. The name of the company may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
+ */
+
+.L_memcpy_base:
+        // Assumes that n >= 0, and dst, src are valid pointers.
+        cmp     r2, #16
+        blo     .L_copy_less_than_16_unknown_align
+
+.L_copy_unknown_alignment:
+        // Unknown alignment of src and dst.
+        // Assumes that the first few bytes have already been prefetched.
+
+        // Align destination to 128 bits. The mainloop store instructions
+        // require this alignment or they will throw an exception.
+        rsb         r3, r0, #0
+        ands        r3, r3, #0xF
+        beq         2f
+
+        // Copy up to 15 bytes (count in r3).
+        sub         r2, r2, r3
+        movs        ip, r3, lsl #31
+
+        itt         mi
+        ldrbmi      lr, [r1], #1
+        strbmi      lr, [r0], #1
+        itttt       cs
+        ldrbcs      ip, [r1], #1
+        ldrbcs      lr, [r1], #1
+        strbcs      ip, [r0], #1
+        strbcs      lr, [r0], #1
+
+        movs        ip, r3, lsl #29
+        bge         1f
+        // Copies 4 bytes, dst 32 bits aligned before, at least 64 bits after.
+        vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]!
+        vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
+1:      bcc         2f
+        // Copies 8 bytes, dst 64 bits aligned before, at least 128 bits after.
+        vld1.8      {d0}, [r1]!
+        vst1.8      {d0}, [r0, :64]!
+
+2:      // Make sure we have at least 64 bytes to copy.
+        subs        r2, r2, #64
+        blo         2f
+
+1:      // The main loop copies 64 bytes at a time.
+        vld1.8      {d0  - d3},   [r1]!
+        vld1.8      {d4  - d7},   [r1]!
+        subs        r2, r2, #64
+        vstmia      r0!, {d0 - d7}
+        pld         [r1, #(64*10)]
+        bhs         1b
+
+2:      // Fix-up the remaining count and make sure we have >= 32 bytes left.
+        adds        r2, r2, #32
+        blo         3f
+
+        // 32 bytes. These cache lines were already preloaded.
+        vld1.8      {d0 - d3},  [r1]!
+        sub         r2, r2, #32
+        vst1.8      {d0 - d3},  [r0, :128]!
+3:      // Less than 32 left.
+        add         r2, r2, #32
+        tst         r2, #0x10
+        beq         .L_copy_less_than_16_unknown_align
+        // Copies 16 bytes, destination 128 bits aligned.
+        vld1.8      {d0, d1}, [r1]!
+        vst1.8      {d0, d1}, [r0, :128]!
+
+.L_copy_less_than_16_unknown_align:
+        // Copy up to 15 bytes (count in r2).
+        movs        ip, r2, lsl #29
+        bcc         1f
+        vld1.8      {d0}, [r1]!
+        vst1.8      {d0}, [r0]!
+1:      bge         2f
+        vld4.8      {d0[0], d1[0], d2[0], d3[0]}, [r1]!
+        vst4.8      {d0[0], d1[0], d2[0], d3[0]}, [r0]!
+
+2:      // Copy 0 to 4 bytes.
+        lsls        r2, r2, #31
+        itt         ne
+        ldrbne      lr, [r1], #1
+        strbne      lr, [r0], #1
+        itttt       cs
+        ldrbcs      ip, [r1], #1
+        ldrbcs      lr, [r1]
+        strbcs      ip, [r0], #1
+        strbcs      lr, [r0]
+
+        pop         {r0, pc}
diff --git a/libc/arch-arm/cortex-a53/cortex-a53.mk b/libc/arch-arm/cortex-a53/cortex-a53.mk
index b5c337c..bb00433 100644
--- a/libc/arch-arm/cortex-a53/cortex-a53.mk
+++ b/libc/arch-arm/cortex-a53/cortex-a53.mk
@@ -1 +1,20 @@
-include bionic/libc/arch-arm/cortex-a7/cortex-a7.mk
+libc_bionic_src_files_arm += \
+    arch-arm/cortex-a53/bionic/memcpy.S \
+    arch-arm/cortex-a53/bionic/__strcat_chk.S \
+    arch-arm/cortex-a53/bionic/__strcpy_chk.S \
+
+libc_bionic_src_files_arm += \
+    arch-arm/cortex-a7/bionic/memset.S \
+
+libc_bionic_src_files_arm += \
+    arch-arm/cortex-a15/bionic/stpcpy.S \
+    arch-arm/cortex-a15/bionic/strcat.S \
+    arch-arm/cortex-a15/bionic/strcmp.S \
+    arch-arm/cortex-a15/bionic/strcpy.S \
+    arch-arm/cortex-a15/bionic/strlen.S \
+
+libc_bionic_src_files_arm += \
+    arch-arm/generic/bionic/memcmp.S \
+
+libc_bionic_src_files_arm += \
+    arch-arm/denver/bionic/memmove.S \
diff --git a/libc/arch-arm/cortex-a7/bionic/memset.S b/libc/arch-arm/cortex-a7/bionic/memset.S
new file mode 100644
index 0000000..6365b06
--- /dev/null
+++ b/libc/arch-arm/cortex-a7/bionic/memset.S
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2013 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 <machine/cpu-features.h>
+#include <private/bionic_asm.h>
+#include <private/libc_events.h>
+
+        /*
+         * Optimized memset() for ARM.
+         *
+         * memset() returns its first argument.
+         */
+
+        .fpu        neon
+        .syntax     unified
+
+ENTRY(__memset_chk)
+        cmp         r2, r3
+        bls         .L_done
+
+        // Preserve lr for backtrace.
+        push        {lr}
+        .cfi_def_cfa_offset 4
+        .cfi_rel_offset lr, 0
+
+        ldr         r0, error_message
+        ldr         r1, error_code
+1:
+        add         r0, pc
+        bl          __fortify_chk_fail
+error_code:
+        .word       BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
+error_message:
+        .word       error_string-(1b+8)
+END(__memset_chk)
+
+ENTRY(bzero)
+        mov         r2, r1
+        mov         r1, #0
+.L_done:
+        // Fall through to memset...
+END(bzero)
+
+ENTRY(memset)
+        mov         r3, r0
+        // At this point only d0, d1 are going to be used below.
+        vdup.8      q0, r1
+        cmp         r2, #16
+        blo         .L_set_less_than_16_unknown_align
+
+.L_check_alignment:
+        // Align destination to a double word to avoid the store crossing
+        // a cache line boundary.
+        ands        ip, r3, #7
+        bne         .L_do_double_word_align
+
+.L_double_word_aligned:
+        // Duplicate since the less than 64 can use d2, d3.
+        vmov        q1, q0
+        subs        r2, #64
+        blo         .L_set_less_than_64
+
+        // Duplicate the copy value so that we can store 64 bytes at a time.
+        vmov        q2, q0
+        vmov        q3, q0
+
+1:      // Main loop stores 64 bytes at a time.
+        subs        r2, #64
+        vstmia      r3!, {d0 - d7}
+        bge         1b
+
+.L_set_less_than_64:
+        // Restore r2 to the count of bytes left to set.
+        add         r2, #64
+        lsls        ip, r2, #27
+        bcc         .L_set_less_than_32
+        // Set 32 bytes.
+        vstmia      r3!, {d0 - d3}
+
+.L_set_less_than_32:
+        bpl         .L_set_less_than_16
+        // Set 16 bytes.
+        vstmia      r3!, {d0, d1}
+
+.L_set_less_than_16:
+        // Less than 16 bytes to set.
+        lsls        ip, r2, #29
+        bcc         .L_set_less_than_8
+
+        // Set 8 bytes.
+        vstmia      r3!, {d0}
+
+.L_set_less_than_8:
+        bpl         .L_set_less_than_4
+        // Set 4 bytes
+        vst1.32     {d0[0]}, [r3]!
+
+.L_set_less_than_4:
+        lsls        ip, r2, #31
+        it          ne
+        strbne      r1, [r3], #1
+        itt         cs
+        strbcs      r1, [r3], #1
+        strbcs      r1, [r3]
+        bx          lr
+
+.L_do_double_word_align:
+        rsb         ip, ip, #8
+        sub         r2, r2, ip
+
+        // Do this comparison now, otherwise we'll need to save a
+        // register to the stack since we've used all available
+        // registers.
+        cmp         ip, #4
+        blo         1f
+
+        // Need to do a four byte copy.
+        movs        ip, ip, lsl #31
+        it          mi
+        strbmi      r1, [r3], #1
+        itt         cs
+        strbcs      r1, [r3], #1
+        strbcs      r1, [r3], #1
+        vst1.32     {d0[0]}, [r3]!
+        b           .L_double_word_aligned
+
+1:
+        // No four byte copy.
+        movs        ip, ip, lsl #31
+        it          mi
+        strbmi      r1, [r3], #1
+        itt         cs
+        strbcs      r1, [r3], #1
+        strbcs      r1, [r3], #1
+        b           .L_double_word_aligned
+
+.L_set_less_than_16_unknown_align:
+        // Set up to 15 bytes.
+        movs        ip, r2, lsl #29
+        bcc         1f
+        vst1.8      {d0}, [r3]!
+1:      bge         2f
+        vst1.32     {d0[0]}, [r3]!
+2:      movs        ip, r2, lsl #31
+        it          mi
+        strbmi      r1, [r3], #1
+        itt         cs
+        strbcs      r1, [r3], #1
+        strbcs      r1, [r3], #1
+        bx          lr
+END(memset)
+
+        .data
+error_string:
+        .string     "memset: prevented write past end of buffer"
diff --git a/libc/arch-arm/cortex-a7/cortex-a7.mk b/libc/arch-arm/cortex-a7/cortex-a7.mk
index 9af03d9..b6af4da 100644
--- a/libc/arch-arm/cortex-a7/cortex-a7.mk
+++ b/libc/arch-arm/cortex-a7/cortex-a7.mk
@@ -1 +1,18 @@
-include bionic/libc/arch-arm/cortex-a15/cortex-a15.mk
+libc_bionic_src_files_arm += \
+    arch-arm/cortex-a7/bionic/memset.S \
+
+libc_bionic_src_files_arm += \
+    arch-arm/cortex-a15/bionic/memcpy.S \
+    arch-arm/cortex-a15/bionic/stpcpy.S \
+    arch-arm/cortex-a15/bionic/strcat.S \
+    arch-arm/cortex-a15/bionic/__strcat_chk.S \
+    arch-arm/cortex-a15/bionic/strcmp.S \
+    arch-arm/cortex-a15/bionic/strcpy.S \
+    arch-arm/cortex-a15/bionic/__strcpy_chk.S \
+    arch-arm/cortex-a15/bionic/strlen.S \
+
+libc_bionic_src_files_arm += \
+    arch-arm/generic/bionic/memcmp.S \
+
+libc_bionic_src_files_arm += \
+    arch-arm/denver/bionic/memmove.S \
diff --git a/libc/bionic/__pwrite64_chk.cpp b/libc/bionic/__pwrite64_chk.cpp
new file mode 100644
index 0000000..e488ca1
--- /dev/null
+++ b/libc/bionic/__pwrite64_chk.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#undef _FORTIFY_SOURCE
+#include <unistd.h>
+#include "private/libc_logging.h"
+
+extern "C" ssize_t __pwrite64_chk(int fd, const void* buf, size_t count, off64_t offset,
+                                  size_t buf_size) {
+  if (__predict_false(count > buf_size)) {
+    __fortify_chk_fail("pwrite64: prevented read past end of buffer", 0);
+  }
+
+  if (__predict_false(count > SSIZE_MAX)) {
+    __fortify_chk_fail("pwrite64: count > SSIZE_MAX", 0);
+  }
+
+  return pwrite64(fd, buf, count, offset);
+}
diff --git a/libc/bionic/__pwrite_chk.cpp b/libc/bionic/__pwrite_chk.cpp
new file mode 100644
index 0000000..a889ef6
--- /dev/null
+++ b/libc/bionic/__pwrite_chk.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#undef _FORTIFY_SOURCE
+#include <unistd.h>
+#include "private/libc_logging.h"
+
+extern "C" ssize_t __pwrite_chk(int fd, const void* buf, size_t count, off_t offset,
+                                size_t buf_size) {
+  if (__predict_false(count > buf_size)) {
+    __fortify_chk_fail("pwrite: prevented read past end of buffer", 0);
+  }
+
+  if (__predict_false(count > SSIZE_MAX)) {
+    __fortify_chk_fail("pwrite: count > SSIZE_MAX", 0);
+  }
+
+  return pwrite(fd, buf, count, offset);
+}
diff --git a/libc/bionic/__write_chk.cpp b/libc/bionic/__write_chk.cpp
new file mode 100644
index 0000000..cbd247a
--- /dev/null
+++ b/libc/bionic/__write_chk.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#undef _FORTIFY_SOURCE
+#include <unistd.h>
+#include "private/libc_logging.h"
+
+extern "C" ssize_t __write_chk(int fd, const void* buf, size_t count, size_t buf_size) {
+  if (__predict_false(count > buf_size)) {
+    __fortify_chk_fail("write: prevented read past end of buffer", 0);
+  }
+
+  if (__predict_false(count > SSIZE_MAX)) {
+    __fortify_chk_fail("write: count > SSIZE_MAX", 0);
+  }
+
+  return write(fd, buf, count);
+}
diff --git a/libc/bionic/debug_stacktrace.cpp b/libc/bionic/debug_stacktrace.cpp
index 71e876b..4100911 100644
--- a/libc/bionic/debug_stacktrace.cpp
+++ b/libc/bionic/debug_stacktrace.cpp
@@ -85,14 +85,14 @@
     return _URC_NO_REASON;
   }
 
-#if defined(__arm__)
-  /*
-   * The instruction pointer is pointing at the instruction after the bl(x), and
-   * the _Unwind_Backtrace routine already masks the Thumb mode indicator (LSB
-   * in PC). So we need to do a quick check here to find out if the previous
-   * instruction is a Thumb-mode BLX(2). If so subtract 2 otherwise 4 from PC.
-   */
+  // The instruction pointer is pointing at the instruction after the return
+  // call on all architectures.
+  // Modify the pc to point at the real function.
   if (ip != 0) {
+#if defined(__arm__)
+    // We need to do a quick check here to find out if the previous
+    // instruction is a Thumb-mode BLX(2). If so subtract 2 otherwise
+    // 4 from PC.
     short* ptr = reinterpret_cast<short*>(ip);
     // Thumb BLX(2)
     if ((*(ptr-1) & 0xff80) == 0x4780) {
@@ -100,8 +100,15 @@
     } else {
       ip -= 4;
     }
-  }
+#elif defined(__aarch64__)
+    // All instructions are 4 bytes long, skip back one instruction.
+    ip -= 4;
+#elif defined(__i386__) || defined(__x86_64__)
+    // It's difficult to decode exactly where the previous instruction is,
+    // so subtract 1 to estimate where the instruction lives.
+    ip--;
 #endif
+  }
 
   state->frames[state->frame_count++] = ip;
   return (state->frame_count >= state->max_depth) ? _URC_END_OF_STACK : _URC_NO_REASON;
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 904447c..91ae89e 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -238,11 +238,26 @@
 __errordecl(__pread64_count_toobig_error, "pread64 called with count > SSIZE_MAX");
 extern ssize_t __pread64_real(int, void*, size_t, off64_t) __RENAME(pread64);
 
+extern ssize_t __pwrite_chk(int, const void*, size_t, off_t, size_t);
+__errordecl(__pwrite_dest_size_error, "pwrite called with size bigger than destination");
+__errordecl(__pwrite_count_toobig_error, "pwrite called with count > SSIZE_MAX");
+extern ssize_t __pwrite_real(int, const void*, size_t, off_t) __RENAME(pwrite);
+
+extern ssize_t __pwrite64_chk(int, const void*, size_t, off64_t, size_t);
+__errordecl(__pwrite64_dest_size_error, "pwrite64 called with size bigger than destination");
+__errordecl(__pwrite64_count_toobig_error, "pwrite64 called with count > SSIZE_MAX");
+extern ssize_t __pwrite64_real(int, const void*, size_t, off64_t) __RENAME(pwrite64);
+
 extern ssize_t __read_chk(int, void*, size_t, size_t);
 __errordecl(__read_dest_size_error, "read called with size bigger than destination");
 __errordecl(__read_count_toobig_error, "read called with count > SSIZE_MAX");
 extern ssize_t __read_real(int, void*, size_t) __RENAME(read);
 
+extern ssize_t __write_chk(int, const void*, size_t, size_t);
+__errordecl(__write_dest_size_error, "write called with size bigger than destination");
+__errordecl(__write_count_toobig_error, "write called with count > SSIZE_MAX");
+extern ssize_t __write_real(int, const void*, size_t) __RENAME(write);
+
 extern ssize_t __readlink_chk(const char*, char*, size_t, size_t);
 __errordecl(__readlink_dest_size_error, "readlink called with size bigger than destination");
 __errordecl(__readlink_size_toobig_error, "readlink called with size > SSIZE_MAX");
@@ -342,6 +357,62 @@
     return __pread64_chk(fd, buf, count, offset, bos);
 }
 
+#if defined(__USE_FILE_OFFSET64)
+#define __PWRITE_PREFIX(x) __pwrite64_ ## x
+#else
+#define __PWRITE_PREFIX(x) __pwrite_ ## x
+#endif
+
+__BIONIC_FORTIFY_INLINE
+ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset) {
+    size_t bos = __bos0(buf);
+
+#if !defined(__clang__)
+    if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
+        __PWRITE_PREFIX(count_toobig_error)();
+    }
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __PWRITE_PREFIX(real)(fd, buf, count, offset);
+    }
+
+    if (__builtin_constant_p(count) && (count > bos)) {
+        __PWRITE_PREFIX(dest_size_error)();
+    }
+
+    if (__builtin_constant_p(count) && (count <= bos)) {
+        return __PWRITE_PREFIX(real)(fd, buf, count, offset);
+    }
+#endif
+
+    return __PWRITE_PREFIX(chk)(fd, buf, count, offset, bos);
+}
+
+__BIONIC_FORTIFY_INLINE
+ssize_t pwrite64(int fd, const void* buf, size_t count, off64_t offset) {
+    size_t bos = __bos0(buf);
+
+#if !defined(__clang__)
+    if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
+        __pwrite64_count_toobig_error();
+    }
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __pwrite64_real(fd, buf, count, offset);
+    }
+
+    if (__builtin_constant_p(count) && (count > bos)) {
+        __pwrite64_dest_size_error();
+    }
+
+    if (__builtin_constant_p(count) && (count <= bos)) {
+        return __pwrite64_real(fd, buf, count, offset);
+    }
+#endif
+
+    return __pwrite64_chk(fd, buf, count, offset, bos);
+}
+
 __BIONIC_FORTIFY_INLINE
 ssize_t read(int fd, void* buf, size_t count) {
     size_t bos = __bos0(buf);
@@ -368,6 +439,33 @@
 }
 
 __BIONIC_FORTIFY_INLINE
+ssize_t write(int fd, const void* buf, size_t count) {
+    size_t bos = __bos0(buf);
+
+#if !defined(__clang__)
+#if 0 /* work around a false positive due to a missed optimization */
+    if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
+        __write_count_toobig_error();
+    }
+#endif
+
+    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+        return __write_real(fd, buf, count);
+    }
+
+    if (__builtin_constant_p(count) && (count > bos)) {
+        __write_dest_size_error();
+    }
+
+    if (__builtin_constant_p(count) && (count <= bos)) {
+        return __write_real(fd, buf, count);
+    }
+#endif
+
+    return __write_chk(fd, buf, count, bos);
+}
+
+__BIONIC_FORTIFY_INLINE
 ssize_t readlink(const char* path, char* buf, size_t size) {
     size_t bos = __bos(buf);
 
diff --git a/libc/libc.map b/libc/libc.map
index 6117d53..4670079 100644
--- a/libc/libc.map
+++ b/libc/libc.map
@@ -1337,6 +1337,9 @@
     __fread_chk;
     __fwrite_chk;
     __getcwd_chk;
+    __pwrite_chk;
+    __pwrite64_chk;
+    __write_chk;
     getgrgid_r;
     getgrnam_r;
 } LIBC;
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index 58670bb..2ca7728 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -70,6 +70,10 @@
   // Fast storage for Thread::Current() in ART.
   TLS_SLOT_ART_THREAD_SELF,
 
+  // Lets TSAN avoid using pthread_getspecific for finding the current thread
+  // state.
+  TLS_SLOT_TSAN,
+
   BIONIC_TLS_SLOTS // Must come last!
 };
 
diff --git a/libc/tools/zoneinfo/ZoneCompactor.java b/libc/tools/zoneinfo/ZoneCompactor.java
deleted file mode 100644
index 2d598fe..0000000
--- a/libc/tools/zoneinfo/ZoneCompactor.java
+++ /dev/null
@@ -1,192 +0,0 @@
-
-import java.io.*;
-import java.util.*;
-
-// usage: java ZoneCompiler <setup file> <data directory> <output directory> <tzdata version>
-//
-// Compile a set of tzfile-formatted files into a single file containing an index.
-//
-// The compilation is controlled by a setup file, which is provided as a
-// command-line argument.  The setup file has the form:
-//
-// Link <toName> <fromName>
-// ...
-// <zone filename>
-// ...
-//
-// Note that the links must be declared prior to the zone names.
-// A zone name is a filename relative to the source directory such as
-// 'GMT', 'Africa/Dakar', or 'America/Argentina/Jujuy'.
-//
-// Use the 'zic' command-line tool to convert from flat files
-// (such as 'africa' or 'northamerica') to a directory
-// hierarchy suitable for this tool (containing files such as 'data/Africa/Abidjan').
-//
-
-public class ZoneCompactor {
-  // Maximum number of characters in a zone name, including '\0' terminator.
-  private static final int MAXNAME = 40;
-
-  // Zone name synonyms.
-  private Map<String,String> links = new HashMap<String,String>();
-
-  // File offsets by zone name.
-  private Map<String,Integer> offsets = new HashMap<String,Integer>();
-
-  // File lengths by zone name.
-  private Map<String,Integer> lengths = new HashMap<String,Integer>();
-
-  // Concatenate the contents of 'inFile' onto 'out'.
-  private static void copyFile(File inFile, OutputStream out) throws Exception {
-    byte[] ret = new byte[0];
-
-    InputStream in = new FileInputStream(inFile);
-    byte[] buf = new byte[8192];
-    while (true) {
-      int nbytes = in.read(buf);
-      if (nbytes == -1) {
-        break;
-      }
-      out.write(buf, 0, nbytes);
-
-      byte[] nret = new byte[ret.length + nbytes];
-      System.arraycopy(ret, 0, nret, 0, ret.length);
-      System.arraycopy(buf, 0, nret, ret.length, nbytes);
-      ret = nret;
-    }
-    out.flush();
-  }
-
-  public ZoneCompactor(String setupFile, String dataDirectory, String zoneTabFile, String outputDirectory, String version) throws Exception {
-    // Read the setup file and concatenate all the data.
-    ByteArrayOutputStream allData = new ByteArrayOutputStream();
-    BufferedReader reader = new BufferedReader(new FileReader(setupFile));
-    String s;
-    int offset = 0;
-    while ((s = reader.readLine()) != null) {
-      s = s.trim();
-      if (s.startsWith("Link")) {
-        StringTokenizer st = new StringTokenizer(s);
-        st.nextToken();
-        String to = st.nextToken();
-        String from = st.nextToken();
-        links.put(from, to);
-      } else {
-        String link = links.get(s);
-        if (link == null) {
-          File sourceFile = new File(dataDirectory, s);
-          long length = sourceFile.length();
-          offsets.put(s, offset);
-          lengths.put(s, (int) length);
-
-          offset += length;
-          copyFile(sourceFile, allData);
-        }
-      }
-    }
-    reader.close();
-
-    // Fill in fields for links.
-    Iterator<String> it = links.keySet().iterator();
-    while (it.hasNext()) {
-      String from = it.next();
-      String to = links.get(from);
-
-      offsets.put(from, offsets.get(to));
-      lengths.put(from, lengths.get(to));
-    }
-
-    // Create/truncate the destination file.
-    RandomAccessFile f = new RandomAccessFile(new File(outputDirectory, "tzdata"), "rw");
-    f.setLength(0);
-
-    // Write the header.
-
-    // byte[12] tzdata_version -- 'tzdata2012f\0'
-    // int index_offset -- so we can slip in extra header fields in a backwards-compatible way
-    // int data_offset
-    // int zonetab_offset
-
-    // tzdata_version
-    f.write(toAscii(new byte[12], version));
-
-    // Write dummy values for the three offsets, and remember where we need to seek back to later
-    // when we have the real values.
-    int index_offset_offset = (int) f.getFilePointer();
-    f.writeInt(0);
-    int data_offset_offset = (int) f.getFilePointer();
-    f.writeInt(0);
-    int zonetab_offset_offset = (int) f.getFilePointer();
-    f.writeInt(0);
-
-    int index_offset = (int) f.getFilePointer();
-
-    // Write the index.
-    ArrayList<String> sortedOlsonIds = new ArrayList<String>();
-    sortedOlsonIds.addAll(offsets.keySet());
-    Collections.sort(sortedOlsonIds);
-    it = sortedOlsonIds.iterator();
-    while (it.hasNext()) {
-      String zoneName = it.next();
-      if (zoneName.length() >= MAXNAME) {
-        throw new RuntimeException("zone filename too long: " + zoneName.length());
-      }
-
-      // Follow the chain of links to work out where the real data for this zone lives.
-      String actualZoneName = zoneName;
-      while (links.get(actualZoneName) != null) {
-        actualZoneName = links.get(actualZoneName);
-      }
-
-      f.write(toAscii(new byte[MAXNAME], zoneName));
-      f.writeInt(offsets.get(actualZoneName));
-      f.writeInt(lengths.get(actualZoneName));
-      f.writeInt(0); // Used to be raw GMT offset. No longer used.
-    }
-
-    int data_offset = (int) f.getFilePointer();
-
-    // Write the data.
-    f.write(allData.toByteArray());
-
-    int zonetab_offset = (int) f.getFilePointer();
-
-    // Copy the zone.tab.
-    reader = new BufferedReader(new FileReader(zoneTabFile));
-    while ((s = reader.readLine()) != null) {
-      if (!s.startsWith("#")) {
-        f.writeBytes(s);
-        f.write('\n');
-      }
-    }
-    reader.close();
-
-    // Go back and fix up the offsets in the header.
-    f.seek(index_offset_offset);
-    f.writeInt(index_offset);
-    f.seek(data_offset_offset);
-    f.writeInt(data_offset);
-    f.seek(zonetab_offset_offset);
-    f.writeInt(zonetab_offset);
-
-    f.close();
-  }
-
-  private static byte[] toAscii(byte[] dst, String src) {
-    for (int i = 0; i < src.length(); ++i) {
-      if (src.charAt(i) > '~') {
-        throw new RuntimeException("non-ASCII string: " + src);
-      }
-      dst[i] = (byte) src.charAt(i);
-    }
-    return dst;
-  }
-
-  public static void main(String[] args) throws Exception {
-    if (args.length != 5) {
-      System.err.println("usage: java ZoneCompactor <setup file> <data directory> <zone.tab file> <output directory> <tzdata version>");
-      System.exit(0);
-    }
-    new ZoneCompactor(args[0], args[1], args[2], args[3], args[4]);
-  }
-}
diff --git a/libc/tools/zoneinfo/update-tzdata.py b/libc/tools/zoneinfo/update-tzdata.py
deleted file mode 100755
index 68a5ff5..0000000
--- a/libc/tools/zoneinfo/update-tzdata.py
+++ /dev/null
@@ -1,262 +0,0 @@
-#!/usr/bin/python
-
-"""Updates the timezone data held in bionic and ICU."""
-
-import ftplib
-import glob
-import httplib
-import os
-import re
-import shutil
-import subprocess
-import sys
-import tarfile
-import tempfile
-
-regions = ['africa', 'antarctica', 'asia', 'australasia',
-           'etcetera', 'europe', 'northamerica', 'southamerica',
-           # These two deliberately come last so they override what came
-           # before (and each other).
-           'backward', 'backzone' ]
-
-def CheckDirExists(dir, dirname):
-  if not os.path.isdir(dir):
-    print "Couldn't find %s (%s)!" % (dirname, dir)
-    sys.exit(1)
-
-bionic_libc_tools_zoneinfo_dir = os.path.realpath(os.path.dirname(sys.argv[0]))
-
-# Find the bionic directory, searching upward from this script.
-bionic_dir = os.path.realpath('%s/../../..' % bionic_libc_tools_zoneinfo_dir)
-bionic_libc_zoneinfo_dir = '%s/libc/zoneinfo' % bionic_dir
-CheckDirExists(bionic_libc_zoneinfo_dir, 'bionic/libc/zoneinfo')
-CheckDirExists(bionic_libc_tools_zoneinfo_dir, 'bionic/libc/tools/zoneinfo')
-print 'Found bionic in %s ...' % bionic_dir
-
-# Find the icu directory.
-icu_dir = os.path.realpath('%s/../external/icu' % bionic_dir)
-icu4c_dir = os.path.realpath('%s/icu4c/source' % icu_dir)
-icu4j_dir = os.path.realpath('%s/icu4j' % icu_dir)
-CheckDirExists(icu4c_dir, 'external/icu/icu4c/source')
-CheckDirExists(icu4j_dir, 'external/icu/icu4j')
-print 'Found icu in %s ...' % icu_dir
-
-
-def GetCurrentTzDataVersion():
-  return open('%s/tzdata' % bionic_libc_zoneinfo_dir).read().split('\x00', 1)[0]
-
-
-def WriteSetupFile():
-  """Writes the list of zones that ZoneCompactor should process."""
-  links = []
-  zones = []
-  for region in regions:
-    for line in open('extracted/%s' % region):
-      fields = line.split()
-      if fields:
-        if fields[0] == 'Link':
-          links.append('%s %s %s' % (fields[0], fields[1], fields[2]))
-          zones.append(fields[2])
-        elif fields[0] == 'Zone':
-          zones.append(fields[1])
-  zones.sort()
-
-  setup = open('setup', 'w')
-  for link in sorted(set(links)):
-    setup.write('%s\n' % link)
-  for zone in sorted(set(zones)):
-    setup.write('%s\n' % zone)
-  setup.close()
-
-
-def SwitchToNewTemporaryDirectory():
-  tmp_dir = tempfile.mkdtemp('-tzdata')
-  os.chdir(tmp_dir)
-  print 'Created temporary directory "%s"...' % tmp_dir
-
-
-def FtpRetrieveFile(ftp, filename):
-  ftp.retrbinary('RETR %s' % filename, open(filename, 'wb').write)
-
-
-def FtpRetrieveFileAndSignature(ftp, data_filename):
-  """Downloads and repackages the given data from the given FTP server."""
-  print 'Downloading data...'
-  FtpRetrieveFile(ftp, data_filename)
-
-  print 'Downloading signature...'
-  signature_filename = '%s.asc' % data_filename
-  FtpRetrieveFile(ftp, signature_filename)
-
-
-def HttpRetrieveFile(http, path, output_filename):
-  http.request("GET", path)
-  f = open(output_filename, 'wb')
-  f.write(http.getresponse().read())
-  f.close()
-
-
-def HttpRetrieveFileAndSignature(http, data_filename):
-  """Downloads and repackages the given data from the given HTTP server."""
-  path = "/time-zones/repository/releases/%s" % data_filename
-
-  print 'Downloading data...'
-  HttpRetrieveFile(http, path, data_filename)
-
-  print 'Downloading signature...'
-  signature_filename = '%s.asc' % data_filename
-  HttpRetrievefile(http, "%s.asc" % path, signature_filename)
-
-
-def BuildIcuToolsAndData(data_filename):
-  # Keep track of the original cwd so we can go back to it at the end.
-  original_working_dir = os.getcwd()
-
-  # Create a directory to run 'make' from.
-  icu_working_dir = '%s/icu' % original_working_dir
-  os.mkdir(icu_working_dir)
-  os.chdir(icu_working_dir)
-
-  # Build the ICU tools.
-  print 'Configuring ICU tools...'
-  subprocess.check_call(['%s/runConfigureICU' % icu4c_dir, 'Linux'])
-
-  # Run the ICU tools.
-  os.chdir('tools/tzcode')
-
-  # The tz2icu tool only picks up icuregions and icuzones in they are in the CWD
-  for icu_data_file in [ 'icuregions', 'icuzones']:
-    icu_data_file_source = '%s/tools/tzcode/%s' % (icu4c_dir, icu_data_file)
-    icu_data_file_symlink = './%s' % icu_data_file
-    os.symlink(icu_data_file_source, icu_data_file_symlink)
-
-  shutil.copyfile('%s/%s' % (original_working_dir, data_filename), data_filename)
-  print 'Making ICU data...'
-  # The Makefile assumes the existence of the bin directory.
-  os.mkdir('%s/bin' % icu_working_dir)
-  subprocess.check_call(['make'])
-
-  # Copy the source file to its ultimate destination.
-  icu_txt_data_dir = '%s/data/misc' % icu4c_dir
-  print 'Copying zoneinfo64.txt to %s ...' % icu_txt_data_dir
-  shutil.copy('zoneinfo64.txt', icu_txt_data_dir)
-
-  # Regenerate the .dat file.
-  os.chdir(icu_working_dir)
-  subprocess.check_call(['make', 'INCLUDE_UNI_CORE_DATA=1', '-j32'])
-
-  # Copy the .dat file to its ultimate destination.
-  icu_dat_data_dir = '%s/stubdata' % icu4c_dir
-  datfiles = glob.glob('data/out/tmp/icudt??l.dat')
-  if len(datfiles) != 1:
-    print 'ERROR: Unexpectedly found %d .dat files (%s). Halting.' % (len(datfiles), datfiles)
-    sys.exit(1)
-  datfile = datfiles[0]
-  print 'Copying %s to %s ...' % (datfile, icu_dat_data_dir)
-  shutil.copy(datfile, icu_dat_data_dir)
-
-  # Generate the ICU4J .jar files
-  os.chdir('%s/data' % icu_working_dir)
-  subprocess.check_call(['make', 'icu4j-data'])
-
-  # Copy the ICU4J .jar files to their ultimate destination.
-  icu_jar_data_dir = '%s/main/shared/data' % icu4j_dir
-  jarfiles = glob.glob('out/icu4j/*.jar')
-  if len(jarfiles) != 2:
-    print 'ERROR: Unexpectedly found %d .jar files (%s). Halting.' % (len(jarfiles), jarfiles)
-    sys.exit(1)
-  for jarfile in jarfiles:
-    print 'Copying %s to %s ...' % (jarfile, icu_jar_data_dir)
-    shutil.copy(jarfile, icu_jar_data_dir)
-
-  # Switch back to the original working cwd.
-  os.chdir(original_working_dir)
-
-
-def CheckSignature(data_filename):
-  signature_filename = '%s.asc' % data_filename
-  print 'Verifying signature...'
-  # If this fails for you, you probably need to import Paul Eggert's public key:
-  # gpg --recv-keys ED97E90E62AA7E34
-  subprocess.check_call(['gpg', '--trusted-key=ED97E90E62AA7E34', '--verify',
-                         signature_filename, data_filename])
-
-
-def BuildBionicToolsAndData(data_filename):
-  new_version = re.search('(tzdata.+)\\.tar\\.gz', data_filename).group(1)
-
-  print 'Extracting...'
-  os.mkdir('extracted')
-  tar = tarfile.open(data_filename, 'r')
-  tar.extractall('extracted')
-
-  print 'Calling zic(1)...'
-  os.mkdir('data')
-  zic_inputs = [ 'extracted/%s' % x for x in regions ]
-  zic_cmd = ['zic', '-d', 'data' ]
-  zic_cmd.extend(zic_inputs)
-  subprocess.check_call(zic_cmd)
-
-  WriteSetupFile()
-
-  print 'Calling ZoneCompactor to update bionic to %s...' % new_version
-  subprocess.check_call(['javac', '-d', '.',
-                         '%s/ZoneCompactor.java' % bionic_libc_tools_zoneinfo_dir])
-  subprocess.check_call(['java', 'ZoneCompactor',
-                         'setup', 'data', 'extracted/zone.tab',
-                         bionic_libc_zoneinfo_dir, new_version])
-
-
-# Run with no arguments from any directory, with no special setup required.
-# See http://www.iana.org/time-zones/ for more about the source of this data.
-def main():
-  print 'Looking for new tzdata...'
-
-  tzdata_filenames = []
-
-  # The FTP server lets you download intermediate releases, and also lets you
-  # download the signatures for verification, so it's your best choice.
-  use_ftp = True
-
-  if use_ftp:
-    ftp = ftplib.FTP('ftp.iana.org')
-    ftp.login()
-    ftp.cwd('tz/releases')
-    for filename in ftp.nlst():
-      if filename.startswith('tzdata20') and filename.endswith('.tar.gz'):
-        tzdata_filenames.append(filename)
-    tzdata_filenames.sort()
-  else:
-    http = httplib.HTTPConnection('www.iana.org')
-    http.request("GET", "/time-zones")
-    index_lines = http.getresponse().read().split('\n')
-    for line in index_lines:
-      m = re.compile('.*href="/time-zones/repository/releases/(tzdata20\d\d\c\.tar\.gz)".*').match(line)
-      if m:
-        tzdata_filenames.append(m.group(1))
-
-  # If you're several releases behind, we'll walk you through the upgrades
-  # one by one.
-  current_version = GetCurrentTzDataVersion()
-  current_filename = '%s.tar.gz' % current_version
-  for filename in tzdata_filenames:
-    if filename > current_filename:
-      print 'Found new tzdata: %s' % filename
-      SwitchToNewTemporaryDirectory()
-      if use_ftp:
-        FtpRetrieveFileAndSignature(ftp, filename)
-      else:
-        HttpRetrieveFileAndSignature(http, filename)
-
-      CheckSignature(filename)
-      BuildIcuToolsAndData(filename)
-      BuildBionicToolsAndData(filename)
-      print 'Look in %s and %s for new data files' % (bionic_dir, icu_dir)
-      sys.exit(0)
-
-  print 'You already have the latest tzdata (%s)!' % current_version
-  sys.exit(0)
-
-
-if __name__ == '__main__':
-  main()
diff --git a/libm/Android.mk b/libm/Android.mk
index 7b28f70..d447417 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -108,8 +108,6 @@
     upstream-freebsd/lib/msun/src/s_exp2.c \
     upstream-freebsd/lib/msun/src/s_exp2f.c \
     upstream-freebsd/lib/msun/src/s_expm1f.c \
-    upstream-freebsd/lib/msun/src/s_fabs.c \
-    upstream-freebsd/lib/msun/src/s_fabsf.c \
     upstream-freebsd/lib/msun/src/s_fdim.c \
     upstream-freebsd/lib/msun/src/s_finite.c \
     upstream-freebsd/lib/msun/src/s_finitef.c \
@@ -175,7 +173,6 @@
     upstream-freebsd/lib/msun/src/s_copysignl.c \
     upstream-freebsd/lib/msun/src/e_coshl.c \
     upstream-freebsd/lib/msun/src/s_cosl.c \
-    upstream-freebsd/lib/msun/src/s_fabsl.c \
     upstream-freebsd/lib/msun/src/s_floorl.c \
     upstream-freebsd/lib/msun/src/s_fmal.c \
     upstream-freebsd/lib/msun/src/s_fmaxl.c \
@@ -228,6 +225,10 @@
 LOCAL_SRC_FILES += \
     signbit.c \
 
+# Home-grown stuff.
+LOCAL_SRC_FILES += \
+    fabs.cpp \
+
 # Arch specific optimizations.
 
 # -----------------------------------------------------------------------------
@@ -481,6 +482,7 @@
 LOCAL_CLANG := $(libm_clang)
 LOCAL_ARM_MODE := arm
 LOCAL_CFLAGS := \
+    -D__BIONIC_NO_MATH_INLINES \
     -DFLT_EVAL_METHOD=0 \
     -include $(LOCAL_PATH)/freebsd-compat.h \
     -Wno-missing-braces \
diff --git a/libm/fabs.cpp b/libm/fabs.cpp
new file mode 100644
index 0000000..add73fe
--- /dev/null
+++ b/libm/fabs.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <math.h>
+
+#include "fpmath.h"
+
+double fabs(double x) {
+#if __arm__
+  // Both Clang and GCC insist on moving r0/r1 into a double register
+  // and using fabs where bit-twiddling would be a better choice.
+  // They get fabsf right, but we need to be careful in fabsl too.
+  IEEEd2bits u;
+  u.d = x;
+  u.bits.sign = 0;
+  return u.d;
+#else
+  return __builtin_fabs(x);
+#endif
+}
+
+float fabsf(float x) {
+  return __builtin_fabsf(x);
+}
+
+#if defined(__LP64__)
+long double fabsl(long double x) { return __builtin_fabsl(x); }
+#else
+long double fabsl(long double x) {
+  // Don't use __builtin_fabs here because of ARM. (See fabs above.)
+  return fabs(x);
+}
+#endif
diff --git a/libm/fake_long_double.c b/libm/fake_long_double.c
index 317a115..5edf839 100644
--- a/libm/fake_long_double.c
+++ b/libm/fake_long_double.c
@@ -25,7 +25,6 @@
  */
 
 long double copysignl(long double a1, long double a2) { return copysign(a1, a2); }
-long double fabsl(long double a1) { return fabs(a1); }
 long double fmaxl(long double a1, long double a2) { return fmax(a1, a2); }
 long double fmodl(long double a1, long double a2) { return fmod(a1, a2); }
 long double fminl(long double a1, long double a2) { return fmin(a1, a2); }
diff --git a/libm/include/math.h b/libm/include/math.h
index bc48b6a..ce8e3b2 100644
--- a/libm/include/math.h
+++ b/libm/include/math.h
@@ -20,6 +20,12 @@
 #include <sys/cdefs.h>
 #include <limits.h>
 
+#if !defined(__BIONIC_NO_MATH_INLINES)
+#define __BIONIC_MATH_INLINE(__def) extern __inline__ __always_inline __attribute__((gnu_inline)) __attribute__((__artificial__)) __def
+#else
+#define __BIONIC_MATH_INLINE(__def)
+#endif
+
 __BEGIN_DECLS
 #pragma GCC visibility push(default)
 
@@ -161,6 +167,7 @@
 
 double	ceil(double);
 double	fabs(double) __pure2;
+__BIONIC_MATH_INLINE(double fabs(double x) { return __builtin_fabs(x); })
 double	floor(double);
 double	fmod(double, double);
 
@@ -279,6 +286,7 @@
 
 float	ceilf(float);
 float	fabsf(float) __pure2;
+__BIONIC_MATH_INLINE(float fabsf(float x) { return __builtin_fabsf(x); })
 float	floorf(float);
 float	fmodf(float, float);
 float	roundf(float);
@@ -366,6 +374,7 @@
 long double	expl(long double);
 long double	expm1l(long double);
 long double	fabsl(long double) __pure2;
+__BIONIC_MATH_INLINE(long double fabsl(long double x) { return __builtin_fabsl(x); })
 long double	fdiml(long double, long double);
 long double	floorl(long double);
 long double	fmal(long double, long double, long double);
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fabs.c b/libm/upstream-freebsd/lib/msun/src/s_fabs.c
deleted file mode 100644
index 15529e5..0000000
--- a/libm/upstream-freebsd/lib/msun/src/s_fabs.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* @(#)s_fabs.c 5.1 93/09/24 */
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-/*
- * fabs(x) returns the absolute value of x.
- */
-
-#include "math.h"
-#include "math_private.h"
-
-double
-fabs(double x)
-{
-	u_int32_t high;
-	GET_HIGH_WORD(high,x);
-	SET_HIGH_WORD(x,high&0x7fffffff);
-        return x;
-}
diff --git a/libm/upstream-freebsd/lib/msun/src/s_fabsf.c b/libm/upstream-freebsd/lib/msun/src/s_fabsf.c
deleted file mode 100644
index e9383d0..0000000
--- a/libm/upstream-freebsd/lib/msun/src/s_fabsf.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/* s_fabsf.c -- float version of s_fabs.c.
- * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
- */
-
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * fabsf(x) returns the absolute value of x.
- */
-
-#include "math.h"
-#include "math_private.h"
-
-float
-fabsf(float x)
-{
-	u_int32_t ix;
-	GET_FLOAT_WORD(ix,x);
-	SET_FLOAT_WORD(x,ix&0x7fffffff);
-        return x;
-}
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index cf012f4..30bc6fa 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -382,7 +382,7 @@
       return false;
     }
 
-    if (file_end >= static_cast<size_t>(file_size_)) {
+    if (file_end > static_cast<size_t>(file_size_)) {
       DL_ERR("invalid ELF file \"%s\" load segment[%zd]:"
           " p_offset (%p) + p_filesz (%p) ( = %p) past end of file (0x%" PRIx64 ")",
           name_, i, reinterpret_cast<void*>(phdr->p_offset),
diff --git a/tests/fortify_compilation_test.cpp b/tests/fortify_compilation_test.cpp
index 072006e..1326597 100644
--- a/tests/fortify_compilation_test.cpp
+++ b/tests/fortify_compilation_test.cpp
@@ -21,6 +21,7 @@
 #include <poll.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
@@ -248,7 +249,7 @@
 }
 
 void test_fwrite_overflow() {
-  char buf[4];
+  char buf[4] = {0};
   // NOLINTNEXTLINE(whitespace/line_length)
   // GCC: error: call to '__fwrite_overflow' declared with attribute error: fwrite called with overflowing size * count
   // clang should emit a warning, but doesn't
@@ -270,3 +271,27 @@
   // clang should emit a warning, but doesn't
   getcwd(buf, 5);
 }
+
+void test_pwrite64_size() {
+  char buf[4] = {0};
+  // NOLINTNEXTLINE(whitespace/line_length)
+  // GCC: error: call to '__pwrite64_dest_size_error' declared with attribute error: pwrite64 called with size bigger than destination
+  // clang should emit a warning, but doesn't
+  pwrite64(STDOUT_FILENO, buf, 5, 0);
+}
+
+void test_pwrite64_too_big() {
+  void *buf = calloc(atoi("5"), 1);
+  // NOLINTNEXTLINE(whitespace/line_length)
+  // GCC: error: call to '__pwrite64_count_toobig_error' declared with attribute error: pwrite64 called with count > SSIZE_MAX
+  // clang should emit a warning, but doesn't
+  pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0);
+}
+
+void test_write_size() {
+  char buf[4] = {0};
+  // NOLINTNEXTLINE(whitespace/line_length)
+  // GCC: error: call to '__write_dest_size_error' declared with attribute error: write called with size bigger than destination
+  // clang should emit a warning, but doesn't
+  write(STDOUT_FILENO, buf, 5);
+}
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 8f66cc8..a349da9 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -645,6 +645,22 @@
   close(fd);
 }
 
+TEST_F(DEATHTEST, pwrite_fortified) {
+  char buf[1] = {0};
+  size_t ct = atoi("2"); // prevent optimizations
+  int fd = open("/dev/null", O_WRONLY);
+  ASSERT_FORTIFY(pwrite(fd, buf, ct, 0));
+  close(fd);
+}
+
+TEST_F(DEATHTEST, pwrite64_fortified) {
+  char buf[1] = {0};
+  size_t ct = atoi("2"); // prevent optimizations
+  int fd = open("/dev/null", O_WRONLY);
+  ASSERT_FORTIFY(pwrite64(fd, buf, ct, 0));
+  close(fd);
+}
+
 TEST_F(DEATHTEST, read_fortified) {
   char buf[1];
   size_t ct = atoi("2"); // prevent optimizations
@@ -653,6 +669,14 @@
   close(fd);
 }
 
+TEST_F(DEATHTEST, write_fortified) {
+  char buf[1] = {0};
+  size_t ct = atoi("2"); // prevent optimizations
+  int fd = open("/dev/null", O_WRONLY);
+  ASSERT_EXIT(write(fd, buf, ct), testing::KilledBySignal(SIGABRT), "");
+  close(fd);
+}
+
 TEST_F(DEATHTEST, fread_fortified) {
   char buf[1];
   size_t ct = atoi("2"); // prevent optimizations