Merge "Revert "Revert "Hide _tolower_tab_ and _toupper_tab_ on LP64."""
diff --git a/benchmarks/unistd_benchmark.cpp b/benchmarks/unistd_benchmark.cpp
index c35e7c3..7e2ac30 100644
--- a/benchmarks/unistd_benchmark.cpp
+++ b/benchmarks/unistd_benchmark.cpp
@@ -30,6 +30,17 @@
}
BENCHMARK(BM_unistd_getpid);
+static void BM_unistd_getpid_syscall(int iters) {
+ StartBenchmarkTiming();
+
+ for (int i = 0; i < iters; ++i) {
+ syscall(__NR_getpid);
+ }
+
+ StopBenchmarkTiming();
+}
+BENCHMARK(BM_unistd_getpid_syscall);
+
// Stop GCC optimizing out our pure function.
/* Must not be static! */ pid_t (*gettid_fp)() = gettid;
diff --git a/libc/Android.mk b/libc/Android.mk
index 2747a3e..078be59 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -127,6 +127,7 @@
bionic/getauxval.cpp \
bionic/getcwd.cpp \
bionic/getpgrp.cpp \
+ bionic/getpid.cpp \
bionic/gettid.cpp \
bionic/inotify_init.cpp \
bionic/lchown.cpp \
@@ -216,7 +217,7 @@
bionic/system_properties.cpp \
bionic/tdestroy.cpp \
bionic/termios.cpp \
- bionic/thread_atexit.cpp \
+ bionic/thread_private.cpp \
bionic/tmpfile.cpp \
bionic/umount.cpp \
bionic/unlink.cpp \
@@ -233,7 +234,6 @@
upstream-freebsd/lib/libc/stdio/fclose.c \
upstream-freebsd/lib/libc/stdio/flags.c \
upstream-freebsd/lib/libc/stdio/fopen.c \
- upstream-freebsd/lib/libc/stdio/mktemp.c \
upstream-freebsd/lib/libc/stdlib/abs.c \
upstream-freebsd/lib/libc/stdlib/getopt_long.c \
upstream-freebsd/lib/libc/stdlib/imaxabs.c \
@@ -262,7 +262,6 @@
upstream-freebsd/lib/libc/string/wmemset.c \
libc_upstream_netbsd_src_files := \
- upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
upstream-netbsd/common/lib/libc/stdlib/random.c \
upstream-netbsd/lib/libc/gen/ftw.c \
upstream-netbsd/lib/libc/gen/nftw.c \
@@ -271,10 +270,12 @@
upstream-netbsd/lib/libc/gen/psignal.c \
upstream-netbsd/lib/libc/gen/utime.c \
upstream-netbsd/lib/libc/gen/utmp.c \
+ upstream-netbsd/lib/libc/inet/nsap_addr.c \
upstream-netbsd/lib/libc/regex/regcomp.c \
upstream-netbsd/lib/libc/regex/regerror.c \
upstream-netbsd/lib/libc/regex/regexec.c \
upstream-netbsd/lib/libc/regex/regfree.c \
+ upstream-netbsd/lib/libc/resolv/mtctxres.c \
upstream-netbsd/lib/libc/stdlib/bsearch.c \
upstream-netbsd/lib/libc/stdlib/div.c \
upstream-netbsd/lib/libc/stdlib/drand48.c \
@@ -412,6 +413,7 @@
upstream-openbsd/lib/libc/stdio/getwc.c \
upstream-openbsd/lib/libc/stdio/getwchar.c \
upstream-openbsd/lib/libc/stdio/makebuf.c \
+ upstream-openbsd/lib/libc/stdio/mktemp.c \
upstream-openbsd/lib/libc/stdio/perror.c \
upstream-openbsd/lib/libc/stdio/printf.c \
upstream-openbsd/lib/libc/stdio/putc.c \
@@ -494,6 +496,7 @@
-Werror=pointer-to-int-cast \
-Werror=int-to-pointer-cast \
-Werror=type-limits \
+ -Werror \
ifeq ($(strip $(DEBUG_BIONIC_LIBC)),true)
libc_common_cflags += -DDEBUG
@@ -563,7 +566,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := bionic/__stack_chk_fail.cpp
-LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector -Werror
+LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
@@ -585,7 +588,9 @@
# tzcode doesn't include wcsftime, so we use the OpenBSD one.
LOCAL_SRC_FILES += upstream-openbsd/lib/libc/time/wcsftime.c
-LOCAL_CFLAGS := $(libc_common_cflags)
+LOCAL_CFLAGS := $(libc_common_cflags) \
+ -fvisibility=hidden \
+
# Don't use ridiculous amounts of stack.
LOCAL_CFLAGS += -DALL_STATE
# Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
@@ -597,6 +602,7 @@
# Include timezone and daylight globals.
LOCAL_CFLAGS += -DUSG_COMPAT=1
LOCAL_CFLAGS += -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
+LOCAL_CFLAGS += -Dlint
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
@@ -625,12 +631,12 @@
-DANDROID_CHANGES \
-DINET6 \
-fvisibility=hidden \
+ -Wno-unused-parameter \
-I$(LOCAL_PATH)/dns/include \
-I$(LOCAL_PATH)/private \
-I$(LOCAL_PATH)/upstream-netbsd/lib/libc/include \
-I$(LOCAL_PATH)/upstream-netbsd/android/include \
-include netbsd-compat.h \
-# -Werror \
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
@@ -659,7 +665,6 @@
-I$(LOCAL_PATH)/upstream-freebsd/android/include \
-I$(LOCAL_PATH)/upstream-freebsd/lib/libc/include \
-include freebsd-compat.h \
-# -Werror \
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
@@ -685,7 +690,6 @@
LOCAL_CFLAGS := \
$(libc_common_cflags) \
-Wno-sign-compare -Wno-uninitialized \
- -Werror \
-DPOSIX_MISTAKE \
-I$(LOCAL_PATH)/upstream-netbsd/android/include \
-I$(LOCAL_PATH)/upstream-netbsd/lib/libc/include \
@@ -699,6 +703,7 @@
LOCAL_SYSTEM_SHARED_LIBRARIES :=
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
+$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_netbsd_src_files))
include $(BUILD_STATIC_LIBRARY)
@@ -715,7 +720,6 @@
LOCAL_CFLAGS := \
$(libc_common_cflags) \
-Wno-sign-compare -Wno-uninitialized -Wno-unused-parameter \
- -Werror \
-I$(LOCAL_PATH)/upstream-openbsd/android/include \
-I$(LOCAL_PATH)/upstream-openbsd/lib/libc/include \
-I$(LOCAL_PATH)/upstream-openbsd/lib/libc/gdtoa/ \
@@ -746,7 +750,6 @@
LOCAL_CFLAGS := \
$(libc_common_cflags) \
-Wno-sign-compare -Wno-uninitialized \
- -Werror \
-fvisibility=hidden \
-I$(LOCAL_PATH)/upstream-openbsd/android/include \
-I$(LOCAL_PATH)/upstream-openbsd/lib/libc/include \
@@ -771,7 +774,6 @@
LOCAL_SRC_FILES := $(libc_bionic_src_files)
LOCAL_CFLAGS := $(libc_common_cflags) \
- -Werror \
-Wframe-larger-than=2048 \
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
@@ -867,7 +869,6 @@
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_CFLAGS := $(libc_common_cflags) \
-DLIBC_STATIC \
- -Werror \
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
@@ -889,7 +890,6 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(libc_malloc_src)
LOCAL_CFLAGS := $(libc_common_cflags) \
- -Werror \
-fvisibility=hidden \
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
@@ -913,7 +913,6 @@
LOCAL_CFLAGS := $(libc_common_cflags) \
-DLIBC_STATIC \
- -Werror \
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
@@ -933,7 +932,7 @@
# ========================================================
include $(CLEAR_VARS)
-LOCAL_CFLAGS := $(libc_common_cflags) -Werror
+LOCAL_CFLAGS := $(libc_common_cflags)
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
LOCAL_C_INCLUDES := $(libc_common_c_includes)
@@ -966,6 +965,13 @@
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
LOCAL_SYSTEM_SHARED_LIBRARIES :=
+# We'd really like to do this for all architectures, but since this wasn't done
+# before, these symbols must continue to be exported on LP32 for binary
+# compatibility.
+LOCAL_LDFLAGS_arm64 := -Wl,--exclude-libs,libgcc.a
+LOCAL_LDFLAGS_mips64 := -Wl,--exclude-libs,libgcc.a
+LOCAL_LDFLAGS_x86_64 := -Wl,--exclude-libs,libgcc.a
+
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_arch_dynamic_src_files))
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_static_common_src_files))
@@ -996,7 +1002,6 @@
LOCAL_CFLAGS := \
$(libc_common_cflags) \
-DMALLOC_LEAK_CHECK \
- -Werror \
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
@@ -1032,7 +1037,6 @@
LOCAL_CFLAGS := \
$(libc_common_cflags) \
-DMALLOC_QEMU_INSTRUMENT \
- -Werror \
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
LOCAL_CPPFLAGS := $(libc_common_cppflags)
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 369b23c..b4c8134 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -97,7 +97,7 @@
ssize_t pwrite64(int, void*, size_t, off64_t) arm,mips,x86
ssize_t pwrite64|pwrite(int, void*, size_t, off_t) arm64,mips64,x86_64
int close(int) all
-pid_t getpid() all
+pid_t __getpid:getpid() all
int munmap(void*, size_t) all
void* mremap(void*, size_t, size_t, unsigned long) all
int msync(const void*, size_t, int) all
@@ -285,6 +285,10 @@
int sysinfo(struct sysinfo*) all
int personality(unsigned long) all
+ssize_t tee(int, int, size_t, unsigned int) all
+ssize_t splice(int, off64_t*, int, off64_t*, size_t, unsigned int) all
+ssize_t vmsplice(int, const struct iovec*, size_t, unsigned int) all
+
int epoll_create1(int) all
int epoll_ctl(int, int op, int, struct epoll_event*) all
int __epoll_pwait:epoll_pwait(int, struct epoll_event*, int, int, const sigset_t*, size_t) all
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index 38301bc..47e436c 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -65,6 +65,9 @@
libc_arch_static_src_files_arm := arch-arm/bionic/exidx_static.c
libc_arch_dynamic_src_files_arm := arch-arm/bionic/exidx_dynamic.c
+libc_netbsd_src_files_arm := \
+ upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
+
## CPU variant specific source files
ifeq ($(strip $(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT)),)
$(warning TARGET_$(my_2nd_arch_prefix)ARCH is arm, but TARGET_$(my_2nd_arch_prefix)CPU_VARIANT is not defined)
diff --git a/libc/arch-arm/syscalls/getpid.S b/libc/arch-arm/syscalls/__getpid.S
similarity index 89%
rename from libc/arch-arm/syscalls/getpid.S
rename to libc/arch-arm/syscalls/__getpid.S
index 10bcb8e..eedc33a 100644
--- a/libc/arch-arm/syscalls/getpid.S
+++ b/libc/arch-arm/syscalls/__getpid.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(__getpid)
mov ip, r7
ldr r7, =__NR_getpid
swi #0
@@ -11,4 +11,4 @@
bxls lr
neg r0, r0
b __set_errno
-END(getpid)
+END(__getpid)
diff --git a/libc/arch-arm/syscalls/splice.S b/libc/arch-arm/syscalls/splice.S
new file mode 100644
index 0000000..782ba6c
--- /dev/null
+++ b/libc/arch-arm/syscalls/splice.S
@@ -0,0 +1,22 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(splice)
+ mov ip, sp
+ stmfd sp!, {r4, r5, r6, r7}
+ .cfi_def_cfa_offset 16
+ .cfi_rel_offset r4, 0
+ .cfi_rel_offset r5, 4
+ .cfi_rel_offset r6, 8
+ .cfi_rel_offset r7, 12
+ ldmfd ip, {r4, r5, r6}
+ ldr r7, =__NR_splice
+ swi #0
+ ldmfd sp!, {r4, r5, r6, r7}
+ .cfi_def_cfa_offset 0
+ cmn r0, #(MAX_ERRNO + 1)
+ bxls lr
+ neg r0, r0
+ b __set_errno
+END(splice)
diff --git a/libc/arch-arm/syscalls/getpid.S b/libc/arch-arm/syscalls/tee.S
similarity index 80%
copy from libc/arch-arm/syscalls/getpid.S
copy to libc/arch-arm/syscalls/tee.S
index 10bcb8e..9174617 100644
--- a/libc/arch-arm/syscalls/getpid.S
+++ b/libc/arch-arm/syscalls/tee.S
@@ -2,13 +2,13 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(tee)
mov ip, r7
- ldr r7, =__NR_getpid
+ ldr r7, =__NR_tee
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
-END(getpid)
+END(tee)
diff --git a/libc/arch-arm/syscalls/getpid.S b/libc/arch-arm/syscalls/vmsplice.S
similarity index 78%
copy from libc/arch-arm/syscalls/getpid.S
copy to libc/arch-arm/syscalls/vmsplice.S
index 10bcb8e..3b89623 100644
--- a/libc/arch-arm/syscalls/getpid.S
+++ b/libc/arch-arm/syscalls/vmsplice.S
@@ -2,13 +2,13 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(vmsplice)
mov ip, r7
- ldr r7, =__NR_getpid
+ ldr r7, =__NR_vmsplice
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
-END(getpid)
+END(vmsplice)
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 2d34f52..20d9cf1 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -3,7 +3,6 @@
libc_common_src_files_arm64 := \
bionic/memchr.c \
bionic/memrchr.c \
- bionic/strchr.cpp \
bionic/strrchr.cpp \
upstream-freebsd/lib/libc/string/wcscat.c \
upstream-freebsd/lib/libc/string/wcschr.c \
@@ -12,10 +11,8 @@
upstream-freebsd/lib/libc/string/wcslen.c \
upstream-freebsd/lib/libc/string/wcsrchr.c \
upstream-freebsd/lib/libc/string/wmemcmp.c \
- upstream-openbsd/lib/libc/string/stpcpy.c \
upstream-openbsd/lib/libc/string/stpncpy.c \
upstream-openbsd/lib/libc/string/strcat.c \
- upstream-openbsd/lib/libc/string/strcpy.c \
upstream-openbsd/lib/libc/string/strlcat.c \
upstream-openbsd/lib/libc/string/strlcpy.c \
upstream-openbsd/lib/libc/string/strncat.c \
@@ -57,7 +54,7 @@
endif
cpu_variant_mk := $(LOCAL_PATH)/arch-arm64/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk
ifeq ($(wildcard $(cpu_variant_mk)),)
-$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, generic-neon. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
+$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, generic-neon, denver64. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
endif
include $(cpu_variant_mk)
libc_common_additional_dependencies += $(cpu_variank_mk)
diff --git a/libc/arch-arm64/denver64/bionic/memcpy.S b/libc/arch-arm64/denver64/bionic/memcpy.S
new file mode 100644
index 0000000..700f0d0
--- /dev/null
+++ b/libc/arch-arm64/denver64/bionic/memcpy.S
@@ -0,0 +1,205 @@
+/* Copyright (c) 2012, Linaro Limited
+ All rights reserved.
+ Copyright (c) 2014, NVIDIA Corporation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Linaro 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 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
+ HOLDER 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.
+*/
+
+/* Assumptions:
+ *
+ * denver, ARMv8-a, AArch64
+ * Unaligned accesses
+ *
+ */
+
+#include <private/bionic_asm.h>
+
+#define dstin x0
+#define src x1
+#define count x2
+#define tmp1 x3
+#define tmp1w w3
+#define tmp2 x4
+#define tmp2w w4
+#define tmp3 x5
+#define tmp3w w5
+#define dst x6
+
+#define A_l x7
+#define A_h x8
+#define B_l x9
+#define B_h x10
+#define C_l x11
+#define C_h x12
+#define D_l x13
+#define D_h x14
+
+#define QA_l q0
+#define QA_h q1
+#define QB_l q2
+#define QB_h q3
+
+ENTRY(memcpy)
+
+ mov dst, dstin
+ cmp count, #64
+ b.ge .Lcpy_not_short
+ cmp count, #15
+ b.le .Ltail15tiny
+
+ /* Deal with small copies quickly by dropping straight into the
+ * exit block. */
+.Ltail63:
+ /* Copy up to 48 bytes of data. At this point we only need the
+ * bottom 6 bits of count to be accurate. */
+ ands tmp1, count, #0x30
+ b.eq .Ltail15
+ add dst, dst, tmp1
+ add src, src, tmp1
+ cmp tmp1w, #0x20
+ b.eq 1f
+ b.lt 2f
+ ldp A_l, A_h, [src, #-48]
+ stp A_l, A_h, [dst, #-48]
+1:
+ ldp A_l, A_h, [src, #-32]
+ stp A_l, A_h, [dst, #-32]
+2:
+ ldp A_l, A_h, [src, #-16]
+ stp A_l, A_h, [dst, #-16]
+
+.Ltail15:
+ ands count, count, #15
+ beq 1f
+ add src, src, count
+ ldp A_l, A_h, [src, #-16]
+ add dst, dst, count
+ stp A_l, A_h, [dst, #-16]
+1:
+ ret
+
+.Ltail15tiny:
+ /* Copy up to 15 bytes of data. Does not assume additional data
+ being copied. */
+ tbz count, #3, 1f
+ ldr tmp1, [src], #8
+ str tmp1, [dst], #8
+1:
+ tbz count, #2, 1f
+ ldr tmp1w, [src], #4
+ str tmp1w, [dst], #4
+1:
+ tbz count, #1, 1f
+ ldrh tmp1w, [src], #2
+ strh tmp1w, [dst], #2
+1:
+ tbz count, #0, 1f
+ ldrb tmp1w, [src]
+ strb tmp1w, [dst]
+1:
+ ret
+
+.Lcpy_not_short:
+ /* We don't much care about the alignment of DST, but we want SRC
+ * to be 128-bit (16 byte) aligned so that we don't cross cache line
+ * boundaries on both loads and stores. */
+ neg tmp2, src
+ ands tmp2, tmp2, #15 /* Bytes to reach alignment. */
+ b.eq 2f
+ sub count, count, tmp2
+ /* Copy more data than needed; it's faster than jumping
+ * around copying sub-Quadword quantities. We know that
+ * it can't overrun. */
+ ldp A_l, A_h, [src]
+ add src, src, tmp2
+ stp A_l, A_h, [dst]
+ add dst, dst, tmp2
+ /* There may be less than 63 bytes to go now. */
+ cmp count, #63
+ b.le .Ltail63
+2:
+ subs count, count, #128
+ b.ge .Lcpy_body_large
+ /* Less than 128 bytes to copy, so handle 64 here and then jump
+ * to the tail. */
+ ldp QA_l, QA_h, [src]
+ ldp QB_l, QB_h, [src, #32]
+ stp QA_l, QA_h, [dst]
+ stp QB_l, QB_h, [dst, #32]
+ tst count, #0x3f
+ add src, src, #64
+ add dst, dst, #64
+ b.ne .Ltail63
+ ret
+
+ /* Critical loop. Start at a new cache line boundary. Assuming
+ * 64 bytes per line this ensures the entire loop is in one line. */
+ .p2align 6
+.Lcpy_body_large:
+ cmp count, 65536
+ bhi .Lcpy_body_huge
+ /* There are at least 128 bytes to copy. */
+ ldp QA_l, QA_h, [src, #0]
+ sub dst, dst, #32 /* Pre-bias. */
+ ldp QB_l, QB_h, [src, #32]! /* src += 64 - Pre-bias. */
+1:
+ stp QA_l, QA_h, [dst, #32]
+ ldp QA_l, QA_h, [src, #32]
+ stp QB_l, QB_h, [dst, #64]!
+ ldp QB_l, QB_h, [src, #64]!
+
+ subs count, count, #64
+ b.ge 1b
+
+ stp QA_l, QA_h, [dst, #32]
+ stp QB_l, QB_h, [dst, #64]
+ add src, src, #32
+ add dst, dst, #64 + 32
+ tst count, #0x3f
+ b.ne .Ltail63
+ ret
+.Lcpy_body_huge:
+ /* There are at least 128 bytes to copy. */
+ ldp QA_l, QA_h, [src, #0]
+ sub dst, dst, #32 /* Pre-bias. */
+ ldp QB_l, QB_h, [src, #32]!
+1:
+ stnp QA_l, QA_h, [dst, #32]
+ stnp QB_l, QB_h, [dst, #64]
+ ldp QA_l, QA_h, [src, #32]
+ ldp QB_l, QB_h, [src, #64]!
+ add dst, dst, #64
+
+ subs count, count, #64
+ b.ge 1b
+
+ stnp QA_l, QA_h, [dst, #32]
+ stnp QB_l, QB_h, [dst, #64]
+ add src, src, #32
+ add dst, dst, #64 + 32
+ tst count, #0x3f
+ b.ne .Ltail63
+ ret
+
+END(memcpy)
diff --git a/libc/arch-arm64/denver64/bionic/memset.S b/libc/arch-arm64/denver64/bionic/memset.S
new file mode 100644
index 0000000..9127d89
--- /dev/null
+++ b/libc/arch-arm64/denver64/bionic/memset.S
@@ -0,0 +1,271 @@
+/* Copyright (c) 2012, Linaro Limited
+ All rights reserved.
+ Copyright (c) 2014, NVIDIA Corporation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Linaro 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 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
+ HOLDER 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.
+*/
+
+/* Assumptions:
+ *
+ * denver, ARMv8-a, AArch64
+ * Unaligned accesses
+ *
+ */
+
+#include <private/bionic_asm.h>
+
+/* By default we assume that the DC instruction can be used to zero
+ data blocks more efficiently. In some circumstances this might be
+ unsafe, for example in an asymmetric multiprocessor environment with
+ different DC clear lengths (neither the upper nor lower lengths are
+ safe to use). The feature can be disabled by defining DONT_USE_DC.
+
+ If code may be run in a virtualized environment, then define
+ MAYBE_VIRT. This will cause the code to cache the system register
+ values rather than re-reading them each call. */
+
+#define dstin x0
+#define val w1
+#define count x2
+#define tmp1 x3
+#define tmp1w w3
+#define tmp2 x4
+#define tmp2w w4
+#define zva_len_x x5
+#define zva_len w5
+#define zva_bits_x x6
+
+#define A_l x7
+#define A_lw w7
+#define dst x8
+#define tmp3w w9
+
+#define QA_l q0
+
+ENTRY(memset)
+
+ mov dst, dstin /* Preserve return value. */
+ ands A_lw, val, #255
+#ifndef DONT_USE_DC
+# b.eq .Lzero_mem
+#endif
+ orr A_lw, A_lw, A_lw, lsl #8
+ orr A_lw, A_lw, A_lw, lsl #16
+ orr A_l, A_l, A_l, lsl #32
+.Ltail_maybe_long:
+ cmp count, #256
+ b.ge .Lnot_short
+.Ltail_maybe_tiny:
+ cmp count, #15
+ b.le .Ltail15tiny
+.Ltail255:
+ ands tmp1, count, #0xC0
+ b.eq .Ltail63
+ dup v0.4s, A_lw
+ cmp tmp1w, #0x80
+ b.eq 1f
+ b.lt 2f
+ stp QA_l, QA_l, [dst], #32
+ stp QA_l, QA_l, [dst], #32
+1:
+ stp QA_l, QA_l, [dst], #32
+ stp QA_l, QA_l, [dst], #32
+2:
+ stp QA_l, QA_l, [dst], #32
+ stp QA_l, QA_l, [dst], #32
+.Ltail63:
+ ands tmp1, count, #0x30
+ b.eq .Ltail15
+ add dst, dst, tmp1
+ cmp tmp1w, #0x20
+ b.eq 1f
+ b.lt 2f
+ stp A_l, A_l, [dst, #-48]
+1:
+ stp A_l, A_l, [dst, #-32]
+2:
+ stp A_l, A_l, [dst, #-16]
+
+.Ltail15:
+ and count, count, #15
+ add dst, dst, count
+ stp A_l, A_l, [dst, #-16] /* Repeat some/all of last store. */
+ ret
+
+.Ltail15tiny:
+ /* Set up to 15 bytes. Does not assume earlier memory
+ being set. */
+ tbz count, #3, 1f
+ str A_l, [dst], #8
+1:
+ tbz count, #2, 1f
+ str A_lw, [dst], #4
+1:
+ tbz count, #1, 1f
+ strh A_lw, [dst], #2
+1:
+ tbz count, #0, 1f
+ strb A_lw, [dst]
+1:
+ ret
+
+ /* Critical loop. Start at a new cache line boundary. Assuming
+ * 64 bytes per line, this ensures the entire loop is in one line. */
+ .p2align 6
+.Lnot_short:
+ dup v0.4s, A_lw
+ neg tmp2, dst
+ ands tmp2, tmp2, #15
+ b.eq 2f
+ /* Bring DST to 128-bit (16-byte) alignment. We know that there's
+ * more than that to set, so we simply store 16 bytes and advance by
+ * the amount required to reach alignment. */
+ sub count, count, tmp2
+ stp A_l, A_l, [dst]
+ add dst, dst, tmp2
+ /* There may be less than 63 bytes to go now. */
+ cmp count, #255
+ b.le .Ltail255
+2:
+ cmp count, #2097152
+ b.gt 3f
+1:
+ sub count, count, #256
+2:
+ stp QA_l, QA_l, [dst], #32
+ stp QA_l, QA_l, [dst], #32
+ stp QA_l, QA_l, [dst], #32
+ stp QA_l, QA_l, [dst], #32
+ stp QA_l, QA_l, [dst], #32
+ stp QA_l, QA_l, [dst], #32
+ stp QA_l, QA_l, [dst], #32
+ stp QA_l, QA_l, [dst], #32
+ subs count, count, #256
+ b.ge 2b
+ tst count, #0xff
+ b.ne .Ltail255
+ ret
+3:
+ sub count, count, #64
+4:
+ subs count, count, #64
+ stnp QA_l, QA_l, [dst]
+ stnp QA_l, QA_l, [dst, #32]
+ add dst, dst, #64
+ b.ge 4b
+ tst count, #0x3f
+ b.ne .Ltail63
+ ret
+
+#ifndef DONT_USE_DC
+ /* For zeroing memory, check to see if we can use the ZVA feature to
+ * zero entire 'cache' lines. */
+.Lzero_mem:
+ mov A_l, #0
+ cmp count, #63
+ b.le .Ltail_maybe_tiny
+ neg tmp2, dst
+ ands tmp2, tmp2, #15
+ b.eq 1f
+ sub count, count, tmp2
+ stp A_l, A_l, [dst]
+ add dst, dst, tmp2
+ cmp count, #63
+ b.le .Ltail63
+1:
+ /* For zeroing small amounts of memory, it's not worth setting up
+ * the line-clear code. */
+ cmp count, #128
+ b.lt .Lnot_short
+#ifdef MAYBE_VIRT
+ /* For efficiency when virtualized, we cache the ZVA capability. */
+ adrp tmp2, .Lcache_clear
+ ldr zva_len, [tmp2, #:lo12:.Lcache_clear]
+ tbnz zva_len, #31, .Lnot_short
+ cbnz zva_len, .Lzero_by_line
+ mrs tmp1, dczid_el0
+ tbz tmp1, #4, 1f
+ /* ZVA not available. Remember this for next time. */
+ mov zva_len, #~0
+ str zva_len, [tmp2, #:lo12:.Lcache_clear]
+ b .Lnot_short
+1:
+ mov tmp3w, #4
+ and zva_len, tmp1w, #15 /* Safety: other bits reserved. */
+ lsl zva_len, tmp3w, zva_len
+ str zva_len, [tmp2, #:lo12:.Lcache_clear]
+#else
+ mrs tmp1, dczid_el0
+ tbnz tmp1, #4, .Lnot_short
+ mov tmp3w, #4
+ and zva_len, tmp1w, #15 /* Safety: other bits reserved. */
+ lsl zva_len, tmp3w, zva_len
+#endif
+
+.Lzero_by_line:
+ /* Compute how far we need to go to become suitably aligned. We're
+ * already at quad-word alignment. */
+ cmp count, zva_len_x
+ b.lt .Lnot_short /* Not enough to reach alignment. */
+ sub zva_bits_x, zva_len_x, #1
+ neg tmp2, dst
+ ands tmp2, tmp2, zva_bits_x
+ b.eq 1f /* Already aligned. */
+ /* Not aligned, check that there's enough to copy after alignment. */
+ sub tmp1, count, tmp2
+ cmp tmp1, #64
+ ccmp tmp1, zva_len_x, #8, ge /* NZCV=0b1000 */
+ b.lt .Lnot_short
+ /* We know that there's at least 64 bytes to zero and that it's safe
+ * to overrun by 64 bytes. */
+ mov count, tmp1
+2:
+ stp A_l, A_l, [dst]
+ stp A_l, A_l, [dst, #16]
+ stp A_l, A_l, [dst, #32]
+ subs tmp2, tmp2, #64
+ stp A_l, A_l, [dst, #48]
+ add dst, dst, #64
+ b.ge 2b
+ /* We've overrun a bit, so adjust dst downwards. */
+ add dst, dst, tmp2
+1:
+ sub count, count, zva_len_x
+3:
+ dc zva, dst
+ add dst, dst, zva_len_x
+ subs count, count, zva_len_x
+ b.ge 3b
+ ands count, count, zva_bits_x
+ b.ne .Ltail_maybe_long
+ ret
+END(memset)
+
+#ifdef MAYBE_VIRT
+ .bss
+ .p2align 2
+.Lcache_clear:
+ .space 4
+#endif
+#endif /* DONT_USE_DC */
diff --git a/libc/arch-arm64/denver64/denver64.mk b/libc/arch-arm64/denver64/denver64.mk
new file mode 100644
index 0000000..c6ddb3f
--- /dev/null
+++ b/libc/arch-arm64/denver64/denver64.mk
@@ -0,0 +1,13 @@
+libc_bionic_src_files_arm64 += \
+ arch-arm64/generic/bionic/memcmp.S \
+ arch-arm64/denver64/bionic/memcpy.S \
+ arch-arm64/generic/bionic/memmove.S \
+ arch-arm64/denver64/bionic/memset.S \
+ arch-arm64/generic/bionic/stpcpy.S \
+ arch-arm64/generic/bionic/strchr.S \
+ arch-arm64/generic/bionic/strcmp.S \
+ arch-arm64/generic/bionic/strcpy.S \
+ arch-arm64/generic/bionic/strlen.S \
+ arch-arm64/generic/bionic/strncmp.S \
+ arch-arm64/generic/bionic/strnlen.S \
+ arch-arm64/generic/bionic/wmemmove.S
diff --git a/libc/arch-arm64/generic-neon/generic-neon.mk b/libc/arch-arm64/generic-neon/generic-neon.mk
index 2cbe3cf..f3bde5c 100644
--- a/libc/arch-arm64/generic-neon/generic-neon.mk
+++ b/libc/arch-arm64/generic-neon/generic-neon.mk
@@ -2,7 +2,10 @@
arch-arm64/generic/bionic/memcmp.S \
arch-arm64/generic/bionic/memmove.S \
arch-arm64/generic/bionic/memset.S \
+ arch-arm64/generic/bionic/stpcpy.S \
+ arch-arm64/generic/bionic/strchr.S \
arch-arm64/generic/bionic/strcmp.S \
+ arch-arm64/generic/bionic/strcpy.S \
arch-arm64/generic/bionic/strlen.S \
arch-arm64/generic/bionic/strncmp.S \
arch-arm64/generic/bionic/strnlen.S \
diff --git a/libc/bionic/thread_atexit.cpp b/libc/arch-arm64/generic/bionic/stpcpy.S
similarity index 73%
copy from libc/bionic/thread_atexit.cpp
copy to libc/arch-arm64/generic/bionic/stpcpy.S
index 68c119d..e4a7993 100644
--- a/libc/bionic/thread_atexit.cpp
+++ b/libc/arch-arm64/generic/bionic/stpcpy.S
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,22 +25,5 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-
-/* some simple glue used to make the BSD atexit code happy */
-
-#include <pthread.h>
-
-static pthread_mutex_t g_atexit_lock = PTHREAD_MUTEX_INITIALIZER;
-
-__BEGIN_DECLS
-__LIBC_HIDDEN__ void _thread_atexit_lock();
-__LIBC_HIDDEN__ void _thread_atexit_unlock();
-__END_DECLS
-
-void _thread_atexit_lock() {
- pthread_mutex_lock(&g_atexit_lock);
-}
-
-void _thread_atexit_unlock() {
- pthread_mutex_unlock(&g_atexit_lock);
-}
+#define STPCPY
+#include "string_copy.S"
diff --git a/libc/arch-arm64/generic/bionic/strchr.S b/libc/arch-arm64/generic/bionic/strchr.S
new file mode 100644
index 0000000..158eaf7
--- /dev/null
+++ b/libc/arch-arm64/generic/bionic/strchr.S
@@ -0,0 +1,153 @@
+/*
+ strchr - find a character in a string
+
+ Copyright (c) 2014, ARM Limited
+ All rights Reserved.
+ Copyright (c) 2014, Linaro Ltd.
+
+ 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.
+ * Neither the name of the company 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 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
+ HOLDER 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. */
+
+/* Assumptions:
+ *
+ * ARMv8-a, AArch64
+ * Neon Available.
+ */
+
+#include <private/bionic_asm.h>
+
+/* Arguments and results. */
+#define srcin x0
+#define chrin w1
+
+#define result x0
+
+#define src x2
+#define tmp1 x3
+#define wtmp2 w4
+#define tmp3 x5
+
+#define vrepchr v0
+#define vdata1 v1
+#define vdata2 v2
+#define vhas_nul1 v3
+#define vhas_nul2 v4
+#define vhas_chr1 v5
+#define vhas_chr2 v6
+#define vrepmask_0 v7
+#define vrepmask_c v16
+#define vend1 v17
+#define vend2 v18
+
+/* Core algorithm.
+
+ For each 32-byte hunk we calculate a 64-bit syndrome value, with
+ two bits per byte (LSB is always in bits 0 and 1, for both big
+ and little-endian systems). For each tuple, bit 0 is set iff
+ the relevant byte matched the requested character; bit 1 is set
+ iff the relevant byte matched the NUL end of string (we trigger
+ off bit0 for the special case of looking for NUL). Since the bits
+ in the syndrome reflect exactly the order in which things occur
+ in the original string a count_trailing_zeros() operation will
+ identify exactly which byte is causing the termination, and why. */
+
+/* Locals and temporaries. */
+
+ENTRY(strchr)
+ /* Magic constant 0x40100401 to allow us to identify which lane
+ matches the requested byte. Magic constant 0x80200802 used
+ similarly for NUL termination. */
+ mov wtmp2, #0x0401
+ movk wtmp2, #0x4010, lsl #16
+ dup vrepchr.16b, chrin
+ bic src, srcin, #31 /* Work with aligned 32-byte hunks. */
+ dup vrepmask_c.4s, wtmp2
+ ands tmp1, srcin, #31
+ add vrepmask_0.4s, vrepmask_c.4s, vrepmask_c.4s /* equiv: lsl #1 */
+ b.eq .Lloop
+
+ /* Input string is not 32-byte aligned. Rather than forcing
+ the padding bytes to a safe value, we calculate the syndrome
+ for all the bytes, but then mask off those bits of the
+ syndrome that are related to the padding. */
+ ld1 {vdata1.16b, vdata2.16b}, [src], #32
+ neg tmp1, tmp1
+ cmeq vhas_nul1.16b, vdata1.16b, #0
+ cmeq vhas_chr1.16b, vdata1.16b, vrepchr.16b
+ cmeq vhas_nul2.16b, vdata2.16b, #0
+ cmeq vhas_chr2.16b, vdata2.16b, vrepchr.16b
+ and vhas_nul1.16b, vhas_nul1.16b, vrepmask_0.16b
+ and vhas_nul2.16b, vhas_nul2.16b, vrepmask_0.16b
+ and vhas_chr1.16b, vhas_chr1.16b, vrepmask_c.16b
+ and vhas_chr2.16b, vhas_chr2.16b, vrepmask_c.16b
+ orr vend1.16b, vhas_nul1.16b, vhas_chr1.16b
+ orr vend2.16b, vhas_nul2.16b, vhas_chr2.16b
+ lsl tmp1, tmp1, #1
+ addp vend1.16b, vend1.16b, vend2.16b // 256->128
+ mov tmp3, #~0
+ addp vend1.16b, vend1.16b, vend2.16b // 128->64
+ lsr tmp1, tmp3, tmp1
+
+ mov tmp3, vend1.2d[0]
+ bic tmp1, tmp3, tmp1 // Mask padding bits.
+ cbnz tmp1, .Ltail
+
+.Lloop:
+ ld1 {vdata1.16b, vdata2.16b}, [src], #32
+ cmeq vhas_nul1.16b, vdata1.16b, #0
+ cmeq vhas_chr1.16b, vdata1.16b, vrepchr.16b
+ cmeq vhas_nul2.16b, vdata2.16b, #0
+ cmeq vhas_chr2.16b, vdata2.16b, vrepchr.16b
+ /* Use a fast check for the termination condition. */
+ orr vend1.16b, vhas_nul1.16b, vhas_chr1.16b
+ orr vend2.16b, vhas_nul2.16b, vhas_chr2.16b
+ orr vend1.16b, vend1.16b, vend2.16b
+ addp vend1.2d, vend1.2d, vend1.2d
+ mov tmp1, vend1.2d[0]
+ cbz tmp1, .Lloop
+
+ /* Termination condition found. Now need to establish exactly why
+ we terminated. */
+ and vhas_nul1.16b, vhas_nul1.16b, vrepmask_0.16b
+ and vhas_nul2.16b, vhas_nul2.16b, vrepmask_0.16b
+ and vhas_chr1.16b, vhas_chr1.16b, vrepmask_c.16b
+ and vhas_chr2.16b, vhas_chr2.16b, vrepmask_c.16b
+ orr vend1.16b, vhas_nul1.16b, vhas_chr1.16b
+ orr vend2.16b, vhas_nul2.16b, vhas_chr2.16b
+ addp vend1.16b, vend1.16b, vend2.16b // 256->128
+ addp vend1.16b, vend1.16b, vend2.16b // 128->64
+
+ mov tmp1, vend1.2d[0]
+.Ltail:
+ /* Count the trailing zeros, by bit reversing... */
+ rbit tmp1, tmp1
+ /* Re-bias source. */
+ sub src, src, #32
+ clz tmp1, tmp1 /* And counting the leading zeros. */
+ /* Tmp1 is even if the target charager was found first. Otherwise
+ we've found the end of string and we weren't looking for NUL. */
+ tst tmp1, #1
+ add result, src, tmp1, lsr #1
+ csel result, result, xzr, eq
+ ret
+END(strchr)
diff --git a/libc/bionic/thread_atexit.cpp b/libc/arch-arm64/generic/bionic/strcpy.S
similarity index 73%
copy from libc/bionic/thread_atexit.cpp
copy to libc/arch-arm64/generic/bionic/strcpy.S
index 68c119d..260c321 100644
--- a/libc/bionic/thread_atexit.cpp
+++ b/libc/arch-arm64/generic/bionic/strcpy.S
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,22 +25,5 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-
-/* some simple glue used to make the BSD atexit code happy */
-
-#include <pthread.h>
-
-static pthread_mutex_t g_atexit_lock = PTHREAD_MUTEX_INITIALIZER;
-
-__BEGIN_DECLS
-__LIBC_HIDDEN__ void _thread_atexit_lock();
-__LIBC_HIDDEN__ void _thread_atexit_unlock();
-__END_DECLS
-
-void _thread_atexit_lock() {
- pthread_mutex_lock(&g_atexit_lock);
-}
-
-void _thread_atexit_unlock() {
- pthread_mutex_unlock(&g_atexit_lock);
-}
+#define STRCPY
+#include "string_copy.S"
diff --git a/libc/arch-arm64/generic/bionic/string_copy.S b/libc/arch-arm64/generic/bionic/string_copy.S
new file mode 100644
index 0000000..3d753b6
--- /dev/null
+++ b/libc/arch-arm64/generic/bionic/string_copy.S
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* Copyright (c) 2014, Linaro Limited
+ 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.
+ * Neither the name of the Linaro 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 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
+ HOLDER 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.
+*/
+
+/* Assumptions:
+ *
+ * ARMv8-a, AArch64
+ */
+
+#if !defined(STPCPY) && !defined(STRCPY)
+#error "Either STPCPY or STRCPY must be defined."
+#endif
+
+#include <private/bionic_asm.h>
+
+/* Arguments and results. */
+#if defined(STPCPY)
+#define dst x0
+#elif defined(STRCPY)
+#define dstin x0
+#endif
+#define src x1
+
+/* Locals and temporaries. */
+#if defined(STRCPY)
+#define dst x2
+#endif
+#define data1 x3
+#define data1_w w3
+#define data2 x4
+#define data2_w w4
+#define has_nul1 x5
+#define has_nul1_w w5
+#define has_nul2 x6
+#define tmp1 x7
+#define tmp2 x8
+#define tmp3 x9
+#define tmp4 x10
+#define zeroones x11
+#define zeroones_w w11
+#define pos x12
+
+#define REP8_01 0x0101010101010101
+#define REP8_7f 0x7f7f7f7f7f7f7f7f
+#define REP8_80 0x8080808080808080
+
+#if defined(STPCPY)
+ENTRY(stpcpy)
+#elif defined(STRCPY)
+ENTRY(strcpy)
+#endif
+ mov zeroones, #REP8_01
+#if defined(STRCPY)
+ mov dst, dstin
+#endif
+ ands tmp1, src, #15
+ b.ne .Lmisaligned
+ // NUL detection works on the principle that (X - 1) & (~X) & 0x80
+ // (=> (X - 1) & ~(X | 0x7f)) is non-zero iff a byte is zero, and
+ // can be done in parallel across the entire word.
+ // The inner loop deals with two Dwords at a time. This has a
+ // slightly higher start-up cost, but we should win quite quickly,
+ // especially on cores with a high number of issue slots per
+ // cycle, as we get much better parallelism out of the operations.
+.Lloop:
+ ldp data1, data2, [src], #16
+ sub tmp1, data1, zeroones
+ orr tmp2, data1, #REP8_7f
+ bic has_nul1, tmp1, tmp2
+ cbnz has_nul1, .Lnul_in_data1
+ sub tmp3, data2, zeroones
+ orr tmp4, data2, #REP8_7f
+ bic has_nul2, tmp3, tmp4
+ cbnz has_nul2, .Lnul_in_data2
+ // No NUL in either register, copy it in a single instruction.
+ stp data1, data2, [dst], #16
+ b .Lloop
+
+.Lnul_in_data1:
+ rev has_nul1, has_nul1
+ clz pos, has_nul1
+ add tmp1, pos, #0x8
+
+ tbz tmp1, #6, 1f
+#if defined(STPCPY)
+ str data1, [dst], #7
+#elif defined(STRCPY)
+ str data1, [dst]
+#endif
+ ret
+1:
+ tbz tmp1, #5, 1f
+ str data1_w, [dst], #4
+ lsr data1, data1, #32
+1:
+ tbz tmp1, #4, 1f
+ strh data1_w, [dst], #2
+ lsr data1, data1, #16
+1:
+ tbz tmp1, #3, 1f
+ strb data1_w, [dst]
+#if defined(STPCPY)
+ ret
+#endif
+1:
+#if defined(STPCPY)
+ // Back up one so that dst points to the '\0' string terminator.
+ sub dst, dst, #1
+#endif
+ ret
+
+.Lnul_in_data2:
+ str data1, [dst], #8
+ rev has_nul2, has_nul2
+ clz pos, has_nul2
+ add tmp1, pos, #0x8
+
+ tbz tmp1, #6, 1f
+#if defined(STPCPY)
+ str data2, [dst], #7
+#elif defined(STRCPY)
+ str data2, [dst]
+#endif
+ ret
+1:
+ tbz tmp1, #5, 1f
+ str data2_w, [dst], #4
+ lsr data2, data2, #32
+1:
+ tbz tmp1, #4, 1f
+ strh data2_w, [dst], #2
+ lsr data2, data2, #16
+1:
+ tbz tmp1, #3, 1f
+ strb data2_w, [dst]
+#if defined(STPCPY)
+ ret
+#endif
+1:
+#if defined(STPCPY)
+ // Back up one so that dst points to the '\0' string terminator.
+ sub dst, dst, #1
+#endif
+ ret
+
+.Lmisaligned:
+ tbz src, #0, 1f
+ ldrb data1_w, [src], #1
+ strb data1_w, [dst], #1
+ cbnz data1_w, 1f
+#if defined(STPCPY)
+ // Back up one so that dst points to the '\0' string terminator.
+ sub dst, dst, #1
+#endif
+ ret
+1:
+ tbz src, #1, 1f
+ ldrb data1_w, [src], #1
+ strb data1_w, [dst], #1
+ cbz data1_w, .Ldone
+ ldrb data2_w, [src], #1
+ strb data2_w, [dst], #1
+ cbnz data2_w, 1f
+.Ldone:
+#if defined(STPCPY)
+ // Back up one so that dst points to the '\0' string terminator.
+ sub dst, dst, #1
+#endif
+ ret
+1:
+ tbz src, #2, 1f
+ ldr data1_w, [src], #4
+ // Check for a zero.
+ sub has_nul1_w, data1_w, zeroones_w
+ bic has_nul1_w, has_nul1_w, data1_w
+ ands has_nul1_w, has_nul1_w, #0x80808080
+ b.ne .Lnul_in_data1
+ str data1_w, [dst], #4
+1:
+ tbz src, #3, .Lloop
+ ldr data1, [src], #8
+ // Check for a zero.
+ sub tmp1, data1, zeroones
+ orr tmp2, data1, #REP8_7f
+ bics has_nul1, tmp1, tmp2
+ b.ne .Lnul_in_data1
+ str data1, [dst], #8
+ b .Lloop
+#if defined(STPCPY)
+END(stpcpy)
+#elif defined(STRCPY)
+END(strcpy)
+#endif
diff --git a/libc/arch-arm64/generic/generic.mk b/libc/arch-arm64/generic/generic.mk
index e10cf66..878dcdf 100644
--- a/libc/arch-arm64/generic/generic.mk
+++ b/libc/arch-arm64/generic/generic.mk
@@ -3,7 +3,10 @@
arch-arm64/generic/bionic/memcpy.S \
arch-arm64/generic/bionic/memmove.S \
arch-arm64/generic/bionic/memset.S \
+ arch-arm64/generic/bionic/stpcpy.S \
+ arch-arm64/generic/bionic/strchr.S \
arch-arm64/generic/bionic/strcmp.S \
+ arch-arm64/generic/bionic/strcpy.S \
arch-arm64/generic/bionic/strlen.S \
arch-arm64/generic/bionic/strncmp.S \
arch-arm64/generic/bionic/strnlen.S \
diff --git a/libc/arch-arm64/syscalls/getpid.S b/libc/arch-arm64/syscalls/__getpid.S
similarity index 82%
rename from libc/arch-arm64/syscalls/getpid.S
rename to libc/arch-arm64/syscalls/__getpid.S
index 1802ce8..c3003c3 100644
--- a/libc/arch-arm64/syscalls/getpid.S
+++ b/libc/arch-arm64/syscalls/__getpid.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(__getpid)
mov x8, __NR_getpid
svc #0
@@ -11,4 +11,5 @@
b.hi __set_errno
ret
-END(getpid)
+END(__getpid)
+.hidden __getpid
diff --git a/libc/arch-arm64/syscalls/getpid.S b/libc/arch-arm64/syscalls/splice.S
similarity index 77%
copy from libc/arch-arm64/syscalls/getpid.S
copy to libc/arch-arm64/syscalls/splice.S
index 1802ce8..103805a 100644
--- a/libc/arch-arm64/syscalls/getpid.S
+++ b/libc/arch-arm64/syscalls/splice.S
@@ -2,8 +2,8 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
- mov x8, __NR_getpid
+ENTRY(splice)
+ mov x8, __NR_splice
svc #0
cmn x0, #(MAX_ERRNO + 1)
@@ -11,4 +11,4 @@
b.hi __set_errno
ret
-END(getpid)
+END(splice)
diff --git a/libc/arch-arm64/syscalls/getpid.S b/libc/arch-arm64/syscalls/tee.S
similarity index 77%
copy from libc/arch-arm64/syscalls/getpid.S
copy to libc/arch-arm64/syscalls/tee.S
index 1802ce8..d730076 100644
--- a/libc/arch-arm64/syscalls/getpid.S
+++ b/libc/arch-arm64/syscalls/tee.S
@@ -2,8 +2,8 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
- mov x8, __NR_getpid
+ENTRY(tee)
+ mov x8, __NR_tee
svc #0
cmn x0, #(MAX_ERRNO + 1)
@@ -11,4 +11,4 @@
b.hi __set_errno
ret
-END(getpid)
+END(tee)
diff --git a/libc/arch-arm64/syscalls/getpid.S b/libc/arch-arm64/syscalls/vmsplice.S
similarity index 75%
copy from libc/arch-arm64/syscalls/getpid.S
copy to libc/arch-arm64/syscalls/vmsplice.S
index 1802ce8..b4bec3f 100644
--- a/libc/arch-arm64/syscalls/getpid.S
+++ b/libc/arch-arm64/syscalls/vmsplice.S
@@ -2,8 +2,8 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
- mov x8, __NR_getpid
+ENTRY(vmsplice)
+ mov x8, __NR_vmsplice
svc #0
cmn x0, #(MAX_ERRNO + 1)
@@ -11,4 +11,4 @@
b.hi __set_errno
ret
-END(getpid)
+END(vmsplice)
diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk
index fe5e24d..0a3718b 100644
--- a/libc/arch-mips/mips.mk
+++ b/libc/arch-mips/mips.mk
@@ -68,6 +68,8 @@
arch-mips/string/memset.S \
arch-mips/string/mips_strlen.c \
+libc_netbsd_src_files_mips := \
+ upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
libc_crt_target_cflags_mips := \
$($(my_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) \
diff --git a/libc/arch-mips/syscalls/getpid.S b/libc/arch-mips/syscalls/__getpid.S
similarity index 89%
rename from libc/arch-mips/syscalls/getpid.S
rename to libc/arch-mips/syscalls/__getpid.S
index a053f5b..52cf6f4 100644
--- a/libc/arch-mips/syscalls/getpid.S
+++ b/libc/arch-mips/syscalls/__getpid.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(__getpid)
.set noreorder
.cpload t9
li v0, __NR_getpid
@@ -16,4 +16,4 @@
j t9
nop
.set reorder
-END(getpid)
+END(__getpid)
diff --git a/libc/arch-mips/syscalls/getpid.S b/libc/arch-mips/syscalls/splice.S
similarity index 82%
copy from libc/arch-mips/syscalls/getpid.S
copy to libc/arch-mips/syscalls/splice.S
index a053f5b..d344a6c 100644
--- a/libc/arch-mips/syscalls/getpid.S
+++ b/libc/arch-mips/syscalls/splice.S
@@ -2,10 +2,10 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(splice)
.set noreorder
.cpload t9
- li v0, __NR_getpid
+ li v0, __NR_splice
syscall
bnez a3, 1f
move a0, v0
@@ -16,4 +16,4 @@
j t9
nop
.set reorder
-END(getpid)
+END(splice)
diff --git a/libc/arch-mips/syscalls/getpid.S b/libc/arch-mips/syscalls/tee.S
similarity index 82%
copy from libc/arch-mips/syscalls/getpid.S
copy to libc/arch-mips/syscalls/tee.S
index a053f5b..e51732d 100644
--- a/libc/arch-mips/syscalls/getpid.S
+++ b/libc/arch-mips/syscalls/tee.S
@@ -2,10 +2,10 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(tee)
.set noreorder
.cpload t9
- li v0, __NR_getpid
+ li v0, __NR_tee
syscall
bnez a3, 1f
move a0, v0
@@ -16,4 +16,4 @@
j t9
nop
.set reorder
-END(getpid)
+END(tee)
diff --git a/libc/arch-mips/syscalls/getpid.S b/libc/arch-mips/syscalls/vmsplice.S
similarity index 80%
copy from libc/arch-mips/syscalls/getpid.S
copy to libc/arch-mips/syscalls/vmsplice.S
index a053f5b..24da515 100644
--- a/libc/arch-mips/syscalls/getpid.S
+++ b/libc/arch-mips/syscalls/vmsplice.S
@@ -2,10 +2,10 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(vmsplice)
.set noreorder
.cpload t9
- li v0, __NR_getpid
+ li v0, __NR_vmsplice
syscall
bnez a3, 1f
move a0, v0
@@ -16,4 +16,4 @@
j t9
nop
.set reorder
-END(getpid)
+END(vmsplice)
diff --git a/libc/arch-mips64/syscalls/getpid.S b/libc/arch-mips64/syscalls/__getpid.S
similarity index 87%
rename from libc/arch-mips64/syscalls/getpid.S
rename to libc/arch-mips64/syscalls/__getpid.S
index 3b457b5..0977ff0 100644
--- a/libc/arch-mips64/syscalls/getpid.S
+++ b/libc/arch-mips64/syscalls/__getpid.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(__getpid)
.set push
.set noreorder
li v0, __NR_getpid
@@ -22,4 +22,5 @@
j t9
move ra, t0
.set pop
-END(getpid)
+END(__getpid)
+.hidden __getpid
diff --git a/libc/arch-mips64/syscalls/getpid.S b/libc/arch-mips64/syscalls/splice.S
similarity index 86%
copy from libc/arch-mips64/syscalls/getpid.S
copy to libc/arch-mips64/syscalls/splice.S
index 3b457b5..d626904 100644
--- a/libc/arch-mips64/syscalls/getpid.S
+++ b/libc/arch-mips64/syscalls/splice.S
@@ -2,10 +2,10 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(splice)
.set push
.set noreorder
- li v0, __NR_getpid
+ li v0, __NR_splice
syscall
bnez a3, 1f
move a0, v0
@@ -22,4 +22,4 @@
j t9
move ra, t0
.set pop
-END(getpid)
+END(splice)
diff --git a/libc/arch-mips64/syscalls/getpid.S b/libc/arch-mips64/syscalls/tee.S
similarity index 86%
copy from libc/arch-mips64/syscalls/getpid.S
copy to libc/arch-mips64/syscalls/tee.S
index 3b457b5..429700c 100644
--- a/libc/arch-mips64/syscalls/getpid.S
+++ b/libc/arch-mips64/syscalls/tee.S
@@ -2,10 +2,10 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(tee)
.set push
.set noreorder
- li v0, __NR_getpid
+ li v0, __NR_tee
syscall
bnez a3, 1f
move a0, v0
@@ -22,4 +22,4 @@
j t9
move ra, t0
.set pop
-END(getpid)
+END(tee)
diff --git a/libc/arch-mips64/syscalls/getpid.S b/libc/arch-mips64/syscalls/vmsplice.S
similarity index 85%
copy from libc/arch-mips64/syscalls/getpid.S
copy to libc/arch-mips64/syscalls/vmsplice.S
index 3b457b5..aa03585 100644
--- a/libc/arch-mips64/syscalls/getpid.S
+++ b/libc/arch-mips64/syscalls/vmsplice.S
@@ -2,10 +2,10 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(vmsplice)
.set push
.set noreorder
- li v0, __NR_getpid
+ li v0, __NR_vmsplice
syscall
bnez a3, 1f
move a0, v0
@@ -22,4 +22,4 @@
j t9
move ra, t0
.set pop
-END(getpid)
+END(vmsplice)
diff --git a/libc/arch-x86/syscalls/getpid.S b/libc/arch-x86/syscalls/__getpid.S
similarity index 89%
rename from libc/arch-x86/syscalls/getpid.S
rename to libc/arch-x86/syscalls/__getpid.S
index 0e12d5a..f138d2f 100644
--- a/libc/arch-x86/syscalls/getpid.S
+++ b/libc/arch-x86/syscalls/__getpid.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(__getpid)
movl $__NR_getpid, %eax
int $0x80
cmpl $-MAX_ERRNO, %eax
@@ -13,4 +13,4 @@
addl $4, %esp
1:
ret
-END(getpid)
+END(__getpid)
diff --git a/libc/arch-x86/syscalls/splice.S b/libc/arch-x86/syscalls/splice.S
new file mode 100644
index 0000000..46e2312
--- /dev/null
+++ b/libc/arch-x86/syscalls/splice.S
@@ -0,0 +1,46 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(splice)
+ pushl %ebx
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset ebx, 0
+ pushl %ecx
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset ecx, 0
+ pushl %edx
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset edx, 0
+ pushl %esi
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset esi, 0
+ pushl %edi
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset edi, 0
+ pushl %ebp
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset ebp, 0
+ mov 28(%esp), %ebx
+ mov 32(%esp), %ecx
+ mov 36(%esp), %edx
+ mov 40(%esp), %esi
+ mov 44(%esp), %edi
+ mov 48(%esp), %ebp
+ movl $__NR_splice, %eax
+ int $0x80
+ cmpl $-MAX_ERRNO, %eax
+ jb 1f
+ negl %eax
+ pushl %eax
+ call __set_errno
+ addl $4, %esp
+1:
+ popl %ebp
+ popl %edi
+ popl %esi
+ popl %edx
+ popl %ecx
+ popl %ebx
+ ret
+END(splice)
diff --git a/libc/arch-x86/syscalls/tee.S b/libc/arch-x86/syscalls/tee.S
new file mode 100644
index 0000000..9422660
--- /dev/null
+++ b/libc/arch-x86/syscalls/tee.S
@@ -0,0 +1,36 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(tee)
+ pushl %ebx
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset ebx, 0
+ pushl %ecx
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset ecx, 0
+ pushl %edx
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset edx, 0
+ pushl %esi
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset esi, 0
+ mov 20(%esp), %ebx
+ mov 24(%esp), %ecx
+ mov 28(%esp), %edx
+ mov 32(%esp), %esi
+ movl $__NR_tee, %eax
+ int $0x80
+ cmpl $-MAX_ERRNO, %eax
+ jb 1f
+ negl %eax
+ pushl %eax
+ call __set_errno
+ addl $4, %esp
+1:
+ popl %esi
+ popl %edx
+ popl %ecx
+ popl %ebx
+ ret
+END(tee)
diff --git a/libc/arch-x86/syscalls/vmsplice.S b/libc/arch-x86/syscalls/vmsplice.S
new file mode 100644
index 0000000..2afba60
--- /dev/null
+++ b/libc/arch-x86/syscalls/vmsplice.S
@@ -0,0 +1,36 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(vmsplice)
+ pushl %ebx
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset ebx, 0
+ pushl %ecx
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset ecx, 0
+ pushl %edx
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset edx, 0
+ pushl %esi
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset esi, 0
+ mov 20(%esp), %ebx
+ mov 24(%esp), %ecx
+ mov 28(%esp), %edx
+ mov 32(%esp), %esi
+ movl $__NR_vmsplice, %eax
+ int $0x80
+ cmpl $-MAX_ERRNO, %eax
+ jb 1f
+ negl %eax
+ pushl %eax
+ call __set_errno
+ addl $4, %esp
+1:
+ popl %esi
+ popl %edx
+ popl %ecx
+ popl %ebx
+ ret
+END(vmsplice)
diff --git a/libc/arch-x86/x86.mk b/libc/arch-x86/x86.mk
index 3dc71d1..8aa2645 100644
--- a/libc/arch-x86/x86.mk
+++ b/libc/arch-x86/x86.mk
@@ -40,6 +40,9 @@
include $(arch_variant_mk)
libc_common_additional_dependencies += $(arch_variant_mk)
+libc_netbsd_src_files_x86 := \
+ upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
+
arch_variant_mk :=
libc_crt_target_cflags_x86 := \
diff --git a/libc/arch-x86_64/syscalls/getpid.S b/libc/arch-x86_64/syscalls/__getpid.S
similarity index 83%
rename from libc/arch-x86_64/syscalls/getpid.S
rename to libc/arch-x86_64/syscalls/__getpid.S
index a2d732c..bd1bf1e 100644
--- a/libc/arch-x86_64/syscalls/getpid.S
+++ b/libc/arch-x86_64/syscalls/__getpid.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
+ENTRY(__getpid)
movl $__NR_getpid, %eax
syscall
cmpq $-MAX_ERRNO, %rax
@@ -12,4 +12,5 @@
call __set_errno
1:
ret
-END(getpid)
+END(__getpid)
+.hidden __getpid
diff --git a/libc/arch-x86_64/syscalls/getpid.S b/libc/arch-x86_64/syscalls/splice.S
similarity index 72%
copy from libc/arch-x86_64/syscalls/getpid.S
copy to libc/arch-x86_64/syscalls/splice.S
index a2d732c..3c245a5 100644
--- a/libc/arch-x86_64/syscalls/getpid.S
+++ b/libc/arch-x86_64/syscalls/splice.S
@@ -2,8 +2,9 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
- movl $__NR_getpid, %eax
+ENTRY(splice)
+ movq %rcx, %r10
+ movl $__NR_splice, %eax
syscall
cmpq $-MAX_ERRNO, %rax
jb 1f
@@ -12,4 +13,4 @@
call __set_errno
1:
ret
-END(getpid)
+END(splice)
diff --git a/libc/arch-x86_64/syscalls/getpid.S b/libc/arch-x86_64/syscalls/tee.S
similarity index 74%
copy from libc/arch-x86_64/syscalls/getpid.S
copy to libc/arch-x86_64/syscalls/tee.S
index a2d732c..ad5698c 100644
--- a/libc/arch-x86_64/syscalls/getpid.S
+++ b/libc/arch-x86_64/syscalls/tee.S
@@ -2,8 +2,9 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
- movl $__NR_getpid, %eax
+ENTRY(tee)
+ movq %rcx, %r10
+ movl $__NR_tee, %eax
syscall
cmpq $-MAX_ERRNO, %rax
jb 1f
@@ -12,4 +13,4 @@
call __set_errno
1:
ret
-END(getpid)
+END(tee)
diff --git a/libc/arch-x86_64/syscalls/getpid.S b/libc/arch-x86_64/syscalls/vmsplice.S
similarity index 71%
copy from libc/arch-x86_64/syscalls/getpid.S
copy to libc/arch-x86_64/syscalls/vmsplice.S
index a2d732c..cc94cc6 100644
--- a/libc/arch-x86_64/syscalls/getpid.S
+++ b/libc/arch-x86_64/syscalls/vmsplice.S
@@ -2,8 +2,9 @@
#include <private/bionic_asm.h>
-ENTRY(getpid)
- movl $__NR_getpid, %eax
+ENTRY(vmsplice)
+ movq %rcx, %r10
+ movl $__NR_vmsplice, %eax
syscall
cmpq $-MAX_ERRNO, %rax
jb 1f
@@ -12,4 +13,4 @@
call __set_errno
1:
ret
-END(getpid)
+END(vmsplice)
diff --git a/libc/bionic/arc4random.c b/libc/bionic/arc4random.c
index 687030b..9bdf341 100644
--- a/libc/bionic/arc4random.c
+++ b/libc/bionic/arc4random.c
@@ -1,8 +1,9 @@
-/* $OpenBSD: arc4random.c,v 1.19 2008/06/04 00:50:23 djm Exp $ */
+/* $OpenBSD: arc4random.c,v 1.33 2014/06/13 18:58:58 deraadt Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -18,214 +19,236 @@
*/
/*
- * Arc4 random number generator for OpenBSD.
- *
- * This code is derived from section 17.1 of Applied Cryptography,
- * second edition, which describes a stream cipher allegedly
- * compatible with RSA Labs "RC4" cipher (the actual description of
- * which is a trade secret). The same algorithm is used as a stream
- * cipher called "arcfour" in Tatu Ylonen's ssh package.
- *
- * Here the stream cipher has been modified always to include the time
- * when initializing the state. That makes it impossible to
- * regenerate the same random sequence twice, so this can't be used
- * for encryption, but will generate good random numbers.
- *
- * RC4 is a registered trademark of RSA Laboratories.
+ * ChaCha based random number generator for OpenBSD.
*/
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
+#include <sys/mman.h>
+
+#if defined(__ANDROID__)
+#include <sys/stat.h>
+#include <linux/random.h>
+#include "private/libc_logging.h"
#include "private/thread_private.h"
-/* BIONIC-BEGIN */
-/* this lock should protect the global variables in this file */
-static pthread_mutex_t _arc4_lock = PTHREAD_MUTEX_INITIALIZER;
-#define _ARC4_LOCK() pthread_mutex_lock(&_arc4_lock)
-#define _ARC4_UNLOCK() pthread_mutex_unlock(&_arc4_lock)
-/* BIONIC-END */
+#define explicit_bzero(p, s) memset(p, 0, s)
+
+#undef MAP_ANON
+#define MAP_ANON (MAP_PRIVATE | MAP_ANONYMOUS)
+
+/*
+ * XXX Should be replaced with a proper entropy measure.
+ */
+static int
+gotdata(u_char *buf, size_t len)
+{
+ char any_set = 0;
+ size_t i;
+
+ for (i = 0; i < len; ++i)
+ any_set |= buf[i];
+ if (any_set == 0)
+ return -1;
+ return 0;
+}
+
+static int
+getentropy/*_urandom*/(u_char *buf, size_t len)
+{
+ int save_errno = errno;
+
+ int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOFOLLOW, 0));
+ if (fd == -1) {
+ __libc_fatal("getentropy_urandom failed to open \"/dev/urandom\": %s",
+ strerror(errno));
+ }
+
+ /* Lightly verify that the device node looks sane */
+ struct stat st;
+ if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
+ __libc_fatal("getentropy_urandom failed to fstat \"/dev/urandom\": %s",
+ strerror(errno));
+ }
+ int cnt;
+ if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
+ __libc_fatal("getentropy_urandom failed to ioctl \"/dev/urandom\": %s",
+ strerror(errno));
+ }
+ for (size_t i = 0; i < len; ) {
+ size_t wanted = len - i;
+ ssize_t ret = TEMP_FAILURE_RETRY(read(fd, buf + i, wanted));
+
+ if (ret == -1) {
+ __libc_fatal("getentropy_urandom failed to read \"/dev/urandom\": %s",
+ strerror(errno));
+ }
+ i += ret;
+ }
+ close(fd);
+ if (gotdata(buf, len) == -1) {
+ __libc_fatal("getentropy_urandom failed to get enough entropy: %s",
+ strerror(errno));
+ }
+
+ errno = save_errno;
+ return 0;
+}
+#endif /* __ANDROID__ */
+
+#define KEYSTREAM_ONLY
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#include "../upstream-openbsd/lib/libc/crypt/chacha_private.h"
+#pragma GCC diagnostic pop
#ifdef __GNUC__
#define inline __inline
-#else /* !__GNUC__ */
+#else /* !__GNUC__ */
#define inline
-#endif /* !__GNUC__ */
+#endif /* !__GNUC__ */
-struct arc4_stream {
- u_int8_t i;
- u_int8_t j;
- u_int8_t s[256];
-};
-
+#define KEYSZ 32
+#define IVSZ 8
+#define BLOCKSZ 64
+#define RSBUFSZ (16*BLOCKSZ)
static int rs_initialized;
-static struct arc4_stream rs;
-static pid_t arc4_stir_pid;
-static int arc4_count;
+static pid_t rs_stir_pid;
+static chacha_ctx *rs; /* chacha context for random keystream */
+static u_char *rs_buf; /* keystream blocks */
+static size_t rs_have; /* valid bytes at end of rs_buf */
+static size_t rs_count; /* bytes till reseed */
-static inline u_int8_t arc4_getbyte(void);
+static inline void _rs_rekey(u_char *dat, size_t datlen);
static inline void
-arc4_init(void)
+_rs_init(u_char *buf, size_t n)
{
- int n;
+ if (n < KEYSZ + IVSZ)
+ return;
- for (n = 0; n < 256; n++)
- rs.s[n] = n;
- rs.i = 0;
- rs.j = 0;
-}
+ if (rs == NULL && (rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE,
+ MAP_ANON, -1, 0)) == MAP_FAILED)
+ abort();
+ if (rs_buf == NULL && (rs_buf = mmap(NULL, RSBUFSZ, PROT_READ|PROT_WRITE,
+ MAP_ANON, -1, 0)) == MAP_FAILED)
+ abort();
-static inline void
-arc4_addrandom(u_char *dat, int datlen)
-{
- int n;
- u_int8_t si;
-
- rs.i--;
- for (n = 0; n < 256; n++) {
- rs.i = (rs.i + 1);
- si = rs.s[rs.i];
- rs.j = (rs.j + si + dat[n % datlen]);
- rs.s[rs.i] = rs.s[rs.j];
- rs.s[rs.j] = si;
- }
- rs.j = rs.i;
+ chacha_keysetup(rs, buf, KEYSZ * 8, 0);
+ chacha_ivsetup(rs, buf + KEYSZ);
}
static void
-arc4_stir(void)
+_rs_stir(void)
{
-#if 1 /* BIONIC-BEGIN */
- int i, fd;
- union {
- struct timeval tv;
- u_int rnd[128 / sizeof(u_int)];
- } rdat;
- int n;
+ u_char rnd[KEYSZ + IVSZ];
- if (!rs_initialized) {
- arc4_init();
- rs_initialized = 1;
- }
+ /* XXX */
+ (void) getentropy(rnd, sizeof rnd);
- fd = open("/dev/urandom", O_RDONLY);
- if (fd != -1) {
- read(fd, rdat.rnd, sizeof(rdat.rnd));
- close(fd);
- }
- else
- {
- /* fd < 0 ? Ah, what the heck. We'll just take
- * whatever was on the stack. just add a little more
- * time-based randomness though
- */
- gettimeofday(&rdat.tv, NULL);
- }
+ if (!rs_initialized) {
+ rs_initialized = 1;
+ _rs_init(rnd, sizeof(rnd));
+ } else
+ _rs_rekey(rnd, sizeof(rnd));
+ explicit_bzero(rnd, sizeof(rnd));
- arc4_stir_pid = getpid();
- arc4_addrandom((void *) &rdat, sizeof(rdat));
-#else /* BIONIC-END */
- int i, mib[2];
- size_t len;
- u_char rnd[128];
+ /* invalidate rs_buf */
+ rs_have = 0;
+ memset(rs_buf, 0, RSBUFSZ);
- if (!rs_initialized) {
- arc4_init();
- rs_initialized = 1;
- }
+ rs_count = 1600000;
+}
- mib[0] = CTL_KERN;
- mib[1] = KERN_ARND;
+static inline void
+_rs_stir_if_needed(size_t len)
+{
+ pid_t pid = getpid();
- len = sizeof(rnd);
- sysctl(mib, 2, rnd, &len, NULL, 0);
+ if (rs_count <= len || !rs_initialized || rs_stir_pid != pid) {
+ rs_stir_pid = pid;
+ _rs_stir();
+ } else
+ rs_count -= len;
+}
- arc4_stir_pid = getpid();
- arc4_addrandom(rnd, sizeof(rnd));
+static inline void
+_rs_rekey(u_char *dat, size_t datlen)
+{
+#ifndef KEYSTREAM_ONLY
+ memset(rs_buf, 0,RSBUFSZ);
#endif
- /*
- * Discard early keystream, as per recommendations in:
- * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
- */
- for (i = 0; i < 256; i++)
- (void)arc4_getbyte();
- arc4_count = 1600000;
+ /* fill rs_buf with the keystream */
+ chacha_encrypt_bytes(rs, rs_buf, rs_buf, RSBUFSZ);
+ /* mix in optional user provided data */
+ if (dat) {
+ size_t i, m;
+
+ m = MIN(datlen, KEYSZ + IVSZ);
+ for (i = 0; i < m; i++)
+ rs_buf[i] ^= dat[i];
+ }
+ /* immediately reinit for backtracking resistance */
+ _rs_init(rs_buf, KEYSZ + IVSZ);
+ memset(rs_buf, 0, KEYSZ + IVSZ);
+ rs_have = RSBUFSZ - KEYSZ - IVSZ;
}
-static inline u_int8_t
-arc4_getbyte(void)
+static inline void
+_rs_random_buf(void *_buf, size_t n)
{
- u_int8_t si, sj;
+ u_char *buf = (u_char *)_buf;
+ size_t m;
- rs.i = (rs.i + 1);
- si = rs.s[rs.i];
- rs.j = (rs.j + si);
- sj = rs.s[rs.j];
- rs.s[rs.i] = sj;
- rs.s[rs.j] = si;
- return (rs.s[(si + sj) & 0xff]);
+ _rs_stir_if_needed(n);
+ while (n > 0) {
+ if (rs_have > 0) {
+ m = MIN(n, rs_have);
+ memcpy(buf, rs_buf + RSBUFSZ - rs_have, m);
+ memset(rs_buf + RSBUFSZ - rs_have, 0, m);
+ buf += m;
+ n -= m;
+ rs_have -= m;
+ }
+ if (rs_have == 0)
+ _rs_rekey(NULL, 0);
+ }
}
-static inline u_int32_t
-arc4_getword(void)
+static inline void
+_rs_random_u32(u_int32_t *val)
{
- u_int32_t val;
- val = arc4_getbyte() << 24;
- val |= arc4_getbyte() << 16;
- val |= arc4_getbyte() << 8;
- val |= arc4_getbyte();
- return val;
-}
-
-void
-arc4random_stir(void)
-{
- _ARC4_LOCK();
- arc4_stir();
- _ARC4_UNLOCK();
-}
-
-void
-arc4random_addrandom(u_char *dat, int datlen)
-{
- _ARC4_LOCK();
- if (!rs_initialized)
- arc4_stir();
- arc4_addrandom(dat, datlen);
- _ARC4_UNLOCK();
+ _rs_stir_if_needed(sizeof(*val));
+ if (rs_have < sizeof(*val))
+ _rs_rekey(NULL, 0);
+ memcpy(val, rs_buf + RSBUFSZ - rs_have, sizeof(*val));
+ memset(rs_buf + RSBUFSZ - rs_have, 0, sizeof(*val));
+ rs_have -= sizeof(*val);
}
u_int32_t
arc4random(void)
{
- u_int32_t val;
- _ARC4_LOCK();
- arc4_count -= 4;
- if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != getpid())
- arc4_stir();
- val = arc4_getword();
- _ARC4_UNLOCK();
- return val;
+ u_int32_t val;
+
+ _ARC4_LOCK();
+ _rs_random_u32(&val);
+ _ARC4_UNLOCK();
+ return val;
}
void
-arc4random_buf(void *_buf, size_t n)
+arc4random_buf(void *buf, size_t n)
{
- u_char *buf = (u_char *)_buf;
- _ARC4_LOCK();
- if (!rs_initialized || arc4_stir_pid != getpid())
- arc4_stir();
- while (n--) {
- if (--arc4_count <= 0)
- arc4_stir();
- buf[n] = arc4_getbyte();
- }
- _ARC4_UNLOCK();
+ _ARC4_LOCK();
+ _rs_random_buf(buf, n);
+ _ARC4_UNLOCK();
}
/*
@@ -241,55 +264,25 @@
u_int32_t
arc4random_uniform(u_int32_t upper_bound)
{
- u_int32_t r, min;
+ u_int32_t r, min;
- if (upper_bound < 2)
- return 0;
+ if (upper_bound < 2)
+ return 0;
-#if (ULONG_MAX > 0xffffffffUL)
- min = 0x100000000UL % upper_bound;
-#else
- /* Calculate (2**32 % upper_bound) avoiding 64-bit math */
- if (upper_bound > 0x80000000)
- min = 1 + ~upper_bound; /* 2**32 - upper_bound */
- else {
- /* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
- min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
- }
-#endif
+ /* 2**32 % x == (2**32 - x) % x */
+ min = -upper_bound % upper_bound;
- /*
- * This could theoretically loop forever but each retry has
- * p > 0.5 (worst case, usually far better) of selecting a
- * number inside the range we need, so it should rarely need
- * to re-roll.
- */
- for (;;) {
- r = arc4random();
- if (r >= min)
- break;
- }
+ /*
+ * This could theoretically loop forever but each retry has
+ * p > 0.5 (worst case, usually far better) of selecting a
+ * number inside the range we need, so it should rarely need
+ * to re-roll.
+ */
+ for (;;) {
+ r = arc4random();
+ if (r >= min)
+ break;
+ }
- return r % upper_bound;
+ return r % upper_bound;
}
-
-#if 0
-/*-------- Test code for i386 --------*/
-#include <stdio.h>
-#include <machine/pctr.h>
-int
-main(int argc, char **argv)
-{
- const int iter = 1000000;
- int i;
- pctrval v;
-
- v = rdtsc();
- for (i = 0; i < iter; i++)
- arc4random();
- v = rdtsc() - v;
- v /= iter;
-
- printf("%qd cycles\n", v);
-}
-#endif
diff --git a/libc/bionic/clone.cpp b/libc/bionic/clone.cpp
index 001e245..0a0fdd5 100644
--- a/libc/bionic/clone.cpp
+++ b/libc/bionic/clone.cpp
@@ -31,6 +31,8 @@
#include <stdlib.h>
#include <stdarg.h>
+#include "pthread_internal.h"
+
extern "C" pid_t __bionic_clone(uint32_t flags, void* child_stack, int* parent_tid, void* tls, int* child_tid, int (*fn)(void*), void* arg);
extern "C" __noreturn void __exit(int status);
@@ -64,5 +66,18 @@
child_stack_addr &= ~0xf;
child_stack = reinterpret_cast<void*>(child_stack_addr);
- return __bionic_clone(flags, child_stack, parent_tid, new_tls, child_tid, fn, arg);
+ // Remember the parent pid and invalidate the cached value while we clone.
+ pthread_internal_t* self = __get_thread();
+ pid_t parent_pid = self->invalidate_cached_pid();
+
+ // Actually do the clone.
+ int clone_result = __bionic_clone(flags, child_stack, parent_tid, new_tls, child_tid, fn, arg);
+
+ // We're the parent, so put our known pid back in place.
+ // We leave the child without a cached pid, but:
+ // 1. pthread_create gives its children their own pthread_internal_t with the correct pid.
+ // 2. fork makes a clone system call directly.
+ // If any other cases become important, we could use a double trampoline like __pthread_start.
+ self->set_cached_pid(parent_pid);
+ return clone_result;
}
diff --git a/libc/bionic/cmsg_nxthdr.cpp b/libc/bionic/cmsg_nxthdr.cpp
index 6f0a47c..8a2b33e 100644
--- a/libc/bionic/cmsg_nxthdr.cpp
+++ b/libc/bionic/cmsg_nxthdr.cpp
@@ -28,7 +28,7 @@
#include <sys/socket.h>
-cmsghdr* cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
+cmsghdr* __cmsg_nxthdr(msghdr* msg, cmsghdr* cmsg) {
cmsghdr* ptr;
ptr = reinterpret_cast<cmsghdr*>(reinterpret_cast<char*>(cmsg) + CMSG_ALIGN(cmsg->cmsg_len));
size_t len = reinterpret_cast<char*>(ptr+1) - reinterpret_cast<char*>(msg->msg_control);
@@ -37,3 +37,6 @@
}
return ptr;
}
+
+// TODO: remove after NDK refresh.
+__weak_alias(cmsg_nxthdr, __cmsg_nxthdr);
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index a0f98e4..6cfc736 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -31,19 +31,26 @@
#include "pthread_internal.h"
+#define FORK_FLAGS (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD)
+
int fork() {
__bionic_atfork_run_prepare();
pthread_internal_t* self = __get_thread();
- int flags = CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD;
+
+ // Remember the parent pid and invalidate the cached value while we fork.
+ pid_t parent_pid = self->invalidate_cached_pid();
+
#if defined(__x86_64__) // sys_clone's last two arguments are flipped on x86-64.
- int result = syscall(__NR_clone, flags, NULL, NULL, &(self->tid), NULL);
+ int result = syscall(__NR_clone, FORK_FLAGS, NULL, NULL, &(self->tid), NULL);
#else
- int result = syscall(__NR_clone, flags, NULL, NULL, NULL, &(self->tid));
+ int result = syscall(__NR_clone, FORK_FLAGS, NULL, NULL, NULL, &(self->tid));
#endif
if (result == 0) {
+ self->set_cached_pid(gettid());
__bionic_atfork_run_child();
} else {
+ self->set_cached_pid(parent_pid);
__bionic_atfork_run_parent();
}
return result;
diff --git a/libc/bionic/fts.c b/libc/bionic/fts.c
index ec0baf7..c491b6a 100644
--- a/libc/bionic/fts.c
+++ b/libc/bionic/fts.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fts.c,v 1.43 2009/08/27 16:19:27 millert Exp $ */
+/* $OpenBSD: fts.c,v 1.46 2014/05/25 17:47:04 tedu Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -36,6 +36,7 @@
#include <errno.h>
#include <fcntl.h>
#include <fts.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -97,7 +98,7 @@
* Start out with 1K of path space, and enough, in any case,
* to hold the user's paths.
*/
- if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
+ if (fts_palloc(sp, MAX(fts_maxarglen(argv), PATH_MAX)))
goto mem1;
/* Allocate/initialize root's parent. */
@@ -447,7 +448,7 @@
*/
/* ARGSUSED */
int
-fts_set(FTS *sp, FTSENT *p, int instr)
+fts_set(FTS *sp __unused, FTSENT *p, int instr)
{
if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
instr != FTS_NOINSTR && instr != FTS_SKIP) {
@@ -637,7 +638,7 @@
maxlen = sp->fts_pathlen - len;
/*
- * fts_level is a short so we must prevent it from wrapping
+ * fts_level is signed so we must prevent it from wrapping
* around to FTS_ROOTLEVEL and FTS_ROOTPARENTLEVEL.
*/
level = cur->fts_level;
@@ -908,10 +909,9 @@
len = sizeof(FTSENT) + namelen;
if (!ISSET(FTS_NOSTAT))
len += sizeof(struct stat) + ALIGNBYTES;
- if ((p = malloc(len)) == NULL)
+ if ((p = calloc(1, len)) == NULL)
return (NULL);
- memset(p, 0, len);
p->fts_path = sp->fts_path;
p->fts_namelen = namelen;
p->fts_instr = FTS_NOINSTR;
@@ -936,7 +936,7 @@
/*
* Allow essentially unlimited paths; find, rm, ls should all work on any tree.
- * Most systems will allow creation of paths much longer than MAXPATHLEN, even
+ * Most systems will allow creation of paths much longer than PATH_MAX, even
* though the kernel won't resolve them. Add the size (not just what's needed)
* plus 256 bytes so don't realloc the path 2 bytes at a time.
*/
diff --git a/libc/bionic/thread_atexit.cpp b/libc/bionic/getpid.cpp
similarity index 71%
copy from libc/bionic/thread_atexit.cpp
copy to libc/bionic/getpid.cpp
index 68c119d..a3d5b35 100644
--- a/libc/bionic/thread_atexit.cpp
+++ b/libc/bionic/getpid.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,21 +26,22 @@
* SUCH DAMAGE.
*/
-/* some simple glue used to make the BSD atexit code happy */
+#include <unistd.h>
-#include <pthread.h>
+#include "pthread_internal.h"
-static pthread_mutex_t g_atexit_lock = PTHREAD_MUTEX_INITIALIZER;
+extern "C" pid_t __getpid();
-__BEGIN_DECLS
-__LIBC_HIDDEN__ void _thread_atexit_lock();
-__LIBC_HIDDEN__ void _thread_atexit_unlock();
-__END_DECLS
+pid_t getpid() {
+ pthread_internal_t* self = __get_thread();
-void _thread_atexit_lock() {
- pthread_mutex_lock(&g_atexit_lock);
-}
+ // Do we have a valid cached pid?
+ pid_t cached_pid;
+ if (__predict_true(self->get_cached_pid(&cached_pid))) {
+ return cached_pid;
+ }
-void _thread_atexit_unlock() {
- pthread_mutex_unlock(&g_atexit_lock);
+ // We're still in the dynamic linker or we're in the middle of forking, so ask the kernel.
+ // We don't know whether it's safe to update the cached value, so don't try.
+ return __getpid();
}
diff --git a/libc/bionic/if_indextoname.c b/libc/bionic/if_indextoname.c
index dc08b28..f0db512 100644
--- a/libc/bionic/if_indextoname.c
+++ b/libc/bionic/if_indextoname.c
@@ -41,7 +41,6 @@
char*
if_indextoname(unsigned ifindex, char *ifname)
{
- int index;
int ctl_sock;
struct ifreq ifr;
char* ret = NULL;
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index 625d789..d1fe960 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -14,13 +14,19 @@
* limitations under the License.
*/
+#include <sys/param.h>
#include <unistd.h>
#include "jemalloc.h"
+#include "private/bionic_macros.h"
void* je_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- return je_memalign(pagesize, (bytes + pagesize - 1) & ~(pagesize - 1));
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
+ if (size < bytes) {
+ return NULL;
+ }
+ return je_memalign(pagesize, size);
}
#ifdef je_memalign
@@ -31,11 +37,9 @@
// but this is not true. Both glibc and dlmalloc round up to the next power
// of 2, so we'll do the same.
void* je_memalign_round_up_boundary(size_t boundary, size_t size) {
- unsigned int power_of_2 = static_cast<unsigned int>(boundary);
- if (power_of_2 != 0) {
- power_of_2 = 1UL << (sizeof(unsigned int)*8 - 1 - __builtin_clz(power_of_2));
- if (power_of_2 != boundary) {
- boundary = power_of_2 << 1;
+ if (boundary != 0) {
+ if (!powerof2(boundary)) {
+ boundary = BIONIC_ROUND_UP_POWER_OF_2(boundary);
}
} else {
boundary = 1;
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index abf2d36..fa61c3c 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -86,21 +86,24 @@
void __libc_init_tls(KernelArgumentBlock& args) {
__libc_auxv = args.auxv;
- uintptr_t stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
- size_t stack_size = get_main_thread_stack_size();
- uintptr_t stack_bottom = stack_top - stack_size;
-
static void* tls[BIONIC_TLS_SLOTS];
static pthread_internal_t main_thread;
main_thread.tls = tls;
// Tell the kernel to clear our tid field when we exit, so we're like any other pthread.
+ // As a side-effect, this tells us our pid (which is the same as the main thread's tid).
main_thread.tid = __set_tid_address(&main_thread.tid);
+ main_thread.set_cached_pid(main_thread.tid);
- // We already have a stack, and we don't want to free it up on exit (because things like
- // environment variables with global scope live on it).
+ // Work out the extent of the main thread's stack.
+ uintptr_t stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
+ size_t stack_size = get_main_thread_stack_size();
+ void* stack_bottom = reinterpret_cast<void*>(stack_top - stack_size);
+
+ // We don't want to free the main thread's stack even when the main thread exits
+ // because things like environment variables with global scope live on it.
pthread_attr_init(&main_thread.attr);
- pthread_attr_setstack(&main_thread.attr, (void*) stack_bottom, stack_size);
+ pthread_attr_setstack(&main_thread.attr, stack_bottom, stack_size);
main_thread.attr.flags = PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK | PTHREAD_ATTR_FLAG_MAIN_THREAD;
__init_thread(&main_thread, false);
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index 8966a5f..e656a12 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -453,7 +453,7 @@
// found that all logd crashes thus far have had no problem stuffing
// the UNIX domain socket and moving on so not critical *today*.
- int log_fd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM, 0));
+ int log_fd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0));
if (log_fd < 0) {
return -1;
}
@@ -619,7 +619,8 @@
BufferOutputStream os(msg, sizeof(msg));
out_vformat(os, format, args);
- // TODO: log to stderr for the benefit of "adb shell" users.
+ // log to stderr for the benefit of "adb shell" users.
+ write(2, msg, strlen(msg));
// Log to the log for the benefit of regular app developers (whose stdout and stderr are closed).
__libc_write_log(ANDROID_LOG_FATAL, "libc", msg);
diff --git a/libc/bionic/malloc_debug_check.cpp b/libc/bionic/malloc_debug_check.cpp
index faf61bf..e4e4c2e 100644
--- a/libc/bionic/malloc_debug_check.cpp
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -38,6 +38,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/param.h>
#include <sys/socket.h>
#include <sys/system_properties.h>
#include <sys/types.h>
@@ -47,8 +48,9 @@
#include "debug_mapinfo.h"
#include "debug_stacktrace.h"
-#include "private/libc_logging.h"
#include "malloc_debug_common.h"
+#include "private/bionic_macros.h"
+#include "private/libc_logging.h"
#include "private/ScopedPthreadMutexLocker.h"
#define MAX_BACKTRACE_DEPTH 16
@@ -350,8 +352,8 @@
}
// Make the alignment a power of two.
- if (alignment & (alignment-1)) {
- alignment = 1L << (31 - __builtin_clz(alignment));
+ if (!powerof2(alignment)) {
+ alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
}
// here, alignment is at least MALLOC_ALIGNMENT<<1 bytes
@@ -526,7 +528,7 @@
}
extern "C" int chk_posix_memalign(void** memptr, size_t alignment, size_t size) {
- if ((alignment & (alignment - 1)) != 0) {
+ if (!powerof2(alignment)) {
return EINVAL;
}
int saved_errno = errno;
@@ -537,7 +539,7 @@
extern "C" void* chk_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
}
diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp
index 2cc38cc..308d40b 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -37,6 +37,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/param.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/system_properties.h>
@@ -48,6 +49,7 @@
#include "debug_stacktrace.h"
#include "malloc_debug_common.h"
+#include "private/bionic_macros.h"
#include "private/libc_logging.h"
#include "private/ScopedPthreadMutexLocker.h"
@@ -255,7 +257,7 @@
}
extern "C" int fill_posix_memalign(void** memptr, size_t alignment, size_t size) {
- if ((alignment & (alignment - 1)) != 0) {
+ if (!powerof2(alignment)) {
return EINVAL;
}
int saved_errno = errno;
@@ -266,7 +268,7 @@
extern "C" void* fill_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
}
@@ -401,8 +403,8 @@
}
// need to make sure it's a power of two
- if (alignment & (alignment-1)) {
- alignment = 1L << (31 - __builtin_clz(alignment));
+ if (!powerof2(alignment)) {
+ alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
}
// here, alignment is at least MALLOC_ALIGNMENT<<1 bytes
@@ -464,7 +466,7 @@
}
extern "C" int leak_posix_memalign(void** memptr, size_t alignment, size_t size) {
- if ((alignment & (alignment - 1)) != 0) {
+ if (!powerof2(alignment)) {
return EINVAL;
}
int saved_errno = errno;
@@ -475,7 +477,7 @@
extern "C" void* leak_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
}
diff --git a/libc/bionic/malloc_debug_qemu.cpp b/libc/bionic/malloc_debug_qemu.cpp
index 9b3bb55..fd5161a 100644
--- a/libc/bionic/malloc_debug_qemu.cpp
+++ b/libc/bionic/malloc_debug_qemu.cpp
@@ -47,11 +47,13 @@
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
+#include <sys/param.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
-#include "private/libc_logging.h"
#include "malloc_debug_common.h"
+#include "private/bionic_macros.h"
+#include "private/libc_logging.h"
/* This file should be included into the build only when
* MALLOC_QEMU_INSTRUMENT macro is defined. */
@@ -970,8 +972,8 @@
// size.
if (alignment < DEFAULT_PREFIX_SIZE) {
alignment = DEFAULT_PREFIX_SIZE;
- } else if (alignment & (alignment - 1)) {
- alignment = 1L << (31 - __builtin_clz(alignment));
+ } else if (!powerof2(alignment)) {
+ alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
}
desc.prefix_size = alignment;
desc.requested_bytes = bytes;
@@ -1047,7 +1049,7 @@
extern "C" void* qemu_instrumented_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
qemu_error_log("<libc_pid=%03u, pid=%03u> pvalloc(%zu): overflow (%zu).",
malloc_pid, getpid(), bytes, size);
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index c4cb262..2ded22b 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -30,9 +30,11 @@
#include <errno.h>
#include <sys/mman.h>
+#include <unistd.h>
#include "pthread_internal.h"
+#include "private/bionic_macros.h"
#include "private/bionic_ssp.h"
#include "private/bionic_tls.h"
#include "private/libc_logging.h"
@@ -183,8 +185,8 @@
}
// Make sure the stack size and guard size are multiples of PAGE_SIZE.
- thread->attr.stack_size = (thread->attr.stack_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
- thread->attr.guard_size = (thread->attr.guard_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+ thread->attr.stack_size = BIONIC_ALIGN(thread->attr.stack_size, PAGE_SIZE);
+ thread->attr.guard_size = BIONIC_ALIGN(thread->attr.guard_size, PAGE_SIZE);
if (thread->attr.stack_base == NULL) {
// The caller didn't provide a stack, so allocate one.
@@ -219,6 +221,8 @@
thread->start_routine = start_routine;
thread->start_routine_arg = arg;
+ thread->set_cached_pid(getpid());
+
int flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
void* tls = thread->tls;
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 490ae86..e05d15c 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -36,6 +36,26 @@
pid_t tid;
+ private:
+ pid_t cached_pid_;
+
+ public:
+ pid_t invalidate_cached_pid() {
+ pid_t old_value;
+ get_cached_pid(&old_value);
+ set_cached_pid(0);
+ return old_value;
+ }
+
+ void set_cached_pid(pid_t value) {
+ cached_pid_ = value;
+ }
+
+ bool get_cached_pid(pid_t* cached_pid) {
+ *cached_pid = cached_pid_;
+ return (*cached_pid != 0);
+ }
+
void** tls;
pthread_attr_t attr;
diff --git a/libc/bionic/recv.cpp b/libc/bionic/recv.cpp
index 60f264d..061cd46 100644
--- a/libc/bionic/recv.cpp
+++ b/libc/bionic/recv.cpp
@@ -26,6 +26,7 @@
* SUCH DAMAGE.
*/
+#undef _FORTIFY_SOURCE
#include <sys/socket.h>
ssize_t recv(int socket, void *buf, size_t len, int flags) {
diff --git a/libc/bionic/semaphore.c b/libc/bionic/semaphore.c
index b12a37d..7387d6e 100644
--- a/libc/bionic/semaphore.c
+++ b/libc/bionic/semaphore.c
@@ -147,7 +147,7 @@
}
-int sem_unlink(const char * name)
+int sem_unlink(const char* name __unused)
{
errno = ENOSYS;
return -1;
@@ -266,7 +266,6 @@
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
{
- int ret;
unsigned int shared;
if (sem == NULL) {
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index 7618586..a564c39 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -55,9 +55,6 @@
#include "private/bionic_futex.h"
#include "private/bionic_macros.h"
-#define ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
-
-
static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
@@ -301,7 +298,7 @@
static void *allocate_obj(const size_t size, uint32_t *const off)
{
prop_area *pa = __system_property_area__;
- const size_t aligned = ALIGN(size, sizeof(uint32_t));
+ const size_t aligned = BIONIC_ALIGN(size, sizeof(uint32_t));
if (pa->bytes_used + aligned > pa_data_size) {
return NULL;
}
diff --git a/libc/bionic/thread_atexit.cpp b/libc/bionic/thread_private.cpp
similarity index 84%
rename from libc/bionic/thread_atexit.cpp
rename to libc/bionic/thread_private.cpp
index 68c119d..1c04019 100644
--- a/libc/bionic/thread_atexit.cpp
+++ b/libc/bionic/thread_private.cpp
@@ -26,17 +26,13 @@
* SUCH DAMAGE.
*/
-/* some simple glue used to make the BSD atexit code happy */
-
#include <pthread.h>
+#include "private/thread_private.h"
+
+// Some simple glue used to make BSD code thread-safe.
static pthread_mutex_t g_atexit_lock = PTHREAD_MUTEX_INITIALIZER;
-__BEGIN_DECLS
-__LIBC_HIDDEN__ void _thread_atexit_lock();
-__LIBC_HIDDEN__ void _thread_atexit_unlock();
-__END_DECLS
-
void _thread_atexit_lock() {
pthread_mutex_lock(&g_atexit_lock);
}
@@ -44,3 +40,13 @@
void _thread_atexit_unlock() {
pthread_mutex_unlock(&g_atexit_lock);
}
+
+static pthread_mutex_t g_arc4_lock = PTHREAD_MUTEX_INITIALIZER;
+
+void _thread_arc4_lock() {
+ pthread_mutex_lock(&g_arc4_lock);
+}
+
+void _thread_arc4_unlock() {
+ pthread_mutex_unlock(&g_arc4_lock);
+}
diff --git a/libc/bionic/time64.c b/libc/bionic/time64.c
index 7163b34..62ee903 100644
--- a/libc/bionic/time64.c
+++ b/libc/bionic/time64.c
@@ -252,6 +252,7 @@
}
+#if !defined(NDEBUG)
static int check_tm(struct TM *tm)
{
/* Don't forget leap seconds */
@@ -283,6 +284,7 @@
return 1;
}
+#endif
/* The exceptional centuries without leap years cause the cycle to
diff --git a/libc/dns/gethnamaddr.c b/libc/dns/gethnamaddr.c
index 1afad6d..6f30f75 100644
--- a/libc/dns/gethnamaddr.c
+++ b/libc/dns/gethnamaddr.c
@@ -539,7 +539,7 @@
const int one = 1;
struct sockaddr_un proxy_addr;
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (sock < 0) {
return NULL;
}
diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c
index be692e3..65fd1c1 100644
--- a/libc/dns/net/getaddrinfo.c
+++ b/libc/dns/net/getaddrinfo.c
@@ -362,7 +362,7 @@
*/
static int
_test_connect(int pf, struct sockaddr *addr, size_t addrlen, unsigned mark) {
- int s = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
+ int s = socket(pf, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
if (s < 0)
return 0;
if (mark != MARK_UNSET && setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
@@ -433,7 +433,7 @@
return EAI_NODATA;
}
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (sock < 0) {
return EAI_NODATA;
}
@@ -884,7 +884,7 @@
* filter out AFs that are not supported by the kernel
* XXX errno?
*/
- s = socket(pai->ai_family, SOCK_DGRAM, 0);
+ s = socket(pai->ai_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (s < 0) {
if (errno != EMFILE)
return 0;
@@ -1792,7 +1792,7 @@
return 0;
}
- sock = socket(addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+ sock = socket(addr->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
if (sock == -1) {
if (errno == EAFNOSUPPORT) {
return 0;
diff --git a/libc/dns/net/getservbyname.c b/libc/dns/net/getservbyname.c
index 5ea528e..c95c9b0 100644
--- a/libc/dns/net/getservbyname.c
+++ b/libc/dns/net/getservbyname.c
@@ -34,7 +34,6 @@
getservbyname(const char *name, const char *proto)
{
res_static rs = __res_get_static();
- struct servent* s;
if (rs == NULL || proto == NULL || name == NULL) {
errno = EINVAL;
diff --git a/libc/dns/net/getservbyport.c b/libc/dns/net/getservbyport.c
index fad7e23..7dcaafb 100644
--- a/libc/dns/net/getservbyport.c
+++ b/libc/dns/net/getservbyport.c
@@ -33,7 +33,6 @@
getservbyport(int port, const char *proto)
{
res_static rs = __res_get_static();
- struct servent* s;
if (rs == NULL || proto == NULL) {
errno = EINVAL;
diff --git a/libc/dns/net/nsdispatch.c b/libc/dns/net/nsdispatch.c
index 15282be..fb6d8f6 100644
--- a/libc/dns/net/nsdispatch.c
+++ b/libc/dns/net/nsdispatch.c
@@ -69,26 +69,14 @@
*/
#include <sys/cdefs.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
#include <assert.h>
-#ifdef __ELF__
-#include <dlfcn.h>
-#endif /* __ELF__ */
-#include <fcntl.h>
-#define _NS_PRIVATE
#include <nsswitch.h>
#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <strings.h>
-#include <unistd.h>
static nss_method
-_nsmethod(const char *source, const char *database, const char *method,
+_nsmethod(const char *source, const char *database __unused, const char *method __unused,
const ns_dtab disp_tab[], void **cb_data)
{
int curdisp;
diff --git a/libc/dns/resolv/res_cache.c b/libc/dns/resolv/res_cache.c
index 9df97cd..77a1b4d 100644
--- a/libc/dns/resolv/res_cache.c
+++ b/libc/dns/resolv/res_cache.c
@@ -2043,7 +2043,7 @@
register char **pp = statp->dnsrch;
register int *p = info->dnsrch_offset;
while (pp < statp->dnsrch + MAXDNSRCH && *p != -1) {
- *pp++ = &statp->defdname + *p++;
+ *pp++ = &statp->defdname[0] + *p++;
}
}
pthread_mutex_unlock(&_res_cache_list_lock);
diff --git a/libc/dns/resolv/res_init.c b/libc/dns/resolv/res_init.c
index 9f3a9da..f1cbed8 100644
--- a/libc/dns/resolv/res_init.c
+++ b/libc/dns/resolv/res_init.c
@@ -104,10 +104,6 @@
#include <sys/system_properties.h>
#endif /* ANDROID_CHANGES */
-#ifndef MIN
-#define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
/* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */
#ifdef ANDROID_CHANGES
#include "resolv_netid.h"
@@ -125,9 +121,11 @@
static void res_setoptions __P((res_state, const char *, const char *));
+#ifdef RESOLVSORT
static const char sort_mask[] = "/&";
#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
-static u_int32_t net_mask __P((struct in_addr));
+static uint32_t net_mask(struct in_addr);
+#endif
#if !defined(isascii) /* XXX - could be a function */
# define isascii(c) (!(c & 0200))
@@ -168,15 +166,25 @@
/* This function has to be reachable by res_data.c but not publicly. */
int
__res_vinit(res_state statp, int preinit) {
+#if !defined(__ANDROID__)
register FILE *fp;
+#endif
register char *cp, **pp;
+#if !defined(__ANDROID__)
register int n;
+#endif
char buf[BUFSIZ];
int nserv = 0; /* number of nameserver records read from file */
+#if !defined(__ANDROID__)
int haveenv = 0;
+#endif
int havesearch = 0;
+#ifdef RESOLVSORT
int nsort = 0;
+#endif
+#if !defined(__ANDROID__)
char *net;
+#endif
int dots;
union res_sockaddr_union u[2];
@@ -235,7 +243,7 @@
statp->nsort = 0;
res_setservers(statp, u, nserv);
-#if 0 /* IGNORE THE ENVIRONMENT */
+#if !defined(__ANDROID__) /* IGNORE THE ENVIRONMENT */
/* Allow user to override the local domain definition */
if ((cp = getenv("LOCALDOMAIN")) != NULL) {
(void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
@@ -593,12 +601,12 @@
}
}
+#ifdef RESOLVSORT
/* XXX - should really support CIDR which means explicit masks always. */
-static u_int32_t
-net_mask(in) /* XXX - should really use system's version of this */
- struct in_addr in;
+static uint32_t
+net_mask(struct in_addr in) /*!< XXX - should really use system's version of this */
{
- register u_int32_t i = ntohl(in.s_addr);
+ register uint32_t i = ntohl(in.s_addr);
if (IN_CLASSA(i))
return (htonl(IN_CLASSA_NET));
@@ -606,19 +614,19 @@
return (htonl(IN_CLASSB_NET));
return (htonl(IN_CLASSC_NET));
}
+#endif
#ifdef ANDROID_CHANGES
static int
real_randomid(u_int *random_value) {
/* open the nonblocking random device, returning -1 on failure */
- int random_device = open("/dev/urandom", O_RDONLY);
+ int random_device = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
if (random_device < 0) {
return -1;
}
/* read from the random device, returning -1 on failure (or too many retries)*/
- u_int retry = 5;
- for (retry; retry > 0; retry--) {
+ for (u_int retry = 5; retry > 0; retry--) {
int retval = read(random_device, random_value, sizeof(u_int));
if (retval == sizeof(u_int)) {
*random_value &= 0xffff;
@@ -649,7 +657,7 @@
return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
}
-/*
+/*%
* This routine is for closing the socket if a virtual circuit is used and
* the program wants to close it. This provides support for endhostent()
* which expects to close the socket.
@@ -657,7 +665,8 @@
* This routine is not expected to be user visible.
*/
void
-res_nclose(res_state statp) {
+res_nclose(res_state statp)
+{
int ns;
if (statp->_vcsock >= 0) {
@@ -674,7 +683,8 @@
}
void
-res_ndestroy(res_state statp) {
+res_ndestroy(res_state statp)
+{
res_nclose(statp);
if (statp->_u._ext.ext != NULL)
free(statp->_u._ext.ext);
@@ -683,21 +693,24 @@
}
const char *
-res_get_nibblesuffix(res_state statp) {
+res_get_nibblesuffix(res_state statp)
+{
if (statp->_u._ext.ext)
return (statp->_u._ext.ext->nsuffix);
return ("ip6.arpa");
}
const char *
-res_get_nibblesuffix2(res_state statp) {
+res_get_nibblesuffix2(res_state statp)
+{
if (statp->_u._ext.ext)
return (statp->_u._ext.ext->nsuffix2);
return ("ip6.int");
}
void
-res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) {
+res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt)
+{
int i, nserv;
size_t size;
@@ -718,10 +731,8 @@
if (size <= sizeof(statp->nsaddr_list[nserv]))
memcpy(&statp->nsaddr_list[nserv],
&set->sin, size);
-#ifdef notdef
else
statp->nsaddr_list[nserv].sin_family = 0;
-#endif
nserv++;
break;
@@ -750,10 +761,11 @@
}
int
-res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) {
+res_getservers(res_state statp, union res_sockaddr_union *set, int cnt)
+{
int i;
size_t size;
- u_int16_t family;
+ uint16_t family;
for (i = 0; i < statp->nscount && i < cnt; i++) {
if (statp->_u._ext.ext)
diff --git a/libc/dns/resolv/res_send.c b/libc/dns/resolv/res_send.c
index 9b36f55..4a010d5 100644
--- a/libc/dns/resolv/res_send.c
+++ b/libc/dns/resolv/res_send.c
@@ -764,7 +764,7 @@
struct sockaddr_storage peer;
socklen_t size = sizeof peer;
unsigned old_mark;
- int mark_size = sizeof(old_mark);
+ socklen_t mark_size = sizeof(old_mark);
if (getpeername(statp->_vcsock,
(struct sockaddr *)(void *)&peer, &size) < 0 ||
!sock_eq((struct sockaddr *)(void *)&peer, nsap) ||
@@ -779,7 +779,7 @@
if (statp->_vcsock >= 0)
res_nclose(statp);
- statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
+ statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (statp->_vcsock > highestFD) {
res_nclose(statp);
errno = ENOTSOCK;
@@ -1062,7 +1062,7 @@
nsap = get_nsaddr(statp, (size_t)ns);
nsaplen = get_salen(nsap);
if (EXT(statp).nssocks[ns] == -1) {
- EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0);
+ EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (EXT(statp).nssocks[ns] > highestFD) {
res_nclose(statp);
errno = ENOTSOCK;
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index 90962fa..616e08e 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -49,11 +49,17 @@
*/
ANDROID_DLEXT_USE_RELRO = 0x8,
+ /* Instruct dlopen to use library_fd instead of opening file by name.
+ * The filename parameter is still used to identify the library.
+ */
+ ANDROID_DLEXT_USE_LIBRARY_FD = 0x10,
+
/* Mask of valid bits */
ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS |
ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
ANDROID_DLEXT_WRITE_RELRO |
- ANDROID_DLEXT_USE_RELRO,
+ ANDROID_DLEXT_USE_RELRO |
+ ANDROID_DLEXT_USE_LIBRARY_FD,
};
typedef struct {
@@ -61,6 +67,7 @@
void* reserved_addr;
size_t reserved_size;
int relro_fd;
+ int library_fd;
} android_dlextinfo;
extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo);
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index cd68154..4450bb6 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -33,6 +33,7 @@
#include <sys/types.h>
#include <linux/fadvise.h>
#include <linux/fcntl.h>
+#include <linux/uio.h>
#include <unistd.h> /* this is not required, but makes client code much happier */
__BEGIN_DECLS
@@ -51,9 +52,12 @@
#define F_SETLKW64 F_SETLKW
#endif
-#ifndef O_ASYNC
-#define O_ASYNC FASYNC
-#endif
+#define O_ASYNC FASYNC
+
+#define SPLICE_F_MOVE 1
+#define SPLICE_F_NONBLOCK 2
+#define SPLICE_F_MORE 4
+#define SPLICE_F_GIFT 8
#define SYNC_FILE_RANGE_WAIT_BEFORE 1
#define SYNC_FILE_RANGE_WRITE 2
@@ -70,7 +74,10 @@
extern int open64(const char*, int, ...);
extern int posix_fallocate64(int, off64_t, off64_t);
extern int posix_fallocate(int, off_t, off_t);
+extern ssize_t splice(int, off64_t*, int, off64_t*, size_t, unsigned int);
+extern ssize_t tee(int, int, size_t, unsigned int);
extern int unlinkat(int, const char*, int);
+extern ssize_t vmsplice(int, const struct iovec*, size_t, unsigned int);
#if defined(__BIONIC_FORTIFY)
diff --git a/libc/dns/include/nsswitch.h b/libc/include/nsswitch.h
similarity index 91%
rename from libc/dns/include/nsswitch.h
rename to libc/include/nsswitch.h
index e03844b..af88433 100644
--- a/libc/dns/include/nsswitch.h
+++ b/libc/include/nsswitch.h
@@ -1,4 +1,4 @@
-/* $NetBSD: nsswitch.h,v 1.18 2005/11/29 03:12:58 christos Exp $ */
+/* $NetBSD: nsswitch.h,v 1.21 2011/07/17 20:54:34 joerg Exp $ */
/*-
* Copyright (c) 1997, 1998, 1999, 2004 The NetBSD Foundation, Inc.
@@ -15,13 +15,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -137,6 +130,7 @@
#else
# define NS_NIS_CB(F,C)
#endif
+#define NS_NULL_CB { .src = NULL },
/*
* ns_src - `nsswitch source'
@@ -149,7 +143,6 @@
} ns_src;
-#if 0
/*
* Default sourcelists (if nsswitch.conf is missing, corrupt,
* or the requested database doesn't have an entry)
@@ -161,7 +154,7 @@
extern const ns_src __nsdefaultfiles_forceall[];
extern const ns_src __nsdefaultnis[];
extern const ns_src __nsdefaultnis_forceall[];
-#endif
+
/*
* ns_mtab - `nsswitch method table'
@@ -222,7 +215,7 @@
__BEGIN_DECLS
int nsdispatch(void *, const ns_dtab [], const char *,
- const char *, const ns_src [], ...);
+ const char *, const ns_src [], ...) __LIBC_ABI_PUBLIC__;
#ifdef _NS_PRIVATE
int _nsdbtaddsrc(ns_dbt *, const ns_src *);
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 0063b24..f1849c5 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -34,6 +34,7 @@
#include <limits.h> /* For LONG_BIT */
#include <string.h> /* For memset() */
#include <sys/types.h>
+#include <asm/sigcontext.h>
#if defined(__LP64__) || defined(__mips__)
/* For 64-bit (and mips), the kernel's struct sigaction doesn't match the POSIX one,
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 266aa5e..62b7a67 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -100,9 +100,10 @@
extern double erand48(unsigned short xsubi[3]);
extern double drand48(void);
extern void srand48(long);
-extern unsigned int arc4random(void);
-extern void arc4random_stir(void);
-extern void arc4random_addrandom(unsigned char *, int);
+
+unsigned int arc4random(void);
+unsigned int arc4random_uniform(unsigned int);
+void arc4random_buf(void*, size_t);
#define RAND_MAX 0x7fffffff
diff --git a/libc/include/strings.h b/libc/include/strings.h
index c4d5f6c..ae261cf 100644
--- a/libc/include/strings.h
+++ b/libc/include/strings.h
@@ -43,8 +43,16 @@
#include <sys/cdefs.h>
__BEGIN_DECLS
-#define bcopy(b1, b2, len) (void)(memmove((b2), (b1), (len)))
-#define bzero(b, len) (void)(memset((b), '\0', (len)))
+#if defined(__BIONIC_FORTIFY)
+#define bcopy(b1, b2, len) \
+ (void)(__builtin___memmove_chk((b2), (b1), (len), __bos0(b2)))
+#define bzero(b, len) \
+ (void)(__builtin___memset_chk((b), '\0', (len), __bos0(b)))
+#else
+#define bcopy(b1, b2, len) (void)(__builtin_memmove((b2), (b1), (len)))
+#define bzero(b, len) (void)(__builtin_memset((b), '\0', (len)))
+#endif
+
int ffs(int);
int strcasecmp(const char *, const char *);
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index 7edaac9..ae2f238 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -107,7 +107,7 @@
int cmsg_type;
};
-#define CMSG_NXTHDR(mhdr, cmsg) cmsg_nxthdr((mhdr), (cmsg))
+#define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr((mhdr), (cmsg))
#define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) )
#define CMSG_DATA(cmsg) ((void*)((char*)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr))))
#define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len))
@@ -117,7 +117,7 @@
? (struct cmsghdr*) (msg)->msg_control : (struct cmsghdr*) NULL)
#define CMSG_OK(mhdr, cmsg) ((cmsg)->cmsg_len >= sizeof(struct cmsghdr) && (cmsg)->cmsg_len <= (unsigned long) ((mhdr)->msg_controllen - ((char*)(cmsg) - (char*)(mhdr)->msg_control)))
-struct cmsghdr* cmsg_nxthdr(struct msghdr*, struct cmsghdr*);
+struct cmsghdr* __cmsg_nxthdr(struct msghdr*, struct cmsghdr*);
#define SCM_RIGHTS 0x01
#define SCM_CREDENTIALS 0x02
diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h
index 9a76ad2..a5fa692 100644
--- a/libc/include/sys/types.h
+++ b/libc/include/sys/types.h
@@ -91,12 +91,17 @@
typedef __time_t time_t;
/* This historical accident means that we had a 32-bit off_t on 32-bit architectures. */
-#ifndef _OFF_T_DEFINED_
-#define _OFF_T_DEFINED_
+#if !defined(__LP64__)
typedef __kernel_off_t off_t;
-#endif
typedef __kernel_loff_t loff_t;
typedef loff_t off64_t;
+#else
+/* We could re-use the LP32 definitions, but that would mean that although off_t and loff_t/off64_t
+ * would be the same size, they wouldn't actually be the same type, which can lead to warnings. */
+typedef __kernel_off_t off_t;
+typedef off_t loff_t;
+typedef loff_t off64_t;
+#endif
/* while POSIX wants these in <sys/types.h>, we
* declare then in <pthread.h> instead */
diff --git a/libc/include/time.h b/libc/include/time.h
index 0f86fd3..0587a2d 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -36,9 +36,9 @@
#define CLOCKS_PER_SEC 1000000
-extern char* tzname[];
-extern int daylight;
-extern long int timezone;
+extern char* tzname[] __LIBC_ABI_PUBLIC__;
+extern int daylight __LIBC_ABI_PUBLIC__;
+extern long int timezone __LIBC_ABI_PUBLIC__;
struct sigevent;
@@ -58,44 +58,43 @@
#define TM_ZONE tm_zone
-extern time_t time(time_t*);
-extern int nanosleep(const struct timespec*, struct timespec*);
+extern time_t time(time_t*) __LIBC_ABI_PUBLIC__;
+extern int nanosleep(const struct timespec*, struct timespec*) __LIBC_ABI_PUBLIC__;
-extern char* asctime(const struct tm*);
-extern char* asctime_r(const struct tm*, char*);
+extern char* asctime(const struct tm*) __LIBC_ABI_PUBLIC__;
+extern char* asctime_r(const struct tm*, char*) __LIBC_ABI_PUBLIC__;
-extern double difftime(time_t, time_t);
-extern time_t mktime(struct tm*);
+extern double difftime(time_t, time_t) __LIBC_ABI_PUBLIC__;
+extern time_t mktime(struct tm*) __LIBC_ABI_PUBLIC__;
-extern struct tm* localtime(const time_t*);
-extern struct tm* localtime_r(const time_t*, struct tm*);
+extern struct tm* localtime(const time_t*) __LIBC_ABI_PUBLIC__;
+extern struct tm* localtime_r(const time_t*, struct tm*) __LIBC_ABI_PUBLIC__;
-extern struct tm* gmtime(const time_t*);
-extern struct tm* gmtime_r(const time_t*, struct tm*);
+extern struct tm* gmtime(const time_t*) __LIBC_ABI_PUBLIC__;
+extern struct tm* gmtime_r(const time_t*, struct tm*) __LIBC_ABI_PUBLIC__;
-extern char* strptime(const char*, const char*, struct tm*);
-extern size_t strftime(char*, size_t, const char*, const struct tm*);
+extern char* strptime(const char*, const char*, struct tm*) __LIBC_ABI_PUBLIC__;
+extern size_t strftime(char*, size_t, const char*, const struct tm*) __LIBC_ABI_PUBLIC__;
-extern char* ctime(const time_t*);
-extern char* ctime_r(const time_t*, char*);
+extern char* ctime(const time_t*) __LIBC_ABI_PUBLIC__;
+extern char* ctime_r(const time_t*, char*) __LIBC_ABI_PUBLIC__;
-extern void tzset(void);
+extern void tzset(void) __LIBC_ABI_PUBLIC__;
-extern clock_t clock(void);
+extern clock_t clock(void) __LIBC_ABI_PUBLIC__;
-extern int clock_getres(int, struct timespec*);
-extern int clock_gettime(int, struct timespec*);
+extern int clock_getres(int, struct timespec*) __LIBC_ABI_PUBLIC__;
+extern int clock_gettime(int, struct timespec*) __LIBC_ABI_PUBLIC__;
-extern int timer_create(int, struct sigevent*, timer_t*);
-extern int timer_delete(timer_t);
-extern int timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*);
-extern int timer_gettime(timer_t, struct itimerspec*);
-extern int timer_getoverrun(timer_t);
+extern int timer_create(int, struct sigevent*, timer_t*) __LIBC_ABI_PUBLIC__;
+extern int timer_delete(timer_t) __LIBC_ABI_PUBLIC__;
+extern int timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*) __LIBC_ABI_PUBLIC__;
+extern int timer_gettime(timer_t, struct itimerspec*) __LIBC_ABI_PUBLIC__;
+extern int timer_getoverrun(timer_t) __LIBC_ABI_PUBLIC__;
-extern time_t timelocal(struct tm*);
-extern time_t timegm(struct tm*);
-extern time_t time2posix(time_t);
-extern time_t posix2time(time_t);
+/* Non-standard extensions that are in the BSDs and glibc. */
+extern time_t timelocal(struct tm*) __LIBC_ABI_PUBLIC__;
+extern time_t timegm(struct tm*) __LIBC_ABI_PUBLIC__;
__END_DECLS
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index d50e9ec..014fed3 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -118,7 +118,7 @@
extern int wcscoll(const wchar_t *, const wchar_t *);
extern wchar_t *wcscpy(wchar_t *, const wchar_t *);
extern size_t wcscspn(const wchar_t *, const wchar_t *);
-extern size_t wcsftime(wchar_t *, size_t, const wchar_t *, const struct tm *);
+extern size_t wcsftime(wchar_t *, size_t, const wchar_t *, const struct tm *) __LIBC_ABI_PUBLIC__;
extern size_t wcslen(const wchar_t *);
extern int wcsncasecmp(const wchar_t *, const wchar_t *, size_t);
extern wchar_t *wcsncat(wchar_t *, const wchar_t *, size_t);
diff --git a/libc/kernel/tools/defaults.py b/libc/kernel/tools/defaults.py
index 67ab702..2efd455 100644
--- a/libc/kernel/tools/defaults.py
+++ b/libc/kernel/tools/defaults.py
@@ -44,7 +44,11 @@
kernel_default_arch_macros = {
"arm": {"__ARMEB__": kCppUndefinedMacro, "__ARM_EABI__": "1"},
"arm64": {},
- "mips": {"CONFIG_32BIT":"1", "__MIPSEB__": kCppUndefinedMacro, "__MIPSEL__": "1"},
+ "mips": {"__MIPSEB__": kCppUndefinedMacro,
+ "__MIPSEL__": "1",
+ "CONFIG_32BIT": "_ABIO32",
+ "CONFIG_CPU_LITTLE_ENDIAN": "1",
+ "__SANE_USERSPACE_TYPES__": "1",},
"x86": {},
}
diff --git a/libc/kernel/uapi/asm-mips/asm/fcntl.h b/libc/kernel/uapi/asm-mips/asm/fcntl.h
index 4a9bf5c..e77f79a 100644
--- a/libc/kernel/uapi/asm-mips/asm/fcntl.h
+++ b/libc/kernel/uapi/asm-mips/asm/fcntl.h
@@ -46,19 +46,21 @@
#define F_SETLKW64 35
#endif
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#ifdef _ABIO32
#include <linux/types.h>
struct flock {
short l_type;
- short l_whence;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ short l_whence;
__kernel_off_t l_start;
__kernel_off_t l_len;
long l_sysid;
- __kernel_pid_t l_pid;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __kernel_pid_t l_pid;
long pad[4];
};
#define HAVE_ARCH_STRUCT_FLOCK
-#include <asm-generic/fcntl.h>
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif
+#include <asm-generic/fcntl.h>
+#endif
diff --git a/libc/kernel/uapi/asm-mips/asm/msgbuf.h b/libc/kernel/uapi/asm-mips/asm/msgbuf.h
index d81da73..624bddf 100644
--- a/libc/kernel/uapi/asm-mips/asm/msgbuf.h
+++ b/libc/kernel/uapi/asm-mips/asm/msgbuf.h
@@ -21,21 +21,29 @@
struct msqid64_ds {
struct ipc64_perm msg_perm;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- unsigned long __unused1;
__kernel_time_t msg_stime;
- unsigned long __unused2;
- __kernel_time_t msg_rtime;
+#ifdef _ABIO32
+ unsigned long __unused1;
+#endif
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- unsigned long __unused3;
+ __kernel_time_t msg_rtime;
+#ifdef _ABIO32
+ unsigned long __unused2;
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__kernel_time_t msg_ctime;
+#ifdef _ABIO32
+ unsigned long __unused3;
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
unsigned long msg_cbytes;
unsigned long msg_qnum;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
unsigned long msg_qbytes;
__kernel_pid_t msg_lspid;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__kernel_pid_t msg_lrpid;
unsigned long __unused4;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
unsigned long __unused5;
};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif
diff --git a/libc/kernel/uapi/asm-mips/asm/resource.h b/libc/kernel/uapi/asm-mips/asm/resource.h
index 8761697..ff7cfd5 100644
--- a/libc/kernel/uapi/asm-mips/asm/resource.h
+++ b/libc/kernel/uapi/asm-mips/asm/resource.h
@@ -24,7 +24,10 @@
#define RLIMIT_RSS 7
#define RLIMIT_NPROC 8
#define RLIMIT_MEMLOCK 9
-#define RLIM_INFINITY 0x7fffffffUL
+#ifdef _ABIO32
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define RLIM_INFINITY 0x7fffffffUL
+#endif
#include <asm-generic/resource.h>
#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libc/kernel/uapi/asm-mips/asm/siginfo.h b/libc/kernel/uapi/asm-mips/asm/siginfo.h
index 45b418a..4abc7af 100644
--- a/libc/kernel/uapi/asm-mips/asm/siginfo.h
+++ b/libc/kernel/uapi/asm-mips/asm/siginfo.h
@@ -24,80 +24,82 @@
#define HAVE_ARCH_SIGINFO_T
#define HAVE_ARCH_COPY_SIGINFO
struct siginfo;
-#define __ARCH_SI_PREAMBLE_SIZE (3 * sizeof(int))
+#ifdef _ABIO32
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define __ARCH_SI_PREAMBLE_SIZE (3 * sizeof(int))
+#endif
#ifdef __LP64__
#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif
#include <asm-generic/siginfo.h>
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
typedef struct siginfo {
int si_signo;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
int si_code;
int si_errno;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
int __pad0[SI_MAX_SIZE / sizeof(int) - SI_PAD_SIZE - 3];
union {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
int _pad[SI_PAD_SIZE];
struct {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
pid_t _pid;
__ARCH_SI_UID_T _uid;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
} _kill;
struct {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
timer_t _tid;
int _overrun;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
sigval_t _sigval;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
int _sys_private;
} _timer;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
struct {
pid_t _pid;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__ARCH_SI_UID_T _uid;
sigval_t _sigval;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
} _rt;
struct {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
pid_t _pid;
__ARCH_SI_UID_T _uid;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
int _status;
clock_t _utime;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
clock_t _stime;
} _sigchld;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
struct {
pid_t _pid;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
clock_t _utime;
int _status;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
clock_t _stime;
} _irix_sigchld;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
struct {
void __user *_addr;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#ifdef __ARCH_SI_TRAPNO
int _trapno;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif
short _addr_lsb;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
} _sigfault;
struct {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__ARCH_SI_BAND_T _band;
int _fd;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
} _sigpoll;
} _sifields;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
} siginfo_t;
#undef SI_ASYNCIO
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#undef SI_TIMER
#undef SI_MESGQ
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define SI_ASYNCIO -2
#define SI_TIMER __SI_CODE(__SI_TIMER, -3)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define SI_MESGQ __SI_CODE(__SI_MESGQ, -4)
#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libc/kernel/uapi/asm-mips/asm/types.h b/libc/kernel/uapi/asm-mips/asm/types.h
index 45fea6c..9ef7b7c 100644
--- a/libc/kernel/uapi/asm-mips/asm/types.h
+++ b/libc/kernel/uapi/asm-mips/asm/types.h
@@ -18,11 +18,6 @@
****************************************************************************/
#ifndef _UAPI_ASM_TYPES_H
#define _UAPI_ASM_TYPES_H
-#if _MIPS_SZLONG == 64
-#include <asm-generic/int-l64.h>
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#else
#include <asm-generic/int-ll64.h>
#endif
-#endif
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libc/private/ScopedFd.h b/libc/private/ScopedFd.h
new file mode 100644
index 0000000..e56c139
--- /dev/null
+++ b/libc/private/ScopedFd.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009 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 SCOPED_FD_H
+#define SCOPED_FD_H
+
+#include <unistd.h>
+#include "bionic_macros.h"
+
+// A smart pointer that closes the given fd on going out of scope.
+// Use this when the fd is incidental to the purpose of your function,
+// but needs to be cleaned up on exit.
+class ScopedFd {
+public:
+ explicit ScopedFd(int fd) : fd(fd) {
+ }
+
+ ~ScopedFd() {
+ reset();
+ }
+
+ int get() const {
+ return fd;
+ }
+
+ int release() __attribute__((warn_unused_result)) {
+ int localFd = fd;
+ fd = -1;
+ return localFd;
+ }
+
+ void reset(int new_fd = -1) {
+ if (fd != -1) {
+ TEMP_FAILURE_RETRY(close(fd));
+ }
+ fd = new_fd;
+ }
+
+private:
+ int fd;
+
+ // Disallow copy and assignment.
+ DISALLOW_COPY_AND_ASSIGN(ScopedFd);
+};
+
+#endif // SCOPED_FD_H
diff --git a/libc/private/bionic_macros.h b/libc/private/bionic_macros.h
index 34da501..a3a6985 100644
--- a/libc/private/bionic_macros.h
+++ b/libc/private/bionic_macros.h
@@ -33,4 +33,10 @@
TypeName(); \
DISALLOW_COPY_AND_ASSIGN(TypeName)
+#define BIONIC_ALIGN(value, alignment) \
+ (((value) + (alignment) - 1) & ~((alignment) - 1))
+
+#define BIONIC_ROUND_UP_POWER_OF_2(value) \
+ (1UL << (sizeof(value) * 8 - 1 - __builtin_clz(value)))
+
#endif // _BIONIC_MACROS_H_
diff --git a/libc/private/bionic_time.h b/libc/private/bionic_time.h
index 7c80f59..ca5c146 100644
--- a/libc/private/bionic_time.h
+++ b/libc/private/bionic_time.h
@@ -52,10 +52,11 @@
/*
* Note: you should consider these extensions deprecated and use managed code or icu4c instead.
+ * We'd like to hide them but they're currently still used in frameworks code.
*/
-extern size_t strftime_tz(char* s, size_t max, const char* format, const struct tm* tm, const struct strftime_locale* lc);
-extern time_t mktime_tz(struct tm* const tmp, char const* tz);
-extern void localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz);
+extern size_t strftime_tz(char*, size_t, const char*, const struct tm*, const struct strftime_locale*);
+extern time_t mktime_tz(struct tm* const, char const*);
+extern void localtime_tz(const time_t* const, struct tm*, const char*);
#endif /* _BIONIC_STRFTIME_TZ_DECLARED */
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index b52013f..56a61be 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -31,6 +31,7 @@
#include <sys/cdefs.h>
#include <sys/limits.h>
+#include "bionic_macros.h"
#include "__get_tls.h"
__BEGIN_DECLS
@@ -84,8 +85,6 @@
#define BIONIC_TLS_RESERVED_SLOTS GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT
#endif
-#define BIONIC_ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
-
/*
* Maximum number of elements in the TLS array.
* This includes space for pthread keys and our own internal slots.
diff --git a/libc/private/thread_private.h b/libc/private/thread_private.h
index f731181..724808a 100644
--- a/libc/private/thread_private.h
+++ b/libc/private/thread_private.h
@@ -7,6 +7,8 @@
#include <pthread.h>
+__BEGIN_DECLS
+
/*
* This file defines the thread library interface to libc. Thread
* libraries must implement the functions described here for proper
@@ -31,10 +33,18 @@
#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \
pthread_mutex_unlock( &__THREAD_NAME(name)._private_lock )
-void _thread_atexit_lock(void);
-void _thread_atexit_unlock(void);
+__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()
+__LIBC_HIDDEN__ void _thread_arc4_lock(void);
+__LIBC_HIDDEN__ void _thread_arc4_unlock(void);
+
+#define _ARC4_LOCK() _thread_arc4_lock()
+#define _ARC4_UNLOCK() _thread_arc4_unlock()
+
+__END_DECLS
+
#endif /* _THREAD_PRIVATE_H_ */
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index c607206..05f2faa 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -37,7 +37,6 @@
#include "atexit.h"
#include "private/thread_private.h"
-int __atexit_invalid = 1;
struct atexit *__atexit;
/*
@@ -131,8 +130,6 @@
sizeof(p->fns[0]);
p->next = __atexit;
__atexit = p;
- if (__atexit_invalid)
- __atexit_invalid = 0;
}
fnp = &p->fns[p->ind++];
fnp->cxa_func = func;
@@ -159,8 +156,6 @@
int n, pgsize = getpagesize(), original_ind;
static int call_depth;
- if (__atexit_invalid)
- return;
_ATEXIT_LOCK();
call_depth++;
diff --git a/libc/stdlib/atexit.h b/libc/stdlib/atexit.h
index 2e88ad6..b530ade 100644
--- a/libc/stdlib/atexit.h
+++ b/libc/stdlib/atexit.h
@@ -45,8 +45,7 @@
__BEGIN_DECLS
-extern int __atexit_invalid;
-extern struct atexit *__atexit; /* points to head of LIFO stack */
+__LIBC_HIDDEN__ extern struct atexit *__atexit; /* points to head of LIFO stack */
int __cxa_atexit(void (*)(void *), void *, void *);
void __cxa_finalize(void *);
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 0033652..4dd7ab0 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -74,7 +74,7 @@
#define WILDABBR " "
#endif /* !defined WILDABBR */
-static char wildabbr[] = WILDABBR;
+static const char wildabbr[] = WILDABBR;
static const char gmt[] = "GMT";
@@ -128,16 +128,16 @@
};
struct rule {
- int r_type; /* type of rule--see below */
+ int r_type; /* type of rule; see below */
int r_day; /* day number of rule */
int r_week; /* week number of rule */
int r_mon; /* month number of rule */
int_fast32_t r_time; /* transition time of rule */
};
-#define JULIAN_DAY 0 /* Jn - Julian day */
-#define DAY_OF_YEAR 1 /* n - day of year */
-#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
+#define JULIAN_DAY 0 /* Jn = Julian day */
+#define DAY_OF_YEAR 1 /* n = day of year */
+#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d = month, week, day of week */
/*
** Prototypes for static functions.
@@ -158,10 +158,10 @@
static const char * getoffset(const char * strp, int_fast32_t * offsetp);
static const char * getrule(const char * strp, struct rule * rulep);
static void gmtload(struct state * sp);
-static struct tm * gmtsub(const time_t * timep, const int_fast32_t offset,
- struct tm * tmp, const struct state * sp); // android-changed: added sp.
+static struct tm * gmtsub(const time_t * timep, int_fast32_t offset,
+ struct tm * tmp, struct state * sp); // android-changed: added sp.
static struct tm * localsub(const time_t * timep, int_fast32_t offset,
- struct tm * tmp, const struct state * sp); // android-changed: added sp.
+ struct tm * tmp, struct state * sp); // android-changed: added sp.
static int increment_overflow(int * number, int delta);
static int leaps_thru_end_of(int y) ATTRIBUTE_PURE;
static int increment_overflow32(int_fast32_t * number, int delta);
@@ -173,16 +173,16 @@
static void settzname(void);
static time_t time1(struct tm * tmp,
struct tm * (*funcp)(const time_t *,
- int_fast32_t, struct tm *, const struct state *), // android-changed: added state*.
- int_fast32_t offset, const struct state * sp); // android-changed: added sp.
-static time_t time2(struct tm * const tmp,
- struct tm * (*const funcp)(const time_t *,
- int_fast32_t, struct tm*, const struct state *), // android-changed: added state*.
- int_fast32_t offset, int * okayp, const struct state * sp); // android-changed: added sp.
+ int_fast32_t, struct tm *, struct state *), // android-changed: added state*.
+ int_fast32_t, struct state * sp); // android-changed: added sp.
+static time_t time2(struct tm * tmp,
+ struct tm * (*funcp)(const time_t *,
+ int_fast32_t, struct tm*, struct state *), // android-changed: added state*.
+ int_fast32_t offset, int * okayp, struct state * sp); // android-changed: added sp.
static time_t time2sub(struct tm *tmp,
struct tm * (*funcp) (const time_t *,
- int_fast32_t, struct tm*, const struct state *), // android-changed: added state*.
- int_fast32_t offset, int * okayp, int do_norm_secs, const struct state * sp); // android-change: added sp.
+ int_fast32_t, struct tm*, struct state *), // android-changed: added state*.
+ int_fast32_t offset, int * okayp, int do_norm_secs, struct state * sp); // android-change: added sp.
static struct tm * timesub(const time_t * timep, int_fast32_t offset,
const struct state * sp, struct tm * tmp);
static int tmcomp(const struct tm * atmp,
@@ -217,8 +217,8 @@
static int gmt_is_set;
char * tzname[2] = {
- wildabbr,
- wildabbr
+ (char *) wildabbr,
+ (char *) wildabbr
};
/*
@@ -270,8 +270,7 @@
register struct state * const sp = lclptr;
register int i;
- tzname[0] = wildabbr;
- tzname[1] = wildabbr;
+ tzname[0] = tzname[1] = (char *) wildabbr;
#ifdef USG_COMPAT
daylight = 0;
timezone = 0;
@@ -279,12 +278,10 @@
#ifdef ALTZONE
altzone = 0;
#endif /* defined ALTZONE */
-#ifdef ALL_STATE
if (sp == NULL) {
tzname[0] = tzname[1] = (char *) gmt;
return;
}
-#endif /* defined ALL_STATE */
/*
** And to get the latest zone names into tzname. . .
*/
@@ -356,25 +353,50 @@
2 * sizeof *sp +
4 * TZ_MAX_TIMES];
} u_t;
-#ifdef ALL_STATE
- register u_t * up;
+ union local_storage {
+ /*
+ ** Section 4.9.1 of the C standard says that
+ ** "FILENAME_MAX expands to an integral constant expression
+ ** that is the size needed for an array of char large enough
+ ** to hold the longest file name string that the implementation
+ ** guarantees can be opened."
+ */
+ //char fullname[FILENAME_MAX + 1];
- up = (u_t *) calloc(1, sizeof *up);
- if (up == NULL)
+ /* The main part of the storage for this function. */
+ struct {
+ u_t u;
+ struct state st;
+ } u;
+ };
+ //register char *fullname;
+ register u_t *up;
+ register union local_storage *lsp;
+#ifdef ALL_STATE
+ lsp = malloc(sizeof *lsp);
+ if (!lsp)
return -1;
#else /* !defined ALL_STATE */
- u_t u;
- register u_t * const up = &u;
+ union local_storage ls;
+ lsp = &ls;
#endif /* !defined ALL_STATE */
+ //fullname = lsp->fullname;
+ up = &lsp->u.u;
sp->goback = sp->goahead = FALSE;
- if (name == NULL && (name = TZDEFAULT) == NULL)
- goto oops;
+
+ if (! name) {
+ name = TZDEFAULT;
+ if (! name)
+ goto oops;
+ }
+
int toread;
fid = __bionic_open_tzdata(name, &toread);
if (fid < 0)
goto oops;
- nread = read(fid, up->buf, toread);
+
+ nread = read(fid, up->buf, sizeof up->buf);
if (close(fid) < 0 || nread <= 0)
goto oops;
for (stored = 4; stored <= 8; stored *= 2) {
@@ -506,12 +528,9 @@
if (doextend && nread > 2 &&
up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
sp->typecnt + 2 <= TZ_MAX_TYPES) {
- struct state * ts = malloc(sizeof *ts);
+ struct state *ts = &lsp->u.st;
register int result;
- if (ts == NULL)
- goto oops;
-
up->buf[nread - 1] = '\0';
result = tzparse(&up->buf[1], ts, FALSE);
if (result == 0 && ts->typecnt == 2 &&
@@ -540,7 +559,6 @@
sp->ttis[sp->typecnt++] = ts->ttis[0];
sp->ttis[sp->typecnt++] = ts->ttis[1];
}
- free(ts);
}
if (sp->timecnt > 1) {
for (i = 1; i < sp->timecnt; ++i)
@@ -712,10 +730,10 @@
int num;
/*
- ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
+ ** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
** "M10.4.6/26", which does not conform to Posix,
** but which specifies the equivalent of
- ** ``02:00 on the first Sunday on or after 23 Oct''.
+ ** "02:00 on the first Sunday on or after 23 Oct".
*/
strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
if (strp == NULL)
@@ -729,7 +747,7 @@
*secsp += num * SECSPERMIN;
if (*strp == ':') {
++strp;
- /* `SECSPERMIN' allows for leap seconds. */
+ /* 'SECSPERMIN' allows for leap seconds. */
strp = getnum(strp, &num, 0, SECSPERMIN);
if (strp == NULL)
return NULL;
@@ -927,7 +945,6 @@
register int load_result;
static struct ttinfo zttinfo;
- INITIALIZE(dstname);
stdname = name;
if (lastditch) {
stdlen = strlen(name); /* length of standard zone name */
@@ -1005,6 +1022,7 @@
sp->ttis[1].tt_gmtoff = -stdoffset;
sp->ttis[1].tt_isdst = 0;
sp->ttis[1].tt_abbrind = 0;
+ sp->defaulttype = 0;
timecnt = 0;
janfirst = 0;
yearlim = EPOCH_YEAR + YEARSPERREPEAT;
@@ -1130,6 +1148,7 @@
sp->ttis[1].tt_isdst = TRUE;
sp->ttis[1].tt_abbrind = stdlen + 1;
sp->typecnt = 2;
+ sp->defaulttype = 0;
}
} else {
dstlen = 0;
@@ -1139,6 +1158,7 @@
sp->ttis[0].tt_gmtoff = -stdoffset;
sp->ttis[0].tt_isdst = 0;
sp->ttis[0].tt_abbrind = 0;
+ sp->defaulttype = 0;
}
sp->charcnt = stdlen + 1;
if (dstlen != 0)
@@ -1179,7 +1199,7 @@
#ifdef ALL_STATE
if (lclptr == NULL) {
- lclptr = calloc(1, sizeof *lclptr);
+ lclptr = malloc(sizeof *lclptr);
if (lclptr == NULL) {
settzname(); /* all we can do */
return;
@@ -1196,7 +1216,7 @@
static void
tzset_locked(void)
{
- register const char * name = NULL;
+ register const char * name;
name = getenv("TZ");
@@ -1219,7 +1239,7 @@
#ifdef ALL_STATE
if (lclptr == NULL) {
- lclptr = calloc(1, sizeof *lclptr);
+ lclptr = malloc(sizeof *lclptr);
if (lclptr == NULL) {
settzname(); /* all we can do */
return;
@@ -1263,7 +1283,7 @@
/*ARGSUSED*/
static struct tm *
localsub(const time_t * const timep, const int_fast32_t offset,
- struct tm * const tmp, const struct state * sp) // android-changed: added sp.
+ struct tm * const tmp, struct state * sp) // android-changed: added sp.
{
register const struct ttinfo * ttisp;
register int i;
@@ -1275,10 +1295,8 @@
sp = lclptr;
}
// END android-changed
-#ifdef ALL_STATE
if (sp == NULL)
return gmtsub(timep, offset, tmp, sp); // android-changed: added sp.
-#endif /* defined ALL_STATE */
if ((sp->goback && t < sp->ats[0]) ||
(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
time_t newt = t;
@@ -1371,18 +1389,18 @@
static struct tm *
gmtsub(const time_t * const timep, const int_fast32_t offset,
- struct tm *const tmp, const struct state * sp) // android-changed: added sp.
+ struct tm *const tmp, struct state * sp __unused) // android-changed: added sp.
{
register struct tm * result;
- (void) sp; // android-added: unused.
-
if (!gmt_is_set) {
- gmt_is_set = TRUE;
#ifdef ALL_STATE
- gmtptr = calloc(1, sizeof *gmtptr);
- if (gmtptr != NULL)
+ gmtptr = malloc(sizeof *gmtptr);
+ gmt_is_set = gmtptr != NULL;
+#else
+ gmt_is_set = TRUE;
#endif /* defined ALL_STATE */
+ if (gmt_is_set)
gmtload(gmtptr);
}
result = timesub(timep, offset, gmtptr, tmp);
@@ -1392,18 +1410,7 @@
** "UT+xxxx" or "UT-xxxx" if offset is non-zero,
** but this is no time for a treasure hunt.
*/
- if (offset != 0)
- tmp->TM_ZONE = wildabbr;
- else {
-#ifdef ALL_STATE
- if (gmtptr == NULL)
- tmp->TM_ZONE = gmt;
- else tmp->TM_ZONE = gmtptr->chars;
-#endif /* defined ALL_STATE */
-#ifndef ALL_STATE
- tmp->TM_ZONE = gmtptr->chars;
-#endif /* State Farm */
- }
+ tmp->TM_ZONE = offset ? wildabbr : gmtptr ? gmtptr->chars : gmt;
#endif /* defined TM_ZONE */
return result;
}
@@ -1430,6 +1437,16 @@
return result;
}
+#ifdef STD_INSPIRED
+
+struct tm *
+offtime(const time_t *const timep, const long offset)
+{
+ return gmtsub(timep, offset, &tmGlobal, NULL); // android-changed: extra parameter.
+}
+
+#endif /* defined STD_INSPIRED */
+
/*
** Return the number of leap years through the end of the given year
** where, to make the math easy, the answer for year zero is defined as zero.
@@ -1459,12 +1476,7 @@
corr = 0;
hit = 0;
-#ifdef ALL_STATE
i = (sp == NULL) ? 0 : sp->leapcnt;
-#endif /* defined ALL_STATE */
-#ifndef ALL_STATE
- i = sp->leapcnt;
-#endif /* State Farm */
while (--i >= 0) {
lp = &sp->lsis[i];
if (*timep >= lp->ls_trans) {
@@ -1699,10 +1711,10 @@
static time_t
time2sub(struct tm * const tmp,
- struct tm *(*const funcp)(const time_t*, int_fast32_t, struct tm*, const struct state*),
+ struct tm *(*const funcp)(const time_t*, int_fast32_t, struct tm*, struct state*),
const int_fast32_t offset,
int * const okayp,
- const int do_norm_secs, const struct state * sp) // android-changed: added sp
+ const int do_norm_secs, struct state * sp) // android-changed: added sp
{
register int dir;
register int i, j;
@@ -1837,14 +1849,12 @@
*/
// BEGIN android-changed: support user-supplied sp
if (sp == NULL) {
- sp = (const struct state *)
+ sp = (struct state *)
((funcp == localsub) ? lclptr : gmtptr);
}
// END android-changed
-#ifdef ALL_STATE
if (sp == NULL)
return WRONG;
-#endif /* defined ALL_STATE */
for (i = sp->typecnt - 1; i >= 0; --i) {
if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
continue;
@@ -1880,9 +1890,9 @@
static time_t
time2(struct tm * const tmp,
- struct tm * (*const funcp)(const time_t *, int_fast32_t, struct tm *, const struct state *), // android-changed: added sp.
+ struct tm * (*const funcp)(const time_t *, int_fast32_t, struct tm *, struct state *), // android-changed: added sp.
const int_fast32_t offset,
- int *const okayp, const struct state* sp) // android-changed: added sp.
+ int *const okayp, struct state* sp) // android-changed: added sp.
{
time_t t;
@@ -1897,16 +1907,16 @@
static time_t
time1(struct tm * const tmp,
- struct tm * (* const funcp) (const time_t *, int_fast32_t, struct tm *, const struct state *), // android-changed: added sp.
- const int_fast32_t offset, const struct state * sp) // android-changed: added sp.
+ struct tm * (* const funcp) (const time_t *, int_fast32_t, struct tm *, struct state *), // android-changed: added sp.
+ const int_fast32_t offset, struct state * sp) // android-changed: added sp.
{
register time_t t;
register int samei, otheri;
register int sameind, otherind;
register int i;
register int nseen;
- int seen[TZ_MAX_TYPES];
- int types[TZ_MAX_TYPES];
+ char seen[TZ_MAX_TYPES];
+ unsigned char types[TZ_MAX_TYPES];
int okay;
if (tmp == NULL) {
@@ -1916,17 +1926,15 @@
if (tmp->tm_isdst > 1)
tmp->tm_isdst = 1;
t = time2(tmp, funcp, offset, &okay, sp); // android-changed: added sp.
-#ifdef PCTS
- /*
- ** PCTS code courtesy Grant Sullivan.
- */
if (okay)
return t;
if (tmp->tm_isdst < 0)
+#ifdef PCTS
+ /*
+ ** POSIX Conformance Test Suite code courtesy Grant Sullivan.
+ */
tmp->tm_isdst = 0; /* reset to std and try again */
-#endif /* defined PCTS */
-#ifndef PCTS
- if (okay || tmp->tm_isdst < 0)
+#else
return t;
#endif /* !defined PCTS */
/*
@@ -1937,13 +1945,11 @@
*/
// BEGIN android-changed: support user-supplied sp.
if (sp == NULL) {
- sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr);
+ sp = (struct state *) ((funcp == localsub) ? lclptr : gmtptr);
}
// BEGIN android-changed
-#ifdef ALL_STATE
if (sp == NULL)
return WRONG;
-#endif /* defined ALL_STATE */
for (i = 0; i < sp->typecnt; ++i)
seen[i] = FALSE;
nseen = 0;
@@ -2008,6 +2014,14 @@
return result;
}
+time_t
+timeoff(struct tm *const tmp, const long offset)
+{
+ if (tmp != NULL)
+ tmp->tm_isdst = 0;
+ return time1(tmp, gmtsub, offset, NULL); // android-changed: extra parameter.
+}
+
#endif /* defined STD_INSPIRED */
#ifdef CMUCS
@@ -2279,7 +2293,7 @@
}
// Non-standard API: mktime(3) but with an explicit timezone parameter.
-time_t mktime_tz(struct tm* const tmp, const char* tz) {
+time_t __attribute__((visibility("default"))) mktime_tz(struct tm* const tmp, const char* tz) {
struct state* st = malloc(sizeof(*st));
time_t return_value;
@@ -2296,7 +2310,7 @@
}
// Non-standard API: localtime(3) but with an explicit timezone parameter.
-void localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz) {
+void __attribute__((visibility("default"))) localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz) {
struct state* st = malloc(sizeof(*st));
if (st == NULL)
diff --git a/libc/tzcode/private.h b/libc/tzcode/private.h
index 4eb0ab6..c30c711 100644
--- a/libc/tzcode/private.h
+++ b/libc/tzcode/private.h
@@ -19,7 +19,7 @@
/*
** Defaults for preprocessor symbols.
-** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
+** You can override these in your C compiler options, e.g. '-DHAVE_ADJTIME=0'.
*/
#ifndef HAVE_ADJTIME
@@ -62,9 +62,11 @@
#define HAVE_UTMPX_H 0
#endif /* !defined HAVE_UTMPX_H */
+#if !defined(__ANDROID__)
#ifndef LOCALE_HOME
#define LOCALE_HOME "/usr/lib/locale"
#endif /* !defined LOCALE_HOME */
+#endif // __ANDROID__
#if HAVE_INCOMPATIBLE_CTIME_R
#define asctime_r _incompatible_asctime_r
@@ -120,8 +122,9 @@
*/
#ifndef HAVE_STDINT_H
#define HAVE_STDINT_H \
- (199901 <= __STDC_VERSION__ || \
- 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
+ (199901 <= __STDC_VERSION__ \
+ || 2 < __GLIBC__ + (1 <= __GLIBC_MINOR__) \
+ || __CYGWIN__)
#endif /* !defined HAVE_STDINT_H */
#if HAVE_STDINT_H
@@ -205,6 +208,10 @@
#define INT32_MIN (-1 - INT32_MAX)
#endif /* !defined INT32_MIN */
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t) -1)
+#endif
+
#if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
# define ATTRIBUTE_CONST __attribute__ ((const))
# define ATTRIBUTE_PURE __attribute__ ((__pure__))
@@ -347,29 +354,15 @@
** INITIALIZE(x)
*/
-#ifndef GNUC_or_lint
#ifdef lint
-#define GNUC_or_lint
-#endif /* defined lint */
-#ifndef lint
-#ifdef __GNUC__
-#define GNUC_or_lint
-#endif /* defined __GNUC__ */
-#endif /* !defined lint */
-#endif /* !defined GNUC_or_lint */
-
-#ifndef INITIALIZE
-#ifdef GNUC_or_lint
-#define INITIALIZE(x) ((x) = 0)
-#endif /* defined GNUC_or_lint */
-#ifndef GNUC_or_lint
-#define INITIALIZE(x)
-#endif /* !defined GNUC_or_lint */
-#endif /* !defined INITIALIZE */
+# define INITIALIZE(x) ((x) = 0)
+#else
+# define INITIALIZE(x)
+#endif
/*
** For the benefit of GNU folk...
-** `_(MSGID)' uses the current locale's message library string for MSGID.
+** '_(MSGID)' uses the current locale's message library string for MSGID.
** The default is to use gettext if available, and use MSGID otherwise.
*/
@@ -381,9 +374,9 @@
#endif /* !HAVE_GETTEXT */
#endif /* !defined _ */
-#ifndef TZ_DOMAIN
-#define TZ_DOMAIN "tz"
-#endif /* !defined TZ_DOMAIN */
+#if !defined TZ_DOMAIN && defined TZ_DOMAINDIR
+# define TZ_DOMAIN "tz"
+#endif
#if HAVE_INCOMPATIBLE_CTIME_R
#undef asctime_r
diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c
index 967629d..f996f48 100644
--- a/libc/tzcode/strftime.c
+++ b/libc/tzcode/strftime.c
@@ -1,12 +1,9 @@
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)strftime.c 8.1";
/*
-** Based on the UCB version with the ID appearing below.
+** Based on the UCB version with the copyright notice and sccsid
+** appearing below.
+**
** This is ANSIish only when "multibyte character == plain character".
*/
-#endif /* !defined NOID */
-#endif /* !defined lint */
#include "private.h"
@@ -22,35 +19,27 @@
** by the University of California, Berkeley. The name of the
** University may not be used to endorse or promote products derived
** from this software without specific prior written permission.
-** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+** THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#ifndef LIBC_SCCS
-#ifndef lint
-static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
-#endif /* !defined lint */
-#endif /* !defined LIBC_SCCS */
-
#include "tzfile.h"
#include "fcntl.h"
#include "locale.h"
-#include <ctype.h>
+
+#if __ANDROID__
+/* Android: struct lc_time_T is defined as strftime_locale in "bionic_time.h" */
+#include "private/bionic_time.h" /* for strftime_tz */
+#define lc_time_T strftime_locale
#if defined(__LP64__)
#define time64_t time_t
#define mktime64 mktime
#else
#include <time64.h>
#endif
-#include "private/bionic_time.h" /* for strftime_tz */
-
-/* struct lc_time_T is now defined as strftime_locale
- * in <time.h>
- */
-#if 1
-#define lc_time_T strftime_locale
-#else
+#include <ctype.h>
+#else // not __ANDROID__
struct lc_time_T {
const char * mon[MONSPERYEAR];
const char * month[MONSPERYEAR];
@@ -65,7 +54,15 @@
};
#endif
+#if LOCALE_HOME
+#include "sys/stat.h"
+static struct lc_time_T localebuf;
+static struct lc_time_T * _loc(void);
+#define Locale _loc()
+#endif /* defined LOCALE_HOME */
+#ifndef LOCALE_HOME
#define Locale (&C_time_locale)
+#endif /* !defined LOCALE_HOME */
static const struct lc_time_T C_time_locale = {
{
@@ -147,7 +144,7 @@
}
size_t
-strftime_tz(s, maxsize, format, t, locale)
+__attribute__((visibility("default"))) strftime_tz(s, maxsize, format, t, locale)
char * const s;
const size_t maxsize;
const char * const format;
diff --git a/libc/upstream-freebsd/lib/libc/stdio/mktemp.c b/libc/upstream-freebsd/lib/libc/stdio/mktemp.c
deleted file mode 100644
index 58783dd..0000000
--- a/libc/upstream-freebsd/lib/libc/stdio/mktemp.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 1987, 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.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "namespace.h"
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include "un-namespace.h"
-
-char *_mktemp(char *);
-
-static int _gettemp(char *, int *, int, int);
-
-static const unsigned char padchar[] =
-"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
-int
-mkstemps(char *path, int slen)
-{
- int fd;
-
- return (_gettemp(path, &fd, 0, slen) ? fd : -1);
-}
-
-int
-mkstemp(char *path)
-{
- int fd;
-
- return (_gettemp(path, &fd, 0, 0) ? fd : -1);
-}
-
-char *
-mkdtemp(char *path)
-{
- return (_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL);
-}
-
-char *
-_mktemp(char *path)
-{
- return (_gettemp(path, (int *)NULL, 0, 0) ? path : (char *)NULL);
-}
-
-__warn_references(mktemp,
- "warning: mktemp() possibly used unsafely; consider using mkstemp()");
-
-char *
-mktemp(char *path)
-{
- return (_mktemp(path));
-}
-
-static int
-_gettemp(char *path, int *doopen, int domkdir, int slen)
-{
- char *start, *trv, *suffp, *carryp;
- char *pad;
- struct stat sbuf;
- int rval;
- uint32_t rand;
- char carrybuf[MAXPATHLEN];
-
- if ((doopen != NULL && domkdir) || slen < 0) {
- errno = EINVAL;
- return (0);
- }
-
- for (trv = path; *trv != '\0'; ++trv)
- ;
- if (trv - path >= MAXPATHLEN) {
- errno = ENAMETOOLONG;
- return (0);
- }
- trv -= slen;
- suffp = trv;
- --trv;
- if (trv < path || NULL != strchr(suffp, '/')) {
- errno = EINVAL;
- return (0);
- }
-
- /* Fill space with random characters */
- while (trv >= path && *trv == 'X') {
- rand = arc4random_uniform(sizeof(padchar) - 1);
- *trv-- = padchar[rand];
- }
- start = trv + 1;
-
- /* save first combination of random characters */
- memcpy(carrybuf, start, suffp - start);
-
- /*
- * check the target directory.
- */
- if (doopen != NULL || domkdir) {
- for (; trv > path; --trv) {
- if (*trv == '/') {
- *trv = '\0';
- rval = stat(path, &sbuf);
- *trv = '/';
- if (rval != 0)
- return (0);
- if (!S_ISDIR(sbuf.st_mode)) {
- errno = ENOTDIR;
- return (0);
- }
- break;
- }
- }
- }
-
- for (;;) {
- if (doopen) {
- if ((*doopen =
- _open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
- return (1);
- if (errno != EEXIST)
- return (0);
- } else if (domkdir) {
- if (mkdir(path, 0700) == 0)
- return (1);
- if (errno != EEXIST)
- return (0);
- } else if (lstat(path, &sbuf))
- return (errno == ENOENT);
-
- /* If we have a collision, cycle through the space of filenames */
- for (trv = start, carryp = carrybuf;;) {
- /* have we tried all possible permutations? */
- if (trv == suffp)
- return (0); /* yes - exit with EEXIST */
- pad = strchr(padchar, *trv);
- if (pad == NULL) {
- /* this should never happen */
- errno = EIO;
- return (0);
- }
- /* increment character */
- *trv = (*++pad == '\0') ? padchar[0] : *pad;
- /* carry to next position? */
- if (*trv == *carryp) {
- /* increment position and loop */
- ++trv;
- ++carryp;
- } else {
- /* try with new name */
- break;
- }
- }
- }
- /*NOTREACHED*/
-}
diff --git a/libc/include/sys/sha1.h b/libc/upstream-netbsd/android/include/sys/sha1.h
similarity index 100%
rename from libc/include/sys/sha1.h
rename to libc/upstream-netbsd/android/include/sys/sha1.h
diff --git a/libc/upstream-netbsd/lib/libc/include/resolv_mt.h b/libc/upstream-netbsd/lib/libc/include/resolv_mt.h
new file mode 100644
index 0000000..73a8dcc
--- /dev/null
+++ b/libc/upstream-netbsd/lib/libc/include/resolv_mt.h
@@ -0,0 +1,49 @@
+/* $NetBSD: resolv_mt.h,v 1.1.1.3 2009/04/12 16:35:44 christos Exp $ */
+
+#ifndef _RESOLV_MT_H
+#define _RESOLV_MT_H
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+/* Access functions for the libresolv private interface */
+
+int __res_enable_mt(void);
+int __res_disable_mt(void);
+
+/* Per-thread context */
+
+typedef struct {
+int no_hosts_fallback_private;
+int retry_save;
+int retry_private;
+char inet_nsap_ntoa_tmpbuf[255*3];
+char sym_ntos_unname[20];
+char sym_ntop_unname[20];
+char p_option_nbuf[40];
+char p_time_nbuf[40];
+char precsize_ntoa_retbuf[sizeof "90000000.00"];
+char loc_ntoa_tmpbuf[sizeof
+"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
+char p_secstodate_output[15];
+} mtctxres_t;
+
+/* Thread-specific data (TSD) */
+
+mtctxres_t *___mtctxres(void);
+#define mtctxres (___mtctxres())
+
+/* Various static data that should be TSD */
+
+#define sym_ntos_unname (mtctxres->sym_ntos_unname)
+#define sym_ntop_unname (mtctxres->sym_ntop_unname)
+#define inet_nsap_ntoa_tmpbuf (mtctxres->inet_nsap_ntoa_tmpbuf)
+#define p_option_nbuf (mtctxres->p_option_nbuf)
+#define p_time_nbuf (mtctxres->p_time_nbuf)
+#define precsize_ntoa_retbuf (mtctxres->precsize_ntoa_retbuf)
+#define loc_ntoa_tmpbuf (mtctxres->loc_ntoa_tmpbuf)
+#define p_secstodate_output (mtctxres->p_secstodate_output)
+
+#endif /* _RESOLV_MT_H */
diff --git a/libc/dns/inet/nsap_addr.c b/libc/upstream-netbsd/lib/libc/inet/nsap_addr.c
similarity index 81%
rename from libc/dns/inet/nsap_addr.c
rename to libc/upstream-netbsd/lib/libc/inet/nsap_addr.c
index 4deabac..8633205 100644
--- a/libc/dns/inet/nsap_addr.c
+++ b/libc/upstream-netbsd/lib/libc/inet/nsap_addr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: nsap_addr.c,v 1.2 2004/05/20 23:12:33 christos Exp $ */
+/* $NetBSD: nsap_addr.c,v 1.6 2009/04/12 17:07:17 christos Exp $ */
/*
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
@@ -20,12 +20,15 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static const char rcsid[] = "Id: nsap_addr.c,v 1.2.206.1 2004/03/09 08:33:33 marka Exp";
+static const char rcsid[] = "Id: nsap_addr.c,v 1.5 2005/07/28 06:51:48 marka Exp";
#else
-__RCSID("$NetBSD: nsap_addr.c,v 1.2 2004/05/20 23:12:33 christos Exp $");
+__RCSID("$NetBSD: nsap_addr.c,v 1.6 2009/04/12 17:07:17 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
+#include "port_before.h"
+
+#include "namespace.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
@@ -36,10 +39,14 @@
#include <assert.h>
#include <ctype.h>
-#ifdef ANDROID_CHANGES
-#include "resolv_private.h"
-#else
#include <resolv.h>
+#include <resolv_mt.h>
+
+#include "port_after.h"
+
+#ifdef __weak_alias
+__weak_alias(inet_nsap_addr,_inet_nsap_addr)
+__weak_alias(inet_nsap_ntoa,_inet_nsap_ntoa)
#endif
static char
@@ -52,8 +59,8 @@
u_char c, nib;
u_int len = 0;
- assert(ascii != NULL);
- assert(binary != NULL);
+ _DIAGASSERT(ascii != NULL);
+ _DIAGASSERT(binary != NULL);
if (ascii[0] != '0' || (ascii[1] != 'x' && ascii[1] != 'X'))
return (0);
@@ -90,10 +97,10 @@
inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) {
int nib;
int i;
- static char tmpbuf[2+255*3];
+ char *tmpbuf = inet_nsap_ntoa_tmpbuf;
char *start;
- assert(binary != NULL);
+ _DIAGASSERT(binary != NULL);
if (ascii)
start = ascii;
@@ -119,3 +126,5 @@
*ascii = '\0';
return (start);
}
+
+/*! \file */
diff --git a/libc/upstream-netbsd/lib/libc/resolv/mtctxres.c b/libc/upstream-netbsd/lib/libc/resolv/mtctxres.c
new file mode 100644
index 0000000..6e3281a
--- /dev/null
+++ b/libc/upstream-netbsd/lib/libc/resolv/mtctxres.c
@@ -0,0 +1,130 @@
+/* $NetBSD: mtctxres.c,v 1.4 2007/03/30 20:40:52 ghen Exp $ */
+
+#include <port_before.h>
+#ifdef DO_PTHREADS
+#include <pthread.h>
+#endif
+#include <errno.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <resolv_mt.h>
+#include <port_after.h>
+
+#ifdef DO_PTHREADS
+static pthread_key_t key;
+static int mt_key_initialized = 0;
+
+static int __res_init_ctx(void);
+static void __res_destroy_ctx(void *);
+
+#if defined(sun) && !defined(__GNUC__)
+#pragma init (_mtctxres_init)
+#endif
+#endif
+
+static mtctxres_t sharedctx;
+
+#ifdef DO_PTHREADS
+/*
+ * Initialize the TSD key. By doing this at library load time, we're
+ * implicitly running without interference from other threads, so there's
+ * no need for locking.
+ */
+static void
+_mtctxres_init(void) {
+ int pthread_keycreate_ret;
+
+ pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx);
+ if (pthread_keycreate_ret == 0)
+ mt_key_initialized = 1;
+}
+#endif
+
+/*
+ * To support binaries that used the private MT-safe interface in
+ * Solaris 8, we still need to provide the __res_enable_mt()
+ * and __res_disable_mt() entry points. They're do-nothing routines.
+ */
+int
+__res_enable_mt(void) {
+ return (-1);
+}
+
+int
+__res_disable_mt(void) {
+ return (0);
+}
+
+#ifdef DO_PTHREADS
+static int
+__res_init_ctx(void) {
+
+ mtctxres_t *mt;
+ int ret;
+
+
+ if (pthread_getspecific(key) != 0) {
+ /* Already exists */
+ return (0);
+ }
+
+ if ((mt = malloc(sizeof (mtctxres_t))) == 0) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ memset(mt, 0, sizeof (mtctxres_t));
+
+ if ((ret = pthread_setspecific(key, mt)) != 0) {
+ free(mt);
+ errno = ret;
+ return (-1);
+ }
+
+ return (0);
+}
+
+static void
+__res_destroy_ctx(void *value) {
+
+ mtctxres_t *mt = (mtctxres_t *)value;
+
+ if (mt != 0)
+ free(mt);
+}
+#endif
+
+mtctxres_t *
+___mtctxres(void) {
+#ifdef DO_PTHREADS
+ mtctxres_t *mt;
+
+ /*
+ * This if clause should only be executed if we are linking
+ * statically. When linked dynamically _mtctxres_init() should
+ * be called at binding time due the #pragma above.
+ */
+ if (!mt_key_initialized) {
+ static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER;
+ if (pthread_mutex_lock(&keylock) == 0) {
+ _mtctxres_init();
+ (void) pthread_mutex_unlock(&keylock);
+ }
+ }
+
+ /*
+ * If we have already been called in this thread return the existing
+ * context. Otherwise recreat a new context and return it. If
+ * that fails return a global context.
+ */
+ if (mt_key_initialized) {
+ if (((mt = pthread_getspecific(key)) != 0) ||
+ (__res_init_ctx() == 0 &&
+ (mt = pthread_getspecific(key)) != 0)) {
+ return (mt);
+ }
+ }
+#endif
+ return (&sharedctx);
+}
diff --git a/libc/upstream-openbsd/lib/libc/crypt/chacha_private.h b/libc/upstream-openbsd/lib/libc/crypt/chacha_private.h
new file mode 100644
index 0000000..7c3680f
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/crypt/chacha_private.h
@@ -0,0 +1,222 @@
+/*
+chacha-merged.c version 20080118
+D. J. Bernstein
+Public domain.
+*/
+
+/* $OpenBSD: chacha_private.h,v 1.2 2013/10/04 07:02:27 djm Exp $ */
+
+typedef unsigned char u8;
+typedef unsigned int u32;
+
+typedef struct
+{
+ u32 input[16]; /* could be compressed */
+} chacha_ctx;
+
+#define U8C(v) (v##U)
+#define U32C(v) (v##U)
+
+#define U8V(v) ((u8)(v) & U8C(0xFF))
+#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
+
+#define ROTL32(v, n) \
+ (U32V((v) << (n)) | ((v) >> (32 - (n))))
+
+#define U8TO32_LITTLE(p) \
+ (((u32)((p)[0]) ) | \
+ ((u32)((p)[1]) << 8) | \
+ ((u32)((p)[2]) << 16) | \
+ ((u32)((p)[3]) << 24))
+
+#define U32TO8_LITTLE(p, v) \
+ do { \
+ (p)[0] = U8V((v) ); \
+ (p)[1] = U8V((v) >> 8); \
+ (p)[2] = U8V((v) >> 16); \
+ (p)[3] = U8V((v) >> 24); \
+ } while (0)
+
+#define ROTATE(v,c) (ROTL32(v,c))
+#define XOR(v,w) ((v) ^ (w))
+#define PLUS(v,w) (U32V((v) + (w)))
+#define PLUSONE(v) (PLUS((v),1))
+
+#define QUARTERROUND(a,b,c,d) \
+ a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
+ c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
+ a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
+ c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
+
+static const char sigma[16] = "expand 32-byte k";
+static const char tau[16] = "expand 16-byte k";
+
+static void
+chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
+{
+ const char *constants;
+
+ x->input[4] = U8TO32_LITTLE(k + 0);
+ x->input[5] = U8TO32_LITTLE(k + 4);
+ x->input[6] = U8TO32_LITTLE(k + 8);
+ x->input[7] = U8TO32_LITTLE(k + 12);
+ if (kbits == 256) { /* recommended */
+ k += 16;
+ constants = sigma;
+ } else { /* kbits == 128 */
+ constants = tau;
+ }
+ x->input[8] = U8TO32_LITTLE(k + 0);
+ x->input[9] = U8TO32_LITTLE(k + 4);
+ x->input[10] = U8TO32_LITTLE(k + 8);
+ x->input[11] = U8TO32_LITTLE(k + 12);
+ x->input[0] = U8TO32_LITTLE(constants + 0);
+ x->input[1] = U8TO32_LITTLE(constants + 4);
+ x->input[2] = U8TO32_LITTLE(constants + 8);
+ x->input[3] = U8TO32_LITTLE(constants + 12);
+}
+
+static void
+chacha_ivsetup(chacha_ctx *x,const u8 *iv)
+{
+ x->input[12] = 0;
+ x->input[13] = 0;
+ x->input[14] = U8TO32_LITTLE(iv + 0);
+ x->input[15] = U8TO32_LITTLE(iv + 4);
+}
+
+static void
+chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
+{
+ u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
+ u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
+ u8 *ctarget = NULL;
+ u8 tmp[64];
+ u_int i;
+
+ if (!bytes) return;
+
+ j0 = x->input[0];
+ j1 = x->input[1];
+ j2 = x->input[2];
+ j3 = x->input[3];
+ j4 = x->input[4];
+ j5 = x->input[5];
+ j6 = x->input[6];
+ j7 = x->input[7];
+ j8 = x->input[8];
+ j9 = x->input[9];
+ j10 = x->input[10];
+ j11 = x->input[11];
+ j12 = x->input[12];
+ j13 = x->input[13];
+ j14 = x->input[14];
+ j15 = x->input[15];
+
+ for (;;) {
+ if (bytes < 64) {
+ for (i = 0;i < bytes;++i) tmp[i] = m[i];
+ m = tmp;
+ ctarget = c;
+ c = tmp;
+ }
+ x0 = j0;
+ x1 = j1;
+ x2 = j2;
+ x3 = j3;
+ x4 = j4;
+ x5 = j5;
+ x6 = j6;
+ x7 = j7;
+ x8 = j8;
+ x9 = j9;
+ x10 = j10;
+ x11 = j11;
+ x12 = j12;
+ x13 = j13;
+ x14 = j14;
+ x15 = j15;
+ for (i = 20;i > 0;i -= 2) {
+ QUARTERROUND( x0, x4, x8,x12)
+ QUARTERROUND( x1, x5, x9,x13)
+ QUARTERROUND( x2, x6,x10,x14)
+ QUARTERROUND( x3, x7,x11,x15)
+ QUARTERROUND( x0, x5,x10,x15)
+ QUARTERROUND( x1, x6,x11,x12)
+ QUARTERROUND( x2, x7, x8,x13)
+ QUARTERROUND( x3, x4, x9,x14)
+ }
+ x0 = PLUS(x0,j0);
+ x1 = PLUS(x1,j1);
+ x2 = PLUS(x2,j2);
+ x3 = PLUS(x3,j3);
+ x4 = PLUS(x4,j4);
+ x5 = PLUS(x5,j5);
+ x6 = PLUS(x6,j6);
+ x7 = PLUS(x7,j7);
+ x8 = PLUS(x8,j8);
+ x9 = PLUS(x9,j9);
+ x10 = PLUS(x10,j10);
+ x11 = PLUS(x11,j11);
+ x12 = PLUS(x12,j12);
+ x13 = PLUS(x13,j13);
+ x14 = PLUS(x14,j14);
+ x15 = PLUS(x15,j15);
+
+#ifndef KEYSTREAM_ONLY
+ x0 = XOR(x0,U8TO32_LITTLE(m + 0));
+ x1 = XOR(x1,U8TO32_LITTLE(m + 4));
+ x2 = XOR(x2,U8TO32_LITTLE(m + 8));
+ x3 = XOR(x3,U8TO32_LITTLE(m + 12));
+ x4 = XOR(x4,U8TO32_LITTLE(m + 16));
+ x5 = XOR(x5,U8TO32_LITTLE(m + 20));
+ x6 = XOR(x6,U8TO32_LITTLE(m + 24));
+ x7 = XOR(x7,U8TO32_LITTLE(m + 28));
+ x8 = XOR(x8,U8TO32_LITTLE(m + 32));
+ x9 = XOR(x9,U8TO32_LITTLE(m + 36));
+ x10 = XOR(x10,U8TO32_LITTLE(m + 40));
+ x11 = XOR(x11,U8TO32_LITTLE(m + 44));
+ x12 = XOR(x12,U8TO32_LITTLE(m + 48));
+ x13 = XOR(x13,U8TO32_LITTLE(m + 52));
+ x14 = XOR(x14,U8TO32_LITTLE(m + 56));
+ x15 = XOR(x15,U8TO32_LITTLE(m + 60));
+#endif
+
+ j12 = PLUSONE(j12);
+ if (!j12) {
+ j13 = PLUSONE(j13);
+ /* stopping at 2^70 bytes per nonce is user's responsibility */
+ }
+
+ U32TO8_LITTLE(c + 0,x0);
+ U32TO8_LITTLE(c + 4,x1);
+ U32TO8_LITTLE(c + 8,x2);
+ U32TO8_LITTLE(c + 12,x3);
+ U32TO8_LITTLE(c + 16,x4);
+ U32TO8_LITTLE(c + 20,x5);
+ U32TO8_LITTLE(c + 24,x6);
+ U32TO8_LITTLE(c + 28,x7);
+ U32TO8_LITTLE(c + 32,x8);
+ U32TO8_LITTLE(c + 36,x9);
+ U32TO8_LITTLE(c + 40,x10);
+ U32TO8_LITTLE(c + 44,x11);
+ U32TO8_LITTLE(c + 48,x12);
+ U32TO8_LITTLE(c + 52,x13);
+ U32TO8_LITTLE(c + 56,x14);
+ U32TO8_LITTLE(c + 60,x15);
+
+ if (bytes <= 64) {
+ if (bytes < 64) {
+ for (i = 0;i < bytes;++i) ctarget[i] = c[i];
+ }
+ x->input[12] = j12;
+ x->input[13] = j13;
+ return;
+ }
+ bytes -= 64;
+ c += 64;
+#ifndef KEYSTREAM_ONLY
+ m += 64;
+#endif
+ }
+}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/mktemp.c b/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
new file mode 100644
index 0000000..cb154c4
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
@@ -0,0 +1,143 @@
+/* $OpenBSD: mktemp.c,v 1.33 2014/05/06 22:55:27 millert Exp $ */
+/*
+ * Copyright (c) 1996-1998, 2008 Theo de Raadt
+ * Copyright (c) 1997, 2008-2009 Todd C. Miller
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#define MKTEMP_NAME 0
+#define MKTEMP_FILE 1
+#define MKTEMP_DIR 2
+
+#define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+#define NUM_CHARS (sizeof(TEMPCHARS) - 1)
+#define MIN_X 6
+
+#ifndef nitems
+#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
+#endif
+
+static int
+mktemp_internal(char *path, int slen, int mode)
+{
+ char *start, *cp, *ep;
+ const char *tempchars = TEMPCHARS;
+ unsigned int tries;
+ struct stat sb;
+ size_t len;
+ int fd;
+
+ len = strlen(path);
+ if (len < MIN_X || slen < 0 || (size_t)slen > len - MIN_X) {
+ errno = EINVAL;
+ return(-1);
+ }
+ ep = path + len - slen;
+
+ for (start = ep; start > path && start[-1] == 'X'; start--)
+ ;
+ if (ep - start < MIN_X) {
+ errno = EINVAL;
+ return(-1);
+ }
+
+ tries = INT_MAX;
+ do {
+ cp = start;
+ do {
+ unsigned short rbuf[16];
+ unsigned int i;
+
+ /*
+ * Avoid lots of arc4random() calls by using
+ * a buffer sized for up to 16 Xs at a time.
+ */
+ arc4random_buf(rbuf, sizeof(rbuf));
+ for (i = 0; i < nitems(rbuf) && cp != ep; i++)
+ *cp++ = tempchars[rbuf[i] % NUM_CHARS];
+ } while (cp != ep);
+
+ switch (mode) {
+ case MKTEMP_NAME:
+ if (lstat(path, &sb) != 0)
+ return(errno == ENOENT ? 0 : -1);
+ break;
+ case MKTEMP_FILE:
+ fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
+ if (fd != -1 || errno != EEXIST)
+ return(fd);
+ break;
+ case MKTEMP_DIR:
+ if (mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR) == 0)
+ return(0);
+ if (errno != EEXIST)
+ return(-1);
+ break;
+ }
+ } while (--tries);
+
+ errno = EEXIST;
+ return(-1);
+}
+
+char *_mktemp(char *);
+
+char *
+_mktemp(char *path)
+{
+ if (mktemp_internal(path, 0, MKTEMP_NAME) == -1)
+ return(NULL);
+ return(path);
+}
+
+__warn_references(mktemp,
+ "warning: mktemp() possibly used unsafely; consider using mkstemp()");
+
+char *
+mktemp(char *path)
+{
+ return(_mktemp(path));
+}
+
+int
+mkstemp(char *path)
+{
+ return(mktemp_internal(path, 0, MKTEMP_FILE));
+}
+
+int
+mkstemps(char *path, int slen)
+{
+ return(mktemp_internal(path, slen, MKTEMP_FILE));
+}
+
+char *
+mkdtemp(char *path)
+{
+ int error;
+
+ error = mktemp_internal(path, 0, MKTEMP_DIR);
+ return(error ? NULL : path);
+}
diff --git a/libm/Android.mk b/libm/Android.mk
index 90b4906..994caa0 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -291,5 +291,12 @@
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_SYSTEM_SHARED_LIBRARIES := libc
LOCAL_WHOLE_STATIC_LIBRARIES := libm
+
+# We'd really like to do this for all architectures, but since this wasn't done
+# before, these symbols must continue to be exported on LP32 for binary
+# compatibility.
+LOCAL_LDFLAGS_arm64 := -Wl,--exclude-libs,libgcc.a
+LOCAL_LDFLAGS_mips64 := -Wl,--exclude-libs,libgcc.a
+LOCAL_LDFLAGS_x86_64 := -Wl,--exclude-libs,libgcc.a
include $(BUILD_SHARED_LIBRARY)
endif
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 6d63ad6..efb829e 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -100,30 +100,23 @@
soinfo* found = NULL;
ElfW(Sym)* sym = NULL;
- if (handle == RTLD_DEFAULT || handle == (void*)0xffffffffL) {
- sym = dlsym_linear_lookup(symbol, &found, NULL);
- } else if (handle == RTLD_NEXT || handle == (void*)0xfffffffeL) {
- void* caller_addr = __builtin_return_address(0);
- soinfo* si = find_containing_library(caller_addr);
+ void* caller_addr = __builtin_return_address(0);
+ soinfo* caller_si = find_containing_library(caller_addr);
+ if (handle == RTLD_DEFAULT) {
+ sym = dlsym_linear_lookup(symbol, &found, NULL, caller_si);
+ } else if (handle == RTLD_NEXT) {
sym = NULL;
- if (si && si->next) {
- sym = dlsym_linear_lookup(symbol, &found, si->next);
+ if (caller_si && caller_si->next) {
+ sym = dlsym_linear_lookup(symbol, &found, caller_si->next, caller_si);
}
} else {
found = reinterpret_cast<soinfo*>(handle);
- sym = dlsym_handle_lookup(found, symbol);
+ sym = dlsym_handle_lookup(found, symbol, caller_si);
}
- if (sym != NULL) {
- unsigned bind = ELF_ST_BIND(sym->st_info);
-
- if (bind == STB_GLOBAL && sym->st_shndx != 0) {
- return reinterpret_cast<void*>(sym->st_value + found->load_bias);
- }
-
- __bionic_format_dlerror("symbol found but not global", symbol);
- return NULL;
+ if (sym != NULL && sym->st_shndx != 0) {
+ return reinterpret_cast<void*>(sym->st_value + found->load_bias);
} else {
__bionic_format_dlerror("undefined symbol", symbol);
return NULL;
diff --git a/linker/linker.cpp b/linker/linker.cpp
index a22233d..506c3f2 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -42,6 +42,7 @@
#include "private/bionic_tls.h"
#include "private/KernelArgumentBlock.h"
#include "private/ScopedPthreadMutexLocker.h"
+#include "private/ScopedFd.h"
#include "linker.h"
#include "linker_debug.h"
@@ -124,6 +125,11 @@
kRelocMax
};
+enum class SymbolLookupScope {
+ kAllowLocal,
+ kExcludeLocal,
+};
+
#if STATS
struct linker_stats_t {
int count[kRelocMax];
@@ -162,10 +168,7 @@
#define DISALLOW_ALLOCATION(return_type, name, ...) \
return_type name __VA_ARGS__ \
{ \
- const char* msg = "ERROR: " #name " called from the dynamic linker!\n"; \
- __libc_format_log(ANDROID_LOG_FATAL, "linker", "%s", msg); \
- write(2, msg, strlen(msg)); \
- abort(); \
+ __libc_fatal("ERROR: " #name " called from the dynamic linker!\n"); \
}
DISALLOW_ALLOCATION(void*, malloc, (size_t u __unused));
DISALLOW_ALLOCATION(void, free, (void* u __unused));
@@ -430,7 +433,7 @@
return rv;
}
-static ElfW(Sym)* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name) {
+static ElfW(Sym)* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name, const SymbolLookupScope& lookup_scope) {
ElfW(Sym)* symtab = si->symtab;
const char* strtab = si->strtab;
@@ -441,18 +444,28 @@
ElfW(Sym)* s = symtab + n;
if (strcmp(strtab + s->st_name, name)) continue;
- /* only concern ourselves with global and weak symbol definitions */
switch (ELF_ST_BIND(s->st_info)) {
case STB_GLOBAL:
case STB_WEAK:
if (s->st_shndx == SHN_UNDEF) {
- continue;
- }
+ continue;
+ }
- TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
+ TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
name, si->name, reinterpret_cast<void*>(s->st_value),
static_cast<size_t>(s->st_size));
- return s;
+ return s;
+ case STB_LOCAL:
+ if (lookup_scope != SymbolLookupScope::kAllowLocal) {
+ continue;
+ }
+ TRACE_TYPE(LOOKUP, "FOUND LOCAL %s in %s (%p) %zd",
+ name, si->name, reinterpret_cast<void*>(s->st_value),
+ static_cast<size_t>(s->st_size));
+ return s;
+ default:
+ __libc_fatal("ERROR: Unexpected ST_BIND value: %d for '%s' in '%s'",
+ ELF_ST_BIND(s->st_info), name, si->name);
}
}
@@ -483,7 +496,7 @@
*/
if (si == somain) {
- s = soinfo_elf_lookup(si, elf_hash, name);
+ s = soinfo_elf_lookup(si, elf_hash, name, SymbolLookupScope::kAllowLocal);
if (s != NULL) {
*lsi = si;
goto done;
@@ -500,7 +513,7 @@
if (!si->has_DT_SYMBOLIC) {
DEBUG("%s: looking up %s in executable %s",
si->name, name, somain->name);
- s = soinfo_elf_lookup(somain, elf_hash, name);
+ s = soinfo_elf_lookup(somain, elf_hash, name, SymbolLookupScope::kExcludeLocal);
if (s != NULL) {
*lsi = somain;
goto done;
@@ -517,7 +530,7 @@
* and some the first non-weak definition. This is system dependent.
* Here we return the first definition found for simplicity. */
- s = soinfo_elf_lookup(si, elf_hash, name);
+ s = soinfo_elf_lookup(si, elf_hash, name, SymbolLookupScope::kAllowLocal);
if (s != NULL) {
*lsi = si;
goto done;
@@ -531,7 +544,7 @@
if (si->has_DT_SYMBOLIC) {
DEBUG("%s: looking up %s in executable %s after local scope",
si->name, name, somain->name);
- s = soinfo_elf_lookup(somain, elf_hash, name);
+ s = soinfo_elf_lookup(somain, elf_hash, name, SymbolLookupScope::kExcludeLocal);
if (s != NULL) {
*lsi = somain;
goto done;
@@ -542,7 +555,7 @@
/* Next, look for it in the preloads list */
for (int i = 0; g_ld_preloads[i] != NULL; i++) {
- s = soinfo_elf_lookup(g_ld_preloads[i], elf_hash, name);
+ s = soinfo_elf_lookup(g_ld_preloads[i], elf_hash, name, SymbolLookupScope::kExcludeLocal);
if (s != NULL) {
*lsi = g_ld_preloads[i];
goto done;
@@ -552,7 +565,7 @@
for (int i = 0; needed[i] != NULL; i++) {
DEBUG("%s: looking up %s in %s",
si->name, name, needed[i]->name);
- s = soinfo_elf_lookup(needed[i], elf_hash, name);
+ s = soinfo_elf_lookup(needed[i], elf_hash, name, SymbolLookupScope::kExcludeLocal);
if (s != NULL) {
*lsi = needed[i];
goto done;
@@ -581,8 +594,9 @@
Binary Interface) where in Chapter 5 it discuss resolving "Shared
Object Dependencies" in breadth first search order.
*/
-ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name) {
- return soinfo_elf_lookup(si, elfhash(name), name);
+ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name, soinfo* caller) {
+ return soinfo_elf_lookup(si, elfhash(name), name,
+ caller == si ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
}
/* This is used by dlsym(3) to performs a global symbol lookup. If the
@@ -590,7 +604,7 @@
beginning of the global solist. Otherwise the search starts at the
specified soinfo (for RTLD_NEXT).
*/
-ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start) {
+ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start, soinfo* caller) {
unsigned elf_hash = elfhash(name);
if (start == NULL) {
@@ -599,7 +613,8 @@
ElfW(Sym)* s = NULL;
for (soinfo* si = start; (s == NULL) && (si != NULL); si = si->next) {
- s = soinfo_elf_lookup(si, elf_hash, name);
+ s = soinfo_elf_lookup(si, elf_hash, name,
+ caller == si ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
if (s != NULL) {
*found = si;
break;
@@ -668,8 +683,7 @@
}
// ...but nvidia binary blobs (at least) rely on this behavior, so fall through for now.
#if defined(__LP64__)
- // TODO: uncomment this after bug b/7465467 is fixed.
- // return -1;
+ return -1;
#endif
}
@@ -682,11 +696,20 @@
}
static soinfo* load_library(const char* name, int dlflags, const android_dlextinfo* extinfo) {
- // Open the file.
- int fd = open_library(name);
- if (fd == -1) {
+ int fd = -1;
+ ScopedFd file_guard(-1);
+
+ if (extinfo != NULL && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
+ fd = extinfo->library_fd;
+ } else {
+ // Open the file.
+ fd = open_library(name);
+ if (fd == -1) {
DL_ERR("library \"%s\" not found", name);
return NULL;
+ }
+
+ file_guard.reset(fd);
}
ElfReader elf_reader(name, fd);
@@ -730,7 +753,7 @@
// At this point we know that whatever is loaded @ base is a valid ELF
// shared library whose segments are properly mapped in.
- TRACE("[ find_library_internal base=%p size=%zu name='%s' ]",
+ TRACE("[ load_library base=%p size=%zu name='%s' ]",
reinterpret_cast<void*>(si->base), si->size, si->name);
if (!soinfo_link_image(si, extinfo)) {
@@ -1863,10 +1886,8 @@
if (si->has_text_relocations) {
// Make segments writable to allow text relocations to work properly. We will later call
// phdr_table_protect_segments() after all of them are applied and all constructors are run.
-#if !defined(__i386__) // The platform itself has too many text relocations on x86.
DL_WARN("%s has text relocations. This is wasting memory and prevents "
"security hardening. Please fix.", si->name);
-#endif
if (phdr_table_unprotect_segments(si->phdr, si->phnum, si->load_bias) < 0) {
DL_ERR("can't unprotect loadable segments for \"%s\": %s",
si->name, strerror(errno));
diff --git a/linker/linker.h b/linker/linker.h
index 0a72d92..e1112e6 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -234,11 +234,11 @@
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo);
void do_dlclose(soinfo* si);
-ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start);
+ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* start, soinfo* caller_si);
soinfo* find_containing_library(const void* addr);
ElfW(Sym)* dladdr_find_symbol(soinfo* si, const void* addr);
-ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name);
+ElfW(Sym)* dlsym_handle_lookup(soinfo* si, const char* name, soinfo* caller_si);
void debuggerd_init();
extern "C" abort_msg_t* g_abort_message;
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 12e9779..11585af 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -127,9 +127,6 @@
}
ElfReader::~ElfReader() {
- if (fd_ != -1) {
- close(fd_);
- }
if (phdr_mmap_ != NULL) {
munmap(phdr_mmap_, phdr_size_);
}
diff --git a/linker/tests/Android.mk b/linker/tests/Android.mk
index 683f9ee..fe64e77 100644
--- a/linker/tests/Android.mk
+++ b/linker/tests/Android.mk
@@ -19,7 +19,6 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_MULTILIB := both
LOCAL_MODULE := linker-unit-tests
LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
diff --git a/tests/Android.build.mk b/tests/Android.build.mk
index 6433d55..bb00648 100644
--- a/tests/Android.build.mk
+++ b/tests/Android.build.mk
@@ -21,14 +21,15 @@
ifeq ($(build_type),host)
# Always make host multilib
LOCAL_MULTILIB := both
-else
-LOCAL_MULTILIB := $($(module)_multilib)
endif
ifneq ($(findstring LIBRARY, $(build_target)),LIBRARY)
-ifeq ($(LOCAL_MULTILIB),both)
LOCAL_MODULE_STEM_32 := $(module)32
LOCAL_MODULE_STEM_64 := $(module)64
+else
+ifeq ($($(module)_install_to_out_data),true)
+ LOCAL_MODULE_PATH_32 := $(TARGET_OUT_DATA_NATIVE_TESTS)/$(module)
+ LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_NATIVE_TESTS)64/$(module)
endif
endif
diff --git a/tests/Android.mk b/tests/Android.mk
index 47e6272..278511b 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -244,8 +244,8 @@
dlext_test.cpp \
dlfcn_test.cpp \
-bionic-unit-tests_cppflags := \
- $(test_cppflags)
+bionic-unit-tests_cflags := $(test_cflags)
+bionic-unit-tests_cppflags := $(test_cppflags)
bionic-unit-tests_ldflags := \
-Wl,--export-dynamic \
@@ -260,7 +260,6 @@
module := bionic-unit-tests
module_tag := optional
-bionic-unit-tests_multilib := both
build_type := target
build_target := NATIVE_TEST
include $(LOCAL_PATH)/Android.build.mk
@@ -282,7 +281,6 @@
module := bionic-unit-tests-static
module_tag := optional
-bionic-unit-tests-static_multilib := both
build_type := target
build_target := NATIVE_TEST
include $(LOCAL_PATH)/Android.build.mk
@@ -303,12 +301,11 @@
bionic-unit-tests-glibc_ldlibs := \
-lrt -ldl \
-bionic-unit-tests-glibc_cppflags := \
- $(test_cppflags)
+bionic-unit-tests-glibc_cflags := $(test_cflags)
+bionic-unit-tests-glibc_cppflags := $(test_cppflags)
module := bionic-unit-tests-glibc
module_tag := optional
-bionic-unit-tests-glibc_multilib := both
build_type := host
build_target := NATIVE_TEST
include $(LOCAL_PATH)/Android.build.mk
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index b56fc41..da63046 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -45,6 +45,11 @@
#define LIBNAME_NORELRO "libdlext_test_norelro.so"
#define LIBSIZE 1024*1024 // how much address space to reserve for it
+#if defined(__LP64__)
+#define LIBPATH "%s/nativetest64/libdlext_test_fd/libdlext_test_fd.so"
+#else
+#define LIBPATH "%s/nativetest/libdlext_test_fd/libdlext_test_fd.so"
+#endif
class DlExtTest : public ::testing::Test {
protected:
@@ -83,6 +88,23 @@
EXPECT_EQ(4, f());
}
+TEST_F(DlExtTest, ExtInfoUseFd) {
+ const char* android_data = getenv("ANDROID_DATA");
+ ASSERT_TRUE(android_data != NULL);
+ char lib_path[PATH_MAX];
+ snprintf(lib_path, sizeof(lib_path), LIBPATH, android_data);
+
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD;
+ extinfo.library_fd = TEMP_FAILURE_RETRY(open(lib_path, O_RDONLY | O_CLOEXEC));
+ ASSERT_TRUE(extinfo.library_fd != -1);
+ handle_ = android_dlopen_ext(lib_path, RTLD_NOW, &extinfo);
+ ASSERT_DL_NOTNULL(handle_);
+ fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
+ ASSERT_DL_NOTNULL(f);
+ EXPECT_EQ(4, f());
+}
+
TEST_F(DlExtTest, Reserved) {
void* start = mmap(NULL, LIBSIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 49cbb7d..a79263d 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -50,6 +50,25 @@
ASSERT_EQ(0, dlclose(self));
}
+#if !defined(__LP64__)
+// Current compiler/static linker used for aarch64
+// platform optimizes LOCAL PROTECTED symbol
+// in libtest_local_symbol.so out of existence
+TEST(dlfcn, dlsym_local_symbol) {
+ void* handle = dlopen("libtest_local_symbol.so", RTLD_NOW);
+ ASSERT_TRUE(handle != NULL);
+ dlerror();
+ void* sym = dlsym(handle, "private_taxicab_number");
+ ASSERT_TRUE(sym == NULL);
+ ASSERT_STREQ("undefined symbol: private_taxicab_number", dlerror());
+
+ uint32_t (*f)(void);
+ f = reinterpret_cast<uint32_t (*)(void)>(dlsym(handle, "dlsym_local_symbol_get_taxicab_number_using_dlsym"));
+ ASSERT_TRUE(f != NULL);
+ ASSERT_EQ(1729U, f());
+}
+#endif
+
TEST(dlfcn, dlopen_noload) {
void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_NOLOAD);
ASSERT_TRUE(handle == NULL);
@@ -254,6 +273,18 @@
ASSERT_TRUE(addr != NULL);
}
+TEST(dlfcn, dlsym_weak_func) {
+ dlerror();
+ void* handle = dlopen("libtest_dlsym_weak_func.so",RTLD_NOW);
+ ASSERT_TRUE(handle != NULL);
+
+ int (*weak_func)();
+ weak_func = reinterpret_cast<int (*)()>(dlsym(handle, "weak_func"));
+ ASSERT_TRUE(weak_func != NULL) << "dlerror: " << dlerror();
+ EXPECT_EQ(42, weak_func());
+ dlclose(handle);
+}
+
TEST(dlfcn, dlopen_symlink) {
void* handle1 = dlopen("libdlext_test.so", RTLD_NOW);
void* handle2 = dlopen("libdlext_test_v2.so", RTLD_NOW);
diff --git a/tests/fcntl_test.cpp b/tests/fcntl_test.cpp
index fb6b07e..5f20295 100644
--- a/tests/fcntl_test.cpp
+++ b/tests/fcntl_test.cpp
@@ -132,3 +132,87 @@
close(fd);
}
+
+TEST(fcntl, splice) {
+ int pipe_fds[2];
+ ASSERT_EQ(0, pipe(pipe_fds));
+
+ int in = open("/proc/cpuinfo", O_RDONLY);
+ ASSERT_NE(in, -1);
+
+ TemporaryFile tf;
+
+ ssize_t bytes_read = splice(in, 0, pipe_fds[1], NULL, 8*1024, SPLICE_F_MORE | SPLICE_F_MOVE);
+ ASSERT_NE(bytes_read, -1);
+
+ ssize_t bytes_written = splice(pipe_fds[0], NULL, tf.fd, 0, bytes_read, SPLICE_F_MORE | SPLICE_F_MOVE);
+ ASSERT_EQ(bytes_read, bytes_written);
+
+ close(pipe_fds[0]);
+ close(pipe_fds[1]);
+ close(in);
+}
+
+TEST(fcntl, vmsplice) {
+ int pipe_fds[2];
+ ASSERT_EQ(0, pipe(pipe_fds));
+
+ iovec v[2];
+ v[0].iov_base = const_cast<char*>("hello ");
+ v[0].iov_len = 6;
+ v[1].iov_base = const_cast<char*>("world\n");
+ v[1].iov_len = 6;
+ ssize_t bytes_written = vmsplice(pipe_fds[1], v, sizeof(v)/sizeof(iovec), 0);
+ ASSERT_EQ(v[0].iov_len + v[1].iov_len, static_cast<size_t>(bytes_written));
+ close(pipe_fds[1]);
+
+ char buf[BUFSIZ];
+ FILE* fp = fdopen(pipe_fds[0], "r");
+ ASSERT_TRUE(fp != NULL);
+ ASSERT_TRUE(fgets(buf, sizeof(buf), fp) != NULL);
+ fclose(fp);
+ ASSERT_STREQ("hello world\n", buf);
+}
+
+TEST(fcntl, tee) {
+ char expected[256];
+ FILE* expected_fp = fopen("/proc/version", "r");
+ ASSERT_TRUE(expected_fp != NULL);
+ ASSERT_TRUE(fgets(expected, sizeof(expected), expected_fp) != NULL);
+ fclose(expected_fp);
+
+ int pipe1[2];
+ ASSERT_EQ(0, pipe(pipe1));
+
+ int pipe2[2];
+ ASSERT_EQ(0, pipe(pipe2));
+
+ int in = open("/proc/version", O_RDONLY);
+ ASSERT_NE(in, -1);
+
+ // Write /proc/version into pipe1.
+ ssize_t bytes_read = splice(in, 0, pipe1[1], NULL, 8*1024, SPLICE_F_MORE | SPLICE_F_MOVE);
+ ASSERT_NE(bytes_read, -1);
+ close(pipe1[1]);
+
+ // Tee /proc/version from pipe1 into pipe2.
+ ssize_t bytes_teed = tee(pipe1[0], pipe2[1], SIZE_MAX, 0);
+ ASSERT_EQ(bytes_read, bytes_teed);
+ close(pipe2[1]);
+
+ // The out fds of both pipe1 and pipe2 should now contain /proc/version.
+ char buf1[BUFSIZ];
+ FILE* fp1 = fdopen(pipe1[0], "r");
+ ASSERT_TRUE(fp1 != NULL);
+ ASSERT_TRUE(fgets(buf1, sizeof(buf1), fp1) != NULL);
+ fclose(fp1);
+
+ char buf2[BUFSIZ];
+ FILE* fp2 = fdopen(pipe2[0], "r");
+ ASSERT_TRUE(fp2 != NULL);
+ ASSERT_TRUE(fgets(buf2, sizeof(buf2), fp2) != NULL);
+ fclose(fp2);
+
+ ASSERT_STREQ(expected, buf1);
+ ASSERT_STREQ(expected, buf2);
+}
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index e75582d..a374e48 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -78,6 +78,19 @@
include $(TEST_PATH)/Android.build.mk
# -----------------------------------------------------------------------------
+# Library used by dlext tests - different name non-default location
+# -----------------------------------------------------------------------------
+libdlext_test_fd_src_files := \
+ dlext_test_library.cpp \
+
+libdlext_test_fd_install_to_out_data := true
+module := libdlext_test_fd
+module_tag := optional
+build_type := target
+build_target := SHARED_LIBRARY
+include $(TEST_PATH)/Android.build.mk
+
+# -----------------------------------------------------------------------------
# Library used by dlfcn tests
# -----------------------------------------------------------------------------
libtest_simple_src_files := \
@@ -88,6 +101,20 @@
build_target := SHARED_LIBRARY
include $(TEST_PATH)/Android.build.mk
+# -----------------------------------------------------------------------------
+# Library used to test local symbol lookup
+# -----------------------------------------------------------------------------
+libtest_local_symbol_src_files := \
+ dlsym_local_symbol_private.cpp \
+ dlsym_local_symbol_public.cpp
+
+module := libtest_local_symbol
+build_target := SHARED_LIBRARY
+libtest_local_symbol_ldflags := -Wl,--version-script=$(LOCAL_PATH)/dlsym_local_symbol.map
+libtest_local_symbol_cppflags := -std=gnu++11
+libtest_local_symbol_shared_libraries_target := libdl
+build_type := target
+include $(TEST_PATH)/Android.build.mk
# -----------------------------------------------------------------------------
# Library used by atexit tests
@@ -103,3 +130,15 @@
build_type := host
include $(TEST_PATH)/Android.build.mk
+# -----------------------------------------------------------------------------
+# Library with weak function
+# -----------------------------------------------------------------------------
+libtest_dlsym_weak_func_src_files := \
+ dlsym_weak_function.cpp
+
+module := libtest_dlsym_weak_func
+build_target := SHARED_LIBRARY
+build_type := target
+include $(TEST_PATH)/Android.build.mk
+build_type := host
+include $(TEST_PATH)/Android.build.mk
diff --git a/libc/include/sha1.h b/tests/libs/dlsym_local_symbol.map
similarity index 72%
copy from libc/include/sha1.h
copy to tests/libs/dlsym_local_symbol.map
index 7f6cf5d..58a2299 100644
--- a/libc/include/sha1.h
+++ b/tests/libs/dlsym_local_symbol.map
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -13,11 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#ifndef _SHA1_H_
-#define _SHA1_H_
-
-#warning "include <sys/sha1.h> instead for better portability"
-#include <sys/sha1.h>
-
-#endif
+LIBTEST_LOCAL_SYMBOL_1.0 {
+ global:
+ dlsym_local_symbol_get_taxicab_number;
+ dlsym_local_symbol_get_taxicab_number_using_dlsym;
+ local:
+ *;
+};
diff --git a/libc/include/sha1.h b/tests/libs/dlsym_local_symbol_private.cpp
similarity index 61%
copy from libc/include/sha1.h
copy to tests/libs/dlsym_local_symbol_private.cpp
index 7f6cf5d..2587508 100644
--- a/libc/include/sha1.h
+++ b/tests/libs/dlsym_local_symbol_private.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#ifndef _SHA1_H_
-#define _SHA1_H_
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <stdio.h>
-#warning "include <sys/sha1.h> instead for better portability"
-#include <sys/sha1.h>
-
-#endif
+// This symbol is declared local in
+// the linker version map: libdlsym_local_symbol.map.
+// It should not be visible from the outside.
+extern "C" const uint32_t __attribute__ ((visibility ("protected"))) private_taxicab_number = 1729;
diff --git a/tests/libs/dlsym_local_symbol_public.cpp b/tests/libs/dlsym_local_symbol_public.cpp
new file mode 100644
index 0000000..d9da32a
--- /dev/null
+++ b/tests/libs/dlsym_local_symbol_public.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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 <stdlib.h>
+#include <dlfcn.h>
+#include <stdio.h>
+
+extern const uint32_t private_taxicab_number;
+
+extern "C" {
+uint32_t dlsym_local_symbol_get_taxicab_number();
+uint32_t dlsym_local_symbol_get_taxicab_number_using_dlsym();
+}
+
+uint32_t dlsym_local_symbol_get_taxicab_number() {
+ return private_taxicab_number;
+}
+
+// Let's make sure that dlsym works correctly for local symbol
+uint32_t dlsym_local_symbol_get_taxicab_number_using_dlsym() {
+ dlerror();
+ uint32_t* ptr = reinterpret_cast<uint32_t*>(dlsym(RTLD_DEFAULT, "private_taxicab_number"));
+ if (ptr == nullptr) {
+ const char* dlerr = dlerror();
+ if (dlerr != nullptr) {
+ fprintf(stderr, "dlsym error: %s\n", dlerr);
+ } else {
+ fprintf(stderr, "dlsym returned NULL with no dlerror.\n");
+ }
+ return 0;
+ }
+
+ return *ptr;
+}
diff --git a/libc/include/sha1.h b/tests/libs/dlsym_weak_function.cpp
similarity index 75%
rename from libc/include/sha1.h
rename to tests/libs/dlsym_weak_function.cpp
index 7f6cf5d..e38f2b8 100644
--- a/libc/include/sha1.h
+++ b/tests/libs/dlsym_weak_function.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -14,10 +14,7 @@
* limitations under the License.
*/
-#ifndef _SHA1_H_
-#define _SHA1_H_
+extern "C" int __attribute__((weak)) weak_func() {
+ return 42;
+}
-#warning "include <sys/sha1.h> instead for better portability"
-#include <sys/sha1.h>
-
-#endif
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 0f42d43..36da481 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -69,6 +69,19 @@
#endif // __BIONIC__
}
+TEST(pthread, pthread_key_delete) {
+ void* expected = reinterpret_cast<void*>(1234);
+ pthread_key_t key;
+ ASSERT_EQ(0, pthread_key_create(&key, NULL));
+ ASSERT_EQ(0, pthread_setspecific(key, expected));
+ ASSERT_EQ(expected, pthread_getspecific(key));
+ ASSERT_EQ(0, pthread_key_delete(key));
+ // After deletion, pthread_getspecific returns NULL.
+ ASSERT_EQ(NULL, pthread_getspecific(key));
+ // And you can't use pthread_setspecific with the deleted key.
+ ASSERT_EQ(EINVAL, pthread_setspecific(key, expected));
+}
+
static void* IdFn(void* arg) {
return arg;
}
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index 2ab60d7..bc2c05b 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -359,6 +359,24 @@
EXPECT_TRUE(strchr(buf, '\0') == (buf + strlen(s)));
}
+TEST(string, strchr_multiple) {
+ char str[128];
+ memset(str, 'a', sizeof(str) - 1);
+ str[sizeof(str)-1] = '\0';
+
+ // Verify that strchr finds the first occurrence of 'a' in a string
+ // filled with 'a' characters. Iterate over the string putting
+ // non 'a' characters at the front of the string during each iteration
+ // and continue to verify that strchr can find the first occurrence
+ // properly. The idea is to cover all possible alignments of the location
+ // of the first occurrence of the 'a' character and which includes
+ // other 'a' characters close by.
+ for (size_t i = 0; i < sizeof(str) - 1; i++) {
+ EXPECT_EQ(&str[i], strchr(str, 'a'));
+ str[i] = 'b';
+ }
+}
+
TEST(string, strchr) {
int seek_char = random() & 255;
@@ -1235,3 +1253,29 @@
TEST(string, memcmp_overread) {
RunCmpBufferOverreadTest(DoMemcmpTest, DoMemcmpFailTest);
}
+
+static void DoStrchrTest(uint8_t* buf, size_t len) {
+ if (len >= 1) {
+ char value = 32 + (len % 96);
+ char search_value = 33 + (len % 96);
+ memset(buf, value, len - 1);
+ buf[len-1] = '\0';
+ ASSERT_EQ(NULL, strchr(reinterpret_cast<char*>(buf), search_value));
+ ASSERT_EQ(reinterpret_cast<char*>(&buf[len-1]), strchr(reinterpret_cast<char*>(buf), '\0'));
+ if (len >= 2) {
+ buf[0] = search_value;
+ ASSERT_EQ(reinterpret_cast<char*>(&buf[0]), strchr(reinterpret_cast<char*>(buf), search_value));
+ buf[0] = value;
+ buf[len-2] = search_value;
+ ASSERT_EQ(reinterpret_cast<char*>(&buf[len-2]), strchr(reinterpret_cast<char*>(buf), search_value));
+ }
+ }
+}
+
+TEST(string, strchr_align) {
+ RunSingleBufferAlignTest(MEDIUM, DoStrchrTest);
+}
+
+TEST(string, strchr_overread) {
+ RunSingleBufferOverreadTest(DoStrchrTest);
+}
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 6aa259a..58c9ad9 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -22,6 +22,7 @@
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
+#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -379,3 +380,72 @@
TEST(unistd, fsync) {
TestFsyncFunction(fsync);
}
+
+static void AssertGetPidCorrect() {
+ // The loop is just to make manual testing/debugging with strace easier.
+ pid_t getpid_syscall_result = syscall(__NR_getpid);
+ for (size_t i = 0; i < 128; ++i) {
+ ASSERT_EQ(getpid_syscall_result, getpid());
+ }
+}
+
+TEST(unistd, getpid_caching_and_fork) {
+ pid_t parent_pid = getpid();
+ ASSERT_EQ(syscall(__NR_getpid), parent_pid);
+
+ pid_t fork_result = fork();
+ ASSERT_NE(fork_result, -1);
+ if (fork_result == 0) {
+ // We're the child.
+ AssertGetPidCorrect();
+ ASSERT_EQ(parent_pid, getppid());
+ _exit(123);
+ } else {
+ // We're the parent.
+ ASSERT_EQ(parent_pid, getpid());
+
+ int status;
+ ASSERT_EQ(fork_result, waitpid(fork_result, &status, 0));
+ ASSERT_TRUE(WIFEXITED(status));
+ ASSERT_EQ(123, WEXITSTATUS(status));
+ }
+}
+
+static int GetPidCachingCloneStartRoutine(void*) {
+ AssertGetPidCorrect();
+ return 123;
+}
+
+TEST(unistd, getpid_caching_and_clone) {
+ pid_t parent_pid = getpid();
+ ASSERT_EQ(syscall(__NR_getpid), parent_pid);
+
+ void* child_stack[1024];
+ int clone_result = clone(GetPidCachingCloneStartRoutine, &child_stack[1024], CLONE_NEWNS | SIGCHLD, NULL);
+ ASSERT_NE(clone_result, -1);
+
+ ASSERT_EQ(parent_pid, getpid());
+
+ int status;
+ ASSERT_EQ(clone_result, waitpid(clone_result, &status, 0));
+ ASSERT_TRUE(WIFEXITED(status));
+ ASSERT_EQ(123, WEXITSTATUS(status));
+}
+
+static void* GetPidCachingPthreadStartRoutine(void*) {
+ AssertGetPidCorrect();
+ return NULL;
+}
+
+TEST(unistd, getpid_caching_and_pthread_create) {
+ pid_t parent_pid = getpid();
+
+ pthread_t t;
+ ASSERT_EQ(0, pthread_create(&t, NULL, GetPidCachingPthreadStartRoutine, NULL));
+
+ ASSERT_EQ(parent_pid, getpid());
+
+ void* result;
+ ASSERT_EQ(0, pthread_join(t, &result));
+ ASSERT_EQ(NULL, result);
+}