Merge "Add __aeabi_idiv to the dummy reference list."
diff --git a/libc/Android.mk b/libc/Android.mk
index 58d8a58..4bf996b 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -222,7 +222,6 @@
 	bionic/signame.c \
 	bionic/sigsetmask.c \
 	bionic/sigsuspend.c \
-	bionic/sigwait.c \
 	bionic/sleep.c \
 	bionic/statfs.c \
 	bionic/strcoll.c \
@@ -276,14 +275,18 @@
     bionic/dirent.cpp \
     bionic/eventfd.cpp \
     bionic/__fgets_chk.cpp \
+    bionic/getauxval.cpp \
     bionic/getcwd.cpp \
     bionic/libgen.cpp \
     bionic/__memcpy_chk.cpp \
     bionic/__memmove_chk.cpp \
     bionic/__memset_chk.cpp \
+    bionic/pthread_sigmask.cpp \
     bionic/raise.cpp \
     bionic/__set_errno.cpp \
     bionic/setlocale.cpp \
+    bionic/signalfd.cpp \
+    bionic/sigwait.cpp \
     bionic/__strcat_chk.cpp \
     bionic/__strcpy_chk.cpp \
     bionic/strerror.cpp \
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 2973caa..dc139bd 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -225,6 +225,7 @@
 int     __rt_sigprocmask:rt_sigprocmask (int  how, const sigset_t *set, sigset_t *oset, size_t sigsetsize)  175,175,195
 int     __rt_sigtimedwait:rt_sigtimedwait(const sigset_t *set, struct siginfo_t  *info, struct timespec_t  *timeout, size_t  sigset_size)  177,177,197
 int     sigpending(sigset_t *)  73
+int     signalfd4(int fd, const sigset_t *mask, size_t sizemask, int flags)  355,327,324
 
 # sockets
 int           socket(int, int, int)              281,-1,183
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index 62eda87..5cb46b5 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -150,6 +150,7 @@
 syscall_src += arch-arm/syscalls/__rt_sigprocmask.S
 syscall_src += arch-arm/syscalls/__rt_sigtimedwait.S
 syscall_src += arch-arm/syscalls/sigpending.S
+syscall_src += arch-arm/syscalls/signalfd4.S
 syscall_src += arch-arm/syscalls/socket.S
 syscall_src += arch-arm/syscalls/socketpair.S
 syscall_src += arch-arm/syscalls/bind.S
diff --git a/libc/arch-arm/syscalls/signalfd4.S b/libc/arch-arm/syscalls/signalfd4.S
new file mode 100644
index 0000000..1ec7055
--- /dev/null
+++ b/libc/arch-arm/syscalls/signalfd4.S
@@ -0,0 +1,14 @@
+/* autogenerated by gensyscalls.py */
+#include <machine/asm.h>
+#include <sys/linux-syscalls.h>
+
+ENTRY(signalfd4)
+    .save   {r4, r7}
+    stmfd   sp!, {r4, r7}
+    ldr     r7, =__NR_signalfd4
+    swi     #0
+    ldmfd   sp!, {r4, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+END(signalfd4)
diff --git a/libc/arch-mips/syscalls.mk b/libc/arch-mips/syscalls.mk
index 263f307..7e40c2e 100644
--- a/libc/arch-mips/syscalls.mk
+++ b/libc/arch-mips/syscalls.mk
@@ -153,6 +153,7 @@
 syscall_src += arch-mips/syscalls/__rt_sigprocmask.S
 syscall_src += arch-mips/syscalls/__rt_sigtimedwait.S
 syscall_src += arch-mips/syscalls/sigpending.S
+syscall_src += arch-mips/syscalls/signalfd4.S
 syscall_src += arch-mips/syscalls/socket.S
 syscall_src += arch-mips/syscalls/socketpair.S
 syscall_src += arch-mips/syscalls/bind.S
diff --git a/libc/arch-mips/syscalls/signalfd4.S b/libc/arch-mips/syscalls/signalfd4.S
new file mode 100644
index 0000000..7e4082c
--- /dev/null
+++ b/libc/arch-mips/syscalls/signalfd4.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+    .text
+    .globl signalfd4
+    .align 4
+    .ent signalfd4
+
+signalfd4:
+    .set noreorder
+    .cpload $t9
+    li $v0, __NR_signalfd4
+    syscall
+    bnez $a3, 1f
+    move $a0, $v0
+    j $ra
+    nop
+1:
+    la $t9,__set_errno
+    j $t9
+    nop
+    .set reorder
+    .end signalfd4
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index 2517ebf..e196c02 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -154,6 +154,7 @@
 syscall_src += arch-x86/syscalls/__rt_sigprocmask.S
 syscall_src += arch-x86/syscalls/__rt_sigtimedwait.S
 syscall_src += arch-x86/syscalls/sigpending.S
+syscall_src += arch-x86/syscalls/signalfd4.S
 syscall_src += arch-x86/syscalls/socket.S
 syscall_src += arch-x86/syscalls/bind.S
 syscall_src += arch-x86/syscalls/connect.S
diff --git a/libc/arch-x86/syscalls/signalfd4.S b/libc/arch-x86/syscalls/signalfd4.S
new file mode 100644
index 0000000..f1c2ea0
--- /dev/null
+++ b/libc/arch-x86/syscalls/signalfd4.S
@@ -0,0 +1,32 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type signalfd4, @function
+    .globl signalfd4
+    .align 4
+
+signalfd4:
+    pushl   %ebx
+    pushl   %ecx
+    pushl   %edx
+    pushl   %esi
+    mov     20(%esp), %ebx
+    mov     24(%esp), %ecx
+    mov     28(%esp), %edx
+    mov     32(%esp), %esi
+    movl    $__NR_signalfd4, %eax
+    int     $0x80
+    cmpl    $-129, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %esi
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
diff --git a/libc/bionic/dlmalloc.c b/libc/bionic/dlmalloc.c
index dc5f8ab..6287549 100644
--- a/libc/bionic/dlmalloc.c
+++ b/libc/bionic/dlmalloc.c
@@ -24,6 +24,10 @@
 #define USAGE_ERROR_ACTION(m,p) \
     __bionic_heap_error("ARGUMENT IS INVALID HEAP ADDRESS", __FUNCTION__, p)
 
+/* Bionic named anonymous memory declarations */
+static void* named_anonymous_mmap(size_t length);
+#define MMAP(s) named_anonymous_mmap(s)
+
 /*
  * Ugly inclusion of C file so that bionic specific #defines configure
  * dlmalloc.
@@ -74,3 +78,40 @@
     /* So that we can get a memory dump around p */
     *((int **) 0xdeadbaad) = (int *) p;
 }
+
+/* Bionic named anonymous memory definitions */
+#include <linux/ashmem.h>
+static int __ashmem_create_region(const char* name, size_t size)
+{
+    int fd, ret;
+    fd = open("/dev/ashmem", O_RDWR);
+    if (fd < 0)
+        return fd;
+    if (name != NULL) {
+        char buf[ASHMEM_NAME_LEN];
+
+        strlcpy(buf, name, sizeof(buf));
+        ret = ioctl(fd, ASHMEM_SET_NAME, buf);
+        if (ret < 0) {  /* error */
+            close(fd);
+            return ret;
+        }
+    }
+    ret = ioctl(fd, ASHMEM_SET_SIZE, size);
+    if (ret < 0) {  /* error */
+        close(fd);
+        return ret;
+    }
+    return fd;
+}
+
+static void* named_anonymous_mmap(size_t length)
+{
+    void* ret;
+    int fd = __ashmem_create_region("libc malloc", length);
+    if (fd < 0)
+        return MAP_FAILED;
+    ret = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+    close (fd);
+    return ret;
+}
diff --git a/libc/bionic/getauxval.cpp b/libc/bionic/getauxval.cpp
new file mode 100644
index 0000000..38a05fc
--- /dev/null
+++ b/libc/bionic/getauxval.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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 <stddef.h>
+#include <sys/cdefs.h>
+#include <sys/auxv.h>
+#include <private/bionic_auxv.h>
+#include <elf.h>
+
+__LIBC_HIDDEN__
+Elf32_auxv_t* __libc_auxv = NULL;
+
+extern "C" unsigned long int getauxval(unsigned long int type) {
+  Elf32_auxv_t* v;
+
+  for (v = __libc_auxv; v->a_type != AT_NULL; v++) {
+    if (v->a_type == type) {
+      return v->a_un.a_val;
+    }
+  }
+
+  return 0;
+}
diff --git a/libc/bionic/libc_init_common.c b/libc/bionic/libc_init_common.c
index fb164f4..86e1eb5 100644
--- a/libc/bionic/libc_init_common.c
+++ b/libc/bionic/libc_init_common.c
@@ -38,6 +38,7 @@
 
 #include <bionic_tls.h>
 #include <errno.h>
+#include <private/bionic_auxv.h>
 
 extern unsigned __get_sp(void);
 extern pid_t gettid(void);
@@ -95,6 +96,15 @@
   __progname = argv[0] ? argv[0] : "<unknown>";
   environ = envp;
 
+  // The auxiliary vector is at the end of the environment block
+  while(*envp != NULL) {
+    envp++;
+  }
+  /* The end of the environment block is marked by two NULL pointers */
+  envp++;
+
+  __libc_auxv = (Elf32_auxv_t*) envp;
+
   __system_properties_init(); // Requires 'environ'.
 }
 
diff --git a/libc/bionic/libc_init_static.c b/libc/bionic/libc_init_static.c
index ba7f008..24a4397 100644
--- a/libc/bionic/libc_init_static.c
+++ b/libc/bionic/libc_init_static.c
@@ -49,6 +49,7 @@
 #include <bionic_tls.h>
 #include <errno.h>
 #include <sys/mman.h>
+#include <sys/auxv.h>
 
 // Returns the address of the page containing address 'x'.
 #define PAGE_START(x)  ((x) & PAGE_MASK)
@@ -65,27 +66,13 @@
     }
 }
 
-/*
- * Find the value of the AT_* variable passed to us by the kernel.
- */
-static unsigned find_aux(unsigned *vecs, unsigned type) {
-    while (vecs[0]) {
-        if (vecs[0] == type) {
-            return vecs[1];
-        }
-        vecs += 2;
-    }
-
-    return 0; // should never happen
-}
-
-static void apply_gnu_relro(unsigned *vecs) {
+static void apply_gnu_relro() {
     Elf32_Phdr *phdr_start;
-    unsigned phdr_ct;
+    unsigned long int phdr_ct;
     Elf32_Phdr *phdr;
 
-    phdr_start = (Elf32_Phdr *) find_aux(vecs, AT_PHDR);
-    phdr_ct    = find_aux(vecs, AT_PHNUM);
+    phdr_start = (Elf32_Phdr *) getauxval(AT_PHDR);
+    phdr_ct    = getauxval(AT_PHNUM);
 
     for (phdr = phdr_start; phdr < (phdr_start + phdr_ct); phdr++) {
         if (phdr->p_type != PT_GNU_RELRO)
@@ -108,13 +95,14 @@
 {
     int  argc;
     char **argv, **envp;
-    unsigned *vecs;
 
     __libc_init_tls(NULL);
 
     /* Initialize the C runtime environment */
     __libc_init_common(elfdata);
 
+    apply_gnu_relro();
+
     /* Several Linux ABIs don't pass the onexit pointer, and the ones that
      * do never use it.  Therefore, we ignore it.
      */
@@ -129,14 +117,6 @@
     argv = (char**)(elfdata + 1);
     envp = argv + argc + 1;
 
-    // The auxiliary vector is at the end of the environment block
-    vecs = (unsigned *) envp;
-    while (vecs[0] != 0) {
-        vecs++;
-    }
-    /* The end of the environment block is marked by two NULL pointers */
-    vecs++;
-
     /* The executable may have its own destructors listed in its .fini_array
      * so we need to ensure that these are called when the program exits
      * normally.
@@ -144,6 +124,5 @@
     if (structors->fini_array)
         __cxa_atexit(__libc_fini,structors->fini_array,NULL);
 
-    apply_gnu_relro(vecs);
     exit(slingshot(argc, argv, envp));
 }
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index b685f2d..f294723 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -450,22 +450,18 @@
     return 0;
 }
 
-int pthread_attr_setstackaddr(pthread_attr_t * attr, void * stack_addr)
+int pthread_attr_setstackaddr(pthread_attr_t * attr __attribute__((unused)),
+                               void * stack_addr __attribute__((unused)))
 {
-#if 1
-    // It's not clear if this is setting the top or bottom of the stack, so don't handle it for now.
+    // This was removed from POSIX.1-2008, and is not implemented on bionic.
+    // Needed for ABI compatibility with the NDK.
     return ENOSYS;
-#else
-    if ((uint32_t)stack_addr & (PAGE_SIZE - 1)) {
-        return EINVAL;
-    }
-    attr->stack_base = stack_addr;
-    return 0;
-#endif
 }
 
 int pthread_attr_getstackaddr(pthread_attr_t const * attr, void ** stack_addr)
 {
+    // This was removed from POSIX.1-2008.
+    // Needed for ABI compatibility with the NDK.
     *stack_addr = (char*)attr->stack_base + attr->stack_size;
     return 0;
 }
@@ -513,7 +509,7 @@
     return 0;
 }
 
-int pthread_attr_setscope(pthread_attr_t *attr, int  scope)
+int pthread_attr_setscope(pthread_attr_t *attr __attribute__((unused)), int  scope)
 {
     if (scope == PTHREAD_SCOPE_SYSTEM)
         return 0;
@@ -523,7 +519,7 @@
     return EINVAL;
 }
 
-int pthread_attr_getscope(pthread_attr_t const *attr)
+int pthread_attr_getscope(pthread_attr_t const *attr __attribute__((unused)))
 {
     return PTHREAD_SCOPE_SYSTEM;
 }
@@ -1181,7 +1177,7 @@
 __LIBC_HIDDEN__
 int pthread_mutex_lock_impl(pthread_mutex_t *mutex)
 {
-    int mvalue, mtype, tid, new_lock_type, shared;
+    int mvalue, mtype, tid, shared;
 
     if (__unlikely(mutex == NULL))
         return EINVAL;
@@ -1275,7 +1271,7 @@
 __LIBC_HIDDEN__
 int pthread_mutex_unlock_impl(pthread_mutex_t *mutex)
 {
-    int mvalue, mtype, tid, oldv, shared;
+    int mvalue, mtype, tid, shared;
 
     if (__unlikely(mutex == NULL))
         return EINVAL;
@@ -1342,7 +1338,7 @@
 __LIBC_HIDDEN__
 int pthread_mutex_trylock_impl(pthread_mutex_t *mutex)
 {
-    int mvalue, mtype, tid, oldv, shared;
+    int mvalue, mtype, tid, shared;
 
     if (__unlikely(mutex == NULL))
         return EINVAL;
@@ -1437,7 +1433,7 @@
     clockid_t        clock = CLOCK_MONOTONIC;
     struct timespec  abstime;
     struct timespec  ts;
-    int               mvalue, mtype, tid, oldv, new_lock_type, shared;
+    int               mvalue, mtype, tid, shared;
 
     /* compute absolute expiration time */
     __timespec_to_relative_msec(&abstime, msecs, clock);
@@ -2099,58 +2095,6 @@
     return ret;
 }
 
-/* Despite the fact that our kernel headers define sigset_t explicitly
- * as a 32-bit integer, the kernel system call really expects a 64-bit
- * bitmap for the signal set, or more exactly an array of two-32-bit
- * values (see $KERNEL/arch/$ARCH/include/asm/signal.h for details).
- *
- * Unfortunately, we cannot fix the sigset_t definition without breaking
- * the C library ABI, so perform a little runtime translation here.
- */
-typedef union {
-    sigset_t   bionic;
-    uint32_t   kernel[2];
-} kernel_sigset_t;
-
-/* this is a private syscall stub */
-extern int __rt_sigprocmask(int, const kernel_sigset_t *, kernel_sigset_t *, size_t);
-
-int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
-{
-    /* pthread_sigmask must return the error code, but the syscall
-     * will set errno instead and return 0/-1
-     */
-    int ret, old_errno = errno;
-
-    /* We must convert *set into a kernel_sigset_t */
-    kernel_sigset_t  in_set, *in_set_ptr;
-    kernel_sigset_t  out_set;
-
-    in_set.kernel[0] = in_set.kernel[1] = 0;
-    out_set.kernel[0] = out_set.kernel[1] = 0;
-
-    /* 'in_set_ptr' is the second parameter to __rt_sigprocmask. It must be NULL
-     * if 'set' is NULL to ensure correct semantics (which in this case would
-     * be to ignore 'how' and return the current signal set into 'oset'.
-     */
-    if (set == NULL) {
-        in_set_ptr = NULL;
-    } else {
-        in_set.bionic = *set;
-        in_set_ptr = &in_set;
-    }
-
-    ret = __rt_sigprocmask(how, in_set_ptr, &out_set, sizeof(kernel_sigset_t));
-    if (ret < 0)
-        ret = errno;
-
-    if (oset)
-        *oset = out_set.bionic;
-
-    errno = old_errno;
-    return ret;
-}
-
 
 int pthread_getcpuclockid(pthread_t  tid, clockid_t  *clockid)
 {
@@ -2170,9 +2114,7 @@
  */
 int  pthread_once( pthread_once_t*  once_control,  void (*init_routine)(void) )
 {
-    static pthread_mutex_t   once_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
     volatile pthread_once_t* ocptr = once_control;
-    pthread_once_t value;
 
     /* PTHREAD_ONCE_INIT is 0, we use the following bit flags
      *
diff --git a/libc/bionic/pthread_sigmask.cpp b/libc/bionic/pthread_sigmask.cpp
new file mode 100644
index 0000000..9c9dc3e
--- /dev/null
+++ b/libc/bionic/pthread_sigmask.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include <private/kernel_sigset_t.h>
+
+extern "C" int __rt_sigprocmask(int, const kernel_sigset_t*, kernel_sigset_t*, size_t);
+
+int pthread_sigmask(int how, const sigset_t* iset, sigset_t* oset) {
+  int old_errno = errno;
+
+  // 'in_set_ptr' is the second parameter to __rt_sigprocmask. It must be NULL
+  // if 'set' is NULL to ensure correct semantics (which in this case would
+  // be to ignore 'how' and return the current signal set into 'oset').
+  kernel_sigset_t in_set;
+  kernel_sigset_t* in_set_ptr = NULL;
+  if (iset != NULL) {
+    in_set.set(iset);
+    in_set_ptr = &in_set;
+  }
+
+  kernel_sigset_t out_set;
+  int result = __rt_sigprocmask(how, in_set_ptr, &out_set, sizeof(out_set));
+  if (result < 0) {
+    result = errno;
+  }
+
+  if (oset != NULL) {
+    *oset = out_set.bionic;
+  }
+
+  errno = old_errno;
+  return result;
+}
diff --git a/libc/bionic/signalfd.cpp b/libc/bionic/signalfd.cpp
new file mode 100644
index 0000000..b7e6474
--- /dev/null
+++ b/libc/bionic/signalfd.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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 <sys/signalfd.h>
+
+#include <private/kernel_sigset_t.h>
+
+extern "C" int signalfd4(int fd, kernel_sigset_t* mask, size_t sizemask, int flags);
+
+int signalfd(int fd, const sigset_t* mask, int flags) {
+  kernel_sigset_t in_set(mask);
+  return signalfd4(fd, &in_set, sizeof(in_set), flags);
+}
diff --git a/libc/bionic/sigwait.c b/libc/bionic/sigwait.c
deleted file mode 100644
index 1e90c41..0000000
--- a/libc/bionic/sigwait.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-#include <time.h>
-
-int __rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo, const struct timespec *uts, size_t sigsetsize);
-
-/* ok, this is really subtle: <asm/signal.h> defines sigset_t differently
- * when you're in the kernel or in the C library.
- *
- * in the kernel, this is an array of 2 32-bit unsigned longs
- * in the C library, this is a single 32-bit unsigned long
- *
- * moreover, the kernel implementation of rt_sigtimedwait doesn't
- * accept anything except kernel-sized signal sets (probably a bug !)
- *
- * we thus need to create a fake kernel sigset !!
- */
-
-int sigwait(const sigset_t *set, int *sig)
-{
-    int  ret;
-#ifdef __mips__
-    /* use a union to get rid of aliasing warnings. On MIPS sigset_t is 128 bits */
-    union {
-      sigset_t       kernel_sigset;
-      sigset_t       dummy_sigset;
-    } u;
-    u.dummy_sigset = *set;
-#else
-    /* use a union to get rid of aliasing warnings */
-    union {
-      unsigned long  kernel_sigset[2];
-      sigset_t       dummy_sigset;
-    } u;
-
-    u.kernel_sigset[0] = *set;
-    u.kernel_sigset[1] = 0;  /* no real-time signals supported ? */
-#endif
-    for (;;)
-    {
-     /* __rt_sigtimedwait can return EAGAIN or EINTR, we need to loop
-      * around them since sigwait is only allowed to return EINVAL
-      */
-      ret = __rt_sigtimedwait ( &u.dummy_sigset, NULL, NULL, sizeof(u.kernel_sigset));
-      if (ret >= 0)
-        break;
-
-      if (errno != EAGAIN && errno != EINTR)
-        return errno;
-    }
-
-    *sig = ret;
-    return 0;
-}
-
diff --git a/libc/bionic/sigwait.cpp b/libc/bionic/sigwait.cpp
new file mode 100644
index 0000000..1546fd6
--- /dev/null
+++ b/libc/bionic/sigwait.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+
+#include <private/kernel_sigset_t.h>
+
+extern "C" int __rt_sigtimedwait(const sigset_t* uthese, siginfo_t* uinfo, const struct timespec* uts, size_t sigsetsize);
+
+int sigwait(const sigset_t* set, int* sig) {
+  kernel_sigset_t sigset(set);
+  while (true) {
+    // __rt_sigtimedwait can return EAGAIN or EINTR, we need to loop
+    // around them since sigwait is only allowed to return EINVAL.
+    int result = __rt_sigtimedwait(sigset.get(), NULL, NULL, sizeof(sigset));
+    if (result >= 0) {
+      *sig = result;
+      return 0;
+    }
+
+    if (errno != EAGAIN && errno != EINTR) {
+      return errno;
+    }
+  }
+}
diff --git a/libc/bionic/strerror_r.cpp b/libc/bionic/strerror_r.cpp
index e6a3975..646cc52 100644
--- a/libc/bionic/strerror_r.cpp
+++ b/libc/bionic/strerror_r.cpp
@@ -49,7 +49,7 @@
   if (error_name != NULL) {
     length = snprintf(buf, buf_len, "%s", error_name);
   } else {
-    length = snprintf(buf, buf_len, "Unknown error %u", error_number);
+    length = snprintf(buf, buf_len, "Unknown error %d", error_number);
   }
   if (length >= buf_len) {
     errno = ERANGE;
diff --git a/libc/include/elf.h b/libc/include/elf.h
index c3e3226..ac0f1d2 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -28,8 +28,23 @@
 #ifndef _ELF_H
 #define _ELF_H
 
+#include <stdint.h>
 #include <linux/auxvec.h>
 #include <sys/exec_elf.h>
 
+typedef struct {
+  uint32_t a_type;
+  union {
+    uint32_t a_val;
+  } a_un;
+} Elf32_auxv_t;
+
+typedef struct {
+  uint64_t a_type;
+  union {
+    uint64_t a_val;
+  } a_un;
+} Elf64_auxv_t;
+
 #endif /* _ELF_H */
 
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 9d3badc..e2713db 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -58,34 +58,34 @@
 extern const char* const sys_signame[];
 
 static __inline__ int sigismember(sigset_t* set, int signum) {
-  if (set == NULL || signum < 1 || signum >= 8*sizeof(sigset_t)) {
+  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+  if (set == NULL || bit < 0 || bit >= 8*sizeof(sigset_t)) {
     errno = EINVAL;
     return -1;
   }
   unsigned long* local_set = (unsigned long*) set;
-  signum--;
-  return (int) ((local_set[signum/LONG_BIT] >> (signum%LONG_BIT)) & 1);
+  return (int) ((local_set[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1);
 }
 
 static __inline__ int sigaddset(sigset_t* set, int signum) {
-  if (set == NULL || signum < 1 || signum >= 8*sizeof(sigset_t)) {
+  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+  if (set == NULL || bit < 0 || bit >= 8*sizeof(sigset_t)) {
     errno = EINVAL;
     return -1;
   }
   unsigned long* local_set = (unsigned long*) set;
-  signum--;
-  local_set[signum/LONG_BIT] |= 1UL << (signum%LONG_BIT);
+  local_set[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
   return 0;
 }
 
 static __inline__ int sigdelset(sigset_t* set, int signum) {
-  if (set == NULL || signum < 1 || signum >= 8*sizeof(sigset_t)) {
+  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+  if (set == NULL || bit < 0 || bit >= 8*sizeof(sigset_t)) {
     errno = EINVAL;
     return -1;
   }
   unsigned long* local_set = (unsigned long*) set;
-  signum--;
-  local_set[signum/LONG_BIT] &= ~(1UL << (signum%LONG_BIT));
+  local_set[bit / LONG_BIT] &= ~(1UL << (bit % LONG_BIT));
   return 0;
 }
 
diff --git a/libc/include/sys/auxv.h b/libc/include/sys/auxv.h
new file mode 100644
index 0000000..918442f
--- /dev/null
+++ b/libc/include/sys/auxv.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+#ifndef _SYS_AUXV_H_
+#define _SYS_AUXV_H_
+
+#include <linux/auxvec.h>
+
+__BEGIN_DECLS
+
+unsigned long int getauxval(unsigned long int type);
+
+__END_DECLS
+
+#endif /* _SYS_AUXV_H_ */
diff --git a/libc/include/sys/linux-syscalls.h b/libc/include/sys/linux-syscalls.h
index ec48ada..738d9e8 100644
--- a/libc/include/sys/linux-syscalls.h
+++ b/libc/include/sys/linux-syscalls.h
@@ -173,6 +173,7 @@
 #define __NR_rt_sigaction                 (__NR_SYSCALL_BASE + 174)
 #define __NR_rt_sigprocmask               (__NR_SYSCALL_BASE + 175)
 #define __NR_rt_sigtimedwait              (__NR_SYSCALL_BASE + 177)
+#define __NR_signalfd4                    (__NR_SYSCALL_BASE + 355)
 #define __NR_socket                       (__NR_SYSCALL_BASE + 281)
 #define __NR_socketpair                   (__NR_SYSCALL_BASE + 288)
 #define __NR_bind                         (__NR_SYSCALL_BASE + 282)
@@ -329,6 +330,7 @@
 #define __NR_unshare                      (__NR_SYSCALL_BASE + 310)
 #define __NR_getcpu                       (__NR_SYSCALL_BASE + 318)
 #define __NR_utimensat                    (__NR_SYSCALL_BASE + 320)
+#define __NR_signalfd4                    (__NR_SYSCALL_BASE + 327)
 #define __NR_eventfd2                     (__NR_SYSCALL_BASE + 328)
 #define __NR_pipe2                        (__NR_SYSCALL_BASE + 331)
 #define __NR_perf_event_open              (__NR_SYSCALL_BASE + 336)
@@ -463,6 +465,7 @@
 #define __NR_ioprio_set                   (__NR_SYSCALL_BASE + 314)
 #define __NR_ioprio_get                   (__NR_SYSCALL_BASE + 315)
 #define __NR_utimensat                    (__NR_SYSCALL_BASE + 316)
+#define __NR_signalfd4                    (__NR_SYSCALL_BASE + 324)
 #define __NR_eventfd2                     (__NR_SYSCALL_BASE + 325)
 #define __NR_pipe2                        (__NR_SYSCALL_BASE + 328)
 #define __NR_perf_event_open              (__NR_SYSCALL_BASE + 333)
diff --git a/libc/include/sys/signalfd.h b/libc/include/sys/signalfd.h
new file mode 100644
index 0000000..af1f290
--- /dev/null
+++ b/libc/include/sys/signalfd.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+#ifndef _SYS_SIGNALFD_H_
+#define _SYS_SIGNALFD_H_
+
+#include <linux/signalfd.h>
+#include <sys/cdefs.h>
+#include <signal.h>
+
+__BEGIN_DECLS
+
+/* Compatibility with GLibc */
+extern int signalfd(int fd, const sigset_t *mask, int flags);
+
+__END_DECLS
+
+#endif /* _SYS_SIGNALFD_H */
diff --git a/libc/kernel/common/linux/signalfd.h b/libc/kernel/common/linux/signalfd.h
new file mode 100644
index 0000000..a064192
--- /dev/null
+++ b/libc/kernel/common/linux/signalfd.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_SIGNALFD_H
+#define _LINUX_SIGNALFD_H
+#include <linux/types.h>
+#include <linux/fcntl.h>
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define SFD_CLOEXEC O_CLOEXEC
+#define SFD_NONBLOCK O_NONBLOCK
+struct signalfd_siginfo {
+ __u32 ssi_signo;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __s32 ssi_errno;
+ __s32 ssi_code;
+ __u32 ssi_pid;
+ __u32 ssi_uid;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __s32 ssi_fd;
+ __u32 ssi_tid;
+ __u32 ssi_band;
+ __u32 ssi_overrun;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 ssi_trapno;
+ __s32 ssi_status;
+ __s32 ssi_int;
+ __u64 ssi_ptr;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u64 ssi_utime;
+ __u64 ssi_stime;
+ __u64 ssi_addr;
+ __u16 ssi_addr_lsb;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u8 __pad[46];
+};
+#endif
diff --git a/libc/netbsd/resolv/res_cache.c b/libc/netbsd/resolv/res_cache.c
index 915fdf0..afc9a36 100644
--- a/libc/netbsd/resolv/res_cache.c
+++ b/libc/netbsd/resolv/res_cache.c
@@ -572,8 +572,6 @@
 static int
 _dnsPacket_checkQR( DnsPacket*  packet )
 {
-    int  len;
-
     if (!_dnsPacket_checkQName(packet))
         return 0;
 
@@ -832,8 +830,6 @@
 static unsigned
 _dnsPacket_hashQR( DnsPacket*  packet, unsigned  hash )
 {
-    int   len;
-
     hash = _dnsPacket_hashQName(packet, hash);
     hash = _dnsPacket_hashBytes(packet, 4, hash); /* TYPE and CLASS */
     return hash;
@@ -1020,8 +1016,58 @@
 } Entry;
 
 /**
- * Parse the answer records and find the smallest
- * TTL among the answer records.
+ * Find the TTL for a negative DNS result.  This is defined as the minimum
+ * of the SOA records TTL and the MINIMUM-TTL field (RFC-2308).
+ *
+ * Return 0 if not found.
+ */
+static u_long
+answer_getNegativeTTL(ns_msg handle) {
+    int n, nscount;
+    u_long result = 0;
+    ns_rr rr;
+
+    nscount = ns_msg_count(handle, ns_s_ns);
+    for (n = 0; n < nscount; n++) {
+        if ((ns_parserr(&handle, ns_s_ns, n, &rr) == 0) && (ns_rr_type(rr) == ns_t_soa)) {
+            const u_char *rdata = ns_rr_rdata(rr); // find the data
+            const u_char *edata = rdata + ns_rr_rdlen(rr); // add the len to find the end
+            int len;
+            u_long ttl, rec_result = ns_rr_ttl(rr);
+
+            // find the MINIMUM-TTL field from the blob of binary data for this record
+            // skip the server name
+            len = dn_skipname(rdata, edata);
+            if (len == -1) continue; // error skipping
+            rdata += len;
+
+            // skip the admin name
+            len = dn_skipname(rdata, edata);
+            if (len == -1) continue; // error skipping
+            rdata += len;
+
+            if (edata - rdata != 5*NS_INT32SZ) continue;
+            // skip: serial number + refresh interval + retry interval + expiry
+            rdata += NS_INT32SZ * 4;
+            // finally read the MINIMUM TTL
+            ttl = ns_get32(rdata);
+            if (ttl < rec_result) {
+                rec_result = ttl;
+            }
+            // Now that the record is read successfully, apply the new min TTL
+            if (n == 0 || rec_result < result) {
+                result = rec_result;
+            }
+        }
+    }
+    return result;
+}
+
+/**
+ * Parse the answer records and find the appropriate
+ * smallest TTL among the records.  This might be from
+ * the answer records if found or from the SOA record
+ * if it's a negative result.
  *
  * The returned TTL is the number of seconds to
  * keep the answer in the cache.
@@ -1041,14 +1087,20 @@
     if (ns_initparse(answer, answerlen, &handle) >= 0) {
         // get number of answer records
         ancount = ns_msg_count(handle, ns_s_an);
-        for (n = 0; n < ancount; n++) {
-            if (ns_parserr(&handle, ns_s_an, n, &rr) == 0) {
-                ttl = ns_rr_ttl(rr);
-                if (n == 0 || ttl < result) {
-                    result = ttl;
+
+        if (ancount == 0) {
+            // a response with no answers?  Cache this negative result.
+            result = answer_getNegativeTTL(handle);
+        } else {
+            for (n = 0; n < ancount; n++) {
+                if (ns_parserr(&handle, ns_s_an, n, &rr) == 0) {
+                    ttl = ns_rr_ttl(rr);
+                    if (n == 0 || ttl < result) {
+                        result = ttl;
+                    }
+                } else {
+                    XLOG("ns_parserr failed ancount no = %d. errno = %s\n", n, strerror(errno));
                 }
-            } else {
-                XLOG("ns_parserr failed ancount no = %d. errno = %s\n", n, strerror(errno));
             }
         }
     } else {
@@ -1253,7 +1305,7 @@
         } else {
             struct timespec ts = {0,0};
             ts.tv_sec = _time_now() + PENDING_REQUEST_TIMEOUT;
-            int rv = pthread_cond_timedwait(&ri->cond, &cache->lock, &ts);
+            pthread_cond_timedwait(&ri->cond, &cache->lock, &ts);
         }
     }
 
@@ -1307,7 +1359,6 @@
 _cache_flush_locked( Cache*  cache )
 {
     int     nn;
-    time_t  now = _time_now();
 
     for (nn = 0; nn < cache->max_entries; nn++)
     {
@@ -1443,6 +1494,7 @@
         remove("/data/reslog.txt");
     }
     else {
+        errno = 0; // else debug is introducing error signals
         XLOG("_dump_answer: can't open file\n");
     }
 }
@@ -1578,9 +1630,7 @@
                       int                   answersize,
                       int                  *answerlen )
 {
-    DnsPacket  pack[1];
     Entry      key[1];
-    int        index;
     Entry**    lookup;
     Entry*     e;
     time_t     now;
@@ -1753,8 +1803,6 @@
 static struct resolv_cache* _find_named_cache_locked(const char* ifname);
 /* gets a resolv_cache_info associated with an interface name, or NULL if not found */
 static struct resolv_cache_info* _find_cache_info_locked(const char* ifname);
-/* free dns name server list of a resolv_cache_info structure */
-static void _free_nameservers(struct resolv_cache_info* cache_info);
 /* look up the named cache, and creates one if needed */
 static struct resolv_cache* _get_res_cache_for_iface_locked(const char* ifname);
 /* empty the named cache */
diff --git a/libc/private/bionic_auxv.h b/libc/private/bionic_auxv.h
new file mode 100644
index 0000000..d3b0038
--- /dev/null
+++ b/libc/private/bionic_auxv.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+#ifndef _SYS_AUXV_H_
+#define _SYS_AUXV_H_
+
+#include <elf.h>
+
+__BEGIN_DECLS
+
+extern Elf32_auxv_t* __libc_auxv;
+
+__END_DECLS
+
+#endif /* _SYS_AUXV_H_ */
diff --git a/libc/private/kernel_sigset_t.h b/libc/private/kernel_sigset_t.h
new file mode 100644
index 0000000..733a842
--- /dev/null
+++ b/libc/private/kernel_sigset_t.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LIBC_PRIVATE_KERNEL_SIGSET_T_H_
+#define LIBC_PRIVATE_KERNEL_SIGSET_T_H_
+
+// Our sigset_t is wrong for ARM and x86. It's 32-bit but the kernel expects 64 bits.
+// This means we can't support real-time signals correctly until we can change the ABI.
+// In the meantime, we can use this union to pass an appropriately-sized block of memory
+// to the kernel, at the cost of not being able to refer to real-time signals.
+union kernel_sigset_t {
+  kernel_sigset_t() {
+    clear();
+  }
+
+  kernel_sigset_t(const sigset_t* value) {
+    clear();
+    set(value);
+  }
+
+  void clear() {
+    memset(this, 0, sizeof(*this));
+  }
+
+  void set(const sigset_t* value) {
+    bionic = *value;
+  }
+
+  sigset_t* get() {
+    return &bionic;
+  }
+
+  sigset_t bionic;
+#ifndef __mips__
+  uint32_t kernel[2];
+#endif
+};
+
+#endif
diff --git a/libm/include/mips/fenv.h b/libm/include/mips/fenv.h
index da7e696..ed69cf8 100644
--- a/libm/include/mips/fenv.h
+++ b/libm/include/mips/fenv.h
@@ -26,193 +26,200 @@
  * $FreeBSD: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $
  */
 
-#ifndef	_FENV_H_
-#define	_FENV_H_
+/*
+   Rewritten for Android.
+*/
+
+/* MIPS FPU floating point control register bits.
+ *
+ * 31-25  -> floating point conditions code bits set by FP compare
+ *           instructions
+ * 24     -> flush denormalized results to zero instead of
+ *           causing unimplemented operation exception.
+ * 23     -> Condition bit
+ * 22     -> In conjunction with FS detects denormalized
+ *           operands and replaces them internally with 0.
+ * 21     -> In conjunction with FS forces denormalized operands
+ *           to the closest normalized value.
+ * 20-18  -> reserved (read as 0, write with 0)
+ * 17     -> cause bit for unimplemented operation
+ * 16     -> cause bit for invalid exception
+ * 15     -> cause bit for division by zero exception
+ * 14     -> cause bit for overflow exception
+ * 13     -> cause bit for underflow exception
+ * 12     -> cause bit for inexact exception
+ * 11     -> enable exception for invalid exception
+ * 10     -> enable exception for division by zero exception
+ *  9     -> enable exception for overflow exception
+ *  8     -> enable exception for underflow exception
+ *  7     -> enable exception for inexact exception
+ *  6     -> flag invalid exception
+ *  5     -> flag division by zero exception
+ *  4     -> flag overflow exception
+ *  3     -> flag underflow exception
+ *  2     -> flag inexact exception
+ *  1-0   -> rounding control
+ *
+ *
+ * Rounding Control:
+ * 00 - rounding to nearest (RN)
+ * 01 - rounding toward zero (RZ)
+ * 10 - rounding (up) toward plus infinity (RP)
+ * 11 - rounding (down)toward minus infinity (RM)
+ */
+
+#ifndef _FENV_H_
+#define _FENV_H_
 
 #include <sys/types.h>
 
 __BEGIN_DECLS
 
-typedef	__uint32_t	fenv_t;
-typedef	__uint32_t	fexcept_t;
+typedef __uint32_t    fenv_t;
+typedef __uint32_t    fexcept_t;
 
 /* Exception flags */
-#define	FE_INVALID	0x0001
-#define	FE_DIVBYZERO	0x0002
-#define	FE_OVERFLOW	0x0004
-#define	FE_UNDERFLOW	0x0008
-#define	FE_INEXACT	0x0010
-#define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
-			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+#define FE_INVALID      0x40
+#define FE_DIVBYZERO    0x20
+#define FE_OVERFLOW     0x10
+#define FE_UNDERFLOW    0x08
+#define FE_INEXACT      0x04
+#define FE_ALL_EXCEPT   (FE_DIVBYZERO | FE_INEXACT | \
+                         FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+#define _FCSR_CAUSE_SHIFT  10
+#define _ENABLE_SHIFT 5
+#define _FCSR_ENABLE_MASK (FE_ALL_EXCEPT << _ENABLE_SHIFT)
 
 /* Rounding modes */
-#define	FE_TONEAREST	0x0000
-#define	FE_TOWARDZERO	0x0001
-#define	FE_UPWARD	0x0002
-#define	FE_DOWNWARD	0x0003
-#define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
-			 FE_UPWARD | FE_TOWARDZERO)
-
+#define FE_TONEAREST    0x0000
+#define FE_TOWARDZERO   0x0001
+#define FE_UPWARD       0x0002
+#define FE_DOWNWARD     0x0003
+#define _FCSR_RMODE_SHIFT 0
+#define _FCSR_RMASK       0x3
 /* Default floating-point environment */
-extern const fenv_t	__fe_dfl_env;
-#define	FE_DFL_ENV	(&__fe_dfl_env)
+extern const fenv_t    __fe_dfl_env;
+#define FE_DFL_ENV    (&__fe_dfl_env)
 
-/* We need to be able to map status flag positions to mask flag positions */
-#define _FPUSW_SHIFT	16
-#define	_ENABLE_MASK	(FE_ALL_EXCEPT << _FPUSW_SHIFT)
-
-#ifdef	ARM_HARD_FLOAT
-#define	__rfs(__fpsr)	__asm __volatile("rfs %0" : "=r" (*(__fpsr)))
-#define	__wfs(__fpsr)	__asm __volatile("wfs %0" : : "r" (__fpsr))
-#else
-#define __rfs(__fpsr)
-#define __wfs(__fpsr)
+static __inline int fegetenv(fenv_t* __envp) {
+   fenv_t _fcsr = 0;
+#ifdef  __mips_hard_float
+   __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr));
 #endif
-
-static __inline int
-feclearexcept(int __excepts)
-{
-	fexcept_t __fpsr;
-
-	__rfs(&__fpsr);
-	__fpsr &= ~__excepts;
-	__wfs(__fpsr);
-	return (0);
+   *__envp = _fcsr;
+   return 0;
 }
 
-static __inline int
-fegetexceptflag(fexcept_t *__flagp, int __excepts)
-{
-	fexcept_t __fpsr;
-
-	__rfs(&__fpsr);
-	*__flagp = __fpsr & __excepts;
-	return (0);
+static __inline int fesetenv(const fenv_t* __envp) {
+  fenv_t _fcsr = *__envp;
+#ifdef  __mips_hard_float
+  __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr));
+#endif
+  return 0;
 }
 
-static __inline int
-fesetexceptflag(const fexcept_t *__flagp, int __excepts)
-{
-	fexcept_t __fpsr;
-
-	__rfs(&__fpsr);
-	__fpsr &= ~__excepts;
-	__fpsr |= *__flagp & __excepts;
-	__wfs(__fpsr);
-	return (0);
+static __inline int feclearexcept(int __excepts) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  __excepts &= FE_ALL_EXCEPT;
+  __fcsr &= ~(__excepts | (__excepts << _FCSR_CAUSE_SHIFT));
+  fesetenv(&__fcsr);
+  return 0;
 }
 
-static __inline int
-feraiseexcept(int __excepts)
-{
-	fexcept_t __ex = __excepts;
-
-	fesetexceptflag(&__ex, __excepts);	/* XXX */
-	return (0);
+static __inline int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT;
+  return 0;
 }
 
-static __inline int
-fetestexcept(int __excepts)
-{
-	fexcept_t __fpsr;
-
-	__rfs(&__fpsr);
-	return (__fpsr & __excepts);
+static __inline int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  /* Ensure that flags are all legal */
+  __excepts &= FE_ALL_EXCEPT;
+  __fcsr &= ~__excepts;
+  __fcsr |= *__flagp & __excepts;
+  fesetenv(&__fcsr);
+  return 0;
 }
 
-static __inline int
-fegetround(void)
-{
-
-	/*
-	 * Apparently, the rounding mode is specified as part of the
-	 * instruction format on ARM, so the dynamic rounding mode is
-	 * indeterminate.  Some FPUs may differ.
-	 */
-	return (-1);
+static __inline int feraiseexcept(int __excepts) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  /* Ensure that flags are all legal */
+  __excepts &= FE_ALL_EXCEPT;
+  /* Cause bit needs to be set as well for generating the exception*/
+  __fcsr |= __excepts | (__excepts << _FCSR_CAUSE_SHIFT);
+  fesetenv(&__fcsr);
+  return 0;
 }
 
-static __inline int
-fesetround(int __round)
-{
-
-	return (-1);
+static __inline int fetestexcept(int __excepts) {
+  fexcept_t __FCSR;
+  fegetenv(&__FCSR);
+  return (__FCSR & __excepts & FE_ALL_EXCEPT);
 }
 
-static __inline int
-fegetenv(fenv_t *__envp)
-{
-
-	__rfs(__envp);
-	return (0);
+static __inline int fegetround(void) {
+  fenv_t _fcsr;
+  fegetenv(&_fcsr);
+  return (_fcsr & _FCSR_RMASK);
 }
 
-static __inline int
-feholdexcept(fenv_t *__envp)
-{
-	fenv_t __env;
-
-	__rfs(&__env);
-	*__envp = __env;
-	__env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
-	__wfs(__env);
-	return (0);
+static __inline int fesetround(int __round) {
+  fenv_t _fcsr;
+  fegetenv(&_fcsr);
+  _fcsr &= ~_FCSR_RMASK;
+  _fcsr |= (__round & _FCSR_RMASK ) ;
+  fesetenv(&_fcsr);
+  return 0;
 }
 
-static __inline int
-fesetenv(const fenv_t *__envp)
-{
-
-	__wfs(*__envp);
-	return (0);
+static __inline int feholdexcept(fenv_t* __envp) {
+  fenv_t __env;
+  fegetenv(&__env);
+  *__envp = __env;
+  __env &= ~(FE_ALL_EXCEPT | _FCSR_ENABLE_MASK);
+  fesetenv(&__env);
+  return 0;
 }
 
-static __inline int
-feupdateenv(const fenv_t *__envp)
-{
-	fexcept_t __fpsr;
-
-	__rfs(&__fpsr);
-	__wfs(*__envp);
-	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
-	return (0);
+static __inline int feupdateenv(const fenv_t* __envp) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  fesetenv(__envp);
+  feraiseexcept(__fcsr & FE_ALL_EXCEPT);
+  return 0;
 }
 
 #if __BSD_VISIBLE
 
-static __inline int
-feenableexcept(int __mask)
-{
-	fenv_t __old_fpsr, __new_fpsr;
-
-	__rfs(&__old_fpsr);
-	__new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
-	__wfs(__new_fpsr);
-	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
+static __inline int feenableexcept(int __mask) {
+  fenv_t __old_fcsr, __new_fcsr;
+  fegetenv(&__old_fcsr);
+  __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT;
+  fesetenv(&__new_fcsr);
+  return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
 }
 
-static __inline int
-fedisableexcept(int __mask)
-{
-	fenv_t __old_fpsr, __new_fpsr;
-
-	__rfs(&__old_fpsr);
-	__new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
-	__wfs(__new_fpsr);
-	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
+static __inline int fedisableexcept(int __mask) {
+  fenv_t __old_fcsr, __new_fcsr;
+  fegetenv(&__old_fcsr);
+  __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT);
+  fesetenv(&__new_fcsr);
+  return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
 }
 
-static __inline int
-fegetexcept(void)
-{
-	fenv_t __fpsr;
-
-	__rfs(&__fpsr);
-	return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
+static __inline int fegetexcept(void) {
+  fenv_t __fcsr;
+  fegetenv(&__fcsr);
+  return ((__fcsr & _FCSR_ENABLE_MASK) >> _ENABLE_SHIFT);
 }
 
 #endif /* __BSD_VISIBLE */
 
 __END_DECLS
 
-#endif	/* !_FENV_H_ */
+#endif /* !_FENV_H_ */
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 09f479f..0a89b72 100755
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1511,8 +1511,9 @@
 
     /* Extract dynamic section */
     size_t dynamic_count;
+    Elf32_Word dynamic_flags;
     phdr_table_get_dynamic_section(phdr, phnum, base, &si->dynamic,
-                                   &dynamic_count);
+                                   &dynamic_count, &dynamic_flags);
     if (si->dynamic == NULL) {
         if (!relocating_linker) {
             DL_ERR("missing PT_DYNAMIC in \"%s\"", si->name);
@@ -1568,10 +1569,11 @@
             si->plt_got = (unsigned *)(base + *d);
             break;
         case DT_DEBUG:
-#if !defined(ANDROID_MIPS_LINKER)
             // Set the DT_DEBUG entry to the address of _r_debug for GDB
-            *d = (int) &_r_debug;
-#endif
+            // if the dynamic table is writable
+            if ((dynamic_flags & PF_W) != 0) {
+                *d = (int) &_r_debug;
+            }
             break;
          case DT_RELA:
             DL_ERR("unsupported DT_RELA in \"%s\"", si->name);
@@ -1866,7 +1868,7 @@
     Elf32_Phdr *phdr =
         (Elf32_Phdr *)((unsigned char *) linker_base + elf_hdr->e_phoff);
     phdr_table_get_dynamic_section(phdr, elf_hdr->e_phnum, linker_base,
-                                   &linker_soinfo.dynamic, NULL);
+                                   &linker_soinfo.dynamic, NULL, NULL);
     insert_soinfo_into_debug_map(&linker_soinfo);
 
     /* extract information passed from the kernel */
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 1990366..94260fa 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -542,6 +542,7 @@
  * Output:
  *   dynamic       -> address of table in memory (NULL on failure).
  *   dynamic_count -> number of items in table (0 on failure).
+ *   dynamic_flags -> protection flags for section (unset on failure)
  * Return:
  *   void
  */
@@ -550,7 +551,8 @@
                                int               phdr_count,
                                Elf32_Addr        load_bias,
                                Elf32_Addr**      dynamic,
-                               size_t*           dynamic_count)
+                               size_t*           dynamic_count,
+                               Elf32_Word*       dynamic_flags)
 {
     const Elf32_Phdr* phdr = phdr_table;
     const Elf32_Phdr* phdr_limit = phdr + phdr_count;
@@ -564,6 +566,9 @@
         if (dynamic_count) {
             *dynamic_count = (unsigned)(phdr->p_memsz / 8);
         }
+        if (dynamic_flags) {
+            *dynamic_flags = phdr->p_flags;
+        }
         return;
     }
     *dynamic = NULL;
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index 2d4d735..d9a4820 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -99,6 +99,7 @@
                                int               phdr_count,
                                Elf32_Addr        load_bias,
                                Elf32_Addr**      dynamic,
-                               size_t*           dynamic_count);
+                               size_t*           dynamic_count,
+                               Elf32_Word*       dynamic_flags);
 
 #endif /* LINKER_PHDR_H */
diff --git a/tests/Android.mk b/tests/Android.mk
index 083bb70..25da120 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -47,7 +47,7 @@
 # -----------------------------------------------------------------------------
 
 test_c_flags = \
-    -fstack-protector \
+    -fstack-protector-all \
     -g \
     -Wall -Wextra \
     -Werror \
@@ -55,6 +55,7 @@
 test_src_files = \
     dirent_test.cpp \
     fenv_test.cpp \
+    getauxval_test.cpp \
     getcwd_test.cpp \
     libgen_test.cpp \
     pthread_test.cpp \
@@ -98,13 +99,15 @@
 # -----------------------------------------------------------------------------
 
 # Build no-elf-hash-table-library.so to test dlopen(3) on a library that
-# only has a GNU-style hash table.
+# only has a GNU-style hash table. MIPS doesn't support GNU hash style.
+ifneq ($(TARGET_ARCH),mips)
 include $(CLEAR_VARS)
 LOCAL_MODULE := no-elf-hash-table-library
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_SRC_FILES := empty.cpp
 LOCAL_LDFLAGS := -Wl,--hash-style=gnu
 include $(BUILD_SHARED_LIBRARY)
+endif
 
 # -----------------------------------------------------------------------------
 # Unit tests built against glibc.
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 0c40eb7..938b8a5 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -188,8 +188,11 @@
   ASSERT_TRUE(dlerror() == NULL); // dladdr(3) doesn't set dlerror(3).
 }
 
-#if __BIONIC__
 // Our dynamic linker doesn't support GNU hash tables.
+#if defined(__BIONIC__)
+// GNU-style ELF hash tables are incompatible with the MIPS ABI.
+// MIPS requires .dynsym to be sorted to match the GOT but GNU-style requires sorting by hash code.
+#if !defined(__mips__)
 TEST(dlfcn, dlopen_library_with_only_gnu_hash) {
   dlerror(); // Clear any pending errors.
   void* handle = dlopen("no-elf-hash-table-library.so", RTLD_NOW);
@@ -197,6 +200,7 @@
   ASSERT_STREQ("dlopen failed: empty/missing DT_HASH in \"no-elf-hash-table-library.so\" (built with --hash-style=gnu?)", dlerror());
 }
 #endif
+#endif
 
 TEST(dlfcn, dlopen_bad_flags) {
   dlerror(); // Clear any pending errors.
diff --git a/tests/getauxval_test.cpp b/tests/getauxval_test.cpp
new file mode 100644
index 0000000..01c11c3
--- /dev/null
+++ b/tests/getauxval_test.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/cdefs.h>
+#include <features.h>
+#include <gtest/gtest.h>
+
+// getauxval() was only added as of glibc version 2.16.
+// See: http://lwn.net/Articles/519085/
+// Don't try to compile this code on older glibc versions.
+
+#if defined(__BIONIC__)
+  #define GETAUXVAL_CAN_COMPILE 1
+#elif defined(__GLIBC_PREREQ)
+  #if __GLIBC_PREREQ(2, 16)
+    #define GETAUXVAL_CAN_COMPILE 1
+  #endif
+#endif
+
+#if defined(GETAUXVAL_CAN_COMPILE)
+
+#include <sys/auxv.h>
+
+TEST(getauxval, expected_values) {
+  ASSERT_EQ((unsigned long int) 0, getauxval(AT_SECURE));
+  ASSERT_EQ(getuid(), getauxval(AT_UID));
+  ASSERT_EQ(geteuid(), getauxval(AT_EUID));
+  ASSERT_EQ(getgid(), getauxval(AT_GID));
+  ASSERT_EQ(getegid(), getauxval(AT_EGID));
+  ASSERT_EQ((unsigned long int) getpagesize(), getauxval(AT_PAGESZ));
+
+  ASSERT_NE((unsigned long int) 0, getauxval(AT_PHDR));
+  ASSERT_NE((unsigned long int) 0, getauxval(AT_PHNUM));
+  ASSERT_NE((unsigned long int) 0, getauxval(AT_ENTRY));
+  ASSERT_NE((unsigned long int) 0, getauxval(AT_PAGESZ));
+}
+
+TEST(getauxval, unexpected_values) {
+  ASSERT_EQ((unsigned long int) 0, getauxval(0xdeadbeef));
+}
+
+#endif /* GETAUXVAL_CAN_COMPILE */
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index da945b4..3e144db 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -126,3 +126,31 @@
   EXPECT_EXIT(TestBug37410(), ::testing::ExitedWithCode(0), "");
 }
 #endif
+
+static void* SignalHandlerFn(void* arg) {
+  sigset_t wait_set;
+  sigfillset(&wait_set);
+  return reinterpret_cast<void*>(sigwait(&wait_set, reinterpret_cast<int*>(arg)));
+}
+
+TEST(pthread, pthread_sigmask) {
+  // Block SIGUSR1.
+  sigset_t set;
+  sigemptyset(&set);
+  sigaddset(&set, SIGUSR1);
+  ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, &set, NULL));
+
+  // Spawn a thread that calls sigwait and tells us what it received.
+  pthread_t signal_thread;
+  int received_signal = -1;
+  ASSERT_EQ(0, pthread_create(&signal_thread, NULL, SignalHandlerFn, &received_signal));
+
+  // Send that thread SIGUSR1.
+  pthread_kill(signal_thread, SIGUSR1);
+
+  // See what it got.
+  void* join_result;
+  ASSERT_EQ(0, pthread_join(signal_thread, &join_result));
+  ASSERT_EQ(SIGUSR1, received_signal);
+  ASSERT_EQ(0, reinterpret_cast<int>(join_result));
+}
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index fcfcb18..b100372 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -48,13 +48,13 @@
   int min_signal = SIGHUP;
   int max_signal = SIGRTMAX;
 
-#if __BIONIC__
-  // bionic's sigset_t is too small: 32 bits instead of 64.
+#if defined(__BIONIC__) && !defined(__mips__)
+  // bionic's sigset_t is too small for ARM and x86: 32 bits instead of 64.
   // This means you can't refer to any of the real-time signals.
   // See http://b/3038348 and http://b/5828899.
-  max_signal = 31;
+  max_signal = 32;
 #else
-  // Other C libraries are perfectly capable of using their largest signal.
+  // Other C libraries (or bionic for MIPS) are perfectly capable of using their largest signal.
   ASSERT_GE(sizeof(sigset_t) * 8, static_cast<size_t>(SIGRTMAX));
 #endif
 
@@ -101,3 +101,27 @@
   ASSERT_EQ(-1, raise(-1));
   ASSERT_EQ(EINVAL, errno);
 }
+
+static void HandleSIGALRM(int signal_number) {
+  ASSERT_EQ(SIGALRM, signal_number);
+}
+
+TEST(signal, sigwait) {
+  struct sigaction action;
+  sigemptyset(&action.sa_mask);
+  action.sa_flags = 0;
+  action.sa_handler = HandleSIGALRM;
+  sigaction(SIGALRM, &action, NULL);
+
+  sigset_t wait_set;
+  sigemptyset(&wait_set);
+  sigaddset(&wait_set, SIGALRM);
+
+  alarm(1);
+
+  int received_signal;
+  errno = 0;
+  ASSERT_EQ(0, sigwait(&wait_set, &received_signal));
+  ASSERT_EQ(0, errno);
+  ASSERT_EQ(SIGALRM, received_signal);
+}
diff --git a/tests/stack_protector_test.cpp b/tests/stack_protector_test.cpp
index 9d86506..9cf3c38 100644
--- a/tests/stack_protector_test.cpp
+++ b/tests/stack_protector_test.cpp
@@ -114,4 +114,24 @@
   ASSERT_NE(0U, reinterpret_cast<uintptr_t>(__stack_chk_guard));
 }
 
+/*
+ * When this function returns, the stack canary will be inconsistent
+ * with the previous value, which will generate a call to __stack_chk_fail(),
+ * eventually resulting in a SIGABRT.
+ *
+ * This must be marked with "__attribute__ ((noinline))", to ensure the
+ * compiler generates the proper stack guards around this function.
+ */
+__attribute__ ((noinline))
+static void do_modify_stack_chk_guard() {
+  __stack_chk_guard = (void *) 0x12345678;
+}
+
+// We have to say "DeathTest" here so gtest knows to run this test (which exits)
+// in its own process.
+TEST(stack_protector_DeathTest, modify_stack_protector) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  ASSERT_EXIT(do_modify_stack_chk_guard(), testing::KilledBySignal(SIGABRT), "");
+}
+
 #endif
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index 71998d8..3f7d500 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -39,7 +39,7 @@
   ASSERT_STREQ("Operation not permitted", strerror(1));
 
   // Invalid.
-  ASSERT_STREQ("Unknown error 4294967295", strerror(-1));
+  ASSERT_STREQ("Unknown error -1", strerror(-1));
   ASSERT_STREQ("Unknown error 1234", strerror(1234));
 }
 
@@ -305,6 +305,19 @@
   }
 }
 
+
+#if __BIONIC__
+// We have to say "DeathTest" here so gtest knows to run this test (which exits)
+// in its own process.
+TEST(string_DeathTest, strcpy_fortified) {
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  char buf[10];
+  char *orig = strdup("0123456789");
+  ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGSEGV), "");
+  free(orig);
+}
+#endif
+
 #if __BIONIC__
 TEST(string, strlcat) {
   StringTestState state(SMALL);