diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2019-11-11 21:09:58 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2019-11-11 21:09:58 +0000 |
commit | 0995b12fb60ecafea0d176a49837955a415828c5 (patch) | |
tree | 648c033a8422762b21015778795272c4fefe300a | |
parent | dfc03a5df956b3e4e9ef67e75d60d0253914633f (diff) | |
parent | 987583ebc20e66dba39e3f7a0f695b06fc932196 (diff) | |
download | bionic-android10-mainline-resolv-release.tar.gz |
Snap for 6001391 from 987583ebc20e66dba39e3f7a0f695b06fc932196 to qt-aml-resolv-releaseandroid-mainline-10.0.0_r8android10-mainline-resolv-release
Change-Id: Iebc558c9a8211541c89560bb8c8ef637b8c7d549
136 files changed, 2378 insertions, 949 deletions
diff --git a/.clang-format b/.clang-format index b8c642840..7630d1626 100644 --- a/.clang-format +++ b/.clang-format @@ -12,3 +12,4 @@ UseTab: Never PenaltyExcessCharacter: 32 Cpp11BracedListStyle: false +IncludeBlocks: Preserve
\ No newline at end of file diff --git a/docs/native_allocator.md b/docs/native_allocator.md index 76954700f..adfa6ef07 100644 --- a/docs/native_allocator.md +++ b/docs/native_allocator.md @@ -100,6 +100,19 @@ To run all of the compliance tests: The allocation tests are not meant to be complete, so it is expected that a native allocator will have its own set of tests that can be run. +### Libmemunreachable Tests +The libmemunreachable tests verify that the iterator functions are working +properly. + +To run all of the tests: + + adb shell /data/nativetest64/memunreachable_binder_test/memunreachable_binder_test + adb shell /data/nativetest/memunreachable_binder_test/memunreachable_binder_test + adb shell /data/nativetest64/memunreachable_test/memunreachable_test + adb shell /data/nativetest/memunreachable_test/memunreachable_test + adb shell /data/nativetest64/memunreachable_unit_test/memunreachable_unit_test + adb shell /data/nativetest/memunreachable_unit_test/memunreachable_unit_test + ### CTS Entropy Test In addition to the bionic tests, there is also a CTS test that is designed to verify that the addresses returned by malloc are sufficiently randomized diff --git a/libc/Android.bp b/libc/Android.bp index 3e2ee1dcd..c5ea4c522 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -83,6 +83,12 @@ cc_defaults { // lld complains about duplicate symbols in libcrt and libgcc. Suppress the // warning since this is intended right now. ldflags: ["-Wl,-z,muldefs"], + + product_variables: { + experimental_mte: { + cflags: ["-DANDROID_EXPERIMENTAL_MTE"], + }, + }, } // Defaults for native allocator libs/includes to make it @@ -136,19 +142,21 @@ cc_defaults { } // ======================================================== -// libc_stack_protector.a - stack protector code +// libc_bootstrap.a - -fno-stack-protector and -ffreestanding // ======================================================== // -// Code that implements the stack protector (or that runs -// before TLS has been set up) needs to be compiled with -// -fno-stack-protector, since it accesses the stack canary -// TLS slot. +// Code that implements the stack protector (or that runs before TLS has been set up) needs to be +// compiled with -fno-stack-protector, since it accesses the stack canary TLS slot. In the linker, +// some of this code runs before ifunc resolvers have made string.h functions work, so compile with +// -ffreestanding. cc_library_static { srcs: [ "bionic/__libc_init_main_thread.cpp", "bionic/__stack_chk_fail.cpp", + "bionic/bionic_call_ifunc_resolver.cpp", + "bionic/getauxval.cpp", ], arch: { arm64: { @@ -166,20 +174,25 @@ cc_library_static { }, defaults: ["libc_defaults"], - cflags: ["-fno-stack-protector"], - name: "libc_stack_protector", + cflags: ["-fno-stack-protector", "-ffreestanding"], + name: "libc_bootstrap", } -// libc_init_static.cpp also needs to be built without stack protector, -// because it's responsible for setting up TLS for static executables. -// This isn't the case for dynamic executables because the dynamic linker -// has already set up the main thread's TLS. +// libc_init_static.cpp and libc_init_dynamic.cpp need to be built without stack protector. +// libc_init_static.cpp sets up TLS for static executables, and libc_init_dynamic.cpp initializes +// the stack protector global variable. cc_library_static { name: "libc_init_static", defaults: ["libc_defaults"], srcs: ["bionic/libc_init_static.cpp"], - cflags: ["-fno-stack-protector"], + cflags: [ + "-fno-stack-protector", + + // Compile libc_init_static.cpp with -ffreestanding, because some of its code is called + // from the linker before ifunc resolvers have made string.h functions available. + "-ffreestanding", + ], } cc_library_static { @@ -271,8 +284,6 @@ cc_library_static { defaults: ["libc_defaults"], srcs: [ "upstream-freebsd/lib/libc/gen/ldexp.c", - "upstream-freebsd/lib/libc/gen/sleep.c", - "upstream-freebsd/lib/libc/gen/usleep.c", "upstream-freebsd/lib/libc/stdlib/getopt_long.c", "upstream-freebsd/lib/libc/stdlib/hcreate.c", "upstream-freebsd/lib/libc/stdlib/hcreate_r.c", @@ -780,12 +791,6 @@ cc_library_static { cc_library_static { defaults: ["libc_defaults"], srcs: [ - // The data that backs getauxval is initialized in the libc init - // functions which are invoked by the linker. If this file is included - // in libc_ndk.a, only one of the copies of the global data will be - // initialized, resulting in nullptr dereferences. - "bionic/getauxval.cpp", - // These require getauxval, which isn't available on older platforms. "bionic/sysconf.cpp", "bionic/vdso.cpp", @@ -856,20 +861,28 @@ cc_library_static { }, arm64: { srcs: [ - "arch-arm64/generic/bionic/memchr.S", "arch-arm64/generic/bionic/memcmp.S", "arch-arm64/generic/bionic/memcpy.S", "arch-arm64/generic/bionic/memmove.S", "arch-arm64/generic/bionic/memset.S", "arch-arm64/generic/bionic/stpcpy.S", - "arch-arm64/generic/bionic/strchr.S", - "arch-arm64/generic/bionic/strcmp.S", "arch-arm64/generic/bionic/strcpy.S", - "arch-arm64/generic/bionic/strlen.S", - "arch-arm64/generic/bionic/strncmp.S", - "arch-arm64/generic/bionic/strnlen.S", "arch-arm64/generic/bionic/wmemmove.S", + "arch-arm64/default/bionic/memchr.S", + "arch-arm64/default/bionic/strchr.S", + "arch-arm64/default/bionic/strcmp.S", + "arch-arm64/default/bionic/strlen.S", + "arch-arm64/default/bionic/strncmp.S", + "arch-arm64/default/bionic/strnlen.S", + + "arch-arm64/mte/bionic/memchr.c", + "arch-arm64/mte/bionic/strchr.cpp", + "arch-arm64/mte/bionic/strcmp.c", + "arch-arm64/mte/bionic/strlen.c", + "arch-arm64/mte/bionic/strncmp.c", + "arch-arm64/mte/bionic/strnlen.c", + "arch-arm64/bionic/__bionic_clone.S", "arch-arm64/bionic/_exit_with_stack_teardown.S", "arch-arm64/bionic/setjmp.S", @@ -1178,6 +1191,7 @@ cc_library_static { "bionic/sigaction.cpp", "bionic/signal.cpp", "bionic/sigprocmask.cpp", + "bionic/sleep.cpp", "bionic/spawn.cpp", "bionic/stat.cpp", "bionic/stdlib_l.cpp", @@ -1212,6 +1226,7 @@ cc_library_static { "bionic/tmpfile.cpp", "bionic/umount.cpp", "bionic/unlink.cpp", + "bionic/usleep.cpp", "bionic/wait.cpp", "bionic/wchar.cpp", "bionic/wchar_l.cpp", @@ -1412,6 +1427,7 @@ cc_library_static { whole_static_libs: [ "libc_bionic_ndk", + "libc_bootstrap", "libc_fortify", "libc_freebsd", "libc_freebsd_large_stack", @@ -1419,7 +1435,6 @@ cc_library_static { "libc_netbsd", "libc_openbsd_large_stack", "libc_openbsd_ndk", - "libc_stack_protector", "libc_syscalls", "libc_tzcode", "libm", @@ -1443,6 +1458,7 @@ cc_library_static { whole_static_libs: [ "libc_bionic", "libc_bionic_ndk", + "libc_bootstrap", "libc_dns", "libc_fortify", "libc_freebsd", @@ -1452,7 +1468,6 @@ cc_library_static { "libc_openbsd", "libc_openbsd_large_stack", "libc_openbsd_ndk", - "libc_stack_protector", "libc_syscalls", "libc_tzcode", "libstdc++", @@ -1480,11 +1495,11 @@ cc_library_static { } // ======================================================== -// libc_common_static.a For static binaries. +// libc_static_dispatch.a // ======================================================== cc_library_static { defaults: ["libc_defaults"], - name: "libc_common_static", + name: "libc_static_dispatch", arch: { x86: { @@ -1493,21 +1508,21 @@ cc_library_static { arm: { srcs: ["arch-arm/static_function_dispatch.S"], }, + arm64: { + srcs: ["arch-arm64/static_function_dispatch.S"], + }, }, - - whole_static_libs: [ - "libc_common", - ], } // ======================================================== -// libc_common_shared.a For shared libraries. +// libc_dynamic_dispatch.a // ======================================================== cc_library_static { defaults: ["libc_defaults"], - name: "libc_common_shared", + name: "libc_dynamic_dispatch", cflags: [ + "-ffreestanding", "-fno-stack-protector", "-fno-jump-tables", ], @@ -1518,10 +1533,35 @@ cc_library_static { arm: { srcs: ["arch-arm/dynamic_function_dispatch.cpp"], }, + arm64: { + srcs: ["arch-arm64/dynamic_function_dispatch.cpp"], + }, }, +} + +// ======================================================== +// libc_common_static.a For static binaries. +// ======================================================== +cc_library_static { + defaults: ["libc_defaults"], + name: "libc_common_static", + + whole_static_libs: [ + "libc_common", + "libc_static_dispatch", + ], +} + +// ======================================================== +// libc_common_shared.a For shared libraries. +// ======================================================== +cc_library_static { + defaults: ["libc_defaults"], + name: "libc_common_shared", whole_static_libs: [ "libc_common", + "libc_dynamic_dispatch", ], } @@ -1545,19 +1585,16 @@ cc_library_static { // libc_nomalloc.a // ======================================================== // -// This is a version of the static C library that does not -// include malloc. It's useful in situations when the user wants -// to provide their own malloc implementation, or wants to -// explicitly disallow the use of malloc, such as in the -// dynamic linker. +// This is a version of the static C library used by the dynamic linker that exclude malloc. It also +// excludes functions selected using ifunc's (e.g. for string.h). Link in either +// libc_static_dispatch or libc_dynamic_dispatch to provide those functions. cc_library_static { name: "libc_nomalloc", defaults: ["libc_defaults"], - cflags: ["-DLIBC_STATIC"], whole_static_libs: [ - "libc_common_static", + "libc_common", "libc_init_static", "libc_unwind_static", ], diff --git a/libc/arch-arm/dynamic_function_dispatch.cpp b/libc/arch-arm/dynamic_function_dispatch.cpp index 75000a248..1d2f38ff5 100644 --- a/libc/arch-arm/dynamic_function_dispatch.cpp +++ b/libc/arch-arm/dynamic_function_dispatch.cpp @@ -149,7 +149,7 @@ DEFINE_IFUNC_FOR(memmove) { typedef void* memcpy_func(void*, const void*, size_t); DEFINE_IFUNC_FOR(memcpy) { - return memmove_resolver(); + return memmove_resolver(hwcap); } typedef void* __memcpy_func(void*, const void*, size_t); diff --git a/libc/arch-arm64/generic/bionic/memchr.S b/libc/arch-arm64/default/bionic/memchr.S index 7b7e69912..7fbcc8fd4 100644 --- a/libc/arch-arm64/generic/bionic/memchr.S +++ b/libc/arch-arm64/default/bionic/memchr.S @@ -69,7 +69,7 @@ * identify exactly which byte has matched. */ -ENTRY(memchr) +ENTRY(memchr_default) /* * Magic constant 0x40100401 allows us to identify which lane matches * the requested byte. @@ -161,4 +161,4 @@ ENTRY(memchr) .Lzero_length: mov result, xzr ret -END(memchr) +END(memchr_default) diff --git a/libc/arch-arm64/generic/bionic/strchr.S b/libc/arch-arm64/default/bionic/strchr.S index 2db0c7681..f8cb724cc 100644 --- a/libc/arch-arm64/generic/bionic/strchr.S +++ b/libc/arch-arm64/default/bionic/strchr.S @@ -73,7 +73,7 @@ /* Locals and temporaries. */ -ENTRY(strchr) +ENTRY(strchr_default) /* Magic constant 0x40100401 to allow us to identify which lane matches the requested byte. Magic constant 0x80200802 used similarly for NUL termination. */ @@ -150,4 +150,4 @@ ENTRY(strchr) add result, src, tmp1, lsr #1 csel result, result, xzr, eq ret -END(strchr) +END(strchr_default) diff --git a/libc/arch-arm64/generic/bionic/strcmp.S b/libc/arch-arm64/default/bionic/strcmp.S index fbc215e6d..dfac7c42c 100644 --- a/libc/arch-arm64/generic/bionic/strcmp.S +++ b/libc/arch-arm64/default/bionic/strcmp.S @@ -58,7 +58,7 @@ #define pos x11 /* Start of performance-critical section -- one 64B cache line. */ -ENTRY(strcmp) +ENTRY(strcmp_default) .p2align 6 eor tmp1, src1, src2 mov zeroones, #REP8_01 @@ -189,4 +189,4 @@ L(loop_misaligned): L(done): sub result, data1, data2 ret -END(strcmp) +END(strcmp_default) diff --git a/libc/arch-arm64/generic/bionic/strlen.S b/libc/arch-arm64/default/bionic/strlen.S index 6e540fc33..07c5294c2 100644 --- a/libc/arch-arm64/generic/bionic/strlen.S +++ b/libc/arch-arm64/default/bionic/strlen.S @@ -94,7 +94,7 @@ whether the first fetch, which may be misaligned, crosses a page boundary. */ -ENTRY(strlen) +ENTRY(strlen_default) and tmp1, srcin, MIN_PAGE_SIZE - 1 mov zeroones, REP8_01 cmp tmp1, MIN_PAGE_SIZE - 16 @@ -224,4 +224,4 @@ L(page_cross): csel data2, data2, tmp2, eq b L(page_cross_entry) -END(strlen) +END(strlen_default) diff --git a/libc/arch-arm64/generic/bionic/strncmp.S b/libc/arch-arm64/default/bionic/strncmp.S index b81f43aa2..5432b738e 100644 --- a/libc/arch-arm64/generic/bionic/strncmp.S +++ b/libc/arch-arm64/default/bionic/strncmp.S @@ -65,7 +65,7 @@ .rep 7 nop /* Pad so that the loop below fits a cache line. */ .endr -ENTRY(strncmp) +ENTRY(strncmp_default) cbz limit, .Lret0 eor tmp1, src1, src2 mov zeroones, #REP8_01 @@ -277,4 +277,4 @@ ENTRY(strncmp) .Lret0: mov result, #0 ret -END(strncmp) +END(strncmp_default) diff --git a/libc/arch-arm64/generic/bionic/strnlen.S b/libc/arch-arm64/default/bionic/strnlen.S index 0ad446e4f..169453207 100644 --- a/libc/arch-arm64/generic/bionic/strnlen.S +++ b/libc/arch-arm64/default/bionic/strnlen.S @@ -68,7 +68,7 @@ mov len, limit ret -ENTRY(strnlen) +ENTRY(strnlen_default) cbz limit, .Lhit_limit mov zeroones, #REP8_01 bic src, srcin, #15 @@ -171,4 +171,4 @@ ENTRY(strnlen) csinv data1, data1, xzr, le csel data2, data2, data2a, le b .Lrealigned -END(strnlen) +END(strnlen_default) diff --git a/libc/arch-arm64/dynamic_function_dispatch.cpp b/libc/arch-arm64/dynamic_function_dispatch.cpp new file mode 100644 index 000000000..37abea429 --- /dev/null +++ b/libc/arch-arm64/dynamic_function_dispatch.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2019 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 <platform/bionic/mte_kernel.h> +#include <private/bionic_ifuncs.h> +#include <stddef.h> +#include <sys/auxv.h> + +extern "C" { + +static bool supports_mte(unsigned long hwcap2) { +#ifdef ANDROID_EXPERIMENTAL_MTE + return hwcap2 & HWCAP2_MTE; +#else + (void)hwcap2; + return false; +#endif +} + +typedef void* memchr_func(const void*, int, size_t); +DEFINE_IFUNC_FOR(memchr) { + if (supports_mte(arg->_hwcap2)) { + RETURN_FUNC(memchr_func, memchr_mte); + } else { + RETURN_FUNC(memchr_func, memchr_default); + } +} + +typedef char* strchr_func(const char*, int); +DEFINE_IFUNC_FOR(strchr) { + if (supports_mte(arg->_hwcap2)) { + RETURN_FUNC(strchr_func, strchr_mte); + } else { + RETURN_FUNC(strchr_func, strchr_default); + } +} + +typedef int strcmp_func(const char*, const char*); +DEFINE_IFUNC_FOR(strcmp) { + if (supports_mte(arg->_hwcap2)) { + RETURN_FUNC(strcmp_func, strcmp_mte); + } else { + RETURN_FUNC(strcmp_func, strcmp_default); + } +} + +typedef size_t strlen_func(const char*); +DEFINE_IFUNC_FOR(strlen) { + if (supports_mte(arg->_hwcap2)) { + RETURN_FUNC(strlen_func, strlen_mte); + } else { + RETURN_FUNC(strlen_func, strlen_default); + } +} + +typedef int strncmp_func(const char*, const char*, int); +DEFINE_IFUNC_FOR(strncmp) { + if (supports_mte(arg->_hwcap2)) { + RETURN_FUNC(strncmp_func, strncmp_mte); + } else { + RETURN_FUNC(strncmp_func, strncmp_default); + } +} + +typedef size_t strnlen_func(const char*, int); +DEFINE_IFUNC_FOR(strnlen) { + if (supports_mte(arg->_hwcap2)) { + RETURN_FUNC(strnlen_func, strnlen_mte); + } else { + RETURN_FUNC(strnlen_func, strnlen_default); + } +} + +} // extern "C" diff --git a/libc/arch-arm64/mte/bionic/memchr.c b/libc/arch-arm64/mte/bionic/memchr.c new file mode 100644 index 000000000..33b2fc2c6 --- /dev/null +++ b/libc/arch-arm64/mte/bionic/memchr.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 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 <upstream-openbsd/android/include/openbsd-compat.h> + +#define memchr memchr_mte +#include <upstream-openbsd/lib/libc/string/memchr.c> diff --git a/libc/arch-arm64/mte/bionic/strchr.cpp b/libc/arch-arm64/mte/bionic/strchr.cpp new file mode 100644 index 000000000..7d394df0a --- /dev/null +++ b/libc/arch-arm64/mte/bionic/strchr.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2019 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. + */ + +#define strchr strchr_mte +#include <bionic/strchr.cpp> diff --git a/libc/arch-arm64/mte/bionic/strcmp.c b/libc/arch-arm64/mte/bionic/strcmp.c new file mode 100644 index 000000000..0e134f025 --- /dev/null +++ b/libc/arch-arm64/mte/bionic/strcmp.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 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 <upstream-openbsd/android/include/openbsd-compat.h> + +#define strcmp strcmp_mte +#include <upstream-openbsd/lib/libc/string/strcmp.c> diff --git a/libc/arch-arm64/mte/bionic/strlen.c b/libc/arch-arm64/mte/bionic/strlen.c new file mode 100644 index 000000000..de88320ce --- /dev/null +++ b/libc/arch-arm64/mte/bionic/strlen.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 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 <upstream-openbsd/android/include/openbsd-compat.h> + +#define strlen strlen_mte +#include <upstream-openbsd/lib/libc/string/strlen.c> diff --git a/libc/arch-arm64/mte/bionic/strncmp.c b/libc/arch-arm64/mte/bionic/strncmp.c new file mode 100644 index 000000000..54d08e98e --- /dev/null +++ b/libc/arch-arm64/mte/bionic/strncmp.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 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 <upstream-openbsd/android/include/openbsd-compat.h> + +#define strncmp strncmp_mte +#include <upstream-openbsd/lib/libc/string/strncmp.c> diff --git a/libc/arch-arm64/mte/bionic/strnlen.c b/libc/arch-arm64/mte/bionic/strnlen.c new file mode 100644 index 000000000..3dc251db3 --- /dev/null +++ b/libc/arch-arm64/mte/bionic/strnlen.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2019 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. + */ + +#define strnlen strnlen_mte +#include <bionic/strnlen.c> diff --git a/libc/arch-arm64/static_function_dispatch.S b/libc/arch-arm64/static_function_dispatch.S new file mode 100644 index 000000000..8e3a4c131 --- /dev/null +++ b/libc/arch-arm64/static_function_dispatch.S @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 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> + +#define FUNCTION_DELEGATE(name, impl) \ +ENTRY(name); \ + b impl; \ +END(name) + +FUNCTION_DELEGATE(memchr, memchr_mte) +FUNCTION_DELEGATE(strchr, strchr_mte) +FUNCTION_DELEGATE(strcmp, strcmp_mte) +FUNCTION_DELEGATE(strlen, strlen_mte) +FUNCTION_DELEGATE(strncmp, strncmp_mte) +FUNCTION_DELEGATE(strnlen, strnlen_mte) diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp index 6e1b0de25..94cf1f8e3 100644 --- a/libc/bionic/__libc_init_main_thread.cpp +++ b/libc/bionic/__libc_init_main_thread.cpp @@ -57,7 +57,9 @@ static pthread_internal_t main_thread; // // This is in a file by itself because it needs to be built with // -fno-stack-protector because it's responsible for setting up the main -// thread's TLS (which stack protector relies on). +// thread's TLS (which stack protector relies on). It's also built with +// -ffreestanding because the early init function runs in the linker before +// ifunc resolvers have run. // Do enough setup to: // - Let the dynamic linker invoke system calls (and access errno) @@ -65,7 +67,8 @@ static pthread_internal_t main_thread; // - Allow the stack protector to work (with a zero cookie) // Avoid doing much more because, when this code is called within the dynamic // linker, the linker binary hasn't been relocated yet, so certain kinds of code -// are hazardous, such as accessing non-hidden global variables. +// are hazardous, such as accessing non-hidden global variables or calling +// string.h functions. __BIONIC_WEAK_FOR_NATIVE_BRIDGE extern "C" void __libc_init_main_thread_early(const KernelArgumentBlock& args, bionic_tcb* temp_tcb) { @@ -80,6 +83,23 @@ extern "C" void __libc_init_main_thread_early(const KernelArgumentBlock& args, main_thread.set_cached_pid(main_thread.tid); } +// This code is used both by each new pthread and the code that initializes the main thread. +void __init_tcb(bionic_tcb* tcb, pthread_internal_t* thread) { +#ifdef TLS_SLOT_SELF + // On x86, slot 0 must point to itself so code can read the thread pointer by + // loading %fs:0 or %gs:0. + tcb->tls_slot(TLS_SLOT_SELF) = &tcb->tls_slot(TLS_SLOT_SELF); +#endif + tcb->tls_slot(TLS_SLOT_THREAD_ID) = thread; +} + +void __init_tcb_dtv(bionic_tcb* tcb) { + // Initialize the DTV slot to a statically-allocated empty DTV. The first + // access to a dynamic TLS variable allocates a new DTV. + static const TlsDtv zero_dtv = {}; + __set_tcb_dtv(tcb, const_cast<TlsDtv*>(&zero_dtv)); +} + // Finish initializing the main thread. __BIONIC_WEAK_FOR_NATIVE_BRIDGE extern "C" void __libc_init_main_thread_late() { diff --git a/libc/bionic/bionic_call_ifunc_resolver.cpp b/libc/bionic/bionic_call_ifunc_resolver.cpp new file mode 100644 index 000000000..437de78ce --- /dev/null +++ b/libc/bionic/bionic_call_ifunc_resolver.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019 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_call_ifunc_resolver.h" +#include <sys/auxv.h> +#include <sys/ifunc.h> + +#include "private/bionic_auxv.h" + +// This code is called in the linker before it has been relocated, so minimize calls into other +// parts of Bionic. In particular, we won't ever have two ifunc resolvers called concurrently, so +// initializing the ifunc resolver argument doesn't need to be thread-safe. + +ElfW(Addr) __bionic_call_ifunc_resolver(ElfW(Addr) resolver_addr) { +#if defined(__aarch64__) + typedef ElfW(Addr) (*ifunc_resolver_t)(uint64_t, __ifunc_arg_t*); + static __ifunc_arg_t arg; + static bool initialized = false; + if (!initialized) { + initialized = true; + arg._size = sizeof(__ifunc_arg_t); + arg._hwcap = getauxval(AT_HWCAP); + arg._hwcap2 = getauxval(AT_HWCAP2); + } + return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(arg._hwcap | _IFUNC_ARG_HWCAP, &arg); +#elif defined(__arm__) + typedef ElfW(Addr) (*ifunc_resolver_t)(unsigned long); + static unsigned long hwcap; + static bool initialized = false; + if (!initialized) { + initialized = true; + hwcap = getauxval(AT_HWCAP); + } + return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(hwcap); +#else + typedef ElfW(Addr) (*ifunc_resolver_t)(void); + return reinterpret_cast<ifunc_resolver_t>(resolver_addr)(); +#endif +} diff --git a/libc/bionic/bionic_netlink.cpp b/libc/bionic/bionic_netlink.cpp index f2449dc9a..5d5a02624 100644 --- a/libc/bionic/bionic_netlink.cpp +++ b/libc/bionic/bionic_netlink.cpp @@ -39,8 +39,6 @@ #include "private/ErrnoRestorer.h" NetlinkConnection::NetlinkConnection() { - fd_ = -1; - // The kernel keeps packets under 8KiB (NLMSG_GOODSIZE), // but that's a bit too large to go on the stack. size_ = 8192; @@ -48,8 +46,6 @@ NetlinkConnection::NetlinkConnection() { } NetlinkConnection::~NetlinkConnection() { - ErrnoRestorer errno_restorer; - if (fd_ != -1) close(fd_); delete[] data_; } @@ -59,9 +55,9 @@ bool NetlinkConnection::SendRequest(int type) { if (data_ == nullptr) return false; // Did we open a netlink socket yet? - if (fd_ == -1) { - fd_ = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); - if (fd_ == -1) return false; + if (fd_.get() == -1) { + fd_.reset(socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE)); + if (fd_.get() == -1) return false; } // Construct and send the message. @@ -74,13 +70,13 @@ bool NetlinkConnection::SendRequest(int type) { request.hdr.nlmsg_type = type; request.hdr.nlmsg_len = sizeof(request); request.msg.rtgen_family = AF_UNSPEC; // All families. - return (TEMP_FAILURE_RETRY(send(fd_, &request, sizeof(request), 0)) == sizeof(request)); + return (TEMP_FAILURE_RETRY(send(fd_.get(), &request, sizeof(request), 0)) == sizeof(request)); } bool NetlinkConnection::ReadResponses(void callback(void*, nlmsghdr*), void* context) { // Read through all the responses, handing interesting ones to the callback. ssize_t bytes_read; - while ((bytes_read = TEMP_FAILURE_RETRY(recv(fd_, data_, size_, 0))) > 0) { + while ((bytes_read = TEMP_FAILURE_RETRY(recv(fd_.get(), data_, size_, 0))) > 0) { nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(data_); for (; NLMSG_OK(hdr, static_cast<size_t>(bytes_read)); hdr = NLMSG_NEXT(hdr, bytes_read)) { if (hdr->nlmsg_type == NLMSG_DONE) return true; diff --git a/libc/bionic/bionic_netlink.h b/libc/bionic/bionic_netlink.h index a21200e64..fc1bd0fb0 100644 --- a/libc/bionic/bionic_netlink.h +++ b/libc/bionic/bionic_netlink.h @@ -33,6 +33,8 @@ #include <linux/netlink.h> #include <linux/rtnetlink.h> +#include "private/ScopedFd.h" + struct nlmsghdr; class NetlinkConnection { @@ -44,7 +46,7 @@ class NetlinkConnection { bool ReadResponses(void callback(void*, nlmsghdr*), void* context); private: - int fd_; + ScopedFd fd_; char* data_; size_t size_; }; diff --git a/libc/bionic/fchmodat.cpp b/libc/bionic/fchmodat.cpp index c28e15ac7..632d2ac85 100644 --- a/libc/bionic/fchmodat.cpp +++ b/libc/bionic/fchmodat.cpp @@ -32,7 +32,7 @@ #include <errno.h> #include <unistd.h> -#include "private/ErrnoRestorer.h" +#include "private/ScopedFd.h" extern "C" int __fchmodat(int, const char*, mode_t); @@ -47,20 +47,15 @@ int fchmodat(int dirfd, const char* pathname, mode_t mode, int flags) { // at https://sourceware.org/bugzilla/show_bug.cgi?id=14578 // comment #10 - int fd = openat(dirfd, pathname, O_PATH | O_NOFOLLOW | O_CLOEXEC); - if (fd == -1) { - return -1; // returns errno from openat - } + ScopedFd fd(openat(dirfd, pathname, O_PATH | O_NOFOLLOW | O_CLOEXEC)); + if (fd.get() == -1) return -1; // POSIX requires that ENOTSUP be returned when the system // doesn't support setting the mode of a symbolic link. // This is true for all Linux kernels. // We rely on the O_PATH compatibility layer added in the // fchmod() function to get errno correct. - int result = fchmod(fd, mode); - ErrnoRestorer errno_restorer; // don't let close() clobber errno - close(fd); - return result; + return fchmod(fd.get(), mode); } return __fchmodat(dirfd, pathname, mode); diff --git a/libc/bionic/getauxval.cpp b/libc/bionic/getauxval.cpp index c8f867b64..f865f97b4 100644 --- a/libc/bionic/getauxval.cpp +++ b/libc/bionic/getauxval.cpp @@ -36,7 +36,6 @@ // This function needs to be safe to call before TLS is set up, so it can't // access errno or the stack protector. -__attribute__((no_stack_protector)) __LIBC_HIDDEN__ unsigned long __bionic_getauxval(unsigned long type, bool& exists) { for (ElfW(auxv_t)* v = __libc_shared_globals()->auxv; v->a_type != AT_NULL; ++v) { if (v->a_type == type) { diff --git a/libc/bionic/getentropy.cpp b/libc/bionic/getentropy.cpp index 2c6e417b8..9c93e713b 100644 --- a/libc/bionic/getentropy.cpp +++ b/libc/bionic/getentropy.cpp @@ -31,22 +31,20 @@ #include <sys/random.h> #include <unistd.h> +#include "private/ScopedFd.h" + static int getentropy_urandom(void* buffer, size_t buffer_size, int saved_errno) { - int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_NOFOLLOW | O_CLOEXEC, 0)); - if (fd == -1) return -1; + ScopedFd fd(TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_NOFOLLOW | O_CLOEXEC, 0))); + if (fd.get() == -1) return -1; size_t collected = 0; while (collected < buffer_size) { - ssize_t count = TEMP_FAILURE_RETRY(read(fd, static_cast<char*>(buffer) + collected, + ssize_t count = TEMP_FAILURE_RETRY(read(fd.get(), static_cast<char*>(buffer) + collected, buffer_size - collected)); - if (count == -1) { - close(fd); - return -1; - } + if (count == -1) return -1; collected += count; } - close(fd); errno = saved_errno; return 0; } diff --git a/libc/bionic/grp_pwd_file.cpp b/libc/bionic/grp_pwd_file.cpp index e13604e68..81cf8936d 100644 --- a/libc/bionic/grp_pwd_file.cpp +++ b/libc/bionic/grp_pwd_file.cpp @@ -37,6 +37,7 @@ #include <async_safe/log.h> #include "private/ErrnoRestorer.h" +#include "private/ScopedFd.h" // This file mmap's /*/etc/passwd and /*/etc/group in order to return their contents without any // allocations. Note that these files and the strings contained within them are explicitly not @@ -230,19 +231,16 @@ bool MmapFile::GetFile(const char** start, const char** end) { } bool MmapFile::DoMmap() { - int fd = open(filename_, O_CLOEXEC | O_NOFOLLOW | O_RDONLY); + ScopedFd fd(open(filename_, O_CLOEXEC | O_NOFOLLOW | O_RDONLY)); struct stat fd_stat; - if (fstat(fd, &fd_stat) == -1) { - close(fd); + if (fstat(fd.get(), &fd_stat) == -1) { return false; } auto mmap_size = fd_stat.st_size; - void* map_result = mmap(nullptr, mmap_size, PROT_READ, MAP_SHARED, fd, 0); - close(fd); - + void* map_result = mmap(nullptr, mmap_size, PROT_READ, MAP_SHARED, fd.get(), 0); if (map_result == MAP_FAILED) { return false; } diff --git a/libc/bionic/jemalloc.h b/libc/bionic/jemalloc.h index ef77c9c99..4ce51c0a8 100644 --- a/libc/bionic/jemalloc.h +++ b/libc/bionic/jemalloc.h @@ -29,7 +29,7 @@ __BEGIN_DECLS void* je_aligned_alloc_wrapper(size_t, size_t); -int je_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*); +int je_malloc_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*); int je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen) __attribute__((nothrow)); struct mallinfo je_mallinfo(); void je_malloc_disable(); diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp index 7d0445784..ef488eecc 100644 --- a/libc/bionic/jemalloc_wrapper.cpp +++ b/libc/bionic/jemalloc_wrapper.cpp @@ -140,30 +140,32 @@ int je_malloc_info(int options, FILE* fp) { return -1; } - MallocXmlElem root(fp, "malloc", "version=\"jemalloc-1\""); + fflush(fp); + int fd = fileno(fp); + MallocXmlElem root(fd, "malloc", "version=\"jemalloc-1\""); // Dump all of the large allocations in the arenas. for (size_t i = 0; i < je_mallinfo_narenas(); i++) { struct mallinfo mi = je_mallinfo_arena_info(i); if (mi.hblkhd != 0) { - MallocXmlElem arena_elem(fp, "heap", "nr=\"%d\"", i); + MallocXmlElem arena_elem(fd, "heap", "nr=\"%d\"", i); { - MallocXmlElem(fp, "allocated-large").Contents("%zu", mi.ordblks); - MallocXmlElem(fp, "allocated-huge").Contents("%zu", mi.uordblks); - MallocXmlElem(fp, "allocated-bins").Contents("%zu", mi.fsmblks); + MallocXmlElem(fd, "allocated-large").Contents("%zu", mi.ordblks); + MallocXmlElem(fd, "allocated-huge").Contents("%zu", mi.uordblks); + MallocXmlElem(fd, "allocated-bins").Contents("%zu", mi.fsmblks); size_t total = 0; for (size_t j = 0; j < je_mallinfo_nbins(); j++) { struct mallinfo mi = je_mallinfo_bin_info(i, j); if (mi.ordblks != 0) { - MallocXmlElem bin_elem(fp, "bin", "nr=\"%d\"", j); - MallocXmlElem(fp, "allocated").Contents("%zu", mi.ordblks); - MallocXmlElem(fp, "nmalloc").Contents("%zu", mi.uordblks); - MallocXmlElem(fp, "ndalloc").Contents("%zu", mi.fordblks); + MallocXmlElem bin_elem(fd, "bin", "nr=\"%d\"", j); + MallocXmlElem(fd, "allocated").Contents("%zu", mi.ordblks); + MallocXmlElem(fd, "nmalloc").Contents("%zu", mi.uordblks); + MallocXmlElem(fd, "ndalloc").Contents("%zu", mi.fordblks); total += mi.ordblks; } } - MallocXmlElem(fp, "bins-total").Contents("%zu", total); + MallocXmlElem(fd, "bins-total").Contents("%zu", total); } } } diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp index b4bddcef5..28c0b0c95 100644 --- a/libc/bionic/libc_init_static.cpp +++ b/libc/bionic/libc_init_static.cpp @@ -39,6 +39,7 @@ #include "libc_init_common.h" #include "pthread_internal.h" +#include "private/bionic_call_ifunc_resolver.h" #include "private/bionic_elf_tls.h" #include "private/bionic_globals.h" #include "private/bionic_macros.h" @@ -81,11 +82,10 @@ static void call_ifunc_resolvers() { return; } - typedef ElfW(Addr) (*ifunc_resolver_t)(void); for (ElfW(Rela) *r = __rela_iplt_start; r != __rela_iplt_end; ++r) { ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset); ElfW(Addr) resolver = r->r_addend; - *offset = reinterpret_cast<ifunc_resolver_t>(resolver)(); + *offset = __bionic_call_ifunc_resolver(resolver); } } #else @@ -103,11 +103,10 @@ static void call_ifunc_resolvers() { return; } - typedef ElfW(Addr) (*ifunc_resolver_t)(void); for (ElfW(Rel) *r = __rel_iplt_start; r != __rel_iplt_end; ++r) { ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset); ElfW(Addr) resolver = *offset; - *offset = reinterpret_cast<ifunc_resolver_t>(resolver)(); + *offset = __bionic_call_ifunc_resolver(resolver); } } #endif @@ -232,6 +231,9 @@ extern "C" void android_set_application_target_sdk_version(int target) { g_target_sdk_version = target; } +// This function is called in the dynamic linker before ifunc resolvers have run, so this file is +// compiled with -ffreestanding to avoid implicit string.h function calls. (It shouldn't strictly +// be necessary, though.) __LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals() { static libc_shared_globals globals; return &globals; diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp index 96e614048..a0da3dbff 100644 --- a/libc/bionic/malloc_common.cpp +++ b/libc/bionic/malloc_common.cpp @@ -215,9 +215,9 @@ extern "C" int malloc_iterate(uintptr_t base, size_t size, void (*callback)(uintptr_t base, size_t size, void* arg), void* arg) { auto dispatch_table = GetDispatchTable(); if (__predict_false(dispatch_table != nullptr)) { - return dispatch_table->iterate(base, size, callback, arg); + return dispatch_table->malloc_iterate(base, size, callback, arg); } - return Malloc(iterate)(base, size, callback, arg); + return Malloc(malloc_iterate)(base, size, callback, arg); } // Disable calls to malloc so malloc_iterate gets a consistent view of @@ -247,9 +247,10 @@ extern "C" ssize_t malloc_backtrace(void*, uintptr_t*, size_t) { #if __has_feature(hwaddress_sanitizer) // FIXME: implement these in HWASan allocator. -extern "C" int __sanitizer_iterate(uintptr_t base __unused, size_t size __unused, - void (*callback)(uintptr_t base, size_t size, void* arg) __unused, - void* arg __unused) { +extern "C" int __sanitizer_malloc_iterate(uintptr_t base __unused, size_t size __unused, + void (*callback)(uintptr_t base, size_t size, void* arg) + __unused, + void* arg __unused) { return 0; } diff --git a/libc/bionic/malloc_common.h b/libc/bionic/malloc_common.h index 2176e634d..89dccc31a 100644 --- a/libc/bionic/malloc_common.h +++ b/libc/bionic/malloc_common.h @@ -42,9 +42,9 @@ __BEGIN_DECLS // FIXME: implement these in HWASan allocator. -int __sanitizer_iterate(uintptr_t base, size_t size, - void (*callback)(uintptr_t base, size_t size, void* arg), - void* arg); +int __sanitizer_malloc_iterate(uintptr_t base, size_t size, + void (*callback)(uintptr_t base, size_t size, void* arg), + void* arg); void __sanitizer_malloc_disable(); void __sanitizer_malloc_enable(); int __sanitizer_malloc_info(int options, FILE* fp); diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp index 9ad79a0d0..0ac3f62e6 100644 --- a/libc/bionic/malloc_common_dynamic.cpp +++ b/libc/bionic/malloc_common_dynamic.cpp @@ -95,7 +95,7 @@ static constexpr MallocDispatch __libc_malloc_default_dispatch #if defined(HAVE_DEPRECATED_MALLOC_FUNCS) Malloc(valloc), #endif - Malloc(iterate), + Malloc(malloc_iterate), Malloc(malloc_disable), Malloc(malloc_enable), Malloc(mallopt), @@ -184,7 +184,8 @@ static bool InitMallocFunctions(void* impl_handler, MallocDispatch* table, const if (!InitMallocFunction<MallocRealloc>(impl_handler, &table->realloc, prefix, "realloc")) { return false; } - if (!InitMallocFunction<MallocIterate>(impl_handler, &table->iterate, prefix, "iterate")) { + if (!InitMallocFunction<MallocIterate>(impl_handler, &table->malloc_iterate, prefix, + "malloc_iterate")) { return false; } if (!InitMallocFunction<MallocMallocDisable>(impl_handler, &table->malloc_disable, prefix, diff --git a/libc/bionic/malloc_heapprofd.cpp b/libc/bionic/malloc_heapprofd.cpp index 62249fb1d..586022200 100644 --- a/libc/bionic/malloc_heapprofd.cpp +++ b/libc/bionic/malloc_heapprofd.cpp @@ -104,7 +104,7 @@ static constexpr MallocDispatch __heapprofd_init_dispatch #if defined(HAVE_DEPRECATED_MALLOC_FUNCS) Malloc(valloc), #endif - Malloc(iterate), + Malloc(malloc_iterate), Malloc(malloc_disable), Malloc(malloc_enable), Malloc(mallopt), diff --git a/libc/bionic/malloc_limit.cpp b/libc/bionic/malloc_limit.cpp index 6a67cae95..d8c0ebe54 100644 --- a/libc/bionic/malloc_limit.cpp +++ b/libc/bionic/malloc_limit.cpp @@ -350,9 +350,9 @@ static struct mallinfo LimitMallinfo() { static int LimitIterate(uintptr_t base, size_t size, void (*callback)(uintptr_t, size_t, void*), void* arg) { auto dispatch_table = GetDefaultDispatchTable(); if (__predict_false(dispatch_table != nullptr)) { - return dispatch_table->iterate(base, size, callback, arg); + return dispatch_table->malloc_iterate(base, size, callback, arg); } - return Malloc(iterate)(base, size, callback, arg); + return Malloc(malloc_iterate)(base, size, callback, arg); } static void LimitMallocDisable() { diff --git a/libc/bionic/net_if.cpp b/libc/bionic/net_if.cpp index db9c9ea22..ad53364c9 100644 --- a/libc/bionic/net_if.cpp +++ b/libc/bionic/net_if.cpp @@ -40,37 +40,27 @@ #include <sys/socket.h> #include <unistd.h> -#include "private/ErrnoRestorer.h" +#include "private/ScopedFd.h" #include "bionic_netlink.h" char* if_indextoname(unsigned ifindex, char* ifname) { - int s = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0); - if (s == -1) return nullptr; + ScopedFd s(socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0)); + if (s.get() == -1) return nullptr; - struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_ifindex = ifindex; - - int rc = ioctl(s, SIOCGIFNAME, &ifr); - ErrnoRestorer errno_restorer; - close(s); - return (rc == -1) ? nullptr : strncpy(ifname, ifr.ifr_name, IFNAMSIZ); + ifreq ifr = {.ifr_ifindex = static_cast<int>(ifindex)}; + return (ioctl(s.get(), SIOCGIFNAME, &ifr) == -1) ? nullptr + : strncpy(ifname, ifr.ifr_name, IFNAMSIZ); } unsigned if_nametoindex(const char* ifname) { - int s = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0); - if (s == -1) return 0; + ScopedFd s(socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0)); + if (s.get() == -1) return 0; - struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); + ifreq ifr = {}; strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ifr.ifr_name[IFNAMSIZ - 1] = 0; - - int rc = ioctl(s, SIOCGIFINDEX, &ifr); - ErrnoRestorer errno_restorer; - close(s); - return (rc == -1) ? 0 : ifr.ifr_ifindex; + return (ioctl(s.get(), SIOCGIFINDEX, &ifr) == -1) ? 0 : ifr.ifr_ifindex; } struct if_list { diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp index 1dc10667b..03af2d94a 100644 --- a/libc/bionic/pthread_create.cpp +++ b/libc/bionic/pthread_create.cpp @@ -54,31 +54,12 @@ void __init_user_desc(struct user_desc*, bool, void*); #endif -// This code is used both by each new pthread and the code that initializes the main thread. -__attribute__((no_stack_protector)) -void __init_tcb(bionic_tcb* tcb, pthread_internal_t* thread) { -#ifdef TLS_SLOT_SELF - // On x86, slot 0 must point to itself so code can read the thread pointer by - // loading %fs:0 or %gs:0. - tcb->tls_slot(TLS_SLOT_SELF) = &tcb->tls_slot(TLS_SLOT_SELF); -#endif - tcb->tls_slot(TLS_SLOT_THREAD_ID) = thread; -} - __attribute__((no_stack_protector)) void __init_tcb_stack_guard(bionic_tcb* tcb) { // GCC looks in the TLS for the stack guard on x86, so copy it there from our global. tcb->tls_slot(TLS_SLOT_STACK_GUARD) = reinterpret_cast<void*>(__stack_chk_guard); } -__attribute__((no_stack_protector)) -void __init_tcb_dtv(bionic_tcb* tcb) { - // Initialize the DTV slot to a statically-allocated empty DTV. The first - // access to a dynamic TLS variable allocates a new DTV. - static const TlsDtv zero_dtv = {}; - __set_tcb_dtv(tcb, const_cast<TlsDtv*>(&zero_dtv)); -} - void __init_bionic_tls_ptrs(bionic_tcb* tcb, bionic_tls* tls) { tcb->thread()->bionic_tls = tls; tcb->tls_slot(TLS_SLOT_BIONIC_TLS) = tls; diff --git a/libc/bionic/scudo.h b/libc/bionic/scudo.h index d9933c4d0..a80d75418 100644 --- a/libc/bionic/scudo.h +++ b/libc/bionic/scudo.h @@ -52,7 +52,7 @@ void* scudo_pvalloc(size_t); void* scudo_valloc(size_t); #endif -int scudo_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*); +int scudo_malloc_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*); void scudo_malloc_disable(); void scudo_malloc_enable(); diff --git a/libc/bionic/scudo_wrapper.cpp b/libc/bionic/scudo_wrapper.cpp index e17f20ba5..debd8d996 100644 --- a/libc/bionic/scudo_wrapper.cpp +++ b/libc/bionic/scudo_wrapper.cpp @@ -48,7 +48,7 @@ int scudo_malloc_info(int /*options*/, FILE* /*fp*/) { return -1; } -int scudo_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*) { +int scudo_malloc_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*) { return 0; } diff --git a/libc/bionic/sleep.cpp b/libc/bionic/sleep.cpp new file mode 100644 index 000000000..fcfd9b2a0 --- /dev/null +++ b/libc/bionic/sleep.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <unistd.h> + +#include <time.h> + +unsigned sleep(unsigned s) { +#if !defined(__LP64__) + // `s` is `unsigned`, but tv_sec is `int` on LP32. + if (s > INT_MAX) return s - INT_MAX + sleep(INT_MAX); +#endif + + timespec ts = {.tv_sec = static_cast<time_t>(s)}; + return (nanosleep(&ts, &ts) == -1) ? ts.tv_sec : 0; +} diff --git a/libc/bionic/system_property_set.cpp b/libc/bionic/system_property_set.cpp index c508db162..e981a58d9 100644 --- a/libc/bionic/system_property_set.cpp +++ b/libc/bionic/system_property_set.cpp @@ -46,6 +46,7 @@ #include "private/bionic_defs.h" #include "private/bionic_macros.h" +#include "private/ScopedFd.h" static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME; static const char* kServiceVersionPropertyName = "ro.property_service.version"; @@ -53,8 +54,8 @@ static const char* kServiceVersionPropertyName = "ro.property_service.version"; class PropertyServiceConnection { public: PropertyServiceConnection() : last_error_(0) { - socket_ = ::socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (socket_ == -1) { + socket_.reset(::socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0)); + if (socket_.get() == -1) { last_error_ = errno; return; } @@ -66,15 +67,15 @@ class PropertyServiceConnection { addr.sun_family = AF_LOCAL; socklen_t alen = namelen + offsetof(sockaddr_un, sun_path) + 1; - if (TEMP_FAILURE_RETRY(connect(socket_, reinterpret_cast<sockaddr*>(&addr), alen)) == -1) { + if (TEMP_FAILURE_RETRY(connect(socket_.get(), + reinterpret_cast<sockaddr*>(&addr), alen)) == -1) { last_error_ = errno; - close(socket_); - socket_ = -1; + socket_.reset(); } } bool IsValid() { - return socket_ != -1; + return socket_.get() != -1; } int GetLastError() { @@ -82,18 +83,12 @@ class PropertyServiceConnection { } bool RecvInt32(int32_t* value) { - int result = TEMP_FAILURE_RETRY(recv(socket_, value, sizeof(*value), MSG_WAITALL)); + int result = TEMP_FAILURE_RETRY(recv(socket_.get(), value, sizeof(*value), MSG_WAITALL)); return CheckSendRecvResult(result, sizeof(*value)); } int socket() { - return socket_; - } - - ~PropertyServiceConnection() { - if (socket_ != -1) { - close(socket_); - } + return socket_.get(); } private: @@ -109,7 +104,7 @@ class PropertyServiceConnection { return last_error_ == 0; } - int socket_; + ScopedFd socket_; int last_error_; friend class SocketWriter; diff --git a/libc/bionic/usleep.cpp b/libc/bionic/usleep.cpp new file mode 100644 index 000000000..22046846e --- /dev/null +++ b/libc/bionic/usleep.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <unistd.h> + +#include <time.h> + +int usleep(useconds_t us) { + timespec ts; + ts.tv_sec = us / 1000000; + ts.tv_nsec = (us % 1000000) * 1000; + return nanosleep(&ts, nullptr); +} diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c index 4e1aa61d5..d0c11d2b0 100644 --- a/libc/dns/net/getaddrinfo.c +++ b/libc/dns/net/getaddrinfo.c @@ -470,7 +470,7 @@ android_getaddrinfo_proxy( break; } - struct addrinfo* ai = calloc(1, sizeof(struct addrinfo) + sizeof(struct sockaddr_storage)); + ai = calloc(1, sizeof(struct addrinfo) + sizeof(struct sockaddr_storage)); if (ai == NULL) { break; } diff --git a/libc/include/bits/sys_statvfs_inlines.h b/libc/include/bits/sys_statvfs_inlines.h index fd4578cd5..991fac716 100644 --- a/libc/include/bits/sys_statvfs_inlines.h +++ b/libc/include/bits/sys_statvfs_inlines.h @@ -38,20 +38,20 @@ __BEGIN_DECLS #if defined(__BIONIC_NEED_STATVFS_INLINES) -static __inline void __bionic_statfs_to_statvfs(const struct statfs* __in, - struct statvfs* __out) { - __out->f_bsize = __in->f_bsize; - __out->f_frsize = __in->f_frsize; - __out->f_blocks = __in->f_blocks; - __out->f_bfree = __in->f_bfree; - __out->f_bavail = __in->f_bavail; - __out->f_files = __in->f_files; - __out->f_ffree = __in->f_ffree; - __out->f_favail = __in->f_ffree; - __out->f_fsid = __in->f_fsid.__val[0] | - __BIONIC_CAST(static_cast, uint64_t, __in->f_fsid.__val[1]) << 32; - __out->f_flag = __in->f_flags; - __out->f_namemax = __in->f_namelen; +static __inline void __bionic_statfs_to_statvfs(const struct statfs* __src, + struct statvfs* __dst) { + __dst->f_bsize = __src->f_bsize; + __dst->f_frsize = __src->f_frsize; + __dst->f_blocks = __src->f_blocks; + __dst->f_bfree = __src->f_bfree; + __dst->f_bavail = __src->f_bavail; + __dst->f_files = __src->f_files; + __dst->f_ffree = __src->f_ffree; + __dst->f_favail = __src->f_ffree; + __dst->f_fsid = __src->f_fsid.__val[0] | + __BIONIC_CAST(static_cast, uint64_t, __src->f_fsid.__val[1]) << 32; + __dst->f_flag = __src->f_flags; + __dst->f_namemax = __src->f_namelen; } __BIONIC_SYS_STATVFS_INLINE int statvfs(const char* __path, diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h index 1c5d64c19..c45c91ff4 100644 --- a/libc/include/fcntl.h +++ b/libc/include/fcntl.h @@ -26,9 +26,14 @@ * SUCH DAMAGE. */ -#ifndef _FCNTL_H +#pragma once #define _FCNTL_H +/** + * @file fcntl.h + * @brief File control operations. + */ + #include <sys/cdefs.h> #include <sys/types.h> #include <linux/fadvise.h> @@ -48,47 +53,180 @@ __BEGIN_DECLS #ifdef __LP64__ /* LP64 kernels don't have F_*64 defines because their flock is 64-bit. */ +/** Flag for flock(). */ #define F_GETLK64 F_GETLK +/** Flag for flock(). */ #define F_SETLK64 F_SETLK +/** Flag for flock(). */ #define F_SETLKW64 F_SETLKW #endif +/** Flag for open(). */ #define O_ASYNC FASYNC +/** Flag for open(). */ #define O_RSYNC O_SYNC #if __ANDROID_API__ >= __ANDROID_API_L__ +/** Flag for splice(). */ #define SPLICE_F_MOVE 1 +/** Flag for splice(). */ #define SPLICE_F_NONBLOCK 2 +/** Flag for splice(). */ #define SPLICE_F_MORE 4 +/** Flag for splice(). */ #define SPLICE_F_GIFT 8 #endif #if __ANDROID_API__ >= __ANDROID_API_O__ +/** Flag for sync_file_range(). */ #define SYNC_FILE_RANGE_WAIT_BEFORE 1 +/** Flag for sync_file_range(). */ #define SYNC_FILE_RANGE_WRITE 2 +/** Flag for sync_file_range(). */ #define SYNC_FILE_RANGE_WAIT_AFTER 4 #endif +/** + * [creat(2)](http://man7.org/linux/man-pages/man2/creat.2.html) + * creates a file. + * + * Returns a new file descriptor on success and returns -1 and sets `errno` on + * failure. + */ int creat(const char* __path, mode_t __mode); +/** See creat(). */ int creat64(const char* __path, mode_t __mode) __INTRODUCED_IN(21); + +/** + * [openat(2)](http://man7.org/linux/man-pages/man2/openat.2.html) + * opens (and possibly creates) a file. + * + * Returns a new file descriptor on success and returns -1 and sets `errno` on + * failure. + */ int openat(int __dir_fd, const char* __path, int __flags, ...); +/** See openat(). */ int openat64(int __dir_fd, const char* __path, int __flags, ...) __INTRODUCED_IN(21); + +/** + * [open(2)](http://man7.org/linux/man-pages/man2/open.2.html) + * opens (and possibly creates) a file. + * + * Returns a new file descriptor on success and returns -1 and sets `errno` on + * failure. + */ int open(const char* __path, int __flags, ...); +/** See open(). */ int open64(const char* __path, int __flags, ...) __INTRODUCED_IN(21); + +/** + * [splice(2)](http://man7.org/linux/man-pages/man2/splice.2.html) + * splices data to/from a pipe. + * + * Valid flags are `SPLICE_F_MOVE`, `SPLICE_F_NONBLOCK`, `SPLICE_F_MORE`, and + * `SPLICE_F_GIFT`. + * + * Returns the number of bytes spliced on success and returns -1 and sets + * `errno` on failure. + * + * Available since API level 21. + */ ssize_t splice(int __in_fd, off64_t* __in_offset, int __out_fd, off64_t* __out_offset, size_t __length, unsigned int __flags) __INTRODUCED_IN(21); + +/** + * [tee(2)](http://man7.org/linux/man-pages/man2/tee.2.html) + * duplicates data from one pipe to another. + * + * Valid flags are `SPLICE_F_MOVE`, `SPLICE_F_NONBLOCK`, `SPLICE_F_MORE`, and + * `SPLICE_F_GIFT`. + * + * Returns the number of bytes duplicated on success and returns -1 and sets + * `errno` on failure. + * + * Available since API level 21. + */ ssize_t tee(int __in_fd, int __out_fd, size_t __length, unsigned int __flags) __INTRODUCED_IN(21); + +/** + * [vmsplice(2)](http://man7.org/linux/man-pages/man2/vmsplice.2.html) + * splices data to/from a pipe. + * + * Valid flags are `SPLICE_F_MOVE`, `SPLICE_F_NONBLOCK`, `SPLICE_F_MORE`, and + * `SPLICE_F_GIFT`. + * + * Returns the number of bytes spliced on success and returns -1 and sets + * `errno` on failure. + * + * Available since API level 21. + */ ssize_t vmsplice(int __fd, const struct iovec* __iov, size_t __count, unsigned int __flags) __INTRODUCED_IN(21); +/** + * [fallocate(2)](http://man7.org/linux/man-pages/man2/fallocate.2.html) + * is a Linux-specific extension of posix_fallocate(). + * + * Valid flags are `FALLOC_FL_KEEP_SIZE`, `FALLOC_FL_PUNCH_HOLE`, + * `FALLOC_FL_NO_HIDE_STALE`, `FALLOC_FL_COLLAPSE_RANGE`, + * `FALLOC_FL_ZERO_RANGE`, `FALLOC_FL_INSERT_RANGE`, and + * `FALLOC_FL_UNSHARE_RANGE`. + * + * Returns 0 on success and returns -1 and sets `errno` on failure. + * + * Available since API level 21. + */ int fallocate(int __fd, int __mode, off_t __offset, off_t __length) __RENAME_IF_FILE_OFFSET64(fallocate64) __INTRODUCED_IN(21); +/** See fallocate(). */ int fallocate64(int __fd, int __mode, off64_t __offset, off64_t __length) __INTRODUCED_IN(21); + +/** + * [posix_fadvise(2)](http://man7.org/linux/man-pages/man2/posix_fadvise.2.html) + * declares an expected access pattern for file data. + * + * Valid flags are `POSIX_FADV_NORMAL`, `POSIX_FADV_RANDOM`, + * `POSIX_FADV_SEQUENTIAL`, `POSIX_FADV_WILLNEED`, `POSIX_FADV_DONTNEED`, + * and `POSIX_FADV_NOREUSE`. + * + * Returns 0 on success and returns an error number on failure. + * + * Available since API level 21. + */ int posix_fadvise(int __fd, off_t __offset, off_t __length, int __advice) __RENAME_IF_FILE_OFFSET64(posix_fadvise64) __INTRODUCED_IN(21); +/** See posix_fadvise(). */ int posix_fadvise64(int __fd, off64_t __offset, off64_t __length, int __advice) __INTRODUCED_IN(21); + +/** + * [posix_fallocate(2)](http://man7.org/linux/man-pages/man2/posix_fallocate.2.html) + * allocates file space. + * + * Returns 0 on success and returns an error number on failure. + * + * Available since API level 21. + */ int posix_fallocate(int __fd, off_t __offset, off_t __length) __RENAME_IF_FILE_OFFSET64(posix_fallocate64) __INTRODUCED_IN(21); +/** See posix_fallocate(). */ int posix_fallocate64(int __fd, off64_t __offset, off64_t __length) __INTRODUCED_IN(21); #if defined(__USE_GNU) -ssize_t readahead(int __fd, off64_t __offset, size_t __length) __INTRODUCED_IN(16); + +/** + * [readahead(2)](http://man7.org/linux/man-pages/man2/readahead.2.html) + * initiates readahead for the given file. + * + * Returns 0 on success and returns -1 and sets `errno` on failure. + */ +ssize_t readahead(int __fd, off64_t __offset, size_t __length); + +/** + * [sync_file_range(2)](http://man7.org/linux/man-pages/man2/sync_file_range.2.html) + * syncs part of a file with disk. + * + * Valid flags are `SYNC_FILE_RANGE_WAIT_BEFORE`, `SYNC_FILE_RANGE_WRITE`, and + * `SYNC_FILE_RANGE_WAIT_AFTER`. + * + * Returns 0 on success and returns -1 and sets `errno` on failure. + */ int sync_file_range(int __fd, off64_t __offset, off64_t __length, unsigned int __flags) __INTRODUCED_IN(26); + #endif #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS) @@ -96,5 +234,3 @@ int sync_file_range(int __fd, off64_t __offset, off64_t __length, unsigned int _ #endif __END_DECLS - -#endif diff --git a/libc/include/search.h b/libc/include/search.h index 97fdedaeb..7a75404c9 100644 --- a/libc/include/search.h +++ b/libc/include/search.h @@ -6,30 +6,56 @@ * $FreeBSD: release/9.0.0/include/search.h 105250 2002-10-16 14:29:23Z robert $ */ -#ifndef _SEARCH_H_ -#define _SEARCH_H_ +#pragma once + +/** + * @file search.h + * @brief Queues, hash tables, trees, and linear array searches. + */ #include <sys/cdefs.h> #include <sys/types.h> +/** See hsearch()/hsearch_r(). */ typedef enum { FIND, ENTER } ACTION; +/** See hsearch()/hsearch_r(). */ typedef struct entry { + /** The string key. */ char* key; + /** The associated data. */ void* data; } ENTRY; +/** + * Constants given to the twalk() visitor. + * Note that the constant names are misleading. + */ typedef enum { + /** + * If this is the first visit to a non-leaf node. + * Use this for *preorder* traversal. + */ preorder, + /** + * If this is the second visit to a non-leaf node. + * Use this for *inorder* traversal. + */ postorder, + /** + * If this is the third visit to a non-leaf node. + * Use this for *postorder* traversal. + */ endorder, + /** If this is the first and only visit to a leaf node. */ leaf } VISIT; #if defined(__USE_BSD) || defined(__USE_GNU) +/** The hash table type for hcreate_r()/hdestroy_r()/hsearch_r(). */ struct hsearch_data { struct __hsearch* __hsearch; }; @@ -37,30 +63,157 @@ struct hsearch_data { __BEGIN_DECLS +/** + * [insque(3)](http://man7.org/linux/man-pages/man3/insque.3.html) inserts + * an item in a queue (an intrusive doubly-linked list). + * + * Available since API level 21. + */ void insque(void* __element, void* __previous) __INTRODUCED_IN(21); + +/** + * [remque(3)](http://man7.org/linux/man-pages/man3/remque.3.html) removes + * an item from a queue (an intrusive doubly-linked list). + * + * Available since API level 21. + */ void remque(void* __element) __INTRODUCED_IN(21); -int hcreate(size_t) __INTRODUCED_IN(28); +/** + * [hcreate(3)](http://man7.org/linux/man-pages/man3/hcreate.3.html) + * initializes the global hash table, with space for at least `__n` elements. + * + * See hcreate_r() if you need more than one hash table. + * + * Returns *non-zero* on success and returns 0 and sets `errno` on failure. + * + * Available since API level 28. + */ +int hcreate(size_t __n) __INTRODUCED_IN(28); + +/** + * [hdestroy(3)](http://man7.org/linux/man-pages/man3/hdestroy.3.html) destroys + * the global hash table. + * + * See hdestroy_r() if you need more than one hash table. + * + * Available since API level 28. + */ void hdestroy(void) __INTRODUCED_IN(28); -ENTRY* hsearch(ENTRY, ACTION) __INTRODUCED_IN(28); + +/** + * [hsearch(3)](http://man7.org/linux/man-pages/man3/hsearch.3.html) finds or + * inserts `__entry` in the global hash table, based on `__action`. + * + * See hsearch_r() if you need more than one hash table. + * + * Returns a pointer to the entry on success, and returns NULL and sets + * `errno` on failure. + * + * Available since API level 28. + */ +ENTRY* hsearch(ENTRY __entry, ACTION __action) __INTRODUCED_IN(28); #if defined(__USE_BSD) || defined(__USE_GNU) -int hcreate_r(size_t, struct hsearch_data*) __INTRODUCED_IN(28); -void hdestroy_r(struct hsearch_data*) __INTRODUCED_IN(28); -int hsearch_r(ENTRY, ACTION, ENTRY**, struct hsearch_data*) __INTRODUCED_IN(28); -#endif -void* lfind(const void* __key, const void* __base, size_t* __count, size_t __size, int (*__comparator)(const void*, const void*)) - __INTRODUCED_IN(21); -void* lsearch(const void* __key, void* __base, size_t* __count, size_t __size, int (*__comparator)(const void*, const void*)) - __INTRODUCED_IN(21); +/** + * [hcreate_r(3)](http://man7.org/linux/man-pages/man3/hcreate_r.3.html) + * initializes a hash table `__table` with space for at least `__n` elements. + * + * Returns *non-zero* on success and returns 0 and sets `errno` on failure. + * + * Available since API level 28. + */ +int hcreate_r(size_t __n, struct hsearch_data* __table) __INTRODUCED_IN(28); -void* tdelete(const void* __key, void** __root_ptr, int (*__comparator)(const void*, const void*)) __INTRODUCED_IN(16); -void tdestroy(void* __root, void (*__free_fn)(void*)) __INTRODUCED_IN(16); -void* tfind(const void* __key, void* const* __root_ptr, int (*__comparator)(const void*, const void*)) __INTRODUCED_IN(16); -void* tsearch(const void* __key, void** __root_ptr, int (*__comparator)(const void*, const void*)) __INTRODUCED_IN(16); -void twalk(const void* __root, void (*__visitor)(const void*, VISIT, int)) __INTRODUCED_IN(21); +/** + * [hdestroy_r(3)](http://man7.org/linux/man-pages/man3/hdestroy_r.3.html) destroys + * the hash table `__table`. + * + * Available since API level 28. + */ +void hdestroy_r(struct hsearch_data* __table) __INTRODUCED_IN(28); -__END_DECLS +/** + * [hsearch_r(3)](http://man7.org/linux/man-pages/man3/hsearch_r.3.html) finds or + * inserts `__entry` in the hash table `__table`, based on `__action`. + * + * Returns *non-zero* on success and returns 0 and sets `errno` on failure. + * A pointer to the entry is returned in `*__result`. + * + * Available since API level 28. + */ +int hsearch_r(ENTRY __entry, ACTION __action, ENTRY** __result, struct hsearch_data* __table) __INTRODUCED_IN(28); #endif + +/** + * [lfind(3)](http://man7.org/linux/man-pages/man3/lfind.3.html) brute-force + * searches the unsorted array `__array` (of `__count` items each of size `__size`) + * for `__key`, using `__comparator`. + * + * See bsearch() if you have a sorted array. + * + * Returns a pointer to the matching element on success, or NULL on failure. + * + * Available since API level 21. + */ +void* lfind(const void* __key, const void* __array, size_t* __count, size_t __size, int (*__comparator)(const void*, const void*)) __INTRODUCED_IN(21); + +/** + * [lsearch(3)](http://man7.org/linux/man-pages/man3/lsearch.3.html) brute-force + * searches the unsorted array `__array` (of `__count` items each of size `__size`) + * for `__key`, using `__comparator`. + * + * Unlike lfind(), on failure lsearch() will *insert* `__key` at the end of + * `__array` and increment `*__count`. + * + * Returns a pointer to the matching element on success, or to the newly-added + * element on failure. + * + * Available since API level 21. + */ +void* lsearch(const void* __key, void* __array, size_t* __count, size_t __size, int (*__comparator)(const void*, const void*)) __INTRODUCED_IN(21); + +/** + * [tdelete(3)](http://man7.org/linux/man-pages/man3/tdelete.3.html) searches + * for and removes an element in the tree `*__root_ptr`. The search is performed + * using `__comparator`. + * + * Returns a pointer to the parent of the deleted node, or NULL on failure. + */ +void* tdelete(const void* __key, void** __root_ptr, int (*__comparator)(const void*, const void*)); + +/** + * [tdestroy(3)](http://man7.org/linux/man-pages/man3/tdestroy.3.html) destroys + * the hash table `__root` using `__free_fn` on each node. + */ +void tdestroy(void* __root, void (*__free_fn)(void*)); + +/** + * [tfind(3)](http://man7.org/linux/man-pages/man3/tfind.3.html) searches + * for an element in the tree `*__root_ptr`. The search is performed using + * `__comparator`. + * + * Returns a pointer to the matching node, or NULL on failure. + */ +void* tfind(const void* __key, void* const* __root_ptr, int (*__comparator)(const void*, const void*)); + +/** + * [tsearch(3)](http://man7.org/linux/man-pages/man3/tsearch.3.html) searches + * for an element in the tree `*__root_ptr`. The search is performed using + * `__comparator`. + * + * Unlike tfind(), on failure tsearch() will *insert* `__key` into the tree. + * + * Returns a pointer to the matching node, or to the newly-added node. + */ +void* tsearch(const void* __key, void** __root_ptr, int (*__comparator)(const void*, const void*)); + +/** + * [twalk(3)](http://man7.org/linux/man-pages/man3/twalk.3.html) calls + * `__visitor` on every node in the tree. + */ +void twalk(const void* __root, void (*__visitor)(const void*, VISIT, int)); + +__END_DECLS diff --git a/libc/include/sys/ifunc.h b/libc/include/sys/ifunc.h new file mode 100644 index 000000000..7fbca4a4b --- /dev/null +++ b/libc/include/sys/ifunc.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include <sys/cdefs.h> + +/** + * @file sys/ifunc.h + * @brief Declarations used for ifunc resolvers. Currently only meaningful for arm64. + */ + +__BEGIN_DECLS + +#if defined(__aarch64__) + +/** + * Provides information about hardware capabilities to ifunc resolvers. + * + * Starting with API level 30, ifunc resolvers on arm64 are passed two arguments. The first is a + * uint64_t whose value is equal to getauxval(AT_HWCAP) | _IFUNC_ARG_HWCAP. The second is a pointer + * to a data structure of this type. Prior to API level 30, no arguments are passed to ifunc + * resolvers. Code that wishes to be compatible with prior API levels should not accept any + * arguments in the resolver. + */ +typedef struct __ifunc_arg_t { + /** Set to sizeof(__ifunc_arg_t). */ + unsigned long _size; + + /** Set to getauxval(AT_HWCAP). */ + unsigned long _hwcap; + + /** Set to getauxval(AT_HWCAP2). */ + unsigned long _hwcap2; +} __ifunc_arg_t; + +/** + * If this bit is set in the first argument to an ifunc resolver, indicates that the second argument + * is a pointer to a data structure of type __ifunc_arg_t. This bit is always set on Android + * starting with API level 30. + */ +#define _IFUNC_ARG_HWCAP (1ULL << 62) + +#endif + +__END_DECLS diff --git a/libc/include/sys/xattr.h b/libc/include/sys/xattr.h index d15b3fce9..dc58026eb 100644 --- a/libc/include/sys/xattr.h +++ b/libc/include/sys/xattr.h @@ -26,8 +26,12 @@ * SUCH DAMAGE. */ -#ifndef _SYS_XATTR_H_ -#define _SYS_XATTR_H_ +#pragma once + +/** + * @file sys/xattr.h + * @brief Extended attribute functions. + */ #include <linux/xattr.h> #include <sys/cdefs.h> @@ -35,25 +39,120 @@ __BEGIN_DECLS -int fsetxattr(int __fd, const char* __name, const void* __value, size_t __size, int __flags) - __INTRODUCED_IN(16); -int setxattr(const char* __path, const char* __name, const void* __value, size_t __size, int __flags) - __INTRODUCED_IN(16); -int lsetxattr(const char* __path, const char* __name, const void* __value, size_t __size, int __flags) - __INTRODUCED_IN(16); +/** + * [fsetxattr(2)](http://man7.org/linux/man-pages/man2/fsetxattr.2.html) + * sets an extended attribute on the file referred to by the given file + * descriptor. + * + * Valid flags are `XATTR_CREATE` and `XATTR_REPLACE`. + * + * Returns 0 on success and returns -1 and sets `errno` on failure. + */ +int fsetxattr(int __fd, const char* __name, const void* __value, size_t __size, int __flags); -ssize_t fgetxattr(int __fd, const char* __name, void* __value, size_t __size) __INTRODUCED_IN(16); -ssize_t getxattr(const char* __path, const char* __name, void* __value, size_t __size) __INTRODUCED_IN(16); -ssize_t lgetxattr(const char* __path, const char* __name, void* __value, size_t __size) __INTRODUCED_IN(16); +/** + * [setxattr(2)](http://man7.org/linux/man-pages/man2/setxattr.2.html) + * sets an extended attribute on the file referred to by the given path. + * + * Valid flags are `XATTR_CREATE` and `XATTR_REPLACE`. + * + * Returns 0 on success and returns -1 and sets `errno` on failure. + */ +int setxattr(const char* __path, const char* __name, const void* __value, size_t __size, int __flags); -ssize_t listxattr(const char* __path, char* __list, size_t __size) __INTRODUCED_IN(16); -ssize_t llistxattr(const char* __path, char* __list, size_t __size) __INTRODUCED_IN(16); -ssize_t flistxattr(int __fd, char* __list, size_t __size) __INTRODUCED_IN(16); +/** + * [lsetxattr(2)](http://man7.org/linux/man-pages/man2/lsetxattr.2.html) + * sets an extended attribute on the file referred to by the given path, which + * is the link itself rather than its target in the case of a symbolic link. + * + * Valid flags are `XATTR_CREATE` and `XATTR_REPLACE`. + * + * Returns 0 on success and returns -1 and sets `errno` on failure. + */ +int lsetxattr(const char* __path, const char* __name, const void* __value, size_t __size, int __flags); -int removexattr(const char* __path, const char* __name) __INTRODUCED_IN(16); -int lremovexattr(const char* __path, const char* __name) __INTRODUCED_IN(16); -int fremovexattr(int __fd, const char* __name) __INTRODUCED_IN(16); +/** + * [fgetxattr(2)](http://man7.org/linux/man-pages/man2/fgetxattr.2.html) + * gets an extended attribute on the file referred to by the given file + * descriptor. + * + * Returns the non-negative length of the value on success, or + * returns -1 and sets `errno` on failure. + */ +ssize_t fgetxattr(int __fd, const char* __name, void* __value, size_t __size); -__END_DECLS +/** + * [getxattr(2)](http://man7.org/linux/man-pages/man2/getxattr.2.html) + * gets an extended attribute on the file referred to by the given path. + * + * Returns the non-negative length of the value on success, or + * returns -1 and sets `errno` on failure. + */ +ssize_t getxattr(const char* __path, const char* __name, void* __value, size_t __size); + +/** + * [lgetxattr(2)](http://man7.org/linux/man-pages/man2/lgetxattr.2.html) + * gets an extended attribute on the file referred to by the given path, which + * is the link itself rather than its target in the case of a symbolic link. + * + * Returns the non-negative length of the value on success, or + * returns -1 and sets `errno` on failure. + */ +ssize_t lgetxattr(const char* __path, const char* __name, void* __value, size_t __size); -#endif +/** + * [flistxattr(2)](http://man7.org/linux/man-pages/man2/flistxattr.2.html) + * lists the extended attributes on the file referred to by the given file + * descriptor. + * + * Returns the non-negative length of the list on success, or + * returns -1 and sets `errno` on failure. + */ +ssize_t flistxattr(int __fd, char* __list, size_t __size); + +/** + * [listxattr(2)](http://man7.org/linux/man-pages/man2/listxattr.2.html) + * lists the extended attributes on the file referred to by the given path. + * + * Returns the non-negative length of the list on success, or + * returns -1 and sets `errno` on failure. + */ +ssize_t listxattr(const char* __path, char* __list, size_t __size); + +/** + * [llistxattr(2)](http://man7.org/linux/man-pages/man2/llistxattr.2.html) + * lists the extended attributes on the file referred to by the given path, which + * is the link itself rather than its target in the case of a symbolic link. + * + * Returns the non-negative length of the list on success, or + * returns -1 and sets `errno` on failure. + */ +ssize_t llistxattr(const char* __path, char* __list, size_t __size); + +/** + * [fremovexattr(2)](http://man7.org/linux/man-pages/man2/fremovexattr.2.html) + * removes an extended attribute on the file referred to by the given file + * descriptor. + * + * Returns 0 on success and returns -1 and sets `errno` on failure. + */ +int fremovexattr(int __fd, const char* __name); + +/** + * [lremovexattr(2)](http://man7.org/linux/man-pages/man2/lremovexattr.2.html) + * removes an extended attribute on the file referred to by the given path, which + * is the link itself rather than its target in the case of a symbolic link. + * + * Returns 0 on success and returns -1 and sets `errno` on failure. + */ +int lremovexattr(const char* __path, const char* __name); + +/** + * [removexattr(2)](http://man7.org/linux/man-pages/man2/removexattr.2.html) + * removes an extended attribute on the file referred to by the given path. + * + * Returns 0 on success and returns -1 and sets `errno` on failure. + */ +int removexattr(const char* __path, const char* __name); + +__END_DECLS diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp index ec7e42dda..b1e28b712 100644 --- a/libc/malloc_debug/PointerData.cpp +++ b/libc/malloc_debug/PointerData.cpp @@ -554,7 +554,7 @@ bool PointerData::Exists(const void* ptr) { return pointers_.count(pointer) != 0; } -void PointerData::DumpLiveToFile(FILE* fp) { +void PointerData::DumpLiveToFile(int fd) { std::vector<ListInfoType> list; std::lock_guard<std::mutex> pointer_guard(pointer_mutex_); @@ -566,13 +566,13 @@ void PointerData::DumpLiveToFile(FILE* fp) { total_memory += info.size * info.num_allocations; } - fprintf(fp, "Total memory: %zu\n", total_memory); - fprintf(fp, "Allocation records: %zd\n", list.size()); - fprintf(fp, "Backtrace size: %zu\n", g_debug->config().backtrace_frames()); - fprintf(fp, "\n"); + dprintf(fd, "Total memory: %zu\n", total_memory); + dprintf(fd, "Allocation records: %zd\n", list.size()); + dprintf(fd, "Backtrace size: %zu\n", g_debug->config().backtrace_frames()); + dprintf(fd, "\n"); for (const auto& info : list) { - fprintf(fp, "z %d sz %8zu num %zu bt", (info.zygote_child_alloc) ? 1 : 0, info.size, + dprintf(fd, "z %d sz %8zu num %zu bt", (info.zygote_child_alloc) ? 1 : 0, info.size, info.num_allocations); FrameInfoType* frame_info = info.frame_info; if (frame_info != nullptr) { @@ -580,22 +580,22 @@ void PointerData::DumpLiveToFile(FILE* fp) { if (frame_info->frames[i] == 0) { break; } - fprintf(fp, " %" PRIxPTR, frame_info->frames[i]); + dprintf(fd, " %" PRIxPTR, frame_info->frames[i]); } } - fprintf(fp, "\n"); + dprintf(fd, "\n"); if (info.backtrace_info != nullptr) { - fprintf(fp, " bt_info"); + dprintf(fd, " bt_info"); for (const auto& frame : *info.backtrace_info) { - fprintf(fp, " {"); + dprintf(fd, " {"); if (frame.map_info != nullptr && !frame.map_info->name.empty()) { - fprintf(fp, "\"%s\"", frame.map_info->name.c_str()); + dprintf(fd, "\"%s\"", frame.map_info->name.c_str()); } else { - fprintf(fp, "\"\""); + dprintf(fd, "\"\""); } - fprintf(fp, " %" PRIx64, frame.rel_pc); + dprintf(fd, " %" PRIx64, frame.rel_pc); if (frame.function_name.empty()) { - fprintf(fp, " \"\" 0}"); + dprintf(fd, " \"\" 0}"); } else { char* demangled_name = __cxa_demangle(frame.function_name.c_str(), nullptr, nullptr, nullptr); @@ -605,11 +605,11 @@ void PointerData::DumpLiveToFile(FILE* fp) { } else { name = frame.function_name.c_str(); } - fprintf(fp, " \"%s\" %" PRIx64 "}", name, frame.function_offset); + dprintf(fd, " \"%s\" %" PRIx64 "}", name, frame.function_offset); free(demangled_name); } } - fprintf(fp, "\n"); + dprintf(fd, "\n"); } } } diff --git a/libc/malloc_debug/PointerData.h b/libc/malloc_debug/PointerData.h index c7958f369..78f0ed862 100644 --- a/libc/malloc_debug/PointerData.h +++ b/libc/malloc_debug/PointerData.h @@ -152,7 +152,7 @@ class PointerData : public OptionData { static void GetAllocList(std::vector<ListInfoType>* list); static void LogLeaks(); - static void DumpLiveToFile(FILE* fp); + static void DumpLiveToFile(int fd); static void GetInfo(uint8_t** info, size_t* overall_size, size_t* info_size, size_t* total_memory, size_t* backtrace_size); diff --git a/libc/malloc_debug/exported32.map b/libc/malloc_debug/exported32.map index 8ed37faa2..f75d173df 100644 --- a/libc/malloc_debug/exported32.map +++ b/libc/malloc_debug/exported32.map @@ -8,13 +8,13 @@ LIBC_MALLOC_DEBUG { debug_free_malloc_leak_info; debug_get_malloc_leak_info; debug_initialize; - debug_iterate; debug_mallinfo; debug_malloc; debug_malloc_backtrace; debug_malloc_disable; debug_malloc_enable; debug_malloc_info; + debug_malloc_iterate; debug_malloc_usable_size; debug_mallopt; debug_memalign; diff --git a/libc/malloc_debug/exported64.map b/libc/malloc_debug/exported64.map index cdff88ba1..6dea58c42 100644 --- a/libc/malloc_debug/exported64.map +++ b/libc/malloc_debug/exported64.map @@ -8,13 +8,13 @@ LIBC_MALLOC_DEBUG { debug_free_malloc_leak_info; debug_get_malloc_leak_info; debug_initialize; - debug_iterate; debug_mallinfo; debug_malloc; debug_malloc_backtrace; debug_malloc_disable; debug_malloc_enable; debug_malloc_info; + debug_malloc_iterate; debug_malloc_usable_size; debug_mallopt; debug_memalign; diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp index c030d5429..c0765a983 100644 --- a/libc/malloc_debug/malloc_debug.cpp +++ b/libc/malloc_debug/malloc_debug.cpp @@ -91,8 +91,8 @@ struct mallinfo debug_mallinfo(); int debug_mallopt(int param, int value); int debug_malloc_info(int options, FILE* fp); int debug_posix_memalign(void** memptr, size_t alignment, size_t size); -int debug_iterate(uintptr_t base, size_t size, - void (*callback)(uintptr_t base, size_t size, void* arg), void* arg); +int debug_malloc_iterate(uintptr_t base, size_t size, + void (*callback)(uintptr_t base, size_t size, void* arg), void* arg); void debug_malloc_disable(); void debug_malloc_enable(); @@ -785,16 +785,23 @@ int debug_malloc_info(int options, FILE* fp) { if (DebugCallsDisabled() || !g_debug->TrackPointers()) { return g_dispatch->malloc_info(options, fp); } + + // Make sure any pending output is written to the file. + fflush(fp); + ScopedConcurrentLock lock; ScopedDisableDebugCalls disable; - MallocXmlElem root(fp, "malloc", "version=\"debug-malloc-1\""); + // Avoid any issues where allocations are made that will be freed + // in the fclose. + int fd = fileno(fp); + MallocXmlElem root(fd, "malloc", "version=\"debug-malloc-1\""); std::vector<ListInfoType> list; PointerData::GetAllocList(&list); size_t alloc_num = 0; for (size_t i = 0; i < list.size(); i++) { - MallocXmlElem alloc(fp, "allocation", "nr=\"%zu\"", alloc_num); + MallocXmlElem alloc(fd, "allocation", "nr=\"%zu\"", alloc_num); size_t total = 1; size_t size = list[i].size; @@ -802,8 +809,8 @@ int debug_malloc_info(int options, FILE* fp) { i++; total++; } - MallocXmlElem(fp, "size").Contents("%zu", list[i].size); - MallocXmlElem(fp, "total").Contents("%zu", total); + MallocXmlElem(fd, "size").Contents("%zu", list[i].size); + MallocXmlElem(fd, "total").Contents("%zu", total); alloc_num++; } return 0; @@ -834,7 +841,7 @@ int debug_posix_memalign(void** memptr, size_t alignment, size_t size) { return (*memptr != nullptr) ? 0 : ENOMEM; } -int debug_iterate(uintptr_t base, size_t size, void (*callback)(uintptr_t, size_t, void*), +int debug_malloc_iterate(uintptr_t base, size_t size, void (*callback)(uintptr_t, size_t, void*), void* arg) { ScopedConcurrentLock lock; if (g_debug->TrackPointers()) { @@ -847,7 +854,7 @@ int debug_iterate(uintptr_t base, size_t size, void (*callback)(uintptr_t, size_ // An option that adds a header will add pointer tracking, so no need to // check if headers are enabled. - return g_dispatch->iterate(base, size, callback, arg); + return g_dispatch->malloc_iterate(base, size, callback, arg); } void debug_malloc_disable() { @@ -905,25 +912,28 @@ void* debug_valloc(size_t size) { static std::mutex g_dump_lock; -static void write_dump(FILE* fp) { - fprintf(fp, "Android Native Heap Dump v1.2\n\n"); +static void write_dump(int fd) { + dprintf(fd, "Android Native Heap Dump v1.2\n\n"); std::string fingerprint = android::base::GetProperty("ro.build.fingerprint", "unknown"); - fprintf(fp, "Build fingerprint: '%s'\n\n", fingerprint.c_str()); + dprintf(fd, "Build fingerprint: '%s'\n\n", fingerprint.c_str()); - PointerData::DumpLiveToFile(fp); + PointerData::DumpLiveToFile(fd); - fprintf(fp, "MAPS\n"); + dprintf(fd, "MAPS\n"); std::string content; if (!android::base::ReadFileToString("/proc/self/maps", &content)) { - fprintf(fp, "Could not open /proc/self/maps\n"); + dprintf(fd, "Could not open /proc/self/maps\n"); } else { - fprintf(fp, "%s", content.c_str()); + dprintf(fd, "%s", content.c_str()); } - fprintf(fp, "END\n"); + dprintf(fd, "END\n"); } bool debug_write_malloc_leak_info(FILE* fp) { + // Make sure any pending output is written to the file. + fflush(fp); + ScopedConcurrentLock lock; ScopedDisableDebugCalls disable; @@ -933,7 +943,8 @@ bool debug_write_malloc_leak_info(FILE* fp) { return false; } - write_dump(fp); + write_dump(fileno(fp)); + return true; } @@ -943,13 +954,13 @@ void debug_dump_heap(const char* file_name) { std::lock_guard<std::mutex> guard(g_dump_lock); - FILE* fp = fopen(file_name, "w+e"); - if (fp == nullptr) { + int fd = open(file_name, O_RDWR | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0644); + if (fd == -1) { error_log("Unable to create file: %s", file_name); return; } error_log("Dumping to file: %s\n", file_name); - write_dump(fp); - fclose(fp); + write_dump(fd); + close(fd); } diff --git a/libc/malloc_debug/tests/malloc_debug_system_tests.cpp b/libc/malloc_debug/tests/malloc_debug_system_tests.cpp index 071675875..67bb8d936 100644 --- a/libc/malloc_debug/tests/malloc_debug_system_tests.cpp +++ b/libc/malloc_debug/tests/malloc_debug_system_tests.cpp @@ -37,6 +37,7 @@ #include <time.h> #include <unistd.h> +#include <android-base/file.h> #include <android-base/stringprintf.h> #include <gtest/gtest.h> #include <log/log.h> @@ -174,6 +175,7 @@ static void GetLogStr(pid_t pid, std::string* log_str, log_id log = LOG_ID_MAIN) } static void FindStrings(pid_t pid, std::vector<const char*> match_strings, + std::vector<const char*> no_match_strings = std::vector<const char*>{}, time_t timeout_seconds = kTimeoutSeconds) { std::string log_str; time_t start = time(nullptr); @@ -181,12 +183,18 @@ static void FindStrings(pid_t pid, std::vector<const char*> match_strings, while (true) { GetLogStr(pid, &log_str); found_all = true; + // Look for the expected strings. for (auto str : match_strings) { if (log_str.find(str) == std::string::npos) { found_all = false; break; } } + + // Verify the unexpected strings are not present. + for (auto str : no_match_strings) { + ASSERT_TRUE(log_str.find(str) == std::string::npos) << "Unexpectedly found '" << str << "' in log output:\n" << log_str; + } if (found_all) { return; } @@ -194,7 +202,7 @@ static void FindStrings(pid_t pid, std::vector<const char*> match_strings, break; } } - ASSERT_TRUE(found_all) << "Didn't find expected log output:\n" + log_str; + ASSERT_TRUE(found_all) << "Didn't find expected log output:\n" << log_str; } TEST(MallocTests, DISABLED_smoke) {} @@ -464,3 +472,45 @@ TEST(MallocDebugSystemTest, exit_while_threads_allocating) { << "Found crash in log.\nLog message: " << log_str; } } + +TEST(MallocTests, DISABLED_write_leak_info) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + + FILE* fp = fdopen(tf.fd, "w+"); + if (fp == nullptr) { + printf("Unable to create %s\n", tf.path); + _exit(1); + } + tf.release(); + + void* ptr = malloc(1000); + if (ptr == nullptr) { + printf("malloc failed\n"); + _exit(1); + } + memset(ptr, 0, 1000); + + android_mallopt(M_WRITE_MALLOC_LEAK_INFO_TO_FILE, fp, sizeof(fp)); + + fclose(fp); + + free(ptr); +} + +TEST(MallocDebugSystemTest, write_leak_info_no_header) { + pid_t pid; + ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_write_leak_info", "verbose backtrace", &pid, 0)); + + ASSERT_NO_FATAL_FAILURE(FindStrings(pid, std::vector<const char*>{"malloc debug enabled"}, + + std::vector<const char*>{" HAS INVALID TAG ", "USED AFTER FREE ", "UNKNOWN POINTER "})); +} + +TEST(MallocDebugSystemTest, write_leak_info_header) { + pid_t pid; + ASSERT_NO_FATAL_FAILURE(Exec("MallocTests.DISABLED_write_leak_info", "verbose backtrace guard", &pid, 0)); + + ASSERT_NO_FATAL_FAILURE(FindStrings(pid, std::vector<const char*>{"malloc debug enabled"}, + std::vector<const char*>{" HAS INVALID TAG ", "USED AFTER FREE ", "UNKNOWN POINTER "})); +} diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp index 0238d1049..70457b9ad 100644 --- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp +++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp @@ -27,6 +27,8 @@ #include <algorithm> #include <memory> +#include <string> +#include <string_view> #include <thread> #include <vector> #include <utility> @@ -73,6 +75,9 @@ void* debug_pvalloc(size_t); void* debug_valloc(size_t); #endif +bool debug_write_malloc_leak_info(FILE*); +void debug_dump_heap(const char*); + __END_DECLS constexpr char DIVIDER[] = @@ -1302,6 +1307,10 @@ TEST_F(MallocDebugTest, get_malloc_backtrace_with_header) { } static std::string SanitizeHeapData(const std::string& data) { + if (data.empty()) { + return data; + } + // Remove the map data since it's not consistent. std::string sanitized; bool skip_map_data = false; @@ -1329,7 +1338,7 @@ static std::string SanitizeHeapData(const std::string& data) { sanitized += line + '\n'; } } - return sanitized; + return android::base::Trim(sanitized); } void MallocDebugTest::BacktraceDumpOnSignal(bool trigger_with_alloc) { @@ -1402,9 +1411,7 @@ z 1 sz 100 num 1 bt 100 200 z 1 sz 40 num 1 bt 300 400 MAPS MAP_DATA -END - -)"; +END)"; ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual; ASSERT_STREQ("", getFakeLogBuf().c_str()); @@ -1463,9 +1470,7 @@ z 0 sz 400 num 1 bt a000 b000 z 0 sz 300 num 1 bt 100 200 MAPS MAP_DATA -END - -)"; +END)"; ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual; ASSERT_STREQ("", getFakeLogBuf().c_str()); @@ -1513,9 +1518,7 @@ z 0 sz 400 num 1 bt a000 b000 c000 z 0 sz 300 num 2 bt 100 200 MAPS MAP_DATA -END - -)"; +END)"; ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual; ASSERT_STREQ("", getFakeLogBuf().c_str()); @@ -1575,9 +1578,7 @@ z 0 sz 300 num 1 bt 1100 1200 bt_info {"" 100 "fake1" a} {"" 200 "fake2" 14} MAPS MAP_DATA -END - -)"; +END)"; ASSERT_STREQ(expected.c_str(), sanitized.c_str()) << "Actual data: \n" << actual; ASSERT_STREQ("", getFakeLogBuf().c_str()); @@ -2472,15 +2473,19 @@ TEST_F(MallocDebugTest, abort_on_error_header_tag_corrupted) { TEST_F(MallocDebugTest, malloc_info_no_pointer_tracking) { Init("fill"); - char* buffer; - size_t size; - FILE* memstream = open_memstream(&buffer, &size); - ASSERT_TRUE(memstream != nullptr); - ASSERT_EQ(0, debug_malloc_info(0, memstream)); - ASSERT_EQ(0, fclose(memstream)); + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + FILE* fp = fdopen(tf.fd, "w+"); + tf.release(); + ASSERT_TRUE(fp != nullptr); + ASSERT_EQ(0, debug_malloc_info(0, fp)); + ASSERT_EQ(0, fclose(fp)); + + std::string contents; + ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents)); tinyxml2::XMLDocument doc; - ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(buffer)); + ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str())); auto root = doc.FirstChildElement(); ASSERT_TRUE(root != nullptr); ASSERT_STREQ("malloc", root->Name()); @@ -2501,17 +2506,21 @@ TEST_F(MallocDebugTest, malloc_info_with_pointer_tracking) { std::unique_ptr<void, decltype(debug_free)*> ptr4(debug_malloc(1200), debug_free); ASSERT_TRUE(ptr4.get() != nullptr); - char* buffer; - size_t size; - FILE* memstream = open_memstream(&buffer, &size); - ASSERT_TRUE(memstream != nullptr); - ASSERT_EQ(0, debug_malloc_info(0, memstream)); - ASSERT_EQ(0, fclose(memstream)); + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + FILE* fp = fdopen(tf.fd, "w+"); + tf.release(); + ASSERT_TRUE(fp != nullptr); + ASSERT_EQ(0, debug_malloc_info(0, fp)); + ASSERT_EQ(0, fclose(fp)); - SCOPED_TRACE(testing::Message() << "Output:\n" << buffer); + std::string contents; + ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents)); + + SCOPED_TRACE(testing::Message() << "Output:\n" << contents); tinyxml2::XMLDocument doc; - ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(buffer)); + ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str())); auto root = doc.FirstChildElement(); ASSERT_TRUE(root != nullptr); ASSERT_STREQ("malloc", root->Name()); @@ -2548,3 +2557,134 @@ TEST_F(MallocDebugTest, malloc_info_with_pointer_tracking) { ASSERT_EQ(tinyxml2::XML_SUCCESS, alloc->FirstChildElement("total")->QueryIntText(&val)); ASSERT_EQ(1, val); } + +static void AllocPtrsWithBacktrace(std::vector<void*>* ptrs) { + backtrace_fake_add(std::vector<uintptr_t> {0xf, 0xe, 0xd, 0xc}); + void* ptr = debug_malloc(1024); + ASSERT_TRUE(ptr != nullptr); + memset(ptr, 0, 1024); + ptrs->push_back(ptr); + + backtrace_fake_add(std::vector<uintptr_t> {0xbc000, 0xbc001, 0xbc002}); + ptr = debug_malloc(500); + ASSERT_TRUE(ptr != nullptr); + memset(ptr, 0, 500); + ptrs->push_back(ptr); + + backtrace_fake_add(std::vector<uintptr_t> {0x104}); + ptr = debug_malloc(100); + ASSERT_TRUE(ptr != nullptr); + memset(ptr, 0, 100); + ptrs->push_back(ptr); +} + +static constexpr std::string_view kDumpInfo = R"(Android Native Heap Dump v1.2 + +Build fingerprint: '' + +Total memory: 1624 +Allocation records: 3 +Backtrace size: 16 + +z 0 sz 1024 num 1 bt f e d c +z 0 sz 500 num 1 bt bc000 bc001 bc002 +z 0 sz 100 num 1 bt 104 +MAPS +MAP_DATA +END)"; + +TEST_F(MallocDebugTest, debug_write_malloc_leak_info) { + Init("backtrace=16"); + + std::vector<void*> ptrs; + AllocPtrsWithBacktrace(&ptrs); + + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + close(tf.fd); + tf.release(); + FILE* fp = fopen(tf.path, "w+"); + ASSERT_TRUE(fp != nullptr); + + ASSERT_TRUE(debug_write_malloc_leak_info(fp)); + + fclose(fp); + + for (auto ptr : ptrs) { + debug_free(ptr); + } + ptrs.clear(); + + std::string expected(kDumpInfo); + + std::string contents; + ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents)); + contents = SanitizeHeapData(contents); + ASSERT_EQ(expected, contents); + ASSERT_STREQ("", getFakeLogBuf().c_str()); + ASSERT_STREQ("", getFakeLogPrint().c_str()); +} + +TEST_F(MallocDebugTest, debug_write_malloc_leak_info_extra_data) { + Init("backtrace=16"); + + std::vector<void*> ptrs; + AllocPtrsWithBacktrace(&ptrs); + + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + close(tf.fd); + tf.release(); + FILE* fp = fopen(tf.path, "w+"); + ASSERT_TRUE(fp != nullptr); + + fprintf(fp, "This message should appear before the output.\n"); + ASSERT_TRUE(debug_write_malloc_leak_info(fp)); + fprintf(fp, "This message should appear after the output.\n"); + + fclose(fp); + + for (auto ptr : ptrs) { + debug_free(ptr); + } + ptrs.clear(); + + std::string expected = "This message should appear before the output.\n" + + std::string(kDumpInfo) + + "\nThis message should appear after the output."; + + std::string contents; + ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents)); + contents = SanitizeHeapData(contents); + ASSERT_EQ(expected, contents); + ASSERT_STREQ("", getFakeLogBuf().c_str()); + ASSERT_STREQ("", getFakeLogPrint().c_str()); +} + +TEST_F(MallocDebugTest, dump_heap) { + Init("backtrace=16"); + + std::vector<void*> ptrs; + AllocPtrsWithBacktrace(&ptrs); + + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + close(tf.fd); + tf.release(); + debug_dump_heap(tf.path); + + for (auto ptr : ptrs) { + debug_free(ptr); + } + ptrs.clear(); + + std::string expected(kDumpInfo); + + std::string contents; + ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents)); + contents = SanitizeHeapData(contents); + ASSERT_EQ(expected, contents); + ASSERT_STREQ("", getFakeLogBuf().c_str()); + std::string expected_log = std::string("6 malloc_debug Dumping to file: ") + tf.path + "\n\n"; + ASSERT_EQ(expected_log, getFakeLogPrint()); +} diff --git a/libc/malloc_hooks/exported32.map b/libc/malloc_hooks/exported32.map index 293d9ac15..2b028062b 100644 --- a/libc/malloc_hooks/exported32.map +++ b/libc/malloc_hooks/exported32.map @@ -7,13 +7,13 @@ LIBC_MALLOC_HOOKS { hooks_free_malloc_leak_info; hooks_get_malloc_leak_info; hooks_initialize; - hooks_iterate; hooks_mallinfo; hooks_malloc; hooks_malloc_backtrace; hooks_malloc_disable; hooks_malloc_enable; hooks_malloc_info; + hooks_malloc_iterate; hooks_malloc_usable_size; hooks_mallopt; hooks_memalign; diff --git a/libc/malloc_hooks/exported64.map b/libc/malloc_hooks/exported64.map index 340106b2e..59ec1f01f 100644 --- a/libc/malloc_hooks/exported64.map +++ b/libc/malloc_hooks/exported64.map @@ -7,13 +7,13 @@ LIBC_MALLOC_HOOKS { hooks_free_malloc_leak_info; hooks_get_malloc_leak_info; hooks_initialize; - hooks_iterate; hooks_mallinfo; hooks_malloc; hooks_malloc_backtrace; hooks_malloc_disable; hooks_malloc_enable; hooks_malloc_info; + hooks_malloc_iterate; hooks_malloc_usable_size; hooks_mallopt; hooks_memalign; diff --git a/libc/malloc_hooks/malloc_hooks.cpp b/libc/malloc_hooks/malloc_hooks.cpp index b1c1d5060..1ba869698 100644 --- a/libc/malloc_hooks/malloc_hooks.cpp +++ b/libc/malloc_hooks/malloc_hooks.cpp @@ -67,7 +67,7 @@ void* hooks_calloc(size_t nmemb, size_t bytes); struct mallinfo hooks_mallinfo(); int hooks_mallopt(int param, int value); int hooks_posix_memalign(void** memptr, size_t alignment, size_t size); -int hooks_iterate(uintptr_t base, size_t size, +int hooks_malloc_iterate(uintptr_t base, size_t size, void (*callback)(uintptr_t base, size_t size, void* arg), void* arg); void hooks_malloc_disable(); void hooks_malloc_enable(); @@ -209,7 +209,7 @@ int hooks_posix_memalign(void** memptr, size_t alignment, size_t size) { return g_dispatch->posix_memalign(memptr, alignment, size); } -int hooks_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*) { +int hooks_malloc_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*) { return 0; } diff --git a/libc/platform/bionic/mte_kernel.h b/libc/platform/bionic/mte_kernel.h new file mode 100644 index 000000000..04f2bb6f0 --- /dev/null +++ b/libc/platform/bionic/mte_kernel.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +// Defines constants used as part of the interface in an experimental MTE branch +// of the Linux kernel, which may be found at: +// +// https://github.com/pcc/linux/tree/android-experimental-mte +// +// This interface should not be considered to be stable. + +#ifdef ANDROID_EXPERIMENTAL_MTE +#define HWCAP2_MTE (1UL << 31) +#define PROT_MTE 0x10 +#endif diff --git a/libc/private/MallocXmlElem.h b/libc/private/MallocXmlElem.h index 04d3eeea6..a36797261 100644 --- a/libc/private/MallocXmlElem.h +++ b/libc/private/MallocXmlElem.h @@ -18,38 +18,39 @@ #include <stdarg.h> #include <stdio.h> +#include <unistd.h> #include <private/bionic_macros.h> class MallocXmlElem { public: // Name must be valid throughout lifetime of the object. - explicit MallocXmlElem(FILE* fp, const char* name, - const char* attr_fmt = nullptr, ...) : fp_(fp), name_(name) { - fprintf(fp, "<%s", name_); + explicit MallocXmlElem(int fd, const char* name, + const char* attr_fmt = nullptr, ...) : fd_(fd), name_(name) { + dprintf(fd_, "<%s", name_); if (attr_fmt != nullptr) { va_list args; va_start(args, attr_fmt); - fputc(' ', fp_); - vfprintf(fp_, attr_fmt, args); + write(fd_, " ", 1); + vdprintf(fd_, attr_fmt, args); va_end(args); } - fputc('>', fp_); + write(fd_, ">", 1); } ~MallocXmlElem() noexcept { - fprintf(fp_, "</%s>", name_); + dprintf(fd_, "</%s>", name_); } void Contents(const char* fmt, ...) { va_list args; va_start(args, fmt); - vfprintf(fp_, fmt, args); + vdprintf(fd_, fmt, args); va_end(args); } private: - FILE* fp_; + int fd_; const char* name_; BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(MallocXmlElem); diff --git a/libc/private/ScopedFd.h b/libc/private/ScopedFd.h new file mode 100644 index 000000000..1cec91683 --- /dev/null +++ b/libc/private/ScopedFd.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include <unistd.h> + +#include "private/bionic_macros.h" +#include "private/ErrnoRestorer.h" + +class ScopedFd final { + public: + explicit ScopedFd(int fd) : fd_(fd) { + } + + ScopedFd() : fd_(-1) { + } + + ~ScopedFd() { + reset(-1); + } + + void reset(int fd = -1) { + if (fd_ != -1) { + ErrnoRestorer e; + close(fd_); + } + fd_ = fd; + } + + int get() const { + return fd_; + } + + private: + int fd_; + + BIONIC_DISALLOW_COPY_AND_ASSIGN(ScopedFd); +}; diff --git a/libc/private/bionic_call_ifunc_resolver.h b/libc/private/bionic_call_ifunc_resolver.h new file mode 100644 index 000000000..e0ea35bba --- /dev/null +++ b/libc/private/bionic_call_ifunc_resolver.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include <link.h> +#include <sys/cdefs.h> + +__LIBC_HIDDEN__ ElfW(Addr) __bionic_call_ifunc_resolver(ElfW(Addr) resolver_addr); diff --git a/libc/private/bionic_ifuncs.h b/libc/private/bionic_ifuncs.h index 35961fbdf..f175becb8 100644 --- a/libc/private/bionic_ifuncs.h +++ b/libc/private/bionic_ifuncs.h @@ -28,10 +28,22 @@ #pragma once +#include <stdint.h> +#include <sys/ifunc.h> + +#if defined(__aarch64__) +#define IFUNC_ARGS (uint64_t hwcap __attribute__((unused)), \ + __ifunc_arg_t* arg __attribute__((unused))) +#elif defined(__arm__) +#define IFUNC_ARGS (unsigned long hwcap __attribute__((unused))) +#else +#define IFUNC_ARGS () +#endif + #define DEFINE_IFUNC_FOR(name) \ name##_func name __attribute__((ifunc(#name "_resolver"))); \ __attribute__((visibility("hidden"))) \ - name##_func* name##_resolver() + name##_func* name##_resolver IFUNC_ARGS #define DECLARE_FUNC(type, name) \ __attribute__((visibility("hidden"))) \ diff --git a/libc/private/bionic_malloc_dispatch.h b/libc/private/bionic_malloc_dispatch.h index aea3a1c09..52d857317 100644 --- a/libc/private/bionic_malloc_dispatch.h +++ b/libc/private/bionic_malloc_dispatch.h @@ -70,7 +70,7 @@ struct MallocDispatch { #if defined(HAVE_DEPRECATED_MALLOC_FUNCS) MallocValloc valloc; #endif - MallocIterate iterate; + MallocIterate malloc_iterate; MallocMallocDisable malloc_disable; MallocMallocEnable malloc_enable; MallocMallopt mallopt; diff --git a/libc/upstream-freebsd/android/include/freebsd-compat.h b/libc/upstream-freebsd/android/include/freebsd-compat.h index 6f7a3f09d..b16a68830 100644 --- a/libc/upstream-freebsd/android/include/freebsd-compat.h +++ b/libc/upstream-freebsd/android/include/freebsd-compat.h @@ -14,37 +14,13 @@ * limitations under the License. */ -#ifndef _BIONIC_FREEBSD_COMPAT_H_included -#define _BIONIC_FREEBSD_COMPAT_H_included +#pragma once #define _BSD_SOURCE -#include <sys/cdefs.h> -#include <stddef.h> // For size_t. - #define REPLACE_GETOPT -/* - * FreeBSD's libc has three symbols for every symbol: - * - * __f will be the actual implementation. - * _f will be a weak reference to __f (used for calls to f from within the library). - * f will be a weak reference to __f (used for calls to f from outside the library). - * - * We collapse this into just the one symbol, f. - */ - -/* Prevent weak reference generation. */ -#define __weak_reference(sym,alias) - -/* Ensure that the implementation itself gets the underscore-free name. */ -#define __sleep sleep -#define __usleep usleep - -/* Redirect internal C library calls to the public function. */ -#define _nanosleep nanosleep - /* FreeBSD has this, but we can't really implement it correctly on Linux. */ #define issetugid() 0 -#endif +#define __compiler_membar() __asm __volatile(" " : : : "memory") diff --git a/libc/upstream-freebsd/android/include/machine/atomic.h b/libc/upstream-freebsd/android/include/machine/atomic.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/libc/upstream-freebsd/android/include/machine/atomic.h diff --git a/libc/upstream-freebsd/android/include/namespace.h b/libc/upstream-freebsd/android/include/namespace.h index a3f850ef6..e69de29bb 100644 --- a/libc/upstream-freebsd/android/include/namespace.h +++ b/libc/upstream-freebsd/android/include/namespace.h @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _BIONIC_FREEBSD_NAMESPACE_H_included -#define _BIONIC_FREEBSD_NAMESPACE_H_included - -#endif diff --git a/libc/upstream-freebsd/android/include/un-namespace.h b/libc/upstream-freebsd/android/include/un-namespace.h index a3f850ef6..e69de29bb 100644 --- a/libc/upstream-freebsd/android/include/un-namespace.h +++ b/libc/upstream-freebsd/android/include/un-namespace.h @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _BIONIC_FREEBSD_NAMESPACE_H_included -#define _BIONIC_FREEBSD_NAMESPACE_H_included - -#endif diff --git a/libc/upstream-freebsd/lib/libc/gen/sleep.c b/libc/upstream-freebsd/lib/libc/gen/sleep.c deleted file mode 100644 index b807c2d1d..000000000 --- a/libc/upstream-freebsd/lib/libc/gen/sleep.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)sleep.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "namespace.h" -#include <errno.h> -#include <limits.h> -#include <time.h> -#include <unistd.h> -#include "un-namespace.h" - -unsigned int -__sleep(unsigned int seconds) -{ - struct timespec time_to_sleep; - struct timespec time_remaining; - - /* - * Avoid overflow when `seconds' is huge. This assumes that - * the maximum value for a time_t is >= INT_MAX. - */ - if (seconds > INT_MAX) - return (seconds - INT_MAX + __sleep(INT_MAX)); - - time_to_sleep.tv_sec = seconds; - time_to_sleep.tv_nsec = 0; - if (_nanosleep(&time_to_sleep, &time_remaining) != -1) - return (0); - if (errno != EINTR) - return (seconds); /* best guess */ - return (time_remaining.tv_sec + - (time_remaining.tv_nsec != 0)); /* round up */ -} - -__weak_reference(__sleep, sleep); -__weak_reference(__sleep, _sleep); diff --git a/libc/upstream-freebsd/lib/libc/stdlib/getopt_long.c b/libc/upstream-freebsd/lib/libc/stdlib/getopt_long.c index 9534a2aff..6a3067c42 100644 --- a/libc/upstream-freebsd/lib/libc/stdlib/getopt_long.c +++ b/libc/upstream-freebsd/lib/libc/stdlib/getopt_long.c @@ -55,7 +55,7 @@ static char *rcsid = "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert #endif /* LIBC_SCCS and not lint */ #endif #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/getopt_long.c 342757 2019-01-04 03:13:24Z kevans $"); #include <err.h> #include <errno.h> @@ -481,6 +481,8 @@ start: #endif if (*place == '-') { place++; /* --foo long option */ + if (*place == '\0') + return (BADARG); /* malformed option */ #ifdef GNU_COMPATIBLE dash_prefix = DD_PREFIX; #endif diff --git a/libc/upstream-freebsd/lib/libc/stdlib/hcreate.c b/libc/upstream-freebsd/lib/libc/stdlib/hcreate.c index d512857dd..b175d3401 100644 --- a/libc/upstream-freebsd/lib/libc/stdlib/hcreate.c +++ b/libc/upstream-freebsd/lib/libc/stdlib/hcreate.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2015 Nuxi, https://nuxi.nl/ * * Redistribution and use in source and binary forms, with or without @@ -24,7 +26,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/lib/libc/stdlib/hcreate.c 292767 2015-12-27 07:50:11Z ed $"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/hcreate.c 326193 2017-11-25 17:12:48Z pfg $"); #include <search.h> #include <stdbool.h> diff --git a/libc/upstream-freebsd/lib/libc/stdlib/qsort.c b/libc/upstream-freebsd/lib/libc/stdlib/qsort.c index 1ccc518d3..e0db4f376 100644 --- a/libc/upstream-freebsd/lib/libc/stdlib/qsort.c +++ b/libc/upstream-freebsd/lib/libc/stdlib/qsort.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -31,7 +33,7 @@ static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/stdlib/qsort.c 334928 2018-06-10 17:54:44Z kib $"); #include <stdlib.h> @@ -41,53 +43,27 @@ typedef int cmp_t(void *, const void *, const void *); typedef int cmp_t(const void *, const void *); #endif static inline char *med3(char *, char *, char *, cmp_t *, void *); -static inline void swapfunc(char *, char *, size_t, int, int); #define MIN(a, b) ((a) < (b) ? a : b) /* * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". */ -#define swapcode(TYPE, parmi, parmj, n) { \ - size_t i = (n) / sizeof (TYPE); \ - TYPE *pi = (TYPE *) (parmi); \ - TYPE *pj = (TYPE *) (parmj); \ - do { \ - TYPE t = *pi; \ - *pi++ = *pj; \ - *pj++ = t; \ - } while (--i > 0); \ -} - -#define SWAPINIT(TYPE, a, es) swaptype_ ## TYPE = \ - ((char *)a - (char *)0) % sizeof(TYPE) || \ - es % sizeof(TYPE) ? 2 : es == sizeof(TYPE) ? 0 : 1; static inline void -swapfunc(char *a, char *b, size_t n, int swaptype_long, int swaptype_int) +swapfunc(char *a, char *b, size_t es) { - if (swaptype_long <= 1) - swapcode(long, a, b, n) - else if (swaptype_int <= 1) - swapcode(int, a, b, n) - else - swapcode(char, a, b, n) -} + char t; -#define swap(a, b) \ - if (swaptype_long == 0) { \ - long t = *(long *)(a); \ - *(long *)(a) = *(long *)(b); \ - *(long *)(b) = t; \ - } else if (swaptype_int == 0) { \ - int t = *(int *)(a); \ - *(int *)(a) = *(int *)(b); \ - *(int *)(b) = t; \ - } else \ - swapfunc(a, b, es, swaptype_long, swaptype_int) + do { + t = *a; + *a++ = *b; + *b++ = t; + } while (--es > 0); +} #define vecswap(a, b, n) \ - if ((n) > 0) swapfunc(a, b, n, swaptype_long, swaptype_int) + if ((n) > 0) swapfunc(a, b, n) #ifdef I_AM_QSORT_R #define CMP(t, x, y) (cmp((t), (x), (y))) @@ -119,17 +95,16 @@ qsort(void *a, size_t n, size_t es, cmp_t *cmp) char *pa, *pb, *pc, *pd, *pl, *pm, *pn; size_t d1, d2; int cmp_result; - int swaptype_long, swaptype_int, swap_cnt; + int swap_cnt; -loop: SWAPINIT(long, a, es); - SWAPINIT(int, a, es); +loop: swap_cnt = 0; if (n < 7) { for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) for (pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0; pl -= es) - swap(pl, pl - es); + swapfunc(pl, pl - es, es); return; } pm = (char *)a + (n / 2) * es; @@ -145,7 +120,7 @@ loop: SWAPINIT(long, a, es); } pm = med3(pl, pm, pn, cmp, thunk); } - swap(a, pm); + swapfunc(a, pm, es); pa = pb = (char *)a + es; pc = pd = (char *)a + (n - 1) * es; @@ -153,7 +128,7 @@ loop: SWAPINIT(long, a, es); while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) { if (cmp_result == 0) { swap_cnt = 1; - swap(pa, pb); + swapfunc(pa, pb, es); pa += es; } pb += es; @@ -161,14 +136,14 @@ loop: SWAPINIT(long, a, es); while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) { if (cmp_result == 0) { swap_cnt = 1; - swap(pc, pd); + swapfunc(pc, pd, es); pd -= es; } pc -= es; } if (pb > pc) break; - swap(pb, pc); + swapfunc(pb, pc, es); swap_cnt = 1; pb += es; pc -= es; @@ -178,7 +153,7 @@ loop: SWAPINIT(long, a, es); for (pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0; pl -= es) - swap(pl, pl - es); + swapfunc(pl, pl - es, es); return; } diff --git a/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c b/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c index ef8cdb1b4..9e4e79ddd 100644 --- a/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c +++ b/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2011 David Chisnall * All rights reserved. * @@ -23,9 +25,11 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: head/lib/libc/stdlib/quick_exit.c 326193 2017-11-25 17:12:48Z pfg $ */ +#include <sys/types.h> +#include <machine/atomic.h> #include <stdlib.h> #include <pthread.h> @@ -60,6 +64,7 @@ at_quick_exit(void (*func)(void)) h->cleanup = func; pthread_mutex_lock(&atexit_mutex); h->next = handlers; + __compiler_membar(); handlers = h; pthread_mutex_unlock(&atexit_mutex); return (0); @@ -74,7 +79,9 @@ quick_exit(int status) * XXX: The C++ spec requires us to call std::terminate if there is an * exception here. */ - for (h = handlers; NULL != h; h = h->next) + for (h = handlers; NULL != h; h = h->next) { + __compiler_membar(); h->cleanup(); + } _Exit(status); } diff --git a/libc/upstream-freebsd/lib/libc/string/wcpcpy.c b/libc/upstream-freebsd/lib/libc/string/wcpcpy.c index df63d72a0..e040dbaa7 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcpcpy.c +++ b/libc/upstream-freebsd/lib/libc/string/wcpcpy.c @@ -1,4 +1,6 @@ -/* +/*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999 * David E. O'Brien * Copyright (c) 1988, 1993 @@ -33,7 +35,7 @@ static char sccsid[] = "@(#)strcpy.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcpcpy.c 326025 2017-11-20 19:49:47Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcpncpy.c b/libc/upstream-freebsd/lib/libc/string/wcpncpy.c index 87b361c97..8bf6e8789 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcpncpy.c +++ b/libc/upstream-freebsd/lib/libc/string/wcpncpy.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2009 David Schultz <das@FreeBSD.org> * All rights reserved. * @@ -25,7 +27,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcpncpy.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcscasecmp.c b/libc/upstream-freebsd/lib/libc/string/wcscasecmp.c index 014354327..5bd468df2 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcscasecmp.c +++ b/libc/upstream-freebsd/lib/libc/string/wcscasecmp.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2009 David Schultz <das@FreeBSD.org> * All rights reserved. * @@ -25,7 +27,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcscasecmp.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> #include <wctype.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcscat.c b/libc/upstream-freebsd/lib/libc/string/wcscat.c index 7ae4e8011..792f61e9a 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcscat.c +++ b/libc/upstream-freebsd/lib/libc/string/wcscat.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c)1999 Citrus Project, * All rights reserved. * @@ -32,7 +34,7 @@ __RCSID("$NetBSD: wcscat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcscat.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcschr.c b/libc/upstream-freebsd/lib/libc/string/wcschr.c index 1df1fe6cd..ca740c032 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcschr.c +++ b/libc/upstream-freebsd/lib/libc/string/wcschr.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * @@ -25,7 +27,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcschr.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcscmp.c b/libc/upstream-freebsd/lib/libc/string/wcscmp.c index c2abe4c79..db0189281 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcscmp.c +++ b/libc/upstream-freebsd/lib/libc/string/wcscmp.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * @@ -37,7 +39,7 @@ static char sccsid[] = "@(#)strcmp.c 8.1 (Berkeley) 6/4/93"; __RCSID("$NetBSD: wcscmp.c,v 1.3 2001/01/05 12:13:12 itojun Exp $"); #endif #endif /* LIBC_SCCS and not lint */ -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcscmp.c 326025 2017-11-20 19:49:47Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcscpy.c b/libc/upstream-freebsd/lib/libc/string/wcscpy.c index 0c6e1f28f..a639e74f5 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcscpy.c +++ b/libc/upstream-freebsd/lib/libc/string/wcscpy.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c)1999 Citrus Project, * All rights reserved. * @@ -32,7 +34,7 @@ __RCSID("$NetBSD: wcscpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcscpy.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcscspn.c b/libc/upstream-freebsd/lib/libc/string/wcscspn.c index 7729dc8ab..8a7682f99 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcscspn.c +++ b/libc/upstream-freebsd/lib/libc/string/wcscspn.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c)1999 Citrus Project, * All rights reserved. * @@ -32,7 +34,7 @@ __RCSID("$NetBSD: wcscspn.c,v 1.1 2000/12/23 23:14:36 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcscspn.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcsdup.c b/libc/upstream-freebsd/lib/libc/string/wcsdup.c index 1e5db9258..b97f7666b 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcsdup.c +++ b/libc/upstream-freebsd/lib/libc/string/wcsdup.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2005 Tim J. Robbins. * All rights reserved. * @@ -25,7 +27,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcsdup.c 326193 2017-11-25 17:12:48Z pfg $"); #include <stdlib.h> #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcslcat.c b/libc/upstream-freebsd/lib/libc/string/wcslcat.c index f5f1e1ee7..9706fa639 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcslcat.c +++ b/libc/upstream-freebsd/lib/libc/string/wcslcat.c @@ -1,4 +1,6 @@ -/* +/*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> * All rights reserved. * @@ -33,7 +35,7 @@ __RCSID("$NetBSD: wcslcat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcslcat.c 326193 2017-11-25 17:12:48Z pfg $"); #include <sys/types.h> #include <wchar.h> @@ -54,7 +56,7 @@ wcslcat(wchar_t *dst, const wchar_t *src, size_t siz) size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ - while (*d != '\0' && n-- != 0) + while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; diff --git a/libc/upstream-freebsd/lib/libc/string/wcslen.c b/libc/upstream-freebsd/lib/libc/string/wcslen.c index ca3004e03..c5968251c 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcslen.c +++ b/libc/upstream-freebsd/lib/libc/string/wcslen.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c)1999 Citrus Project, * All rights reserved. * @@ -32,7 +34,7 @@ __RCSID("$NetBSD: wcslen.c,v 1.1 2000/12/23 23:14:36 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcslen.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcsncasecmp.c b/libc/upstream-freebsd/lib/libc/string/wcsncasecmp.c index a42d98c92..a96344432 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcsncasecmp.c +++ b/libc/upstream-freebsd/lib/libc/string/wcsncasecmp.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2009 David Schultz <das@FreeBSD.org> * All rights reserved. * @@ -25,7 +27,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcsncasecmp.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> #include <wctype.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcsncat.c b/libc/upstream-freebsd/lib/libc/string/wcsncat.c index 44f1ff989..0214af40d 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcsncat.c +++ b/libc/upstream-freebsd/lib/libc/string/wcsncat.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c)1999 Citrus Project, * All rights reserved. * @@ -32,7 +34,7 @@ __RCSID("$NetBSD: wcsncat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcsncat.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> @@ -48,7 +50,7 @@ wcsncat(wchar_t * __restrict s1, const wchar_t * __restrict s2, size_t n) p++; q = p; r = s2; - while (*r && n) { + while (n && *r) { *q++ = *r++; n--; } diff --git a/libc/upstream-freebsd/lib/libc/string/wcsncmp.c b/libc/upstream-freebsd/lib/libc/string/wcsncmp.c index 8236d969f..77b709cdd 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcsncmp.c +++ b/libc/upstream-freebsd/lib/libc/string/wcsncmp.c @@ -1,4 +1,6 @@ -/* +/*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * @@ -34,7 +36,7 @@ static char sccsid[] = "@(#)strncmp.c 8.1 (Berkeley) 6/4/93"; __RCSID("$NetBSD: wcsncmp.c,v 1.3 2001/01/05 12:13:13 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcsncmp.c 326025 2017-11-20 19:49:47Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcsncpy.c b/libc/upstream-freebsd/lib/libc/string/wcsncpy.c index 215e9a115..4075ecc59 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcsncpy.c +++ b/libc/upstream-freebsd/lib/libc/string/wcsncpy.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * @@ -36,7 +38,7 @@ static char sccsid[] = "@(#)strncpy.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #endif #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcsncpy.c 326025 2017-11-20 19:49:47Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcsnlen.c b/libc/upstream-freebsd/lib/libc/string/wcsnlen.c index f03cf76c0..271d34147 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcsnlen.c +++ b/libc/upstream-freebsd/lib/libc/string/wcsnlen.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2009 David Schultz <das@FreeBSD.org> * All rights reserved. * @@ -25,7 +27,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcsnlen.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcspbrk.c b/libc/upstream-freebsd/lib/libc/string/wcspbrk.c index 2ff71ba92..63efb0150 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcspbrk.c +++ b/libc/upstream-freebsd/lib/libc/string/wcspbrk.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c)1999 Citrus Project, * All rights reserved. * @@ -32,7 +34,7 @@ __RCSID("$NetBSD: wcspbrk.c,v 1.1 2000/12/23 23:14:37 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcspbrk.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcsrchr.c b/libc/upstream-freebsd/lib/libc/string/wcsrchr.c index 37c81ec8c..97665ca03 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcsrchr.c +++ b/libc/upstream-freebsd/lib/libc/string/wcsrchr.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * @@ -25,7 +27,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcsrchr.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcsspn.c b/libc/upstream-freebsd/lib/libc/string/wcsspn.c index 656920620..b08a39e76 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcsspn.c +++ b/libc/upstream-freebsd/lib/libc/string/wcsspn.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c)1999 Citrus Project, * All rights reserved. * @@ -32,7 +34,7 @@ __RCSID("$NetBSD: wcsspn.c,v 1.1 2000/12/23 23:14:37 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcsspn.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcsstr.c b/libc/upstream-freebsd/lib/libc/string/wcsstr.c index ce598a698..430902533 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcsstr.c +++ b/libc/upstream-freebsd/lib/libc/string/wcsstr.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * @@ -36,7 +38,7 @@ static char sccsid[] = "@(#)strstr.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #endif #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcsstr.c 326025 2017-11-20 19:49:47Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wcstok.c b/libc/upstream-freebsd/lib/libc/string/wcstok.c index 441fbd444..8d62bf792 100644 --- a/libc/upstream-freebsd/lib/libc/string/wcstok.c +++ b/libc/upstream-freebsd/lib/libc/string/wcstok.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1998 Softweyr LLC. All rights reserved. * * strtok_r, from Berkeley strtok @@ -33,7 +35,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wcstok.c 326025 2017-11-20 19:49:47Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wmemchr.c b/libc/upstream-freebsd/lib/libc/string/wmemchr.c index cab89c9ad..412a276dc 100644 --- a/libc/upstream-freebsd/lib/libc/string/wmemchr.c +++ b/libc/upstream-freebsd/lib/libc/string/wmemchr.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c)1999 Citrus Project, * All rights reserved. * @@ -32,7 +34,7 @@ __RCSID("$NetBSD: wmemchr.c,v 1.1 2000/12/23 23:14:37 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wmemchr.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wmemcmp.c b/libc/upstream-freebsd/lib/libc/string/wmemcmp.c index fdb1f986f..c1e9f3c2f 100644 --- a/libc/upstream-freebsd/lib/libc/string/wmemcmp.c +++ b/libc/upstream-freebsd/lib/libc/string/wmemcmp.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c)1999 Citrus Project, * All rights reserved. * @@ -32,7 +34,7 @@ __RCSID("$NetBSD: wmemcmp.c,v 1.1 2000/12/23 23:14:37 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wmemcmp.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wmemcpy.c b/libc/upstream-freebsd/lib/libc/string/wmemcpy.c index c10770ce4..e0d6c040d 100644 --- a/libc/upstream-freebsd/lib/libc/string/wmemcpy.c +++ b/libc/upstream-freebsd/lib/libc/string/wmemcpy.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c)1999 Citrus Project, * All rights reserved. * @@ -32,7 +34,7 @@ __RCSID("$NetBSD: wmemcpy.c,v 1.1 2000/12/23 23:14:37 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wmemcpy.c 326193 2017-11-25 17:12:48Z pfg $"); #include <string.h> #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wmemmove.c b/libc/upstream-freebsd/lib/libc/string/wmemmove.c index 05cfd1082..b84c2c095 100644 --- a/libc/upstream-freebsd/lib/libc/string/wmemmove.c +++ b/libc/upstream-freebsd/lib/libc/string/wmemmove.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c)1999 Citrus Project, * All rights reserved. * @@ -32,7 +34,7 @@ __RCSID("$NetBSD: wmemmove.c,v 1.1 2000/12/23 23:14:37 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wmemmove.c 326193 2017-11-25 17:12:48Z pfg $"); #include <string.h> #include <wchar.h> diff --git a/libc/upstream-freebsd/lib/libc/string/wmemset.c b/libc/upstream-freebsd/lib/libc/string/wmemset.c index 0e96356ec..d4d630865 100644 --- a/libc/upstream-freebsd/lib/libc/string/wmemset.c +++ b/libc/upstream-freebsd/lib/libc/string/wmemset.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c)1999 Citrus Project, * All rights reserved. * @@ -32,7 +34,7 @@ __RCSID("$NetBSD: wmemset.c,v 1.1 2000/12/23 23:14:37 itojun Exp $"); #endif /* LIBC_SCCS and not lint */ #endif -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/libc/string/wmemset.c 326193 2017-11-25 17:12:48Z pfg $"); #include <wchar.h> diff --git a/libc/upstream-netbsd/android/include/env.h b/libc/upstream-netbsd/android/include/env.h index 8f99f9d54..e69de29bb 100644 --- a/libc/upstream-netbsd/android/include/env.h +++ b/libc/upstream-netbsd/android/include/env.h @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _BIONIC_NETBSD_ENV_H_included -#define _BIONIC_NETBSD_ENV_H_included - -/* Placeholder. */ - -#endif diff --git a/libc/upstream-netbsd/android/include/extern.h b/libc/upstream-netbsd/android/include/extern.h index 616becdc9..b8e6151a2 100644 --- a/libc/upstream-netbsd/android/include/extern.h +++ b/libc/upstream-netbsd/android/include/extern.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef _BIONIC_NETBSD_EXTERN_H_included -#define _BIONIC_NETBSD_EXTERN_H_included +#pragma once #include <sys/cdefs.h> @@ -24,5 +23,3 @@ __BEGIN_DECLS const char* __strsignal(int, char*, size_t); __END_DECLS - -#endif diff --git a/libc/upstream-netbsd/android/include/namespace.h b/libc/upstream-netbsd/android/include/namespace.h index 630ea9b06..ae7585cd0 100644 --- a/libc/upstream-netbsd/android/include/namespace.h +++ b/libc/upstream-netbsd/android/include/namespace.h @@ -14,10 +14,7 @@ * limitations under the License. */ -#ifndef _BIONIC_NETBSD_NAMESPACE_H_included -#define _BIONIC_NETBSD_NAMESPACE_H_included +#pragma once __LIBC_HIDDEN__ int __res_enable_mt(void); __LIBC_HIDDEN__ int __res_disable_mt(void); - -#endif diff --git a/libc/upstream-netbsd/android/include/netbsd-compat.h b/libc/upstream-netbsd/android/include/netbsd-compat.h index af5ae2927..ea630b273 100644 --- a/libc/upstream-netbsd/android/include/netbsd-compat.h +++ b/libc/upstream-netbsd/android/include/netbsd-compat.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef _BIONIC_NETBSD_COMPAT_H_included -#define _BIONIC_NETBSD_COMPAT_H_included +#pragma once #define _BSD_SOURCE #define _GNU_SOURCE @@ -47,5 +46,3 @@ int reallocarr(void*, size_t, size_t); /* Use appropriate shell depending on process's executable. */ __LIBC_HIDDEN__ extern const char* __bionic_get_shell_path(); #define _PATH_BSHELL __bionic_get_shell_path() - -#endif diff --git a/libc/upstream-netbsd/android/include/port_after.h b/libc/upstream-netbsd/android/include/port_after.h index 3f8b6f801..e69de29bb 100644 --- a/libc/upstream-netbsd/android/include/port_after.h +++ b/libc/upstream-netbsd/android/include/port_after.h @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _BIONIC_NETBSD_PORT_BEFORE_H_included -#define _BIONIC_NETBSD_PORT_BEFORE_H_included - -#endif diff --git a/libc/upstream-netbsd/android/include/port_before.h b/libc/upstream-netbsd/android/include/port_before.h index 9fa948744..8266f810c 100644 --- a/libc/upstream-netbsd/android/include/port_before.h +++ b/libc/upstream-netbsd/android/include/port_before.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef _BIONIC_NETBSD_PORT_BEFORE_H_included -#define _BIONIC_NETBSD_PORT_BEFORE_H_included +#pragma once #include "namespace.h" #include <sys/cdefs.h> @@ -24,5 +23,3 @@ #define ISC_FORMAT_PRINTF(a,b) __printflike(a,b) #define ISC_SOCKLEN_T socklen_t - -#endif diff --git a/libc/upstream-openbsd/android/include/arith.h b/libc/upstream-openbsd/android/include/arith.h index cb116d479..554aa855b 100644 --- a/libc/upstream-openbsd/android/include/arith.h +++ b/libc/upstream-openbsd/android/include/arith.h @@ -14,6 +14,8 @@ * limitations under the License. */ +#pragma once + #define IEEE_8087 #if defined(__LP64__) diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h index 2c8c7359f..afd10770f 100644 --- a/libc/upstream-openbsd/android/include/openbsd-compat.h +++ b/libc/upstream-openbsd/android/include/openbsd-compat.h @@ -14,34 +14,20 @@ * limitations under the License. */ -#ifndef _BIONIC_OPENBSD_COMPAT_H_included -#define _BIONIC_OPENBSD_COMPAT_H_included +#pragma once #define _BSD_SOURCE #include <sys/cdefs.h> #include <stddef.h> // For size_t. -// TODO: libandroid_support uses this file, so we need to wait for -// <sys/random.h> to be in the NDK headers before we can lose this declaration. -//#include <sys/random.h> // For getentropy. -int getentropy(void*, size_t); +#include <sys/random.h> // For getentropy. #define __BEGIN_HIDDEN_DECLS _Pragma("GCC visibility push(hidden)") #define __END_HIDDEN_DECLS _Pragma("GCC visibility pop") extern const char* __progname; -/* Redirect internal C library calls to the public function. */ -#define _err err -#define _errx errx -#define _verr verr -#define _verrx verrx -#define _vwarn vwarn -#define _vwarnx vwarnx -#define _warn warn -#define _warnx warnx - /* Ignore all DEF_STRONG/DEF_WEAK in OpenBSD. */ #define DEF_STRONG(sym) #define DEF_WEAK(sym) @@ -82,5 +68,3 @@ __LIBC_HIDDEN__ extern const char* __bionic_get_shell_path(); __LIBC_HIDDEN__ extern char* __findenv(const char*, int, int*); __LIBC_HIDDEN__ extern char* _mktemp(char*); - -#endif diff --git a/libc/upstream-freebsd/lib/libc/gen/usleep.c b/libc/upstream-openbsd/lib/libc/string/strlen.c index 7d6559be2..a5721d3e7 100644 --- a/libc/upstream-freebsd/lib/libc/gen/usleep.c +++ b/libc/upstream-openbsd/lib/libc/string/strlen.c @@ -1,5 +1,7 @@ -/* - * Copyright (c) 1989, 1993 +/* $OpenBSD: strlen.c,v 1.9 2015/08/31 02:53:57 guenther Exp $ */ + +/*- + * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,7 +12,7 @@ * 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. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -27,26 +29,16 @@ * SUCH DAMAGE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)usleep.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "namespace.h" -#include <time.h> -#include <unistd.h> -#include "un-namespace.h" +#include <string.h> -int -__usleep(useconds_t useconds) +size_t +strlen(const char *str) { - struct timespec time_to_sleep; + const char *s; - time_to_sleep.tv_nsec = (useconds % 1000000) * 1000; - time_to_sleep.tv_sec = useconds / 1000000; - return (_nanosleep(&time_to_sleep, NULL)); + for (s = str; *s; ++s) + ; + return (s - str); } -__weak_reference(__usleep, usleep); -__weak_reference(__usleep, _usleep); +DEF_STRONG(strlen); diff --git a/libm/upstream-freebsd/lib/msun/src/e_exp.c b/libm/upstream-freebsd/lib/msun/src/e_exp.c index 94c9769da..dd88d3e91 100644 --- a/libm/upstream-freebsd/lib/msun/src/e_exp.c +++ b/libm/upstream-freebsd/lib/msun/src/e_exp.c @@ -11,7 +11,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/msun/src/e_exp.c 352710 2019-09-25 18:50:57Z dim $"); /* __ieee754_exp(x) * Returns the exponential of x. @@ -145,9 +145,9 @@ __ieee754_exp(double x) /* default IEEE double exp */ /* x is now in primary range */ t = x*x; if(k >= -1021) - INSERT_WORDS(twopk,0x3ff00000+(k<<20), 0); + INSERT_WORDS(twopk,((u_int32_t)(0x3ff+k))<<20, 0); else - INSERT_WORDS(twopk,0x3ff00000+((k+1000)<<20), 0); + INSERT_WORDS(twopk,((u_int32_t)(0x3ff+(k+1000)))<<20, 0); c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); if(k==0) return one-((x*c)/(c-2.0)-x); else y = one-((lo-(x*c)/(2.0-c))-hi); diff --git a/libm/upstream-freebsd/lib/msun/src/e_expf.c b/libm/upstream-freebsd/lib/msun/src/e_expf.c index b1fe2c537..aaf6d5f6c 100644 --- a/libm/upstream-freebsd/lib/msun/src/e_expf.c +++ b/libm/upstream-freebsd/lib/msun/src/e_expf.c @@ -14,7 +14,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/msun/src/e_expf.c 352710 2019-09-25 18:50:57Z dim $"); #include <float.h> @@ -83,9 +83,9 @@ __ieee754_expf(float x) /* x is now in primary range */ t = x*x; if(k >= -125) - SET_FLOAT_WORD(twopk,0x3f800000+(k<<23)); + SET_FLOAT_WORD(twopk,((u_int32_t)(0x7f+k))<<23); else - SET_FLOAT_WORD(twopk,0x3f800000+((k+100)<<23)); + SET_FLOAT_WORD(twopk,((u_int32_t)(0x7f+(k+100)))<<23); c = x - t*(P1+t*P2); if(k==0) return one-((x*c)/(c-(float)2.0)-x); else y = one-((lo-(x*c)/((float)2.0-c))-hi); diff --git a/libm/upstream-freebsd/lib/msun/src/e_j0.c b/libm/upstream-freebsd/lib/msun/src/e_j0.c index 6bca542fb..a008b42c0 100644 --- a/libm/upstream-freebsd/lib/msun/src/e_j0.c +++ b/libm/upstream-freebsd/lib/msun/src/e_j0.c @@ -11,7 +11,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/lib/msun/src/e_j0.c 343023 2019-01-14 15:48:35Z pfg $"); +__FBSDID("$FreeBSD: head/lib/msun/src/e_j0.c 343953 2019-02-10 08:46:07Z peterj $"); /* __ieee754_j0(x), __ieee754_y0(x) * Bessel function of the first and second kinds of order zero. @@ -93,8 +93,7 @@ __ieee754_j0(double x) if(ix>=0x7ff00000) return one/(x*x); x = fabs(x); if(ix >= 0x40000000) { /* |x| >= 2.0 */ - s = sin(x); - c = cos(x); + sincos(x, &s, &c); ss = s-c; cc = s+c; if(ix<0x7fe00000) { /* Make sure x+x does not overflow. */ @@ -173,8 +172,7 @@ __ieee754_y0(double x) * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one. */ - s = sin(x); - c = cos(x); + sincos(x, &s, &c); ss = s-c; cc = s+c; /* diff --git a/libm/upstream-freebsd/lib/msun/src/e_j0f.c b/libm/upstream-freebsd/lib/msun/src/e_j0f.c index 714caac1d..495a5e54b 100644 --- a/libm/upstream-freebsd/lib/msun/src/e_j0f.c +++ b/libm/upstream-freebsd/lib/msun/src/e_j0f.c @@ -14,7 +14,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/lib/msun/src/e_j0f.c 343023 2019-01-14 15:48:35Z pfg $"); +__FBSDID("$FreeBSD: head/lib/msun/src/e_j0f.c 343953 2019-02-10 08:46:07Z peterj $"); /* * See e_j0.c for complete comments. @@ -55,8 +55,7 @@ __ieee754_j0f(float x) if(ix>=0x7f800000) return one/(x*x); x = fabsf(x); if(ix >= 0x40000000) { /* |x| >= 2.0 */ - s = sinf(x); - c = cosf(x); + sincosf(x, &s, &c); ss = s-c; cc = s+c; if(ix<0x7f000000) { /* Make sure x+x does not overflow. */ @@ -128,8 +127,7 @@ __ieee754_y0f(float x) * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) * to compute the worse one. */ - s = sinf(x); - c = cosf(x); + sincosf(x, &s, &c); ss = s-c; cc = s+c; /* diff --git a/libm/upstream-freebsd/lib/msun/src/e_j1.c b/libm/upstream-freebsd/lib/msun/src/e_j1.c index 78bb3292b..6d1c41c5b 100644 --- a/libm/upstream-freebsd/lib/msun/src/e_j1.c +++ b/libm/upstream-freebsd/lib/msun/src/e_j1.c @@ -11,7 +11,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/lib/msun/src/e_j1.c 336089 2018-07-08 16:26:13Z markj $"); +__FBSDID("$FreeBSD: head/lib/msun/src/e_j1.c 343953 2019-02-10 08:46:07Z peterj $"); /* __ieee754_j1(x), __ieee754_y1(x) * Bessel function of the first and second kinds of order zero. @@ -94,8 +94,7 @@ __ieee754_j1(double x) if(ix>=0x7ff00000) return one/x; y = fabs(x); if(ix >= 0x40000000) { /* |x| >= 2.0 */ - s = sin(y); - c = cos(y); + sincos(y, &s, &c); ss = -s-c; cc = s-c; if(ix<0x7fe00000) { /* make sure y+y not overflow */ @@ -159,8 +158,7 @@ __ieee754_y1(double x) /* y1(x<0) = NaN and raise invalid exception. */ if(hx<0) return vzero/vzero; if(ix >= 0x40000000) { /* |x| >= 2.0 */ - s = sin(x); - c = cos(x); + sincos(x, &s, &c); ss = -s-c; cc = s-c; if(ix<0x7fe00000) { /* make sure x+x not overflow */ diff --git a/libm/upstream-freebsd/lib/msun/src/e_j1f.c b/libm/upstream-freebsd/lib/msun/src/e_j1f.c index 3abe201f5..31fc28a5d 100644 --- a/libm/upstream-freebsd/lib/msun/src/e_j1f.c +++ b/libm/upstream-freebsd/lib/msun/src/e_j1f.c @@ -14,7 +14,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/lib/msun/src/e_j1f.c 336089 2018-07-08 16:26:13Z markj $"); +__FBSDID("$FreeBSD: head/lib/msun/src/e_j1f.c 343953 2019-02-10 08:46:07Z peterj $"); /* * See e_j1.c for complete comments. @@ -56,8 +56,7 @@ __ieee754_j1f(float x) if(ix>=0x7f800000) return one/x; y = fabsf(x); if(ix >= 0x40000000) { /* |x| >= 2.0 */ - s = sinf(y); - c = cosf(y); + sincosf(y, &s, &c); ss = -s-c; cc = s-c; if(ix<0x7f000000) { /* make sure y+y not overflow */ @@ -114,8 +113,7 @@ __ieee754_y1f(float x) if(ix==0) return -one/vzero; if(hx<0) return vzero/vzero; if(ix >= 0x40000000) { /* |x| >= 2.0 */ - s = sinf(x); - c = cosf(x); + sincosf(x, &s, &c); ss = -s-c; cc = s-c; if(ix<0x7f000000) { /* make sure x+x not overflow */ diff --git a/libm/upstream-freebsd/lib/msun/src/e_jn.c b/libm/upstream-freebsd/lib/msun/src/e_jn.c index 58ec905c9..c039cf234 100644 --- a/libm/upstream-freebsd/lib/msun/src/e_jn.c +++ b/libm/upstream-freebsd/lib/msun/src/e_jn.c @@ -11,7 +11,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/lib/msun/src/e_jn.c 336089 2018-07-08 16:26:13Z markj $"); +__FBSDID("$FreeBSD: head/lib/msun/src/e_jn.c 343953 2019-02-10 08:46:07Z peterj $"); /* * __ieee754_jn(n, x), __ieee754_yn(n, x) @@ -54,7 +54,7 @@ double __ieee754_jn(int n, double x) { int32_t i,hx,ix,lx, sgn; - double a, b, temp, di; + double a, b, c, s, temp, di; double z, w; /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) @@ -91,11 +91,12 @@ __ieee754_jn(int n, double x) * 2 -s+c -c-s * 3 s+c c-s */ + sincos(x, &s, &c); switch(n&3) { - case 0: temp = cos(x)+sin(x); break; - case 1: temp = -cos(x)+sin(x); break; - case 2: temp = -cos(x)-sin(x); break; - case 3: temp = cos(x)-sin(x); break; + case 0: temp = c+s; break; + case 1: temp = -c+s; break; + case 2: temp = -c-s; break; + case 3: temp = c-s; break; } b = invsqrtpi*temp/sqrt(x); } else { @@ -216,7 +217,7 @@ __ieee754_yn(int n, double x) { int32_t i,hx,ix,lx; int32_t sign; - double a, b, temp; + double a, b, c, s, temp; EXTRACT_WORDS(hx,lx,x); ix = 0x7fffffff&hx; @@ -248,11 +249,12 @@ __ieee754_yn(int n, double x) * 2 -s+c -c-s * 3 s+c c-s */ + sincos(x, &s, &c); switch(n&3) { - case 0: temp = sin(x)-cos(x); break; - case 1: temp = -sin(x)-cos(x); break; - case 2: temp = -sin(x)+cos(x); break; - case 3: temp = sin(x)+cos(x); break; + case 0: temp = s-c; break; + case 1: temp = -s-c; break; + case 2: temp = -s+c; break; + case 3: temp = s+c; break; } b = invsqrtpi*temp/sqrt(x); } else { diff --git a/libm/upstream-freebsd/lib/msun/src/s_expm1.c b/libm/upstream-freebsd/lib/msun/src/s_expm1.c index 37998a387..21256ce5a 100644 --- a/libm/upstream-freebsd/lib/msun/src/s_expm1.c +++ b/libm/upstream-freebsd/lib/msun/src/s_expm1.c @@ -11,7 +11,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/msun/src/s_expm1.c 352710 2019-09-25 18:50:57Z dim $"); /* expm1(x) * Returns exp(x)-1, the exponential of x minus 1. @@ -188,7 +188,7 @@ expm1(double x) e = hxs*((r1-t)/(6.0 - x*t)); if(k==0) return x - (x*e-hxs); /* c is 0 */ else { - INSERT_WORDS(twopk,0x3ff00000+(k<<20),0); /* 2^k */ + INSERT_WORDS(twopk,((u_int32_t)(0x3ff+k))<<20,0); /* 2^k */ e = (x*(e-c)-c); e -= hxs; if(k== -1) return 0.5*(x-e)-0.5; diff --git a/libm/upstream-freebsd/lib/msun/src/s_expm1f.c b/libm/upstream-freebsd/lib/msun/src/s_expm1f.c index c0a39340f..4d9ab36b7 100644 --- a/libm/upstream-freebsd/lib/msun/src/s_expm1f.c +++ b/libm/upstream-freebsd/lib/msun/src/s_expm1f.c @@ -14,7 +14,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: head/lib/msun/src/s_expm1f.c 352710 2019-09-25 18:50:57Z dim $"); #include <float.h> @@ -94,7 +94,7 @@ expm1f(float x) e = hxs*((r1-t)/((float)6.0 - x*t)); if(k==0) return x - (x*e-hxs); /* c is 0 */ else { - SET_FLOAT_WORD(twopk,0x3f800000+(k<<23)); /* 2^k */ + SET_FLOAT_WORD(twopk,((u_int32_t)(0x7f+k))<<23); /* 2^k */ e = (x*(e-c)-c); e -= hxs; if(k== -1) return (float)0.5*(x-e)-(float)0.5; diff --git a/libm/upstream-freebsd/lib/msun/src/s_lround.c b/libm/upstream-freebsd/lib/msun/src/s_lround.c index b6a25b733..ce2aee779 100644 --- a/libm/upstream-freebsd/lib/msun/src/s_lround.c +++ b/libm/upstream-freebsd/lib/msun/src/s_lround.c @@ -32,7 +32,7 @@ #include <math.h> #ifndef type -__FBSDID("$FreeBSD: head/lib/msun/src/s_lround.c 326219 2017-11-26 02:00:33Z pfg $"); +__FBSDID("$FreeBSD: head/lib/msun/src/s_lround.c 353329 2019-10-08 21:39:51Z brooks $"); #define type double #define roundit round #define dtype long @@ -49,9 +49,9 @@ __FBSDID("$FreeBSD: head/lib/msun/src/s_lround.c 326219 2017-11-26 02:00:33Z pfg * that everything is in range. At compile time, INRANGE(x) should reduce to * two floating-point comparisons in the former case, or TRUE otherwise. */ -static const type dtype_min = DTYPE_MIN - 0.5; -static const type dtype_max = DTYPE_MAX + 0.5; -#define INRANGE(x) (dtype_max - DTYPE_MAX != 0.5 || \ +static const type dtype_min = (type)DTYPE_MIN - 0.5; +static const type dtype_max = (type)DTYPE_MAX + 0.5; +#define INRANGE(x) (dtype_max - (type)DTYPE_MAX != 0.5 || \ ((x) > dtype_min && (x) < dtype_max)) dtype diff --git a/linker/Android.bp b/linker/Android.bp index bb9d26d88..1800bdb2a 100644 --- a/linker/Android.bp +++ b/linker/Android.bp @@ -1,22 +1,6 @@ -cc_library_static { - name: "liblinker_malloc", - defaults: ["linux_bionic_supported"], - recovery_available: true, - native_bridge_supported: true, - - srcs: [ - "linker_memory.cpp", - ], - cflags: [ - "-Wall", - "-Werror", - ], - - // We need to access Bionic private headers in the linker. - include_dirs: ["bionic/libc"], - - static_libs: ["libasync_safe", "libbase"], -} +// ======================================================== +// linker_wrapper - Linux Bionic (on the host) +// ======================================================== // This is used for bionic on (host) Linux to bootstrap our linker embedded into // a binary. @@ -66,6 +50,103 @@ cc_object { include_dirs: ["bionic/libc"], } +// ======================================================== +// linker default configuration +// ======================================================== + +// Configuration for the linker binary and any of its static libraries. +cc_defaults { + name: "linker_defaults", + arch: { + arm: { + cflags: ["-D__work_around_b_24465209__"], + }, + x86: { + cflags: ["-D__work_around_b_24465209__"], + }, + }, + + cflags: [ + "-fno-stack-protector", + "-Wstrict-overflow=5", + "-fvisibility=hidden", + "-Wall", + "-Wextra", + "-Wunused", + "-Werror", + ], + + // TODO: split out the asflags. + asflags: [ + "-fno-stack-protector", + "-Wstrict-overflow=5", + "-fvisibility=hidden", + "-Wall", + "-Wextra", + "-Wunused", + "-Werror", + ], + + product_variables: { + debuggable: { + cppflags: ["-DUSE_LD_CONFIG_FILE"], + }, + }, + + cppflags: ["-Wold-style-cast"], + + static_libs: [ + "libziparchive", + "libbase", + "libz", + + "libasync_safe", + + "liblog", + ], + + // We need to access Bionic private headers in the linker. + include_dirs: ["bionic/libc"], +} + +// ======================================================== +// linker components +// ======================================================== + +// Enable a module on all targets the linker runs on (ordinary Android targets, Linux Bionic, and +// native bridge implementations). +cc_defaults { + name: "linker_all_targets", + defaults: ["linux_bionic_supported"], + recovery_available: true, + native_bridge_supported: true, +} + +cc_library_static { + name: "liblinker_main", + defaults: ["linker_defaults", "linker_all_targets"], + srcs: ["linker_main.cpp"], + + // Ensure that the compiler won't insert string function calls before ifuncs are resolved. + cflags: ["-ffreestanding"], +} + +cc_library_static { + name: "liblinker_malloc", + defaults: ["linker_defaults", "linker_all_targets"], + srcs: ["linker_memory.cpp"], +} + +cc_library_static { + name: "liblinker_debuggerd_stub", + defaults: ["linker_defaults", "linker_all_targets"], + srcs: ["linker_debuggerd_stub.cpp"], +} + +// ======================================================== +// template for the linker binary +// ======================================================== + filegroup { name: "linker_sources", srcs: [ @@ -79,7 +160,6 @@ filegroup { "linker_globals.cpp", "linker_libc_support.c", "linker_libcxx_support.cpp", - "linker_main.cpp", "linker_namespaces.cpp", "linker_logger.cpp", "linker_mapped_file_fragment.cpp", @@ -137,30 +217,50 @@ filegroup { ], } -filegroup { - name: "linker_version_script", - srcs: ["linker.generic.map"], -} - -filegroup { - name: "linker_version_script_arm", - srcs: ["linker.arm.map"], +cc_defaults { + name: "linker_version_script_overlay", + arch: { + arm: { version_script: "linker.arm.map" }, + arm64: { version_script: "linker.generic.map" }, + x86: { version_script: "linker.generic.map" }, + x86_64: { version_script: "linker.generic.map" }, + mips: { version_script: "linker.generic.map" }, + mips64: { version_script: "linker.generic.map" }, + }, } +// A template for the linker binary. May be inherited by native bridge implementations. cc_defaults { - name: "linker_defaults", + name: "linker_bin_template", + defaults: ["linker_defaults"], + + srcs: [":linker_sources"], + arch: { arm: { - cflags: ["-D__work_around_b_24465209__"], + srcs: [":linker_sources_arm"], + static_libs: ["libunwind_llvm"], + }, + arm64: { + srcs: [":linker_sources_arm64"], }, x86: { - cflags: ["-D__work_around_b_24465209__"], + srcs: [":linker_sources_x86"], + }, + x86_64: { + srcs: [":linker_sources_x86_64"], + }, + mips: { + srcs: [":linker_sources_mips"], + }, + mips64: { + srcs: [":linker_sources_mips64"], }, }, - // -shared is used to overwrite the -Bstatic and -static - // flags triggered by LOCAL_FORCE_STATIC_EXECUTABLE. - // This dynamic linker is actually a shared object linked with static libraries. + // -shared is used to overwrite the -Bstatic and -static flags triggered by enabling + // static_executable. This dynamic linker is actually a shared object linked with static + // libraries. ldflags: [ "-shared", "-Wl,-Bsymbolic", @@ -168,35 +268,6 @@ cc_defaults { "-Wl,-soname,ld-android.so", ], - cflags: [ - "-fno-stack-protector", - "-Wstrict-overflow=5", - "-fvisibility=hidden", - "-Wall", - "-Wextra", - "-Wunused", - "-Werror", - ], - - // TODO: split out the asflags. - asflags: [ - "-fno-stack-protector", - "-Wstrict-overflow=5", - "-fvisibility=hidden", - "-Wall", - "-Wextra", - "-Wunused", - "-Werror", - ], - - product_variables: { - debuggable: { - cppflags: ["-DUSE_LD_CONFIG_FILE"], - }, - }, - - cppflags: ["-Wold-style-cast"], - // we are going to link libc++_static manually because // when stl is not set to "none" build system adds libdl // to the list of static libraries which needs to be @@ -222,58 +293,15 @@ cc_defaults { sanitize: { hwaddress: false, }, -} - -cc_binary { - defaults: ["linux_bionic_supported", "linker_defaults"], - srcs: [ ":linker_sources" ], - - arch: { - arm: { - srcs: [ ":linker_sources_arm" ], - version_script: ":linker_version_script_arm", - static_libs: ["libunwind_llvm"], - }, - arm64: { - srcs: [":linker_sources_arm64"], - version_script: ":linker_version_script", - }, - x86: { - srcs: [":linker_sources_x86"], - version_script: ":linker_version_script", - }, - x86_64: { - srcs: [":linker_sources_x86_64"], - version_script: ":linker_version_script", - }, - mips: { - srcs: [":linker_sources_mips"], - version_script: ":linker_version_script", - }, - mips64: { - srcs: [":linker_sources_mips64"], - version_script: ":linker_version_script", - }, - }, - - // We need to access Bionic private headers in the linker. - include_dirs: ["bionic/libc"], static_libs: [ - "libc_nomalloc", - "libm", - "libziparchive", - "libbase", - "libz", - - "libasync_safe", + "liblinker_main", + "liblinker_malloc", - "liblog", "libc++_static", - - // Important: The liblinker_malloc should be the last library in the list - // to overwrite any other malloc implementations by other static libraries. - "liblinker_malloc", + "libc_nomalloc", + "libc_dynamic_dispatch", + "libm", ], // Ensure that if the linker needs __gnu_Unwind_Find_exidx, then the linker will have a @@ -287,9 +315,25 @@ cc_binary { // linker stops linking against libgcc.a's arm32 unwinder. whole_static_libs: ["libc_unwind_static"], + system_shared_libs: [], + + // Opt out of native_coverage when opting out of system_shared_libs + native_coverage: false, +} + +// ======================================================== +// linker[_asan][64] binary +// ======================================================== + +cc_binary { name: "linker", + defaults: [ + "linker_bin_template", + "linux_bionic_supported", + "linker_version_script_overlay", + ], + symlinks: ["linker_asan"], - recovery_available: true, multilib: { lib32: { cflags: ["-DLIB_PATH=\"lib\""], @@ -299,28 +343,38 @@ cc_binary { suffix: "64", }, }, - system_shared_libs: [], - // Opt out of native_coverage when opting out of system_shared_libs - native_coverage: false, + compile_multilib: "both", + xom: false, + + recovery_available: true, + apex_available: [ + "//apex_available:platform", + "com.android.runtime", + ], target: { android: { + srcs: [ + "linker_debuggerd_android.cpp", + ], static_libs: [ "libc++demangle", "libdebuggerd_handler_fallback", ], }, + linux_bionic: { + static_libs: [ + "liblinker_debuggerd_stub", + ], + } }, - compile_multilib: "both", - xom: false, - - apex_available: [ - "//apex_available:platform", - "com.android.runtime", - ], } +// ======================================================== +// assorted modules +// ======================================================== + sh_binary { name: "ldd", src: "ldd", @@ -347,25 +401,11 @@ cc_library { // for x86, exclude libgcc_eh.a for the same reasons as above arch: { - arm: { - version_script: "linker.arm.map", - }, - arm64: { - version_script: "linker.generic.map", - }, x86: { ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"], - version_script: "linker.generic.map", }, x86_64: { ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"], - version_script: "linker.generic.map", - }, - mips: { - version_script: "linker.generic.map", - }, - mips64: { - version_script: "linker.generic.map", }, }, @@ -379,7 +419,7 @@ cc_library { stl: "none", name: "ld-android", - defaults: ["linux_bionic_supported"], + defaults: ["linux_bionic_supported", "linker_version_script_overlay"], recovery_available: true, native_bridge_supported: true, diff --git a/linker/linker.cpp b/linker/linker.cpp index dec575baf..e09b2a4c8 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -68,6 +68,7 @@ #include "linker_tls.h" #include "linker_utils.h" +#include "private/bionic_call_ifunc_resolver.h" #include "private/bionic_globals.h" #include "android-base/macros.h" #include "android-base/strings.h" @@ -300,10 +301,6 @@ void count_relocation(RelocationKind) { } #endif -#if COUNT_PAGES -uint32_t bitmask[4096]; -#endif - static void notify_gdb_of_load(soinfo* info) { if (info->is_linker() || info->is_main_executable()) { // gdb already knows about the linker and the main executable. @@ -1506,7 +1503,16 @@ static bool load_library(android_namespace_t* ns, // Open the file. int fd = open_library(ns, zip_archive_cache, name, needed_by, &file_offset, &realpath); if (fd == -1) { - DL_OPEN_ERR("library \"%s\" not found", name); + if (task->is_dt_needed()) { + if (needed_by->is_main_executable()) { + DL_OPEN_ERR("library \"%s\" not found: needed by main executable", name); + } else { + DL_OPEN_ERR("library \"%s\" not found: needed by %s in namespace %s", name, + needed_by->get_realpath(), task->get_start_from()->get_name()); + } + } else { + DL_OPEN_ERR("library \"%s\" not found", name); + } return false; } @@ -2690,11 +2696,9 @@ bool link_namespaces_all_libs(android_namespace_t* namespace_from, ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr) { if (g_is_ldd) return 0; - typedef ElfW(Addr) (*ifunc_resolver_t)(void); - ifunc_resolver_t ifunc_resolver = reinterpret_cast<ifunc_resolver_t>(resolver_addr); - ElfW(Addr) ifunc_addr = ifunc_resolver(); + ElfW(Addr) ifunc_addr = __bionic_call_ifunc_resolver(resolver_addr); TRACE_TYPE(RELO, "Called ifunc_resolver@%p. The result is %p", - ifunc_resolver, reinterpret_cast<void*>(ifunc_addr)); + reinterpret_cast<void *>(resolver_addr), reinterpret_cast<void*>(ifunc_addr)); return ifunc_addr; } @@ -3141,7 +3145,6 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r switch (type) { case R_GENERIC_JUMP_SLOT: count_relocation(kRelocAbsolute); - MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO JMP_SLOT %16p <- %16p %s\n", reinterpret_cast<void*>(reloc), reinterpret_cast<void*>(sym_addr + addend), sym_name); @@ -3151,7 +3154,6 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r case R_GENERIC_ABSOLUTE: case R_GENERIC_GLOB_DAT: count_relocation(kRelocAbsolute); - MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO ABSOLUTE/GLOB_DAT %16p <- %16p %s\n", reinterpret_cast<void*>(reloc), reinterpret_cast<void*>(sym_addr + addend), sym_name); @@ -3159,7 +3161,6 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r break; case R_GENERIC_RELATIVE: count_relocation(kRelocRelative); - MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO RELATIVE %16p <- %16p\n", reinterpret_cast<void*>(reloc), reinterpret_cast<void*>(load_bias + addend)); @@ -3167,11 +3168,13 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r break; case R_GENERIC_IRELATIVE: count_relocation(kRelocRelative); - MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO IRELATIVE %16p <- %16p\n", reinterpret_cast<void*>(reloc), reinterpret_cast<void*>(load_bias + addend)); - { + // In the linker, ifuncs are called as soon as possible so that string functions work. + // We must not call them again. (e.g. On arm32, resolving an ifunc changes the meaning of + // the addend from a resolver function to the implementation.) + if (!is_linker()) { #if !defined(__LP64__) // When relocating dso with text_relocation .text segment is // not executable. We need to restore elf flags for this @@ -3211,7 +3214,6 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r return false; case R_GENERIC_TLS_TPREL: count_relocation(kRelocRelative); - MARK(rel->r_offset); { ElfW(Addr) tpoff = 0; if (lsi == nullptr) { @@ -3237,7 +3239,6 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r break; case R_GENERIC_TLS_DTPMOD: count_relocation(kRelocRelative); - MARK(rel->r_offset); { size_t module_id = 0; if (lsi == nullptr) { @@ -3253,7 +3254,6 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r break; case R_GENERIC_TLS_DTPREL: count_relocation(kRelocRelative); - MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO TLS_DTPREL %16p <- %16p %s\n", reinterpret_cast<void*>(reloc), reinterpret_cast<void*>(sym_addr + addend), sym_name); @@ -3265,7 +3265,6 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r // other architectures, as long as the resolver functions are implemented. case R_GENERIC_TLSDESC: count_relocation(kRelocRelative); - MARK(rel->r_offset); { TlsDescriptor* desc = reinterpret_cast<TlsDescriptor*>(reloc); if (lsi == nullptr) { @@ -3306,14 +3305,12 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r #if defined(__x86_64__) case R_X86_64_32: count_relocation(kRelocAbsolute); - MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO R_X86_64_32 %08zx <- +%08zx %s", static_cast<size_t>(reloc), static_cast<size_t>(sym_addr), sym_name); *reinterpret_cast<Elf32_Addr*>(reloc) = sym_addr + addend; break; case R_X86_64_PC32: count_relocation(kRelocRelative); - MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO R_X86_64_PC32 %08zx <- +%08zx (%08zx - %08zx) %s", static_cast<size_t>(reloc), static_cast<size_t>(sym_addr - reloc), static_cast<size_t>(sym_addr), static_cast<size_t>(reloc), sym_name); @@ -3322,7 +3319,6 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r #elif defined(__i386__) case R_386_PC32: count_relocation(kRelocRelative); - MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO R_386_PC32 %08x <- +%08x (%08x - %08x) %s", reloc, (sym_addr - reloc), sym_addr, reloc, sym_name); *reinterpret_cast<ElfW(Addr)*>(reloc) += (sym_addr - reloc); diff --git a/linker/linker_config.cpp b/linker/linker_config.cpp index 46c91a3dd..85ea8d180 100644 --- a/linker/linker_config.cpp +++ b/linker/linker_config.cpp @@ -408,8 +408,10 @@ class Properties { params.push_back({ "SDK_VER", buf }); } - static std::string vndk = Config::get_vndk_version_string('-'); - params.push_back({ "VNDK_VER", vndk }); + static std::string vndk_ver = Config::get_vndk_version_string('-'); + params.push_back({ "VNDK_VER", vndk_ver }); + static std::string vndk_apex_ver = Config::get_vndk_version_string('v'); + params.push_back({ "VNDK_APEX_VER", vndk_apex_ver }); for (auto& path : paths) { format_string(&path, params); diff --git a/linker/linker_debug.h b/linker/linker_debug.h index 7a1cb3cbe..6031850a4 100644 --- a/linker/linker_debug.h +++ b/linker/linker_debug.h @@ -44,7 +44,6 @@ #define DO_TRACE_IFUNC 1 #define TIMING 0 #define STATS 0 -#define COUNT_PAGES 0 /********************************************************************* * You shouldn't need to modify anything below unless you are adding @@ -83,22 +82,3 @@ __LIBC_HIDDEN__ extern int g_ld_debug_verbosity; #endif /* TRACE_DEBUG */ #define TRACE_TYPE(t, x...) do { if (DO_TRACE_##t) { TRACE(x); } } while (0) - -#if COUNT_PAGES -extern uint32_t bitmask[]; -#if defined(__LP64__) -#define MARK(offset) \ - do { \ - if ((((offset) >> 12) >> 5) < 4096) \ - bitmask[((offset) >> 12) >> 5] |= (1 << (((offset) >> 12) & 31)); \ - } while (0) -#else -#define MARK(offset) \ - do { \ - bitmask[((offset) >> 12) >> 3] |= (1 << (((offset) >> 12) & 7)); \ - } while (0) -#endif -#else -#define MARK(x) do {} while (0) - -#endif diff --git a/linker/linker_debuggerd.h b/linker/linker_debuggerd.h new file mode 100644 index 000000000..d70187902 --- /dev/null +++ b/linker/linker_debuggerd.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +void linker_debuggerd_init(); diff --git a/linker/linker_debuggerd_android.cpp b/linker/linker_debuggerd_android.cpp new file mode 100644 index 000000000..b8c82f990 --- /dev/null +++ b/linker/linker_debuggerd_android.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2019 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 "linker_debuggerd.h" + +#include "debuggerd/handler.h" +#include "private/bionic_globals.h" + +#include "linker_gdb_support.h" + +void linker_debuggerd_init() { + debuggerd_callbacks_t callbacks = { + .get_abort_message = []() { + return __libc_shared_globals()->abort_msg; + }, + .post_dump = ¬ify_gdb_of_libraries, + }; + debuggerd_init(&callbacks); +} diff --git a/linker/linker_debuggerd_stub.cpp b/linker/linker_debuggerd_stub.cpp new file mode 100644 index 000000000..631e6e48b --- /dev/null +++ b/linker/linker_debuggerd_stub.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 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 "linker_debuggerd.h" + +void linker_debuggerd_init() { +} diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp index fd1592d33..8ba947f31 100644 --- a/linker/linker_main.cpp +++ b/linker/linker_main.cpp @@ -32,6 +32,7 @@ #include <sys/auxv.h> #include "linker_debug.h" +#include "linker_debuggerd.h" #include "linker_cfi.h" #include "linker_gdb_support.h" #include "linker_globals.h" @@ -39,6 +40,8 @@ #include "linker_tls.h" #include "linker_utils.h" +#include "private/bionic_auxv.h" +#include "private/bionic_call_ifunc_resolver.h" #include "private/bionic_globals.h" #include "private/bionic_tls.h" #include "private/KernelArgumentBlock.h" @@ -46,9 +49,6 @@ #include "android-base/unique_fd.h" #include "android-base/strings.h" #include "android-base/stringprintf.h" -#ifdef __ANDROID__ -#include "debuggerd/handler.h" -#endif #include <async_safe/log.h> #include <bionic/libc_init_common.h> @@ -311,15 +311,7 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load __system_properties_init(); // may use 'environ' // Register the debuggerd signal handler. -#ifdef __ANDROID__ - debuggerd_callbacks_t callbacks = { - .get_abort_message = []() { - return __libc_shared_globals()->abort_msg; - }, - .post_dump = ¬ify_gdb_of_libraries, - }; - debuggerd_init(&callbacks); -#endif + linker_debuggerd_init(); g_linker_logger.ResetState(); @@ -496,31 +488,7 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load #if STATS print_linker_stats(); #endif -#if COUNT_PAGES - { - unsigned n; - unsigned i; - unsigned count = 0; - for (n = 0; n < 4096; n++) { - if (bitmask[n]) { - unsigned x = bitmask[n]; -#if defined(__LP64__) - for (i = 0; i < 32; i++) { -#else - for (i = 0; i < 8; i++) { -#endif - if (x & 1) { - count++; - } - x >>= 1; - } - } - } - PRINT("PAGES MODIFIED: %s: %d (%dKB)", g_argv[0], count, count * 4); - } -#endif - -#if TIMING || STATS || COUNT_PAGES +#if TIMING || STATS fflush(stdout); #endif @@ -599,6 +567,39 @@ static void set_bss_vma_name(soinfo* si) { } } +// TODO: There is a similar ifunc resolver calling loop in libc_init_static.cpp, but that version +// uses weak symbols, which don't work in the linker prior to its relocation. This version also +// supports a load bias. When we stop supporting the gold linker in the NDK, then maybe we can use +// non-weak definitions and merge the two loops. +#if defined(USE_RELA) +extern __LIBC_HIDDEN__ ElfW(Rela) __rela_iplt_start[], __rela_iplt_end[]; + +static void call_ifunc_resolvers(ElfW(Addr) load_bias) { + for (ElfW(Rela) *r = __rela_iplt_start; r != __rela_iplt_end; ++r) { + ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset + load_bias); + ElfW(Addr) resolver = r->r_addend + load_bias; + *offset = __bionic_call_ifunc_resolver(resolver); + } +} +#else +extern __LIBC_HIDDEN__ ElfW(Rel) __rel_iplt_start[], __rel_iplt_end[]; + +static void call_ifunc_resolvers(ElfW(Addr) load_bias) { + for (ElfW(Rel) *r = __rel_iplt_start; r != __rel_iplt_end; ++r) { + ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset + load_bias); + ElfW(Addr) resolver = *offset + load_bias; + *offset = __bionic_call_ifunc_resolver(resolver); + } +} +#endif + +// Usable before ifunc resolvers have been called. This function is compiled with -ffreestanding. +static void linker_memclr(void* dst, size_t cnt) { + for (size_t i = 0; i < cnt; ++i) { + reinterpret_cast<char*>(dst)[i] = '\0'; + } +} + // Detect an attempt to run the linker on itself. e.g.: // /system/bin/linker64 /system/bin/linker64 // Use priority-1 to run this constructor before other constructors. @@ -632,7 +633,8 @@ __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& linker_so); extern "C" ElfW(Addr) __linker_init(void* raw_args) { // Initialize TLS early so system calls and errno work. KernelArgumentBlock args(raw_args); - bionic_tcb temp_tcb = {}; + bionic_tcb temp_tcb __attribute__((uninitialized)); + linker_memclr(&temp_tcb, sizeof(temp_tcb)); __libc_init_main_thread_early(args, &temp_tcb); // When the linker is run by itself (rather than as an interpreter for @@ -650,11 +652,15 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) { ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr); ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_addr + elf_hdr->e_phoff); + // string.h functions must not be used prior to calling the linker's ifunc resolvers. + const ElfW(Addr) load_bias = get_elf_exec_load_bias(elf_hdr); + call_ifunc_resolvers(load_bias); + soinfo tmp_linker_so(nullptr, nullptr, nullptr, 0, 0); tmp_linker_so.base = linker_addr; tmp_linker_so.size = phdr_table_get_load_size(phdr, elf_hdr->e_phnum); - tmp_linker_so.load_bias = get_elf_exec_load_bias(elf_hdr); + tmp_linker_so.load_bias = load_bias; tmp_linker_so.dynamic = nullptr; tmp_linker_so.phdr = phdr; tmp_linker_so.phnum = elf_hdr->e_phnum; diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp index 9e463948a..b69da9702 100644 --- a/tests/dl_test.cpp +++ b/tests/dl_test.cpp @@ -204,7 +204,10 @@ TEST(dl, exec_with_ld_preload) { // The two libs are in ns2/ subdir. TEST(dl, exec_without_ld_config_file) { #if defined(__BIONIC__) - std::string error_message = "CANNOT LINK EXECUTABLE \"" + GetTestlibRoot() + "/ld_config_test_helper/ld_config_test_helper\": library \"ld_config_test_helper_lib1.so\" not found\n"; + std::string error_message = + "CANNOT LINK EXECUTABLE \"" + GetTestlibRoot() + + "/ld_config_test_helper/ld_config_test_helper\": library \"ld_config_test_helper_lib1.so\" " + "not found: needed by main executable\n"; std::string helper = GetTestlibRoot() + "/ld_config_test_helper/ld_config_test_helper"; chmod(helper.c_str(), 0755); diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp index e98d66ffd..7e772b840 100644 --- a/tests/dlext_test.cpp +++ b/tests/dlext_test.cpp @@ -28,6 +28,7 @@ #include <android/dlext.h> #include <android-base/file.h> #include <android-base/strings.h> +#include <android-base/test_utils.h> #include <sys/mman.h> #include <sys/types.h> @@ -1374,7 +1375,10 @@ TEST(dlext, ns_isolated) { void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo); ASSERT_TRUE(handle2 == nullptr); - ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror()); + const char* error = dlerror(); + ASSERT_MATCH(error, + R"(dlopen failed: library "libnstest_private_external.so" not found: needed by )" + R"(\S+libnstest_root_not_isolated.so in namespace private_isolated1)"); // Check dlopen by absolute path handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo); @@ -1502,7 +1506,9 @@ TEST(dlext, ns_shared) { void* handle2 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo); ASSERT_TRUE(handle2 == nullptr); - ASSERT_STREQ("dlopen failed: library \"libnstest_private_external.so\" not found", dlerror()); + ASSERT_MATCH(dlerror(), + R"(dlopen failed: library "libnstest_private_external.so" not found: needed by )" + R"(\S+libnstest_root_not_isolated.so in namespace private_isolated_shared)"); // Check dlopen by absolute path handle2 = android_dlopen_ext(lib_private_external_path.c_str(), RTLD_NOW, &extinfo); @@ -1762,7 +1768,10 @@ TEST(dlext, ns_isolated_rtld_global) { handle1 = android_dlopen_ext(root_lib, RTLD_NOW, &extinfo); ASSERT_TRUE(handle1 == nullptr); - ASSERT_STREQ("dlopen failed: library \"libnstest_public.so\" not found", dlerror()); + ASSERT_MATCH( + dlerror(), + R"(dlopen failed: library "libnstest_public.so" not found: needed by \S+libnstest_root.so)" + R"( in namespace isolated2)"); } TEST(dlext, ns_inaccessible_error_message) { diff --git a/tests/ifunc_test.cpp b/tests/ifunc_test.cpp index 7ab589976..e69271f02 100644 --- a/tests/ifunc_test.cpp +++ b/tests/ifunc_test.cpp @@ -16,12 +16,19 @@ #include <gtest/gtest.h> +#include <sys/auxv.h> +#if defined(__BIONIC__) +#include <sys/ifunc.h> +#endif + +typedef int (*fn_ptr_t)(); + int ret42() { return 42; } -extern "C" void* resolver() { - return (void*)ret42; +extern "C" fn_ptr_t resolver() { + return ret42; } int ifunc() __attribute__((ifunc("resolver"))); @@ -29,3 +36,51 @@ int ifunc() __attribute__((ifunc("resolver"))); TEST(ifunc, function) { ASSERT_EQ(42, ifunc()); } + +#if defined(__BIONIC__) + +#if defined(__aarch64__) + +static uint64_t g_hwcap; +static __ifunc_arg_t g_arg; + +extern "C" fn_ptr_t hwcap_resolver(uint64_t hwcap, __ifunc_arg_t* arg) { + g_hwcap = hwcap; + g_arg = *arg; + return ret42; +} + +#elif defined(__arm__) + +static unsigned long g_hwcap; + +extern "C" fn_ptr_t hwcap_resolver(unsigned long hwcap) { + g_hwcap = hwcap; + return ret42; +} + +#else + +extern "C" fn_ptr_t hwcap_resolver() { + return ret42; +} + +#endif + +int hwcap() __attribute__((ifunc("hwcap_resolver"))); + +TEST(ifunc, hwcap) { + ASSERT_EQ(42, hwcap()); + +#if defined(__aarch64__) + EXPECT_EQ(getauxval(AT_HWCAP) | _IFUNC_ARG_HWCAP, g_hwcap); + + EXPECT_EQ(sizeof(__ifunc_arg_t), g_arg._size); + EXPECT_EQ(getauxval(AT_HWCAP), g_arg._hwcap); + EXPECT_EQ(getauxval(AT_HWCAP2), g_arg._hwcap2); +#elif defined(__arm__) + EXPECT_EQ(getauxval(AT_HWCAP), g_hwcap); +#endif +} + +#endif // defined(__BIONIC__) diff --git a/tests/leak_test.cpp b/tests/leak_test.cpp index 3cc1a0a91..e0a3d5772 100644 --- a/tests/leak_test.cpp +++ b/tests/leak_test.cpp @@ -127,22 +127,20 @@ TEST(pthread_leak, join) { // http://b/36045112 TEST(pthread_leak, detach) { LeakChecker lc; - constexpr int kThreadCount = 100; - // Devices with low power cores/low number of cores can not finish test in time hence decreasing - // threads count to 90. - // http://b/129924384. - int threads_count = (sysconf(_SC_NPROCESSORS_CONF) > 2) ? kThreadCount : (kThreadCount - 10); + // Ancient devices with only 2 cores need a lower limit. + // http://b/129924384 and https://issuetracker.google.com/142210680. + const int thread_count = (sysconf(_SC_NPROCESSORS_CONF) > 2) ? 100 : 50; for (size_t pass = 0; pass < 1; ++pass) { - struct thread_data { pthread_barrier_t* barrier; pid_t* tid; } threads[kThreadCount] = {}; + struct thread_data { pthread_barrier_t* barrier; pid_t* tid; } threads[thread_count]; pthread_barrier_t barrier; - ASSERT_EQ(pthread_barrier_init(&barrier, nullptr, threads_count + 1), 0); + ASSERT_EQ(pthread_barrier_init(&barrier, nullptr, thread_count + 1), 0); // Start child threads. - pid_t tids[kThreadCount]; - for (int i = 0; i < threads_count; ++i) { + pid_t tids[thread_count]; + for (int i = 0; i < thread_count; ++i) { threads[i] = {&barrier, &tids[i]}; const auto thread_function = +[](void* ptr) -> void* { thread_data* data = static_cast<thread_data*>(ptr); @@ -158,7 +156,7 @@ TEST(pthread_leak, detach) { pthread_barrier_wait(&barrier); ASSERT_EQ(pthread_barrier_destroy(&barrier), 0); - WaitUntilAllThreadsExited(tids, threads_count); + WaitUntilAllThreadsExited(tids, thread_count); // A native bridge implementation might need a warm up pass to reach a steady state. // http://b/37920774. diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp index 0407553b2..ebbd24793 100644 --- a/tests/malloc_test.cpp +++ b/tests/malloc_test.cpp @@ -358,15 +358,20 @@ TEST(malloc, valloc_overflow) { TEST(malloc, malloc_info) { #ifdef __BIONIC__ SKIP_WITH_HWASAN; // hwasan does not implement malloc_info - char* buf; - size_t bufsize; - FILE* memstream = open_memstream(&buf, &bufsize); - ASSERT_NE(nullptr, memstream); - ASSERT_EQ(0, malloc_info(0, memstream)); - ASSERT_EQ(0, fclose(memstream)); + + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + FILE* fp = fdopen(tf.fd, "w+"); + tf.release(); + ASSERT_TRUE(fp != nullptr); + ASSERT_EQ(0, malloc_info(0, fp)); + ASSERT_EQ(0, fclose(fp)); + + std::string contents; + ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents)); tinyxml2::XMLDocument doc; - ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(buf)); + ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str())); auto root = doc.FirstChildElement(); ASSERT_NE(nullptr, root); @@ -416,17 +421,21 @@ TEST(malloc, malloc_info_matches_mallinfo) { #ifdef __BIONIC__ SKIP_WITH_HWASAN; // hwasan does not implement malloc_info - char* buf; - size_t bufsize; - FILE* memstream = open_memstream(&buf, &bufsize); - ASSERT_NE(nullptr, memstream); + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + FILE* fp = fdopen(tf.fd, "w+"); + tf.release(); + ASSERT_TRUE(fp != nullptr); size_t mallinfo_before_allocated_bytes = mallinfo().uordblks; - ASSERT_EQ(0, malloc_info(0, memstream)); + ASSERT_EQ(0, malloc_info(0, fp)); size_t mallinfo_after_allocated_bytes = mallinfo().uordblks; - ASSERT_EQ(0, fclose(memstream)); + ASSERT_EQ(0, fclose(fp)); + + std::string contents; + ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents)); tinyxml2::XMLDocument doc; - ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(buf)); + ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str())); size_t total_allocated_bytes = 0; auto root = doc.FirstChildElement(); diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp index 1ae174a63..6db775144 100644 --- a/tests/signal_test.cpp +++ b/tests/signal_test.cpp @@ -20,6 +20,7 @@ #include <sys/types.h> #include <unistd.h> +#include <chrono> #include <thread> #include <android-base/macros.h> @@ -27,6 +28,8 @@ #include "SignalUtils.h" +using namespace std::chrono_literals; + static int SIGNAL_MIN() { return 1; // Signals start at 1 (SIGHUP), not 0. } @@ -753,12 +756,6 @@ TEST(signal, sigtimedwait64_SIGRTMIN) { ASSERT_EQ(0, errno); } -static int64_t NanoTime() { - timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); - return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec; -} - TEST(signal, sigtimedwait_timeout) { // Block SIGALRM. sigset_t just_SIGALRM; @@ -768,13 +765,14 @@ TEST(signal, sigtimedwait_timeout) { ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); // Wait timeout. - int64_t start_time = NanoTime(); + auto t0 = std::chrono::steady_clock::now(); siginfo_t info; timespec timeout = { .tv_sec = 0, .tv_nsec = 1000000 }; errno = 0; ASSERT_EQ(-1, sigtimedwait(&just_SIGALRM, &info, &timeout)); ASSERT_EQ(EAGAIN, errno); - ASSERT_GE(NanoTime() - start_time, 1000000); + auto t1 = std::chrono::steady_clock::now(); + ASSERT_GE(t1-t0, 1000000ns); ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, nullptr)); } diff --git a/tests/system_properties_test2.cpp b/tests/system_properties_test2.cpp index c061faa09..0953bdeb0 100644 --- a/tests/system_properties_test2.cpp +++ b/tests/system_properties_test2.cpp @@ -14,21 +14,23 @@ * limitations under the License. */ -#include <gtest/gtest.h> - #include <errno.h> #include <sys/wait.h> #include <unistd.h> + +#include <chrono> #include <sstream> #include <string> +#include <gtest/gtest.h> + +#include "utils.h" + #if defined(__BIONIC__) #include <sys/system_properties.h> - -static uint64_t NanoTime() { - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_nsec; +int64_t NanoTime() { + auto t = std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now()); + return t.time_since_epoch().count(); } #endif @@ -128,6 +130,29 @@ TEST(properties, smoke) { #endif // __BIONIC__ } +TEST(properties, no_fd_leaks) { +#if defined(__BIONIC__) + FdLeakChecker leak_checker; + std::stringstream ss; + ss << "debug.test." << getpid() << "." << NanoTime() << "."; + const std::string property_prefix = ss.str(); + const std::string property_name = property_prefix + "property1"; + + for (size_t i = 0; i < 100; ++i) { + char propvalue[PROP_VALUE_MAX]; + ASSERT_EQ(0, __system_property_set(property_name.c_str(), "value1")); + ASSERT_EQ(6, __system_property_get(property_name.c_str(), propvalue)); + ASSERT_STREQ("value1", propvalue); + + ASSERT_EQ(0, __system_property_set(property_name.c_str(), "value2")); + ASSERT_EQ(6, __system_property_get(property_name.c_str(), propvalue)); + ASSERT_STREQ("value2", propvalue); + } +#else // __BIONIC__ + GTEST_SKIP() << "bionic-only test"; +#endif // __BIONIC__ +} + TEST(properties, empty_value) { #if defined(__BIONIC__) char propvalue[PROP_VALUE_MAX]; @@ -136,13 +161,13 @@ TEST(properties, empty_value) { ss << "debug.test." << getpid() << "." << NanoTime() << "." << "property_empty"; const std::string property_name = ss.str(); - for (size_t i=0; i<1000; ++i) { + for (size_t i = 0; i < 1000; ++i) { ASSERT_EQ(0, __system_property_set(property_name.c_str(), "")); ASSERT_EQ(0, __system_property_get(property_name.c_str(), propvalue)); ASSERT_STREQ("", propvalue); } -#else // __BIONIC__ - GTEST_SKIP() << "bionic-only test"; +#else // __BIONIC__ + GTEST_SKIP() << "bionic-only test"; #endif // __BIONIC__ } diff --git a/tests/time_test.cpp b/tests/time_test.cpp index 4e1724211..378b4ac22 100644 --- a/tests/time_test.cpp +++ b/tests/time_test.cpp @@ -24,13 +24,17 @@ #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> + #include <atomic> +#include <chrono> #include "SignalUtils.h" #include "utils.h" #include "private/bionic_constants.h" +using namespace std::chrono_literals; + TEST(time, time) { // Acquire time time_t p1, t1 = time(&p1); @@ -797,7 +801,7 @@ TEST(time, clock_settime) { ASSERT_EQ(EINVAL, errno); } -TEST(time, clock_nanosleep) { +TEST(time, clock_nanosleep_EINVAL) { timespec in; timespec out; ASSERT_EQ(EINVAL, clock_nanosleep(-1, 0, &in, &out)); @@ -810,6 +814,29 @@ TEST(time, clock_nanosleep_thread_cputime_id) { ASSERT_EQ(EINVAL, clock_nanosleep(CLOCK_THREAD_CPUTIME_ID, 0, &in, nullptr)); } +TEST(time, clock_nanosleep) { + auto t0 = std::chrono::steady_clock::now(); + const timespec ts = {.tv_nsec = 5000000}; + ASSERT_EQ(0, clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, nullptr)); + auto t1 = std::chrono::steady_clock::now(); + ASSERT_GE(t1-t0, 5000000ns); +} + +TEST(time, nanosleep) { + auto t0 = std::chrono::steady_clock::now(); + const timespec ts = {.tv_nsec = 5000000}; + ASSERT_EQ(0, nanosleep(&ts, nullptr)); + auto t1 = std::chrono::steady_clock::now(); + ASSERT_GE(t1-t0, 5000000ns); +} + +TEST(time, nanosleep_EINVAL) { + timespec ts = {.tv_sec = -1}; + errno = 0; + ASSERT_EQ(-1, nanosleep(&ts, nullptr)); + ASSERT_EQ(EINVAL, errno); +} + TEST(time, bug_31938693) { // User-visible symptoms in N: // http://b/31938693 diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp index 10c1710bd..99d92e6fe 100644 --- a/tests/unistd_test.cpp +++ b/tests/unistd_test.cpp @@ -33,6 +33,8 @@ #include <sys/wait.h> #include <unistd.h> +#include <chrono> + #include <android-base/file.h> #include <android-base/strings.h> @@ -46,6 +48,8 @@ #define UNISTD_DEATHTEST unistd_DeathTest #endif +using namespace std::chrono_literals; + static void* get_brk() { return sbrk(0); } @@ -1516,3 +1520,17 @@ TEST(UNISTD_TEST, swab_negative_byte_count) { swab("hello", buf, -1); ASSERT_EQ('x', buf[0]); } + +TEST(UNISTD_TEST, usleep) { + auto t0 = std::chrono::steady_clock::now(); + ASSERT_EQ(0, usleep(5000)); + auto t1 = std::chrono::steady_clock::now(); + ASSERT_GE(t1-t0, 5000us); +} + +TEST(UNISTD_TEST, sleep) { + auto t0 = std::chrono::steady_clock::now(); + ASSERT_EQ(0U, sleep(1)); + auto t1 = std::chrono::steady_clock::now(); + ASSERT_GE(t1-t0, 1s); +} diff --git a/tests/utils.h b/tests/utils.h index fe41019a7..cfc68c9a3 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -14,9 +14,9 @@ * limitations under the License. */ -#ifndef __TEST_UTILS_H -#define __TEST_UTILS_H +#pragma once +#include <dirent.h> #include <dlfcn.h> #include <fcntl.h> #include <inttypes.h> @@ -255,4 +255,28 @@ class ExecTestHelper { }; #endif -#endif +class FdLeakChecker { + public: + FdLeakChecker() { + } + + ~FdLeakChecker() { + size_t end_count = CountOpenFds(); + EXPECT_EQ(start_count_, end_count); + } + + private: + static size_t CountOpenFds() { + auto fd_dir = std::unique_ptr<DIR, decltype(&closedir)>{ opendir("/proc/self/fd"), closedir }; + size_t count = 0; + dirent* de = nullptr; + while ((de = readdir(fd_dir.get())) != nullptr) { + if (de->d_type == DT_LNK) { + ++count; + } + } + return count; + } + + size_t start_count_ = CountOpenFds(); +}; diff --git a/tools/versioner/src/Driver.cpp b/tools/versioner/src/Driver.cpp index d2c50a96b..bad63ad2d 100644 --- a/tools/versioner/src/Driver.cpp +++ b/tools/versioner/src/Driver.cpp @@ -126,14 +126,7 @@ static void generateTargetCC1Flags(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSyste cmd.push_back("-DANDROID"); cmd.push_back("-D__ANDROID_API__="s + std::to_string(type.api_level)); - // FIXME: Re-enable FORTIFY properly once our clang in external/ is new enough - // to support diagnose_if without giving us syntax errors. -#if 0 cmd.push_back("-D_FORTIFY_SOURCE=2"); -#else - cmd.push_back("-D_FORTIFY_SOURCE=0"); - cmd.push_back("-D__BIONIC_DECLARE_FORTIFY_HELPERS"); -#endif cmd.push_back("-D_GNU_SOURCE"); cmd.push_back("-D_FILE_OFFSET_BITS="s + std::to_string(type.file_offset_bits)); |