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);