Merge "Remove SHA1 from LP64 in favor of libcrypto."
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 37f3059..1b3965e 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 \
@@ -500,7 +501,7 @@
ifeq ($(MALLOC_IMPL),jemalloc)
libc_common_cflags += -DUSE_JEMALLOC
- libc_malloc_src := bionic/jemalloc.cpp
+ libc_malloc_src := bionic/jemalloc_wrapper.cpp
else
libc_common_cflags += -DUSE_DLMALLOC
libc_malloc_src := bionic/dlmalloc.c
@@ -584,7 +585,10 @@
# 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 \
+ -Werror \
+
# Don't use ridiculous amounts of stack.
LOCAL_CFLAGS += -DALL_STATE
# Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
@@ -596,6 +600,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)
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 369b23c..839cfb7 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
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-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 2d34f52..e44ee31 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -57,7 +57,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..36146bf
--- /dev/null
+++ b/libc/arch-arm64/denver64/denver64.mk
@@ -0,0 +1,10 @@
+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/strcmp.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/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-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-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-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_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/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/getpid.cpp b/libc/bionic/getpid.cpp
new file mode 100644
index 0000000..a3d5b35
--- /dev/null
+++ b/libc/bionic/getpid.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#include <unistd.h>
+
+#include "pthread_internal.h"
+
+extern "C" pid_t __getpid();
+
+pid_t getpid() {
+ pthread_internal_t* self = __get_thread();
+
+ // Do we have a valid cached pid?
+ pid_t cached_pid;
+ if (__predict_true(self->get_cached_pid(&cached_pid))) {
+ return cached_pid;
+ }
+
+ // 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/jemalloc.cpp b/libc/bionic/jemalloc_wrapper.cpp
similarity index 77%
rename from libc/bionic/jemalloc.cpp
rename to libc/bionic/jemalloc_wrapper.cpp
index 625d789..d1fe960 100644
--- a/libc/bionic/jemalloc.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/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_common.h b/libc/bionic/malloc_debug_common.h
index a0f9972..fb2f03d 100644
--- a/libc/bionic/malloc_debug_common.h
+++ b/libc/bionic/malloc_debug_common.h
@@ -37,6 +37,7 @@
#include <stdint.h>
#include <stdlib.h>
+#include "private/bionic_config.h"
#include "private/libc_logging.h"
#define HASHTABLE_SIZE 1543
@@ -61,12 +62,6 @@
#define Malloc(function) dl ## function
#endif
-// valloc(3) and pvalloc(3) were removed from POSIX 2004. We do not include them
-// for LP64, but the symbols remain in LP32 for binary compatibility.
-#ifndef __LP64__
-#define HAVE_DEPRECATED_MALLOC_FUNCS 1
-#endif
-
// =============================================================================
// Structures
// =============================================================================
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/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/include/stdio.h b/libc/include/stdio.h
index 62acb3a..e532de4 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -254,7 +254,9 @@
int vdprintf(int, const char * __restrict, __va_list) __printflike(2, 0);
#ifndef __AUDIT__
+#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L
char* gets(char*) __warnattr("gets is very unsafe; consider using fgets");
+#endif
int sprintf(char* __restrict, const char* __restrict, ...)
__printflike(2, 3) __warnattr("sprintf is often misused; please use snprintf");
char* tmpnam(char*) __warnattr("tmpnam possibly used unsafely; consider using mkstemp");
diff --git a/libc/include/sys/ioctl.h b/libc/include/sys/ioctl.h
index 49d452c..a1014dc 100644
--- a/libc/include/sys/ioctl.h
+++ b/libc/include/sys/ioctl.h
@@ -38,6 +38,7 @@
#include <asm/ioctls.h>
#include <asm/termbits.h>
#include <sys/ioctl_compat.h>
+#include <linux/tty.h>
__BEGIN_DECLS
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/bionic_config.h b/libc/private/bionic_config.h
new file mode 100644
index 0000000..0c9811c
--- /dev/null
+++ b/libc/private/bionic_config.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#ifndef _BIONIC_CONFIG_H_
+#define _BIONIC_CONFIG_H_
+
+// valloc(3) and pvalloc(3) were removed from POSIX 2004. We do not include them
+// for LP64, but the symbols remain in LP32 for binary compatibility.
+#if !defined(__LP64__)
+#define HAVE_DEPRECATED_MALLOC_FUNCS 1
+#endif
+
+#endif // _BIONIC_CONFIG_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/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/libm/Android.mk b/libm/Android.mk
index b67395f..90b4906 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -1,3 +1,4 @@
+ifneq ($(TARGET_USE_PRIVATE_LIBM),true)
LOCAL_PATH:= $(call my-dir)
# TODO: this comes from from upstream's libc, not libm, but it's an
@@ -291,3 +292,4 @@
LOCAL_SYSTEM_SHARED_LIBRARIES := libc
LOCAL_WHOLE_STATIC_LIBRARIES := libm
include $(BUILD_SHARED_LIBRARY)
+endif
diff --git a/libstdc++/include/cstdio b/libstdc++/include/cstdio
index 3c8b5c6..2948d85 100644
--- a/libstdc++/include/cstdio
+++ b/libstdc++/include/cstdio
@@ -63,7 +63,9 @@
using ::fwrite;
using ::getc;
using ::getchar;
+#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L
using ::gets;
+#endif
using ::perror;
using ::printf;
using ::putc;
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 6d63ad6..0b60ef5 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -118,7 +118,7 @@
if (sym != NULL) {
unsigned bind = ELF_ST_BIND(sym->st_info);
- if (bind == STB_GLOBAL && sym->st_shndx != 0) {
+ if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) {
return reinterpret_cast<void*>(sym->st_value + found->load_bias);
}
diff --git a/linker/linker.cpp b/linker/linker.cpp
index a22233d..e202aaf 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -59,6 +59,7 @@
*
* open issues / todo:
*
+ * - are we doing everything we should for ARM_COPY relocations?
* - cleaner error reporting
* - after linking, set as much stuff as possible to READONLY
* and NOEXEC
@@ -1037,17 +1038,52 @@
break;
case R_AARCH64_COPY:
- /*
- * ET_EXEC is not supported so this should not happen.
- *
- * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
- *
- * Section 4.7.1.10 "Dynamic relocations"
- * R_AARCH64_COPY may only appear in executable objects where e_type is
- * set to ET_EXEC.
- */
- DL_ERR("%s R_AARCH64_COPY relocations are not supported", si->name);
- return -1;
+ if ((si->flags & FLAG_EXE) == 0) {
+ /*
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
+ *
+ * Section 4.7.1.10 "Dynamic relocations"
+ * R_AARCH64_COPY may only appear in executable objects where e_type is
+ * set to ET_EXEC.
+ *
+ * FLAG_EXE is set for both ET_DYN and ET_EXEC executables.
+ * We should explicitly disallow ET_DYN executables from having
+ * R_AARCH64_COPY relocations.
+ */
+ DL_ERR("%s R_AARCH64_COPY relocations only supported for ET_EXEC", si->name);
+ return -1;
+ }
+ count_relocation(kRelocCopy);
+ MARK(rela->r_offset);
+ TRACE_TYPE(RELO, "RELO COPY %16llx <- %lld @ %16llx %s\n",
+ reloc,
+ s->st_size,
+ (sym_addr + rela->r_addend),
+ sym_name);
+ if (reloc == (sym_addr + rela->r_addend)) {
+ ElfW(Sym)* src = soinfo_do_lookup(NULL, sym_name, &lsi, needed);
+
+ if (src == NULL) {
+ DL_ERR("%s R_AARCH64_COPY relocation source cannot be resolved", si->name);
+ return -1;
+ }
+ if (lsi->has_DT_SYMBOLIC) {
+ DL_ERR("%s invalid R_AARCH64_COPY relocation against DT_SYMBOLIC shared "
+ "library %s (built with -Bsymbolic?)", si->name, lsi->name);
+ return -1;
+ }
+ if (s->st_size < src->st_size) {
+ DL_ERR("%s R_AARCH64_COPY relocation size mismatch (%lld < %lld)",
+ si->name, s->st_size, src->st_size);
+ return -1;
+ }
+ memcpy(reinterpret_cast<void*>(reloc),
+ reinterpret_cast<void*>(src->st_value + lsi->load_bias), src->st_size);
+ } else {
+ DL_ERR("%s R_AARCH64_COPY relocation target cannot be resolved", si->name);
+ return -1;
+ }
+ break;
case R_AARCH64_TLS_TPREL64:
TRACE_TYPE(RELO, "RELO TLS_TPREL64 *** %16llx <- %16llx - %16llx\n",
reloc, (sym_addr + rela->r_addend), rela->r_offset);
@@ -1225,17 +1261,48 @@
*reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr - rel->r_offset;
break;
case R_ARM_COPY:
- /*
- * ET_EXEC is not supported so this should not happen.
- *
- * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
- *
- * Section 4.7.1.10 "Dynamic relocations"
- * R_ARM_COPY may only appear in executable objects where e_type is
- * set to ET_EXEC.
- */
- DL_ERR("%s R_ARM_COPY relocations are not supported", si->name);
- return -1;
+ if ((si->flags & FLAG_EXE) == 0) {
+ /*
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
+ *
+ * Section 4.7.1.10 "Dynamic relocations"
+ * R_ARM_COPY may only appear in executable objects where e_type is
+ * set to ET_EXEC.
+ *
+ * TODO: FLAG_EXE is set for both ET_DYN and ET_EXEC executables.
+ * We should explicitly disallow ET_DYN executables from having
+ * R_ARM_COPY relocations.
+ */
+ DL_ERR("%s R_ARM_COPY relocations only supported for ET_EXEC", si->name);
+ return -1;
+ }
+ count_relocation(kRelocCopy);
+ MARK(rel->r_offset);
+ TRACE_TYPE(RELO, "RELO %08x <- %d @ %08x %s", reloc, s->st_size, sym_addr, sym_name);
+ if (reloc == sym_addr) {
+ ElfW(Sym)* src = soinfo_do_lookup(NULL, sym_name, &lsi, needed);
+
+ if (src == NULL) {
+ DL_ERR("%s R_ARM_COPY relocation source cannot be resolved", si->name);
+ return -1;
+ }
+ if (lsi->has_DT_SYMBOLIC) {
+ DL_ERR("%s invalid R_ARM_COPY relocation against DT_SYMBOLIC shared "
+ "library %s (built with -Bsymbolic?)", si->name, lsi->name);
+ return -1;
+ }
+ if (s->st_size < src->st_size) {
+ DL_ERR("%s R_ARM_COPY relocation size mismatch (%d < %d)",
+ si->name, s->st_size, src->st_size);
+ return -1;
+ }
+ memcpy(reinterpret_cast<void*>(reloc),
+ reinterpret_cast<void*>(src->st_value + lsi->load_bias), src->st_size);
+ } else {
+ DL_ERR("%s R_ARM_COPY relocation target cannot be resolved", si->name);
+ return -1;
+ }
+ break;
#elif defined(__i386__)
case R_386_JMP_SLOT:
count_relocation(kRelocAbsolute);
@@ -2105,11 +2172,13 @@
si->dynamic = NULL;
si->ref_count = 1;
+#if defined(__LP64__)
ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(si->base);
if (elf_hdr->e_type != ET_DYN) {
__libc_format_fd(2, "error: only position independent executables (PIE) are supported.\n");
exit(EXIT_FAILURE);
}
+#endif
// Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid).
parse_LD_LIBRARY_PATH(ldpath_env);
diff --git a/tests/Android.build.mk b/tests/Android.build.mk
index e65ec16..6433d55 100644
--- a/tests/Android.build.mk
+++ b/tests/Android.build.mk
@@ -36,10 +36,6 @@
LOCAL_FORCE_STATIC_EXECUTABLE := $($(module)_force_static_executable)
-LOCAL_ADDITIONAL_DEPENDENCIES := \
- $(LOCAL_PATH)/Android.mk \
- $(LOCAL_PATH)/Android.build.mk \
-
LOCAL_CFLAGS := \
$(common_cflags) \
$($(module)_cflags) \
diff --git a/tests/Android.mk b/tests/Android.mk
index ce0c5f2..47e6272 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -233,88 +233,6 @@
include $(LOCAL_PATH)/Android.build.mk
# -----------------------------------------------------------------------------
-# Library used by dlfcn tests.
-# -----------------------------------------------------------------------------
-ifneq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),mips mips64))
-no-elf-hash-table-library_src_files := \
- empty.cpp \
-
-no-elf-hash-table-library_ldflags := \
- -Wl,--hash-style=gnu \
-
-module := no-elf-hash-table-library
-module_tag := optional
-build_type := target
-build_target := SHARED_LIBRARY
-include $(LOCAL_PATH)/Android.build.mk
-endif
-
-# -----------------------------------------------------------------------------
-# Library used by dlext tests - with/without GNU RELRO program header
-# -----------------------------------------------------------------------------
-libdlext_test_src_files := \
- dlext_test_library.cpp \
-
-libdlext_test_ldflags := \
- -Wl,-z,relro \
-
-module := libdlext_test
-module_tag := optional
-build_type := target
-build_target := SHARED_LIBRARY
-include $(LOCAL_PATH)/Android.build.mk
-
-# -----------------------------------------------------------------------------
-# create symlink to libdlext_test.so for symlink test
-# -----------------------------------------------------------------------------
-# Use = instead of := to defer the evaluation of $@
-$(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD = \
- $(hide) cd $(dir $@) && ln -sf $(notdir $@) libdlext_test_v2.so
-ifneq ($(TARGET_2ND_ARCH),)
-# link 64 bit .so
-$(TARGET_OUT)/lib64/libdlext_test.so: PRIVATE_POST_INSTALL_CMD = \
- $(hide) cd $(dir $@) && ln -sf $(notdir $@) libdlext_test_v2.so
-endif
-
-libdlext_test_norelro_src_files := \
- dlext_test_library.cpp \
-
-libdlext_test_norelro_ldflags := \
- -Wl,-z,norelro \
-
-module := libdlext_test_norelro
-module_tag := optional
-build_type := target
-build_target := SHARED_LIBRARY
-include $(LOCAL_PATH)/Android.build.mk
-
-# -----------------------------------------------------------------------------
-# Library used by dlfcn tests
-# -----------------------------------------------------------------------------
-libtest_simple_src_files := \
- dlopen_testlib_simple.cpp
-
-module := libtest_simple
-build_type := target
-build_target := SHARED_LIBRARY
-include $(LOCAL_PATH)/Android.build.mk
-
-
-# -----------------------------------------------------------------------------
-# Library used by atexit tests
-# -----------------------------------------------------------------------------
-
-libtest_atexit_src_files := \
- atexit_testlib.cpp
-
-module := libtest_atexit
-build_target := SHARED_LIBRARY
-build_type := target
-include $(LOCAL_PATH)/Android.build.mk
-build_type := host
-include $(LOCAL_PATH)/Android.build.mk
-
-# -----------------------------------------------------------------------------
# Tests for the device using bionic's .so. Run with:
# adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests
# -----------------------------------------------------------------------------
@@ -438,4 +356,5 @@
endif # linux-x86
+include $(call first-makefiles-under,$(LOCAL_PATH))
endif # !BUILD_TINY_ANDROID
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 49cbb7d..8b89183 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -254,6 +254,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/libs/Android.mk b/tests/libs/Android.mk
new file mode 100644
index 0000000..67ea562
--- /dev/null
+++ b/tests/libs/Android.mk
@@ -0,0 +1,117 @@
+#
+# Copyright (C) 2012 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+TEST_PATH := $(LOCAL_PATH)/..
+
+# -----------------------------------------------------------------------------
+# Library used by dlfcn tests.
+# -----------------------------------------------------------------------------
+ifneq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),mips mips64))
+no-elf-hash-table-library_src_files := \
+ empty.cpp \
+
+no-elf-hash-table-library_ldflags := \
+ -Wl,--hash-style=gnu \
+
+module := no-elf-hash-table-library
+module_tag := optional
+build_type := target
+build_target := SHARED_LIBRARY
+include $(TEST_PATH)/Android.build.mk
+endif
+
+# -----------------------------------------------------------------------------
+# Library used by dlext tests - with GNU RELRO program header
+# -----------------------------------------------------------------------------
+libdlext_test_src_files := \
+ dlext_test_library.cpp \
+
+libdlext_test_ldflags := \
+ -Wl,-z,relro \
+
+module := libdlext_test
+module_tag := optional
+build_type := target
+build_target := SHARED_LIBRARY
+include $(TEST_PATH)/Android.build.mk
+
+# -----------------------------------------------------------------------------
+# create symlink to libdlext_test.so for symlink test
+# -----------------------------------------------------------------------------
+# Use = instead of := to defer the evaluation of $@
+$(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD = \
+ $(hide) cd $(dir $@) && ln -sf $(notdir $@) libdlext_test_v2.so
+
+ifneq ($(TARGET_2ND_ARCH),)
+# link 64 bit .so
+$(TARGET_OUT)/lib64/libdlext_test.so: PRIVATE_POST_INSTALL_CMD = \
+ $(hide) cd $(dir $@) && ln -sf $(notdir $@) libdlext_test_v2.so
+endif
+
+# -----------------------------------------------------------------------------
+# Library used by dlext tests - without GNU RELRO program header
+# -----------------------------------------------------------------------------
+libdlext_test_norelro_src_files := \
+ dlext_test_library.cpp \
+
+libdlext_test_norelro_ldflags := \
+ -Wl,-z,norelro \
+
+module := libdlext_test_norelro
+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 := \
+ dlopen_testlib_simple.cpp
+
+module := libtest_simple
+build_type := target
+build_target := SHARED_LIBRARY
+include $(TEST_PATH)/Android.build.mk
+
+
+# -----------------------------------------------------------------------------
+# Library used by atexit tests
+# -----------------------------------------------------------------------------
+
+libtest_atexit_src_files := \
+ atexit_testlib.cpp
+
+module := libtest_atexit
+build_target := SHARED_LIBRARY
+build_type := target
+include $(TEST_PATH)/Android.build.mk
+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/tests/atexit_testlib.cpp b/tests/libs/atexit_testlib.cpp
similarity index 100%
rename from tests/atexit_testlib.cpp
rename to tests/libs/atexit_testlib.cpp
diff --git a/tests/dlext_test_library.cpp b/tests/libs/dlext_test_library.cpp
similarity index 100%
rename from tests/dlext_test_library.cpp
rename to tests/libs/dlext_test_library.cpp
diff --git a/tests/dlopen_testlib_simple.cpp b/tests/libs/dlopen_testlib_simple.cpp
similarity index 100%
rename from tests/dlopen_testlib_simple.cpp
rename to tests/libs/dlopen_testlib_simple.cpp
diff --git a/tests/libs/dlsym_weak_function.cpp b/tests/libs/dlsym_weak_function.cpp
new file mode 100644
index 0000000..e38f2b8
--- /dev/null
+++ b/tests/libs/dlsym_weak_function.cpp
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+extern "C" int __attribute__((weak)) weak_func() {
+ return 42;
+}
+
diff --git a/tests/empty.cpp b/tests/libs/empty.cpp
similarity index 100%
rename from tests/empty.cpp
rename to tests/libs/empty.cpp
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index d701364..6b7a28b 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -22,9 +22,7 @@
#include <malloc.h>
#include <unistd.h>
-#if defined(__BIONIC__)
-#include <libc/bionic/malloc_debug_common.h>
-#endif
+#include "private/bionic_config.h"
TEST(malloc, malloc_std) {
// Simple malloc test.
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 6aa259a..95e63b3 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,47 @@
TEST(unistd, fsync) {
TestFsyncFunction(fsync);
}
+
+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.
+ ASSERT_EQ(syscall(__NR_getpid), getpid());
+ 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 void GetPidCachingHelperHelper() {
+ ASSERT_EQ(syscall(__NR_getpid), getpid());
+}
+
+static void* GetPidCachingHelper(void*) {
+ GetPidCachingHelperHelper(); // Can't assert in a non-void function.
+ return NULL;
+}
+
+TEST(unistd, getpid_caching_and_pthread_create) {
+ pid_t parent_pid = getpid();
+
+ pthread_t t;
+ ASSERT_EQ(0, pthread_create(&t, NULL, GetPidCachingHelper, NULL));
+
+ ASSERT_EQ(parent_pid, getpid());
+
+ void* result;
+ ASSERT_EQ(0, pthread_join(t, &result));
+ ASSERT_EQ(NULL, result);
+}