Merge "bionic: Replace iface with opaque netid in resolver."
diff --git a/libc/Android.mk b/libc/Android.mk
index 3faa47f..44bf388 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -292,6 +292,7 @@
     upstream-netbsd/lib/libc/stdlib/ldiv.c \
     upstream-netbsd/lib/libc/stdlib/lldiv.c \
     upstream-netbsd/lib/libc/stdlib/lrand48.c \
+    upstream-netbsd/lib/libc/stdlib/lsearch.c \
     upstream-netbsd/lib/libc/stdlib/mrand48.c \
     upstream-netbsd/lib/libc/stdlib/nrand48.c \
     upstream-netbsd/lib/libc/stdlib/_rand48.c \
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index 89a1ce0..cbc5fa7 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -70,7 +70,7 @@
 endif
 cpu_variant_mk := $(LOCAL_PATH)/arch-arm/$(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT)/$(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT).mk
 ifeq ($(wildcard $(cpu_variant_mk)),)
-$(error "TARGET_$(my_2nd_arch_prefix)CPU_VARIANT not set or set to an unknown value. Possible values are cortex-a7, cortex-a8, cortex-a9, cortex-a15, krait. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
+$(error "TARGET_$(my_2nd_arch_prefix)CPU_VARIANT not set or set to an unknown value. Possible values are cortex-a7, cortex-a8, cortex-a9, cortex-a15, krait, denver. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
 endif
 include $(cpu_variant_mk)
 libc_common_additional_dependencies += $(cpu_variant_mk)
diff --git a/libc/arch-arm/denver/bionic/__strcat_chk.S b/libc/arch-arm/denver/bionic/__strcat_chk.S
new file mode 100644
index 0000000..36da2d9
--- /dev/null
+++ b/libc/arch-arm/denver/bionic/__strcat_chk.S
@@ -0,0 +1,221 @@
+/*
+ * 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}
+    .save   {r0, lr}
+    .cfi_def_cfa_offset 8
+    .cfi_rel_offset r0, 0
+    .cfi_rel_offset lr, 4
+    push    {r4, r5}
+    .save   {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)
+    .save   {r0, lr}
+    .save   {r4, r5}
+
+    .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"
diff --git a/libc/arch-arm/denver/bionic/__strcpy_chk.S b/libc/arch-arm/denver/bionic/__strcpy_chk.S
new file mode 100644
index 0000000..c3e3e14
--- /dev/null
+++ b/libc/arch-arm/denver/bionic/__strcpy_chk.S
@@ -0,0 +1,182 @@
+/*
+ * 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}
+    .save   {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)
+    .save   {r0, lr}
+    .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"
diff --git a/libc/arch-arm/denver/bionic/memcpy.S b/libc/arch-arm/denver/bionic/memcpy.S
new file mode 100644
index 0000000..da4f3dd
--- /dev/null
+++ b/libc/arch-arm/denver/bionic/memcpy.S
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+// Prototype: void *memcpy (void *dst, const void *src, size_t count).
+
+#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}
+        .save   {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}
+        .save   {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"
diff --git a/libc/arch-arm/denver/bionic/memcpy_base.S b/libc/arch-arm/denver/bionic/memcpy_base.S
new file mode 100644
index 0000000..2abb486
--- /dev/null
+++ b/libc/arch-arm/denver/bionic/memcpy_base.S
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ * Copyright (c) 2013-2014, NVIDIA Corporation.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define CACHE_LINE_SIZE         (64)
+#define PREFETCH_DISTANCE       (CACHE_LINE_SIZE*6)
+
+ENTRY_PRIVATE(MEMCPY_BASE)
+        .cfi_def_cfa_offset 8
+        .cfi_rel_offset r0, 0
+        .cfi_rel_offset lr, 4
+
+        cmp         r2, #0
+        beq         .L_memcpy_done
+        cmp         r0, r1
+        beq         .L_memcpy_done
+
+        /* preload next cache line */
+        pld         [r1, #CACHE_LINE_SIZE*1]
+
+        /* Deal with very small blocks (< 32bytes) asap */
+        cmp         r2, #32
+        blo         .L_memcpy_lt_32bytes
+        /* no need to align if len < 128 bytes */
+        cmp         r2, #128
+        blo         .L_memcpy_lt_128bytes
+
+        /* large copy, align dest to 64 byte boundry */
+        pld         [r1, #CACHE_LINE_SIZE*2]
+        rsb         r3, r0, #0
+        ands        r3, r3, #0x3F
+        pld         [r1, #CACHE_LINE_SIZE*3]
+        beq         .L_memcpy_dispatch
+        sub         r2, r2, r3
+        /* copy 1 byte */
+        movs        ip, r3, lsl #31
+        itt         mi
+        ldrbmi      ip, [r1], #1
+        strbmi      ip, [r0], #1
+        /* copy 2 bytes */
+        itt         cs
+        ldrhcs      ip, [r1], #2
+        strhcs      ip, [r0], #2
+        /* copy 4 bytes */
+        movs        ip, r3, lsl #29
+        itt         mi
+        ldrmi       ip, [r1], #4
+        strmi       ip, [r0], #4
+        /* copy 8 bytes */
+        bcc         1f
+        vld1.8      {d0}, [r1]!
+        vst1.8      {d0}, [r0, :64]!
+1:      /* copy 16 bytes */
+        movs        ip, r3, lsl #27
+        bpl         1f
+        vld1.8      {q0}, [r1]!
+        vst1.8      {q0}, [r0, :128]!
+1:      /* copy 32 bytes */
+        bcc         .L_memcpy_dispatch
+        vld1.8      {q0, q1}, [r1]!
+        vst1.8      {q0, q1}, [r0, :256]!
+
+.L_memcpy_dispatch:
+        // pre-decrement by 128 to detect nearly-done condition easily, but
+        // also need to check if we have less than 128 bytes left at this
+        // point due to alignment code above
+        subs        r2, r2, #128
+        blo         .L_memcpy_lt_128presub
+
+        // Denver does better if both source and dest are aligned so
+        // we'll special-case that even though the code is virually identical
+        tst         r1, #0xF
+        bne         .L_memcpy_neon_unalign_src_pld
+
+        // DRAM memcpy should be throttled slightly to get full bandwidth
+        //
+        cmp         r2, #32768
+        bhi         .L_memcpy_neon_unalign_src_pld
+        .align      4
+1:
+        /* copy 128 bytes in each loop */
+        subs        r2, r2, #128
+
+        /* preload a cache line */
+        pld         [r1, #PREFETCH_DISTANCE]
+        /* copy a cache line */
+        vld1.8      {q0, q1}, [r1, :128]!
+        vst1.8      {q0, q1}, [r0, :256]!
+        vld1.8      {q0, q1}, [r1, :128]!
+        vst1.8      {q0, q1}, [r0, :256]!
+        /* preload a cache line */
+        pld         [r1, #PREFETCH_DISTANCE]
+        /* copy a cache line */
+        vld1.8      {q0, q1}, [r1, :128]!
+        vst1.8      {q0, q1}, [r0, :256]!
+        vld1.8      {q0, q1}, [r1, :128]!
+        vst1.8      {q0, q1}, [r0, :256]!
+
+        bhs         1b
+        adds        r2, r2, #128
+        bne         .L_memcpy_lt_128bytes_align
+        pop         {r0, pc}
+
+        .align      4
+.L_memcpy_neon_unalign_src_pld:
+1:
+        /* copy 128 bytes in each loop */
+        subs        r2, r2, #128
+
+        /* preload a cache line */
+        pld         [r1, #PREFETCH_DISTANCE]
+        /* copy a cache line */
+        vld1.8      {q0, q1}, [r1]!
+        vst1.8      {q0, q1}, [r0, :256]!
+        vld1.8      {q0, q1}, [r1]!
+        vst1.8      {q0, q1}, [r0, :256]!
+        /* preload a cache line */
+        pld         [r1, #PREFETCH_DISTANCE]
+        /* copy a cache line */
+        vld1.8      {q0, q1}, [r1]!
+        vst1.8      {q0, q1}, [r0, :256]!
+        vld1.8      {q0, q1}, [r1]!
+        vst1.8      {q0, q1}, [r0, :256]!
+
+        bhs         1b
+        adds        r2, r2, #128
+        bne         .L_memcpy_lt_128bytes_align
+        pop         {r0, pc}
+
+.L_memcpy_lt_128presub:
+        add         r2, r2, #128
+.L_memcpy_lt_128bytes_align:
+        /* copy 64 bytes */
+        movs        ip, r2, lsl #26
+        bcc         1f
+        vld1.8      {q0, q1}, [r1]!
+        vst1.8      {q0, q1}, [r0, :256]!
+        vld1.8      {q0, q1}, [r1]!
+        vst1.8      {q0, q1}, [r0, :256]!
+1:      /* copy 32 bytes */
+        bpl         1f
+        vld1.8      {q0, q1}, [r1]!
+        vst1.8      {q0, q1}, [r0, :256]!
+1:      /* copy 16 bytes */
+        movs        ip, r2, lsl #28
+        bcc         1f
+        vld1.8      {q0}, [r1]!
+        vst1.8      {q0}, [r0, :128]!
+1:      /* copy 8 bytes */
+        bpl         1f
+        vld1.8      {d0}, [r1]!
+        vst1.8      {d0}, [r0, :64]!
+1:      /* copy 4 bytes */
+        tst         r2, #4
+        itt         ne
+        ldrne       ip, [r1], #4
+        strne       ip, [r0], #4
+        /* copy 2 bytes */
+        movs        ip, r2, lsl #31
+        itt         cs
+        ldrhcs      ip, [r1], #2
+        strhcs      ip, [r0], #2
+        /* copy 1 byte */
+        itt         mi
+        ldrbmi      ip, [r1]
+        strbmi      ip, [r0]
+
+        pop         {r0, pc}
+
+.L_memcpy_lt_128bytes:
+        /* copy 64 bytes */
+        movs        ip, r2, lsl #26
+        bcc         1f
+        vld1.8      {q0, q1}, [r1]!
+        vst1.8      {q0, q1}, [r0]!
+        vld1.8      {q0, q1}, [r1]!
+        vst1.8      {q0, q1}, [r0]!
+1:      /* copy 32 bytes */
+        bpl	    .L_memcpy_lt_32bytes
+        vld1.8      {q0, q1}, [r1]!
+        vst1.8      {q0, q1}, [r0]!
+.L_memcpy_lt_32bytes:
+        /* copy 16 bytes */
+        movs        ip, r2, lsl #28
+        bcc         1f
+        vld1.8      {q0}, [r1]!
+        vst1.8      {q0}, [r0]!
+1:      /* copy 8 bytes */
+        bpl         1f
+        vld1.8      {d0}, [r1]!
+        vst1.8      {d0}, [r0]!
+1:      /* copy 4 bytes */
+        tst         r2, #4
+        itt         ne
+        ldrne       ip, [r1], #4
+        strne       ip, [r0], #4
+        /* copy 2 bytes */
+        movs        ip, r2, lsl #31
+        itt         cs
+        ldrhcs      ip, [r1], #2
+        strhcs      ip, [r0], #2
+        /* copy 1 byte */
+        itt         mi
+        ldrbmi      ip, [r1]
+        strbmi      ip, [r0]
+
+.L_memcpy_done:
+        pop         {r0, pc}
+END(MEMCPY_BASE)
diff --git a/libc/arch-arm/denver/bionic/memset.S b/libc/arch-arm/denver/bionic/memset.S
new file mode 100644
index 0000000..bf3d9ad
--- /dev/null
+++ b/libc/arch-arm/denver/bionic/memset.S
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ * 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)
+        pldw        [r0]
+        mov         r3, r0
+
+        // Duplicate the low byte of r1
+        mov         r1, r1, lsl #24
+        orr         r1, r1, r1, lsr #8
+        orr         r1, r1, r1, lsr #16
+
+        cmp         r2, #16
+        blo         .L_less_than_16
+
+        // This section handles regions 16 bytes or larger
+        //
+        // Use aligned vst1.8 and vstm when possible.  Register values will be:
+        //   ip is scratch
+        //   q0, q1, and r1 contain the memset value
+        //   r2 is the number of bytes to set
+        //   r3 is the advancing destination pointer
+        vdup.32     q0, r1
+
+        ands        ip, r3, 0xF
+        beq         .L_memset_aligned
+
+        // Align dest pointer to 16-byte boundary.
+        pldw        [r0, #64]
+        rsb         ip, ip, #16
+
+        // Pre-adjust the byte count to reflect post-aligment value.  Expecting
+        // 8-byte alignment to be rather common so we special case that one.
+        sub         r2, r2, ip
+
+        /* set 1 byte */
+        tst         ip, #1
+        it          ne
+        strbne      r1, [r3], #1
+        /* set 2 bytes */
+        tst         ip, #2
+        it          ne
+        strhne      r1, [r3], #2
+        /* set 4 bytes */
+        movs        ip, ip, lsl #29
+        it          mi
+        strmi       r1, [r3], #4
+        /* set 8 bytes */
+        itt         cs
+        strcs       r1, [r3], #4
+        strcs       r1, [r3], #4
+
+.L_memset_aligned:
+        // Destination is now 16-byte aligned.  Determine how to handle
+        // remaining bytes.
+        vmov        q1, q0
+        cmp         r2, #128
+        blo         .L_less_than_128
+
+        // We need to set a larger block of memory.  Use four Q regs to
+        // set a full cache line in one instruction.  Pre-decrement
+        // r2 to simplify end-of-loop detection
+        vmov        q2, q0
+        vmov        q3, q0
+        pldw        [r0, #128]
+        sub         r2, r2, #128
+        .align 4
+.L_memset_loop_128:
+        pldw        [r3, #192]
+        vstm        r3!, {q0, q1, q2, q3}
+        vstm        r3!, {q0, q1, q2, q3}
+        subs        r2, r2, #128
+        bhs         .L_memset_loop_128
+
+        // Un-bias r2 so it contains the number of bytes left.  Early
+        // exit if we are done.
+        adds        r2, r2, #128
+        beq         2f
+
+        .align 4
+.L_less_than_128:
+        // set 64 bytes
+        movs        ip, r2, lsl #26
+        bcc         1f
+        vst1.8      {q0, q1}, [r3, :128]!
+        vst1.8      {q0, q1}, [r3, :128]!
+        beq         2f
+1:
+        // set 32 bytes
+        bpl         1f
+        vst1.8      {q0, q1}, [r3, :128]!
+1:
+        // set 16 bytes
+        movs        ip, r2, lsl #28
+        bcc         1f
+        vst1.8      {q0}, [r3, :128]!
+        beq         2f
+1:
+        // set 8 bytes
+        bpl         1f
+        vst1.8      {d0}, [r3, :64]!
+1:
+        // set 4 bytes
+        tst         r2, #4
+        it          ne
+        strne       r1, [r3], #4
+1:
+        // set 2 bytes
+        movs        ip, r2, lsl #31
+        it          cs
+        strhcs      r1, [r3], #2
+        // set 1 byte
+        it          mi
+        strbmi      r1, [r3]
+2:
+        bx          lr
+
+.L_less_than_16:
+        // Store up to 15 bytes without worrying about byte alignment
+        movs        ip, r2, lsl #29
+        bcc         1f
+        str         r1, [r3], #4
+        str         r1, [r3], #4
+        beq         2f
+1:
+        it          mi
+        strmi       r1, [r3], #4
+        movs        ip, r2, lsl #31
+        it          mi
+        strbmi      r1, [r3], #1
+        itt         cs
+        strbcs      r1, [r3], #1
+        strbcs      r1, [r3]
+2:
+        bx          lr
+END(memset)
+
+        .data
+error_string:
+        .string     "memset: prevented write past end of buffer"
diff --git a/libc/arch-arm/denver/denver.mk b/libc/arch-arm/denver/denver.mk
new file mode 100644
index 0000000..3fcc457
--- /dev/null
+++ b/libc/arch-arm/denver/denver.mk
@@ -0,0 +1,12 @@
+libc_bionic_src_files_arm += \
+    arch-arm/denver/bionic/memcpy.S \
+    arch-arm/denver/bionic/memset.S \
+    arch-arm/denver/bionic/__strcat_chk.S \
+    arch-arm/denver/bionic/__strcpy_chk.S
+
+# Use cortex-a15 versions of strcat/strcpy/strlen.
+libc_bionic_src_files_arm += \
+    arch-arm/cortex-a15/bionic/strcat.S \
+    arch-arm/cortex-a15/bionic/strcpy.S \
+    arch-arm/cortex-a15/bionic/strlen.S \
+    arch-arm/cortex-a15/bionic/strcmp.S
diff --git a/libc/arch-arm/include/machine/limits.h b/libc/arch-arm/include/machine/limits.h
deleted file mode 100644
index f9c04fa..0000000
--- a/libc/arch-arm/include/machine/limits.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*	$OpenBSD: limits.h,v 1.3 2006/01/06 22:48:46 millert Exp $	*/
-/*	$NetBSD: limits.h,v 1.4 2003/04/28 23:16:18 bjh21 Exp $	*/
-
-/*
- * Copyright (c) 1988 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	from: @(#)limits.h	7.2 (Berkeley) 6/28/90
- */
-
-#ifndef	_ARM32_LIMITS_H_
-#define	_ARM32_LIMITS_H_
-
-#include <sys/cdefs.h>
-
-#define	MB_LEN_MAX	1		/* no multibyte characters */
-
-#ifndef	SIZE_MAX
-#define	SIZE_MAX	UINT_MAX	/* max value for a size_t */
-#endif
-#ifndef SSIZE_MAX
-#define	SSIZE_MAX	INT_MAX		/* max value for a ssize_t */
-#endif
-
-#if __BSD_VISIBLE
-#define	SIZE_T_MAX	UINT_MAX	/* max value for a size_t (historic) */
-
-#define	UQUAD_MAX	0xffffffffffffffffULL		/* max unsigned quad */
-#define	QUAD_MAX	0x7fffffffffffffffLL		/* max signed quad */
-#define	QUAD_MIN	(-0x7fffffffffffffffLL-1)	/* min signed quad */
-
-#endif /* __BSD_VISIBLE */
-
-#define LONGLONG_BIT    64
-#define LONGLONG_MIN    (-9223372036854775807LL-1)
-#define LONGLONG_MAX    9223372036854775807LL
-#define ULONGLONG_MAX   18446744073709551615ULL
-
-#endif	/* _ARM32_LIMITS_H_ */
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 88da1f3..7b6b1c3 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -14,6 +14,11 @@
     upstream-freebsd/lib/libc/string/wcslen.c \
     upstream-freebsd/lib/libc/string/wcsrchr.c \
     upstream-freebsd/lib/libc/string/wmemcmp.c \
+    upstream-openbsd/lib/libc/locale/_def_numeric.c \
+    upstream-openbsd/lib/libc/locale/_def_messages.c \
+    upstream-openbsd/lib/libc/locale/_def_monetary.c \
+    upstream-openbsd/lib/libc/locale/_def_time.c \
+    upstream-openbsd/lib/libc/locale/localeconv.c \
     upstream-openbsd/lib/libc/string/bcopy.c \
     upstream-openbsd/lib/libc/string/strcat.c \
     upstream-openbsd/lib/libc/string/strcpy.c \
diff --git a/libc/arch-arm64/include/machine/limits.h b/libc/arch-arm64/include/machine/limits.h
deleted file mode 100644
index ecddb01..0000000
--- a/libc/arch-arm64/include/machine/limits.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*	$OpenBSD: limits.h,v 1.3 2006/01/06 22:48:46 millert Exp $	*/
-/*	$NetBSD: limits.h,v 1.4 2003/04/28 23:16:18 bjh21 Exp $	*/
-
-/*
- * Copyright (c) 1988 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	from: @(#)limits.h	7.2 (Berkeley) 6/28/90
- */
-
-#ifndef _AARCH64_LIMITS_H_
-#define _AARCH64_LIMITS_H_
-
-#include <sys/cdefs.h>
-
-#define	MB_LEN_MAX	1		/* no multibyte characters */
-
-#define	LONGLONG_BIT	64
-#define	LONGLONG_MIN	(-9223372036854775807LL-1)
-#define	LONGLONG_MAX	9223372036854775807LL
-#define	ULONGLONG_MAX	18446744073709551615ULL
-
-#ifndef	SIZE_MAX
-#define	SIZE_MAX	ULONGLONG_MAX	/* max value for a size_t */
-#endif
-#ifndef SSIZE_MAX
-#define	SSIZE_MAX	LONGLONG_MAX		/* max value for a ssize_t */
-#endif
-
-#if __BSD_VISIBLE
-#define	SIZE_T_MAX	ULONG_MAX	/* max value for a size_t (historic) */
-
-#define	UQUAD_MAX	0xffffffffffffffffULL		/* max unsigned quad */
-#define	QUAD_MAX	0x7fffffffffffffffLL		/* max signed quad */
-#define	QUAD_MIN	(-0x7fffffffffffffffLL-1)	/* min signed quad */
-
-#endif /* __BSD_VISIBLE */
-#endif /* _AARCH64_LIMITS_H_ */
diff --git a/libc/arch-mips/include/machine/limits.h b/libc/arch-mips/include/machine/limits.h
deleted file mode 100644
index 339444d..0000000
--- a/libc/arch-mips/include/machine/limits.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*	$OpenBSD: limits.h,v 1.5 2007/05/07 20:51:07 kettenis Exp $	*/
-
-/*
- * Copyright (c) 1988, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)limits.h	8.3 (Berkeley) 1/4/94
- */
-
-#ifndef _MIPS_LIMITS_H_
-#define _MIPS_LIMITS_H_
-
-#include <sys/cdefs.h>
-
-#define	MB_LEN_MAX	6		/* Allow 31 bit UTF2 */
-
-#ifndef	SIZE_MAX
-#define	SIZE_MAX	ULONG_MAX	/* max value for a size_t */
-#endif
-#define	SSIZE_MAX	LONG_MAX	/* max value for a ssize_t */
-
-#if __BSD_VISIBLE
-#define	SIZE_T_MAX	ULONG_MAX	/* max value for a size_t (historic) */
-
-/* Quads and longs are the same on mips64 */
-#define	UQUAD_MAX	(ULONG_MAX)	/* max value for a uquad_t */
-#define	QUAD_MAX	(LONG_MAX)	/* max value for a quad_t */
-#define	QUAD_MIN	(LONG_MIN)	/* min value for a quad_t */
-
-#endif /* __BSD_VISIBLE */
-
-
-#define LONGLONG_BIT    64
-#define LONGLONG_MIN    (-9223372036854775807LL-1)
-#define LONGLONG_MAX    9223372036854775807LL
-#define ULONGLONG_MAX   18446744073709551615ULL
-
-#endif /* !_MIPS_LIMITS_H_ */
diff --git a/libc/arch-mips64/include/machine/limits.h b/libc/arch-mips64/include/machine/limits.h
deleted file mode 100644
index 339444d..0000000
--- a/libc/arch-mips64/include/machine/limits.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*	$OpenBSD: limits.h,v 1.5 2007/05/07 20:51:07 kettenis Exp $	*/
-
-/*
- * Copyright (c) 1988, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)limits.h	8.3 (Berkeley) 1/4/94
- */
-
-#ifndef _MIPS_LIMITS_H_
-#define _MIPS_LIMITS_H_
-
-#include <sys/cdefs.h>
-
-#define	MB_LEN_MAX	6		/* Allow 31 bit UTF2 */
-
-#ifndef	SIZE_MAX
-#define	SIZE_MAX	ULONG_MAX	/* max value for a size_t */
-#endif
-#define	SSIZE_MAX	LONG_MAX	/* max value for a ssize_t */
-
-#if __BSD_VISIBLE
-#define	SIZE_T_MAX	ULONG_MAX	/* max value for a size_t (historic) */
-
-/* Quads and longs are the same on mips64 */
-#define	UQUAD_MAX	(ULONG_MAX)	/* max value for a uquad_t */
-#define	QUAD_MAX	(LONG_MAX)	/* max value for a quad_t */
-#define	QUAD_MIN	(LONG_MIN)	/* min value for a quad_t */
-
-#endif /* __BSD_VISIBLE */
-
-
-#define LONGLONG_BIT    64
-#define LONGLONG_MIN    (-9223372036854775807LL-1)
-#define LONGLONG_MAX    9223372036854775807LL
-#define ULONGLONG_MAX   18446744073709551615ULL
-
-#endif /* !_MIPS_LIMITS_H_ */
diff --git a/libc/arch-mips64/mips64.mk b/libc/arch-mips64/mips64.mk
index 28806e1..9b29f0d 100644
--- a/libc/arch-mips64/mips64.mk
+++ b/libc/arch-mips64/mips64.mk
@@ -16,6 +16,11 @@
     upstream-freebsd/lib/libc/string/wcslen.c \
     upstream-freebsd/lib/libc/string/wcsrchr.c \
     upstream-freebsd/lib/libc/string/wmemcmp.c \
+    upstream-openbsd/lib/libc/locale/_def_numeric.c \
+    upstream-openbsd/lib/libc/locale/_def_messages.c \
+    upstream-openbsd/lib/libc/locale/_def_monetary.c \
+    upstream-openbsd/lib/libc/locale/_def_time.c \
+    upstream-openbsd/lib/libc/locale/localeconv.c \
     upstream-openbsd/lib/libc/string/bcopy.c \
     upstream-openbsd/lib/libc/string/strcat.c \
     upstream-openbsd/lib/libc/string/strcmp.c \
diff --git a/libc/arch-x86/include/machine/limits.h b/libc/arch-x86/include/machine/limits.h
deleted file mode 100644
index 86fd854..0000000
--- a/libc/arch-x86/include/machine/limits.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*	$OpenBSD: limits.h,v 1.11 2006/01/06 22:48:47 millert Exp $	*/
-/*	$NetBSD: limits.h,v 1.11 1995/12/21 01:08:59 mycroft Exp $	*/
-
-/*
- * Copyright (c) 1988 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)limits.h	7.2 (Berkeley) 6/28/90
- */
-
-#ifndef _MACHINE_LIMITS_H_
-#define _MACHINE_LIMITS_H_
-
-#include <sys/cdefs.h>
-
-#define	MB_LEN_MAX	1		/* no multibyte characters */
-
-#ifndef	SIZE_MAX
-#define	SIZE_MAX	UINT_MAX	/* max value for a size_t */
-#endif
-#ifndef SSIZE_MAX
-#define	SSIZE_MAX	INT_MAX		/* max value for a ssize_t */
-#endif
-
-#if __BSD_VISIBLE
-#define	SIZE_T_MAX	UINT_MAX	/* max value for a size_t (historic) */
-
-#define	UQUAD_MAX	0xffffffffffffffffULL		/* max unsigned quad */
-#define	QUAD_MAX	0x7fffffffffffffffLL		/* max signed quad */
-#define	QUAD_MIN	(-0x7fffffffffffffffLL-1)	/* min signed quad */
-
-#endif /* __BSD_VISIBLE */
-
-#define LONGLONG_BIT    64
-#define LONGLONG_MIN    (-9223372036854775807LL-1)
-#define LONGLONG_MAX    9223372036854775807LL
-#define ULONGLONG_MAX   18446744073709551615ULL
-
-#endif /* _MACHINE_LIMITS_H_ */
diff --git a/libc/arch-x86/string/cache.h b/libc/arch-x86/string/cache.h
index d9aff5c..9d0a563 100644
--- a/libc/arch-x86/string/cache.h
+++ b/libc/arch-x86/string/cache.h
@@ -28,8 +28,15 @@
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#if defined(__slm__)
+/* Values are optimized for Silvermont */
+#define SHARED_CACHE_SIZE	(1024*1024)			/* Silvermont L2 Cache */
+#define DATA_CACHE_SIZE		(24*1024)			/* Silvermont L1 Data Cache */
+#else
 /* Values are optimized for Atom */
 #define SHARED_CACHE_SIZE	(512*1024)			/* Atom L2 Cache */
 #define DATA_CACHE_SIZE		(24*1024)			/* Atom L1 Data Cache */
+#endif
+
 #define SHARED_CACHE_SIZE_HALF	(SHARED_CACHE_SIZE / 2)
 #define DATA_CACHE_SIZE_HALF	(DATA_CACHE_SIZE / 2)
diff --git a/libc/arch-x86_64/include/machine/limits.h b/libc/arch-x86_64/include/machine/limits.h
deleted file mode 100644
index a8c4a88..0000000
--- a/libc/arch-x86_64/include/machine/limits.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*	$OpenBSD: limits.h,v 1.5 2009/11/27 19:54:35 guenther Exp $	*/
-
-/*
- * Copyright (c) 1988 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)limits.h	7.2 (Berkeley) 6/28/90
- */
-
-#ifndef	_MACHINE_LIMITS_H_
-#define	_MACHINE_LIMITS_H_
-
-#include <sys/cdefs.h>
-
-#if __POSIX_VISIBLE || __XPG_VISIBLE
-#ifndef	SIZE_MAX
-#define SIZE_MAX	ULONG_MAX	/* max value for a size_t */
-#endif
-#define SSIZE_MAX	LONG_MAX	/* max value for a ssize_t */
-#endif
-
-#if __BSD_VISIBLE
-#define	SIZE_T_MAX	ULONG_MAX	/* max value for a size_t (historic) */
-
-#define	UQUAD_MAX	0xffffffffffffffffULL		/* max unsigned quad */
-#define	QUAD_MAX	0x7fffffffffffffffLL		/* max signed quad */
-#define	QUAD_MIN	(-0x7fffffffffffffffLL-1)	/* min signed quad */
-
-#endif /* __BSD_VISIBLE */
-
-#endif /* _MACHINE_LIMITS_H_ */
diff --git a/libc/arch-x86_64/x86_64.mk b/libc/arch-x86_64/x86_64.mk
index 9bce065..a3adaa4 100644
--- a/libc/arch-x86_64/x86_64.mk
+++ b/libc/arch-x86_64/x86_64.mk
@@ -18,6 +18,11 @@
     upstream-freebsd/lib/libc/string/wcslen.c \
     upstream-freebsd/lib/libc/string/wcsrchr.c \
     upstream-freebsd/lib/libc/string/wmemcmp.c \
+    upstream-openbsd/lib/libc/locale/_def_numeric.c \
+    upstream-openbsd/lib/libc/locale/_def_messages.c \
+    upstream-openbsd/lib/libc/locale/_def_monetary.c \
+    upstream-openbsd/lib/libc/locale/_def_time.c \
+    upstream-openbsd/lib/libc/locale/localeconv.c \
     upstream-openbsd/lib/libc/string/bcopy.c \
     upstream-openbsd/lib/libc/string/strcat.c \
     upstream-openbsd/lib/libc/string/strcmp.c \
diff --git a/libc/bionic/malloc_debug_common.cpp b/libc/bionic/malloc_debug_common.cpp
index 85f7791..4fa4b6e 100644
--- a/libc/bionic/malloc_debug_common.cpp
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -379,7 +379,7 @@
             if (gMallocDebugBacklog == 0) {
                 gMallocDebugBacklog = BACKLOG_DEFAULT_LEN;
             }
-            so_name = "/system/lib/libc_malloc_debug_leak.so";
+            so_name = "libc_malloc_debug_leak.so";
             break;
         }
         case 20:
@@ -395,7 +395,7 @@
                           __progname);
                 return;
             }
-            so_name = "/system/lib/libc_malloc_debug_qemu.so";
+            so_name = "libc_malloc_debug_qemu.so";
             break;
         default:
             error_log("%s: Debug level %d is unknown\n", __progname, gMallocDebugLevel);
diff --git a/libc/bionic/posix_timers.cpp b/libc/bionic/posix_timers.cpp
index e9190b2..59933ec 100644
--- a/libc/bionic/posix_timers.cpp
+++ b/libc/bionic/posix_timers.cpp
@@ -63,7 +63,6 @@
   pthread_t callback_thread;
   void (*callback)(sigval_t);
   sigval_t callback_argument;
-  volatile int exiting;
 };
 
 static __kernel_timer_t to_kernel_timer_id(timer_t timer) {
@@ -90,8 +89,7 @@
       timer->callback(timer->callback_argument);
     } else if (si.si_code == SI_TKILL) {
       // This signal was sent because someone wants us to exit.
-      timer->exiting = 1;
-      __futex_wake(&timer->exiting, INT32_MAX);
+      free(timer);
       return NULL;
     }
   }
@@ -99,46 +97,35 @@
 
 static void __timer_thread_stop(PosixTimer* timer) {
   pthread_kill(timer->callback_thread, TIMER_SIGNAL);
-
-  // If this is being called from within the callback thread, do nothing else.
-  if (pthread_self() != timer->callback_thread) {
-    // We can't pthread_join because POSIX says "the threads created in response to a timer
-    // expiration are created detached, or in an unspecified way if the thread attribute's
-    // detachstate is PTHREAD_CREATE_JOINABLE".
-    while (timer->exiting == 0) {
-      __futex_wait(&timer->exiting, 0, NULL);
-    }
-  }
 }
 
 // http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_create.html
 int timer_create(clockid_t clock_id, sigevent* evp, timer_t* timer_id) {
-  PosixTimer* new_timer = reinterpret_cast<PosixTimer*>(malloc(sizeof(PosixTimer)));
-  if (new_timer == NULL) {
+  PosixTimer* timer = reinterpret_cast<PosixTimer*>(malloc(sizeof(PosixTimer)));
+  if (timer == NULL) {
     return -1;
   }
 
-  new_timer->sigev_notify = (evp == NULL) ? SIGEV_SIGNAL : evp->sigev_notify;
+  timer->sigev_notify = (evp == NULL) ? SIGEV_SIGNAL : evp->sigev_notify;
 
   // If not a SIGEV_THREAD timer, the kernel can handle it without our help.
-  if (new_timer->sigev_notify != SIGEV_THREAD) {
-    if (__timer_create(clock_id, evp, &new_timer->kernel_timer_id) == -1) {
-      free(new_timer);
+  if (timer->sigev_notify != SIGEV_THREAD) {
+    if (__timer_create(clock_id, evp, &timer->kernel_timer_id) == -1) {
+      free(timer);
       return -1;
     }
 
-    *timer_id = new_timer;
+    *timer_id = timer;
     return 0;
   }
 
   // Otherwise, this must be SIGEV_THREAD timer...
-  new_timer->callback = evp->sigev_notify_function;
-  new_timer->callback_argument = evp->sigev_value;
-  new_timer->exiting = 0;
+  timer->callback = evp->sigev_notify_function;
+  timer->callback_argument = evp->sigev_value;
 
   // Check arguments that the kernel doesn't care about but we do.
-  if (new_timer->callback == NULL) {
-    free(new_timer);
+  if (timer->callback == NULL) {
+    free(timer);
     errno = EINVAL;
     return -1;
   }
@@ -159,12 +146,12 @@
   kernel_sigset_t old_sigset;
   pthread_sigmask(SIG_BLOCK, sigset.get(), old_sigset.get());
 
-  int rc = pthread_create(&new_timer->callback_thread, &thread_attributes, __timer_thread_start, new_timer);
+  int rc = pthread_create(&timer->callback_thread, &thread_attributes, __timer_thread_start, timer);
 
   pthread_sigmask(SIG_SETMASK, old_sigset.get(), NULL);
 
   if (rc != 0) {
-    free(new_timer);
+    free(timer);
     errno = rc;
     return -1;
   }
@@ -172,20 +159,19 @@
   sigevent se = *evp;
   se.sigev_signo = TIMER_SIGNAL;
   se.sigev_notify = SIGEV_THREAD_ID;
-  se.sigev_notify_thread_id = __pthread_gettid(new_timer->callback_thread);
-  if (__timer_create(clock_id, &se, &new_timer->kernel_timer_id) == -1) {
-    __timer_thread_stop(new_timer);
-    free(new_timer);
+  se.sigev_notify_thread_id = __pthread_gettid(timer->callback_thread);
+  if (__timer_create(clock_id, &se, &timer->kernel_timer_id) == -1) {
+    __timer_thread_stop(timer);
     return -1;
   }
 
   // Give the thread a meaningful name.
   // It can't do this itself because the kernel timer isn't created until after it's running.
   char name[32];
-  snprintf(name, sizeof(name), "POSIX interval timer %d", to_kernel_timer_id(new_timer));
-  pthread_setname_np(new_timer->callback_thread, name);
+  snprintf(name, sizeof(name), "POSIX interval timer %d", to_kernel_timer_id(timer));
+  pthread_setname_np(timer->callback_thread, name);
 
-  *timer_id = new_timer;
+  *timer_id = timer;
   return 0;
 }
 
@@ -197,14 +183,14 @@
   }
 
   PosixTimer* timer = reinterpret_cast<PosixTimer*>(id);
-
-  // Make sure the timer's thread has exited before we free the timer data.
   if (timer->sigev_notify == SIGEV_THREAD) {
+    // Stopping the timer's thread frees the timer data when it's safe.
     __timer_thread_stop(timer);
+  } else {
+    // For timers without threads, we can just free right away.
+    free(timer);
   }
 
-  free(timer);
-
   return 0;
 }
 
diff --git a/libc/bionic/strtotimeval.c b/libc/bionic/strtotimeval.c
index 1c132ec..195381b 100644
--- a/libc/bionic/strtotimeval.c
+++ b/libc/bionic/strtotimeval.c
@@ -30,34 +30,29 @@
 #include <stdlib.h>
 #include <sys/time.h>
 
-char * strtotimeval (const char *str, struct timeval *ts)
-{
-    int n;
-    char *s, *s0;
-    long  fs;	/* Fractional seconds */
+char * strtotimeval(const char *str, struct timeval *ts) {
+  char *s;
+  long fs = 0; /* fractional seconds */
 
-    ts->tv_sec = strtoumax(str, &s, 10);
-    fs = 0;
+  ts->tv_sec = strtoumax(str, &s, 10);
 
-    if ( *s == '.' ) {
-	int  count;
+  if (*s == '.') {
+    s++;
+    int count = 0;
 
-        s0 = s+1;
-
-	/* read up to 6 digits */
-	fs    = 0;
-	count = 0;
-	while ( *s && isdigit(*s) )
-	{
-            if ( ++count < 7 )
-	        fs = fs*10 + (*s - '0');
-	    s++;
-	}
-
-	for ( ; count < 6; count++ )
-	    fs *= 10;
+    /* read up to 6 digits (microseconds) */
+    while (*s && isdigit(*s)) {
+      if (++count < 7) {
+        fs = fs*10 + (*s - '0');
+      }
+      s++;
     }
 
-    ts->tv_usec = fs;
-    return s;
+    for (; count < 6; count++) {
+      fs *= 10;
+    }
+  }
+
+  ts->tv_usec = fs;
+  return s;
 }
diff --git a/libc/include/limits.h b/libc/include/limits.h
index 471d380..a70021a 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -105,6 +105,15 @@
 #define ULONG_LONG_MAX  ULLONG_MAX
 #endif
 
+/* BSD compatibility definitions. */
+#if __BSD_VISIBLE
+#define SIZE_T_MAX ULONG_MAX
+#endif /* __BSD_VISIBLE */
+
+#define SSIZE_MAX LONG_MAX
+
+#define MB_LEN_MAX 1 /* No multibyte characters. */
+
 /* New code should use sysconf(_SC_PAGE_SIZE) instead. */
 #ifndef PAGE_SIZE
 #define PAGE_SIZE 4096
diff --git a/libc/include/locale.h b/libc/include/locale.h
index b6dbfdb..4efc564 100644
--- a/libc/include/locale.h
+++ b/libc/include/locale.h
@@ -51,12 +51,41 @@
 
 extern char* setlocale(int, const char*);
 
-#if !defined(__LP64__)
-// TODO: LP32 had these bogus declarations but LP64 should have a real struct lconv and localeconv(3).
+#if defined(__LP64__)
+struct lconv {
+    char* decimal_point;
+    char* thousands_sep;
+    char* grouping;
+    char* int_curr_symbol;
+    char* currency_symbol;
+    char* mon_decimal_point;
+    char* mon_thousands_sep;
+    char* mon_grouping;
+    char* positive_sign;
+    char* negative_sign;
+    char  int_frac_digits;
+    char  frac_digits;
+    char  p_cs_precedes;
+    char  p_sep_by_space;
+    char  n_cs_precedes;
+    char  n_sep_by_space;
+    char  p_sign_posn;
+    char  n_sign_posn;
+    /* ISO-C99 */
+    char  int_p_cs_precedes;
+    char  int_p_sep_by_space;
+    char  int_n_cs_precedes;
+    char  int_n_sep_by_space;
+    char  int_p_sign_posn;
+    char  int_n_sign_posn;
+};
+#else
+// Keep old declaration for ILP32 for compatibility
 struct lconv { };
-struct lconv* localeconv(void);
 #endif
 
+struct lconv* localeconv(void);
+
 __END_DECLS
 
 #endif /* _LOCALE_H_ */
diff --git a/libc/include/search.h b/libc/include/search.h
index 1301a08..b2c0e6b 100644
--- a/libc/include/search.h
+++ b/libc/include/search.h
@@ -10,29 +10,34 @@
 #define _SEARCH_H_
 
 #include <sys/cdefs.h>
+#include <sys/types.h>
 
-typedef	enum {
-	preorder,
-	postorder,
-	endorder,
-	leaf
+typedef enum {
+  preorder,
+  postorder,
+  endorder,
+  leaf
 } VISIT;
 
 #ifdef _SEARCH_PRIVATE
-typedef	struct node {
-	char         *key;
-	struct node  *llink, *rlink;
+typedef struct node {
+  char* key;
+  struct node* llink;
+  struct node* rlink;
 } node_t;
 #endif
 
 __BEGIN_DECLS
-void	*tdelete(const void * __restrict, void ** __restrict,
-	    int (*)(const void *, const void *));
-void	*tfind(const void *, void * const *,
-	    int (*)(const void *, const void *));
-void	*tsearch(const void *, void **, int (*)(const void *, const void *));
-void	 twalk(const void *, void (*)(const void *, VISIT, int));
-void	 tdestroy(void *, void (*)(void *));
+
+void* lfind(const void*, const void*, size_t*, size_t, int (*)(const void*, const void*));
+void* lsearch(const void*, void*, size_t*, size_t, int (*)(const void*, const void*));
+
+void* tdelete(const void* __restrict, void** __restrict, int (*)(const void*, const void*));
+void tdestroy(void*, void (*)(void*));
+void* tfind(const void*, void* const*, int (*)(const void*, const void*));
+void* tsearch(const void*, void**, int (*)(const void*, const void*));
+void twalk(const void*, void (*)(const void*, VISIT, int));
+
 __END_DECLS
 
 #endif /* !_SEARCH_H_ */
diff --git a/libc/include/sys/limits.h b/libc/include/sys/limits.h
index 36f73b2..c50eb10 100644
--- a/libc/include/sys/limits.h
+++ b/libc/include/sys/limits.h
@@ -31,9 +31,6 @@
 
 /* Common definitions for limits.h. */
 
-/* Legacy */
-#include <machine/limits.h>
-
 #define	CHAR_BIT	8		/* number of bits in a char */
 
 #define	SCHAR_MAX	0x7f		/* max value for a signed char */
diff --git a/libc/include/sys/localedef.h b/libc/include/sys/localedef.h
new file mode 100644
index 0000000..b6b5eb1
--- /dev/null
+++ b/libc/include/sys/localedef.h
@@ -0,0 +1,101 @@
+/*	$OpenBSD: localedef.h,v 1.3 1996/04/21 22:31:47 deraadt Exp $	*/
+/*	$NetBSD: localedef.h,v 1.4 1996/04/09 20:55:31 cgd Exp $	*/
+
+/*
+ * Copyright (c) 1994 Winning Strategies, Inc.
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#ifndef _SYS_LOCALEDEF_H_
+#define _SYS_LOCALEDEF_H_
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+typedef struct
+{
+	char *yesexpr;
+	char *noexpr;
+	char *yesstr;
+	char *nostr;
+} _MessagesLocale;
+
+extern const _MessagesLocale *_CurrentMessagesLocale;
+extern const _MessagesLocale  _DefaultMessagesLocale;
+
+
+typedef struct
+{
+	char *int_curr_symbol;
+	char *currency_symbol;
+	char *mon_decimal_point;
+	char *mon_thousands_sep;
+	char *mon_grouping;
+	char *positive_sign;
+	char *negative_sign;
+	char int_frac_digits;
+	char frac_digits;
+	char p_cs_precedes;
+	char p_sep_by_space;
+	char n_cs_precedes;
+	char n_sep_by_space;
+	char p_sign_posn;
+	char n_sign_posn;
+} _MonetaryLocale;
+
+extern const _MonetaryLocale *_CurrentMonetaryLocale;
+extern const _MonetaryLocale  _DefaultMonetaryLocale;
+
+
+typedef struct
+{
+	const char *decimal_point;
+	const char *thousands_sep;
+	const char *grouping;
+} _NumericLocale;
+
+extern const _NumericLocale *_CurrentNumericLocale;
+extern const _NumericLocale  _DefaultNumericLocale;
+
+
+typedef struct {
+	const char *abday[7];
+	const char *day[7];
+	const char *abmon[12];
+	const char *mon[12];
+	const char *am_pm[2];
+	const char *d_t_fmt;
+	const char *d_fmt;
+	const char *t_fmt;
+	const char *t_fmt_ampm;
+} _TimeLocale;
+
+extern const _TimeLocale *_CurrentTimeLocale;
+extern const _TimeLocale  _DefaultTimeLocale;
+
+#endif /* !_SYS_LOCALEDEF_H_ */
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index 5001b2e..86fd3cf 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -284,6 +284,7 @@
 #endif
 
 __socketcall int accept(int, struct sockaddr*, socklen_t*);
+__socketcall int accept4(int, struct sockaddr*, socklen_t*, int);
 __socketcall int bind(int, const struct sockaddr*, int);
 __socketcall int connect(int, const struct sockaddr*, socklen_t);
 __socketcall int getpeername(int, struct sockaddr*, socklen_t*);
@@ -298,7 +299,6 @@
 __socketcall int shutdown(int, int);
 __socketcall int socket(int, int, int);
 __socketcall int socketpair(int, int, int, int*);
-__socketcall int accept4(int, struct sockaddr*, socklen_t*, int);
 
 extern ssize_t send(int, const void*, size_t, int);
 extern ssize_t recv(int, void*, size_t, int);
diff --git a/libc/include/sys/socketcalls.h b/libc/include/sys/socketcalls.h
index 09c079f..131e0bb 100644
--- a/libc/include/sys/socketcalls.h
+++ b/libc/include/sys/socketcalls.h
@@ -48,5 +48,7 @@
 #define SYS_SENDMSG     16              /* sys_sendmsg(2)               */
 #define SYS_RECVMSG     17              /* sys_recvmsg(2)               */
 #define SYS_ACCEPT4     18              /* sys_accept4(2)               */
+#define SYS_RECVMMSG    19              /* sys_recvmmsg(2)              */
+#define SYS_SENDMMSG    20              /* sys_sendmmsg(2)              */
 
 #endif /* _SYS_SOCKETCALLS_H_ */
diff --git a/libc/kernel/uapi/video/adf.h b/libc/kernel/uapi/video/adf.h
index 057ec46..fe23e01 100644
--- a/libc/kernel/uapi/video/adf.h
+++ b/libc/kernel/uapi/video/adf.h
@@ -62,7 +62,7 @@
 struct adf_vsync_event {
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  struct adf_event base;
- __u64 timestamp;
+ __aligned_u64 timestamp;
 };
 struct adf_hotplug_event {
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
@@ -77,12 +77,12 @@
  __u32 h;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __u32 format;
- __s64 fd[ADF_MAX_PLANES];
+ __s32 fd[ADF_MAX_PLANES];
  __u32 offset[ADF_MAX_PLANES];
  __u32 pitch[ADF_MAX_PLANES];
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __u8 n_planes;
- __s64 acquire_fence;
+ __s32 acquire_fence;
 };
 #define ADF_MAX_BUFFERS (4096 / sizeof(struct adf_buffer_config))
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
@@ -94,7 +94,7 @@
  struct adf_buffer_config __user *bufs;
  size_t custom_data_size;
  void __user *custom_data;
- __s64 complete_fence;
+ __s32 complete_fence;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 };
 #define ADF_MAX_INTERFACES (4096 / sizeof(__u32))
@@ -103,7 +103,7 @@
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __u16 h;
  __u32 format;
- __s64 fd;
+ __s32 fd;
  __u32 offset;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __u32 pitch;
@@ -111,7 +111,7 @@
 struct adf_simple_post_config {
  struct adf_buffer_config buf;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __s64 complete_fence;
+ __s32 complete_fence;
 };
 struct adf_attachment_config {
  __u32 overlay_engine;
@@ -161,18 +161,20 @@
 };
 #define ADF_MAX_SUPPORTED_FORMATS (4096 / sizeof(__u32))
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ADF_SET_EVENT _IOW('D', 0, struct adf_set_event)
-#define ADF_BLANK _IOW('D', 1, __u8)
-#define ADF_POST_CONFIG _IOW('D', 2, struct adf_post_config)
-#define ADF_SET_MODE _IOW('D', 3, struct drm_mode_modeinfo)
+#define ADF_IOCTL_TYPE 'D'
+#define ADF_IOCTL_NR_CUSTOM 128
+#define ADF_SET_EVENT _IOW(ADF_IOCTL_TYPE, 0, struct adf_set_event)
+#define ADF_BLANK _IOW(ADF_IOCTL_TYPE, 1, __u8)
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ADF_GET_DEVICE_DATA _IOR('D', 4, struct adf_device_data)
-#define ADF_GET_INTERFACE_DATA _IOR('D', 5, struct adf_interface_data)
-#define ADF_GET_OVERLAY_ENGINE_DATA   _IOR('D', 6, struct adf_overlay_engine_data)
-#define ADF_SIMPLE_POST_CONFIG _IOW('D', 7, struct adf_simple_post_config)
+#define ADF_POST_CONFIG _IOW(ADF_IOCTL_TYPE, 2, struct adf_post_config)
+#define ADF_SET_MODE _IOW(ADF_IOCTL_TYPE, 3,   struct drm_mode_modeinfo)
+#define ADF_GET_DEVICE_DATA _IOR(ADF_IOCTL_TYPE, 4, struct adf_device_data)
+#define ADF_GET_INTERFACE_DATA _IOR(ADF_IOCTL_TYPE, 5,   struct adf_interface_data)
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ADF_SIMPLE_BUFFER_ALLOC _IOW('D', 8, struct adf_simple_buffer_alloc)
-#define ADF_ATTACH _IOW('D', 9, struct adf_attachment_config)
-#define ADF_DETACH _IOW('D', 10, struct adf_attachment_config)
+#define ADF_GET_OVERLAY_ENGINE_DATA   _IOR(ADF_IOCTL_TYPE, 6,   struct adf_overlay_engine_data)
+#define ADF_SIMPLE_POST_CONFIG _IOW(ADF_IOCTL_TYPE, 7,   struct adf_simple_post_config)
+#define ADF_SIMPLE_BUFFER_ALLOC _IOW(ADF_IOCTL_TYPE, 8,   struct adf_simple_buffer_alloc)
+#define ADF_ATTACH _IOW(ADF_IOCTL_TYPE, 9,   struct adf_attachment_config)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ADF_DETACH _IOW(ADF_IOCTL_TYPE, 10,   struct adf_attachment_config)
 #endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libc/stdlib/strtod.c b/libc/stdlib/strtod.c
index 0a19446..b39c90e 100644
--- a/libc/stdlib/strtod.c
+++ b/libc/stdlib/strtod.c
@@ -1332,13 +1332,14 @@
 	Bigint *bb1, *bd0;
 	Bigint *bb = NULL, *bd = NULL, *bs = NULL, *delta = NULL;/* pacify gcc */
 
-	CONST char decimal_point = '.';
-#if 0 /* BEGIN android-changed: no localeconv. */
+#if defined(__LP64__) /* BEGIN android-changed: no localeconv for ILP32. */
 #ifndef KR_headers
 	CONST char decimal_point = localeconv()->decimal_point[0];
 #else
 	CONST char decimal_point = '.';
 #endif
+#else
+	CONST char decimal_point = '.';
 #endif /* END android-changed */
 
 	sign = nz0 = nz = 0;
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/lsearch.c b/libc/upstream-netbsd/lib/libc/stdlib/lsearch.c
new file mode 100644
index 0000000..e17130b
--- /dev/null
+++ b/libc/upstream-netbsd/lib/libc/stdlib/lsearch.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Roger L. Snyder.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)lsearch.c	8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: lsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <search.h>
+
+typedef int (*cmp_fn_t)(const void *, const void *);
+static void *linear_base(const void *, void *, size_t *, size_t,
+			     cmp_fn_t, int);
+
+void *
+lsearch(const void *key, void *base, size_t *nelp, size_t width,
+    cmp_fn_t compar)
+{
+
+	_DIAGASSERT(key != NULL);
+	_DIAGASSERT(base != NULL);
+	_DIAGASSERT(compar != NULL);
+
+	return(linear_base(key, base, nelp, width, compar, 1));
+}
+
+void *
+lfind(const void *key, const void *base, size_t *nelp, size_t width,
+    cmp_fn_t compar)
+{
+
+	_DIAGASSERT(key != NULL);
+	_DIAGASSERT(base != NULL);
+	_DIAGASSERT(compar != NULL);
+
+	return(linear_base(key, __UNCONST(base), nelp, width, compar, 0));
+}
+
+static void *
+linear_base(const void *key, void *base, size_t *nelp, size_t width,
+	cmp_fn_t compar, int add_flag)
+{
+	char *element, *end;
+
+	_DIAGASSERT(key != NULL);
+	_DIAGASSERT(base != NULL);
+	_DIAGASSERT(compar != NULL);
+
+	end = (char *)base + *nelp * width;
+	for (element = (char *)base; element < end; element += width)
+		if (!compar(element, key))		/* key found */
+			return element;
+
+	if (!add_flag)					/* key not found */
+		return(NULL);
+
+	/*
+	 * The UNIX System User's Manual, 1986 edition claims that
+	 * a NULL pointer is returned by lsearch with errno set
+	 * appropriately, if there is not enough room in the table
+	 * to add a new item.  This can't be done as none of these
+	 * routines have any method of determining the size of the
+	 * table.  This comment isn't in the 1986-87 System V
+	 * manual.
+	 */
+	++*nelp;
+	memcpy(end, key, width);
+	return end;
+}
diff --git a/libc/upstream-openbsd/lib/libc/locale/_def_messages.c b/libc/upstream-openbsd/lib/libc/locale/_def_messages.c
new file mode 100644
index 0000000..1ed653a
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_def_messages.c
@@ -0,0 +1,18 @@
+/*	$OpenBSD: _def_messages.c,v 1.5 2005/08/08 08:05:35 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <sys/localedef.h>
+#include <locale.h>
+
+const _MessagesLocale _DefaultMessagesLocale =
+{
+	"^[Yy]",
+	"^[Nn]",
+	"yes",
+	"no"
+} ;
+
+const _MessagesLocale *_CurrentMessagesLocale = &_DefaultMessagesLocale;
diff --git a/libc/upstream-openbsd/lib/libc/locale/_def_monetary.c b/libc/upstream-openbsd/lib/libc/locale/_def_monetary.c
new file mode 100644
index 0000000..aa92c75
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_def_monetary.c
@@ -0,0 +1,30 @@
+/*	$OpenBSD: _def_monetary.c,v 1.4 2005/08/08 08:05:35 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <sys/localedef.h>
+#include <limits.h>
+#include <locale.h>
+
+const _MonetaryLocale _DefaultMonetaryLocale =
+{
+	"",
+	"",
+	"",
+	"",
+	"",
+	"",
+	"",
+	CHAR_MAX,
+	CHAR_MAX,
+	CHAR_MAX,
+	CHAR_MAX,
+	CHAR_MAX,
+	CHAR_MAX,
+	CHAR_MAX,
+	CHAR_MAX
+};
+
+const _MonetaryLocale *_CurrentMonetaryLocale = &_DefaultMonetaryLocale;
diff --git a/libc/upstream-openbsd/lib/libc/locale/_def_numeric.c b/libc/upstream-openbsd/lib/libc/locale/_def_numeric.c
new file mode 100644
index 0000000..6511254
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_def_numeric.c
@@ -0,0 +1,17 @@
+/*	$OpenBSD: _def_numeric.c,v 1.4 2005/08/08 08:05:35 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <sys/localedef.h>
+#include <locale.h>
+
+const _NumericLocale _DefaultNumericLocale =
+{
+	".",
+	"",
+	""
+};
+
+const _NumericLocale *_CurrentNumericLocale = &_DefaultNumericLocale;
diff --git a/libc/upstream-openbsd/lib/libc/locale/_def_time.c b/libc/upstream-openbsd/lib/libc/locale/_def_time.c
new file mode 100644
index 0000000..75179a6
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/_def_time.c
@@ -0,0 +1,36 @@
+/*	$OpenBSD: _def_time.c,v 1.5 2011/10/09 06:39:53 ajacoutot Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <sys/localedef.h>
+#include <locale.h>
+
+const _TimeLocale _DefaultTimeLocale =
+{
+	{
+		"Sun","Mon","Tue","Wed","Thu","Fri","Sat",
+	},
+	{
+		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+		"Friday", "Saturday"
+	},
+	{
+		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+	},
+	{
+		"January", "February", "March", "April", "May", "June", "July",
+		"August", "September", "October", "November", "December"
+	},
+	{
+		"AM", "PM"
+	},
+	"%a %b %e %H:%M:%S %Y",
+	"%m/%d/%y",
+	"%H:%M:%S",
+	"%I:%M:%S %p"
+};
+
+const _TimeLocale *_CurrentTimeLocale = &_DefaultTimeLocale;
diff --git a/libc/upstream-openbsd/lib/libc/locale/localeconv.c b/libc/upstream-openbsd/lib/libc/locale/localeconv.c
new file mode 100644
index 0000000..989eb4b
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/locale/localeconv.c
@@ -0,0 +1,59 @@
+/*	$OpenBSD: localeconv.c,v 1.5 2005/08/08 08:05:35 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <sys/localedef.h>
+#include <locale.h>
+
+/*
+ * The localeconv() function constructs a struct lconv from the current
+ * monetary and numeric locales.
+ *
+ * Because localeconv() may be called many times (especially by library
+ * routines like printf() & strtod()), the approprate members of the
+ * lconv structure are computed only when the monetary or numeric
+ * locale has been changed.
+ */
+int __mlocale_changed = 1;
+int __nlocale_changed = 1;
+
+/*
+ * Return the current locale conversion.
+ */
+struct lconv *
+localeconv(void)
+{
+    static struct lconv ret;
+
+    if (__mlocale_changed) {
+	/* LC_MONETARY */
+	ret.int_curr_symbol	= _CurrentMonetaryLocale->int_curr_symbol;
+	ret.currency_symbol	= _CurrentMonetaryLocale->currency_symbol;
+	ret.mon_decimal_point	= _CurrentMonetaryLocale->mon_decimal_point;
+	ret.mon_thousands_sep	= _CurrentMonetaryLocale->mon_thousands_sep;
+	ret.mon_grouping	= _CurrentMonetaryLocale->mon_grouping;
+	ret.positive_sign	= _CurrentMonetaryLocale->positive_sign;
+	ret.negative_sign	= _CurrentMonetaryLocale->negative_sign;
+	ret.int_frac_digits	= _CurrentMonetaryLocale->int_frac_digits;
+	ret.frac_digits		= _CurrentMonetaryLocale->frac_digits;
+	ret.p_cs_precedes	= _CurrentMonetaryLocale->p_cs_precedes;
+	ret.p_sep_by_space	= _CurrentMonetaryLocale->p_sep_by_space;
+	ret.n_cs_precedes	= _CurrentMonetaryLocale->n_cs_precedes;
+	ret.n_sep_by_space	= _CurrentMonetaryLocale->n_sep_by_space;
+	ret.p_sign_posn		= _CurrentMonetaryLocale->p_sign_posn;
+	ret.n_sign_posn		= _CurrentMonetaryLocale->n_sign_posn;
+	__mlocale_changed = 0;
+    }
+
+    if (__nlocale_changed) {
+	/* LC_NUMERIC */
+	ret.decimal_point	= (char *) _CurrentNumericLocale->decimal_point;
+	ret.thousands_sep	= (char *) _CurrentNumericLocale->thousands_sep;
+	ret.grouping		= (char *) _CurrentNumericLocale->grouping;
+	__nlocale_changed = 0;
+    }
+
+    return (&ret);
+}
diff --git a/libc/zoneinfo/tzdata b/libc/zoneinfo/tzdata
index 8468e83..2178298 100644
--- a/libc/zoneinfo/tzdata
+++ b/libc/zoneinfo/tzdata
Binary files differ
diff --git a/libm/Android.mk b/libm/Android.mk
index 4a826eb..aea4662 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -261,7 +261,6 @@
 LOCAL_C_INCLUDES_x86 := $(LOCAL_PATH)/i386 $(LOCAL_PATH)/i387
 LOCAL_SRC_FILES_x86 := i387/fenv.c
 
-LOCAL_CFLAGS_x86_64 := -include $(LOCAL_PATH)/fpmath.h
 LOCAL_C_INCLUDES_x86_64 := $(LOCAL_PATH)/amd64 $(libm_ld_includes)
 LOCAL_SRC_FILES_x86_64 := amd64/fenv.c $(libm_ld_src_files)
 
diff --git a/libm/fake_long_double.c b/libm/fake_long_double.c
index 13adf2f..b5b264b 100644
--- a/libm/fake_long_double.c
+++ b/libm/fake_long_double.c
@@ -22,16 +22,34 @@
 
 int (isnanf)(float a1) { return __isnanf(a1); }
 
-// FreeBSD falls back to the double variants of these functions as well.
-long double coshl(long double a1) { return cosh(a1); }
-long double erfcl(long double a1) { return erfc(a1); }
-long double erfl(long double a1) { return erf(a1); }
-long double lgammal(long double a1) { return lgamma(a1); }
+/*
+ * On LP64 sizeof(long double) > sizeof(double) so functions which fall back
+ * to their double variants lose precision. Emit a warning whenever something
+ * links against such functions.
+ * On LP32 sizeof(long double) == sizeof(double) so we don't need to warn.
+ */
+#ifdef __LP64__
+#define WARN_IMPRECISE(x) \
+  __warn_references(x, # x " has lower than advertised precision");
+#else
+#define WARN_IMPRECISE(x)
+#endif //__LP64__
+
+#define DECLARE_IMPRECISE(f) \
+  long double f ## l(long double v) { return f(v); } \
+  WARN_IMPRECISE(x)
+
+DECLARE_IMPRECISE(cosh);
+DECLARE_IMPRECISE(erfc);
+DECLARE_IMPRECISE(erf);
+DECLARE_IMPRECISE(lgamma);
+DECLARE_IMPRECISE(sinh);
+DECLARE_IMPRECISE(tanh);
+DECLARE_IMPRECISE(tgamma);
+DECLARE_IMPRECISE(significand);
+
 long double powl(long double a1, long double a2) { return pow(a1, a2); }
-long double sinhl(long double a1) { return sinh(a1); }
-long double tanhl(long double a1) { return tanh(a1); }
-long double tgammal(long double a1) { return tgamma(a1); }
-long double significandl(long double a1) { return significand(a1); }
+WARN_IMPRECISE(powl)
 
 #ifndef __LP64__
 /*
diff --git a/libm/upstream-freebsd/lib/msun/src/imprecise.c b/libm/upstream-freebsd/lib/msun/src/imprecise.c
deleted file mode 100644
index a7503bf..0000000
--- a/libm/upstream-freebsd/lib/msun/src/imprecise.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*-
- * Copyright (c) 2013 David Chisnall
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
- *
- * $FreeBSD$
- */
-
-#include <float.h>
-#include <math.h>
-
-/*
- * If long double is not the same size as double, then these will lose
- * precision and we should emit a warning whenever something links against
- * them.
- */
-#if (LDBL_MANT_DIG > 53)
-#define WARN_IMPRECISE(x) \
-	__warn_references(x, # x " has lower than advertised precision");
-#else
-#define WARN_IMPRECISE(x)
-#endif
-/*
- * Declare the functions as weak variants so that other libraries providing
- * real versions can override them.
- */
-#define	DECLARE_WEAK(x)\
-	__weak_reference(imprecise_## x, x);\
-	WARN_IMPRECISE(x)
-
-long double
-imprecise_powl(long double x, long double y)
-{
-
-	return pow(x, y);
-}
-DECLARE_WEAK(powl);
-
-#define DECLARE_IMPRECISE(f) \
-	long double imprecise_ ## f ## l(long double v) { return f(v); }\
-	DECLARE_WEAK(f ## l)
-
-DECLARE_IMPRECISE(cosh);
-DECLARE_IMPRECISE(erfc);
-DECLARE_IMPRECISE(erf);
-DECLARE_IMPRECISE(lgamma);
-DECLARE_IMPRECISE(sinh);
-DECLARE_IMPRECISE(tanh);
-DECLARE_IMPRECISE(tgamma);
diff --git a/linker/Android.mk b/linker/Android.mk
index 1d03a9c..f0e6c13 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -1,9 +1,69 @@
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
 
-linker_2nd_arch_var_prefix :=
-include $(LOCAL_PATH)/linker.mk
+include $(CLEAR_VARS)
 
+LOCAL_SRC_FILES:= \
+    debugger.cpp \
+    dlfcn.cpp \
+    linker.cpp \
+    linker_environ.cpp \
+    linker_phdr.cpp \
+    rt.cpp \
+
+LOCAL_SRC_FILES_arm     := arch/arm/begin.S
+LOCAL_SRC_FILES_arm64   := arch/arm64/begin.S
+LOCAL_SRC_FILES_x86     := arch/x86/begin.c
+LOCAL_SRC_FILES_x86_64  := arch/x86_64/begin.S
+LOCAL_SRC_FILES_mips    := arch/mips/begin.S
+
+LOCAL_LDFLAGS := \
+    -shared \
+    -Wl,-Bsymbolic \
+    -Wl,--exclude-libs,ALL \
+
+LOCAL_CFLAGS += \
+    -fno-stack-protector \
+    -Wstrict-overflow=5 \
+    -fvisibility=hidden \
+    -Wall -Wextra -Werror \
+
+LOCAL_CONLYFLAGS += \
+    -std=gnu99 \
+
+LOCAL_CPPFLAGS += \
+    -std=gnu++11 \
+
+# We need to access Bionic private headers in the linker.
+LOCAL_CFLAGS += -I$(LOCAL_PATH)/../libc/
+
+# we don't want crtbegin.o (because we have begin.o), so unset it
+# just for this module
+LOCAL_NO_CRT := true
+# TODO: split out the asflags.
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/linker_executable.mk
+
+LOCAL_STATIC_LIBRARIES := libc_nomalloc
+
+LOCAL_FORCE_STATIC_EXECUTABLE := true # not necessary when not including BUILD_EXECUTABLE
+
+LOCAL_2ND_ARCH_VAR_PREFIX := $(linker_2nd_arch_var_prefix)
+
+LOCAL_MODULE := linker
+LOCAL_MODULE_STEM_32 := linker
+LOCAL_MODULE_STEM_64 := linker64
+LOCAL_MULTILIB := both
+
+include $(LOCAL_PATH)/linker_executable.mk
 ifdef TARGET_2ND_ARCH
-linker_2nd_arch_var_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
-include $(LOCAL_PATH)/linker.mk
+LOCAL_2ND_ARCH_VAR_PREFIX := $(TARGET_2ND_ARCH_VAR_PREFIX)
+OVERRIDE_BUILT_MODULE_PATH :=
+LOCAL_BUILT_MODULE :=
+LOCAL_INSTALLED_MODULE :=
+LOCAL_MODULE_STEM :=
+LOCAL_BUILT_MODULE_STEM :=
+LOCAL_INSTALLED_MODULE_STEM :=
+LOCAL_INTERMEDIATE_TARGETS :=
+include $(LOCAL_PATH)/linker_executable.mk
 endif
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 156864c..de7b04d 100755
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -163,11 +163,10 @@
         write(2, msg, strlen(msg)); \
         abort(); \
     }
-#define UNUSED __attribute__((unused))
-DISALLOW_ALLOCATION(void*, malloc, (size_t u UNUSED));
-DISALLOW_ALLOCATION(void, free, (void* u UNUSED));
-DISALLOW_ALLOCATION(void*, realloc, (void* u1 UNUSED, size_t u2 UNUSED));
-DISALLOW_ALLOCATION(void*, calloc, (size_t u1 UNUSED, size_t u2 UNUSED));
+DISALLOW_ALLOCATION(void*, malloc, (size_t u __unused));
+DISALLOW_ALLOCATION(void, free, (void* u __unused));
+DISALLOW_ALLOCATION(void*, realloc, (void* u1 __unused, size_t u2 __unused));
+DISALLOW_ALLOCATION(void*, calloc, (size_t u1 __unused, size_t u2 __unused));
 
 static char tmp_err_buf[768];
 static char __linker_dl_err_buf[768];
@@ -1413,7 +1412,7 @@
 }
 #endif
 
-void soinfo::CallArray(const char* array_name UNUSED, linker_function_t* functions, size_t count, bool reverse) {
+void soinfo::CallArray(const char* array_name __unused, linker_function_t* functions, size_t count, bool reverse) {
   if (functions == NULL) {
     return;
   }
@@ -1432,7 +1431,7 @@
   TRACE("[ Done calling %s for '%s' ]", array_name, name);
 }
 
-void soinfo::CallFunction(const char* function_name UNUSED, linker_function_t function) {
+void soinfo::CallFunction(const char* function_name __unused, linker_function_t function) {
   if (function == NULL || reinterpret_cast<uintptr_t>(function) == static_cast<uintptr_t>(-1)) {
     return;
   }
@@ -1908,7 +1907,7 @@
  * It helps to stack unwinding through signal handlers.
  * Also, it makes bionic more like glibc.
  */
-static void add_vdso(KernelArgumentBlock& args UNUSED) {
+static void add_vdso(KernelArgumentBlock& args __unused) {
 #if defined(AT_SYSINFO_EHDR)
   ElfW(Ehdr)* ehdr_vdso = reinterpret_cast<ElfW(Ehdr)*>(args.getauxval(AT_SYSINFO_EHDR));
   if (ehdr_vdso == NULL) {
diff --git a/linker/linker.mk b/linker/linker.mk
deleted file mode 100644
index 384435a..0000000
--- a/linker/linker.mk
+++ /dev/null
@@ -1,58 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    debugger.cpp \
-    dlfcn.cpp \
-    linker.cpp \
-    linker_environ.cpp \
-    linker_phdr.cpp \
-    rt.cpp \
-
-LOCAL_SRC_FILES_arm     := arch/arm/begin.S
-LOCAL_SRC_FILES_arm64   := arch/arm64/begin.S
-LOCAL_SRC_FILES_x86     := arch/x86/begin.c
-LOCAL_SRC_FILES_x86_64  := arch/x86_64/begin.S
-LOCAL_SRC_FILES_mips    := arch/mips/begin.S
-
-LOCAL_LDFLAGS := \
-    -shared \
-    -Wl,-Bsymbolic \
-    -Wl,--exclude-libs,ALL \
-
-LOCAL_CFLAGS += \
-    -fno-stack-protector \
-    -Wstrict-overflow=5 \
-    -fvisibility=hidden \
-    -Wall -Wextra -Werror \
-
-LOCAL_CONLYFLAGS += \
-    -std=gnu99 \
-
-LOCAL_CPPFLAGS += \
-    -std=gnu++11 \
-
-# We need to access Bionic private headers in the linker.
-LOCAL_CFLAGS += -I$(LOCAL_PATH)/../libc/
-
-# we don't want crtbegin.o (because we have begin.o), so unset it
-# just for this module
-LOCAL_NO_CRT := true
-# TODO: split out the asflags.
-LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/linker.mk $(LOCAL_PATH)/linker_executable.mk
-
-LOCAL_STATIC_LIBRARIES := libc_nomalloc
-
-LOCAL_FORCE_STATIC_EXECUTABLE := true # not necessary when not including BUILD_EXECUTABLE
-
-LOCAL_2ND_ARCH_VAR_PREFIX := $(linker_2nd_arch_var_prefix)
-
-ifeq ($(TARGET_IS_64_BIT)|$(linker_2nd_arch_var_prefix),true|)
-LOCAL_MODULE := linker64
-else
-LOCAL_MODULE := linker
-endif
-
-include $(LOCAL_PATH)/linker_executable.mk
diff --git a/tests/Android.mk b/tests/Android.mk
index 8dffa2f..7482ebc 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -50,6 +50,7 @@
     inttypes_test.cpp \
     libc_logging_test.cpp \
     libgen_test.cpp \
+    locale_test.cpp \
     malloc_test.cpp \
     math_test.cpp \
     netdb_test.cpp \
diff --git a/tests/locale_test.cpp b/tests/locale_test.cpp
new file mode 100644
index 0000000..df58a70
--- /dev/null
+++ b/tests/locale_test.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2014 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 <gtest/gtest.h>
+
+#include <locale.h>
+
+TEST(locale, localeconv) {
+#ifdef __LP64__
+  ASSERT_STREQ(".", localeconv()->decimal_point);
+  ASSERT_STREQ("", localeconv()->currency_symbol);
+#else
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
diff --git a/tests/math_test.cpp b/tests/math_test.cpp
index 80083fa..7734018 100644
--- a/tests/math_test.cpp
+++ b/tests/math_test.cpp
@@ -104,7 +104,7 @@
 
   ASSERT_EQ(FP_NORMAL, fpclassify(1.0f));
   ASSERT_EQ(FP_NORMAL, fpclassify(1.0));
-  ASSERT_EQ(FP_NORMAL, fpclassify(1.0l));
+  ASSERT_EQ(FP_NORMAL, fpclassify(1.0L));
 
   ASSERT_EQ(FP_SUBNORMAL, fpclassify(float_subnormal()));
   ASSERT_EQ(FP_SUBNORMAL, fpclassify(double_subnormal()));
@@ -112,13 +112,13 @@
 
   ASSERT_EQ(FP_ZERO, fpclassify(0.0f));
   ASSERT_EQ(FP_ZERO, fpclassify(0.0));
-  ASSERT_EQ(FP_ZERO, fpclassify(0.0l));
+  ASSERT_EQ(FP_ZERO, fpclassify(0.0L));
 }
 
 TEST(math, isfinite) {
   ASSERT_TRUE(test_capture_isfinite(123.0f));
   ASSERT_TRUE(test_capture_isfinite(123.0));
-  ASSERT_TRUE(test_capture_isfinite(123.0l));
+  ASSERT_TRUE(test_capture_isfinite(123.0L));
   ASSERT_FALSE(test_capture_isfinite(HUGE_VALF));
   ASSERT_FALSE(test_capture_isfinite(HUGE_VAL));
   ASSERT_FALSE(test_capture_isfinite(HUGE_VALL));
@@ -127,7 +127,7 @@
 TEST(math, isinf) {
   ASSERT_FALSE(test_capture_isinf(123.0f));
   ASSERT_FALSE(test_capture_isinf(123.0));
-  ASSERT_FALSE(test_capture_isinf(123.0l));
+  ASSERT_FALSE(test_capture_isinf(123.0L));
   ASSERT_TRUE(test_capture_isinf(HUGE_VALF));
   ASSERT_TRUE(test_capture_isinf(HUGE_VAL));
   ASSERT_TRUE(test_capture_isinf(HUGE_VALL));
@@ -136,7 +136,7 @@
 TEST(math, isnan) {
   ASSERT_FALSE(test_capture_isnan(123.0f));
   ASSERT_FALSE(test_capture_isnan(123.0));
-  ASSERT_FALSE(test_capture_isnan(123.0l));
+  ASSERT_FALSE(test_capture_isnan(123.0L));
   ASSERT_TRUE(test_capture_isnan(nanf("")));
   ASSERT_TRUE(test_capture_isnan(nan("")));
   ASSERT_TRUE(test_capture_isnan(nanl("")));
@@ -145,7 +145,7 @@
 TEST(math, isnormal) {
   ASSERT_TRUE(isnormal(123.0f));
   ASSERT_TRUE(isnormal(123.0));
-  ASSERT_TRUE(isnormal(123.0l));
+  ASSERT_TRUE(isnormal(123.0L));
   ASSERT_FALSE(isnormal(float_subnormal()));
   ASSERT_FALSE(isnormal(double_subnormal()));
   ASSERT_FALSE(isnormal(ldouble_subnormal()));
@@ -155,15 +155,15 @@
 TEST(math, signbit) {
   ASSERT_EQ(0, test_capture_signbit(0.0f));
   ASSERT_EQ(0, test_capture_signbit(0.0));
-  ASSERT_EQ(0, test_capture_signbit(0.0l));
+  ASSERT_EQ(0, test_capture_signbit(0.0L));
 
   ASSERT_EQ(0, test_capture_signbit(1.0f));
   ASSERT_EQ(0, test_capture_signbit(1.0));
-  ASSERT_EQ(0, test_capture_signbit(1.0l));
+  ASSERT_EQ(0, test_capture_signbit(1.0L));
 
   ASSERT_NE(0, test_capture_signbit(-1.0f));
   ASSERT_NE(0, test_capture_signbit(-1.0));
-  ASSERT_NE(0, test_capture_signbit(-1.0l));
+  ASSERT_NE(0, test_capture_signbit(-1.0L));
 }
 
 TEST(math, __fpclassifyd) {
@@ -194,9 +194,9 @@
 #if defined(__BIONIC__)
   EXPECT_EQ(FP_INFINITE, __fpclassifyl(HUGE_VALL));
   EXPECT_EQ(FP_NAN, __fpclassifyl(nanl("")));
-  EXPECT_EQ(FP_NORMAL, __fpclassifyl(1.0l));
+  EXPECT_EQ(FP_NORMAL, __fpclassifyl(1.0L));
   EXPECT_EQ(FP_SUBNORMAL, __fpclassifyl(ldouble_subnormal()));
-  EXPECT_EQ(FP_ZERO, __fpclassifyl(0.0l));
+  EXPECT_EQ(FP_ZERO, __fpclassifyl(0.0L));
 #else // __BIONIC__
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
@@ -227,7 +227,7 @@
 
 TEST(math, __isfinitel) {
 #if defined(__BIONIC__)
-  ASSERT_TRUE(__isfinitel(123.0l));
+  ASSERT_TRUE(__isfinitel(123.0L));
   ASSERT_FALSE(__isfinitel(HUGE_VALL));
 #else // __BIONIC__
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -245,7 +245,7 @@
 }
 
 TEST(math, __isinfl) {
-  ASSERT_FALSE(__isinfl(123.0l));
+  ASSERT_FALSE(__isinfl(123.0L));
   ASSERT_TRUE(__isinfl(HUGE_VALL));
 }
 
@@ -255,7 +255,7 @@
 }
 
 TEST(math, __isnanl) {
-  ASSERT_FALSE(__isnanl(123.0l));
+  ASSERT_FALSE(__isnanl(123.0L));
   ASSERT_TRUE(__isnanl(nanl("")));
 }
 
@@ -284,7 +284,7 @@
 
 TEST(math, __isnormall) {
 #if defined(__BIONIC__)
-  ASSERT_TRUE(__isnormall(123.0l));
+  ASSERT_TRUE(__isnormall(123.0L));
   ASSERT_FALSE(__isnormall(ldouble_subnormal()));
 #else // __BIONIC__
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -304,9 +304,9 @@
 }
 
 TEST(math, __signbitl) {
-  ASSERT_EQ(0l, __signbitl(0.0l));
-  ASSERT_EQ(0l, __signbitl(1.0l));
-  ASSERT_NE(0l, __signbitl(-1.0l));
+  ASSERT_EQ(0L, __signbitl(0.0L));
+  ASSERT_EQ(0L, __signbitl(1.0L));
+  ASSERT_NE(0L, __signbitl(-1.0L));
 }
 
 TEST(math, acos) {
@@ -318,7 +318,7 @@
 }
 
 TEST(math, acosl) {
-  ASSERT_DOUBLE_EQ(M_PI/2.0l, acosl(0.0l));
+  ASSERT_DOUBLE_EQ(M_PI/2.0L, acosl(0.0L));
 }
 
 TEST(math, asin) {
@@ -330,7 +330,7 @@
 }
 
 TEST(math, asinl) {
-  ASSERT_DOUBLE_EQ(0.0l, asinl(0.0l));
+  ASSERT_DOUBLE_EQ(0.0L, asinl(0.0L));
 }
 
 TEST(math, atan) {
@@ -342,7 +342,7 @@
 }
 
 TEST(math, atanl) {
-  ASSERT_DOUBLE_EQ(0.0l, atanl(0.0l));
+  ASSERT_DOUBLE_EQ(0.0L, atanl(0.0L));
 }
 
 TEST(math, atan2) {
@@ -354,7 +354,7 @@
 }
 
 TEST(math, atan2l) {
-  ASSERT_DOUBLE_EQ(0.0l, atan2l(0.0l, 0.0l));
+  ASSERT_DOUBLE_EQ(0.0L, atan2l(0.0L, 0.0L));
 }
 
 TEST(math, cos) {
@@ -366,11 +366,11 @@
 }
 
 TEST(math, cosl) {
-  ASSERT_DOUBLE_EQ(1.0l, cosl(0.0l));
+  ASSERT_DOUBLE_EQ(1.0L, cosl(0.0L));
 }
 
 TEST(math, sin) {
-  ASSERT_FLOAT_EQ(0.0, sin(0.0));
+  ASSERT_DOUBLE_EQ(0.0, sin(0.0));
 }
 
 TEST(math, sinf) {
@@ -378,7 +378,7 @@
 }
 
 TEST(math, sinl) {
-  ASSERT_DOUBLE_EQ(0.0l, sinl(0.0l));
+  ASSERT_DOUBLE_EQ(0.0L, sinl(0.0L));
 }
 
 TEST(math, tan) {
@@ -390,7 +390,7 @@
 }
 
 TEST(math, tanl) {
-  ASSERT_DOUBLE_EQ(0.0l, tanl(0.0l));
+  ASSERT_DOUBLE_EQ(0.0L, tanl(0.0L));
 }
 
 TEST(math, acosh) {
@@ -402,7 +402,7 @@
 }
 
 TEST(math, acoshl) {
-  ASSERT_DOUBLE_EQ(0.0l, acoshl(1.0l));
+  ASSERT_DOUBLE_EQ(0.0L, acoshl(1.0L));
 }
 
 TEST(math, asinh) {
@@ -414,7 +414,7 @@
 }
 
 TEST(math, asinhl) {
-  ASSERT_DOUBLE_EQ(0.0l, asinhl(0.0l));
+  ASSERT_DOUBLE_EQ(0.0L, asinhl(0.0L));
 }
 
 TEST(math, atanh) {
@@ -426,7 +426,7 @@
 }
 
 TEST(math, atanhl) {
-  ASSERT_DOUBLE_EQ(0.0l, atanhl(0.0l));
+  ASSERT_DOUBLE_EQ(0.0L, atanhl(0.0L));
 }
 
 TEST(math, cosh) {
@@ -438,7 +438,7 @@
 }
 
 TEST(math, coshl) {
-  ASSERT_DOUBLE_EQ(1.0l, coshl(0.0l));
+  ASSERT_DOUBLE_EQ(1.0L, coshl(0.0L));
 }
 
 TEST(math, sinh) {
@@ -450,7 +450,7 @@
 }
 
 TEST(math, sinhl) {
-  ASSERT_DOUBLE_EQ(0.0l, sinhl(0.0l));
+  ASSERT_DOUBLE_EQ(0.0L, sinhl(0.0L));
 }
 
 TEST(math, tanh) {
@@ -462,7 +462,7 @@
 }
 
 TEST(math, tanhl) {
-  ASSERT_DOUBLE_EQ(0.0l, tanhl(0.0l));
+  ASSERT_DOUBLE_EQ(0.0L, tanhl(0.0L));
 }
 
 TEST(math, log) {
@@ -474,7 +474,7 @@
 }
 
 TEST(math, logl) {
-  ASSERT_DOUBLE_EQ(1.0l, logl(M_E));
+  ASSERT_DOUBLE_EQ(1.0L, logl(M_E));
 }
 
 TEST(math, log2) {
@@ -486,7 +486,7 @@
 }
 
 TEST(math, log2l) {
-  ASSERT_DOUBLE_EQ(12.0l, log2l(4096.0l));
+  ASSERT_DOUBLE_EQ(12.0L, log2l(4096.0L));
 }
 
 TEST(math, log10) {
@@ -498,7 +498,7 @@
 }
 
 TEST(math, log10l) {
-  ASSERT_DOUBLE_EQ(3.0l, log10l(1000.0l));
+  ASSERT_DOUBLE_EQ(3.0L, log10l(1000.0L));
 }
 
 TEST(math, cbrt) {
@@ -510,7 +510,7 @@
 }
 
 TEST(math, cbrtl) {
-  ASSERT_DOUBLE_EQ(3.0l, cbrtl(27.0l));
+  ASSERT_DOUBLE_EQ(3.0L, cbrtl(27.0L));
 }
 
 TEST(math, sqrt) {
@@ -522,7 +522,7 @@
 }
 
 TEST(math, sqrtl) {
-  ASSERT_DOUBLE_EQ(2.0l, sqrtl(4.0l));
+  ASSERT_DOUBLE_EQ(2.0L, sqrtl(4.0L));
 }
 
 TEST(math, exp) {
@@ -536,8 +536,8 @@
 }
 
 TEST(math, expl) {
-  ASSERT_DOUBLE_EQ(1.0l, expl(0.0l));
-  ASSERT_DOUBLE_EQ(M_E, expl(1.0l));
+  ASSERT_DOUBLE_EQ(1.0L, expl(0.0L));
+  ASSERT_DOUBLE_EQ(M_E, expl(1.0L));
 }
 
 TEST(math, exp2) {
@@ -549,7 +549,7 @@
 }
 
 TEST(math, exp2l) {
-  ASSERT_DOUBLE_EQ(8.0l, exp2l(3.0l));
+  ASSERT_DOUBLE_EQ(8.0L, exp2l(3.0L));
 }
 
 TEST(math, expm1) {
@@ -561,7 +561,7 @@
 }
 
 TEST(math, expm1l) {
-  ASSERT_DOUBLE_EQ(M_E - 1.0l, expm1l(1.0l));
+  ASSERT_DOUBLE_EQ(M_E - 1.0L, expm1l(1.0L));
 }
 
 TEST(math, pow) {
@@ -579,10 +579,10 @@
 }
 
 TEST(math, powl) {
-  ASSERT_TRUE(__isnanl(powl(nanl(""), 3.0l)));
-  ASSERT_DOUBLE_EQ(1.0l, (powl(1.0l, nanl(""))));
-  ASSERT_TRUE(__isnanl(powl(2.0l, nanl(""))));
-  ASSERT_DOUBLE_EQ(8.0l, powl(2.0l, 3.0l));
+  ASSERT_TRUE(__isnanl(powl(nanl(""), 3.0L)));
+  ASSERT_DOUBLE_EQ(1.0L, (powl(1.0L, nanl(""))));
+  ASSERT_TRUE(__isnanl(powl(2.0L, nanl(""))));
+  ASSERT_DOUBLE_EQ(8.0L, powl(2.0L, 3.0L));
 }
 
 TEST(math, ceil) {
@@ -594,7 +594,7 @@
 }
 
 TEST(math, ceill) {
-  ASSERT_DOUBLE_EQ(1.0, ceill(0.9l));
+  ASSERT_DOUBLE_EQ(1.0L, ceill(0.9L));
 }
 
 TEST(math, floor) {
@@ -606,7 +606,7 @@
 }
 
 TEST(math, floorl) {
-  ASSERT_DOUBLE_EQ(1.0l, floorl(1.1l));
+  ASSERT_DOUBLE_EQ(1.0L, floorl(1.1L));
 }
 
 TEST(math, fabs) {
@@ -618,7 +618,7 @@
 }
 
 TEST(math, fabsl) {
-  ASSERT_DOUBLE_EQ(1.0l, fabsl(-1.0l));
+  ASSERT_DOUBLE_EQ(1.0L, fabsl(-1.0L));
 }
 
 TEST(math, ldexp) {
@@ -630,7 +630,7 @@
 }
 
 TEST(math, ldexpl) {
-  ASSERT_DOUBLE_EQ(16.0l, ldexpl(2.0l, 3.0));
+  ASSERT_DOUBLE_EQ(16.0L, ldexpl(2.0L, 3.0));
 }
 
 TEST(math, fmod) {
@@ -642,7 +642,7 @@
 }
 
 TEST(math, fmodl) {
-  ASSERT_DOUBLE_EQ(2.0l, fmodl(12.0l, 10.0l));
+  ASSERT_DOUBLE_EQ(2.0L, fmodl(12.0L, 10.0L));
 }
 
 TEST(math, remainder) {
@@ -654,7 +654,7 @@
 }
 
 TEST(math, remainderl) {
-  ASSERT_DOUBLE_EQ(2.0l, remainderl(12.0l, 10.0l));
+  ASSERT_DOUBLE_EQ(2.0L, remainderl(12.0L, 10.0L));
 }
 
 TEST(math, drem) {
@@ -678,9 +678,9 @@
 }
 
 TEST(math, fmaxl) {
-  ASSERT_DOUBLE_EQ(12.0l, fmaxl(12.0l, 10.0l));
-  ASSERT_DOUBLE_EQ(12.0l, fmaxl(12.0l, nanl("")));
-  ASSERT_DOUBLE_EQ(12.0l, fmaxl(nanl(""), 12.0l));
+  ASSERT_DOUBLE_EQ(12.0L, fmaxl(12.0L, 10.0L));
+  ASSERT_DOUBLE_EQ(12.0L, fmaxl(12.0L, nanl("")));
+  ASSERT_DOUBLE_EQ(12.0L, fmaxl(nanl(""), 12.0L));
 }
 
 TEST(math, fmin) {
@@ -696,9 +696,9 @@
 }
 
 TEST(math, fminl) {
-  ASSERT_DOUBLE_EQ(10.0l, fminl(12.0l, 10.0l));
-  ASSERT_DOUBLE_EQ(12.0l, fminl(12.0l, nanl("")));
-  ASSERT_DOUBLE_EQ(12.0l, fminl(nanl(""), 12.0l));
+  ASSERT_DOUBLE_EQ(10.0L, fminl(12.0L, 10.0L));
+  ASSERT_DOUBLE_EQ(12.0L, fminl(12.0L, nanl("")));
+  ASSERT_DOUBLE_EQ(12.0L, fminl(nanl(""), 12.0L));
 }
 
 TEST(math, fma) {
@@ -710,7 +710,7 @@
 }
 
 TEST(math, fmal) {
-  ASSERT_DOUBLE_EQ(10.0l, fmal(2.0l, 3.0l, 4.0l));
+  ASSERT_DOUBLE_EQ(10.0L, fmal(2.0L, 3.0L, 4.0L));
 }
 
 TEST(math, hypot) {
@@ -722,7 +722,7 @@
 }
 
 TEST(math, hypotl) {
-  ASSERT_DOUBLE_EQ(5.0l, hypotl(3.0l, 4.0l));
+  ASSERT_DOUBLE_EQ(5.0L, hypotl(3.0L, 4.0L));
 }
 
 TEST(math, erf) {
@@ -734,7 +734,7 @@
 }
 
 TEST(math, erfl) {
-  ASSERT_DOUBLE_EQ(0.84270079294971489l, erfl(1.0l));
+  ASSERT_DOUBLE_EQ(0.84270079294971489L, erfl(1.0L));
 }
 
 TEST(math, erfc) {
@@ -746,27 +746,27 @@
 }
 
 TEST(math, erfcl) {
-  ASSERT_DOUBLE_EQ(0.15729920705028513l, erfcl(1.0l));
+  ASSERT_DOUBLE_EQ(0.15729920705028513l, erfcl(1.0L));
 }
 
 TEST(math, lrint) {
   fesetround(FE_UPWARD); // lrint/lrintf/lrintl obey the rounding mode.
   ASSERT_EQ(1235, lrint(1234.01));
   ASSERT_EQ(1235, lrintf(1234.01f));
-  ASSERT_EQ(1235, lrintl(1234.01l));
+  ASSERT_EQ(1235, lrintl(1234.01L));
   fesetround(FE_TOWARDZERO); // lrint/lrintf/lrintl obey the rounding mode.
   ASSERT_EQ(1234, lrint(1234.01));
   ASSERT_EQ(1234, lrintf(1234.01f));
-  ASSERT_EQ(1234, lrintl(1234.01l));
+  ASSERT_EQ(1234, lrintl(1234.01L));
 
   fesetround(FE_UPWARD); // llrint/llrintf/llrintl obey the rounding mode.
   ASSERT_EQ(1235L, llrint(1234.01));
   ASSERT_EQ(1235L, llrintf(1234.01f));
-  ASSERT_EQ(1235L, llrintl(1234.01l));
+  ASSERT_EQ(1235L, llrintl(1234.01L));
   fesetround(FE_TOWARDZERO); // llrint/llrintf/llrintl obey the rounding mode.
   ASSERT_EQ(1234L, llrint(1234.01));
   ASSERT_EQ(1234L, llrintf(1234.01f));
-  ASSERT_EQ(1234L, llrintl(1234.01l));
+  ASSERT_EQ(1234L, llrintl(1234.01L));
 }
 
 TEST(math, rint) {
@@ -784,15 +784,15 @@
   ASSERT_TRUE((fetestexcept(FE_ALL_EXCEPT) & FE_INEXACT) != 0);
 
   feclearexcept(FE_ALL_EXCEPT); // rint/rintf/rintl do set the FE_INEXACT flag.
-  ASSERT_EQ(1234.0, rintl(1234.0l));
+  ASSERT_EQ(1234.0, rintl(1234.0L));
   ASSERT_TRUE((fetestexcept(FE_ALL_EXCEPT) & FE_INEXACT) == 0);
-  ASSERT_EQ(1235.0, rintl(1234.01l));
+  ASSERT_EQ(1235.0, rintl(1234.01L));
   ASSERT_TRUE((fetestexcept(FE_ALL_EXCEPT) & FE_INEXACT) != 0);
 
   fesetround(FE_TOWARDZERO); // rint/rintf obey the rounding mode.
   ASSERT_EQ(1234.0, rint(1234.01));
   ASSERT_EQ(1234.0f, rintf(1234.01f));
-  ASSERT_EQ(1234.0, rintl(1234.01l));
+  ASSERT_EQ(1234.0, rintl(1234.01L));
 }
 
 TEST(math, nearbyint) {
@@ -810,29 +810,29 @@
   ASSERT_TRUE((fetestexcept(FE_ALL_EXCEPT) & FE_INEXACT) == 0);
 
   feclearexcept(FE_ALL_EXCEPT); // nearbyint/nearbyintf/nearbyintl don't set the FE_INEXACT flag.
-  ASSERT_EQ(1234.0, nearbyintl(1234.0l));
+  ASSERT_EQ(1234.0, nearbyintl(1234.0L));
   ASSERT_TRUE((fetestexcept(FE_ALL_EXCEPT) & FE_INEXACT) == 0);
-  ASSERT_EQ(1235.0, nearbyintl(1234.01l));
+  ASSERT_EQ(1235.0, nearbyintl(1234.01L));
   ASSERT_TRUE((fetestexcept(FE_ALL_EXCEPT) & FE_INEXACT) == 0);
 
   fesetround(FE_TOWARDZERO); // nearbyint/nearbyintf/nearbyintl obey the rounding mode.
   ASSERT_EQ(1234.0, nearbyint(1234.01));
   ASSERT_EQ(1234.0f, nearbyintf(1234.01f));
-  ASSERT_EQ(1234.0, nearbyintl(1234.01l));
+  ASSERT_EQ(1234.0, nearbyintl(1234.01L));
 }
 
 TEST(math, lround) {
   fesetround(FE_UPWARD); // lround ignores the rounding mode.
   ASSERT_EQ(1234, lround(1234.01));
   ASSERT_EQ(1234, lroundf(1234.01f));
-  ASSERT_EQ(1234, lroundl(1234.01l));
+  ASSERT_EQ(1234, lroundl(1234.01L));
 }
 
 TEST(math, llround) {
   fesetround(FE_UPWARD); // llround ignores the rounding mode.
   ASSERT_EQ(1234L, llround(1234.01));
   ASSERT_EQ(1234L, llroundf(1234.01f));
-  ASSERT_EQ(1234L, llroundl(1234.01l));
+  ASSERT_EQ(1234L, llroundl(1234.01L));
 }
 
 TEST(math, ilogb) {
@@ -852,11 +852,11 @@
 }
 
 TEST(math, ilogbl) {
-  ASSERT_EQ(FP_ILOGB0, ilogbl(0.0l));
+  ASSERT_EQ(FP_ILOGB0, ilogbl(0.0L));
   ASSERT_EQ(FP_ILOGBNAN, ilogbl(nanl("")));
   ASSERT_EQ(INT_MAX, ilogbl(HUGE_VALL));
-  ASSERT_EQ(0l, ilogbl(1.0l));
-  ASSERT_EQ(3l, ilogbl(10.0l));
+  ASSERT_EQ(0L, ilogbl(1.0L));
+  ASSERT_EQ(3L, ilogbl(10.0L));
 }
 
 TEST(math, logb) {
@@ -876,11 +876,11 @@
 }
 
 TEST(math, logbl) {
-  ASSERT_EQ(-HUGE_VAL, logbl(0.0l));
+  ASSERT_EQ(-HUGE_VAL, logbl(0.0L));
   ASSERT_TRUE(isnan(logbl(nanl(""))));
   ASSERT_TRUE(isinf(logbl(HUGE_VALL)));
-  ASSERT_EQ(0.0l, logbl(1.0l));
-  ASSERT_EQ(3.0l, logbl(10.0l));
+  ASSERT_EQ(0.0L, logbl(1.0L));
+  ASSERT_EQ(3.0L, logbl(10.0L));
 }
 
 TEST(math, log1p) {
@@ -898,10 +898,10 @@
 }
 
 TEST(math, log1pl) {
-  ASSERT_EQ(-HUGE_VALL, log1pl(-1.0l));
+  ASSERT_EQ(-HUGE_VALL, log1pl(-1.0L));
   ASSERT_TRUE(isnan(log1pl(nanl(""))));
   ASSERT_TRUE(isinf(log1pl(HUGE_VALL)));
-  ASSERT_DOUBLE_EQ(1.0l, log1pl(M_E - 1.0l));
+  ASSERT_DOUBLE_EQ(1.0L, log1pl(M_E - 1.0L));
 }
 
 TEST(math, fdim) {
@@ -917,9 +917,9 @@
 }
 
 TEST(math, fdiml) {
-  ASSERT_DOUBLE_EQ(0.0l, fdiml(1.0l, 1.0l));
-  ASSERT_DOUBLE_EQ(1.0l, fdiml(2.0l, 1.0l));
-  ASSERT_DOUBLE_EQ(0.0l, fdiml(1.0l, 2.0l));
+  ASSERT_DOUBLE_EQ(0.0L, fdiml(1.0L, 1.0L));
+  ASSERT_DOUBLE_EQ(1.0L, fdiml(2.0L, 1.0L));
+  ASSERT_DOUBLE_EQ(0.0L, fdiml(1.0L, 2.0L));
 }
 
 TEST(math, round) {
@@ -944,10 +944,10 @@
 
 TEST(math, roundl) {
   fesetround(FE_TOWARDZERO); // roundl ignores the rounding mode and always rounds away from zero.
-  ASSERT_DOUBLE_EQ(1.0l, roundl(0.5l));
-  ASSERT_DOUBLE_EQ(-1.0l, roundl(-0.5l));
-  ASSERT_DOUBLE_EQ(0.0l, roundl(0.0l));
-  ASSERT_DOUBLE_EQ(-0.0l, roundl(-0.0l));
+  ASSERT_DOUBLE_EQ(1.0L, roundl(0.5L));
+  ASSERT_DOUBLE_EQ(-1.0L, roundl(-0.5L));
+  ASSERT_DOUBLE_EQ(0.0L, roundl(0.0L));
+  ASSERT_DOUBLE_EQ(-0.0L, roundl(-0.0L));
   ASSERT_TRUE(isnan(roundl(nanl(""))));
   ASSERT_DOUBLE_EQ(HUGE_VALL, roundl(HUGE_VALL));
 }
@@ -974,10 +974,10 @@
 
 TEST(math, truncl) {
   fesetround(FE_UPWARD); // truncl ignores the rounding mode and always rounds toward zero.
-  ASSERT_DOUBLE_EQ(1.0l, truncl(1.5l));
-  ASSERT_DOUBLE_EQ(-1.0l, truncl(-1.5l));
-  ASSERT_DOUBLE_EQ(0.0l, truncl(0.0l));
-  ASSERT_DOUBLE_EQ(-0.0l, truncl(-0.0l));
+  ASSERT_DOUBLE_EQ(1.0L, truncl(1.5L));
+  ASSERT_DOUBLE_EQ(-1.0L, truncl(-1.5L));
+  ASSERT_DOUBLE_EQ(0.0L, truncl(0.0L));
+  ASSERT_DOUBLE_EQ(-0.0L, truncl(-0.0L));
   ASSERT_TRUE(isnan(truncl(nan(""))));
   ASSERT_DOUBLE_EQ(HUGE_VALL, truncl(HUGE_VALL));
 }
@@ -995,12 +995,12 @@
 }
 
 TEST(math, nextafterl) {
-  ASSERT_DOUBLE_EQ(0.0l, nextafterl(0.0l, 0.0l));
+  ASSERT_DOUBLE_EQ(0.0L, nextafterl(0.0L, 0.0L));
   // Use a runtime value to accomodate the case when
   // sizeof(double) == sizeof(long double)
-  long double smallest_positive = ldexpl(1.0l, LDBL_MIN_EXP - LDBL_MANT_DIG);
-  ASSERT_DOUBLE_EQ(smallest_positive, nextafterl(0.0l, 1.0l));
-  ASSERT_DOUBLE_EQ(0.0l, nextafterl(0.0l, -1.0l));
+  long double smallest_positive = ldexpl(1.0L, LDBL_MIN_EXP - LDBL_MANT_DIG);
+  ASSERT_DOUBLE_EQ(smallest_positive, nextafterl(0.0L, 1.0L));
+  ASSERT_DOUBLE_EQ(0.0L, nextafterl(0.0L, -1.0L));
 }
 
 // TODO: nexttoward
@@ -1022,10 +1022,10 @@
 }
 
 TEST(math, copysignl) {
-  ASSERT_DOUBLE_EQ(0.0l, copysignl(0.0l, 1.0l));
-  ASSERT_DOUBLE_EQ(-0.0l, copysignl(0.0l, -1.0l));
-  ASSERT_DOUBLE_EQ(2.0l, copysignl(2.0l, 1.0l));
-  ASSERT_DOUBLE_EQ(-2.0l, copysignl(2.0l, -1.0l));
+  ASSERT_DOUBLE_EQ(0.0L, copysignl(0.0L, 1.0L));
+  ASSERT_DOUBLE_EQ(-0.0L, copysignl(0.0L, -1.0L));
+  ASSERT_DOUBLE_EQ(2.0L, copysignl(2.0L, 1.0L));
+  ASSERT_DOUBLE_EQ(-2.0L, copysignl(2.0L, -1.0L));
 }
 
 TEST(math, significand) {
@@ -1043,9 +1043,9 @@
 extern "C" long double significandl(long double); // BSD's <math.h> doesn't declare this.
 
 TEST(math, significandl) {
-  ASSERT_DOUBLE_EQ(0.0l, significandl(0.0l));
-  ASSERT_DOUBLE_EQ(1.2l, significandl(1.2l));
-  ASSERT_DOUBLE_EQ(1.5375l, significandl(12.3l));
+  ASSERT_DOUBLE_EQ(0.0L, significandl(0.0L));
+  ASSERT_DOUBLE_EQ(1.2L, significandl(1.2L));
+  ASSERT_DOUBLE_EQ(1.5375L, significandl(12.3L));
 }
 
 TEST(math, scalb) {
@@ -1065,7 +1065,7 @@
 }
 
 TEST(math, scalblnl) {
-  ASSERT_DOUBLE_EQ(12.0l, scalblnl(3.0l, 2L));
+  ASSERT_DOUBLE_EQ(12.0L, scalblnl(3.0L, 2L));
 }
 
 TEST(math, scalbn) {
@@ -1077,7 +1077,7 @@
 }
 
 TEST(math, scalbnl) {
-  ASSERT_DOUBLE_EQ(12.0l, scalbnl(3.0l, 2));
+  ASSERT_DOUBLE_EQ(12.0L, scalbnl(3.0L, 2));
 }
 
 TEST(math, gamma) {
@@ -1117,7 +1117,7 @@
 }
 
 TEST(math, lgammal) {
-  ASSERT_DOUBLE_EQ(logl(24.0l), lgammal(5.0l));
+  ASSERT_DOUBLE_EQ(logl(24.0L), lgammal(5.0L));
 }
 
 TEST(math, lgamma_r) {
@@ -1141,7 +1141,7 @@
 }
 
 TEST(math, tgammal) {
-  ASSERT_DOUBLE_EQ(24.0l, tgammal(5.0l));
+  ASSERT_DOUBLE_EQ(24.0L, tgammal(5.0L));
 }
 
 TEST(math, j0) {
@@ -1218,29 +1218,29 @@
 
 TEST(math, frexpl) {
   int exp;
-  long double ldr = frexpl(1024.0l, &exp);
-  ASSERT_DOUBLE_EQ(1024.0l, scalbnl(ldr, exp));
+  long double ldr = frexpl(1024.0L, &exp);
+  ASSERT_DOUBLE_EQ(1024.0L, scalbnl(ldr, exp));
 }
 
 TEST(math, modf) {
   double di;
-  double df = modf(123.456, &di);
+  double df = modf(123.75, &di);
   ASSERT_DOUBLE_EQ(123.0, di);
-  ASSERT_DOUBLE_EQ(0.45600000000000307, df);
+  ASSERT_DOUBLE_EQ(0.75, df);
 }
 
 TEST(math, modff) {
   float fi;
-  float ff = modff(123.456f, &fi);
+  float ff = modff(123.75f, &fi);
   ASSERT_FLOAT_EQ(123.0f, fi);
-  ASSERT_FLOAT_EQ(0.45600128f, ff);
+  ASSERT_FLOAT_EQ(0.75f, ff);
 }
 
 TEST(math, modfl) {
   long double ldi;
-  long double ldf = modfl(123.456l, &ldi);
-  ASSERT_DOUBLE_EQ(123.0l, ldi);
-  ASSERT_DOUBLE_EQ(0.45600000000000002l, ldf);
+  long double ldf = modfl(123.75L, &ldi);
+  ASSERT_DOUBLE_EQ(123.0L, ldi);
+  ASSERT_DOUBLE_EQ(0.75L, ldf);
 }
 
 TEST(math, remquo) {
@@ -1259,9 +1259,9 @@
 
 TEST(math, remquol) {
   int q;
-  long double ld = remquol(13.0l, 4.0l, &q);
-  ASSERT_DOUBLE_EQ(3l, q);
-  ASSERT_DOUBLE_EQ(1.0l, ld);
+  long double ld = remquol(13.0L, 4.0L, &q);
+  ASSERT_DOUBLE_EQ(3L, q);
+  ASSERT_DOUBLE_EQ(1.0L, ld);
 }
 
 // https://code.google.com/p/android/issues/detail?id=6697
diff --git a/tests/sys_select_test.cpp b/tests/sys_select_test.cpp
index 4bb2d18..c1732ee 100644
--- a/tests/sys_select_test.cpp
+++ b/tests/sys_select_test.cpp
@@ -20,6 +20,8 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <sys/select.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 
 TEST(sys_select, fd_set_smoke) {
   fd_set fds;
@@ -43,6 +45,32 @@
   EXPECT_FALSE(FD_ISSET(1, &fds));
 }
 
+#define DELAY_MSG "1234"
+
+static void DelayedWrite(int* pid, int* fd) {
+  int fds[2];
+  ASSERT_EQ(0, pipe(fds));
+
+  if ((*pid = fork()) == 0) {
+    close(fds[0]);
+    usleep(5000);
+    EXPECT_EQ(5, write(fds[1], DELAY_MSG, sizeof(DELAY_MSG)));
+    close(fds[1]);
+    exit(0);
+  }
+  ASSERT_LT(0, *pid);
+  close(fds[1]);
+
+  *fd = fds[0];
+}
+
+static void DelayedWriteCleanup(int pid, int fd) {
+  char buf[sizeof(DELAY_MSG)];
+  ASSERT_EQ(static_cast<ssize_t>(sizeof(DELAY_MSG)), read(fd, buf, sizeof(DELAY_MSG)));
+  ASSERT_STREQ(DELAY_MSG, buf);
+  ASSERT_EQ(pid, waitpid(pid, NULL, 0));
+}
+
 TEST(sys_select, select_smoke) {
   fd_set r;
   FD_ZERO(&r);
@@ -72,8 +100,17 @@
 
   // Valid timeout...
   tv.tv_sec = 1;
-  ASSERT_EQ(2, select(max, &r, &w, &e, &tv));
-  ASSERT_NE(0, tv.tv_usec); // ...which got updated.
+  int pid, fd;
+  DelayedWrite(&pid, &fd);
+
+  FD_ZERO(&r);
+  FD_SET(fd, &r);
+  ASSERT_EQ(1, select(fd+1, &r, NULL, NULL, &tv));
+  // Both tv_sec and tv_nsec should have been updated.
+  ASSERT_EQ(0, tv.tv_sec);
+  ASSERT_NE(0, tv.tv_usec);
+
+  DelayedWriteCleanup(pid, fd);
 }
 
 TEST(sys_select, pselect_smoke) {
@@ -109,6 +146,15 @@
 
   // Valid timeout...
   tv.tv_sec = 1;
-  ASSERT_EQ(2, pselect(max, &r, &w, &e, &tv, &ss));
-  ASSERT_EQ(0, tv.tv_nsec); // ...which did _not_ get updated.
+  int pid, fd;
+  DelayedWrite(&pid, &fd);
+
+  FD_ZERO(&r);
+  FD_SET(fd, &r);
+  ASSERT_EQ(1, pselect(fd+1, &r, NULL, NULL, &tv, NULL));
+  // Neither tv_sec nor tv_nsec should have been updated.
+  ASSERT_EQ(1, tv.tv_sec);
+  ASSERT_EQ(0, tv.tv_nsec);
+
+  DelayedWriteCleanup(pid, fd);
 }
diff --git a/tests/sys_socket_test.cpp b/tests/sys_socket_test.cpp
index 901ac17..018889a 100644
--- a/tests/sys_socket_test.cpp
+++ b/tests/sys_socket_test.cpp
@@ -17,18 +17,257 @@
 #include <gtest/gtest.h>
 
 #include <errno.h>
+#include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/un.h>
+#include <fcntl.h>
 
-TEST(sys_socket, recvmmsg) {
-#if !defined(__GLIBC__) // TODO: Android's prebuilt gcc is too old for recvmmsg/sendmmsg.
-  ASSERT_EQ(-1, recvmmsg(-1, NULL, 0, 0, NULL));
+#if defined(__BIONIC__)
+  #define ACCEPT4_SUPPORTED 1
+  #define RECVMMSG_SUPPORTED 1
+  #define SENDMMSG_SUPPORTED 1
+#elif defined(__GLIBC_PREREQ)
+  #if __GLIBC_PREREQ(2, 9)
+    #define ACCEPT4_SUPPORTED 1
+  #endif
+  #if __GLIBC_PREREQ(2, 12)
+    #define RECVMMSG_SUPPORTED 1
+  #endif
+  #if __GLIBC_PREREQ(2, 14)
+    #define SENDMMSG_SUPPORTED 1
+  #endif
+#endif
+
+#if defined(ACCEPT4_SUPPORTED) || defined(RECVMMSG_SUPPORTED) || defined(SENDMMSG_SUPPORTED)
+
+#define SOCK_PATH "test"
+
+static void* ConnectFn(void* data) {
+  bool (*callback_fn)(int) = reinterpret_cast<bool (*)(int)>(data);
+  void* return_value = NULL;
+
+  int fd = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
+  if (fd < 0) {
+    GTEST_LOG_(ERROR) << "socket call failed: " << strerror(errno);
+    return reinterpret_cast<void*>(-1);
+  }
+
+  struct sockaddr_un addr;
+  memset(&addr, 0, sizeof(addr));
+  addr.sun_family = AF_UNIX;
+  addr.sun_path[0] = '\0';
+  strcpy(addr.sun_path + 1, SOCK_PATH);
+
+  if (connect(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
+    GTEST_LOG_(ERROR) << "connect call failed: " << strerror(errno);
+    return_value = reinterpret_cast<void*>(-1);
+  }
+  else if (callback_fn != NULL && !callback_fn(fd)) {
+    return_value = reinterpret_cast<void*>(-1);
+  }
+
+  close(fd);
+
+  return return_value;
+}
+
+static void RunTest(void (*test_fn)(struct sockaddr_un*, int),
+                    bool (*callback_fn)(int fd)) {
+  int fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
+  ASSERT_NE(fd, -1) << strerror(errno);
+
+  struct sockaddr_un addr;
+  memset(&addr, 0, sizeof(addr));
+  addr.sun_family = AF_UNIX;
+  addr.sun_path[0] = '\0';
+  strcpy(addr.sun_path + 1, SOCK_PATH);
+
+  ASSERT_NE(-1, bind(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))) << strerror(errno);
+
+  ASSERT_NE(-1, listen(fd, 1)) << strerror(errno);
+
+  pthread_t thread;
+  ASSERT_EQ(0, pthread_create(&thread, NULL, ConnectFn, reinterpret_cast<void*>(callback_fn)));
+
+  fd_set read_set;
+  FD_ZERO(&read_set);
+  FD_SET(fd, &read_set);
+  timeval tv;
+  tv.tv_sec = 5;
+  tv.tv_usec = 0;
+  ASSERT_LT(0, select(fd+1, &read_set, NULL, NULL, &tv));
+
+  test_fn(&addr, fd);
+
+  void* ret_val;
+  ASSERT_EQ(0, pthread_join(thread, &ret_val));
+  ASSERT_EQ(NULL, ret_val);
+
+  close(fd);
+}
+#endif
+
+TEST(sys_socket, accept4_error) {
+#if defined(ACCEPT4_SUPPORTED)
+  ASSERT_EQ(-1, accept4(-1, NULL, NULL, 0));
   ASSERT_EQ(EBADF, errno);
+#else
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
-TEST(sys_socket, sendmmsg) {
-#if !defined(__GLIBC__) // TODO: Android's prebuilt gcc is too old for recvmmsg/sendmmsg.
+#if defined(ACCEPT4_SUPPORTED)
+static void TestAccept4(struct sockaddr_un* addr, int fd) {
+  socklen_t len = sizeof(*addr);
+  int fd_acc = accept4(fd, reinterpret_cast<struct sockaddr*>(addr), &len, SOCK_CLOEXEC);
+  ASSERT_NE(fd_acc, -1) << strerror(errno);
+
+  // Check that the flag was set properly.
+  ASSERT_EQ(FD_CLOEXEC, fcntl(fd_acc, F_GETFD) & FD_CLOEXEC);
+
+  close(fd_acc);
+}
+#endif
+
+TEST(sys_socket, accept4_smoke) {
+#if defined(ACCEPT4_SUPPORTED)
+  RunTest(TestAccept4, NULL);
+#else
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+#if defined(RECVMMSG_SUPPORTED)
+const char* g_RecvMsgs[] = {
+  "RECVMMSG_ONE",
+  "RECVMMSG_TWO",
+  "RECVMMSG_THREE",
+};
+#define NUM_RECV_MSGS (sizeof(g_RecvMsgs)/sizeof(const char*))
+
+static bool SendMultiple(int fd) {
+  for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
+    if (send(fd, g_RecvMsgs[i], strlen(g_RecvMsgs[i]) + 1, 0) < 0) {
+      GTEST_LOG_(ERROR) << "send call failed: " << strerror(errno);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static void TestRecvMMsg(struct sockaddr_un *addr, int fd) {
+  socklen_t len = sizeof(*addr);
+  int fd_acc = accept(fd, reinterpret_cast<struct sockaddr*>(addr), &len);
+  ASSERT_NE(fd_acc, -1) << strerror(errno);
+
+  struct mmsghdr msgs[NUM_RECV_MSGS];
+  memset(msgs, 0, sizeof(struct mmsghdr)*NUM_RECV_MSGS);
+
+  struct iovec io[NUM_RECV_MSGS];
+  char bufs[NUM_RECV_MSGS][100];
+  for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
+    io[i].iov_base = reinterpret_cast<void*>(bufs[i]);
+    io[i].iov_len = strlen(g_RecvMsgs[i]) + 1;
+
+    msgs[i].msg_hdr.msg_iov = &io[i];
+    msgs[i].msg_hdr.msg_iovlen = 1;
+    msgs[i].msg_len = sizeof(struct msghdr);
+  }
+
+  struct timespec ts;
+  memset(&ts, 0, sizeof(ts));
+  ts.tv_sec = 5;
+  ts.tv_nsec = 0;
+  ASSERT_EQ(NUM_RECV_MSGS, recvmmsg(fd_acc, msgs, NUM_RECV_MSGS, 0, &ts)) << strerror(errno);
+  for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
+    ASSERT_STREQ(g_RecvMsgs[i], bufs[i]);
+  }
+
+  close(fd_acc);
+}
+#endif
+
+TEST(sys_socket, recvmmsg_smoke) {
+#if defined(RECVMMSG_SUPPORTED)
+  RunTest(TestRecvMMsg, SendMultiple);
+#else
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+TEST(sys_socket, recvmmsg_error) {
+#if defined(RECVMMSG_SUPPORTED)
+  ASSERT_EQ(-1, recvmmsg(-1, NULL, 0, 0, NULL));
+  ASSERT_EQ(EBADF, errno);
+#else
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+#if defined(SENDMMSG_SUPPORTED)
+const char* g_SendMsgs[] = {
+  "MSG_ONE",
+  "MSG_TWO",
+  "MSG_THREE"
+};
+#define NUM_SEND_MSGS (sizeof(g_SendMsgs)/sizeof(const char*))
+
+static bool SendMMsg(int fd) {
+  struct mmsghdr msgs[NUM_SEND_MSGS];
+  memset(msgs, 0, sizeof(struct mmsghdr)*NUM_SEND_MSGS);
+  struct iovec io[NUM_SEND_MSGS];
+  for (size_t i = 0; i < NUM_SEND_MSGS; i++) {
+    io[i].iov_base = reinterpret_cast<void*>(const_cast<char*>(g_SendMsgs[i]));
+    io[i].iov_len = strlen(g_SendMsgs[i]) + 1;
+    msgs[i].msg_hdr.msg_iov = &io[i];
+    msgs[i].msg_hdr.msg_iovlen = 1;
+    msgs[i].msg_len = sizeof(struct msghdr);
+  }
+
+  if (sendmmsg(fd, msgs, NUM_SEND_MSGS, 0) < 0) {
+    GTEST_LOG_(ERROR) << "sendmmsg call failed: " << strerror(errno);
+    return false;
+  }
+  return true;
+}
+
+static void TestSendMMsg(struct sockaddr_un *addr, int fd) {
+  socklen_t len = sizeof(*addr);
+  int fd_acc = accept(fd, reinterpret_cast<struct sockaddr*>(addr), &len);
+  ASSERT_NE(fd_acc, -1) << strerror(errno);
+
+  fd_set read_set;
+  FD_ZERO(&read_set);
+  FD_SET(fd_acc, &read_set);
+
+  for (size_t i = 0; i < NUM_SEND_MSGS; i++) {
+    timeval tv;
+    tv.tv_sec = 5;
+    tv.tv_usec = 0;
+    ASSERT_LT(0, select(fd_acc+1, &read_set, NULL, NULL, &tv));
+    char buffer[100];
+    ASSERT_EQ(strlen(g_SendMsgs[i]) + 1, recv(fd_acc, buffer, sizeof(buffer), 0));
+    ASSERT_STREQ(g_SendMsgs[i], buffer);
+  }
+
+  close(fd_acc);
+}
+#endif
+
+TEST(sys_socket, sendmmsg_smoke) {
+#if defined(SENDMMSG_SUPPORTED)
+  RunTest(TestSendMMsg, SendMMsg);
+#else
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+TEST(sys_socket, sendmmsg_error) {
+#if defined(SENDMMSG_SUPPORTED)
   ASSERT_EQ(-1, sendmmsg(-1, NULL, 0, 0));
   ASSERT_EQ(EBADF, errno);
+#else
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 26b7775..c055769 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -387,3 +387,51 @@
   ASSERT_EQ(ESRCH, pthread_detach(tdd.thread_id));
 #endif
 }
+
+TEST(time, strtotimeval) {
+#if defined(__BIONIC__)
+  struct timeval tv1;
+  char* rest1 = strtotimeval("10.123456", &tv1);
+  ASSERT_EQ(10, tv1.tv_sec);
+  ASSERT_EQ(123456, tv1.tv_usec);
+  ASSERT_EQ('\0', *rest1);
+
+  // strtotimeval interprets the fractional part as microseconds and thus will
+  // only consider its first 6 digits. Even so it should consume all valid
+  // digits.
+  struct timeval tv2;
+  char* rest2 = strtotimeval(".1234567", &tv2);
+  ASSERT_EQ(0, tv2.tv_sec);
+  ASSERT_EQ(123456, tv2.tv_usec);
+  ASSERT_EQ('\0', *rest2);
+
+  struct timeval tv3;
+  char* rest3 = strtotimeval("1.1a", &tv3);
+  ASSERT_EQ(1, tv3.tv_sec);
+  ASSERT_EQ(100000, tv3.tv_usec);
+  ASSERT_EQ('a', *rest3);
+
+  struct timeval tv4;
+  char* rest4 = strtotimeval("a", &tv4);
+  ASSERT_EQ(0, tv4.tv_sec);
+  ASSERT_EQ(0, tv4.tv_usec);
+  ASSERT_EQ('a', *rest4);
+
+  struct timeval tv5;
+  char* rest5 = strtotimeval("0", &tv5);
+  ASSERT_EQ(0, tv5.tv_sec);
+  ASSERT_EQ(0, tv5.tv_usec);
+  ASSERT_EQ('\0', *rest5);
+
+  // TODO: should we reject this case and just return '.'?
+  struct timeval tv6;
+  char* rest6 = strtotimeval(".", &tv6);
+  ASSERT_EQ(0, tv6.tv_sec);
+  ASSERT_EQ(0, tv6.tv_usec);
+  ASSERT_EQ('\0', *rest6);
+
+#else // __BIONIC__
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif // __BIONIC__
+}
+