Merge "Revert "fix incompatibility with -fstack-protector-strong""
diff --git a/README.md b/README.md
index 79bb72a..72b7124 100644
--- a/README.md
+++ b/README.md
@@ -194,14 +194,15 @@
### Device tests
$ mma
+ $ adb remount
$ adb sync
$ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
$ adb shell \
/data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static32
# Only for 64-bit targets
- $ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests64
+ $ adb shell /data/nativetest64/bionic-unit-tests/bionic-unit-tests64
$ adb shell \
- /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static64
+ /data/nativetest64/bionic-unit-tests-static/bionic-unit-tests-static64
### Host tests
diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk
index e1580fe..20742bd 100644
--- a/benchmarks/Android.mk
+++ b/benchmarks/Android.mk
@@ -29,7 +29,6 @@
-Wunused \
benchmark_cppflags := \
- -std=gnu++11 \
benchmarklib_src_files := \
Benchmark.cpp \
diff --git a/benchmarks/math_benchmark.cpp b/benchmarks/math_benchmark.cpp
index 4de28d1..2e0c962 100644
--- a/benchmarks/math_benchmark.cpp
+++ b/benchmarks/math_benchmark.cpp
@@ -65,6 +65,50 @@
StopBenchmarkTiming();
}
+BENCHMARK_WITH_ARG(BM_math_isfinite_macro, double)->AT_COMMON_VALS;
+void BM_math_isfinite_macro::Run(int iters, double value) {
+ StartBenchmarkTiming();
+
+ d = 0.0;
+ v = value;
+ for (int i = 0; i < iters; ++i) {
+ d += isfinite(v);
+ }
+
+ StopBenchmarkTiming();
+}
+
+#if defined(__BIONIC__)
+#define test_isfinite __isfinite
+#else
+#define test_isfinite __finite
+#endif
+BENCHMARK_WITH_ARG(BM_math_isfinite, double)->AT_COMMON_VALS;
+void BM_math_isfinite::Run(int iters, double value) {
+ StartBenchmarkTiming();
+
+ d = 0.0;
+ v = value;
+ for (int i = 0; i < iters; ++i) {
+ d += test_isfinite(v);
+ }
+
+ StopBenchmarkTiming();
+}
+
+BENCHMARK_WITH_ARG(BM_math_isinf_macro, double)->AT_COMMON_VALS;
+void BM_math_isinf_macro::Run(int iters, double value) {
+ StartBenchmarkTiming();
+
+ d = 0.0;
+ v = value;
+ for (int i = 0; i < iters; ++i) {
+ d += isinf(v);
+ }
+
+ StopBenchmarkTiming();
+}
+
BENCHMARK_WITH_ARG(BM_math_isinf, double)->AT_COMMON_VALS;
void BM_math_isinf::Run(int iters, double value) {
StartBenchmarkTiming();
@@ -78,6 +122,60 @@
StopBenchmarkTiming();
}
+BENCHMARK_WITH_ARG(BM_math_isnan_macro, double)->AT_COMMON_VALS;
+void BM_math_isnan_macro::Run(int iters, double value) {
+ StartBenchmarkTiming();
+
+ d = 0.0;
+ v = value;
+ for (int i = 0; i < iters; ++i) {
+ d += isnan(v);
+ }
+
+ StopBenchmarkTiming();
+}
+
+BENCHMARK_WITH_ARG(BM_math_isnan, double)->AT_COMMON_VALS;
+void BM_math_isnan::Run(int iters, double value) {
+ StartBenchmarkTiming();
+
+ d = 0.0;
+ v = value;
+ for (int i = 0; i < iters; ++i) {
+ d += (isnan)(v);
+ }
+
+ StopBenchmarkTiming();
+}
+
+BENCHMARK_WITH_ARG(BM_math_isnormal_macro, double)->AT_COMMON_VALS;
+void BM_math_isnormal_macro::Run(int iters, double value) {
+ StartBenchmarkTiming();
+
+ d = 0.0;
+ v = value;
+ for (int i = 0; i < iters; ++i) {
+ d += isnormal(v);
+ }
+
+ StopBenchmarkTiming();
+}
+
+#if defined(__BIONIC__)
+BENCHMARK_WITH_ARG(BM_math_isnormal, double)->AT_COMMON_VALS;
+void BM_math_isnormal::Run(int iters, double value) {
+ StartBenchmarkTiming();
+
+ d = 0.0;
+ v = value;
+ for (int i = 0; i < iters; ++i) {
+ d += (__isnormal)(v);
+ }
+
+ StopBenchmarkTiming();
+}
+#endif
+
BENCHMARK_NO_ARG(BM_math_sin_fast);
void BM_math_sin_fast::Run(int iters) {
StartBenchmarkTiming();
@@ -134,3 +232,29 @@
StopBenchmarkTiming();
}
+
+BENCHMARK_WITH_ARG(BM_math_signbit_macro, double)->AT_COMMON_VALS;
+void BM_math_signbit_macro::Run(int iters, double value) {
+ StartBenchmarkTiming();
+
+ d = 0.0;
+ v = value;
+ for (int i = 0; i < iters; ++i) {
+ d += signbit(v);
+ }
+
+ StopBenchmarkTiming();
+}
+
+BENCHMARK_WITH_ARG(BM_math_signbit, double)->AT_COMMON_VALS;
+void BM_math_signbit::Run(int iters, double value) {
+ StartBenchmarkTiming();
+
+ d = 0.0;
+ v = value;
+ for (int i = 0; i < iters; ++i) {
+ d += (__signbit)(v);
+ }
+
+ StopBenchmarkTiming();
+}
diff --git a/benchmarks/time_benchmark.cpp b/benchmarks/time_benchmark.cpp
index 6688bbc..1b0d08d 100644
--- a/benchmarks/time_benchmark.cpp
+++ b/benchmarks/time_benchmark.cpp
@@ -17,6 +17,7 @@
#include <sys/syscall.h>
#include <sys/time.h>
#include <time.h>
+#include <unistd.h>
#include <benchmark/Benchmark.h>
diff --git a/libc/Android.mk b/libc/Android.mk
index de0bb41..ca20d3d 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -70,12 +70,17 @@
libc_common_src_files += \
bionic/__FD_chk.cpp \
bionic/__fgets_chk.cpp \
+ bionic/__fread_chk.cpp \
+ bionic/__fwrite_chk.cpp \
+ bionic/__getcwd_chk.cpp \
bionic/__memchr_chk.cpp \
bionic/__memmove_chk.cpp \
bionic/__memrchr_chk.cpp \
bionic/__poll_chk.cpp \
bionic/__pread64_chk.cpp \
bionic/__pread_chk.cpp \
+ bionic/__pwrite64_chk.cpp \
+ bionic/__pwrite_chk.cpp \
bionic/__read_chk.cpp \
bionic/__readlink_chk.cpp \
bionic/__readlinkat_chk.cpp \
@@ -92,6 +97,7 @@
bionic/__umask_chk.cpp \
bionic/__vsnprintf_chk.cpp \
bionic/__vsprintf_chk.cpp \
+ bionic/__write_chk.cpp
libc_bionic_ndk_src_files := \
bionic/abort.cpp \
@@ -575,10 +581,6 @@
-D_LIBC=1 \
-Wall -Wextra -Wunused \
-ifneq ($(TARGET_USES_LOGD),false)
-libc_common_cflags += -DTARGET_USES_LOGD
-endif
-
use_clang := $(USE_CLANG_PLATFORM_BUILD)
# Clang/llvm has incompatible long double (fp128) for x86_64.
@@ -624,7 +626,6 @@
# Define some common cppflags
libc_common_cppflags := \
- -std=gnu++11
# Define some common includes
# ========================================================
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 151749b..ac8db62 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -77,7 +77,6 @@
int setgroups:setgroups32(int, const gid_t*) arm,x86
int setgroups:setgroups(int, const gid_t*) arm64,mips,mips64,x86_64
int setpgid(pid_t, pid_t) all
-pid_t vfork(void) arm
int setregid:setregid32(gid_t, gid_t) arm,x86
int setregid:setregid(gid_t, gid_t) arm64,mips,mips64,x86_64
int chroot(const char*) all
@@ -333,7 +332,7 @@
int __set_thread_area:set_thread_area(void*) x86
# vdso stuff.
-int clock_gettime(clockid_t, timespec*) arm,mips,mips64,x86
-int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86_64
-int gettimeofday(timeval*, timezone*) arm,mips,mips64,x86
-int __gettimeofday:gettimeofday(timeval*, timezone*) arm64,x86_64
+int clock_gettime(clockid_t, timespec*) arm,mips,mips64
+int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86,x86_64
+int gettimeofday(timeval*, timezone*) arm,mips,mips64
+int __gettimeofday:gettimeofday(timeval*, timezone*) arm64,x86,x86_64
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index 6ef81bb..b5283f6 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -39,10 +39,10 @@
arch-arm/bionic/__bionic_clone.S \
arch-arm/bionic/_exit_with_stack_teardown.S \
arch-arm/bionic/libgcc_compat.c \
- arch-arm/bionic/libgcc_protect_unwind.c \
arch-arm/bionic/__restore.S \
arch-arm/bionic/setjmp.S \
arch-arm/bionic/syscall.S \
+ arch-arm/bionic/vfork.S \
libc_arch_static_src_files_arm := arch-arm/bionic/exidx_static.c
libc_arch_dynamic_src_files_arm := arch-arm/bionic/exidx_dynamic.c
diff --git a/libc/arch-arm/bionic/libgcc_protect_unwind.c b/libc/arch-arm/bionic/libgcc_protect_unwind.c
deleted file mode 100644
index 6d758fc..0000000
--- a/libc/arch-arm/bionic/libgcc_protect_unwind.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-// TODO: This file should go away once unwinder migration to libc++.so is complete.
-
-extern char _Unwind_Backtrace __attribute((visibility("protected")));
-extern char __gnu_Unwind_Find_exidx __attribute((visibility("protected")));
-extern char __gnu_Unwind_Restore_VFP_D __attribute((visibility("protected")));
-extern char __gnu_Unwind_Restore_VFP __attribute((visibility("protected")));
-extern char __gnu_Unwind_Restore_VFP_D_16_to_31 __attribute((visibility("protected")));
-extern char __gnu_Unwind_Restore_WMMXD __attribute((visibility("protected")));
-extern char __gnu_Unwind_Restore_WMMXC __attribute((visibility("protected")));
-extern char _Unwind_GetCFA __attribute((visibility("protected")));
-extern char __gnu_Unwind_RaiseException __attribute((visibility("protected")));
-extern char __gnu_Unwind_ForcedUnwind __attribute((visibility("protected")));
-extern char __gnu_Unwind_Resume __attribute((visibility("protected")));
-extern char __gnu_Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
-extern char _Unwind_Complete __attribute((visibility("protected")));
-extern char _Unwind_DeleteException __attribute((visibility("protected")));
-extern char _Unwind_VRS_Get __attribute((visibility("protected")));
-extern char _Unwind_VRS_Set __attribute((visibility("protected")));
-extern char __gnu_Unwind_Backtrace __attribute((visibility("protected")));
-extern char _Unwind_VRS_Pop __attribute((visibility("protected")));
-extern char __gnu_Unwind_Save_VFP_D __attribute((visibility("protected")));
-extern char __gnu_Unwind_Save_VFP __attribute((visibility("protected")));
-extern char __gnu_Unwind_Save_VFP_D_16_to_31 __attribute((visibility("protected")));
-extern char __gnu_Unwind_Save_WMMXD __attribute((visibility("protected")));
-extern char __gnu_Unwind_Save_WMMXC __attribute((visibility("protected")));
-extern char ___Unwind_RaiseException __attribute((visibility("protected")));
-extern char _Unwind_RaiseException __attribute((visibility("protected")));
-extern char ___Unwind_Resume __attribute((visibility("protected")));
-extern char _Unwind_Resume __attribute((visibility("protected")));
-extern char ___Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
-extern char _Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
-extern char ___Unwind_ForcedUnwind __attribute((visibility("protected")));
-extern char _Unwind_ForcedUnwind __attribute((visibility("protected")));
-extern char ___Unwind_Backtrace __attribute((visibility("protected")));
-extern char _Unwind_GetRegionStart __attribute((visibility("protected")));
-extern char _Unwind_GetLanguageSpecificData __attribute((visibility("protected")));
-extern char _Unwind_GetDataRelBase __attribute((visibility("protected")));
-extern char _Unwind_GetTextRelBase __attribute((visibility("protected")));
-
-void* __bionic_libgcc_unwind_symbols[] = {
- &_Unwind_Backtrace,
- &__gnu_Unwind_Find_exidx,
- &__gnu_Unwind_Restore_VFP_D,
- &__gnu_Unwind_Restore_VFP,
- &__gnu_Unwind_Restore_VFP_D_16_to_31,
- &__gnu_Unwind_Restore_WMMXD,
- &__gnu_Unwind_Restore_WMMXC,
- &_Unwind_GetCFA,
- &__gnu_Unwind_RaiseException,
- &__gnu_Unwind_ForcedUnwind,
- &__gnu_Unwind_Resume,
- &__gnu_Unwind_Resume_or_Rethrow,
- &_Unwind_Complete,
- &_Unwind_DeleteException,
- &_Unwind_VRS_Get,
- &_Unwind_VRS_Set,
- &__gnu_Unwind_Backtrace,
- &_Unwind_VRS_Pop,
- &__gnu_Unwind_Save_VFP_D,
- &__gnu_Unwind_Save_VFP,
- &__gnu_Unwind_Save_VFP_D_16_to_31,
- &__gnu_Unwind_Save_WMMXD,
- &__gnu_Unwind_Save_WMMXC,
- &___Unwind_RaiseException,
- &_Unwind_RaiseException,
- &___Unwind_Resume,
- &_Unwind_Resume,
- &___Unwind_Resume_or_Rethrow,
- &_Unwind_Resume_or_Rethrow,
- &___Unwind_ForcedUnwind,
- &_Unwind_ForcedUnwind,
- &___Unwind_Backtrace,
- &_Unwind_GetRegionStart,
- &_Unwind_GetLanguageSpecificData,
- &_Unwind_GetDataRelBase,
- &_Unwind_GetTextRelBase,
-};
diff --git a/libc/arch-arm/bionic/vfork.S b/libc/arch-arm/bionic/vfork.S
new file mode 100644
index 0000000..1b7cbad
--- /dev/null
+++ b/libc/arch-arm/bionic/vfork.S
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 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 <private/bionic_asm.h>
+
+ENTRY(vfork)
+ // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
+ mrc p15, 0, r3, c13, c0, 3
+ ldr r3, [r3, #4]
+ mov r0, #0
+ str r0, [r3, #12]
+
+ mov ip, r7
+ ldr r7, =__NR_vfork
+ swi #0
+ mov r7, ip
+ cmn r0, #(MAX_ERRNO + 1)
+ bxls lr
+ neg r0, r0
+ b __set_errno_internal
+END(vfork)
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S b/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
index a2e9c22..3692f04 100644
--- a/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
+++ b/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,191 +26,7 @@
* SUCH DAMAGE.
*/
-#include <private/bionic_asm.h>
-#include <private/libc_events.h>
+// Indicate which memcpy base file to include.
+#define MEMCPY_BASE "memcpy_base.S"
- .syntax unified
-
- .thumb
- .thumb_func
-
-// Get the length of src string, then get the source of the dst string.
-// Check that the two lengths together don't exceed the threshold, then
-// do a memcpy of the data.
-ENTRY(__strcat_chk)
- pld [r0, #0]
- push {r0, lr}
- .cfi_def_cfa_offset 8
- .cfi_rel_offset r0, 0
- .cfi_rel_offset lr, 4
- push {r4, r5}
- .cfi_adjust_cfa_offset 8
- .cfi_rel_offset r4, 0
- .cfi_rel_offset r5, 4
-
- mov lr, r2
-
- // Save the dst register to r5
- mov r5, r0
-
- // Zero out r4
- eor r4, r4, r4
-
- // r1 contains the address of the string to count.
-.L_strlen_start:
- mov r0, r1
- ands r3, r1, #7
- beq .L_mainloop
-
- // Align to a double word (64 bits).
- rsb r3, r3, #8
- lsls ip, r3, #31
- beq .L_align_to_32
-
- ldrb r2, [r1], #1
- cbz r2, .L_update_count_and_finish
-
-.L_align_to_32:
- bcc .L_align_to_64
- ands ip, r3, #2
- beq .L_align_to_64
-
- ldrb r2, [r1], #1
- cbz r2, .L_update_count_and_finish
- ldrb r2, [r1], #1
- cbz r2, .L_update_count_and_finish
-
-.L_align_to_64:
- tst r3, #4
- beq .L_mainloop
- ldr r3, [r1], #4
-
- sub ip, r3, #0x01010101
- bic ip, ip, r3
- ands ip, ip, #0x80808080
- bne .L_zero_in_second_register
-
- .p2align 2
-.L_mainloop:
- ldrd r2, r3, [r1], #8
-
- pld [r1, #64]
-
- sub ip, r2, #0x01010101
- bic ip, ip, r2
- ands ip, ip, #0x80808080
- bne .L_zero_in_first_register
-
- sub ip, r3, #0x01010101
- bic ip, ip, r3
- ands ip, ip, #0x80808080
- bne .L_zero_in_second_register
- b .L_mainloop
-
-.L_update_count_and_finish:
- sub r3, r1, r0
- sub r3, r3, #1
- b .L_finish
-
-.L_zero_in_first_register:
- sub r3, r1, r0
- lsls r2, ip, #17
- bne .L_sub8_and_finish
- bcs .L_sub7_and_finish
- lsls ip, ip, #1
- bne .L_sub6_and_finish
-
- sub r3, r3, #5
- b .L_finish
-
-.L_sub8_and_finish:
- sub r3, r3, #8
- b .L_finish
-
-.L_sub7_and_finish:
- sub r3, r3, #7
- b .L_finish
-
-.L_sub6_and_finish:
- sub r3, r3, #6
- b .L_finish
-
-.L_zero_in_second_register:
- sub r3, r1, r0
- lsls r2, ip, #17
- bne .L_sub4_and_finish
- bcs .L_sub3_and_finish
- lsls ip, ip, #1
- bne .L_sub2_and_finish
-
- sub r3, r3, #1
- b .L_finish
-
-.L_sub4_and_finish:
- sub r3, r3, #4
- b .L_finish
-
-.L_sub3_and_finish:
- sub r3, r3, #3
- b .L_finish
-
-.L_sub2_and_finish:
- sub r3, r3, #2
-
-.L_finish:
- cmp r4, #0
- bne .L_strlen_done
-
- // Time to get the dst string length.
- mov r1, r5
-
- // Save the original source address to r5.
- mov r5, r0
-
- // Save the current length (adding 1 for the terminator).
- add r4, r3, #1
- b .L_strlen_start
-
- // r0 holds the pointer to the dst string.
- // r3 holds the dst string length.
- // r4 holds the src string length + 1.
-.L_strlen_done:
- add r2, r3, r4
- cmp r2, lr
- bhi __strcat_chk_failed
-
- // Set up the registers for the memcpy code.
- mov r1, r5
- pld [r1, #64]
- mov r2, r4
- add r0, r0, r3
- pop {r4, r5}
-END(__strcat_chk)
-
-#define MEMCPY_BASE __strcat_chk_memcpy_base
-#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
-
-#include "memcpy_base.S"
-
-ENTRY_PRIVATE(__strcat_chk_failed)
- .cfi_def_cfa_offset 8
- .cfi_rel_offset r0, 0
- .cfi_rel_offset lr, 4
- .cfi_adjust_cfa_offset 8
- .cfi_rel_offset r4, 0
- .cfi_rel_offset r5, 4
-
- ldr r0, error_message
- ldr r1, error_code
-1:
- add r0, pc
- bl __fortify_chk_fail
-error_code:
- .word BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
-error_message:
- .word error_string-(1b+4)
-END(__strcat_chk_failed)
-
- .data
-error_string:
- .string "strcat: prevented write past end of buffer"
+#include "__strcat_chk_common.S"
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcat_chk_common.S b/libc/arch-arm/cortex-a15/bionic/__strcat_chk_common.S
new file mode 100644
index 0000000..de66967
--- /dev/null
+++ b/libc/arch-arm/cortex-a15/bionic/__strcat_chk_common.S
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+#include <private/libc_events.h>
+
+ .syntax unified
+
+ .thumb
+ .thumb_func
+
+// Get the length of src string, then get the source of the dst string.
+// Check that the two lengths together don't exceed the threshold, then
+// do a memcpy of the data.
+ENTRY(__strcat_chk)
+ pld [r0, #0]
+ push {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+ push {r4, r5}
+ .cfi_adjust_cfa_offset 8
+ .cfi_rel_offset r4, 0
+ .cfi_rel_offset r5, 4
+
+ mov lr, r2
+
+ // Save the dst register to r5
+ mov r5, r0
+
+ // Zero out r4
+ eor r4, r4, r4
+
+ // r1 contains the address of the string to count.
+.L_strlen_start:
+ mov r0, r1
+ ands r3, r1, #7
+ beq .L_mainloop
+
+ // Align to a double word (64 bits).
+ rsb r3, r3, #8
+ lsls ip, r3, #31
+ beq .L_align_to_32
+
+ ldrb r2, [r1], #1
+ cbz r2, .L_update_count_and_finish
+
+.L_align_to_32:
+ bcc .L_align_to_64
+ ands ip, r3, #2
+ beq .L_align_to_64
+
+ ldrb r2, [r1], #1
+ cbz r2, .L_update_count_and_finish
+ ldrb r2, [r1], #1
+ cbz r2, .L_update_count_and_finish
+
+.L_align_to_64:
+ tst r3, #4
+ beq .L_mainloop
+ ldr r3, [r1], #4
+
+ sub ip, r3, #0x01010101
+ bic ip, ip, r3
+ ands ip, ip, #0x80808080
+ bne .L_zero_in_second_register
+
+ .p2align 2
+.L_mainloop:
+ ldrd r2, r3, [r1], #8
+
+ pld [r1, #64]
+
+ sub ip, r2, #0x01010101
+ bic ip, ip, r2
+ ands ip, ip, #0x80808080
+ bne .L_zero_in_first_register
+
+ sub ip, r3, #0x01010101
+ bic ip, ip, r3
+ ands ip, ip, #0x80808080
+ bne .L_zero_in_second_register
+ b .L_mainloop
+
+.L_update_count_and_finish:
+ sub r3, r1, r0
+ sub r3, r3, #1
+ b .L_finish
+
+.L_zero_in_first_register:
+ sub r3, r1, r0
+ lsls r2, ip, #17
+ bne .L_sub8_and_finish
+ bcs .L_sub7_and_finish
+ lsls ip, ip, #1
+ bne .L_sub6_and_finish
+
+ sub r3, r3, #5
+ b .L_finish
+
+.L_sub8_and_finish:
+ sub r3, r3, #8
+ b .L_finish
+
+.L_sub7_and_finish:
+ sub r3, r3, #7
+ b .L_finish
+
+.L_sub6_and_finish:
+ sub r3, r3, #6
+ b .L_finish
+
+.L_zero_in_second_register:
+ sub r3, r1, r0
+ lsls r2, ip, #17
+ bne .L_sub4_and_finish
+ bcs .L_sub3_and_finish
+ lsls ip, ip, #1
+ bne .L_sub2_and_finish
+
+ sub r3, r3, #1
+ b .L_finish
+
+.L_sub4_and_finish:
+ sub r3, r3, #4
+ b .L_finish
+
+.L_sub3_and_finish:
+ sub r3, r3, #3
+ b .L_finish
+
+.L_sub2_and_finish:
+ sub r3, r3, #2
+
+.L_finish:
+ cmp r4, #0
+ bne .L_strlen_done
+
+ // Time to get the dst string length.
+ mov r1, r5
+
+ // Save the original source address to r5.
+ mov r5, r0
+
+ // Save the current length (adding 1 for the terminator).
+ add r4, r3, #1
+ b .L_strlen_start
+
+ // r0 holds the pointer to the dst string.
+ // r3 holds the dst string length.
+ // r4 holds the src string length + 1.
+.L_strlen_done:
+ add r2, r3, r4
+ cmp r2, lr
+ bhi .L_strcat_chk_failed
+
+ // Set up the registers for the memcpy code.
+ mov r1, r5
+ pld [r1, #64]
+ mov r2, r4
+ add r0, r0, r3
+ pop {r4, r5}
+ .cfi_adjust_cfa_offset -8
+ .cfi_restore r4
+ .cfi_restore r5
+
+#include MEMCPY_BASE
+
+ // Undo the above cfi directives
+ .cfi_adjust_cfa_offset 8
+ .cfi_rel_offset r4, 0
+ .cfi_rel_offset r5, 4
+.L_strcat_chk_failed:
+ ldr r0, error_message
+ ldr r1, error_code
+1:
+ add r0, pc
+ bl __fortify_chk_fail
+error_code:
+ .word BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
+error_message:
+ .word error_string-(1b+4)
+END(__strcat_chk)
+
+ .data
+error_string:
+ .string "strcat: prevented write past end of buffer"
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
index db76686..d8cb3d9 100644
--- a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
+++ b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,155 +26,7 @@
* SUCH DAMAGE.
*/
-#include <private/bionic_asm.h>
-#include <private/libc_events.h>
+// Indicate which memcpy base file to include.
+#define MEMCPY_BASE "memcpy_base.S"
- .syntax unified
-
- .thumb
- .thumb_func
-
-// Get the length of the source string first, then do a memcpy of the data
-// instead of a strcpy.
-ENTRY(__strcpy_chk)
- pld [r0, #0]
- push {r0, lr}
- .cfi_def_cfa_offset 8
- .cfi_rel_offset r0, 0
- .cfi_rel_offset lr, 4
-
- mov lr, r2
- mov r0, r1
-
- ands r3, r1, #7
- beq .L_mainloop
-
- // Align to a double word (64 bits).
- rsb r3, r3, #8
- lsls ip, r3, #31
- beq .L_align_to_32
-
- ldrb r2, [r0], #1
- cbz r2, .L_update_count_and_finish
-
-.L_align_to_32:
- bcc .L_align_to_64
- ands ip, r3, #2
- beq .L_align_to_64
-
- ldrb r2, [r0], #1
- cbz r2, .L_update_count_and_finish
- ldrb r2, [r0], #1
- cbz r2, .L_update_count_and_finish
-
-.L_align_to_64:
- tst r3, #4
- beq .L_mainloop
- ldr r3, [r0], #4
-
- sub ip, r3, #0x01010101
- bic ip, ip, r3
- ands ip, ip, #0x80808080
- bne .L_zero_in_second_register
-
- .p2align 2
-.L_mainloop:
- ldrd r2, r3, [r0], #8
-
- pld [r0, #64]
-
- sub ip, r2, #0x01010101
- bic ip, ip, r2
- ands ip, ip, #0x80808080
- bne .L_zero_in_first_register
-
- sub ip, r3, #0x01010101
- bic ip, ip, r3
- ands ip, ip, #0x80808080
- bne .L_zero_in_second_register
- b .L_mainloop
-
-.L_update_count_and_finish:
- sub r3, r0, r1
- sub r3, r3, #1
- b .L_check_size
-
-.L_zero_in_first_register:
- sub r3, r0, r1
- lsls r2, ip, #17
- bne .L_sub8_and_finish
- bcs .L_sub7_and_finish
- lsls ip, ip, #1
- bne .L_sub6_and_finish
-
- sub r3, r3, #5
- b .L_check_size
-
-.L_sub8_and_finish:
- sub r3, r3, #8
- b .L_check_size
-
-.L_sub7_and_finish:
- sub r3, r3, #7
- b .L_check_size
-
-.L_sub6_and_finish:
- sub r3, r3, #6
- b .L_check_size
-
-.L_zero_in_second_register:
- sub r3, r0, r1
- lsls r2, ip, #17
- bne .L_sub4_and_finish
- bcs .L_sub3_and_finish
- lsls ip, ip, #1
- bne .L_sub2_and_finish
-
- sub r3, r3, #1
- b .L_check_size
-
-.L_sub4_and_finish:
- sub r3, r3, #4
- b .L_check_size
-
-.L_sub3_and_finish:
- sub r3, r3, #3
- b .L_check_size
-
-.L_sub2_and_finish:
- sub r3, r3, #2
-
-.L_check_size:
- pld [r1, #0]
- pld [r1, #64]
- ldr r0, [sp]
- cmp r3, lr
- bhs __strcpy_chk_failed
-
- // Add 1 for copy length to get the string terminator.
- add r2, r3, #1
-END(__strcpy_chk)
-
-#define MEMCPY_BASE __strcpy_chk_memcpy_base
-#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
-#include "memcpy_base.S"
-
-ENTRY_PRIVATE(__strcpy_chk_failed)
- .cfi_def_cfa_offset 8
- .cfi_rel_offset r0, 0
- .cfi_rel_offset lr, 4
-
- ldr r0, error_message
- ldr r1, error_code
-1:
- add r0, pc
- bl __fortify_chk_fail
-error_code:
- .word BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
-error_message:
- .word error_string-(1b+4)
-END(__strcpy_chk_failed)
-
- .data
-error_string:
- .string "strcpy: prevented write past end of buffer"
+#include "__strcpy_chk_common.S"
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk_common.S b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk_common.S
new file mode 100644
index 0000000..69ebcb4
--- /dev/null
+++ b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk_common.S
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <private/bionic_asm.h>
+#include <private/libc_events.h>
+
+ .syntax unified
+
+ .thumb
+ .thumb_func
+
+// Get the length of the source string first, then do a memcpy of the data
+// instead of a strcpy.
+ENTRY(__strcpy_chk)
+ pld [r0, #0]
+ push {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+
+ mov lr, r2
+ mov r0, r1
+
+ ands r3, r1, #7
+ beq .L_mainloop
+
+ // Align to a double word (64 bits).
+ rsb r3, r3, #8
+ lsls ip, r3, #31
+ beq .L_align_to_32
+
+ ldrb r2, [r0], #1
+ cbz r2, .L_update_count_and_finish
+
+.L_align_to_32:
+ bcc .L_align_to_64
+ ands ip, r3, #2
+ beq .L_align_to_64
+
+ ldrb r2, [r0], #1
+ cbz r2, .L_update_count_and_finish
+ ldrb r2, [r0], #1
+ cbz r2, .L_update_count_and_finish
+
+.L_align_to_64:
+ tst r3, #4
+ beq .L_mainloop
+ ldr r3, [r0], #4
+
+ sub ip, r3, #0x01010101
+ bic ip, ip, r3
+ ands ip, ip, #0x80808080
+ bne .L_zero_in_second_register
+
+ .p2align 2
+.L_mainloop:
+ ldrd r2, r3, [r0], #8
+
+ pld [r0, #64]
+
+ sub ip, r2, #0x01010101
+ bic ip, ip, r2
+ ands ip, ip, #0x80808080
+ bne .L_zero_in_first_register
+
+ sub ip, r3, #0x01010101
+ bic ip, ip, r3
+ ands ip, ip, #0x80808080
+ bne .L_zero_in_second_register
+ b .L_mainloop
+
+.L_update_count_and_finish:
+ sub r3, r0, r1
+ sub r3, r3, #1
+ b .L_check_size
+
+.L_zero_in_first_register:
+ sub r3, r0, r1
+ lsls r2, ip, #17
+ bne .L_sub8_and_finish
+ bcs .L_sub7_and_finish
+ lsls ip, ip, #1
+ bne .L_sub6_and_finish
+
+ sub r3, r3, #5
+ b .L_check_size
+
+.L_sub8_and_finish:
+ sub r3, r3, #8
+ b .L_check_size
+
+.L_sub7_and_finish:
+ sub r3, r3, #7
+ b .L_check_size
+
+.L_sub6_and_finish:
+ sub r3, r3, #6
+ b .L_check_size
+
+.L_zero_in_second_register:
+ sub r3, r0, r1
+ lsls r2, ip, #17
+ bne .L_sub4_and_finish
+ bcs .L_sub3_and_finish
+ lsls ip, ip, #1
+ bne .L_sub2_and_finish
+
+ sub r3, r3, #1
+ b .L_check_size
+
+.L_sub4_and_finish:
+ sub r3, r3, #4
+ b .L_check_size
+
+.L_sub3_and_finish:
+ sub r3, r3, #3
+ b .L_check_size
+
+.L_sub2_and_finish:
+ sub r3, r3, #2
+
+.L_check_size:
+ pld [r1, #0]
+ pld [r1, #64]
+ ldr r0, [sp]
+ cmp r3, lr
+ bhs .L_strcpy_chk_failed
+
+ // Add 1 for copy length to get the string terminator.
+ add r2, r3, #1
+
+#include MEMCPY_BASE
+
+.L_strcpy_chk_failed:
+ ldr r0, error_message
+ ldr r1, error_code
+1:
+ add r0, pc
+ bl __fortify_chk_fail
+error_code:
+ .word BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
+error_message:
+ .word error_string-(1b+4)
+END(__strcpy_chk)
+
+ .data
+error_string:
+ .string "strcpy: prevented write past end of buffer"
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy.S b/libc/arch-arm/cortex-a15/bionic/memcpy.S
index 410b663..537f3de 100644
--- a/libc/arch-arm/cortex-a15/bionic/memcpy.S
+++ b/libc/arch-arm/cortex-a15/bionic/memcpy.S
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,79 +25,8 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-/*
- * Copyright (c) 2013 ARM Ltd
- * 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. The name of the company may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
- */
-// Prototype: void *memcpy (void *dst, const void *src, size_t count).
+// Indicate which memcpy base file to include.
+#define MEMCPY_BASE "memcpy_base.S"
-#include <private/bionic_asm.h>
-#include <private/libc_events.h>
-
- .text
- .syntax unified
- .fpu neon
-
-ENTRY(__memcpy_chk)
- cmp r2, r3
- bhi __memcpy_chk_fail
-
- // Fall through to memcpy...
-END(__memcpy_chk)
-
-ENTRY(memcpy)
- pld [r1, #64]
- push {r0, lr}
- .cfi_def_cfa_offset 8
- .cfi_rel_offset r0, 0
- .cfi_rel_offset lr, 4
-END(memcpy)
-
-#define MEMCPY_BASE __memcpy_base
-#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
-#include "memcpy_base.S"
-
-ENTRY_PRIVATE(__memcpy_chk_fail)
- // Preserve lr for backtrace.
- push {lr}
- .cfi_def_cfa_offset 4
- .cfi_rel_offset lr, 0
-
- ldr r0, error_message
- ldr r1, error_code
-1:
- add r0, pc
- bl __fortify_chk_fail
-error_code:
- .word BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
-error_message:
- .word error_string-(1b+8)
-END(__memcpy_chk_fail)
-
- .data
-error_string:
- .string "memcpy: prevented write past end of buffer"
+#include "memcpy_common.S"
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy_base.S b/libc/arch-arm/cortex-a15/bionic/memcpy_base.S
index 2a73852..aac737d 100644
--- a/libc/arch-arm/cortex-a15/bionic/memcpy_base.S
+++ b/libc/arch-arm/cortex-a15/bionic/memcpy_base.S
@@ -53,11 +53,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-ENTRY_PRIVATE(MEMCPY_BASE)
- .cfi_def_cfa_offset 8
- .cfi_rel_offset r0, 0
- .cfi_rel_offset lr, 4
-
+.L_memcpy_base:
// Assumes that n >= 0, and dst, src are valid pointers.
// For any sizes less than 832 use the neon code that doesn't
// care about the src alignment. This avoids any checks
@@ -168,12 +164,6 @@
eor r3, r0, r1
ands r3, r3, #0x3
bne .L_copy_unknown_alignment
-END(MEMCPY_BASE)
-
-ENTRY_PRIVATE(MEMCPY_BASE_ALIGNED)
- .cfi_def_cfa_offset 8
- .cfi_rel_offset r0, 0
- .cfi_rel_offset lr, 4
// To try and improve performance, stack layout changed,
// i.e., not keeping the stack looking like users expect
@@ -185,7 +175,7 @@
strd r6, r7, [sp, #-8]!
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r6, 0
- .cfi_rel_offset r7, 0
+ .cfi_rel_offset r7, 4
strd r8, r9, [sp, #-8]!
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r8, 0
@@ -291,10 +281,28 @@
// Restore registers: optimized pop {r0, pc}
ldrd r8, r9, [sp], #8
+ .cfi_adjust_cfa_offset -8
+ .cfi_restore r8
+ .cfi_restore r9
ldrd r6, r7, [sp], #8
+ .cfi_adjust_cfa_offset -8
+ .cfi_restore r6
+ .cfi_restore r7
ldrd r4, r5, [sp], #8
+ .cfi_adjust_cfa_offset -8
+ .cfi_restore r4
+ .cfi_restore r5
pop {r0, pc}
+ // Put the cfi directives back for the below instructions.
+ .cfi_adjust_cfa_offset 24
+ .cfi_rel_offset r4, 0
+ .cfi_rel_offset r5, 4
+ .cfi_rel_offset r6, 8
+ .cfi_rel_offset r7, 12
+ .cfi_rel_offset r8, 16
+ .cfi_rel_offset r9, 20
+
.L_dst_not_word_aligned:
// Align dst to word.
rsb ip, ip, #4
@@ -315,4 +323,12 @@
// Src is guaranteed to be at least word aligned by this point.
b .L_word_aligned
-END(MEMCPY_BASE_ALIGNED)
+
+ // Undo any cfi directives from above.
+ .cfi_adjust_cfa_offset -24
+ .cfi_restore r4
+ .cfi_restore r5
+ .cfi_restore r6
+ .cfi_restore r7
+ .cfi_restore r8
+ .cfi_restore r9
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy_common.S b/libc/arch-arm/cortex-a15/bionic/memcpy_common.S
new file mode 100644
index 0000000..464fb46
--- /dev/null
+++ b/libc/arch-arm/cortex-a15/bionic/memcpy_common.S
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 2013 ARM Ltd
+ * 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. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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 <private/bionic_asm.h>
+#include <private/libc_events.h>
+
+ .text
+ .syntax unified
+ .fpu neon
+
+ENTRY(__memcpy_chk)
+ cmp r2, r3
+ bhi .L_memcpy_chk_fail
+
+ // Fall through to memcpy...
+END(__memcpy_chk)
+
+// Prototype: void *memcpy (void *dst, const void *src, size_t count).
+ENTRY(memcpy)
+ pld [r1, #64]
+ push {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+
+#include MEMCPY_BASE
+
+ // Undo the cfi instructions from above.
+ .cfi_def_cfa_offset 0
+ .cfi_restore r0
+ .cfi_restore lr
+.L_memcpy_chk_fail:
+ // Preserve lr for backtrace.
+ push {lr}
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset lr, 0
+
+ ldr r0, error_message
+ ldr r1, error_code
+1:
+ add r0, pc
+ bl __fortify_chk_fail
+error_code:
+ .word BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
+error_message:
+ .word error_string-(1b+8)
+END(memcpy)
+
+ .data
+error_string:
+ .string "memcpy: prevented write past end of buffer"
diff --git a/libc/arch-arm/cortex-a15/bionic/strcat.S b/libc/arch-arm/cortex-a15/bionic/strcat.S
index b95be94..b174aa9 100644
--- a/libc/arch-arm/cortex-a15/bionic/strcat.S
+++ b/libc/arch-arm/cortex-a15/bionic/strcat.S
@@ -70,7 +70,7 @@
.macro m_scan_byte
ldrb r3, [r0]
- cbz r3, strcat_r0_scan_done
+ cbz r3, .L_strcat_r0_scan_done
add r0, #1
.endm // m_scan_byte
@@ -84,10 +84,10 @@
// Quick check to see if src is empty.
ldrb r2, [r1]
pld [r1, #0]
- cbnz r2, strcat_continue
+ cbnz r2, .L_strcat_continue
bx lr
-strcat_continue:
+.L_strcat_continue:
// To speed up really small dst strings, unroll checking the first 4 bytes.
m_push
m_scan_byte
@@ -96,95 +96,95 @@
m_scan_byte
ands r3, r0, #7
- beq strcat_mainloop
+ beq .L_strcat_mainloop
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
- beq strcat_align_to_32
+ beq .L_strcat_align_to_32
ldrb r5, [r0]
- cbz r5, strcat_r0_scan_done
+ cbz r5, .L_strcat_r0_scan_done
add r0, r0, #1
-strcat_align_to_32:
- bcc strcat_align_to_64
+.L_strcat_align_to_32:
+ bcc .L_strcat_align_to_64
ldrb r2, [r0]
- cbz r2, strcat_r0_scan_done
+ cbz r2, .L_strcat_r0_scan_done
add r0, r0, #1
ldrb r4, [r0]
- cbz r4, strcat_r0_scan_done
+ cbz r4, .L_strcat_r0_scan_done
add r0, r0, #1
-strcat_align_to_64:
+.L_strcat_align_to_64:
tst r3, #4
- beq strcat_mainloop
+ beq .L_strcat_mainloop
ldr r3, [r0], #4
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
- bne strcat_zero_in_second_register
- b strcat_mainloop
+ bne .L_strcat_zero_in_second_register
+ b .L_strcat_mainloop
-strcat_r0_scan_done:
+.L_strcat_r0_scan_done:
// For short copies, hard-code checking the first 8 bytes since this
// new code doesn't win until after about 8 bytes.
- m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
- m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
- m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
- m_copy_byte reg=r5, cmd=cbz, label=strcpy_finish
- m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
- m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
- m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
- m_copy_byte reg=r5, cmd=cbnz, label=strcpy_continue
+ m_copy_byte reg=r2, cmd=cbz, label=.L_strcpy_finish
+ m_copy_byte reg=r3, cmd=cbz, label=.L_strcpy_finish
+ m_copy_byte reg=r4, cmd=cbz, label=.L_strcpy_finish
+ m_copy_byte reg=r5, cmd=cbz, label=.L_strcpy_finish
+ m_copy_byte reg=r2, cmd=cbz, label=.L_strcpy_finish
+ m_copy_byte reg=r3, cmd=cbz, label=.L_strcpy_finish
+ m_copy_byte reg=r4, cmd=cbz, label=.L_strcpy_finish
+ m_copy_byte reg=r5, cmd=cbnz, label=.L_strcpy_continue
-strcpy_finish:
+.L_strcpy_finish:
m_pop
-strcpy_continue:
+.L_strcpy_continue:
ands r3, r0, #7
- beq strcpy_check_src_align
+ beq .L_strcpy_check_src_align
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
- beq strcpy_align_to_32
+ beq .L_strcpy_align_to_32
ldrb r2, [r1], #1
strb r2, [r0], #1
- cbz r2, strcpy_complete
+ cbz r2, .L_strcpy_complete
-strcpy_align_to_32:
- bcc strcpy_align_to_64
+.L_strcpy_align_to_32:
+ bcc .L_strcpy_align_to_64
ldrb r2, [r1], #1
strb r2, [r0], #1
- cbz r2, strcpy_complete
+ cbz r2, .L_strcpy_complete
ldrb r2, [r1], #1
strb r2, [r0], #1
- cbz r2, strcpy_complete
+ cbz r2, .L_strcpy_complete
-strcpy_align_to_64:
+.L_strcpy_align_to_64:
tst r3, #4
- beq strcpy_check_src_align
+ beq .L_strcpy_check_src_align
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
- bne strcpy_zero_in_first_register
+ bne .L_strcpy_zero_in_first_register
str r2, [r0], #4
-strcpy_check_src_align:
+.L_strcpy_check_src_align:
// At this point dst is aligned to a double word, check if src
// is also aligned to a double word.
ands r3, r1, #7
- bne strcpy_unaligned_copy
+ bne .L_strcpy_unaligned_copy
.p2align 2
-strcpy_mainloop:
+.L_strcpy_mainloop:
ldrd r2, r3, [r1], #8
pld [r1, #64]
@@ -192,128 +192,128 @@
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
- bne strcpy_zero_in_first_register
+ bne .L_strcpy_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
- bne strcpy_zero_in_second_register
+ bne .L_strcpy_zero_in_second_register
strd r2, r3, [r0], #8
- b strcpy_mainloop
+ b .L_strcpy_mainloop
-strcpy_complete:
+.L_strcpy_complete:
m_pop
-strcpy_zero_in_first_register:
+.L_strcpy_zero_in_first_register:
lsls lr, ip, #17
- bne strcpy_copy1byte
- bcs strcpy_copy2bytes
+ bne .L_strcpy_copy1byte
+ bcs .L_strcpy_copy2bytes
lsls ip, ip, #1
- bne strcpy_copy3bytes
+ bne .L_strcpy_copy3bytes
-strcpy_copy4bytes:
+.L_strcpy_copy4bytes:
// Copy 4 bytes to the destiniation.
str r2, [r0]
m_pop
-strcpy_copy1byte:
+.L_strcpy_copy1byte:
strb r2, [r0]
m_pop
-strcpy_copy2bytes:
+.L_strcpy_copy2bytes:
strh r2, [r0]
m_pop
-strcpy_copy3bytes:
+.L_strcpy_copy3bytes:
strh r2, [r0], #2
lsr r2, #16
strb r2, [r0]
m_pop
-strcpy_zero_in_second_register:
+.L_strcpy_zero_in_second_register:
lsls lr, ip, #17
- bne strcpy_copy5bytes
- bcs strcpy_copy6bytes
+ bne .L_strcpy_copy5bytes
+ bcs .L_strcpy_copy6bytes
lsls ip, ip, #1
- bne strcpy_copy7bytes
+ bne .L_strcpy_copy7bytes
// Copy 8 bytes to the destination.
strd r2, r3, [r0]
m_pop
-strcpy_copy5bytes:
+.L_strcpy_copy5bytes:
str r2, [r0], #4
strb r3, [r0]
m_pop
-strcpy_copy6bytes:
+.L_strcpy_copy6bytes:
str r2, [r0], #4
strh r3, [r0]
m_pop
-strcpy_copy7bytes:
+.L_strcpy_copy7bytes:
str r2, [r0], #4
strh r3, [r0], #2
lsr r3, #16
strb r3, [r0]
m_pop
-strcpy_unaligned_copy:
+.L_strcpy_unaligned_copy:
// Dst is aligned to a double word, while src is at an unknown alignment.
// There are 7 different versions of the unaligned copy code
// to prevent overreading the src. The mainloop of every single version
// will store 64 bits per loop. The difference is how much of src can
// be read without potentially crossing a page boundary.
tbb [pc, r3]
-strcpy_unaligned_branchtable:
+.L_strcpy_unaligned_branchtable:
.byte 0
- .byte ((strcpy_unalign7 - strcpy_unaligned_branchtable)/2)
- .byte ((strcpy_unalign6 - strcpy_unaligned_branchtable)/2)
- .byte ((strcpy_unalign5 - strcpy_unaligned_branchtable)/2)
- .byte ((strcpy_unalign4 - strcpy_unaligned_branchtable)/2)
- .byte ((strcpy_unalign3 - strcpy_unaligned_branchtable)/2)
- .byte ((strcpy_unalign2 - strcpy_unaligned_branchtable)/2)
- .byte ((strcpy_unalign1 - strcpy_unaligned_branchtable)/2)
+ .byte ((.L_strcpy_unalign7 - .L_strcpy_unaligned_branchtable)/2)
+ .byte ((.L_strcpy_unalign6 - .L_strcpy_unaligned_branchtable)/2)
+ .byte ((.L_strcpy_unalign5 - .L_strcpy_unaligned_branchtable)/2)
+ .byte ((.L_strcpy_unalign4 - .L_strcpy_unaligned_branchtable)/2)
+ .byte ((.L_strcpy_unalign3 - .L_strcpy_unaligned_branchtable)/2)
+ .byte ((.L_strcpy_unalign2 - .L_strcpy_unaligned_branchtable)/2)
+ .byte ((.L_strcpy_unalign1 - .L_strcpy_unaligned_branchtable)/2)
.p2align 2
// Can read 7 bytes before possibly crossing a page.
-strcpy_unalign7:
+.L_strcpy_unalign7:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
- bne strcpy_zero_in_first_register
+ bne .L_strcpy_zero_in_first_register
ldrb r3, [r1]
- cbz r3, strcpy_unalign7_copy5bytes
+ cbz r3, .L_strcpy_unalign7_copy5bytes
ldrb r4, [r1, #1]
- cbz r4, strcpy_unalign7_copy6bytes
+ cbz r4, .L_strcpy_unalign7_copy6bytes
ldrb r5, [r1, #2]
- cbz r5, strcpy_unalign7_copy7bytes
+ cbz r5, .L_strcpy_unalign7_copy7bytes
ldr r3, [r1], #4
pld [r1, #64]
lsrs ip, r3, #24
strd r2, r3, [r0], #8
- beq strcpy_unalign_return
- b strcpy_unalign7
+ beq .L_strcpy_unalign_return
+ b .L_strcpy_unalign7
-strcpy_unalign7_copy5bytes:
+.L_strcpy_unalign7_copy5bytes:
str r2, [r0], #4
strb r3, [r0]
-strcpy_unalign_return:
+.L_strcpy_unalign_return:
m_pop
-strcpy_unalign7_copy6bytes:
+.L_strcpy_unalign7_copy6bytes:
str r2, [r0], #4
strb r3, [r0], #1
strb r4, [r0], #1
m_pop
-strcpy_unalign7_copy7bytes:
+.L_strcpy_unalign7_copy7bytes:
str r2, [r0], #4
strb r3, [r0], #1
strb r4, [r0], #1
@@ -322,41 +322,41 @@
.p2align 2
// Can read 6 bytes before possibly crossing a page.
-strcpy_unalign6:
+.L_strcpy_unalign6:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
- bne strcpy_zero_in_first_register
+ bne .L_strcpy_zero_in_first_register
ldrb r4, [r1]
- cbz r4, strcpy_unalign_copy5bytes
+ cbz r4, .L_strcpy_unalign_copy5bytes
ldrb r5, [r1, #1]
- cbz r5, strcpy_unalign_copy6bytes
+ cbz r5, .L_strcpy_unalign_copy6bytes
ldr r3, [r1], #4
pld [r1, #64]
tst r3, #0xff0000
- beq strcpy_copy7bytes
+ beq .L_strcpy_copy7bytes
lsrs ip, r3, #24
strd r2, r3, [r0], #8
- beq strcpy_unalign_return
- b strcpy_unalign6
+ beq .L_strcpy_unalign_return
+ b .L_strcpy_unalign6
.p2align 2
// Can read 5 bytes before possibly crossing a page.
-strcpy_unalign5:
+.L_strcpy_unalign5:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
- bne strcpy_zero_in_first_register
+ bne .L_strcpy_zero_in_first_register
ldrb r4, [r1]
- cbz r4, strcpy_unalign_copy5bytes
+ cbz r4, .L_strcpy_unalign_copy5bytes
ldr r3, [r1], #4
@@ -365,17 +365,17 @@
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
- bne strcpy_zero_in_second_register
+ bne .L_strcpy_zero_in_second_register
strd r2, r3, [r0], #8
- b strcpy_unalign5
+ b .L_strcpy_unalign5
-strcpy_unalign_copy5bytes:
+.L_strcpy_unalign_copy5bytes:
str r2, [r0], #4
strb r4, [r0]
m_pop
-strcpy_unalign_copy6bytes:
+.L_strcpy_unalign_copy6bytes:
str r2, [r0], #4
strb r4, [r0], #1
strb r5, [r0]
@@ -383,13 +383,13 @@
.p2align 2
// Can read 4 bytes before possibly crossing a page.
-strcpy_unalign4:
+.L_strcpy_unalign4:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
- bne strcpy_zero_in_first_register
+ bne .L_strcpy_zero_in_first_register
ldr r3, [r1], #4
pld [r1, #64]
@@ -397,20 +397,20 @@
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
- bne strcpy_zero_in_second_register
+ bne .L_strcpy_zero_in_second_register
strd r2, r3, [r0], #8
- b strcpy_unalign4
+ b .L_strcpy_unalign4
.p2align 2
// Can read 3 bytes before possibly crossing a page.
-strcpy_unalign3:
+.L_strcpy_unalign3:
ldrb r2, [r1]
- cbz r2, strcpy_unalign3_copy1byte
+ cbz r2, .L_strcpy_unalign3_copy1byte
ldrb r3, [r1, #1]
- cbz r3, strcpy_unalign3_copy2bytes
+ cbz r3, .L_strcpy_unalign3_copy2bytes
ldrb r4, [r1, #2]
- cbz r4, strcpy_unalign3_copy3bytes
+ cbz r4, .L_strcpy_unalign3_copy3bytes
ldr r2, [r1], #4
ldr r3, [r1], #4
@@ -418,26 +418,26 @@
pld [r1, #64]
lsrs lr, r2, #24
- beq strcpy_copy4bytes
+ beq .L_strcpy_copy4bytes
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
- bne strcpy_zero_in_second_register
+ bne .L_strcpy_zero_in_second_register
strd r2, r3, [r0], #8
- b strcpy_unalign3
+ b .L_strcpy_unalign3
-strcpy_unalign3_copy1byte:
+.L_strcpy_unalign3_copy1byte:
strb r2, [r0]
m_pop
-strcpy_unalign3_copy2bytes:
+.L_strcpy_unalign3_copy2bytes:
strb r2, [r0], #1
strb r3, [r0]
m_pop
-strcpy_unalign3_copy3bytes:
+.L_strcpy_unalign3_copy3bytes:
strb r2, [r0], #1
strb r3, [r0], #1
strb r4, [r0]
@@ -445,34 +445,34 @@
.p2align 2
// Can read 2 bytes before possibly crossing a page.
-strcpy_unalign2:
+.L_strcpy_unalign2:
ldrb r2, [r1]
- cbz r2, strcpy_unalign_copy1byte
+ cbz r2, .L_strcpy_unalign_copy1byte
ldrb r4, [r1, #1]
- cbz r4, strcpy_unalign_copy2bytes
+ cbz r4, .L_strcpy_unalign_copy2bytes
ldr r2, [r1], #4
ldr r3, [r1], #4
pld [r1, #64]
tst r2, #0xff0000
- beq strcpy_copy3bytes
+ beq .L_strcpy_copy3bytes
lsrs ip, r2, #24
- beq strcpy_copy4bytes
+ beq .L_strcpy_copy4bytes
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
- bne strcpy_zero_in_second_register
+ bne .L_strcpy_zero_in_second_register
strd r2, r3, [r0], #8
- b strcpy_unalign2
+ b .L_strcpy_unalign2
.p2align 2
// Can read 1 byte before possibly crossing a page.
-strcpy_unalign1:
+.L_strcpy_unalign1:
ldrb r2, [r1]
- cbz r2, strcpy_unalign_copy1byte
+ cbz r2, .L_strcpy_unalign_copy1byte
ldr r2, [r1], #4
ldr r3, [r1], #4
@@ -482,27 +482,27 @@
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
- bne strcpy_zero_in_first_register
+ bne .L_strcpy_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
- bne strcpy_zero_in_second_register
+ bne .L_strcpy_zero_in_second_register
strd r2, r3, [r0], #8
- b strcpy_unalign1
+ b .L_strcpy_unalign1
-strcpy_unalign_copy1byte:
+.L_strcpy_unalign_copy1byte:
strb r2, [r0]
m_pop
-strcpy_unalign_copy2bytes:
+.L_strcpy_unalign_copy2bytes:
strb r2, [r0], #1
strb r4, [r0]
m_pop
.p2align 2
-strcat_mainloop:
+.L_strcat_mainloop:
ldrd r2, r3, [r0], #8
pld [r0, #64]
@@ -510,59 +510,59 @@
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
- bne strcat_zero_in_first_register
+ bne .L_strcat_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
- bne strcat_zero_in_second_register
- b strcat_mainloop
+ bne .L_strcat_zero_in_second_register
+ b .L_strcat_mainloop
-strcat_zero_in_first_register:
+.L_strcat_zero_in_first_register:
// Prefetch the src now, it's going to be used soon.
pld [r1, #0]
lsls lr, ip, #17
- bne strcat_sub8
- bcs strcat_sub7
+ bne .L_strcat_sub8
+ bcs .L_strcat_sub7
lsls ip, ip, #1
- bne strcat_sub6
+ bne .L_strcat_sub6
sub r0, r0, #5
- b strcat_r0_scan_done
+ b .L_strcat_r0_scan_done
-strcat_sub8:
+.L_strcat_sub8:
sub r0, r0, #8
- b strcat_r0_scan_done
+ b .L_strcat_r0_scan_done
-strcat_sub7:
+.L_strcat_sub7:
sub r0, r0, #7
- b strcat_r0_scan_done
+ b .L_strcat_r0_scan_done
-strcat_sub6:
+.L_strcat_sub6:
sub r0, r0, #6
- b strcat_r0_scan_done
+ b .L_strcat_r0_scan_done
-strcat_zero_in_second_register:
+.L_strcat_zero_in_second_register:
// Prefetch the src now, it's going to be used soon.
pld [r1, #0]
lsls lr, ip, #17
- bne strcat_sub4
- bcs strcat_sub3
+ bne .L_strcat_sub4
+ bcs .L_strcat_sub3
lsls ip, ip, #1
- bne strcat_sub2
+ bne .L_strcat_sub2
sub r0, r0, #1
- b strcat_r0_scan_done
+ b .L_strcat_r0_scan_done
-strcat_sub4:
+.L_strcat_sub4:
sub r0, r0, #4
- b strcat_r0_scan_done
+ b .L_strcat_r0_scan_done
-strcat_sub3:
+.L_strcat_sub3:
sub r0, r0, #3
- b strcat_r0_scan_done
+ b .L_strcat_r0_scan_done
-strcat_sub2:
+.L_strcat_sub2:
sub r0, r0, #2
- b strcat_r0_scan_done
+ b .L_strcat_r0_scan_done
END(strcat)
diff --git a/libc/arch-arm/cortex-a15/bionic/strlen.S b/libc/arch-arm/cortex-a15/bionic/strlen.S
index 9a0ce62..4fd6284 100644
--- a/libc/arch-arm/cortex-a15/bionic/strlen.S
+++ b/libc/arch-arm/cortex-a15/bionic/strlen.S
@@ -65,38 +65,38 @@
mov r1, r0
ands r3, r0, #7
- beq mainloop
+ beq .L_mainloop
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
- beq align_to_32
+ beq .L_align_to_32
ldrb r2, [r1], #1
- cbz r2, update_count_and_return
+ cbz r2, .L_update_count_and_return
-align_to_32:
- bcc align_to_64
+.L_align_to_32:
+ bcc .L_align_to_64
ands ip, r3, #2
- beq align_to_64
+ beq .L_align_to_64
ldrb r2, [r1], #1
- cbz r2, update_count_and_return
+ cbz r2, .L_update_count_and_return
ldrb r2, [r1], #1
- cbz r2, update_count_and_return
+ cbz r2, .L_update_count_and_return
-align_to_64:
+.L_align_to_64:
tst r3, #4
- beq mainloop
+ beq .L_mainloop
ldr r3, [r1], #4
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
- bne zero_in_second_register
+ bne .L_zero_in_second_register
.p2align 2
-mainloop:
+.L_mainloop:
ldrd r2, r3, [r1], #8
pld [r1, #64]
@@ -104,62 +104,62 @@
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
- bne zero_in_first_register
+ bne .L_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
- bne zero_in_second_register
- b mainloop
+ bne .L_zero_in_second_register
+ b .L_mainloop
-update_count_and_return:
+.L_update_count_and_return:
sub r0, r1, r0
sub r0, r0, #1
bx lr
-zero_in_first_register:
+.L_zero_in_first_register:
sub r0, r1, r0
lsls r3, ip, #17
- bne sub8_and_return
- bcs sub7_and_return
+ bne .L_sub8_and_return
+ bcs .L_sub7_and_return
lsls ip, ip, #1
- bne sub6_and_return
+ bne .L_sub6_and_return
sub r0, r0, #5
bx lr
-sub8_and_return:
+.L_sub8_and_return:
sub r0, r0, #8
bx lr
-sub7_and_return:
+.L_sub7_and_return:
sub r0, r0, #7
bx lr
-sub6_and_return:
+.L_sub6_and_return:
sub r0, r0, #6
bx lr
-zero_in_second_register:
+.L_zero_in_second_register:
sub r0, r1, r0
lsls r3, ip, #17
- bne sub4_and_return
- bcs sub3_and_return
+ bne .L_sub4_and_return
+ bcs .L_sub3_and_return
lsls ip, ip, #1
- bne sub2_and_return
+ bne .L_sub2_and_return
sub r0, r0, #1
bx lr
-sub4_and_return:
+.L_sub4_and_return:
sub r0, r0, #4
bx lr
-sub3_and_return:
+.L_sub3_and_return:
sub r0, r0, #3
bx lr
-sub2_and_return:
+.L_sub2_and_return:
sub r0, r0, #2
bx lr
END(strlen)
diff --git a/libc/arch-arm/cortex-a53/bionic/__strcat_chk.S b/libc/arch-arm/cortex-a53/bionic/__strcat_chk.S
new file mode 100644
index 0000000..c5bc98a
--- /dev/null
+++ b/libc/arch-arm/cortex-a53/bionic/__strcat_chk.S
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+// Indicate which memcpy base file to include.
+#define MEMCPY_BASE "arch-arm/cortex-a53/bionic/memcpy_base.S"
+
+#include "arch-arm/cortex-a15/bionic/__strcat_chk_common.S"
diff --git a/libc/arch-arm/cortex-a53/bionic/__strcpy_chk.S b/libc/arch-arm/cortex-a53/bionic/__strcpy_chk.S
new file mode 100644
index 0000000..1f8945d
--- /dev/null
+++ b/libc/arch-arm/cortex-a53/bionic/__strcpy_chk.S
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+// Indicate which memcpy base file to include.
+#define MEMCPY_BASE "arch-arm/cortex-a53/bionic/memcpy_base.S"
+
+#include "arch-arm/cortex-a15/bionic/__strcpy_chk_common.S"
diff --git a/libc/arch-arm/cortex-a53/bionic/memcpy.S b/libc/arch-arm/cortex-a53/bionic/memcpy.S
new file mode 100644
index 0000000..664f574
--- /dev/null
+++ b/libc/arch-arm/cortex-a53/bionic/memcpy.S
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+// Indicate which memcpy base file to include.
+#define MEMCPY_BASE "arch-arm/cortex-a53/bionic/memcpy_base.S"
+
+#include "arch-arm/cortex-a15/bionic/memcpy_common.S"
diff --git a/libc/arch-arm/cortex-a53/bionic/memcpy_base.S b/libc/arch-arm/cortex-a53/bionic/memcpy_base.S
new file mode 100644
index 0000000..2749fc8
--- /dev/null
+++ b/libc/arch-arm/cortex-a53/bionic/memcpy_base.S
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 2013 ARM Ltd
+ * 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. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
+ */
+
+.L_memcpy_base:
+ // Assumes that n >= 0, and dst, src are valid pointers.
+ cmp r2, #16
+ blo .L_copy_less_than_16_unknown_align
+
+.L_copy_unknown_alignment:
+ // Unknown alignment of src and dst.
+ // Assumes that the first few bytes have already been prefetched.
+
+ // Align destination to 128 bits. The mainloop store instructions
+ // require this alignment or they will throw an exception.
+ rsb r3, r0, #0
+ ands r3, r3, #0xF
+ beq 2f
+
+ // Copy up to 15 bytes (count in r3).
+ sub r2, r2, r3
+ movs ip, r3, lsl #31
+
+ itt mi
+ ldrbmi lr, [r1], #1
+ strbmi lr, [r0], #1
+ itttt cs
+ ldrbcs ip, [r1], #1
+ ldrbcs lr, [r1], #1
+ strbcs ip, [r0], #1
+ strbcs lr, [r0], #1
+
+ movs ip, r3, lsl #29
+ bge 1f
+ // Copies 4 bytes, dst 32 bits aligned before, at least 64 bits after.
+ vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
+ vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
+1: bcc 2f
+ // Copies 8 bytes, dst 64 bits aligned before, at least 128 bits after.
+ vld1.8 {d0}, [r1]!
+ vst1.8 {d0}, [r0, :64]!
+
+2: // Make sure we have at least 64 bytes to copy.
+ subs r2, r2, #64
+ blo 2f
+
+1: // The main loop copies 64 bytes at a time.
+ vld1.8 {d0 - d3}, [r1]!
+ vld1.8 {d4 - d7}, [r1]!
+ subs r2, r2, #64
+ vstmia r0!, {d0 - d7}
+ pld [r1, #(64*10)]
+ bhs 1b
+
+2: // Fix-up the remaining count and make sure we have >= 32 bytes left.
+ adds r2, r2, #32
+ blo 3f
+
+ // 32 bytes. These cache lines were already preloaded.
+ vld1.8 {d0 - d3}, [r1]!
+ sub r2, r2, #32
+ vst1.8 {d0 - d3}, [r0, :128]!
+3: // Less than 32 left.
+ add r2, r2, #32
+ tst r2, #0x10
+ beq .L_copy_less_than_16_unknown_align
+ // Copies 16 bytes, destination 128 bits aligned.
+ vld1.8 {d0, d1}, [r1]!
+ vst1.8 {d0, d1}, [r0, :128]!
+
+.L_copy_less_than_16_unknown_align:
+ // Copy up to 15 bytes (count in r2).
+ movs ip, r2, lsl #29
+ bcc 1f
+ vld1.8 {d0}, [r1]!
+ vst1.8 {d0}, [r0]!
+1: bge 2f
+ vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
+ vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
+
+2: // Copy 0 to 4 bytes.
+ lsls r2, r2, #31
+ itt ne
+ ldrbne lr, [r1], #1
+ strbne lr, [r0], #1
+ itttt cs
+ ldrbcs ip, [r1], #1
+ ldrbcs lr, [r1]
+ strbcs ip, [r0], #1
+ strbcs lr, [r0]
+
+ pop {r0, pc}
diff --git a/libc/arch-arm/cortex-a53/cortex-a53.mk b/libc/arch-arm/cortex-a53/cortex-a53.mk
index b5c337c..bb00433 100644
--- a/libc/arch-arm/cortex-a53/cortex-a53.mk
+++ b/libc/arch-arm/cortex-a53/cortex-a53.mk
@@ -1 +1,20 @@
-include bionic/libc/arch-arm/cortex-a7/cortex-a7.mk
+libc_bionic_src_files_arm += \
+ arch-arm/cortex-a53/bionic/memcpy.S \
+ arch-arm/cortex-a53/bionic/__strcat_chk.S \
+ arch-arm/cortex-a53/bionic/__strcpy_chk.S \
+
+libc_bionic_src_files_arm += \
+ arch-arm/cortex-a7/bionic/memset.S \
+
+libc_bionic_src_files_arm += \
+ arch-arm/cortex-a15/bionic/stpcpy.S \
+ arch-arm/cortex-a15/bionic/strcat.S \
+ arch-arm/cortex-a15/bionic/strcmp.S \
+ arch-arm/cortex-a15/bionic/strcpy.S \
+ arch-arm/cortex-a15/bionic/strlen.S \
+
+libc_bionic_src_files_arm += \
+ arch-arm/generic/bionic/memcmp.S \
+
+libc_bionic_src_files_arm += \
+ arch-arm/denver/bionic/memmove.S \
diff --git a/libc/arch-arm/cortex-a7/bionic/memset.S b/libc/arch-arm/cortex-a7/bionic/memset.S
new file mode 100644
index 0000000..6365b06
--- /dev/null
+++ b/libc/arch-arm/cortex-a7/bionic/memset.S
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/cpu-features.h>
+#include <private/bionic_asm.h>
+#include <private/libc_events.h>
+
+ /*
+ * Optimized memset() for ARM.
+ *
+ * memset() returns its first argument.
+ */
+
+ .fpu neon
+ .syntax unified
+
+ENTRY(__memset_chk)
+ cmp r2, r3
+ bls .L_done
+
+ // Preserve lr for backtrace.
+ push {lr}
+ .cfi_def_cfa_offset 4
+ .cfi_rel_offset lr, 0
+
+ ldr r0, error_message
+ ldr r1, error_code
+1:
+ add r0, pc
+ bl __fortify_chk_fail
+error_code:
+ .word BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
+error_message:
+ .word error_string-(1b+8)
+END(__memset_chk)
+
+ENTRY(bzero)
+ mov r2, r1
+ mov r1, #0
+.L_done:
+ // Fall through to memset...
+END(bzero)
+
+ENTRY(memset)
+ mov r3, r0
+ // At this point only d0, d1 are going to be used below.
+ vdup.8 q0, r1
+ cmp r2, #16
+ blo .L_set_less_than_16_unknown_align
+
+.L_check_alignment:
+ // Align destination to a double word to avoid the store crossing
+ // a cache line boundary.
+ ands ip, r3, #7
+ bne .L_do_double_word_align
+
+.L_double_word_aligned:
+ // Duplicate since the less than 64 can use d2, d3.
+ vmov q1, q0
+ subs r2, #64
+ blo .L_set_less_than_64
+
+ // Duplicate the copy value so that we can store 64 bytes at a time.
+ vmov q2, q0
+ vmov q3, q0
+
+1: // Main loop stores 64 bytes at a time.
+ subs r2, #64
+ vstmia r3!, {d0 - d7}
+ bge 1b
+
+.L_set_less_than_64:
+ // Restore r2 to the count of bytes left to set.
+ add r2, #64
+ lsls ip, r2, #27
+ bcc .L_set_less_than_32
+ // Set 32 bytes.
+ vstmia r3!, {d0 - d3}
+
+.L_set_less_than_32:
+ bpl .L_set_less_than_16
+ // Set 16 bytes.
+ vstmia r3!, {d0, d1}
+
+.L_set_less_than_16:
+ // Less than 16 bytes to set.
+ lsls ip, r2, #29
+ bcc .L_set_less_than_8
+
+ // Set 8 bytes.
+ vstmia r3!, {d0}
+
+.L_set_less_than_8:
+ bpl .L_set_less_than_4
+ // Set 4 bytes
+ vst1.32 {d0[0]}, [r3]!
+
+.L_set_less_than_4:
+ lsls ip, r2, #31
+ it ne
+ strbne r1, [r3], #1
+ itt cs
+ strbcs r1, [r3], #1
+ strbcs r1, [r3]
+ bx lr
+
+.L_do_double_word_align:
+ rsb ip, ip, #8
+ sub r2, r2, ip
+
+ // Do this comparison now, otherwise we'll need to save a
+ // register to the stack since we've used all available
+ // registers.
+ cmp ip, #4
+ blo 1f
+
+ // Need to do a four byte copy.
+ movs ip, ip, lsl #31
+ it mi
+ strbmi r1, [r3], #1
+ itt cs
+ strbcs r1, [r3], #1
+ strbcs r1, [r3], #1
+ vst1.32 {d0[0]}, [r3]!
+ b .L_double_word_aligned
+
+1:
+ // No four byte copy.
+ movs ip, ip, lsl #31
+ it mi
+ strbmi r1, [r3], #1
+ itt cs
+ strbcs r1, [r3], #1
+ strbcs r1, [r3], #1
+ b .L_double_word_aligned
+
+.L_set_less_than_16_unknown_align:
+ // Set up to 15 bytes.
+ movs ip, r2, lsl #29
+ bcc 1f
+ vst1.8 {d0}, [r3]!
+1: bge 2f
+ vst1.32 {d0[0]}, [r3]!
+2: movs ip, r2, lsl #31
+ it mi
+ strbmi r1, [r3], #1
+ itt cs
+ strbcs r1, [r3], #1
+ strbcs r1, [r3], #1
+ bx lr
+END(memset)
+
+ .data
+error_string:
+ .string "memset: prevented write past end of buffer"
diff --git a/libc/arch-arm/cortex-a7/cortex-a7.mk b/libc/arch-arm/cortex-a7/cortex-a7.mk
index 9af03d9..b6af4da 100644
--- a/libc/arch-arm/cortex-a7/cortex-a7.mk
+++ b/libc/arch-arm/cortex-a7/cortex-a7.mk
@@ -1 +1,18 @@
-include bionic/libc/arch-arm/cortex-a15/cortex-a15.mk
+libc_bionic_src_files_arm += \
+ arch-arm/cortex-a7/bionic/memset.S \
+
+libc_bionic_src_files_arm += \
+ arch-arm/cortex-a15/bionic/memcpy.S \
+ arch-arm/cortex-a15/bionic/stpcpy.S \
+ arch-arm/cortex-a15/bionic/strcat.S \
+ arch-arm/cortex-a15/bionic/__strcat_chk.S \
+ arch-arm/cortex-a15/bionic/strcmp.S \
+ arch-arm/cortex-a15/bionic/strcpy.S \
+ arch-arm/cortex-a15/bionic/__strcpy_chk.S \
+ arch-arm/cortex-a15/bionic/strlen.S \
+
+libc_bionic_src_files_arm += \
+ arch-arm/generic/bionic/memcmp.S \
+
+libc_bionic_src_files_arm += \
+ arch-arm/denver/bionic/memmove.S \
diff --git a/libc/arch-arm/cortex-a9/bionic/memset.S b/libc/arch-arm/cortex-a9/bionic/memset.S
index 48ba815..b39fcc4 100644
--- a/libc/arch-arm/cortex-a9/bionic/memset.S
+++ b/libc/arch-arm/cortex-a9/bionic/memset.S
@@ -69,12 +69,9 @@
ENTRY(memset)
// The neon memset only wins for less than 132.
cmp r2, #132
- bhi __memset_large_copy
+ bhi .L_memset_large_copy
- stmfd sp!, {r0}
- .cfi_def_cfa_offset 4
- .cfi_rel_offset r0, 0
-
+ mov r3, r0
vdup.8 q0, r1
/* make sure we have at least 32 bytes to write */
@@ -84,7 +81,7 @@
1: /* The main loop writes 32 bytes at a time */
subs r2, r2, #32
- vst1.8 {d0 - d3}, [r0]!
+ vst1.8 {d0 - d3}, [r3]!
bhs 1b
2: /* less than 32 left */
@@ -93,22 +90,20 @@
beq 3f
// writes 16 bytes, 128-bits aligned
- vst1.8 {d0, d1}, [r0]!
+ vst1.8 {d0, d1}, [r3]!
3: /* write up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
- vst1.8 {d0}, [r0]!
+ vst1.8 {d0}, [r3]!
1: bge 2f
- vst1.32 {d0[0]}, [r0]!
+ vst1.32 {d0[0]}, [r3]!
2: movs ip, r2, lsl #31
- strbmi r1, [r0], #1
- strbcs r1, [r0], #1
- strbcs r1, [r0], #1
- ldmfd sp!, {r0}
+ strbmi r1, [r3], #1
+ strbcs r1, [r3], #1
+ strbcs r1, [r3], #1
bx lr
-END(memset)
-ENTRY_PRIVATE(__memset_large_copy)
+.L_memset_large_copy:
/* compute the offset to align the destination
* offset = (4-(src&3))&3 = -src & 3
*/
@@ -180,7 +175,7 @@
movs r2, r2, lsl #2
strbcs r1, [r0]
ldmfd sp!, {r0, r4-r7, pc}
-END(__memset_large_copy)
+END(memset)
.data
error_string:
diff --git a/libc/arch-arm/krait/bionic/memset.S b/libc/arch-arm/krait/bionic/memset.S
index a4fbe17..ae05965 100644
--- a/libc/arch-arm/krait/bionic/memset.S
+++ b/libc/arch-arm/krait/bionic/memset.S
@@ -69,10 +69,7 @@
/* memset() returns its first argument. */
ENTRY(memset)
- stmfd sp!, {r0}
- .cfi_def_cfa_offset 4
- .cfi_rel_offset r0, 0
-
+ mov r3, r0
vdup.8 q0, r1
/* make sure we have at least 32 bytes to write */
@@ -82,7 +79,7 @@
1: /* The main loop writes 32 bytes at a time */
subs r2, r2, #32
- vst1.8 {d0 - d3}, [r0]!
+ vst1.8 {d0 - d3}, [r3]!
bhs 1b
2: /* less than 32 left */
@@ -91,18 +88,17 @@
beq 3f
// writes 16 bytes, 128-bits aligned
- vst1.8 {d0, d1}, [r0]!
+ vst1.8 {d0, d1}, [r3]!
3: /* write up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
- vst1.8 {d0}, [r0]!
+ vst1.8 {d0}, [r3]!
1: bge 2f
- vst1.32 {d0[0]}, [r0]!
+ vst1.32 {d0[0]}, [r3]!
2: movs ip, r2, lsl #31
- strbmi r1, [r0], #1
- strbcs r1, [r0], #1
- strbcs r1, [r0], #1
- ldmfd sp!, {r0}
+ strbmi r1, [r3], #1
+ strbcs r1, [r3], #1
+ strbcs r1, [r3], #1
bx lr
END(memset)
diff --git a/libc/arch-arm/syscalls/vfork.S b/libc/arch-arm/syscalls/vfork.S
deleted file mode 100644
index 5f4cb3d..0000000
--- a/libc/arch-arm/syscalls/vfork.S
+++ /dev/null
@@ -1,14 +0,0 @@
-/* Generated by gensyscalls.py. Do not edit. */
-
-#include <private/bionic_asm.h>
-
-ENTRY(vfork)
- mov ip, r7
- ldr r7, =__NR_vfork
- swi #0
- mov r7, ip
- cmn r0, #(MAX_ERRNO + 1)
- bxls lr
- neg r0, r0
- b __set_errno_internal
-END(vfork)
diff --git a/libc/arch-arm64/bionic/vfork.S b/libc/arch-arm64/bionic/vfork.S
index b6a672d..92fa333 100644
--- a/libc/arch-arm64/bionic/vfork.S
+++ b/libc/arch-arm64/bionic/vfork.S
@@ -31,6 +31,11 @@
#include <linux/sched.h>
ENTRY(vfork)
+ // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
+ mrs x0, tpidr_el0
+ ldr x0, [x0, #8]
+ str wzr, [x0, #20]
+
mov x0, #(CLONE_VM | CLONE_VFORK | SIGCHLD)
mov x1, xzr
mov x2, xzr
diff --git a/libc/arch-arm64/generic/bionic/memmove.S b/libc/arch-arm64/generic/bionic/memmove.S
index 8b366a3..739ce49 100644
--- a/libc/arch-arm64/generic/bionic/memmove.S
+++ b/libc/arch-arm64/generic/bionic/memmove.S
@@ -35,10 +35,6 @@
#include <private/bionic_asm.h>
/* Parameters and result. */
-#ifdef BCOPY
-#define origdstin x1
-#define origsrc x0
-#endif
#define dstin x0
#define src x1
#define count x2
@@ -59,13 +55,7 @@
#define D_l x13
#define D_h x14
-#ifdef BCOPY
-ENTRY(bcopy)
- /* Swap src and dst so that a branch to memcpy doesn't cause issues. */
- mov tmp1, origsrc
- mov origsrc, origdstin
- mov origdstin, tmp1
-#elif defined(WMEMMOVE)
+#if defined(WMEMMOVE)
ENTRY(wmemmove)
lsl count, count, #2
#else
@@ -332,9 +322,7 @@
tst count, #0x3f
b.ne .Ltail63down
ret
-#ifdef BCOPY
-END(bcopy)
-#elif defined(WMEMMOVE)
+#if defined(WMEMMOVE)
END(wmemmove)
#else
END(memmove)
diff --git a/libc/arch-mips/bionic/vfork.S b/libc/arch-mips/bionic/vfork.S
index 1849624..7ccf70b 100644
--- a/libc/arch-mips/bionic/vfork.S
+++ b/libc/arch-mips/bionic/vfork.S
@@ -37,6 +37,14 @@
.set noreorder
.cpload t9
+ // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
+ .set push
+ .set mips32r2
+ rdhwr v0, $29 // v0 = tls; kernel trap on mips32r1
+ .set pop
+ lw v0, REGSZ*1(v0) // v0 = v0[TLS_SLOT_THREAD_ID ie 1]
+ sw $0, REGSZ*2+4(v0) // v0->cached_pid_ = 0
+
li a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
li a1, 0
li a2, 0
diff --git a/libc/arch-mips64/bionic/vfork.S b/libc/arch-mips64/bionic/vfork.S
index d180a8c..e0a39ed 100644
--- a/libc/arch-mips64/bionic/vfork.S
+++ b/libc/arch-mips64/bionic/vfork.S
@@ -46,6 +46,12 @@
PTR_SUBU sp, FRAMESZ
#endif
SETUP_GP64(a5, vfork)
+
+ // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
+ rdhwr v0, $29 // v0 = tls
+ REG_L v0, REGSZ*1(v0) // v0 = v0[TLS_SLOT_THREAD_ID ie 1]
+ sw $0, REGSZ*2+4(v0) // v0->cached_pid_ = 0
+
LI a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
move a1, $0
move a2, $0
diff --git a/libc/arch-x86/bionic/vfork.S b/libc/arch-x86/bionic/vfork.S
index ca7af0f..5c71b8d 100644
--- a/libc/arch-x86/bionic/vfork.S
+++ b/libc/arch-x86/bionic/vfork.S
@@ -34,6 +34,12 @@
popl %ecx // Grab the return address.
.cfi_adjust_cfa_offset 4
.cfi_rel_offset ecx, 0
+
+ // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
+ movl %gs:0, %eax
+ movl 4(%eax), %eax
+ movl $0, 12(%eax)
+
movl $__NR_vfork, %eax
int $0x80
cmpl $-MAX_ERRNO, %eax
diff --git a/libc/arch-x86/syscalls/clock_gettime.S b/libc/arch-x86/syscalls/__clock_gettime.S
similarity index 92%
rename from libc/arch-x86/syscalls/clock_gettime.S
rename to libc/arch-x86/syscalls/__clock_gettime.S
index 0875cfb..61eadc8 100644
--- a/libc/arch-x86/syscalls/clock_gettime.S
+++ b/libc/arch-x86/syscalls/__clock_gettime.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(clock_gettime)
+ENTRY(__clock_gettime)
pushl %ebx
.cfi_def_cfa_offset 8
.cfi_rel_offset ebx, 0
@@ -23,4 +23,4 @@
popl %ecx
popl %ebx
ret
-END(clock_gettime)
+END(__clock_gettime)
diff --git a/libc/arch-x86/syscalls/gettimeofday.S b/libc/arch-x86/syscalls/__gettimeofday.S
similarity index 92%
rename from libc/arch-x86/syscalls/gettimeofday.S
rename to libc/arch-x86/syscalls/__gettimeofday.S
index a508c14..90f3f91 100644
--- a/libc/arch-x86/syscalls/gettimeofday.S
+++ b/libc/arch-x86/syscalls/__gettimeofday.S
@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
-ENTRY(gettimeofday)
+ENTRY(__gettimeofday)
pushl %ebx
.cfi_def_cfa_offset 8
.cfi_rel_offset ebx, 0
@@ -23,4 +23,4 @@
popl %ecx
popl %ebx
ret
-END(gettimeofday)
+END(__gettimeofday)
diff --git a/libc/arch-x86_64/bionic/vfork.S b/libc/arch-x86_64/bionic/vfork.S
index 129f1db..3b32c66 100644
--- a/libc/arch-x86_64/bionic/vfork.S
+++ b/libc/arch-x86_64/bionic/vfork.S
@@ -32,6 +32,12 @@
ENTRY(vfork)
popq %rdi // Grab the return address.
+
+ // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
+ mov %fs:0, %rax
+ mov 8(%rax), %rax
+ movl $0, 20(%rax)
+
movl $__NR_vfork, %eax
syscall
pushq %rdi // Restore the return address.
diff --git a/libc/arch-x86_64/string/sse2-memmove-slm.S b/libc/arch-x86_64/string/sse2-memmove-slm.S
index 0dbffad..6a5afd6 100644
--- a/libc/arch-x86_64/string/sse2-memmove-slm.S
+++ b/libc/arch-x86_64/string/sse2-memmove-slm.S
@@ -91,9 +91,6 @@
.section .text.sse2,"ax",@progbits
ENTRY (MEMMOVE)
ENTRANCE
-#ifdef USE_AS_BCOPY
- xchg %rsi, %rdi
-#endif
mov %rdi, %rax
/* Check whether we should copy backward or forward. */
diff --git a/libc/bionic/__fread_chk.cpp b/libc/bionic/__fread_chk.cpp
new file mode 100644
index 0000000..afc8d90
--- /dev/null
+++ b/libc/bionic/__fread_chk.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#undef _FORTIFY_SOURCE
+#include <stdio.h>
+#include <sys/cdefs.h>
+#include "private/libc_logging.h"
+
+extern "C" size_t __fread_chk(void * __restrict buf, size_t size, size_t count,
+ FILE * __restrict stream, size_t buf_size) {
+ size_t total;
+ if (__predict_false(__size_mul_overflow(size, count, &total))) {
+ // overflow: trigger the error path in fread
+ return fread(buf, size, count, stream);
+ }
+
+ if (__predict_false(total > buf_size)) {
+ __fortify_chk_fail("fread: prevented write past end of buffer", 0);
+ }
+
+ return fread(buf, size, count, stream);
+}
diff --git a/libc/bionic/__fwrite_chk.cpp b/libc/bionic/__fwrite_chk.cpp
new file mode 100644
index 0000000..2af13d6
--- /dev/null
+++ b/libc/bionic/__fwrite_chk.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#undef _FORTIFY_SOURCE
+#include <stdio.h>
+#include <sys/cdefs.h>
+#include "private/libc_logging.h"
+
+extern "C" size_t __fwrite_chk(const void * __restrict buf, size_t size, size_t count,
+ FILE * __restrict stream, size_t buf_size) {
+ size_t total;
+ if (__predict_false(__size_mul_overflow(size, count, &total))) {
+ // overflow: trigger the error path in fwrite
+ return fwrite(buf, size, count, stream);
+ }
+
+ if (__predict_false(total > buf_size)) {
+ __fortify_chk_fail("fwrite: prevented read past end of buffer", 0);
+ }
+
+ return fwrite(buf, size, count, stream);
+}
diff --git a/libc/bionic/__getcwd_chk.cpp b/libc/bionic/__getcwd_chk.cpp
new file mode 100644
index 0000000..b53ab5c
--- /dev/null
+++ b/libc/bionic/__getcwd_chk.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#undef _FORTIFY_SOURCE
+
+#include <unistd.h>
+#include "private/libc_logging.h"
+
+extern char* __getcwd_chk(char* buf, size_t len, size_t buflen) {
+ if (__predict_false(len > buflen)) {
+ __fortify_chk_fail("getcwd: prevented write past end of buffer", 0);
+ }
+
+ return getcwd(buf, len);
+}
diff --git a/libc/bionic/__pwrite64_chk.cpp b/libc/bionic/__pwrite64_chk.cpp
new file mode 100644
index 0000000..e488ca1
--- /dev/null
+++ b/libc/bionic/__pwrite64_chk.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#undef _FORTIFY_SOURCE
+#include <unistd.h>
+#include "private/libc_logging.h"
+
+extern "C" ssize_t __pwrite64_chk(int fd, const void* buf, size_t count, off64_t offset,
+ size_t buf_size) {
+ if (__predict_false(count > buf_size)) {
+ __fortify_chk_fail("pwrite64: prevented read past end of buffer", 0);
+ }
+
+ if (__predict_false(count > SSIZE_MAX)) {
+ __fortify_chk_fail("pwrite64: count > SSIZE_MAX", 0);
+ }
+
+ return pwrite64(fd, buf, count, offset);
+}
diff --git a/libc/bionic/__pwrite_chk.cpp b/libc/bionic/__pwrite_chk.cpp
new file mode 100644
index 0000000..a889ef6
--- /dev/null
+++ b/libc/bionic/__pwrite_chk.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#undef _FORTIFY_SOURCE
+#include <unistd.h>
+#include "private/libc_logging.h"
+
+extern "C" ssize_t __pwrite_chk(int fd, const void* buf, size_t count, off_t offset,
+ size_t buf_size) {
+ if (__predict_false(count > buf_size)) {
+ __fortify_chk_fail("pwrite: prevented read past end of buffer", 0);
+ }
+
+ if (__predict_false(count > SSIZE_MAX)) {
+ __fortify_chk_fail("pwrite: count > SSIZE_MAX", 0);
+ }
+
+ return pwrite(fd, buf, count, offset);
+}
diff --git a/libc/bionic/__write_chk.cpp b/libc/bionic/__write_chk.cpp
new file mode 100644
index 0000000..cbd247a
--- /dev/null
+++ b/libc/bionic/__write_chk.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#undef _FORTIFY_SOURCE
+#include <unistd.h>
+#include "private/libc_logging.h"
+
+extern "C" ssize_t __write_chk(int fd, const void* buf, size_t count, size_t buf_size) {
+ if (__predict_false(count > buf_size)) {
+ __fortify_chk_fail("write: prevented read past end of buffer", 0);
+ }
+
+ if (__predict_false(count > SSIZE_MAX)) {
+ __fortify_chk_fail("write: count > SSIZE_MAX", 0);
+ }
+
+ return write(fd, buf, count);
+}
diff --git a/libc/bionic/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
index 10521cf..103aa8f 100644
--- a/libc/bionic/bionic_systrace.cpp
+++ b/libc/bionic/bionic_systrace.cpp
@@ -21,6 +21,7 @@
#include <stdlib.h>
#include <string.h>
+#include "private/bionic_lock.h"
#include "private/bionic_systrace.h"
#include "private/libc_logging.h"
@@ -29,12 +30,17 @@
#define WRITE_OFFSET 32
-static const prop_info* g_pinfo = NULL;
+constexpr char SYSTRACE_PROPERTY_NAME[] = "debug.atrace.tags.enableflags";
+
+static Lock g_lock;
+static const prop_info* g_pinfo;
static uint32_t g_serial = -1;
-static uint64_t g_tags = 0;
+static uint64_t g_tags;
static int g_trace_marker_fd = -1;
static bool should_trace() {
+ bool result = false;
+ g_lock.lock();
// If g_pinfo is null, this means that systrace hasn't been run and it's safe to
// assume that no trace writing will need to take place. However, to avoid running
// this costly find check each time, we set it to a non-tracing value so that next
@@ -42,32 +48,39 @@
// this function also deals with the bootup case, during which the call to property
// set will fail if the property server hasn't yet started.
if (g_pinfo == NULL) {
- g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
+ g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
if (g_pinfo == NULL) {
- __system_property_set("debug.atrace.tags.enableflags", "0");
- g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
- if (g_pinfo == NULL) {
- return false;
- }
+ __system_property_set(SYSTRACE_PROPERTY_NAME, "0");
+ g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
}
}
-
- // Find out which tags have been enabled on the command line and set
- // the value of tags accordingly. If the value of the property changes,
- // the serial will also change, so the costly system_property_read function
- // can be avoided by calling the much cheaper system_property_serial
- // first. The values within pinfo may change, but its location is guaranteed
- // not to move.
- const uint32_t cur_serial = __system_property_serial(g_pinfo);
- if (cur_serial != g_serial) {
- g_serial = cur_serial;
- char value[PROP_VALUE_MAX];
- __system_property_read(g_pinfo, 0, value);
- g_tags = strtoull(value, NULL, 0);
+ if (g_pinfo != NULL) {
+ // Find out which tags have been enabled on the command line and set
+ // the value of tags accordingly. If the value of the property changes,
+ // the serial will also change, so the costly system_property_read function
+ // can be avoided by calling the much cheaper system_property_serial
+ // first. The values within pinfo may change, but its location is guaranteed
+ // not to move.
+ uint32_t cur_serial = __system_property_serial(g_pinfo);
+ if (cur_serial != g_serial) {
+ g_serial = cur_serial;
+ char value[PROP_VALUE_MAX];
+ __system_property_read(g_pinfo, 0, value);
+ g_tags = strtoull(value, NULL, 0);
+ }
+ result = ((g_tags & ATRACE_TAG_BIONIC) != 0);
}
+ g_lock.unlock();
+ return result;
+}
- // Finally, verify that this tag value enables bionic tracing.
- return ((g_tags & ATRACE_TAG_BIONIC) != 0);
+static int get_trace_marker_fd() {
+ g_lock.lock();
+ if (g_trace_marker_fd == -1) {
+ g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
+ }
+ g_lock.unlock();
+ return g_trace_marker_fd;
}
ScopedTrace::ScopedTrace(const char* message) {
@@ -75,11 +88,9 @@
return;
}
- if (g_trace_marker_fd == -1) {
- g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
- if (g_trace_marker_fd == -1) {
- __libc_fatal("Could not open kernel trace file: %s\n", strerror(errno));
- }
+ int trace_marker_fd = get_trace_marker_fd();
+ if (trace_marker_fd == -1) {
+ return;
}
// If bionic tracing has been enabled, then write the message to the
@@ -87,12 +98,10 @@
int length = strlen(message);
char buf[length + WRITE_OFFSET];
size_t len = snprintf(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
- ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, buf, len));
- // Error while writing
- if (static_cast<size_t>(wbytes) != len) {
- __libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
- }
+ // Tracing may stop just after checking property and before writing the message.
+ // So the write is acceptable to fail. See b/20666100.
+ TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
}
ScopedTrace::~ScopedTrace() {
@@ -100,10 +109,10 @@
return;
}
- ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, "E", 1));
-
- // Error while writing
- if (static_cast<size_t>(wbytes) != 1) {
- __libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
+ int trace_marker_fd = get_trace_marker_fd();
+ if (trace_marker_fd == -1) {
+ return;
}
+
+ TEMP_FAILURE_RETRY(write(trace_marker_fd, "E", 1));
}
diff --git a/libc/bionic/debug_mapinfo.cpp b/libc/bionic/debug_mapinfo.cpp
index 698ab6b..de72cb2 100644
--- a/libc/bionic/debug_mapinfo.cpp
+++ b/libc/bionic/debug_mapinfo.cpp
@@ -27,6 +27,7 @@
*/
#include <ctype.h>
+#include <elf.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
@@ -35,14 +36,22 @@
#include "debug_mapinfo.h"
#include "malloc_debug_disable.h"
+#if defined(__LP64__)
+#define Elf_W(x) Elf64_##x
+#else
+#define Elf_W(x) Elf32_##x
+#endif
+
// Format of /proc/<PID>/maps:
// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /system/lib/libcomposer.so
static mapinfo_t* parse_maps_line(char* line) {
uintptr_t start;
uintptr_t end;
+ uintptr_t offset;
+ char permissions[4];
int name_pos;
- if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d%n", &start,
- &end, &name_pos) < 2) {
+ if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %4s %" PRIxPTR " %*x:%*x %*d%n", &start,
+ &end, permissions, &offset, &name_pos) < 2) {
return NULL;
}
@@ -59,6 +68,14 @@
if (mi) {
mi->start = start;
mi->end = end;
+ mi->offset = offset;
+ if (permissions[0] != 'r') {
+ // Any unreadable map will just get a zero load base.
+ mi->load_base = 0;
+ mi->load_base_read = true;
+ } else {
+ mi->load_base_read = false;
+ }
memcpy(mi->name, name, name_len);
mi->name[name_len] = '\0';
}
@@ -95,11 +112,58 @@
}
}
+template<typename T>
+static inline bool get_val(mapinfo_t* mi, uintptr_t addr, T* store) {
+ if (addr < mi->start || addr + sizeof(T) > mi->end) {
+ return false;
+ }
+ // Make sure the address is aligned properly.
+ if (addr & (sizeof(T)-1)) {
+ return false;
+ }
+ *store = *reinterpret_cast<T*>(addr);
+ return true;
+}
+
+__LIBC_HIDDEN__ void mapinfo_read_loadbase(mapinfo_t* mi) {
+ mi->load_base = 0;
+ mi->load_base_read = true;
+ uintptr_t addr = mi->start;
+ Elf_W(Ehdr) ehdr;
+ if (!get_val<Elf_W(Half)>(mi, addr + offsetof(Elf_W(Ehdr), e_phnum), &ehdr.e_phnum)) {
+ return;
+ }
+ if (!get_val<Elf_W(Off)>(mi, addr + offsetof(Elf_W(Ehdr), e_phoff), &ehdr.e_phoff)) {
+ return;
+ }
+ addr += ehdr.e_phoff;
+ for (size_t i = 0; i < ehdr.e_phnum; i++) {
+ Elf_W(Phdr) phdr;
+ if (!get_val<Elf_W(Word)>(mi, addr + offsetof(Elf_W(Phdr), p_type), &phdr.p_type)) {
+ return;
+ }
+ if (!get_val<Elf_W(Off)>(mi, addr + offsetof(Elf_W(Phdr), p_offset), &phdr.p_offset)) {
+ return;
+ }
+ if (phdr.p_type == PT_LOAD && phdr.p_offset == mi->offset) {
+ if (!get_val<Elf_W(Addr)>(mi, addr + offsetof(Elf_W(Phdr), p_vaddr), &phdr.p_vaddr)) {
+ return;
+ }
+ mi->load_base = phdr.p_vaddr;
+ return;
+ }
+ addr += sizeof(phdr);
+ }
+}
+
// Find the containing map info for the PC.
__LIBC_HIDDEN__ const mapinfo_t* mapinfo_find(mapinfo_t* mi, uintptr_t pc, uintptr_t* rel_pc) {
for (; mi != NULL; mi = mi->next) {
if ((pc >= mi->start) && (pc < mi->end)) {
- *rel_pc = pc - mi->start;
+ if (!mi->load_base_read) {
+ mapinfo_read_loadbase(mi);
+ }
+ *rel_pc = pc - mi->start + mi->load_base;
return mi;
}
}
diff --git a/libc/bionic/debug_mapinfo.h b/libc/bionic/debug_mapinfo.h
index 926b377..af7d05d 100644
--- a/libc/bionic/debug_mapinfo.h
+++ b/libc/bionic/debug_mapinfo.h
@@ -35,6 +35,9 @@
struct mapinfo_t* next;
uintptr_t start;
uintptr_t end;
+ uintptr_t offset;
+ uintptr_t load_base;
+ bool load_base_read;
char name[];
};
diff --git a/libc/bionic/debug_stacktrace.cpp b/libc/bionic/debug_stacktrace.cpp
index 71e876b..4100911 100644
--- a/libc/bionic/debug_stacktrace.cpp
+++ b/libc/bionic/debug_stacktrace.cpp
@@ -85,14 +85,14 @@
return _URC_NO_REASON;
}
-#if defined(__arm__)
- /*
- * The instruction pointer is pointing at the instruction after the bl(x), and
- * the _Unwind_Backtrace routine already masks the Thumb mode indicator (LSB
- * in PC). So we need to do a quick check here to find out if the previous
- * instruction is a Thumb-mode BLX(2). If so subtract 2 otherwise 4 from PC.
- */
+ // The instruction pointer is pointing at the instruction after the return
+ // call on all architectures.
+ // Modify the pc to point at the real function.
if (ip != 0) {
+#if defined(__arm__)
+ // We need to do a quick check here to find out if the previous
+ // instruction is a Thumb-mode BLX(2). If so subtract 2 otherwise
+ // 4 from PC.
short* ptr = reinterpret_cast<short*>(ip);
// Thumb BLX(2)
if ((*(ptr-1) & 0xff80) == 0x4780) {
@@ -100,8 +100,15 @@
} else {
ip -= 4;
}
- }
+#elif defined(__aarch64__)
+ // All instructions are 4 bytes long, skip back one instruction.
+ ip -= 4;
+#elif defined(__i386__) || defined(__x86_64__)
+ // It's difficult to decode exactly where the previous instruction is,
+ // so subtract 1 to estimate where the instruction lives.
+ ip--;
#endif
+ }
state->frames[state->frame_count++] = ip;
return (state->frame_count >= state->max_depth) ? _URC_END_OF_STACK : _URC_NO_REASON;
diff --git a/libc/bionic/getcwd.cpp b/libc/bionic/getcwd.cpp
index a8bbcf3..bcd6a57 100644
--- a/libc/bionic/getcwd.cpp
+++ b/libc/bionic/getcwd.cpp
@@ -26,6 +26,7 @@
* SUCH DAMAGE.
*/
+#undef _FORTIFY_SOURCE
#include <errno.h>
#include <malloc.h>
#include <string.h>
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index bd71628..3ca6c0d 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -64,18 +64,15 @@
// Declared in "private/bionic_ssp.h".
uintptr_t __stack_chk_guard = 0;
-/* Init TLS for the initial thread. Called by the linker _before_ libc is mapped
- * in memory. Beware: all writes to libc globals from this function will
- * apply to linker-private copies and will not be visible from libc later on.
- *
- * Note: this function creates a pthread_internal_t for the initial thread and
- * stores the pointer in TLS, but does not add it to pthread's thread list. This
- * has to be done later from libc itself (see __libc_init_common).
- *
- * This function also stores a pointer to the kernel argument block in a TLS slot to be
- * picked up by the libc constructor.
- */
-void __libc_init_tls(KernelArgumentBlock& args) {
+// Setup for the main thread. For dynamic executables, this is called by the
+// linker _before_ libc is mapped in memory. This means that all writes to
+// globals from this function will apply to linker-private copies and will not
+// be visible from libc later on.
+//
+// Note: this function creates a pthread_internal_t for the initial thread and
+// stores the pointer in TLS, but does not add it to pthread's thread list. This
+// has to be done later from libc itself (see __libc_init_common).
+void __libc_init_main_thread(KernelArgumentBlock& args) {
__libc_auxv = args.auxv;
static pthread_internal_t main_thread;
@@ -99,6 +96,9 @@
__init_thread(&main_thread);
__init_tls(&main_thread);
__set_tls(main_thread.tls);
+
+ // Store a pointer to the kernel argument block in a TLS slot to be
+ // picked up by the libc constructor.
main_thread.tls[TLS_SLOT_BIONIC_PREINIT] = &args;
__init_alternate_signal_stack(&main_thread);
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 7794fbe..2b1a8cb 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -49,16 +49,10 @@
#include "libc_init_common.h"
#include "pthread_internal.h"
+#include "private/bionic_page.h"
#include "private/bionic_tls.h"
#include "private/KernelArgumentBlock.h"
-// Returns the address of the page containing address 'x'.
-#define PAGE_START(x) ((x) & PAGE_MASK)
-
-// Returns the address of the next page after address 'x', unless 'x' is
-// itself at the start of a page.
-#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
-
extern "C" int __cxa_atexit(void (*)(void *), void *, void *);
static void call_array(void(**list)()) {
@@ -90,7 +84,7 @@
int (*slingshot)(int, char**, char**),
structors_array_t const * const structors) {
KernelArgumentBlock args(raw_args);
- __libc_init_tls(args);
+ __libc_init_main_thread(args);
__libc_init_AT_SECURE(args);
__libc_init_common(args);
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index cb0b334..2a987b9 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -448,7 +448,6 @@
return result;
}
-#ifdef TARGET_USES_LOGD
static int __libc_open_log_socket() {
// ToDo: Ideally we want this to fail if the gid of the current
// process is AID_LOGD, but will have to wait until we have
@@ -486,10 +485,8 @@
uint32_t tv_sec;
uint32_t tv_nsec;
};
-#endif
static int __libc_write_log(int priority, const char* tag, const char* msg) {
-#ifdef TARGET_USES_LOGD
int main_log_fd = __libc_open_log_socket();
if (main_log_fd == -1) {
// Try stderr instead.
@@ -517,24 +514,6 @@
vec[4].iov_len = strlen(tag) + 1;
vec[5].iov_base = const_cast<char*>(msg);
vec[5].iov_len = strlen(msg) + 1;
-#else
- int main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY));
- if (main_log_fd == -1) {
- if (errno == ENOTDIR) {
- // /dev/log isn't a directory? Maybe we're running on the host? Try stderr instead.
- return __libc_write_stderr(tag, msg);
- }
- return -1;
- }
-
- iovec vec[3];
- vec[0].iov_base = &priority;
- vec[0].iov_len = 1;
- vec[1].iov_base = const_cast<char*>(tag);
- vec[1].iov_len = strlen(tag) + 1;
- vec[2].iov_base = const_cast<char*>(msg);
- vec[2].iov_len = strlen(msg) + 1;
-#endif
int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0])));
close(main_log_fd);
@@ -557,7 +536,6 @@
}
static int __libc_android_log_event(int32_t tag, char type, const void* payload, size_t len) {
-#ifdef TARGET_USES_LOGD
iovec vec[6];
char log_id = LOG_ID_EVENTS;
vec[0].iov_base = &log_id;
@@ -581,17 +559,6 @@
vec[5].iov_len = len;
int event_log_fd = __libc_open_log_socket();
-#else
- iovec vec[3];
- vec[0].iov_base = &tag;
- vec[0].iov_len = sizeof(tag);
- vec[1].iov_base = &type;
- vec[1].iov_len = sizeof(type);
- vec[2].iov_base = const_cast<void*>(payload);
- vec[2].iov_len = len;
-
- int event_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/events", O_CLOEXEC | O_WRONLY));
-#endif
if (event_log_fd == -1) {
return -1;
diff --git a/libc/bionic/malloc_debug_qemu.cpp b/libc/bionic/malloc_debug_qemu.cpp
index fa40b35..b01cef2 100644
--- a/libc/bionic/malloc_debug_qemu.cpp
+++ b/libc/bionic/malloc_debug_qemu.cpp
@@ -612,7 +612,7 @@
error_log("Unable to open /dev/qemu_trace");
return false;
} else {
- qtrace = mmap(NULL, PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ qtrace = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
if (qtrace == MAP_FAILED) {
diff --git a/libc/bionic/stubs.cpp b/libc/bionic/stubs.cpp
index b57aeda..41c78bc 100644
--- a/libc/bionic/stubs.cpp
+++ b/libc/bionic/stubs.cpp
@@ -39,6 +39,7 @@
#include <unistd.h>
#include "private/android_filesystem_config.h"
+#include "private/bionic_macros.h"
#include "private/ErrnoRestorer.h"
#include "private/libc_logging.h"
#include "private/ThreadLocalBuffer.h"
@@ -66,11 +67,15 @@
static ThreadLocalBuffer<group_state_t> g_group_tls_buffer;
static ThreadLocalBuffer<passwd_state_t> g_passwd_tls_buffer;
+static void init_group_state(group_state_t* state) {
+ memset(state, 0, sizeof(group_state_t));
+ state->group_.gr_mem = state->group_members_;
+}
+
static group_state_t* __group_state() {
group_state_t* result = g_group_tls_buffer.get();
if (result != nullptr) {
- memset(result, 0, sizeof(group_state_t));
- result->group_.gr_mem = result->group_members_;
+ init_group_state(result);
}
return result;
}
@@ -397,17 +402,28 @@
return (pw != NULL) ? pw->pw_name : NULL;
}
+static group* getgrgid_internal(gid_t gid, group_state_t* state) {
+ group* grp = android_id_to_group(state, gid);
+ if (grp != NULL) {
+ return grp;
+ }
+ return app_id_to_group(gid, state);
+}
+
group* getgrgid(gid_t gid) { // NOLINT: implementing bad function.
group_state_t* state = __group_state();
if (state == NULL) {
return NULL;
}
+ return getgrgid_internal(gid, state);
+}
- group* gr = android_id_to_group(state, gid);
- if (gr != NULL) {
- return gr;
+static group* getgrnam_internal(const char* name, group_state_t* state) {
+ group* grp = android_name_to_group(state, name);
+ if (grp != NULL) {
+ return grp;
}
- return app_id_to_group(gid, state);
+ return app_id_to_group(app_id_from_name(name, true), state);
}
group* getgrnam(const char* name) { // NOLINT: implementing bad function.
@@ -415,11 +431,36 @@
if (state == NULL) {
return NULL;
}
+ return getgrnam_internal(name, state);
+}
- if (android_name_to_group(state, name) != 0) {
- return &state->group_;
+static int getgroup_r(bool by_name, const char* name, gid_t gid, struct group* grp, char* buf,
+ size_t buflen, struct group** result) {
+ ErrnoRestorer errno_restorer;
+ *result = NULL;
+ char* p = reinterpret_cast<char*>(
+ BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t)));
+ if (p + sizeof(group_state_t) > buf + buflen) {
+ return ERANGE;
}
- return app_id_to_group(app_id_from_name(name, true), state);
+ group_state_t* state = reinterpret_cast<group_state_t*>(p);
+ init_group_state(state);
+ group* retval = (by_name ? getgrnam_internal(name, state) : getgrgid_internal(gid, state));
+ if (retval != NULL) {
+ *grp = *retval;
+ *result = grp;
+ return 0;
+ }
+ return errno;
+}
+
+int getgrgid_r(gid_t gid, struct group* grp, char* buf, size_t buflen, struct group** result) {
+ return getgroup_r(false, NULL, gid, grp, buf, buflen, result);
+}
+
+int getgrnam_r(const char* name, struct group* grp, char* buf, size_t buflen,
+ struct group **result) {
+ return getgroup_r(true, name, 0, grp, buf, buflen, result);
}
// We don't have an /etc/networks, so all inputs return NULL.
diff --git a/libc/bionic/sysconf.cpp b/libc/bionic/sysconf.cpp
index c301b27..8a55f7e 100644
--- a/libc/bionic/sysconf.cpp
+++ b/libc/bionic/sysconf.cpp
@@ -97,8 +97,11 @@
case _SC_ATEXIT_MAX: return LONG_MAX; // Unlimited.
case _SC_IOV_MAX: return UIO_MAXIOV;
- case _SC_PAGESIZE: // Fall through, PAGESIZE and PAGE_SIZE always hold the same value.
- case _SC_PAGE_SIZE: return PAGE_SIZE;
+ // _SC_PAGESIZE and _SC_PAGE_SIZE are distinct, but return the same value.
+ case _SC_PAGESIZE:
+ case _SC_PAGE_SIZE:
+ return static_cast<long>(getauxval(AT_PAGESZ));
+
case _SC_XOPEN_UNIX: return _XOPEN_UNIX;
case _SC_AIO_LISTIO_MAX: return _POSIX_AIO_LISTIO_MAX; // Minimum requirement.
case _SC_AIO_MAX: return _POSIX_AIO_MAX; // Minimum requirement.
diff --git a/libc/bionic/sysinfo.cpp b/libc/bionic/sysinfo.cpp
index 82cb76a..a48bfea 100644
--- a/libc/bionic/sysinfo.cpp
+++ b/libc/bionic/sysinfo.cpp
@@ -29,9 +29,9 @@
#include <sys/sysinfo.h>
#include <dirent.h>
-#include <limits.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
#include "private/ScopedReaddir.h"
@@ -94,7 +94,7 @@
while (fgets(buf, sizeof(buf), fp) != NULL) {
long total;
if (sscanf(buf, pattern, &total) == 1) {
- page_count = static_cast<int>(total / (PAGE_SIZE / 1024));
+ page_count = static_cast<int>(total / (sysconf(_SC_PAGE_SIZE) / 1024));
break;
}
}
diff --git a/libc/bionic/vdso.cpp b/libc/bionic/vdso.cpp
index a240663..9eae3d5 100644
--- a/libc/bionic/vdso.cpp
+++ b/libc/bionic/vdso.cpp
@@ -19,19 +19,24 @@
#include <sys/auxv.h>
#include <unistd.h>
-// x86 has a vdso, but there's nothing useful to us in it.
-#if defined(__aarch64__) || defined(__x86_64__)
+#if defined(__aarch64__) || defined(__x86_64__) || defined (__i386__)
#if defined(__aarch64__)
#define VDSO_CLOCK_GETTIME_SYMBOL "__kernel_clock_gettime"
#define VDSO_GETTIMEOFDAY_SYMBOL "__kernel_gettimeofday"
-#elif defined(__x86_64__)
+#elif defined(__x86_64__) || defined(__i386__)
#define VDSO_CLOCK_GETTIME_SYMBOL "__vdso_clock_gettime"
#define VDSO_GETTIMEOFDAY_SYMBOL "__vdso_gettimeofday"
#endif
+#include <errno.h>
+#include <limits.h>
+#include <sys/mman.h>
#include <time.h>
+#include "private/bionic_prctl.h"
+#include "private/libc_logging.h"
+
extern "C" int __clock_gettime(int, timespec*);
extern "C" int __gettimeofday(timeval*, struct timezone*);
@@ -46,28 +51,31 @@
VDSO_END
};
-static vdso_entry vdso_entries[] = {
+static union {
+ vdso_entry entries[VDSO_END];
+ char padding[PAGE_SIZE];
+} vdso __attribute__((aligned(PAGE_SIZE))) = {{
[VDSO_CLOCK_GETTIME] = { VDSO_CLOCK_GETTIME_SYMBOL, reinterpret_cast<void*>(__clock_gettime) },
[VDSO_GETTIMEOFDAY] = { VDSO_GETTIMEOFDAY_SYMBOL, reinterpret_cast<void*>(__gettimeofday) },
-};
+}};
int clock_gettime(int clock_id, timespec* tp) {
- static int (*vdso_clock_gettime)(int, timespec*) =
- reinterpret_cast<int (*)(int, timespec*)>(vdso_entries[VDSO_CLOCK_GETTIME].fn);
+ int (*vdso_clock_gettime)(int, timespec*) =
+ reinterpret_cast<int (*)(int, timespec*)>(vdso.entries[VDSO_CLOCK_GETTIME].fn);
return vdso_clock_gettime(clock_id, tp);
}
int gettimeofday(timeval* tv, struct timezone* tz) {
- static int (*vdso_gettimeofday)(timeval*, struct timezone*) =
- reinterpret_cast<int (*)(timeval*, struct timezone*)>(vdso_entries[VDSO_GETTIMEOFDAY].fn);
+ int (*vdso_gettimeofday)(timeval*, struct timezone*) =
+ reinterpret_cast<int (*)(timeval*, struct timezone*)>(vdso.entries[VDSO_GETTIMEOFDAY].fn);
return vdso_gettimeofday(tv, tz);
}
-void __libc_init_vdso() {
+static void __libc_init_vdso_entries() {
// Do we have a vdso?
uintptr_t vdso_ehdr_addr = getauxval(AT_SYSINFO_EHDR);
ElfW(Ehdr)* vdso_ehdr = reinterpret_cast<ElfW(Ehdr)*>(vdso_ehdr_addr);
- if (vdso_ehdr == NULL) {
+ if (vdso_ehdr == nullptr) {
return;
}
@@ -85,7 +93,7 @@
// Where's the dynamic table?
ElfW(Addr) vdso_addr = 0;
- ElfW(Dyn)* vdso_dyn = NULL;
+ ElfW(Dyn)* vdso_dyn = nullptr;
ElfW(Phdr)* vdso_phdr = reinterpret_cast<ElfW(Phdr)*>(vdso_ehdr_addr + vdso_ehdr->e_phoff);
for (size_t i = 0; i < vdso_ehdr->e_phnum; ++i) {
if (vdso_phdr[i].p_type == PT_DYNAMIC) {
@@ -94,13 +102,13 @@
vdso_addr = vdso_ehdr_addr + vdso_phdr[i].p_offset - vdso_phdr[i].p_vaddr;
}
}
- if (vdso_addr == 0 || vdso_dyn == NULL) {
+ if (vdso_addr == 0 || vdso_dyn == nullptr) {
return;
}
// Where are the string and symbol tables?
- const char* strtab = NULL;
- ElfW(Sym)* symtab = NULL;
+ const char* strtab = nullptr;
+ ElfW(Sym)* symtab = nullptr;
for (ElfW(Dyn)* d = vdso_dyn; d->d_tag != DT_NULL; ++d) {
if (d->d_tag == DT_STRTAB) {
strtab = reinterpret_cast<const char*>(vdso_addr + d->d_un.d_ptr);
@@ -108,20 +116,31 @@
symtab = reinterpret_cast<ElfW(Sym)*>(vdso_addr + d->d_un.d_ptr);
}
}
- if (strtab == NULL || symtab == NULL) {
+ if (strtab == nullptr || symtab == nullptr) {
return;
}
// Are there any symbols we want?
for (size_t i = 0; i < symbol_count; ++i) {
for (size_t j = 0; j < VDSO_END; ++j) {
- if (strcmp(vdso_entries[j].name, strtab + symtab[i].st_name) == 0) {
- vdso_entries[j].fn = reinterpret_cast<void*>(vdso_addr + symtab[i].st_value);
+ if (strcmp(vdso.entries[j].name, strtab + symtab[i].st_name) == 0) {
+ vdso.entries[j].fn = reinterpret_cast<void*>(vdso_addr + symtab[i].st_value);
}
}
}
}
+void __libc_init_vdso() {
+ __libc_init_vdso_entries();
+
+ // We can't use PR_SET_VMA because this isn't an anonymous region.
+ // Long-term we should be able to replace all of this with ifuncs.
+ static_assert(PAGE_SIZE == sizeof(vdso), "sizeof(vdso) too large");
+ if (mprotect(vdso.entries, sizeof(vdso), PROT_READ) == -1) {
+ __libc_fatal("failed to mprotect PROT_READ vdso function pointer table: %s", strerror(errno));
+ }
+}
+
#else
void __libc_init_vdso() {
diff --git a/libc/include/limits.h b/libc/include/limits.h
index 6ae629b..67c7719 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -81,17 +81,6 @@
#define MB_LEN_MAX 4
-/* New code should use sysconf(_SC_PAGE_SIZE) instead. */
-#ifndef PAGE_SIZE
-#define PAGE_SIZE 4096
-#endif
-#ifndef PAGESIZE
-#define PAGESIZE PAGE_SIZE
-#endif
-
-/* glibc's PAGE_MASK is the bitwise negation of BSD's! TODO: remove? */
-#define PAGE_MASK (~(PAGE_SIZE - 1))
-
#define SEM_VALUE_MAX 0x3fffffff
/* POSIX says these belong in <unistd.h> but BSD has some in <limits.h>. */
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index f5ed652..c4bfb4f 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -382,6 +382,16 @@
__errordecl(__fgets_too_big_error, "fgets called with size bigger than buffer");
__errordecl(__fgets_too_small_error, "fgets called with size less than zero");
+extern size_t __fread_chk(void * __restrict, size_t, size_t, FILE * __restrict, size_t);
+extern size_t __fread_real(void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fread);
+__errordecl(__fread_too_big_error, "fread called with size * count bigger than buffer");
+__errordecl(__fread_overflow, "fread called with overflowing size * count");
+
+extern size_t __fwrite_chk(const void * __restrict, size_t, size_t, FILE * __restrict, size_t);
+extern size_t __fwrite_real(const void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fwrite);
+__errordecl(__fwrite_too_big_error, "fwrite called with size * count bigger than buffer");
+__errordecl(__fwrite_overflow, "fwrite called with overflowing size * count");
+
#if defined(__BIONIC_FORTIFY)
__BIONIC_FORTIFY_INLINE
@@ -428,6 +438,58 @@
}
#endif
+__BIONIC_FORTIFY_INLINE
+size_t fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict stream) {
+ size_t bos = __bos0(buf);
+
+#if !defined(__clang__)
+ if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+ return __fread_real(buf, size, count, stream);
+ }
+
+ if (__builtin_constant_p(size) && __builtin_constant_p(count)) {
+ size_t total;
+ if (__size_mul_overflow(size, count, &total)) {
+ __fread_overflow();
+ }
+
+ if (total > bos) {
+ __fread_too_big_error();
+ }
+
+ return __fread_real(buf, size, count, stream);
+ }
+#endif
+
+ return __fread_chk(buf, size, count, stream, bos);
+}
+
+__BIONIC_FORTIFY_INLINE
+size_t fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict stream) {
+ size_t bos = __bos0(buf);
+
+#if !defined(__clang__)
+ if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+ return __fwrite_real(buf, size, count, stream);
+ }
+
+ if (__builtin_constant_p(size) && __builtin_constant_p(count)) {
+ size_t total;
+ if (__size_mul_overflow(size, count, &total)) {
+ __fwrite_overflow();
+ }
+
+ if (total > bos) {
+ __fwrite_too_big_error();
+ }
+
+ return __fwrite_real(buf, size, count, stream);
+ }
+#endif
+
+ return __fwrite_chk(buf, size, count, stream, bos);
+}
+
#if !defined(__clang__)
__BIONIC_FORTIFY_INLINE
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 7df8b60..8a11bc6 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -578,4 +578,19 @@
#define _BIONIC_NOT_BEFORE_21(x)
#endif /* __ANDROID_API__ >= 21 */
+#if __has_builtin(__builtin_umul_overflow) || __GNUC__ >= 5
+#if __LP64__
+#define __size_mul_overflow(a, b, result) __builtin_umull_overflow(a, b, result)
+#else
+#define __size_mul_overflow(a, b, result) __builtin_umul_overflow(a, b, result)
+#endif
+#else
+static __inline__ __always_inline int __size_mul_overflow(__SIZE_TYPE__ a, __SIZE_TYPE__ b,
+ __SIZE_TYPE__ *result) {
+ *result = a * b;
+ static const __SIZE_TYPE__ mul_no_overflow = 1UL << (sizeof(__SIZE_TYPE__) * 4);
+ return (a >= mul_no_overflow || b >= mul_no_overflow) && a > 0 && (__SIZE_TYPE__)-1 / a < b;
+}
+#endif
+
#endif /* !_SYS_CDEFS_H_ */
diff --git a/libc/include/sys/syslog.h b/libc/include/sys/syslog.h
new file mode 100644
index 0000000..7761ece
--- /dev/null
+++ b/libc/include/sys/syslog.h
@@ -0,0 +1 @@
+#include <syslog.h>
diff --git a/libc/include/sys/time.h b/libc/include/sys/time.h
index 1f010d4..f60c905 100644
--- a/libc/include/sys/time.h
+++ b/libc/include/sys/time.h
@@ -25,6 +25,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
#ifndef _SYS_TIME_H_
#define _SYS_TIME_H_
@@ -32,6 +33,9 @@
#include <sys/types.h>
#include <linux/time.h>
+/* POSIX says <sys/time.h> gets you most of <sys/select.h> and may get you all of it. */
+#include <sys/select.h>
+
__BEGIN_DECLS
extern int gettimeofday(struct timeval *, struct timezone *);
@@ -73,6 +77,15 @@
} \
} while (0)
+#define TIMEVAL_TO_TIMESPEC(tv, ts) { \
+ (ts)->tv_sec = (tv)->tv_sec; \
+ (ts)->tv_nsec = (tv)->tv_usec * 1000; \
+}
+#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
+ (tv)->tv_sec = (ts)->tv_sec; \
+ (tv)->tv_usec = (ts)->tv_nsec / 1000; \
+}
+
__END_DECLS
#endif /* _SYS_TIME_H_ */
diff --git a/libc/include/sys/unistd.h b/libc/include/sys/unistd.h
new file mode 100644
index 0000000..1e823fb
--- /dev/null
+++ b/libc/include/sys/unistd.h
@@ -0,0 +1 @@
+#include <unistd.h>
diff --git a/libc/include/sys/user.h b/libc/include/sys/user.h
index d63fe6a..ce4c07c 100644
--- a/libc/include/sys/user.h
+++ b/libc/include/sys/user.h
@@ -30,11 +30,13 @@
#define _SYS_USER_H_
#include <sys/cdefs.h>
-#include <limits.h> /* For PAGE_SIZE. */
#include <stddef.h> /* For size_t. */
__BEGIN_DECLS
+#define PAGE_SIZE 4096
+#define PAGE_MASK (~(PAGE_SIZE - 1))
+
#if __i386__
struct user_fpregs_struct {
diff --git a/libc/include/sys/vt.h b/libc/include/sys/vt.h
index b37a869..834abfb 100644
--- a/libc/include/sys/vt.h
+++ b/libc/include/sys/vt.h
@@ -1,28 +1 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
#include <linux/vt.h>
diff --git a/libc/include/syscall.h b/libc/include/syscall.h
new file mode 100644
index 0000000..4c30578
--- /dev/null
+++ b/libc/include/syscall.h
@@ -0,0 +1 @@
+#include <sys/syscall.h>
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index f0de29e..91ae89e 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -224,6 +224,10 @@
} while (_rc == -1 && errno == EINTR); \
_rc; })
+extern char* __getcwd_chk(char*, size_t, size_t);
+__errordecl(__getcwd_dest_size_error, "getcwd called with size bigger than destination");
+extern char* __getcwd_real(char*, size_t) __RENAME(getcwd);
+
extern ssize_t __pread_chk(int, void*, size_t, off_t, size_t);
__errordecl(__pread_dest_size_error, "pread called with size bigger than destination");
__errordecl(__pread_count_toobig_error, "pread called with count > SSIZE_MAX");
@@ -234,11 +238,26 @@
__errordecl(__pread64_count_toobig_error, "pread64 called with count > SSIZE_MAX");
extern ssize_t __pread64_real(int, void*, size_t, off64_t) __RENAME(pread64);
+extern ssize_t __pwrite_chk(int, const void*, size_t, off_t, size_t);
+__errordecl(__pwrite_dest_size_error, "pwrite called with size bigger than destination");
+__errordecl(__pwrite_count_toobig_error, "pwrite called with count > SSIZE_MAX");
+extern ssize_t __pwrite_real(int, const void*, size_t, off_t) __RENAME(pwrite);
+
+extern ssize_t __pwrite64_chk(int, const void*, size_t, off64_t, size_t);
+__errordecl(__pwrite64_dest_size_error, "pwrite64 called with size bigger than destination");
+__errordecl(__pwrite64_count_toobig_error, "pwrite64 called with count > SSIZE_MAX");
+extern ssize_t __pwrite64_real(int, const void*, size_t, off64_t) __RENAME(pwrite64);
+
extern ssize_t __read_chk(int, void*, size_t, size_t);
__errordecl(__read_dest_size_error, "read called with size bigger than destination");
__errordecl(__read_count_toobig_error, "read called with count > SSIZE_MAX");
extern ssize_t __read_real(int, void*, size_t) __RENAME(read);
+extern ssize_t __write_chk(int, const void*, size_t, size_t);
+__errordecl(__write_dest_size_error, "write called with size bigger than destination");
+__errordecl(__write_count_toobig_error, "write called with count > SSIZE_MAX");
+extern ssize_t __write_real(int, const void*, size_t) __RENAME(write);
+
extern ssize_t __readlink_chk(const char*, char*, size_t, size_t);
__errordecl(__readlink_dest_size_error, "readlink called with size bigger than destination");
__errordecl(__readlink_size_toobig_error, "readlink called with size > SSIZE_MAX");
@@ -251,6 +270,37 @@
#if defined(__BIONIC_FORTIFY)
+__BIONIC_FORTIFY_INLINE
+char* getcwd(char* buf, size_t size) {
+ size_t bos = __bos(buf);
+
+#if defined(__clang__)
+ /*
+ * Work around LLVM's incorrect __builtin_object_size implementation here
+ * to avoid needing the workaround in the __getcwd_chk ABI forever.
+ *
+ * https://llvm.org/bugs/show_bug.cgi?id=23277
+ */
+ if (buf == NULL) {
+ bos = __BIONIC_FORTIFY_UNKNOWN_SIZE;
+ }
+#else
+ if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+ return __getcwd_real(buf, size);
+ }
+
+ if (__builtin_constant_p(size) && (size > bos)) {
+ __getcwd_dest_size_error();
+ }
+
+ if (__builtin_constant_p(size) && (size <= bos)) {
+ return __getcwd_real(buf, size);
+ }
+#endif
+
+ return __getcwd_chk(buf, size, bos);
+}
+
#if defined(__USE_FILE_OFFSET64)
#define __PREAD_PREFIX(x) __pread64_ ## x
#else
@@ -307,6 +357,62 @@
return __pread64_chk(fd, buf, count, offset, bos);
}
+#if defined(__USE_FILE_OFFSET64)
+#define __PWRITE_PREFIX(x) __pwrite64_ ## x
+#else
+#define __PWRITE_PREFIX(x) __pwrite_ ## x
+#endif
+
+__BIONIC_FORTIFY_INLINE
+ssize_t pwrite(int fd, const void* buf, size_t count, off_t offset) {
+ size_t bos = __bos0(buf);
+
+#if !defined(__clang__)
+ if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
+ __PWRITE_PREFIX(count_toobig_error)();
+ }
+
+ if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+ return __PWRITE_PREFIX(real)(fd, buf, count, offset);
+ }
+
+ if (__builtin_constant_p(count) && (count > bos)) {
+ __PWRITE_PREFIX(dest_size_error)();
+ }
+
+ if (__builtin_constant_p(count) && (count <= bos)) {
+ return __PWRITE_PREFIX(real)(fd, buf, count, offset);
+ }
+#endif
+
+ return __PWRITE_PREFIX(chk)(fd, buf, count, offset, bos);
+}
+
+__BIONIC_FORTIFY_INLINE
+ssize_t pwrite64(int fd, const void* buf, size_t count, off64_t offset) {
+ size_t bos = __bos0(buf);
+
+#if !defined(__clang__)
+ if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
+ __pwrite64_count_toobig_error();
+ }
+
+ if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+ return __pwrite64_real(fd, buf, count, offset);
+ }
+
+ if (__builtin_constant_p(count) && (count > bos)) {
+ __pwrite64_dest_size_error();
+ }
+
+ if (__builtin_constant_p(count) && (count <= bos)) {
+ return __pwrite64_real(fd, buf, count, offset);
+ }
+#endif
+
+ return __pwrite64_chk(fd, buf, count, offset, bos);
+}
+
__BIONIC_FORTIFY_INLINE
ssize_t read(int fd, void* buf, size_t count) {
size_t bos = __bos0(buf);
@@ -333,6 +439,33 @@
}
__BIONIC_FORTIFY_INLINE
+ssize_t write(int fd, const void* buf, size_t count) {
+ size_t bos = __bos0(buf);
+
+#if !defined(__clang__)
+#if 0 /* work around a false positive due to a missed optimization */
+ if (__builtin_constant_p(count) && (count > SSIZE_MAX)) {
+ __write_count_toobig_error();
+ }
+#endif
+
+ if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
+ return __write_real(fd, buf, count);
+ }
+
+ if (__builtin_constant_p(count) && (count > bos)) {
+ __write_dest_size_error();
+ }
+
+ if (__builtin_constant_p(count) && (count <= bos)) {
+ return __write_real(fd, buf, count);
+ }
+#endif
+
+ return __write_chk(fd, buf, count, bos);
+}
+
+__BIONIC_FORTIFY_INLINE
ssize_t readlink(const char* path, char* buf, size_t size) {
size_t bos = __bos(buf);
diff --git a/libc/include/wait.h b/libc/include/wait.h
new file mode 100644
index 0000000..d01b811
--- /dev/null
+++ b/libc/include/wait.h
@@ -0,0 +1 @@
+#include <sys/wait.h>
diff --git a/libc/libc.map b/libc/libc.map
index 47c52a4..4670079 100644
--- a/libc/libc.map
+++ b/libc/libc.map
@@ -1332,6 +1332,18 @@
*;
};
+LIBC_N {
+ global:
+ __fread_chk;
+ __fwrite_chk;
+ __getcwd_chk;
+ __pwrite_chk;
+ __pwrite64_chk;
+ __write_chk;
+ getgrgid_r;
+ getgrnam_r;
+} LIBC;
+
LIBC_PRIVATE {
global:
___Unwind_Backtrace; # arm
@@ -1453,4 +1465,4 @@
SHA1Init; # arm x86 mips
SHA1Transform; # arm x86 mips
SHA1Update; # arm x86 mips
-} LIBC;
+} LIBC_N;
diff --git a/libc/private/bionic_page.h b/libc/private/bionic_page.h
new file mode 100644
index 0000000..0beb708
--- /dev/null
+++ b/libc/private/bionic_page.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 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_PAGE_H_
+#define _BIONIC_PAGE_H_
+
+// Get PAGE_SIZE and PAGE_MASK.
+#include <sys/user.h>
+
+// Returns the address of the page containing address 'x'.
+#define PAGE_START(x) ((x) & PAGE_MASK)
+
+// Returns the offset of address 'x' in its page.
+#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK)
+
+// Returns the address of the next page after address 'x', unless 'x' is
+// itself at the start of a page.
+#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
+
+#endif // _BIONIC_PAGE_H_
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index 30dc0eb..2ca7728 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -67,6 +67,13 @@
TLS_SLOT_STACK_GUARD = 5, // GCC requires this specific slot for x86.
TLS_SLOT_DLERROR,
+ // Fast storage for Thread::Current() in ART.
+ TLS_SLOT_ART_THREAD_SELF,
+
+ // Lets TSAN avoid using pthread_getspecific for finding the current thread
+ // state.
+ TLS_SLOT_TSAN,
+
BIONIC_TLS_SLOTS // Must come last!
};
@@ -114,7 +121,7 @@
#if defined(__cplusplus)
class KernelArgumentBlock;
-extern __LIBC_HIDDEN__ void __libc_init_tls(KernelArgumentBlock& args);
+extern __LIBC_HIDDEN__ void __libc_init_main_thread(KernelArgumentBlock& args);
#endif
#endif /* __BIONIC_PRIVATE_BIONIC_TLS_H_ */
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index a6970dd..34a4db1 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -37,6 +37,10 @@
#include "atexit.h"
#include "private/thread_private.h"
+/* BEGIN android-changed */
+#include "private/bionic_prctl.h"
+/* END android-changed */
+
struct atexit {
struct atexit *next; /* next in list */
int ind; /* next index in this table */
@@ -95,6 +99,10 @@
MAP_ANON | MAP_PRIVATE, -1, 0);
if (p == MAP_FAILED)
goto unlock;
+/* BEGIN android-changed */
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, pgsize,
+ "atexit handlers");
+/* END android-changed */
if (__atexit == NULL) {
memset(&p->fns[0], 0, sizeof(p->fns[0]));
p->ind = 1;
@@ -204,6 +212,10 @@
MAP_ANON | MAP_PRIVATE, -1, 0);
if (p == MAP_FAILED)
goto unlock;
+/* BEGIN android-changed */
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, pgsize,
+ "atexit handlers");
+/* END android-changed */
p->ind = 1;
p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
sizeof(p->fns[0]);
diff --git a/libc/upstream-openbsd/android/include/arc4random.h b/libc/upstream-openbsd/android/include/arc4random.h
index c07257d..96d9c9a 100644
--- a/libc/upstream-openbsd/android/include/arc4random.h
+++ b/libc/upstream-openbsd/android/include/arc4random.h
@@ -27,6 +27,8 @@
#include <pthread.h>
#include <signal.h>
+#include "private/bionic_prctl.h"
+
// Android gets these from "thread_private.h".
#include "thread_private.h"
//static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
@@ -76,12 +78,18 @@
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return (-1);
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, *rsp, sizeof(**rsp),
+ "arc4random _rs structure");
+
if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
munmap(*rsxp, sizeof(**rsxp));
return (-1);
}
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, *rsxp, sizeof(**rsxp),
+ "arc4random _rsx structure");
+
_ARC4_ATFORK(_rs_forkhandler);
return (0);
}
diff --git a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
index 2c860f7..0d0f18f 100644
--- a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
+++ b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fnmatch.c,v 1.17 2013/11/24 23:51:29 deraadt Exp $ */
+/* $OpenBSD: fnmatch.c,v 1.19 2015/08/01 18:11:08 millert Exp $ */
/* Copyright (c) 2011, VMware, Inc.
* All rights reserved.
@@ -88,7 +88,6 @@
#include <fnmatch.h>
#include <string.h>
#include <ctype.h>
-#include <limits.h>
#include "charclass.h"
@@ -193,6 +192,8 @@
result = 0;
continue;
}
+ if (!**pattern)
+ break;
leadingclosebrace:
/* Look at only well-formed range patterns;
@@ -294,10 +295,6 @@
const char *mismatch = NULL;
int matchlen = 0;
- if (strnlen(pattern, PATH_MAX) == PATH_MAX ||
- strnlen(string, PATH_MAX) == PATH_MAX)
- return (FNM_NOMATCH);
-
if (*pattern == '*')
goto firstsegment;
diff --git a/libm/Android.mk b/libm/Android.mk
index 7a7e3b0..7b28f70 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -283,9 +283,8 @@
else
LOCAL_SRC_FILES_arm += \
- arm/e_sqrt.S \
- arm/e_sqrtf.S \
- arm/s_floor.S \
+ arm/sqrt.S \
+ arm/floor.S \
endif
diff --git a/libm/arm/e_sqrtf.S b/libm/arm/e_sqrtf.S
deleted file mode 100644
index ddefb22..0000000
--- a/libm/arm/e_sqrtf.S
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2013-2014, NVIDIA Corporation. All rights reserved.
- * Johhnny Qiu <joqiu@nvidia.com>
- * Shu Zhang <chazhang@nvidia.com>
- *
- * 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 Linux 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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 <private/bionic_asm.h>
-
-ENTRY(sqrtf)
- vmov.f32 s0, r0
- vsqrt.f32 s0, s0
- vmov.f32 r0, s0
- bx lr
-END(sqrtf)
diff --git a/libm/arm/s_floor.S b/libm/arm/floor.S
similarity index 100%
rename from libm/arm/s_floor.S
rename to libm/arm/floor.S
diff --git a/libm/arm/e_sqrt.S b/libm/arm/sqrt.S
similarity index 94%
rename from libm/arm/e_sqrt.S
rename to libm/arm/sqrt.S
index 17312f5..f2981f4 100644
--- a/libm/arm/e_sqrt.S
+++ b/libm/arm/sqrt.S
@@ -39,4 +39,11 @@
bx lr
END(sqrt)
+ENTRY(sqrtf)
+ vmov.f32 s0, r0
+ vsqrt.f32 s0, s0
+ vmov.f32 r0, s0
+ bx lr
+END(sqrtf)
+
ALIAS_SYMBOL(sqrtl, sqrt);
diff --git a/libm/include/math.h b/libm/include/math.h
index 1542374..bc48b6a 100644
--- a/libm/include/math.h
+++ b/libm/include/math.h
@@ -15,7 +15,7 @@
*/
#ifndef _MATH_H_
-#define _MATH_H_
+#define _MATH_H_
#include <sys/cdefs.h>
#include <limits.h>
@@ -23,108 +23,56 @@
__BEGIN_DECLS
#pragma GCC visibility push(default)
-/*
- * ANSI/POSIX
- */
-extern const union __infinity_un {
- unsigned char __uc[8];
- double __ud;
-} __infinity;
-
-extern const union __nan_un {
- unsigned char __uc[sizeof(float)];
- float __uf;
-} __nan;
-
-#if __GNUC_PREREQ(3, 3) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 800)
-#define __MATH_BUILTIN_CONSTANTS
-#endif
-
-#if __GNUC_PREREQ(3, 0) && !defined(__INTEL_COMPILER)
-#define __MATH_BUILTIN_RELOPS
-#endif
-
-#ifdef __MATH_BUILTIN_CONSTANTS
-#define HUGE_VAL __builtin_huge_val()
-#else
-#define HUGE_VAL (__infinity.__ud)
-#endif
+#define HUGE_VAL __builtin_huge_val()
#if __ISO_C_VISIBLE >= 1999
-#define FP_ILOGB0 (-INT_MAX) /* Android-changed */
-#define FP_ILOGBNAN INT_MAX /* Android-changed */
+#define FP_ILOGB0 (-INT_MAX)
+#define FP_ILOGBNAN INT_MAX
-#ifdef __MATH_BUILTIN_CONSTANTS
-#define HUGE_VALF __builtin_huge_valf()
-#define HUGE_VALL __builtin_huge_vall()
-#define INFINITY __builtin_inff()
-#define NAN __builtin_nanf("")
-#else
-#define HUGE_VALF (float)HUGE_VAL
-#define HUGE_VALL (long double)HUGE_VAL
-#define INFINITY HUGE_VALF
-#define NAN (__nan.__uf)
-#endif /* __MATH_BUILTIN_CONSTANTS */
+#define HUGE_VALF __builtin_huge_valf()
+#define HUGE_VALL __builtin_huge_vall()
+#define INFINITY __builtin_inff()
+#define NAN __builtin_nanf("")
-#define MATH_ERRNO 1
-#define MATH_ERREXCEPT 2
-#define math_errhandling MATH_ERREXCEPT
+#define MATH_ERRNO 1
+#define MATH_ERREXCEPT 2
+#define math_errhandling MATH_ERREXCEPT
-#define FP_FAST_FMAF 1
-#ifdef __ia64__
-#define FP_FAST_FMA 1
-#define FP_FAST_FMAL 1
+#if defined(__FP_FAST_FMA)
+#define FP_FAST_FMA 1
+#endif
+#if defined(__FP_FAST_FMAF)
+#define FP_FAST_FMAF 1
+#endif
+#if defined(__FP_FAST_FMAL)
+#define FP_FAST_FMAL 1
#endif
/* Symbolic constants to classify floating point numbers. */
-#define FP_INFINITE 0x01
-#define FP_NAN 0x02
-#define FP_NORMAL 0x04
-#define FP_SUBNORMAL 0x08
-#define FP_ZERO 0x10
-#define fpclassify(x) \
- ((sizeof (x) == sizeof (float)) ? __fpclassifyf(x) \
- : (sizeof (x) == sizeof (double)) ? __fpclassifyd(x) \
- : __fpclassifyl(x))
+#define FP_INFINITE 0x01
+#define FP_NAN 0x02
+#define FP_NORMAL 0x04
+#define FP_SUBNORMAL 0x08
+#define FP_ZERO 0x10
+#define fpclassify(x) \
+ __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x)
-#define isfinite(x) \
- ((sizeof (x) == sizeof (float)) ? __isfinitef(x) \
- : (sizeof (x) == sizeof (double)) ? __isfinite(x) \
- : __isfinitel(x))
-#define isinf(x) \
- ((sizeof (x) == sizeof (float)) ? __isinff(x) \
- : (sizeof (x) == sizeof (double)) ? isinf(x) \
- : __isinfl(x))
-#define isnan(x) \
- ((sizeof (x) == sizeof (float)) ? __isnanf(x) \
- : (sizeof (x) == sizeof (double)) ? isnan(x) \
- : __isnanl(x))
-#define isnormal(x) \
- ((sizeof (x) == sizeof (float)) ? __isnormalf(x) \
- : (sizeof (x) == sizeof (double)) ? __isnormal(x) \
- : __isnormall(x))
+#define isfinite(x) __builtin_isfinite(x)
+#define isinf(x) __builtin_isinf(x)
+#define isnan(x) __builtin_isnan(x)
+#define isnormal(x) __builtin_isnormal(x)
-#ifdef __MATH_BUILTIN_RELOPS
-#define isgreater(x, y) __builtin_isgreater((x), (y))
-#define isgreaterequal(x, y) __builtin_isgreaterequal((x), (y))
-#define isless(x, y) __builtin_isless((x), (y))
-#define islessequal(x, y) __builtin_islessequal((x), (y))
-#define islessgreater(x, y) __builtin_islessgreater((x), (y))
-#define isunordered(x, y) __builtin_isunordered((x), (y))
-#else
-#define isgreater(x, y) (!isunordered((x), (y)) && (x) > (y))
-#define isgreaterequal(x, y) (!isunordered((x), (y)) && (x) >= (y))
-#define isless(x, y) (!isunordered((x), (y)) && (x) < (y))
-#define islessequal(x, y) (!isunordered((x), (y)) && (x) <= (y))
-#define islessgreater(x, y) (!isunordered((x), (y)) && \
- ((x) > (y) || (y) > (x)))
-#define isunordered(x, y) (isnan(x) || isnan(y))
-#endif /* __MATH_BUILTIN_RELOPS */
+#define isgreater(x, y) __builtin_isgreater((x), (y))
+#define isgreaterequal(x, y) __builtin_isgreaterequal((x), (y))
+#define isless(x, y) __builtin_isless((x), (y))
+#define islessequal(x, y) __builtin_islessequal((x), (y))
+#define islessgreater(x, y) __builtin_islessgreater((x), (y))
+#define isunordered(x, y) __builtin_isunordered((x), (y))
-#define signbit(x) \
- ((sizeof (x) == sizeof (float)) ? __signbitf(x) \
- : (sizeof (x) == sizeof (double)) ? __signbit(x) \
- : __signbitl(x))
+#define signbit(x) \
+ ((sizeof(x) == sizeof(float)) ? __builtin_signbitf(x) \
+ : (sizeof(x) == sizeof(double)) ? __builtin_signbit(x) \
+ : __builtin_signbitl(x))
typedef double __double_t;
typedef __double_t double_t;
diff --git a/linker/Android.mk b/linker/Android.mk
index 04b4370..d8487d3 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -42,7 +42,6 @@
-std=gnu99 \
LOCAL_CPPFLAGS += \
- -std=gnu++11 \
-Wold-style-cast \
ifeq ($(TARGET_IS_64_BIT),true)
@@ -60,7 +59,7 @@
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_STATIC_LIBRARIES := libc_nomalloc libziparchive libutils libz liblog
+LOCAL_STATIC_LIBRARIES := libc_nomalloc libziparchive libutils libbase libz liblog
LOCAL_FORCE_STATIC_EXECUTABLE := true
@@ -84,8 +83,6 @@
include $(BUILD_EXECUTABLE)
-ifeq (address, $(strip $(SANITIZE_TARGET)))
-
define add-linker-symlink
$(eval _from := $(TARGET_OUT)/bin/$(1))
$(eval _to:=$(2))
@@ -94,15 +91,11 @@
@mkdir -p $$(dir $$@)
@rm -rf $$@
$(hide) ln -sf $(_to) $$@
-ALL_MODULES.linker.INSTALLED += $(_from)
-linker: $(_from)
endef
$(eval $(call add-linker-symlink,linker_asan,linker))
ifeq ($(TARGET_IS_64_BIT),true)
$(eval $(call add-linker-symlink,linker_asan64,linker64))
endif
-ALL_MODULES += linker
-endif
include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/linker/debugger.cpp b/linker/debugger.cpp
index 46c97af..3731c99 100644
--- a/linker/debugger.cpp
+++ b/linker/debugger.cpp
@@ -135,9 +135,6 @@
signal_name = "SIGILL";
has_address = true;
break;
- case SIGPIPE:
- signal_name = "SIGPIPE";
- break;
case SIGSEGV:
signal_name = "SIGSEGV";
has_address = true;
@@ -273,7 +270,7 @@
signal(signal_number, SIG_DFL);
// These signals are not re-thrown when we resume. This means that
- // crashing due to (say) SIGPIPE doesn't work the way you'd expect it
+ // crashing due to (say) SIGABRT doesn't work the way you'd expect it
// to. We work around this by throwing them manually. We don't want
// to do this for *all* signals because it'll screw up the si_addr for
// faults like SIGSEGV. It does screw up the si_code, which is why we
@@ -281,7 +278,6 @@
switch (signal_number) {
case SIGABRT:
case SIGFPE:
- case SIGPIPE:
#if defined(SIGSTKFLT)
case SIGSTKFLT:
#endif
@@ -307,7 +303,6 @@
sigaction(SIGBUS, &action, nullptr);
sigaction(SIGFPE, &action, nullptr);
sigaction(SIGILL, &action, nullptr);
- sigaction(SIGPIPE, &action, nullptr);
sigaction(SIGSEGV, &action, nullptr);
#if defined(SIGSTKFLT)
sigaction(SIGSTKFLT, &action, nullptr);
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 4993568..f1b26c9 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -68,8 +68,9 @@
}
static void* dlopen_ext(const char* filename, int flags,
- const android_dlextinfo* extinfo, soinfo* caller) {
+ const android_dlextinfo* extinfo, void* caller_addr) {
ScopedPthreadMutexLocker locker(&g_dl_mutex);
+ soinfo* caller = find_containing_library(caller_addr);
soinfo* result = do_dlopen(filename, flags, extinfo, caller);
if (result == nullptr) {
__bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
@@ -80,14 +81,12 @@
void* android_dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo) {
void* caller_addr = __builtin_return_address(0);
- soinfo* caller = find_containing_library(caller_addr);
- return dlopen_ext(filename, flags, extinfo, caller);
+ return dlopen_ext(filename, flags, extinfo, caller_addr);
}
void* dlopen(const char* filename, int flags) {
void* caller_addr = __builtin_return_address(0);
- soinfo* caller = find_containing_library(caller_addr);
- return dlopen_ext(filename, flags, nullptr, caller);
+ return dlopen_ext(filename, flags, nullptr, caller_addr);
}
void* dlsym(void* handle, const char* symbol) {
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 73eeba1..4428e51 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -57,6 +57,8 @@
#include "linker_phdr.h"
#include "linker_relocs.h"
#include "linker_reloc_iterators.h"
+
+#include "base/strings.h"
#include "ziparchive/zip_archive.h"
extern void __libc_init_AT_SECURE(KernelArgumentBlock&);
@@ -308,25 +310,9 @@
static void parse_path(const char* path, const char* delimiters,
std::vector<std::string>* paths) {
- if (path == nullptr) {
- return;
- }
-
paths->clear();
-
- for (const char *p = path; ; ++p) {
- size_t len = strcspn(p, delimiters);
- // skip empty tokens
- if (len == 0) {
- continue;
- }
-
- paths->push_back(std::string(p, len));
- p += len;
-
- if (*p == '\0') {
- break;
- }
+ if (path != nullptr) {
+ *paths = android::base::Split(path, delimiters);
}
}
@@ -1999,9 +1985,32 @@
DL_ERR("unknown weak reloc type %d @ %p (%zu)", type, rel, idx);
return false;
}
- } else {
- // We got a definition.
+ } else { // We got a definition.
+#if !defined(__LP64__)
+ // When relocating dso with text_relocation .text segment is
+ // not executable. We need to restore elf flags before resolving
+ // STT_GNU_IFUNC symbol.
+ bool protect_segments = has_text_relocations &&
+ lsi == this &&
+ ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC;
+ if (protect_segments) {
+ if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
+ DL_ERR("can't protect segments for \"%s\": %s",
+ get_realpath(), strerror(errno));
+ return false;
+ }
+ }
+#endif
sym_addr = lsi->resolve_symbol_address(s);
+#if !defined(__LP64__)
+ if (protect_segments) {
+ if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
+ DL_ERR("can't unprotect loadable segments for \"%s\": %s",
+ get_realpath(), strerror(errno));
+ return false;
+ }
+ }
+#endif
}
count_relocation(kRelocSymbol);
}
@@ -2038,7 +2047,32 @@
TRACE_TYPE(RELO, "RELO IRELATIVE %16p <- %16p\n",
reinterpret_cast<void*>(reloc),
reinterpret_cast<void*>(load_bias + addend));
- *reinterpret_cast<ElfW(Addr)*>(reloc) = call_ifunc_resolver(load_bias + addend);
+ {
+#if !defined(__LP64__)
+ // When relocating dso with text_relocation .text segment is
+ // not executable. We need to restore elf flags for this
+ // particular call.
+ if (has_text_relocations) {
+ if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
+ DL_ERR("can't protect segments for \"%s\": %s",
+ get_realpath(), strerror(errno));
+ return false;
+ }
+ }
+#endif
+ ElfW(Addr) ifunc_addr = call_ifunc_resolver(load_bias + addend);
+#if !defined(__LP64__)
+ // Unprotect it afterwards...
+ if (has_text_relocations) {
+ if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
+ DL_ERR("can't unprotect loadable segments for \"%s\": %s",
+ get_realpath(), strerror(errno));
+ return false;
+ }
+ }
+#endif
+ *reinterpret_cast<ElfW(Addr)*>(reloc) = ifunc_addr;
+ }
break;
#if defined(__aarch64__)
@@ -3465,7 +3499,7 @@
_exit(EXIT_FAILURE);
}
- __libc_init_tls(args);
+ __libc_init_main_thread(args);
// Initialize the linker's own global variables
linker_so.call_constructors();
diff --git a/linker/linker.h b/linker/linker.h
index b1d2566..6f8bf1f 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -29,13 +29,14 @@
#ifndef _LINKER_H_
#define _LINKER_H_
+#include <android/dlext.h>
#include <elf.h>
#include <inttypes.h>
#include <link.h>
-#include <unistd.h>
-#include <android/dlext.h>
#include <sys/stat.h>
+#include <unistd.h>
+#include "private/bionic_page.h"
#include "private/libc_logging.h"
#include "linked_list.h"
@@ -77,16 +78,6 @@
#define ELF64_R_TYPE(info) (((info) >> 56) & 0xff)
#endif
-// Returns the address of the page containing address 'x'.
-#define PAGE_START(x) ((x) & PAGE_MASK)
-
-// Returns the offset of address 'x' in its page.
-#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK)
-
-// Returns the address of the next page after address 'x', unless 'x' is
-// itself at the start of a page.
-#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
-
#define FLAG_LINKED 0x00000001
#define FLAG_EXE 0x00000004 // The main executable
#define FLAG_LINKER 0x00000010 // The linker itself
diff --git a/linker/linker_mips.cpp b/linker/linker_mips.cpp
index 75ea290..4dc97c8 100644
--- a/linker/linker_mips.cpp
+++ b/linker/linker_mips.cpp
@@ -264,10 +264,18 @@
// FP ABI-variant compatibility checks for MIPS o32 ABI
if (abiflags == nullptr) {
- // Old compiles lack the new abiflags section.
- // These compilers used -mfp32 -mdouble-float -modd-spreg defaults,
- // ie FP32 aka DOUBLE, using odd-numbered single-prec regs
- mips_fpabi = MIPS_ABI_FP_DOUBLE;
+ // Old compilers and some translators don't emit the new abiflags section.
+ const char* filename = get_realpath();
+ size_t len = strlen(filename);
+ if (len > 4 && (strcmp(filename+len-4, ".dex") == 0 ||
+ strcmp(filename+len-4, ".oat") == 0 )) {
+ // Assume dex2oat is compatible with target
+ mips_fpabi = MIPS_ABI_FP_XX;
+ } else {
+ // Old Android compilers used -mfp32 -mdouble-float -modd-spreg defaults,
+ // ie FP32 aka DOUBLE, using FR=0 mode fpregs & odd single-prec fpregs
+ mips_fpabi = MIPS_ABI_FP_DOUBLE;
+ }
} else {
mips_fpabi = abiflags->fp_abi;
if ( (abiflags->flags1 & MIPS_AFL_FLAGS1_ODDSPREG)
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index cf012f4..30bc6fa 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -382,7 +382,7 @@
return false;
}
- if (file_end >= static_cast<size_t>(file_size_)) {
+ if (file_end > static_cast<size_t>(file_size_)) {
DL_ERR("invalid ELF file \"%s\" load segment[%zd]:"
" p_offset (%p) + p_filesz (%p) ( = %p) past end of file (0x%" PRIx64 ")",
name_, i, reinterpret_cast<void*>(phdr->p_offset),
diff --git a/linker/tests/Android.mk b/linker/tests/Android.mk
index 35992c5..0aaee3e 100644
--- a/linker/tests/Android.mk
+++ b/linker/tests/Android.mk
@@ -23,7 +23,7 @@
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_CFLAGS += -g -Wall -Wextra -Wunused -Werror -std=gnu++11
+LOCAL_CFLAGS += -g -Wall -Wextra -Wunused -Werror
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../libc/
LOCAL_SRC_FILES := \
diff --git a/tests/Android.mk b/tests/Android.mk
index 4d9a136..205ccc5 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -46,8 +46,7 @@
test_cflags += -DUSE_JEMALLOC
endif
-test_cppflags = \
- -std=gnu++11 \
+test_cppflags := \
libBionicStandardTests_src_files := \
arpa_inet_test.cpp \
@@ -280,6 +279,7 @@
dlfcn_test.cpp \
libdl_test.cpp \
pthread_dlfcn_test.cpp \
+ thread_local_test.cpp \
bionic-unit-tests_cflags := $(test_cflags)
@@ -408,7 +408,7 @@
LOCAL_CXX = $(LOCAL_PATH)/file-check-cxx \
$(HOST_OUT_EXECUTABLES)/FileCheck \
- $($(LOCAL_2ND_ARCH_VAR_PREFIX)CXX_BARE) \
+ $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_CXX) \
GCC \
LOCAL_CLANG := false
diff --git a/tests/fortify_compilation_test.cpp b/tests/fortify_compilation_test.cpp
index 537b341..1326597 100644
--- a/tests/fortify_compilation_test.cpp
+++ b/tests/fortify_compilation_test.cpp
@@ -21,6 +21,7 @@
#include <poll.h>
#include <stdarg.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -230,3 +231,67 @@
// clang should emit a warning, but doesn't
ppoll(fds, 2, &timeout, NULL);
}
+
+void test_fread_overflow() {
+ char buf[4];
+ // NOLINTNEXTLINE(whitespace/line_length)
+ // GCC: error: call to '__fread_overflow' declared with attribute error: fread called with overflowing size * count
+ // clang should emit a warning, but doesn't
+ fread(buf, 2, (size_t)-1, stdin);
+}
+
+void test_fread_too_big() {
+ char buf[4];
+ // NOLINTNEXTLINE(whitespace/line_length)
+ // GCC: error: call to '__fread_too_big_error' declared with attribute error: fread called with size * count bigger than buffer
+ // clang should emit a warning, but doesn't
+ fread(buf, 1, 5, stdin);
+}
+
+void test_fwrite_overflow() {
+ char buf[4] = {0};
+ // NOLINTNEXTLINE(whitespace/line_length)
+ // GCC: error: call to '__fwrite_overflow' declared with attribute error: fwrite called with overflowing size * count
+ // clang should emit a warning, but doesn't
+ fwrite(buf, 2, (size_t)-1, stdout);
+}
+
+void test_fwrite_too_big() {
+ char buf[4] = {0};
+ // NOLINTNEXTLINE(whitespace/line_length)
+ // GCC: error: call to '__fwrite_too_big_error' declared with attribute error: fwrite called with size * count bigger than buffer
+ // clang should emit a warning, but doesn't
+ fwrite(buf, 1, 5, stdout);
+}
+
+void test_getcwd() {
+ char buf[4];
+ // NOLINTNEXTLINE(whitespace/line_length)
+ // GCC: error: call to '__getcwd_dest_size_error' declared with attribute error: getcwd called with size bigger than destination
+ // clang should emit a warning, but doesn't
+ getcwd(buf, 5);
+}
+
+void test_pwrite64_size() {
+ char buf[4] = {0};
+ // NOLINTNEXTLINE(whitespace/line_length)
+ // GCC: error: call to '__pwrite64_dest_size_error' declared with attribute error: pwrite64 called with size bigger than destination
+ // clang should emit a warning, but doesn't
+ pwrite64(STDOUT_FILENO, buf, 5, 0);
+}
+
+void test_pwrite64_too_big() {
+ void *buf = calloc(atoi("5"), 1);
+ // NOLINTNEXTLINE(whitespace/line_length)
+ // GCC: error: call to '__pwrite64_count_toobig_error' declared with attribute error: pwrite64 called with count > SSIZE_MAX
+ // clang should emit a warning, but doesn't
+ pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0);
+}
+
+void test_write_size() {
+ char buf[4] = {0};
+ // NOLINTNEXTLINE(whitespace/line_length)
+ // GCC: error: call to '__write_dest_size_error' declared with attribute error: write called with size bigger than destination
+ // clang should emit a warning, but doesn't
+ write(STDOUT_FILENO, buf, 5);
+}
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 4faccb4..a349da9 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -623,6 +623,12 @@
ASSERT_FORTIFY(FD_ISSET(0, set));
}
+TEST_F(DEATHTEST, getcwd_fortified) {
+ char buf[1];
+ size_t ct = atoi("2"); // prevent optimizations
+ ASSERT_FORTIFY(getcwd(buf, ct));
+}
+
TEST_F(DEATHTEST, pread_fortified) {
char buf[1];
size_t ct = atoi("2"); // prevent optimizations
@@ -639,6 +645,22 @@
close(fd);
}
+TEST_F(DEATHTEST, pwrite_fortified) {
+ char buf[1] = {0};
+ size_t ct = atoi("2"); // prevent optimizations
+ int fd = open("/dev/null", O_WRONLY);
+ ASSERT_FORTIFY(pwrite(fd, buf, ct, 0));
+ close(fd);
+}
+
+TEST_F(DEATHTEST, pwrite64_fortified) {
+ char buf[1] = {0};
+ size_t ct = atoi("2"); // prevent optimizations
+ int fd = open("/dev/null", O_WRONLY);
+ ASSERT_FORTIFY(pwrite64(fd, buf, ct, 0));
+ close(fd);
+}
+
TEST_F(DEATHTEST, read_fortified) {
char buf[1];
size_t ct = atoi("2"); // prevent optimizations
@@ -647,6 +669,30 @@
close(fd);
}
+TEST_F(DEATHTEST, write_fortified) {
+ char buf[1] = {0};
+ size_t ct = atoi("2"); // prevent optimizations
+ int fd = open("/dev/null", O_WRONLY);
+ ASSERT_EXIT(write(fd, buf, ct), testing::KilledBySignal(SIGABRT), "");
+ close(fd);
+}
+
+TEST_F(DEATHTEST, fread_fortified) {
+ char buf[1];
+ size_t ct = atoi("2"); // prevent optimizations
+ FILE* fp = fopen("/dev/null", "r");
+ ASSERT_FORTIFY(fread(buf, 1, ct, fp));
+ fclose(fp);
+}
+
+TEST_F(DEATHTEST, fwrite_fortified) {
+ char buf[1] = {0};
+ size_t ct = atoi("2"); // prevent optimizations
+ FILE* fp = fopen("/dev/null", "w");
+ ASSERT_FORTIFY(fwrite(buf, 1, ct, fp));
+ fclose(fp);
+}
+
TEST_F(DEATHTEST, readlink_fortified) {
char buf[1];
size_t ct = atoi("2"); // prevent optimizations
diff --git a/tests/gtest_main.cpp b/tests/gtest_main.cpp
index 692b7e8..35211da 100644
--- a/tests/gtest_main.cpp
+++ b/tests/gtest_main.cpp
@@ -256,7 +256,7 @@
while (*p != '\0' && isspace(*p)) {
++p;
}
- if (*p != '\0') {
+ if (*p != '\0' && *p != '#') {
// This is not we want, gtest must meet with some error when parsing the arguments.
fprintf(stderr, "argument error, check with --help\n");
return false;
diff --git a/tests/libs/Android.build.dt_runpath.mk b/tests/libs/Android.build.dt_runpath.mk
index e9b5265..44c8125 100644
--- a/tests/libs/Android.build.dt_runpath.mk
+++ b/tests/libs/Android.build.dt_runpath.mk
@@ -31,7 +31,7 @@
empty.cpp
libtest_dt_runpath_b_shared_libraries := libtest_dt_runpath_a
-libtest_dt_runpath_b_ldflags := -Wl,--rpath,\$${ORIGIN}/../dt_runpath_a
+libtest_dt_runpath_b_ldflags := -Wl,--rpath,\$${ORIGIN}/../dt_runpath_a -Wl,--enable-new-dtags
libtest_dt_runpath_b_relative_path := dt_runpath_b_c_x
module := libtest_dt_runpath_b
include $(LOCAL_PATH)/Android.build.testlib.mk
@@ -43,7 +43,7 @@
empty.cpp
libtest_dt_runpath_c_shared_libraries := libtest_dt_runpath_a
-libtest_dt_runpath_c_ldflags := -Wl,--rpath,\$${ORIGIN}/invalid_dt_runpath
+libtest_dt_runpath_c_ldflags := -Wl,--rpath,\$${ORIGIN}/invalid_dt_runpath -Wl,--enable-new-dtags
libtest_dt_runpath_c_relative_path := dt_runpath_b_c_x
module := libtest_dt_runpath_c
include $(LOCAL_PATH)/Android.build.testlib.mk
@@ -53,7 +53,7 @@
dlopen_b.cpp
libtest_dt_runpath_d_shared_libraries := libtest_dt_runpath_b libtest_dt_runpath_c
-libtest_dt_runpath_d_ldflags := -Wl,--rpath,\$${ORIGIN}/dt_runpath_b_c_x
+libtest_dt_runpath_d_ldflags := -Wl,--rpath,\$${ORIGIN}/dt_runpath_b_c_x -Wl,--enable-new-dtags
module := libtest_dt_runpath_d
include $(LOCAL_PATH)/Android.build.testlib.mk
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index 662aeef..8615934 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -17,7 +17,7 @@
LOCAL_PATH := $(call my-dir)
TEST_PATH := $(LOCAL_PATH)/..
-common_cppflags += -std=gnu++11
+common_cppflags :=
common_additional_dependencies := \
$(LOCAL_PATH)/Android.mk \
$(LOCAL_PATH)/Android.build.dt_runpath.mk \
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index 1d63c76..cf90045 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -22,6 +22,7 @@
#include <gtest/gtest.h>
#include <malloc.h>
#include <math.h>
+#include <stdint.h>
#include "buffer_tests.h"
@@ -1396,6 +1397,10 @@
delete[] heap_src;
}
+TEST(string, strnlen_74741) {
+ ASSERT_EQ(4U, strnlen("test", SIZE_MAX));
+}
+
TEST(string, mempcpy) {
char dst[6];
ASSERT_EQ(&dst[4], reinterpret_cast<char*>(mempcpy(dst, "hello", 4)));
diff --git a/tests/stubs_test.cpp b/tests/stubs_test.cpp
index 89d67cb..2d1bdee 100644
--- a/tests/stubs_test.cpp
+++ b/tests/stubs_test.cpp
@@ -163,8 +163,6 @@
check_get_passwd("u1_i0", 199000, TYPE_APP);
}
-#if defined(__BIONIC__)
-
static void check_group(const group* grp, const char* group_name, gid_t gid) {
ASSERT_TRUE(grp != NULL);
ASSERT_STREQ(group_name, grp->gr_name);
@@ -174,6 +172,8 @@
ASSERT_TRUE(grp->gr_mem[1] == NULL);
}
+#if defined(__BIONIC__)
+
static void check_getgrgid(const char* group_name, gid_t gid) {
errno = 0;
group* grp = getgrgid(gid);
@@ -190,17 +190,49 @@
check_group(grp, group_name, gid);
}
+static void check_getgrgid_r(const char* group_name, gid_t gid) {
+ group grp_storage;
+ char buf[512];
+ group* grp;
+
+ errno = 0;
+ int result = getgrgid_r(gid, &grp_storage, buf, sizeof(buf), &grp);
+ ASSERT_EQ(0, result);
+ ASSERT_EQ(0, errno);
+ SCOPED_TRACE("getgrgid_r");
+ check_group(grp, group_name, gid);
+}
+
+static void check_getgrnam_r(const char* group_name, gid_t gid) {
+ group grp_storage;
+ char buf[512];
+ group* grp;
+
+ errno = 0;
+ int result = getgrnam_r(group_name, &grp_storage, buf, sizeof(buf), &grp);
+ ASSERT_EQ(0, result);
+ ASSERT_EQ(0, errno);
+ SCOPED_TRACE("getgrnam_r");
+ check_group(grp, group_name, gid);
+}
+
static void check_get_group(const char* group_name, gid_t gid) {
check_getgrgid(group_name, gid);
check_getgrnam(group_name, gid);
+ check_getgrgid_r(group_name, gid);
+ check_getgrnam_r(group_name, gid);
}
#else // !defined(__BIONIC__)
-static void check_get_group(const char* /* group_name */, gid_t /* gid */) {
+static void print_no_getgrnam_test_info() {
GTEST_LOG_(INFO) << "This test is about gid/group_name translation for Android, which does nothing on libc other than bionic.\n";
}
+static void check_get_group(const char*, gid_t) {
+ print_no_getgrnam_test_info();
+}
+
#endif
TEST(getgrnam, system_id_root) {
@@ -259,3 +291,53 @@
TEST(getgrnam, app_id_u1_i0) {
check_get_group("u1_i0", 199000);
}
+
+TEST(getgrnam_r, reentrancy) {
+#if defined(__BIONIC__)
+ group grp_storage[2];
+ char buf[2][512];
+ group* grp[3];
+ int result = getgrnam_r("root", &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
+ ASSERT_EQ(0, result);
+ check_group(grp[0], "root", 0);
+ grp[1] = getgrnam("system");
+ check_group(grp[1], "system", 1000);
+ result = getgrnam_r("radio", &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
+ ASSERT_EQ(0, result);
+ check_group(grp[2], "radio", 1001);
+ check_group(grp[0], "root", 0);
+ check_group(grp[1], "system", 1000);
+#else
+ print_no_getgrnam_test_info();
+#endif
+}
+
+TEST(getgrgid_r, reentrancy) {
+#if defined(__BIONIC__)
+ group grp_storage[2];
+ char buf[2][512];
+ group* grp[3];
+ int result = getgrgid_r(0, &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
+ ASSERT_EQ(0, result);
+ check_group(grp[0], "root", 0);
+ grp[1] = getgrgid(1000);
+ check_group(grp[1], "system", 1000);
+ result = getgrgid_r(1001, &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
+ ASSERT_EQ(0, result);
+ check_group(grp[2], "radio", 1001);
+ check_group(grp[0], "root", 0);
+ check_group(grp[1], "system", 1000);
+#else
+ print_no_getgrnam_test_info();
+#endif
+}
+
+TEST(getgrnam_r, large_enough_suggested_buffer_size) {
+ long size = sysconf(_SC_GETGR_R_SIZE_MAX);
+ ASSERT_GT(size, 0);
+ char buf[size];
+ group grp_storage;
+ group* grp;
+ ASSERT_EQ(0, getgrnam_r("root", &grp_storage, buf, size, &grp));
+ check_group(grp, "root", 0);
+}
diff --git a/tests/thread_local_test.cpp b/tests/thread_local_test.cpp
new file mode 100644
index 0000000..5dead32
--- /dev/null
+++ b/tests/thread_local_test.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2015 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 <gtest/gtest.h>
+
+#ifdef __GNUC__
+// Gcc has a bug with -O -fdata-section for the arm target: http://b/22772147.
+// Until that bug is fixed, disable optimization since
+// it is not essential for this test.
+#pragma GCC optimize("-O0")
+#endif
+
+__thread int local_var = 100;
+int shared_var = 200;
+
+static void reset_vars() {
+ local_var = 1000;
+ shared_var = 2000;
+ // local_var should be reset by threads
+}
+
+typedef void* (*MyThread)(void*);
+
+static void* inc_shared_var(void* p) {
+ int *data = reinterpret_cast<int*>(p);
+ shared_var++;
+ *data = shared_var;
+ return nullptr;
+}
+
+static void* inc_local_var(void* p) {
+ int *data = reinterpret_cast<int*>(p);
+ local_var++;
+ *data = local_var;
+ return nullptr;
+}
+
+static int run_one_thread(MyThread foo) {
+ pthread_t t;
+ int data;
+ int error = pthread_create(&t, nullptr, foo, &data);
+ if (!error)
+ error = pthread_join(t, nullptr);
+ return error ? error : data;
+}
+
+TEST(thread_local_storage, shared) {
+ reset_vars();
+ ASSERT_EQ(local_var, 1000);
+ ASSERT_EQ(shared_var, 2000);
+
+ // Update shared_var, local_var remains 1000.
+ ASSERT_EQ(run_one_thread(inc_shared_var), 2001);
+ ASSERT_EQ(local_var, 1000);
+ ASSERT_EQ(shared_var, 2001);
+
+ ASSERT_EQ(run_one_thread(inc_shared_var), 2002);
+ ASSERT_EQ(local_var, 1000);
+ ASSERT_EQ(shared_var, 2002);
+
+ ASSERT_EQ(run_one_thread(inc_shared_var), 2003);
+ ASSERT_EQ(local_var, 1000);
+ ASSERT_EQ(shared_var, 2003);
+}
+
+TEST(thread_local_storage, local) {
+ reset_vars();
+ ASSERT_EQ(local_var, 1000);
+ ASSERT_EQ(shared_var, 2000);
+
+ // When a child thread updates its own TLS variable,
+ // this thread's local_var and shared_var are not changed.
+ // TLS local_var is initialized to 100 in a thread.
+ ASSERT_EQ(run_one_thread(inc_local_var), 101);
+ ASSERT_EQ(local_var, 1000);
+ ASSERT_EQ(shared_var, 2000);
+
+ ASSERT_EQ(run_one_thread(inc_local_var), 101);
+ ASSERT_EQ(local_var, 1000);
+ ASSERT_EQ(shared_var, 2000);
+
+ ASSERT_EQ(run_one_thread(inc_local_var), 101);
+ ASSERT_EQ(local_var, 1000);
+ ASSERT_EQ(shared_var, 2000);
+}
+
+// Test TLS initialization of more complicated type, array of struct.
+struct Point {
+ int x, y;
+};
+
+typedef Point Triangle[3];
+
+__thread Triangle local_triangle = {{10,10}, {20,20}, {30,30}};
+Triangle shared_triangle = {{1,1}, {2,2}, {3,3}};
+
+static void reset_triangle() {
+ static const Triangle t1 = {{3,3}, {4,4}, {5,5}};
+ static const Triangle t2 = {{2,2}, {3,3}, {4,4}};
+ memcpy(local_triangle, t1, sizeof(local_triangle));
+ memcpy(shared_triangle, t2, sizeof(shared_triangle));
+}
+
+static void* move_shared_triangle(void* p) {
+ int *data = reinterpret_cast<int*>(p);
+ shared_triangle[1].y++;
+ *data = shared_triangle[1].y;
+ return nullptr;
+}
+
+static void* move_local_triangle(void* p) {
+ int *data = reinterpret_cast<int*>(p);
+ local_triangle[1].y++;
+ *data = local_triangle[1].y;
+ return nullptr;
+}
+
+TEST(thread_local_storage, shared_triangle) {
+ reset_triangle();
+ ASSERT_EQ(local_triangle[1].y, 4);
+ ASSERT_EQ(shared_triangle[1].y, 3);
+
+ // Update shared_triangle, local_triangle remains 1000.
+ ASSERT_EQ(run_one_thread(move_shared_triangle), 4);
+ ASSERT_EQ(local_triangle[1].y, 4);
+ ASSERT_EQ(shared_triangle[1].y, 4);
+
+ ASSERT_EQ(run_one_thread(move_shared_triangle), 5);
+ ASSERT_EQ(local_triangle[1].y, 4);
+ ASSERT_EQ(shared_triangle[1].y, 5);
+
+ ASSERT_EQ(run_one_thread(move_shared_triangle), 6);
+ ASSERT_EQ(local_triangle[1].y, 4);
+ ASSERT_EQ(shared_triangle[1].y, 6);
+}
+
+TEST(thread_local_storage, local_triangle) {
+ reset_triangle();
+ ASSERT_EQ(local_triangle[1].y, 4);
+ ASSERT_EQ(shared_triangle[1].y, 3);
+
+ // Update local_triangle, parent thread's
+ // shared_triangle and local_triangle are unchanged.
+ ASSERT_EQ(run_one_thread(move_local_triangle), 21);
+ ASSERT_EQ(local_triangle[1].y, 4);
+ ASSERT_EQ(shared_triangle[1].y, 3);
+
+ ASSERT_EQ(run_one_thread(move_local_triangle), 21);
+ ASSERT_EQ(local_triangle[1].y, 4);
+ ASSERT_EQ(shared_triangle[1].y, 3);
+
+ ASSERT_EQ(run_one_thread(move_local_triangle), 21);
+ ASSERT_EQ(local_triangle[1].y, 4);
+ ASSERT_EQ(shared_triangle[1].y, 3);
+}
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 79c16d7..8e1f412 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -402,11 +402,11 @@
}
}
-TEST(unistd, getpid_caching_and_fork) {
+static void TestGetPidCachingWithFork(int (*fork_fn)()) {
pid_t parent_pid = getpid();
ASSERT_EQ(syscall(__NR_getpid), parent_pid);
- pid_t fork_result = fork();
+ pid_t fork_result = fork_fn();
ASSERT_NE(fork_result, -1);
if (fork_result == 0) {
// We're the child.
@@ -424,6 +424,14 @@
}
}
+TEST(unistd, getpid_caching_and_fork) {
+ TestGetPidCachingWithFork(fork);
+}
+
+TEST(unistd, getpid_caching_and_vfork) {
+ TestGetPidCachingWithFork(vfork);
+}
+
static int GetPidCachingCloneStartRoutine(void*) {
AssertGetPidCorrect();
return 123;
@@ -694,6 +702,8 @@
VERIFY_SYSCONF_POSITIVE(_SC_IOV_MAX);
VERIFY_SYSCONF_POSITIVE(_SC_PAGESIZE);
VERIFY_SYSCONF_POSITIVE(_SC_PAGE_SIZE);
+ VerifySysconf(_SC_PAGE_SIZE, "_SC_PAGE_SIZE",
+ [](long v){return v == sysconf(_SC_PAGESIZE) && v == getpagesize();});
VERIFY_SYSCONF_POSITIVE(_SC_XOPEN_UNIX);
VERIFY_SYSCONF_POSITIVE(_SC_AIO_LISTIO_MAX);
VERIFY_SYSCONF_POSITIVE(_SC_AIO_MAX);