Merge "Define atomic_charN_t only if charN_t is supported."
diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk
index f9722ae..4d7ad96 100644
--- a/benchmarks/Android.mk
+++ b/benchmarks/Android.mk
@@ -54,7 +54,7 @@
LOCAL_SRC_FILES := $(benchmark_src_files)
include $(BUILD_EXECUTABLE)
-ifeq ($(HOST_OS)-$(HOST_ARCH),linux-x86)
+ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
ifeq ($(TARGET_ARCH),x86)
LINKER = linker
NATIVE_SUFFIX=32
diff --git a/benchmarks/property_benchmark.cpp b/benchmarks/property_benchmark.cpp
index f330d7e..0802b4c 100644
--- a/benchmarks/property_benchmark.cpp
+++ b/benchmarks/property_benchmark.cpp
@@ -28,12 +28,14 @@
extern void *__system_property_area__;
+// Do not exceed 512, that is about the largest number of properties
+// that can be created with the current property area size.
#define TEST_NUM_PROPS \
- Arg(1)->Arg(4)->Arg(16)->Arg(64)->Arg(128)->Arg(256)->Arg(512)->Arg(1024)
+ Arg(1)->Arg(4)->Arg(16)->Arg(64)->Arg(128)->Arg(256)->Arg(512)
struct LocalPropertyTestState {
LocalPropertyTestState(int nprops) : nprops(nprops), valid(false) {
- static const char prop_name_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_";
+ static const char prop_name_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
const char* android_data = getenv("ANDROID_DATA");
if (android_data == NULL) {
@@ -66,18 +68,38 @@
srandom(nprops);
for (int i = 0; i < nprops; i++) {
- name_lens[i] = random() % PROP_NAME_MAX;
+ // Make sure the name has at least 10 characters to make
+ // it very unlikely to generate the same random name.
+ name_lens[i] = (random() % (PROP_NAME_MAX - 10)) + 10;
names[i] = new char[PROP_NAME_MAX + 1];
+ size_t prop_name_len = sizeof(prop_name_chars) - 1;
for (int j = 0; j < name_lens[i]; j++) {
- names[i][j] = prop_name_chars[random() % (sizeof(prop_name_chars) - 1)];
+ if (j == 0 || names[i][j-1] == '.' || j == name_lens[i] - 1) {
+ // Certain values are not allowed:
+ // - Don't start name with '.'
+ // - Don't allow '.' to appear twice in a row
+ // - Don't allow the name to end with '.'
+ // This assumes that '.' is the last character in the
+ // array so that decrementing the length by one removes
+ // the value from the possible values.
+ prop_name_len--;
+ }
+ names[i][j] = prop_name_chars[random() % prop_name_len];
}
names[i][name_lens[i]] = 0;
- value_lens[i] = random() % PROP_VALUE_MAX;
+
+ // Make sure the value contains at least 1 character.
+ value_lens[i] = (random() % (PROP_VALUE_MAX - 1)) + 1;
values[i] = new char[PROP_VALUE_MAX];
for (int j = 0; j < value_lens[i]; j++) {
values[i][j] = prop_name_chars[random() % (sizeof(prop_name_chars) - 1)];
}
- __system_property_add(names[i], name_lens[i], values[i], value_lens[i]);
+
+ if (__system_property_add(names[i], name_lens[i], values[i], value_lens[i]) < 0) {
+ printf("Failed to add a property, terminating...\n");
+ printf("%s = %.*s\n", names[i], value_lens[i], values[i]);
+ exit(1);
+ }
}
valid = true;
diff --git a/benchmarks/time_benchmark.cpp b/benchmarks/time_benchmark.cpp
index 3bf8c07..0a146ae 100644
--- a/benchmarks/time_benchmark.cpp
+++ b/benchmarks/time_benchmark.cpp
@@ -16,6 +16,7 @@
#include "benchmark.h"
+#include <sys/syscall.h>
#include <time.h>
#if defined(__BIONIC__)
@@ -41,7 +42,7 @@
static void BM_time_clock_gettime(int iters) {
StartBenchmarkTiming();
- struct timespec t;
+ timespec t;
for (int i = 0; i < iters; ++i) {
clock_gettime(CLOCK_MONOTONIC, &t);
}
@@ -49,3 +50,50 @@
StopBenchmarkTiming();
}
BENCHMARK(BM_time_clock_gettime);
+
+static void BM_time_clock_gettime_syscall(int iters) {
+ StartBenchmarkTiming();
+
+ timespec t;
+ for (int i = 0; i < iters; ++i) {
+ syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &t);
+ }
+
+ StopBenchmarkTiming();
+}
+BENCHMARK(BM_time_clock_gettime_syscall);
+
+static void BM_time_gettimeofday(int iters) {
+ StartBenchmarkTiming();
+
+ timeval tv;
+ for (int i = 0; i < iters; ++i) {
+ gettimeofday(&tv, NULL);
+ }
+
+ StopBenchmarkTiming();
+}
+BENCHMARK(BM_time_gettimeofday);
+
+static void BM_time_gettimeofday_syscall(int iters) {
+ StartBenchmarkTiming();
+
+ timeval tv;
+ for (int i = 0; i < iters; ++i) {
+ syscall(__NR_gettimeofday, &tv, NULL);
+ }
+
+ StopBenchmarkTiming();
+}
+BENCHMARK(BM_time_gettimeofday_syscall);
+
+static void BM_time_time(int iters) {
+ StartBenchmarkTiming();
+
+ for (int i = 0; i < iters; ++i) {
+ time(NULL);
+ }
+
+ StopBenchmarkTiming();
+}
+BENCHMARK(BM_time_time);
diff --git a/libc/Android.mk b/libc/Android.mk
index 765f4d2..0485d72 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -67,7 +67,6 @@
bionic/unlockpt.c \
stdio/snprintf.c\
stdio/sprintf.c \
- stdlib/atexit.c \
unistd/syslog.c \
# Fortify implementations of libc functions.
@@ -178,6 +177,7 @@
bionic/pthread_sigmask.cpp \
bionic/ptrace.cpp \
bionic/raise.cpp \
+ bionic/rand.cpp \
bionic/readlink.cpp \
bionic/reboot.cpp \
bionic/recv.cpp \
@@ -229,6 +229,7 @@
bionic/umount.cpp \
bionic/unlink.cpp \
bionic/utimes.cpp \
+ bionic/vdso.cpp \
bionic/vfork.cpp \
bionic/wait.cpp \
bionic/wchar.cpp \
@@ -295,7 +296,6 @@
upstream-netbsd/lib/libc/stdlib/mrand48.c \
upstream-netbsd/lib/libc/stdlib/nrand48.c \
upstream-netbsd/lib/libc/stdlib/_rand48.c \
- upstream-netbsd/lib/libc/stdlib/rand.c \
upstream-netbsd/lib/libc/stdlib/rand_r.c \
upstream-netbsd/lib/libc/stdlib/seed48.c \
upstream-netbsd/lib/libc/stdlib/srand48.c \
@@ -306,7 +306,6 @@
upstream-netbsd/lib/libc/string/strcasestr.c \
upstream-netbsd/lib/libc/string/strcoll.c \
upstream-netbsd/lib/libc/string/strxfrm.c \
- upstream-netbsd/lib/libc/thread-stub/__isthreaded.c \
upstream-netbsd/lib/libc/unistd/killpg.c \
libc_upstream_openbsd_gdtoa_src_files := \
@@ -463,6 +462,7 @@
upstream-openbsd/lib/libc/stdio/wprintf.c \
upstream-openbsd/lib/libc/stdio/wscanf.c \
upstream-openbsd/lib/libc/stdio/wsetup.c \
+ upstream-openbsd/lib/libc/stdlib/atexit.c \
upstream-openbsd/lib/libc/stdlib/atoi.c \
upstream-openbsd/lib/libc/stdlib/atol.c \
upstream-openbsd/lib/libc/stdlib/atoll.c \
@@ -549,7 +549,6 @@
# Define some common includes
# ========================================================
libc_common_c_includes += \
- $(LOCAL_PATH)/stdlib \
$(LOCAL_PATH)/stdio \
# ========================================================
@@ -735,6 +734,7 @@
LOCAL_CFLAGS := \
$(libc_common_cflags) \
-Wno-sign-compare -Wno-uninitialized -Wno-unused-parameter \
+ -I$(LOCAL_PATH)/private \
-I$(LOCAL_PATH)/upstream-openbsd/android/include \
-I$(LOCAL_PATH)/upstream-openbsd/lib/libc/include \
-I$(LOCAL_PATH)/upstream-openbsd/lib/libc/gdtoa/ \
@@ -767,6 +767,7 @@
$(libc_common_cflags) \
-Wno-sign-compare -Wno-uninitialized \
-fvisibility=hidden \
+ -I$(LOCAL_PATH)/private \
-I$(LOCAL_PATH)/upstream-openbsd/android/include \
-I$(LOCAL_PATH)/upstream-openbsd/lib/libc/include \
-include openbsd-compat.h \
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index b4c8134..7ae054e 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -194,11 +194,9 @@
int swapoff(const char*) all
# time
-int gettimeofday(struct timeval*, struct timezone*) all
int settimeofday(const struct timeval*, const struct timezone*) all
clock_t times(struct tms*) all
int nanosleep(const struct timespec*, struct timespec*) all
-int clock_gettime(clockid_t clk_id, struct timespec* tp) all
int clock_settime(clockid_t clk_id, const struct timespec* tp) all
int clock_getres(clockid_t clk_id, struct timespec* res) all
int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec* req, struct timespec* rem) all
@@ -320,3 +318,9 @@
# x86-specific
int __set_thread_area:set_thread_area(void*) x86
+
+# vdso stuff.
+int clock_gettime(clockid_t, timespec*) arm,mips,mips64,x86
+int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86_64
+int gettimeofday(timeval*, timezone*) arm,mips,mips64,x86
+int __gettimeofday:gettimeofday(timeval*, timezone*) arm64,x86_64
diff --git a/libc/arch-arm64/syscalls/clock_gettime.S b/libc/arch-arm64/syscalls/__clock_gettime.S
similarity index 76%
rename from libc/arch-arm64/syscalls/clock_gettime.S
rename to libc/arch-arm64/syscalls/__clock_gettime.S
index ffdde57..f346648 100644
--- a/libc/arch-arm64/syscalls/clock_gettime.S
+++ b/libc/arch-arm64/syscalls/__clock_gettime.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(clock_gettime)
+ENTRY(__clock_gettime)
mov x8, __NR_clock_gettime
svc #0
@@ -11,4 +11,5 @@
b.hi __set_errno
ret
-END(clock_gettime)
+END(__clock_gettime)
+.hidden __clock_gettime
diff --git a/libc/arch-arm64/syscalls/gettimeofday.S b/libc/arch-arm64/syscalls/__gettimeofday.S
similarity index 77%
rename from libc/arch-arm64/syscalls/gettimeofday.S
rename to libc/arch-arm64/syscalls/__gettimeofday.S
index 3b6104b..6582c49 100644
--- a/libc/arch-arm64/syscalls/gettimeofday.S
+++ b/libc/arch-arm64/syscalls/__gettimeofday.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(gettimeofday)
+ENTRY(__gettimeofday)
mov x8, __NR_gettimeofday
svc #0
@@ -11,4 +11,5 @@
b.hi __set_errno
ret
-END(gettimeofday)
+END(__gettimeofday)
+.hidden __gettimeofday
diff --git a/libc/arch-x86_64/syscalls/clock_gettime.S b/libc/arch-x86_64/syscalls/__clock_gettime.S
similarity index 78%
rename from libc/arch-x86_64/syscalls/clock_gettime.S
rename to libc/arch-x86_64/syscalls/__clock_gettime.S
index 20850c8..7e553b8 100644
--- a/libc/arch-x86_64/syscalls/clock_gettime.S
+++ b/libc/arch-x86_64/syscalls/__clock_gettime.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(clock_gettime)
+ENTRY(__clock_gettime)
movl $__NR_clock_gettime, %eax
syscall
cmpq $-MAX_ERRNO, %rax
@@ -12,4 +12,5 @@
call __set_errno
1:
ret
-END(clock_gettime)
+END(__clock_gettime)
+.hidden __clock_gettime
diff --git a/libc/arch-x86_64/syscalls/gettimeofday.S b/libc/arch-x86_64/syscalls/__gettimeofday.S
similarity index 79%
rename from libc/arch-x86_64/syscalls/gettimeofday.S
rename to libc/arch-x86_64/syscalls/__gettimeofday.S
index 4867c30..a38eb64 100644
--- a/libc/arch-x86_64/syscalls/gettimeofday.S
+++ b/libc/arch-x86_64/syscalls/__gettimeofday.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(gettimeofday)
+ENTRY(__gettimeofday)
movl $__NR_gettimeofday, %eax
syscall
cmpq $-MAX_ERRNO, %rax
@@ -12,4 +12,5 @@
call __set_errno
1:
ret
-END(gettimeofday)
+END(__gettimeofday)
+.hidden __gettimeofday
diff --git a/libc/bionic/abort.cpp b/libc/bionic/abort.cpp
index 69ac0e5..75413c6 100644
--- a/libc/bionic/abort.cpp
+++ b/libc/bionic/abort.cpp
@@ -30,7 +30,6 @@
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
-#include "atexit.h"
#ifdef __arm__
extern "C" __LIBC_HIDDEN__ void __libc_android_abort()
diff --git a/libc/bionic/ctype.cpp b/libc/bionic/ctype.cpp
index 3960d9d..2b31d52 100644
--- a/libc/bionic/ctype.cpp
+++ b/libc/bionic/ctype.cpp
@@ -36,10 +36,6 @@
return isalpha(c);
}
-int isascii_l(int c, locale_t) {
- return isascii(c);
-}
-
int isblank_l(int c, locale_t) {
return isblank(c);
}
diff --git a/libc/bionic/dl_iterate_phdr_static.cpp b/libc/bionic/dl_iterate_phdr_static.cpp
index 7e9eedd..155a7a0 100644
--- a/libc/bionic/dl_iterate_phdr_static.cpp
+++ b/libc/bionic/dl_iterate_phdr_static.cpp
@@ -27,6 +27,7 @@
*/
#include <elf.h>
+#include <string.h>
#include <sys/auxv.h>
#include <sys/types.h>
#include <link.h>
@@ -37,11 +38,9 @@
int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data), void* data) {
ElfW(Ehdr)* ehdr = reinterpret_cast<ElfW(Ehdr)*>(&__executable_start);
- // TODO: again, copied from linker.c. Find a better home for this later.
- if (ehdr->e_ident[EI_MAG0] != ELFMAG0) return -1;
- if (ehdr->e_ident[EI_MAG1] != ELFMAG1) return -1;
- if (ehdr->e_ident[EI_MAG2] != ELFMAG2) return -1;
- if (ehdr->e_ident[EI_MAG3] != ELFMAG3) return -1;
+ if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
+ return -1;
+ }
// Dynamic binaries get their dl_iterate_phdr from the dynamic linker, but
// static binaries get this. We don't have a list of shared objects to
@@ -54,7 +53,7 @@
exe_info.dlpi_phdr = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<uintptr_t>(ehdr) + ehdr->e_phoff);
exe_info.dlpi_phnum = ehdr->e_phnum;
-#ifdef AT_SYSINFO_EHDR
+#if defined(AT_SYSINFO_EHDR)
// Try the executable first.
int rc = cb(&exe_info, sizeof(exe_info), data);
if (rc != 0) {
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index fa61c3c..9e4eecd 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -39,7 +39,6 @@
#include <sys/resource.h>
#include <unistd.h>
-#include "atexit.h"
#include "private/bionic_auxv.h"
#include "private/bionic_ssp.h"
#include "private/bionic_tls.h"
@@ -52,6 +51,8 @@
extern "C" int __set_tls(void* ptr);
extern "C" int __set_tid_address(int* tid_address);
+void __libc_init_vdso();
+
// Not public, but well-known in the BSDs.
const char* __progname;
@@ -130,6 +131,8 @@
_pthread_internal_add(main_thread);
__system_properties_init(); // Requires 'environ'.
+
+ __libc_init_vdso();
}
/* This function will be called during normal program termination
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 7c46364..78125f9 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -48,7 +48,6 @@
#include <stdlib.h>
#include <stdint.h>
#include <elf.h>
-#include "atexit.h"
#include "libc_init_common.h"
#include "private/bionic_tls.h"
@@ -58,6 +57,7 @@
extern void malloc_debug_init(void);
extern void malloc_debug_fini(void);
extern void netdClientInit(void);
+ extern int __cxa_atexit(void (*)(void *), void *, void *);
};
// We flag the __libc_preinit function as a constructor to ensure
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index ab0b3a6..bc11f3d 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -46,7 +46,6 @@
#include <sys/auxv.h>
#include <sys/mman.h>
-#include "atexit.h"
#include "libc_init_common.h"
#include "pthread_internal.h"
@@ -60,6 +59,8 @@
// itself at the start of a page.
#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
+extern "C" int __cxa_atexit(void (*)(void *), void *, void *);
+
static void call_array(void(**list)()) {
// First element is -1, list is null-terminated
while (*++list) {
diff --git a/libc/bionic/ptrace.cpp b/libc/bionic/ptrace.cpp
index 5715b09..5156ec2 100644
--- a/libc/bionic/ptrace.cpp
+++ b/libc/bionic/ptrace.cpp
@@ -26,28 +26,30 @@
* SUCH DAMAGE.
*/
-#include <sys/types.h>
+#include <stdarg.h>
#include <sys/ptrace.h>
-extern "C" long __ptrace(int request, pid_t pid, void* addr, void* data);
+extern "C" long __ptrace(int req, pid_t pid, void* addr, void* data);
-long ptrace(int request, pid_t pid, void* addr, void* data) {
- switch (request) {
- case PTRACE_PEEKUSR:
- case PTRACE_PEEKTEXT:
- case PTRACE_PEEKDATA:
- {
- long word;
- long ret = __ptrace(request, pid, addr, &word);
- if (ret == 0) {
- return word;
- } else {
- // __ptrace already set errno for us.
- return -1;
- }
- }
+long ptrace(int req, ...) {
+ bool is_peek = (req == PTRACE_PEEKUSR || req == PTRACE_PEEKTEXT || req == PTRACE_PEEKDATA);
+ long peek_result;
- default:
- return __ptrace(request, pid, addr, data);
+ va_list args;
+ va_start(args, req);
+ pid_t pid = va_arg(args, pid_t);
+ void* addr = va_arg(args, void*);
+ void* data;
+ if (is_peek) {
+ data = &peek_result;
+ } else {
+ data = va_arg(args, void*);
}
+ va_end(args);
+
+ long result = __ptrace(req, pid, addr, data);
+ if (is_peek && result == 0) {
+ return peek_result;
+ }
+ return result;
}
diff --git a/libc/upstream-openbsd/android/include/thread_private.h b/libc/bionic/rand.cpp
similarity index 64%
rename from libc/upstream-openbsd/android/include/thread_private.h
rename to libc/bionic/rand.cpp
index 10421e2..0074f2d 100644
--- a/libc/upstream-openbsd/android/include/thread_private.h
+++ b/libc/bionic/rand.cpp
@@ -14,13 +14,16 @@
* limitations under the License.
*/
-#ifndef _THREAD_PRIVATE_H_
-#define _THREAD_PRIVATE_H_
+#include <stdlib.h>
-#include <pthread.h>
+// The BSD rand/srand is very weak. glibc just uses random/srandom instead.
+// Since we're likely to run code intended for glibc, and POSIX doesn't seem
+// to disallow this, we go that route too.
-/* Note that these aren't compatible with the usual OpenBSD ones which lazy-initialize! */
-#define _MUTEX_LOCK(l) pthread_mutex_lock((pthread_mutex_t*) l)
-#define _MUTEX_UNLOCK(l) pthread_mutex_unlock((pthread_mutex_t*) l)
+int rand() {
+ return random();
+}
-#endif /* _THREAD_PRIVATE_H_ */
+void srand(unsigned int seed) {
+ return srandom(seed);
+}
diff --git a/libc/bionic/vdso.cpp b/libc/bionic/vdso.cpp
new file mode 100644
index 0000000..0875ee6
--- /dev/null
+++ b/libc/bionic/vdso.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <link.h>
+#include <sys/auxv.h>
+#include <unistd.h>
+
+// x86 has a vdso, but there's nothing useful to us in it.
+#if defined(__aarch64__) || defined(__x86_64__)
+
+#if defined(__aarch64__)
+#define VDSO_CLOCK_GETTIME_SYMBOL "__kernel_clock_gettime"
+#define VDSO_GETTIMEOFDAY_SYMBOL "__kernel_gettimeofday"
+#elif defined(__x86_64__)
+#define VDSO_CLOCK_GETTIME_SYMBOL "__vdso_clock_gettime"
+#define VDSO_GETTIMEOFDAY_SYMBOL "__vdso_gettimeofday"
+#endif
+
+#include <time.h>
+
+extern "C" int __clock_gettime(int, timespec*);
+extern "C" int __gettimeofday(timeval*, struct timezone*);
+
+struct vdso_entry {
+ const char* name;
+ void* fn;
+};
+
+enum {
+ VDSO_CLOCK_GETTIME = 0,
+ VDSO_GETTIMEOFDAY,
+ VDSO_END
+};
+
+static vdso_entry vdso_entries[] = {
+ [VDSO_CLOCK_GETTIME] = { VDSO_CLOCK_GETTIME_SYMBOL, reinterpret_cast<void*>(__clock_gettime) },
+ [VDSO_GETTIMEOFDAY] = { VDSO_GETTIMEOFDAY_SYMBOL, reinterpret_cast<void*>(__gettimeofday) },
+};
+
+int clock_gettime(int clock_id, timespec* tp) {
+ static int (*vdso_clock_gettime)(int, timespec*) =
+ (int (*)(int, timespec*)) vdso_entries[VDSO_CLOCK_GETTIME].fn;
+ return vdso_clock_gettime(clock_id, tp);
+}
+
+int gettimeofday(timeval* tv, struct timezone* tz) {
+ static int (*vdso_gettimeofday)(timeval*, struct timezone*) =
+ (int (*)(timeval*, struct timezone*)) vdso_entries[VDSO_GETTIMEOFDAY].fn;
+ return vdso_gettimeofday(tv, tz);
+}
+
+void __libc_init_vdso() {
+ // Do we have a vdso?
+ uintptr_t vdso_ehdr_addr = getauxval(AT_SYSINFO_EHDR);
+ ElfW(Ehdr)* vdso_ehdr = reinterpret_cast<ElfW(Ehdr)*>(vdso_ehdr_addr);
+ if (vdso_ehdr == NULL) {
+ return;
+ }
+
+ // How many symbols does it have?
+ size_t symbol_count = 0;
+ ElfW(Shdr)* vdso_shdr = reinterpret_cast<ElfW(Shdr)*>(vdso_ehdr_addr + vdso_ehdr->e_shoff);
+ for (size_t i = 0; i < vdso_ehdr->e_shnum; ++i) {
+ if (vdso_shdr[i].sh_type == SHT_DYNSYM) {
+ symbol_count = vdso_shdr[i].sh_size / sizeof(ElfW(Sym));
+ }
+ }
+ if (symbol_count == 0) {
+ return;
+ }
+
+ // Where's the dynamic table?
+ ElfW(Addr) vdso_addr = 0;
+ ElfW(Dyn)* vdso_dyn = NULL;
+ ElfW(Phdr)* vdso_phdr = reinterpret_cast<ElfW(Phdr)*>(vdso_ehdr_addr + vdso_ehdr->e_phoff);
+ for (size_t i = 0; i < vdso_ehdr->e_phnum; ++i) {
+ if (vdso_phdr[i].p_type == PT_DYNAMIC) {
+ vdso_dyn = reinterpret_cast<ElfW(Dyn)*>(vdso_ehdr_addr + vdso_phdr[i].p_offset);
+ } else if (vdso_phdr[i].p_type == PT_LOAD) {
+ vdso_addr = vdso_ehdr_addr + vdso_phdr[i].p_offset - vdso_phdr[i].p_vaddr;
+ }
+ }
+ if (vdso_addr == 0 || vdso_dyn == NULL) {
+ return;
+ }
+
+ // Where are the string and symbol tables?
+ const char* strtab = NULL;
+ ElfW(Sym)* symtab = NULL;
+ for (ElfW(Dyn)* d = vdso_dyn; d->d_tag != DT_NULL; ++d) {
+ if (d->d_tag == DT_STRTAB) {
+ strtab = reinterpret_cast<const char*>(vdso_addr + d->d_un.d_ptr);
+ } else if (d->d_tag == DT_SYMTAB) {
+ symtab = reinterpret_cast<ElfW(Sym)*>(vdso_addr + d->d_un.d_ptr);
+ }
+ }
+ if (strtab == NULL || symtab == NULL) {
+ return;
+ }
+
+ // Are there any symbols we want?
+ for (size_t i = 0; i < symbol_count; ++i) {
+ for (size_t j = 0; j < VDSO_END; ++j) {
+ if (strcmp(vdso_entries[j].name, strtab + symtab[i].st_name) == 0) {
+ vdso_entries[j].fn = reinterpret_cast<void*>(vdso_addr + symtab[i].st_value);
+ }
+ }
+ }
+}
+
+#else
+
+void __libc_init_vdso() {
+}
+
+#endif
diff --git a/libc/include/ctype.h b/libc/include/ctype.h
index 19b1adf..d05a952 100644
--- a/libc/include/ctype.h
+++ b/libc/include/ctype.h
@@ -75,7 +75,6 @@
int isalnum_l(int, locale_t);
int isalpha_l(int, locale_t);
-int isascii_l(int, locale_t);
int isblank_l(int, locale_t);
int iscntrl_l(int, locale_t);
int isdigit_l(int, locale_t);
diff --git a/libc/include/elf.h b/libc/include/elf.h
index 7a217b0..0975b7a 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -67,9 +67,6 @@
#define ELFOSABI_SYSV 0 /* Synonym for ELFOSABI_NONE used by valgrind. */
-#define EM_ARM 40
-#define EM_AARCH64 183
-
#define PT_GNU_RELRO 0x6474e552
#define STB_LOOS 10
diff --git a/libc/include/sys/glibc-syscalls.h b/libc/include/sys/glibc-syscalls.h
index 3131b6b..459ee78 100644
--- a/libc/include/sys/glibc-syscalls.h
+++ b/libc/include/sys/glibc-syscalls.h
@@ -217,10 +217,12 @@
#define SYS_sched_get_priority_max __NR_sched_get_priority_max
#define SYS_sched_get_priority_min __NR_sched_get_priority_min
#define SYS_sched_getaffinity __NR_sched_getaffinity
+#define SYS_sched_getattr __NR_sched_getattr
#define SYS_sched_getparam __NR_sched_getparam
#define SYS_sched_getscheduler __NR_sched_getscheduler
#define SYS_sched_rr_get_interval __NR_sched_rr_get_interval
#define SYS_sched_setaffinity __NR_sched_setaffinity
+#define SYS_sched_setattr __NR_sched_setattr
#define SYS_sched_setparam __NR_sched_setparam
#define SYS_sched_setscheduler __NR_sched_setscheduler
#define SYS_sched_yield __NR_sched_yield
@@ -545,10 +547,12 @@
#define SYS_sched_get_priority_max __NR_sched_get_priority_max
#define SYS_sched_get_priority_min __NR_sched_get_priority_min
#define SYS_sched_getaffinity __NR_sched_getaffinity
+#define SYS_sched_getattr __NR_sched_getattr
#define SYS_sched_getparam __NR_sched_getparam
#define SYS_sched_getscheduler __NR_sched_getscheduler
#define SYS_sched_rr_get_interval __NR_sched_rr_get_interval
#define SYS_sched_setaffinity __NR_sched_setaffinity
+#define SYS_sched_setattr __NR_sched_setattr
#define SYS_sched_setparam __NR_sched_setparam
#define SYS_sched_setscheduler __NR_sched_setscheduler
#define SYS_sched_yield __NR_sched_yield
@@ -902,10 +906,12 @@
#define SYS_sched_get_priority_max __NR_sched_get_priority_max
#define SYS_sched_get_priority_min __NR_sched_get_priority_min
#define SYS_sched_getaffinity __NR_sched_getaffinity
+#define SYS_sched_getattr __NR_sched_getattr
#define SYS_sched_getparam __NR_sched_getparam
#define SYS_sched_getscheduler __NR_sched_getscheduler
#define SYS_sched_rr_get_interval __NR_sched_rr_get_interval
#define SYS_sched_setaffinity __NR_sched_setaffinity
+#define SYS_sched_setattr __NR_sched_setattr
#define SYS_sched_setparam __NR_sched_setparam
#define SYS_sched_setscheduler __NR_sched_setscheduler
#define SYS_sched_yield __NR_sched_yield
@@ -1258,10 +1264,12 @@
#define SYS_sched_get_priority_max __NR_sched_get_priority_max
#define SYS_sched_get_priority_min __NR_sched_get_priority_min
#define SYS_sched_getaffinity __NR_sched_getaffinity
+#define SYS_sched_getattr __NR_sched_getattr
#define SYS_sched_getparam __NR_sched_getparam
#define SYS_sched_getscheduler __NR_sched_getscheduler
#define SYS_sched_rr_get_interval __NR_sched_rr_get_interval
#define SYS_sched_setaffinity __NR_sched_setaffinity
+#define SYS_sched_setattr __NR_sched_setattr
#define SYS_sched_setparam __NR_sched_setparam
#define SYS_sched_setscheduler __NR_sched_setscheduler
#define SYS_sched_yield __NR_sched_yield
@@ -1586,10 +1594,12 @@
#define SYS_sched_get_priority_max __NR_sched_get_priority_max
#define SYS_sched_get_priority_min __NR_sched_get_priority_min
#define SYS_sched_getaffinity __NR_sched_getaffinity
+#define SYS_sched_getattr __NR_sched_getattr
#define SYS_sched_getparam __NR_sched_getparam
#define SYS_sched_getscheduler __NR_sched_getscheduler
#define SYS_sched_rr_get_interval __NR_sched_rr_get_interval
#define SYS_sched_setaffinity __NR_sched_setaffinity
+#define SYS_sched_setattr __NR_sched_setattr
#define SYS_sched_setparam __NR_sched_setparam
#define SYS_sched_setscheduler __NR_sched_setscheduler
#define SYS_sched_yield __NR_sched_yield
diff --git a/libc/include/sys/prctl.h b/libc/include/sys/prctl.h
index 00e5837..391c22a 100644
--- a/libc/include/sys/prctl.h
+++ b/libc/include/sys/prctl.h
@@ -31,6 +31,25 @@
#include <linux/prctl.h>
#include <sys/cdefs.h>
+/* These should appear in the uapi headers at some point, but they're not there right now. */
+#if !defined(PR_SET_TIMERSLACK_PID)
+#define PR_SET_TIMERSLACK_PID 41
+#else
+#error PR_SET_TIMERSLACK_PID defined twice
+#endif
+
+#if !defined(PR_SET_VMA)
+#define PR_SET_VMA 0x53564d41
+#else
+#error PR_SET_VMA defined twice
+#endif
+
+#if !defined(PR_SET_VMA_ANON_NAME)
+#define PR_SET_VMA_ANON_NAME 0
+#else
+#error PR_SET_VMA_ANON_NAME defined twice
+#endif
+
__BEGIN_DECLS
/* IMPORTANT NOTE: This function is declared as taking a variable number
diff --git a/libc/include/sys/ptrace.h b/libc/include/sys/ptrace.h
index 848416b..8bba9fe 100644
--- a/libc/include/sys/ptrace.h
+++ b/libc/include/sys/ptrace.h
@@ -30,15 +30,15 @@
#include <sys/cdefs.h>
#include <sys/types.h>
-/* For all of the defines */
#include <linux/ptrace.h>
__BEGIN_DECLS
-#define PTRACE_POKEUSER PTRACE_POKEUSR
-#define PTRACE_PEEKUSER PTRACE_PEEKUSR
+/* glibc uses different names from the kernel for these two... */
+#define PTRACE_POKEUSER PTRACE_POKEUSR
+#define PTRACE_PEEKUSER PTRACE_PEEKUSR
-extern long ptrace(int request, pid_t pid, void *addr, void *data);
+extern long ptrace(int, ...);
__END_DECLS
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index ae2f238..3b11d20 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -40,6 +40,13 @@
#include <linux/types.h>
#include <linux/compiler.h>
+/* This is an Android extension that won't be in the uapi headers for the common kernel. */
+#if !defined(SIOCKILLADDR)
+#define SIOCKILLADDR 0x8939
+#else
+#error SIOCKILLADDR defined twice
+#endif
+
__BEGIN_DECLS
#define sockaddr_storage __kernel_sockaddr_storage
diff --git a/libc/kernel/README.TXT b/libc/kernel/README.TXT
index 0edbcc6..e7312ef 100644
--- a/libc/kernel/README.TXT
+++ b/libc/kernel/README.TXT
@@ -55,11 +55,15 @@
Grab the latest headers from the android kernel by running this command:
- bionic/kernel/tools/generate_uapi_headers.sh --download-kernel
+ bionic/libc/kernel/tools/generate_uapi_headers.sh --download-kernel
Next, run this command to copy the parsed files to bionic/libc/kernel/uapi:
- bionic/kernel/tools/update_all.py
+ bionic/libc/kernel/tools/update_all.py
+
+Finally, run this command to regenerate the syscalls list:
+
+ bionic/libc/tools/gensyscalls.py
After this, you will need to build/test the tree to make sure that these
changes do not introduce any errors.
diff --git a/libc/private/bionic_macros.h b/libc/private/bionic_macros.h
index a3a6985..61794bd 100644
--- a/libc/private/bionic_macros.h
+++ b/libc/private/bionic_macros.h
@@ -37,6 +37,8 @@
(((value) + (alignment) - 1) & ~((alignment) - 1))
#define BIONIC_ROUND_UP_POWER_OF_2(value) \
- (1UL << (sizeof(value) * 8 - 1 - __builtin_clz(value)))
+ (sizeof(value) == 8) \
+ ? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(value)))) \
+ : (1UL << (32 - __builtin_clz(static_cast<unsigned int>(value))))
#endif // _BIONIC_MACROS_H_
diff --git a/libc/private/bionic_name_mem.h b/libc/private/bionic_name_mem.h
index 98716f4..1c7664e 100644
--- a/libc/private/bionic_name_mem.h
+++ b/libc/private/bionic_name_mem.h
@@ -34,7 +34,7 @@
__BEGIN_DECLS
-int __bionic_name_mem(void* addr, size_t len, const char* name);
+__LIBC_HIDDEN__ int __bionic_name_mem(void* addr, size_t len, const char* name);
__END_DECLS
diff --git a/libc/private/thread_private.h b/libc/private/thread_private.h
index 724808a..b8b1a81 100644
--- a/libc/private/thread_private.h
+++ b/libc/private/thread_private.h
@@ -33,8 +33,12 @@
#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \
pthread_mutex_unlock( &__THREAD_NAME(name)._private_lock )
-__LIBC_HIDDEN__ void _thread_atexit_lock(void);
-__LIBC_HIDDEN__ void _thread_atexit_unlock(void);
+/* Note that these aren't compatible with the usual OpenBSD ones which lazy-initialize! */
+#define _MUTEX_LOCK(l) pthread_mutex_lock((pthread_mutex_t*) l)
+#define _MUTEX_UNLOCK(l) pthread_mutex_unlock((pthread_mutex_t*) l)
+
+__LIBC_HIDDEN__ void _thread_atexit_lock(void);
+__LIBC_HIDDEN__ void _thread_atexit_unlock(void);
#define _ATEXIT_LOCK() _thread_atexit_lock()
#define _ATEXIT_UNLOCK() _thread_atexit_unlock()
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index 151e009..4511a71 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -49,14 +49,7 @@
*/
__LIBC_HIDDEN__ int __srget(FILE*);
__LIBC_HIDDEN__ int __swbuf(int, FILE*);
-
-/*
- * The NDK apparently includes an android_support.a library that
- * refers to __srefill in its copy of the vsnprintf implementation.
- */
-/* TODO(LP64): __LIBC_HIDDEN__ int __srefill(FILE*);*/
-/* http://b/15291317: the LP64 NDK needs to be fixed to remove that cruft. */
-__LIBC_ABI_PUBLIC__ int __srefill(FILE*);
+__LIBC_HIDDEN__ int __srefill(FILE*);
#else
__LIBC_ABI_PUBLIC__ int __srget(FILE*);
__LIBC_ABI_PUBLIC__ int __swbuf(int, FILE*);
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
deleted file mode 100644
index e10238b..0000000
--- a/libc/stdlib/atexit.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/* $OpenBSD: atexit.c,v 1.14 2007/09/05 20:47:47 chl Exp $ */
-/*
- * Copyright (c) 2002 Daniel Hartmeier
- * 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 HOLDERS 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/types.h>
-#include <sys/mman.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "atexit.h"
-#include "private/thread_private.h"
-
-struct atexit *__atexit;
-
-/*
- * TODO: Read this before upstreaming:
- *
- * As of Apr 2014 there is a bug regaring function type detection logic in
- * Free/Open/NetBSD implementations of __cxa_finalize().
- *
- * What it is about:
- * First of all there are two kind of atexit handlers:
- * 1) void handler(void) - this is the regular type
- * available for to user via atexit(.) function call.
- *
- * 2) void internal_handler(void*) - this is the type
- * __cxa_atexit() function expects. This handler is used
- * by C++ compiler to register static destructor calls.
- * Note that calling this function as the handler of type (1)
- * results in incorrect this pointer in static d-tors.
- *
- * What is wrong with BSD implementations:
- *
- * They use dso argument to identify the handler type. The problem
- * with it is dso is also used to identify the handlers associated
- * with particular dynamic library and allow __cxa_finalize to call correct
- * set of functions on dlclose(). And it cannot identify both.
- *
- * What is correct way to identify function type?
- *
- * Consider this:
- * 1. __cxa_finalize and __cxa_atexit are part of libc and do not have access to hidden
- * &__dso_handle.
- * 2. __cxa_atexit has only 3 arguments: function pointer, function argument, dso.
- * none of them can be reliably used to pass information about handler type.
- * 3. following http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor (3.3.5.3 - B)
- * translation of user atexit -> __cxa_atexit(f, NULL, NULL) results in crashes
- * on exit() after dlclose() of a library with an atexit() call.
- *
- * One way to resolve this is to always call second form of handler, which will
- * result in storing unused argument in register/stack depending on architecture
- * and should not present any problems.
- *
- * Another way is to make them dso-local in one way or the other.
- */
-
-/*
- * Function pointers are stored in a linked list of pages. The list
- * is initially empty, and pages are allocated on demand. The first
- * function pointer in the first allocated page (the last one in
- * the linked list) was reserved for the cleanup function.
- *
- * Outside the following functions, all pages are mprotect()'ed
- * to prevent unintentional/malicious corruption.
- */
-
-/*
- * Register a function to be performed at exit or when a shared object
- * with the given dso handle is unloaded dynamically. Also used as
- * the backend for atexit(). For more info on this API, see:
- *
- * http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor
- */
-int
-__cxa_atexit(void (*func)(void *), void *arg, void *dso)
-{
- struct atexit *p = __atexit;
- struct atexit_fn *fnp;
- size_t pgsize = getpagesize();
- int ret = -1;
-
- if (pgsize < sizeof(*p))
- return (-1);
- _ATEXIT_LOCK();
- p = __atexit;
- if (p != NULL) {
- if (p->ind + 1 >= p->max)
- p = NULL;
- else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
- goto unlock;
- }
- if (p == NULL) {
- p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
- MAP_ANON | MAP_PRIVATE, -1, 0);
- if (p == MAP_FAILED)
- goto unlock;
- if (__atexit == NULL) {
- memset(&p->fns[0], 0, sizeof(p->fns[0]));
- p->ind = 1;
- } else
- p->ind = 0;
- p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
- sizeof(p->fns[0]);
- p->next = __atexit;
- __atexit = p;
- }
- fnp = &p->fns[p->ind++];
- fnp->cxa_func = func;
- fnp->fn_arg = arg;
- fnp->fn_dso = dso;
- if (mprotect(p, pgsize, PROT_READ))
- goto unlock;
- ret = 0;
-unlock:
- _ATEXIT_UNLOCK();
- return (ret);
-}
-
-/*
- * Call all handlers registered with __cxa_atexit() for the shared
- * object owning 'dso'.
- * Note: if 'dso' is NULL, then all remaining handlers are called.
- */
-void
-__cxa_finalize(void *dso)
-{
- struct atexit *p, *q, *original_atexit;
- struct atexit_fn fn;
- int n, pgsize = getpagesize(), original_ind;
- static int call_depth;
-
- _ATEXIT_LOCK();
- call_depth++;
-
- p = original_atexit = __atexit;
- n = original_ind = p != NULL ? p->ind : 0;
- while (p != NULL) {
- if (p->fns[n].cxa_func != NULL /* not called */
- && (dso == NULL || dso == p->fns[n].fn_dso)) { /* correct DSO */
- /*
- * Mark handler as having been already called to avoid
- * dupes and loops, then call the appropriate function.
- */
- fn = p->fns[n];
- if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) {
- p->fns[n].cxa_func = NULL;
- mprotect(p, pgsize, PROT_READ);
- }
-
- _ATEXIT_UNLOCK();
- (*fn.cxa_func)(fn.fn_arg);
- _ATEXIT_LOCK();
- // check for new atexit handlers
- if ((__atexit->ind != original_ind) || (__atexit != original_atexit)) {
- // need to restart now to preserve correct
- // call order - LIFO
- p = original_atexit = __atexit;
- n = original_ind = p->ind;
- continue;
- }
- }
- if (n == 0) {
- p = p->next;
- n = p != NULL ? p->ind : 0;
- } else {
- --n;
- }
- }
-
- --call_depth;
-
- /*
- * If called via exit(), unmap the pages since we have now run
- * all the handlers. We defer this until calldepth == 0 so that
- * we don't unmap things prematurely if called recursively.
- */
- if (dso == NULL && call_depth == 0) {
- for (p = __atexit; p != NULL; ) {
- q = p;
- p = p->next;
- munmap(q, pgsize);
- }
- __atexit = NULL;
- }
- _ATEXIT_UNLOCK();
-}
-
-/*
- * Register the cleanup function
- */
-void
-__atexit_register_cleanup(void (*func)(void))
-{
- struct atexit *p;
- size_t pgsize = getpagesize();
-
- if (pgsize < sizeof(*p))
- return;
- _ATEXIT_LOCK();
- p = __atexit;
- while (p != NULL && p->next != NULL)
- p = p->next;
- if (p == NULL) {
- p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
- MAP_ANON | MAP_PRIVATE, -1, 0);
- if (p == MAP_FAILED)
- goto unlock;
- p->ind = 1;
- p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
- sizeof(p->fns[0]);
- p->next = NULL;
- __atexit = p;
- } else {
- if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
- goto unlock;
- }
- p->fns[0].cxa_func = (void (*)(void*))func;
- p->fns[0].fn_arg = NULL;
- p->fns[0].fn_dso = NULL;
- mprotect(p, pgsize, PROT_READ);
-unlock:
- _ATEXIT_UNLOCK();
-}
diff --git a/libc/upstream-freebsd/android/include/namespace.h b/libc/upstream-freebsd/android/include/namespace.h
index a980b57..a3f850e 100644
--- a/libc/upstream-freebsd/android/include/namespace.h
+++ b/libc/upstream-freebsd/android/include/namespace.h
@@ -17,6 +17,4 @@
#ifndef _BIONIC_FREEBSD_NAMESPACE_H_included
#define _BIONIC_FREEBSD_NAMESPACE_H_included
-__attribute__((visibility("hidden"))) char* _mktemp(char*);
-
#endif
diff --git a/libc/upstream-netbsd/android/include/namespace.h b/libc/upstream-netbsd/android/include/namespace.h
index a4d4151..5df543c 100644
--- a/libc/upstream-netbsd/android/include/namespace.h
+++ b/libc/upstream-netbsd/android/include/namespace.h
@@ -22,4 +22,7 @@
#undef __weak_alias
#endif
+__LIBC_HIDDEN__ int __res_enable_mt(void);
+__LIBC_HIDDEN__ int __res_disable_mt(void);
+
#endif
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/rand.c b/libc/upstream-netbsd/lib/libc/stdlib/rand.c
deleted file mode 100644
index 4909d14..0000000
--- a/libc/upstream-netbsd/lib/libc/stdlib/rand.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* $NetBSD: rand.c,v 1.12 2012/06/25 22:32:45 abs Exp $ */
-
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)rand.c 8.1 (Berkeley) 6/14/93";
-#else
-__RCSID("$NetBSD: rand.c,v 1.12 2012/06/25 22:32:45 abs Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-#include <stdlib.h>
-
-static u_long next = 1;
-
-int
-rand(void)
-{
- /* LINTED integer overflow */
- return (int)((next = next * 1103515245 + 12345) % ((u_long)RAND_MAX + 1));
-}
-
-void
-srand(u_int seed)
-{
- next = seed;
-}
diff --git a/libc/upstream-netbsd/lib/libc/thread-stub/__isthreaded.c b/libc/upstream-netbsd/lib/libc/thread-stub/__isthreaded.c
deleted file mode 100644
index 50c1b6f..0000000
--- a/libc/upstream-netbsd/lib/libc/thread-stub/__isthreaded.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* $NetBSD: __isthreaded.c,v 1.3 2009/12/01 01:33:25 explorer Exp $ */
-
-/*-
- * Copyright (c) 1999 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Michael Graff.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: __isthreaded.c,v 1.3 2009/12/01 01:33:25 explorer Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-int __isthreaded = 0;
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index f00d91a..5827a82 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -37,7 +37,17 @@
#define issetugid() 0
/* LP32 NDK ctype.h contained references to these. */
-__LIBC64_HIDDEN__ extern const short *_tolower_tab_;
-__LIBC64_HIDDEN__ extern const short *_toupper_tab_;
+__LIBC64_HIDDEN__ extern const short* _tolower_tab_;
+__LIBC64_HIDDEN__ extern const short* _toupper_tab_;
+
+__LIBC_HIDDEN__ extern struct atexit* __atexit;
+__LIBC_HIDDEN__ extern const char _C_ctype_[];
+__LIBC_HIDDEN__ extern const short _C_toupper_[];
+__LIBC_HIDDEN__ extern const short _C_tolower_[];
+__LIBC_HIDDEN__ extern char* __findenv(const char*, int, int*);
+__LIBC_HIDDEN__ extern char* _mktemp(char*);
+
+/* TODO: hide this when android_support.a is fixed (http://b/16298580).*/
+/*__LIBC_HIDDEN__*/ extern int __isthreaded;
#endif
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/atexit.c b/libc/upstream-openbsd/lib/libc/stdlib/atexit.c
new file mode 100644
index 0000000..6532b38
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdlib/atexit.c
@@ -0,0 +1,202 @@
+/* $OpenBSD: atexit.c,v 1.20 2014/07/11 09:51:37 kettenis Exp $ */
+/*
+ * Copyright (c) 2002 Daniel Hartmeier
+ * 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 HOLDERS 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/types.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "atexit.h"
+#include "thread_private.h"
+
+struct atexit *__atexit;
+static int restartloop;
+
+/*
+ * Function pointers are stored in a linked list of pages. The list
+ * is initially empty, and pages are allocated on demand. The first
+ * function pointer in the first allocated page (the last one in
+ * the linked list) is reserved for the cleanup function.
+ *
+ * Outside the following functions, all pages are mprotect()'ed
+ * to prevent unintentional/malicious corruption.
+ */
+
+/*
+ * Register a function to be performed at exit or when a shared object
+ * with the given dso handle is unloaded dynamically. Also used as
+ * the backend for atexit(). For more info on this API, see:
+ *
+ * http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor
+ */
+int
+__cxa_atexit(void (*func)(void *), void *arg, void *dso)
+{
+ struct atexit *p = __atexit;
+ struct atexit_fn *fnp;
+ int pgsize = getpagesize();
+ int ret = -1;
+
+ if (pgsize < sizeof(*p))
+ return (-1);
+ _ATEXIT_LOCK();
+ p = __atexit;
+ if (p != NULL) {
+ if (p->ind + 1 >= p->max)
+ p = NULL;
+ else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
+ goto unlock;
+ }
+ if (p == NULL) {
+ p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (p == MAP_FAILED)
+ goto unlock;
+ if (__atexit == NULL) {
+ memset(&p->fns[0], 0, sizeof(p->fns[0]));
+ p->ind = 1;
+ } else
+ p->ind = 0;
+ p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
+ sizeof(p->fns[0]);
+ p->next = __atexit;
+ __atexit = p;
+ }
+ fnp = &p->fns[p->ind++];
+ fnp->fn_ptr = func;
+ fnp->fn_arg = arg;
+ fnp->fn_dso = dso;
+ if (mprotect(p, pgsize, PROT_READ))
+ goto unlock;
+ restartloop = 1;
+ ret = 0;
+unlock:
+ _ATEXIT_UNLOCK();
+ return (ret);
+}
+
+/*
+ * Call all handlers registered with __cxa_atexit() for the shared
+ * object owning 'dso'.
+ * Note: if 'dso' is NULL, then all remaining handlers are called.
+ */
+void
+__cxa_finalize(void *dso)
+{
+ struct atexit *p, *q;
+ struct atexit_fn fn;
+ int n, pgsize = getpagesize();
+ static int call_depth;
+
+ _ATEXIT_LOCK();
+ call_depth++;
+
+restart:
+ restartloop = 0;
+ for (p = __atexit; p != NULL; p = p->next) {
+ for (n = p->ind; --n >= 0;) {
+ if (p->fns[n].fn_ptr == NULL)
+ continue; /* already called */
+ if (dso != NULL && dso != p->fns[n].fn_dso)
+ continue; /* wrong DSO */
+
+ /*
+ * Mark handler as having been already called to avoid
+ * dupes and loops, then call the appropriate function.
+ */
+ fn = p->fns[n];
+ if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) {
+ p->fns[n].fn_ptr = NULL;
+ mprotect(p, pgsize, PROT_READ);
+ }
+ _ATEXIT_UNLOCK();
+ (*fn.fn_ptr)(fn.fn_arg);
+ _ATEXIT_LOCK();
+ if (restartloop)
+ goto restart;
+ }
+ }
+
+ call_depth--;
+
+ /*
+ * If called via exit(), unmap the pages since we have now run
+ * all the handlers. We defer this until calldepth == 0 so that
+ * we don't unmap things prematurely if called recursively.
+ */
+ if (dso == NULL && call_depth == 0) {
+ for (p = __atexit; p != NULL; ) {
+ q = p;
+ p = p->next;
+ munmap(q, pgsize);
+ }
+ __atexit = NULL;
+ }
+ _ATEXIT_UNLOCK();
+}
+
+/*
+ * Register the cleanup function
+ */
+void
+__atexit_register_cleanup(void (*func)(void))
+{
+ struct atexit *p;
+ int pgsize = getpagesize();
+
+ if (pgsize < sizeof(*p))
+ return;
+ _ATEXIT_LOCK();
+ p = __atexit;
+ while (p != NULL && p->next != NULL)
+ p = p->next;
+ if (p == NULL) {
+ p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (p == MAP_FAILED)
+ goto unlock;
+ p->ind = 1;
+ p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
+ sizeof(p->fns[0]);
+ p->next = NULL;
+ __atexit = p;
+ } else {
+ if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
+ goto unlock;
+ }
+ p->fns[0].fn_ptr = (void (*)(void *))func;
+ p->fns[0].fn_arg = NULL;
+ p->fns[0].fn_dso = NULL;
+ mprotect(p, pgsize, PROT_READ);
+ restartloop = 1;
+unlock:
+ _ATEXIT_UNLOCK();
+}
diff --git a/libc/stdlib/atexit.h b/libc/upstream-openbsd/lib/libc/stdlib/atexit.h
similarity index 88%
rename from libc/stdlib/atexit.h
rename to libc/upstream-openbsd/lib/libc/stdlib/atexit.h
index b530ade..3de2aa3 100644
--- a/libc/stdlib/atexit.h
+++ b/libc/upstream-openbsd/lib/libc/stdlib/atexit.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: atexit.h,v 1.7 2007/09/03 14:40:16 millert Exp $ */
+/* $OpenBSD: atexit.h,v 1.9 2014/06/18 19:01:10 kettenis Exp $ */
/*
* Copyright (c) 2002 Daniel Hartmeier
@@ -30,24 +30,18 @@
*
*/
-#include <sys/cdefs.h>
-
struct atexit {
struct atexit *next; /* next in list */
int ind; /* next index in this table */
int max; /* max entries >= ATEXIT_SIZE */
struct atexit_fn {
- void (*cxa_func)(void *);
+ void (*fn_ptr)(void *);
void *fn_arg; /* argument for CXA callback */
void *fn_dso; /* shared module handle */
} fns[1]; /* the table itself */
};
-__BEGIN_DECLS
-
-__LIBC_HIDDEN__ extern struct atexit *__atexit; /* points to head of LIFO stack */
+extern struct atexit *__atexit; /* points to head of LIFO stack */
int __cxa_atexit(void (*)(void *), void *, void *);
void __cxa_finalize(void *);
-
-__END_DECLS
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/exit.c b/libc/upstream-openbsd/lib/libc/stdlib/exit.c
index ef8b335..83fe3d2 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/exit.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/exit.c
@@ -33,6 +33,16 @@
#include <stdlib.h>
#include <unistd.h>
#include "atexit.h"
+#include "thread_private.h"
+
+/*
+ * This variable is zero until a process has created a thread.
+ * It is used to avoid calling locking functions in libc when they
+ * are not required. By default, libc is intended to be(come)
+ * thread-safe, but without a (significant) penalty to non-threaded
+ * processes.
+ */
+int __isthreaded = 0;
/*
* Exit, flushing stdio buffers if necessary.
diff --git a/libc/upstream-openbsd/lib/libc/string/stpcpy.c b/libc/upstream-openbsd/lib/libc/string/stpcpy.c
index d3d61e0..d88afac 100644
--- a/libc/upstream-openbsd/lib/libc/string/stpcpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/stpcpy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: stpcpy.c,v 1.1 2012/01/17 02:48:01 guenther Exp $ */
+/* $OpenBSD: stpcpy.c,v 1.2 2014/07/09 17:08:21 naddy Exp $ */
/*
* Copyright (c) 1988 Regents of the University of California.
@@ -33,7 +33,7 @@
#if defined(APIWARN)
__warn_references(stpcpy,
- "warning: stpcpy() is dangerous GNU crap; don't use it");
+ "warning: stpcpy() is dangerous; do not use it");
#endif
char *
diff --git a/libc/upstream-openbsd/lib/libc/string/strcat.c b/libc/upstream-openbsd/lib/libc/string/strcat.c
index 7cea522..646c9c2 100644
--- a/libc/upstream-openbsd/lib/libc/string/strcat.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: strcat.c,v 1.8 2005/08/08 08:05:37 espie Exp $ */
+/* $OpenBSD: strcat.c,v 1.9 2014/06/10 04:17:37 deraadt Exp $ */
/*
* Copyright (c) 1988 Regents of the University of California.
@@ -29,11 +29,7 @@
* SUCH DAMAGE.
*/
-#if !defined(_KERNEL) && !defined(_STANDALONE)
#include <string.h>
-#else
-#include <lib/libkern/libkern.h>
-#endif
#if defined(APIWARN)
__warn_references(strcat,
diff --git a/libc/upstream-openbsd/lib/libc/string/strcmp.c b/libc/upstream-openbsd/lib/libc/string/strcmp.c
index 816fd11..d1b6c50 100644
--- a/libc/upstream-openbsd/lib/libc/string/strcmp.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: strcmp.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */
+/* $OpenBSD: strcmp.c,v 1.8 2014/06/10 04:17:37 deraadt Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@@ -32,11 +32,7 @@
* SUCH DAMAGE.
*/
-#if !defined(_KERNEL) && !defined(_STANDALONE)
#include <string.h>
-#else
-#include <lib/libkern/libkern.h>
-#endif
/*
* Compare strings.
diff --git a/libc/upstream-openbsd/lib/libc/string/strcpy.c b/libc/upstream-openbsd/lib/libc/string/strcpy.c
index 71d90d4..5a9001e 100644
--- a/libc/upstream-openbsd/lib/libc/string/strcpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/strcpy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: strcpy.c,v 1.8 2005/08/08 08:05:37 espie Exp $ */
+/* $OpenBSD: strcpy.c,v 1.9 2014/06/10 04:17:37 deraadt Exp $ */
/*
* Copyright (c) 1988 Regents of the University of California.
@@ -29,11 +29,7 @@
* SUCH DAMAGE.
*/
-#if !defined(_KERNEL) && !defined(_STANDALONE)
#include <string.h>
-#else
-#include <lib/libkern/libkern.h>
-#endif
#if defined(APIWARN)
__warn_references(strcpy,
diff --git a/libc/upstream-openbsd/lib/libc/string/strlen.c b/libc/upstream-openbsd/lib/libc/string/strlen.c
index 12d9ec4..7e0e27b 100644
--- a/libc/upstream-openbsd/lib/libc/string/strlen.c
+++ b/libc/upstream-openbsd/lib/libc/string/strlen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: strlen.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */
+/* $OpenBSD: strlen.c,v 1.8 2014/06/10 04:17:37 deraadt Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -29,11 +29,7 @@
* SUCH DAMAGE.
*/
-#if !defined(_KERNEL) && !defined(_STANDALONE)
#include <string.h>
-#else
-#include <lib/libkern/libkern.h>
-#endif
size_t
strlen(const char *str)
diff --git a/libc/upstream-openbsd/lib/libc/string/strncmp.c b/libc/upstream-openbsd/lib/libc/string/strncmp.c
index 0aea80d..0a4ddc1 100644
--- a/libc/upstream-openbsd/lib/libc/string/strncmp.c
+++ b/libc/upstream-openbsd/lib/libc/string/strncmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: strncmp.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */
+/* $OpenBSD: strncmp.c,v 1.8 2014/06/10 04:17:37 deraadt Exp $ */
/*
* Copyright (c) 1989 The Regents of the University of California.
@@ -29,11 +29,7 @@
* SUCH DAMAGE.
*/
-#if !defined(_KERNEL) && !defined(_STANDALONE)
#include <string.h>
-#else
-#include <lib/libkern/libkern.h>
-#endif
int
strncmp(const char *s1, const char *s2, size_t n)
diff --git a/libc/upstream-openbsd/lib/libc/string/strncpy.c b/libc/upstream-openbsd/lib/libc/string/strncpy.c
index 4426cbe..5003a19 100644
--- a/libc/upstream-openbsd/lib/libc/string/strncpy.c
+++ b/libc/upstream-openbsd/lib/libc/string/strncpy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: strncpy.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
+/* $OpenBSD: strncpy.c,v 1.7 2014/06/10 04:17:37 deraadt Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@@ -32,11 +32,7 @@
* SUCH DAMAGE.
*/
-#if !defined(_KERNEL) && !defined(_STANDALONE)
#include <string.h>
-#else
-#include <lib/libkern/libkern.h>
-#endif
/*
* Copy src to dst, truncating or null-padding to always copy n bytes.
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 11585af..0b99d20 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -156,10 +156,7 @@
}
bool ElfReader::VerifyElfHeader() {
- if (header_.e_ident[EI_MAG0] != ELFMAG0 ||
- header_.e_ident[EI_MAG1] != ELFMAG1 ||
- header_.e_ident[EI_MAG2] != ELFMAG2 ||
- header_.e_ident[EI_MAG3] != ELFMAG3) {
+ if (memcmp(header_.e_ident, ELFMAG, SELFMAG) != 0) {
DL_ERR("\"%s\" has bad ELF magic", name_);
return false;
}
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 7c86d76..6d29421 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -53,17 +53,10 @@
TEST(stdlib, rand) {
srand(0x01020304);
-#if defined(__BIONIC__)
- EXPECT_EQ(1675538669, rand());
- EXPECT_EQ(1678228258, rand());
- EXPECT_EQ(1352350131, rand());
- EXPECT_EQ(824068976, rand());
-#else
EXPECT_EQ(55436735, rand());
EXPECT_EQ(1399865117, rand());
EXPECT_EQ(2032643283, rand());
EXPECT_EQ(571329216, rand());
-#endif
}
TEST(stdlib, mrand48) {
diff --git a/tests/sys_time_test.cpp b/tests/sys_time_test.cpp
index 730992f..bb142bc 100644
--- a/tests/sys_time_test.cpp
+++ b/tests/sys_time_test.cpp
@@ -17,6 +17,7 @@
#include <gtest/gtest.h>
#include <errno.h>
+#include <sys/syscall.h>
#include <sys/time.h>
#include "TemporaryFile.h"
@@ -46,3 +47,23 @@
TemporaryFile tf;
ASSERT_EQ(0, utimes(tf.filename, NULL));
}
+
+TEST(sys_time, gettimeofday) {
+ // Try to ensure that our vdso gettimeofday is working.
+ timeval tv1;
+ ASSERT_EQ(0, gettimeofday(&tv1, NULL));
+ timeval tv2;
+ ASSERT_EQ(0, syscall(__NR_gettimeofday, &tv2, NULL));
+
+ // What's the difference between the two?
+ tv2.tv_sec -= tv1.tv_sec;
+ tv2.tv_usec -= tv1.tv_usec;
+ if (tv2.tv_usec < 0) {
+ --tv2.tv_sec;
+ tv2.tv_usec += 1000000;
+ }
+
+ // Should be less than (a very generous, to try to avoid flakiness) 1000us.
+ ASSERT_EQ(0, tv2.tv_sec);
+ ASSERT_LT(tv2.tv_usec, 1000);
+}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 58cb374..12b1ea7 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -21,6 +21,7 @@
#include <gtest/gtest.h>
#include <pthread.h>
#include <signal.h>
+#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -419,3 +420,23 @@
ASSERT_EQ(ESRCH, pthread_detach(tdd.thread_id));
#endif
}
+
+TEST(time, clock_gettime) {
+ // Try to ensure that our vdso clock_gettime is working.
+ timespec ts1;
+ ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts1));
+ timespec ts2;
+ ASSERT_EQ(0, syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts2));
+
+ // What's the difference between the two?
+ ts2.tv_sec -= ts1.tv_sec;
+ ts2.tv_nsec -= ts1.tv_nsec;
+ if (ts2.tv_nsec < 0) {
+ --ts2.tv_sec;
+ ts2.tv_nsec += 1000000000;
+ }
+
+ // Should be less than (a very generous, to try to avoid flakiness) 1000000ns.
+ ASSERT_EQ(0, ts2.tv_sec);
+ ASSERT_LT(ts2.tv_nsec, 1000000);
+}