OSDN Git Service

Merge "Add a netcontext variant of gethostbyaddr"
authorTreehugger Robot <treehugger-gerrit@google.com>
Mon, 22 May 2017 10:06:29 +0000 (10:06 +0000)
committerGerrit Code Review <noreply-gerritcodereview@google.com>
Mon, 22 May 2017 10:06:31 +0000 (10:06 +0000)
124 files changed:
libc/Android.bp
libc/NOTICE
libc/SYSCALLS.TXT
libc/arch-arm/bionic/atexit_legacy.c
libc/arch-arm64/generic/bionic/memchr.S
libc/arch-arm64/generic/bionic/memset.S
libc/arch-arm64/generic/bionic/strchr.S
libc/arch-mips/bionic/cacheflush.cpp
libc/arch-x86/bionic/__set_tls.cpp
libc/async_safe/Android.bp [new file with mode: 0644]
libc/async_safe/async_safe_log.cpp [moved from libc/bionic/libc_logging.cpp with 54% similarity]
libc/async_safe/include/async_safe/log.h [moved from libc/private/libc_logging.h with 62% similarity]
libc/bionic/NetdClient.cpp
libc/bionic/__cxa_pure_virtual.cpp
libc/bionic/__libc_current_sigrtmax.cpp
libc/bionic/__libc_current_sigrtmin.cpp
libc/bionic/__stack_chk_fail.cpp
libc/bionic/abort.cpp
libc/bionic/assert.cpp
libc/bionic/bionic_arc4random.cpp
libc/bionic/bionic_systrace.cpp
libc/bionic/exec.cpp
libc/bionic/grp_pwd.cpp
libc/bionic/icu.cpp
libc/bionic/jemalloc.h
libc/bionic/jemalloc_wrapper.cpp
libc/bionic/libc_init_common.cpp
libc/bionic/malloc_common.cpp
libc/bionic/ndk_cruft.cpp
libc/bionic/new.cpp
libc/bionic/open.cpp
libc/bionic/pthread_attr.cpp
libc/bionic/pthread_create.cpp
libc/bionic/pthread_internal.cpp
libc/bionic/raise.cpp
libc/bionic/setjmp_cookie.cpp
libc/bionic/strerror_r.cpp
libc/bionic/syslog.cpp
libc/bionic/system_properties.cpp
libc/dns/resolv/res_cache.c
libc/dns/resolv/res_send.c
libc/dns/resolv/res_state.c
libc/dns/resolv/res_stats.c
libc/include/android/legacy_signal_inlines.h
libc/include/elf.h
libc/include/malloc.h
libc/include/sys/sem.h
libc/kernel/tools/defaults.py
libc/kernel/uapi/linux/sem.h
libc/libc.arm.map
libc/libc.arm64.map
libc/libc.mips.map
libc/libc.mips64.map
libc/libc.x86.map
libc/libc.x86_64.map
libc/malloc_debug/Android.bp
libc/malloc_debug/backtrace.cpp
libc/malloc_debug/debug_log.h
libc/malloc_debug/exported32.map
libc/malloc_debug/exported64.map
libc/malloc_debug/malloc_debug.cpp
libc/malloc_debug/tests/log_fake.cpp
libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
libc/private/WriteProtected.h
libc/private/bionic_fortify.h
libc/private/bionic_malloc_dispatch.h
libc/seccomp/mips64_policy.cpp
libc/seccomp/seccomp_policy.cpp
libc/stdio/stdio_ext.cpp
libc/stdlib/exit.c
libc/upstream-openbsd/android/include/arc4random.h
libc/upstream-openbsd/android/include/openbsd-compat.h
libdl/libdl.arm.map
libdl/libdl.arm64.map
libdl/libdl.c
libdl/libdl.map.txt
libdl/libdl.mips.map
libdl/libdl.mips64.map
libdl/libdl.x86.map
libdl/libdl.x86_64.map
linker/Android.bp
linker/dlfcn.cpp
linker/linker.cpp
linker/linker.h
linker/linker_allocator.cpp
linker/linker_allocator.h
linker/linker_config.cpp
linker/linker_config.h
linker/linker_debug.h
linker/linker_globals.h
linker/linker_libcxx_support.cpp
linker/linker_logger.cpp
linker/linker_main.cpp
linker/linker_memory.cpp
linker/linker_namespaces.h
linker/linker_sleb128.h
linker/linker_soinfo.cpp
linker/tests/Android.mk
linker/tests/linker_config_test.cpp
tests/Android.bp
tests/async_safe_test.cpp [moved from tests/libc_logging_test.cpp with 55% similarity]
tests/dlext_private.h
tests/dlext_test.cpp
tests/dlfcn_test.cpp
tests/elf_test.cpp [new file with mode: 0644]
tests/fortify_test.cpp
tests/gtest_main.cpp
tests/leak_test.cpp
tests/libs/Android.bp
tests/libs/Android.build.dlext_testzip.mk
tests/libs/bionic_tests_zipalign.cpp
tests/libs/dlopen_testlib_ifunc.cpp [moved from tests/libs/dlopen_testlib_ifunc.c with 65% similarity]
tests/libs/dlopen_testlib_ifunc_variable.cpp [new file with mode: 0644]
tests/libs/dlopen_testlib_ifunc_variable_impl.cpp [new file with mode: 0644]
tests/malloc_test.cpp
tests/pthread_test.cpp
tests/run-on-host.sh
tests/string_test.cpp
tests/sys_ptrace_test.cpp
tests/sys_sem_test.cpp
tests/utils.h
tools/versioner/dependencies [new symlink]
tools/versioner/src/Driver.cpp
tools/versioner/src/versioner.cpp

index e8175f4..3877145 100644 (file)
@@ -1,6 +1,7 @@
 // Define the common source files for all the libc instances
 // =========================================================
 libc_common_src_files = [
+    "async_safe/async_safe_log.cpp",
     "bionic/ether_aton.c",
     "bionic/ether_ntoa.c",
     "bionic/fts.c",
@@ -58,7 +59,10 @@ cc_defaults {
     asflags: libc_common_flags,
     conlyflags: ["-std=gnu99"],
     cppflags: [],
-    include_dirs: ["external/jemalloc/include"],
+    include_dirs: [
+        "bionic/libc/async_safe/include",
+        "external/jemalloc/include",
+    ],
 
     stl: "none",
     system_shared_libs: [],
@@ -609,6 +613,13 @@ cc_library_static {
                     "upstream-openbsd/lib/libc/string/strcat.c",
                 ],
             },
+            cortex_a73: {
+                exclude_srcs: [
+                    "upstream-openbsd/lib/libc/string/memmove.c",
+                    "upstream-openbsd/lib/libc/string/stpcpy.c",
+                    "upstream-openbsd/lib/libc/string/strcat.c",
+                ],
+            },
             denver: {
                 exclude_srcs: [
                     "upstream-openbsd/lib/libc/string/memmove.c",
@@ -965,6 +976,32 @@ cc_library_static {
                     "bionic/__strcpy_chk.cpp",
                 ],
             },
+            cortex_a73: {
+                srcs: [
+                    "arch-arm/cortex-a7/bionic/memset.S",
+
+                    "arch-arm/denver/bionic/memcpy.S",
+                    "arch-arm/denver/bionic/memmove.S",
+                    "arch-arm/denver/bionic/__strcat_chk.S",
+                    "arch-arm/denver/bionic/__strcpy_chk.S",
+
+                    "arch-arm/krait/bionic/strcmp.S",
+
+                    "arch-arm/cortex-a15/bionic/stpcpy.S",
+                    "arch-arm/cortex-a15/bionic/strcat.S",
+                    "arch-arm/cortex-a15/bionic/strcpy.S",
+                    "arch-arm/cortex-a15/bionic/strlen.S",
+                ],
+                exclude_srcs: [
+                    "arch-arm/generic/bionic/memcpy.S",
+                    "arch-arm/generic/bionic/memset.S",
+                    "arch-arm/generic/bionic/strcmp.S",
+                    "arch-arm/generic/bionic/strcpy.S",
+                    "arch-arm/generic/bionic/strlen.c",
+                    "bionic/__strcat_chk.cpp",
+                    "bionic/__strcpy_chk.cpp",
+                ],
+            },
             denver: {
                 srcs: [
                     "arch-arm/denver/bionic/memcpy.S",
@@ -1088,6 +1125,14 @@ cc_library_static {
                     "arch-arm64/generic/bionic/memmove.S",
                 ],
             },
+            cortex_a73: {
+                srcs: [
+                    "arch-arm64/cortex-a53/bionic/memmove.S",
+                ],
+                exclude_srcs: [
+                    "arch-arm64/generic/bionic/memmove.S",
+                ],
+            },
         },
 
         mips: {
@@ -1346,7 +1391,6 @@ cc_library_static {
         "bionic/__libc_current_sigrtmax.cpp",
         "bionic/__libc_current_sigrtmin.cpp",
         "bionic/libc_init_common.cpp",
-        "bionic/libc_logging.cpp",
         "bionic/libgen.cpp",
         "bionic/link.cpp",
         "bionic/locale.cpp",
@@ -1705,7 +1749,7 @@ cc_library {
             "bionic/libc_init_static.cpp",
         ],
         cflags: ["-DLIBC_STATIC"],
-        whole_static_libs: ["libc_init_static", "libjemalloc"],
+        whole_static_libs: ["libc_init_static"],
     },
     shared: {
         srcs: [
@@ -1717,7 +1761,6 @@ cc_library {
             "bionic/NetdClient.cpp",
             "arch-common/bionic/crtend_so.S",
         ],
-        whole_static_libs: ["libjemalloc"],
     },
 
     required: ["tzdata"],
@@ -1740,7 +1783,7 @@ cc_library {
     // you wanted!
 
     shared_libs: ["libdl"],
-    whole_static_libs: ["libc_common"],
+    whole_static_libs: ["libc_common", "libjemalloc"],
 
     nocrt: true,
 
@@ -1793,19 +1836,6 @@ cc_library {
 }
 
 // ========================================================
-// libc_logging.a
-// ========================================================
-cc_library_static {
-    defaults: ["libc_defaults"],
-
-    srcs: [
-        "bionic/libc_logging.cpp",
-    ],
-
-    name: "libc_logging",
-}
-
-// ========================================================
 // libstdc++.so + libstdc++.a
 // ========================================================
 cc_library {
@@ -1818,9 +1848,7 @@ cc_library {
     ],
     name: "libstdc++",
     system_shared_libs: ["libc"],
-    shared: {
-        static_libs: ["libc_logging"],
-    },
+               static_libs: ["libasync_safe"],
 
     //TODO (dimitry): This is to work around b/24465209. Remove after root cause is fixed
     arch: {
@@ -2076,7 +2104,7 @@ ndk_headers {
 }
 
 ndk_headers {
-    name: "libc_android",
+    name: "libc_kernel_android_uapi_linux",
     from: "kernel/android/uapi/linux",
     to: "linux",
     srcs: ["kernel/android/uapi/linux/**/*.h"],
@@ -2084,6 +2112,14 @@ ndk_headers {
 }
 
 ndk_headers {
+    name: "libc_kernel_android_scsi",
+    from: "kernel/android/scsi",
+    to: "scsi",
+    srcs: ["kernel/android/scsi/**/*.h"],
+    license: "NOTICE",
+}
+
+ndk_headers {
     name: "libc_asm_arm",
     from: "kernel/uapi/asm-arm",
     to: "arm-linux-androideabi",
index 1c317a9..fcc3c85 100644 (file)
@@ -1,5 +1,6 @@
-   Copyright (c) 2014, Linaro Limited
-   All rights reserved.
+   Copyright (c) 2014, ARM Limited
+   All rights Reserved.
+   Copyright (c) 2014, Linaro Ltd.
 
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:
@@ -8,9 +9,9 @@
        * Redistributions in binary form must reproduce the above copyright
          notice, this list of conditions and the following disclaimer in the
          documentation and/or other materials provided with the distribution.
-       * Neither the name of the Linaro nor the
-         names of its contributors may be used to endorse or promote products
-         derived from this software without specific prior written permission.
+       * Neither the name of the company nor the names of its contributors
+         may be used to endorse or promote products derived from this
+         software without specific prior written permission.
 
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
 -------------------------------------------------------------------
 
-   strchr - find a character in a string
-
-   Copyright (c) 2014, ARM Limited
-   All rights Reserved.
-   Copyright (c) 2014, Linaro Ltd.
+   Copyright (c) 2014, Linaro Limited
+   All rights reserved.
 
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:
@@ -39,9 +37,9 @@
        * Redistributions in binary form must reproduce the above copyright
          notice, this list of conditions and the following disclaimer in the
          documentation and/or other materials provided with the distribution.
-       * Neither the name of the company nor the names of its contributors
-         may be used to endorse or promote products derived from this
-         software without specific prior written permission.
+       * Neither the name of the Linaro nor the
+         names of its contributors may be used to endorse or promote products
+         derived from this software without specific prior written permission.
 
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@@ -6137,34 +6135,3 @@ THIS SOFTWARE.
 
 -------------------------------------------------------------------
 
-memchr - find a character in a memory zone
-
-Copyright (c) 2014, ARM Limited
-All rights Reserved.
-Copyright (c) 2014, Linaro Ltd.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-    * Neither the name of the company nor the names of its contributors
-      may be used to endorse or promote products derived from this
-      software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
--------------------------------------------------------------------
-
index f98cc61..936f3fd 100644 (file)
@@ -143,7 +143,7 @@ int ___faccessat:faccessat(int, const char*, int)  all
 int ___fchmodat:fchmodat(int, const char*, mode_t)  all
 int fchownat(int, const char*, uid_t, gid_t, int)  all
 int fstatat64|fstatat:fstatat64(int, const char*, struct stat*, int)   arm,mips,x86
-int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int)  arm64,x86_64
+int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int)  arm64,mips64,x86_64
 int linkat(int, const char*, int, const char*, int)  all
 int mkdirat(int, const char*, mode_t)  all
 int mknodat(int, const char*, mode_t, dev_t)  all
@@ -187,7 +187,7 @@ int __statfs64:statfs64(const char*, size_t, struct statfs*)  arm,mips,x86
 int __statfs:statfs(const char*, struct statfs*)  arm64,mips64,x86_64
 
 int     fstat64|fstat:fstat64(int, struct stat*)    arm,mips,x86
-int     fstat64|fstat:fstat(int, struct stat*)    arm64,x86_64
+int     fstat64|fstat:fstat(int, struct stat*)    arm64,mips64,x86_64
 
 # file system
 int     chdir(const char*)              all
@@ -343,7 +343,7 @@ int     __set_tls:__ARM_NR_set_tls(void*)                                 arm
 int     cacheflush:__ARM_NR_cacheflush(long start, long end, long flags)  arm
 
 # MIPS-specific
-int     _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips
+int     _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips,mips64
 int     __set_tls:set_thread_area(void*) mips,mips64
 
 # x86-specific
index c0d704d..7254017 100644 (file)
@@ -29,7 +29,7 @@
 #include <sys/types.h>
 #include <stdio.h>
 
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
 
 /*
  * This source file should only be included by libc.so, its purpose is
@@ -53,7 +53,7 @@ atexit(void (*func)(void))
      */
     static char const warning[] = "WARNING: generic atexit() called from legacy shared library\n";
 
-    __libc_format_log(ANDROID_LOG_WARN, "libc", warning);
+    async_safe_format_log(ANDROID_LOG_WARN, "libc", warning);
     fprintf(stderr, warning);
 
     return (__cxa_atexit((void (*)(void *))func, NULL, NULL));
index a00dd8d..7b7e699 100644 (file)
@@ -1,33 +1,32 @@
 /*
- * memchr - find a character in a memory zone
  *
* Copyright (c) 2014, ARM Limited
* All rights Reserved.
* Copyright (c) 2014, Linaro Ltd.
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of the company nor the names of its contributors
*       may be used to endorse or promote products derived from this
*       software without specific prior written permission.
- *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
  Copyright (c) 2014, ARM Limited
  All rights Reserved.
  Copyright (c) 2014, Linaro Ltd.
+
  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
      * Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
      * Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
      * Neither the name of the company nor the names of its contributors
        may be used to endorse or promote products derived from this
        software without specific prior written permission.
+
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
 
 /* Assumptions:
  *
index 3416cfb..12fc09d 100644 (file)
@@ -80,7 +80,7 @@
 #define tmp1w          w5
 #define tmp2           x6
 #define tmp2w          w6
-#define zva_len                x5
+#define zva_len                x7
 #define zva_lenw       w7
 
 #define L(l) .L ## l
index b54106d..2db0c76 100644 (file)
@@ -1,6 +1,5 @@
 /*
-   strchr - find a character in a string
-
+ *
    Copyright (c) 2014, ARM Limited
    All rights Reserved.
    Copyright (c) 2014, Linaro Ltd.
index 98c0bd4..380ad90 100644 (file)
@@ -29,7 +29,7 @@
 #include <unistd.h>
 #include <sys/cachectl.h>
 
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
 
 // Linux historically defines a cacheflush(3) routine for MIPS
 // with this signature:
@@ -50,7 +50,8 @@ int cacheflush(long start, long end, long /*flags*/) {
     // It looks like this is really a MIPS-style cacheflush call.
     static bool warned = false;
     if (!warned) {
-      __libc_format_log(ANDROID_LOG_WARN, "libc", "cacheflush called with (start,len) instead of (start,end)");
+      async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                            "cacheflush called with (start,len) instead of (start,end)");
       warned = true;
     }
     end += start;
index b26fd56..241d94a 100644 (file)
@@ -32,9 +32,9 @@
 
 #include <asm/ldt.h>
 
-extern "C" int __set_thread_area(struct user_desc*);
+extern "C" int __set_thread_area(user_desc*);
 
-__LIBC_HIDDEN__ void __init_user_desc(struct user_desc* result, bool allocate, void* base_addr) {
+__LIBC_HIDDEN__ void __init_user_desc(user_desc* result, bool allocate, void* base_addr) {
   if (allocate) {
     // Let the kernel choose.
     result->entry_number = -1;
@@ -58,7 +58,7 @@ __LIBC_HIDDEN__ void __init_user_desc(struct user_desc* result, bool allocate, v
 }
 
 extern "C" __LIBC_HIDDEN__ int __set_tls(void* ptr) {
-  struct user_desc tls_descriptor;
+  user_desc tls_descriptor = {};
   __init_user_desc(&tls_descriptor, true, ptr);
 
   int rc = __set_thread_area(&tls_descriptor);
diff --git a/libc/async_safe/Android.bp b/libc/async_safe/Android.bp
new file mode 100644 (file)
index 0000000..9e36d97
--- /dev/null
@@ -0,0 +1,15 @@
+// ========================================================
+// libasync_safe.a
+// ========================================================
+cc_library_static {
+    defaults: ["libc_defaults"],
+    srcs: [
+        "async_safe_log.cpp",
+    ],
+
+    name: "libasync_safe",
+
+    include_dirs: ["bionic/libc"],
+
+    export_include_dirs: ["include"],
+}
similarity index 54%
rename from libc/bionic/libc_logging.cpp
rename to libc/async_safe/async_safe_log.cpp
index 54664d9..372f385 100644 (file)
  * SUCH DAMAGE.
  */
 
-// Relative paths so we can #include this .cpp file for testing.
-#include "../private/CachedProperty.h"
-#include "../private/libc_logging.h"
-#include "../private/ScopedPthreadMutexLocker.h"
-
-#include <android/set_abort_message.h>
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <time.h>
 #include <unistd.h>
 
+#include <android/set_abort_message.h>
+#include <async_safe/log.h>
+
+#include "private/CachedProperty.h"
+#include "private/ScopedPthreadMutexLocker.h"
+
 // Must be kept in sync with frameworks/base/core/java/android/util/EventLog.java.
 enum AndroidEventLogType {
-  EVENT_TYPE_INT      = 0,
-  EVENT_TYPE_LONG     = 1,
-  EVENT_TYPE_STRING   = 2,
-  EVENT_TYPE_LIST     = 3,
-  EVENT_TYPE_FLOAT    = 4,
+  EVENT_TYPE_INT = 0,
+  EVENT_TYPE_LONG = 1,
+  EVENT_TYPE_STRING = 2,
+  EVENT_TYPE_LIST = 3,
+  EVENT_TYPE_FLOAT = 4,
 };
 
 struct BufferOutputStream {
@@ -67,8 +67,7 @@ struct BufferOutputStream {
     pos_[0] = '\0';
   }
 
-  ~BufferOutputStream() {
-  }
+  ~BufferOutputStream() {}
 
   void Send(const char* data, int len) {
     if (len < 0) {
@@ -102,8 +101,7 @@ struct BufferOutputStream {
 
 struct FdOutputStream {
  public:
-  explicit FdOutputStream(int fd) : total(0), fd_(fd) {
-  }
+  explicit FdOutputStream(int fd) : total(0), fd_(fd) {}
 
   void Send(const char* data, int len) {
     if (len < 0) {
@@ -137,23 +135,23 @@ struct FdOutputStream {
  *
  * NOTE: Does *not* handle a sign prefix.
  */
-static unsigned parse_decimal(const char *format, int *ppos) {
-    const char* p = format + *ppos;
-    unsigned result = 0;
-
-    for (;;) {
-        int ch = *p;
-        unsigned d = static_cast<unsigned>(ch - '0');
+static unsigned parse_decimal(const char* format, int* ppos) {
+  const char* p = format + *ppos;
+  unsigned result = 0;
 
-        if (d >= 10U) {
-            break;
-        }
+  for (;;) {
+    int ch = *p;
+    unsigned d = static_cast<unsigned>(ch - '0');
 
-        result = result*10 + d;
-        p++;
+    if (d >= 10U) {
+      break;
     }
-    *ppos = p - format;
-    return result;
+
+    result = result * 10 + d;
+    p++;
+  }
+  *ppos = p - format;
+  return result;
 }
 
 // Writes number 'value' in base 'base' into buffer 'buf' of size 'buf_size' bytes.
@@ -233,182 +231,185 @@ static void SendRepeat(Out& o, char ch, int count) {
 /* Perform formatted output to an output target 'o' */
 template <typename Out>
 static void out_vformat(Out& o, const char* format, va_list args) {
-    int nn = 0;
+  int nn = 0;
+
+  for (;;) {
+    int mm;
+    int padZero = 0;
+    int padLeft = 0;
+    char sign = '\0';
+    int width = -1;
+    int prec = -1;
+    size_t bytelen = sizeof(int);
+    int slen;
+    char buffer[32]; /* temporary buffer used to format numbers */
+
+    char c;
+
+    /* first, find all characters that are not 0 or '%' */
+    /* then send them to the output directly */
+    mm = nn;
+    do {
+      c = format[mm];
+      if (c == '\0' || c == '%') break;
+      mm++;
+    } while (1);
+
+    if (mm > nn) {
+      o.Send(format + nn, mm - nn);
+      nn = mm;
+    }
+
+    /* is this it ? then exit */
+    if (c == '\0') break;
 
+    /* nope, we are at a '%' modifier */
+    nn++;  // skip it
+
+    /* parse flags */
     for (;;) {
-        int mm;
-        int padZero = 0;
-        int padLeft = 0;
-        char sign = '\0';
-        int width = -1;
-        int prec  = -1;
-        size_t bytelen = sizeof(int);
-        int slen;
-        char buffer[32];  /* temporary buffer used to format numbers */
-
-        char  c;
-
-        /* first, find all characters that are not 0 or '%' */
-        /* then send them to the output directly */
-        mm = nn;
-        do {
-            c = format[mm];
-            if (c == '\0' || c == '%')
-                break;
-            mm++;
-        } while (1);
-
-        if (mm > nn) {
-            o.Send(format+nn, mm-nn);
-            nn = mm;
-        }
+      c = format[nn++];
+      if (c == '\0') { /* single trailing '%' ? */
+        c = '%';
+        o.Send(&c, 1);
+        return;
+      } else if (c == '0') {
+        padZero = 1;
+        continue;
+      } else if (c == '-') {
+        padLeft = 1;
+        continue;
+      } else if (c == ' ' || c == '+') {
+        sign = c;
+        continue;
+      }
+      break;
+    }
 
-        /* is this it ? then exit */
-        if (c == '\0')
-            break;
-
-        /* nope, we are at a '%' modifier */
-        nn++;  // skip it
-
-        /* parse flags */
-        for (;;) {
-            c = format[nn++];
-            if (c == '\0') {  /* single trailing '%' ? */
-                c = '%';
-                o.Send(&c, 1);
-                return;
-            }
-            else if (c == '0') {
-                padZero = 1;
-                continue;
-            }
-            else if (c == '-') {
-                padLeft = 1;
-                continue;
-            }
-            else if (c == ' ' || c == '+') {
-                sign = c;
-                continue;
-            }
-            break;
-        }
+    /* parse field width */
+    if ((c >= '0' && c <= '9')) {
+      nn--;
+      width = static_cast<int>(parse_decimal(format, &nn));
+      c = format[nn++];
+    }
 
-        /* parse field width */
-        if ((c >= '0' && c <= '9')) {
-            nn --;
-            width = static_cast<int>(parse_decimal(format, &nn));
-            c = format[nn++];
-        }
+    /* parse precision */
+    if (c == '.') {
+      prec = static_cast<int>(parse_decimal(format, &nn));
+      c = format[nn++];
+    }
 
-        /* parse precision */
-        if (c == '.') {
-            prec = static_cast<int>(parse_decimal(format, &nn));
-            c = format[nn++];
+    /* length modifier */
+    switch (c) {
+      case 'h':
+        bytelen = sizeof(short);
+        if (format[nn] == 'h') {
+          bytelen = sizeof(char);
+          nn += 1;
+        }
+        c = format[nn++];
+        break;
+      case 'l':
+        bytelen = sizeof(long);
+        if (format[nn] == 'l') {
+          bytelen = sizeof(long long);
+          nn += 1;
         }
+        c = format[nn++];
+        break;
+      case 'z':
+        bytelen = sizeof(size_t);
+        c = format[nn++];
+        break;
+      case 't':
+        bytelen = sizeof(ptrdiff_t);
+        c = format[nn++];
+        break;
+      default:;
+    }
 
-        /* length modifier */
-        switch (c) {
-        case 'h':
-            bytelen = sizeof(short);
-            if (format[nn] == 'h') {
-                bytelen = sizeof(char);
-                nn += 1;
-            }
-            c = format[nn++];
-            break;
-        case 'l':
-            bytelen = sizeof(long);
-            if (format[nn] == 'l') {
-                bytelen = sizeof(long long);
-                nn += 1;
-            }
-            c = format[nn++];
-            break;
-        case 'z':
-            bytelen = sizeof(size_t);
-            c = format[nn++];
-            break;
-        case 't':
-            bytelen = sizeof(ptrdiff_t);
-            c = format[nn++];
-            break;
+    /* conversion specifier */
+    const char* str = buffer;
+    if (c == 's') {
+      /* string */
+      str = va_arg(args, const char*);
+      if (str == NULL) {
+        str = "(null)";
+      }
+    } else if (c == 'c') {
+      /* character */
+      /* NOTE: char is promoted to int when passed through the stack */
+      buffer[0] = static_cast<char>(va_arg(args, int));
+      buffer[1] = '\0';
+    } else if (c == 'p') {
+      uint64_t value = reinterpret_cast<uintptr_t>(va_arg(args, void*));
+      buffer[0] = '0';
+      buffer[1] = 'x';
+      format_integer(buffer + 2, sizeof(buffer) - 2, value, 'x');
+    } else if (c == 'd' || c == 'i' || c == 'o' || c == 'u' || c == 'x' || c == 'X') {
+      /* integers - first read value from stack */
+      uint64_t value;
+      int is_signed = (c == 'd' || c == 'i' || c == 'o');
+
+      /* NOTE: int8_t and int16_t are promoted to int when passed
+       *       through the stack
+       */
+      switch (bytelen) {
+        case 1:
+          value = static_cast<uint8_t>(va_arg(args, int));
+          break;
+        case 2:
+          value = static_cast<uint16_t>(va_arg(args, int));
+          break;
+        case 4:
+          value = va_arg(args, uint32_t);
+          break;
+        case 8:
+          value = va_arg(args, uint64_t);
+          break;
         default:
-            ;
-        }
+          return; /* should not happen */
+      }
 
-        /* conversion specifier */
-        const char* str = buffer;
-        if (c == 's') {
-            /* string */
-            str = va_arg(args, const char*);
-            if (str == NULL) {
-                str = "(null)";
-            }
-        } else if (c == 'c') {
-            /* character */
-            /* NOTE: char is promoted to int when passed through the stack */
-            buffer[0] = static_cast<char>(va_arg(args, int));
-            buffer[1] = '\0';
-        } else if (c == 'p') {
-            uint64_t  value = reinterpret_cast<uintptr_t>(va_arg(args, void*));
-            buffer[0] = '0';
-            buffer[1] = 'x';
-            format_integer(buffer + 2, sizeof(buffer) - 2, value, 'x');
-        } else if (c == 'd' || c == 'i' || c == 'o' || c == 'u' || c == 'x' || c == 'X') {
-            /* integers - first read value from stack */
-            uint64_t value;
-            int is_signed = (c == 'd' || c == 'i' || c == 'o');
-
-            /* NOTE: int8_t and int16_t are promoted to int when passed
-             *       through the stack
-             */
-            switch (bytelen) {
-            case 1: value = static_cast<uint8_t>(va_arg(args, int)); break;
-            case 2: value = static_cast<uint16_t>(va_arg(args, int)); break;
-            case 4: value = va_arg(args, uint32_t); break;
-            case 8: value = va_arg(args, uint64_t); break;
-            default: return;  /* should not happen */
-            }
-
-            /* sign extension, if needed */
-            if (is_signed) {
-                int shift = 64 - 8*bytelen;
-                value = static_cast<uint64_t>((static_cast<int64_t>(value << shift)) >> shift);
-            }
-
-            /* format the number properly into our buffer */
-            format_integer(buffer, sizeof(buffer), value, c);
-        } else if (c == '%') {
-            buffer[0] = '%';
-            buffer[1] = '\0';
-        } else {
-            __assert(__FILE__, __LINE__, "conversion specifier unsupported");
-        }
+      /* sign extension, if needed */
+      if (is_signed) {
+        int shift = 64 - 8 * bytelen;
+        value = static_cast<uint64_t>((static_cast<int64_t>(value << shift)) >> shift);
+      }
 
-        /* if we are here, 'str' points to the content that must be
-         * outputted. handle padding and alignment now */
+      /* format the number properly into our buffer */
+      format_integer(buffer, sizeof(buffer), value, c);
+    } else if (c == '%') {
+      buffer[0] = '%';
+      buffer[1] = '\0';
+    } else {
+      __assert(__FILE__, __LINE__, "conversion specifier unsupported");
+    }
 
-        slen = strlen(str);
+    /* if we are here, 'str' points to the content that must be
+     * outputted. handle padding and alignment now */
 
-        if (sign != '\0' || prec != -1) {
-            __assert(__FILE__, __LINE__, "sign/precision unsupported");
-        }
+    slen = strlen(str);
 
-        if (slen < width && !padLeft) {
-            char padChar = padZero ? '0' : ' ';
-            SendRepeat(o, padChar, width - slen);
-        }
+    if (sign != '\0' || prec != -1) {
+      __assert(__FILE__, __LINE__, "sign/precision unsupported");
+    }
 
-        o.Send(str, slen);
+    if (slen < width && !padLeft) {
+      char padChar = padZero ? '0' : ' ';
+      SendRepeat(o, padChar, width - slen);
+    }
 
-        if (slen < width && padLeft) {
-            char padChar = padZero ? '0' : ' ';
-            SendRepeat(o, padChar, width - slen);
-        }
+    o.Send(str, slen);
+
+    if (slen < width && padLeft) {
+      char padChar = padZero ? '0' : ' ';
+      SendRepeat(o, padChar, width - slen);
     }
+  }
 }
 
-int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...) {
+int async_safe_format_buffer(char* buffer, size_t buffer_size, const char* format, ...) {
   BufferOutputStream os(buffer, buffer_size);
   va_list args;
   va_start(args, format);
@@ -417,14 +418,14 @@ int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, .
   return os.total;
 }
 
-int __libc_format_buffer_va_list(char* buffer, size_t buffer_size, const char* format,
-                                 va_list args) {
+int async_safe_format_buffer_va_list(char* buffer, size_t buffer_size, const char* format,
+                                     va_list args) {
   BufferOutputStream os(buffer, buffer_size);
   out_vformat(os, format, args);
   return os.total;
 }
 
-int __libc_format_fd(int fd, const char* format, ...) {
+int async_safe_format_fd(int fd, const char* format, ...) {
   FdOutputStream os(fd);
   va_list args;
   va_start(args, format);
@@ -433,7 +434,7 @@ int __libc_format_fd(int fd, const char* format, ...) {
   return os.total;
 }
 
-static int __libc_write_stderr(const char* tag, const char* msg) {
+static int write_stderr(const char* tag, const char* msg) {
   iovec vec[4];
   vec[0].iov_base = const_cast<char*>(tag);
   vec[0].iov_len = strlen(tag);
@@ -448,7 +449,7 @@ static int __libc_write_stderr(const char* tag, const char* msg) {
   return result;
 }
 
-static int __libc_open_log_socket() {
+static int open_log_socket() {
   // ToDo: Ideally we want this to fail if the gid of the current
   // process is AID_LOGD, but will have to wait until we have
   // registered this in private/android_filesystem_config.h. We have
@@ -461,7 +462,7 @@ static int __libc_open_log_socket() {
   }
 
   union {
-    struct sockaddr    addr;
+    struct sockaddr addr;
     struct sockaddr_un addrUn;
   } u;
   memset(&u, 0, sizeof(u));
@@ -476,7 +477,7 @@ static int __libc_open_log_socket() {
   return log_fd;
 }
 
-static clockid_t __android_log_clockid() {
+static clockid_t log_clockid() {
   static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
   ScopedPthreadMutexLocker locker(&mutex);
 
@@ -489,16 +490,16 @@ static clockid_t __android_log_clockid() {
   return (tolower(ch) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
 }
 
-struct log_time { // Wire format
+struct log_time {  // Wire format
   uint32_t tv_sec;
   uint32_t tv_nsec;
 };
 
-int __libc_write_log(int priority, const char* tag, const char* msg) {
-  int main_log_fd = __libc_open_log_socket();
+int async_safe_write_log(int priority, const char* tag, const char* msg) {
+  int main_log_fd = open_log_socket();
   if (main_log_fd == -1) {
     // Try stderr instead.
-    return __libc_write_stderr(tag, msg);
+    return write_stderr(tag, msg);
   }
 
   iovec vec[6];
@@ -509,7 +510,7 @@ int __libc_write_log(int priority, const char* tag, const char* msg) {
   vec[1].iov_base = &tid;
   vec[1].iov_len = sizeof(tid);
   timespec ts;
-  clock_gettime(__android_log_clockid(), &ts);
+  clock_gettime(log_clockid(), &ts);
   log_time realtime_ts;
   realtime_ts.tv_sec = ts.tv_sec;
   realtime_ts.tv_nsec = ts.tv_nsec;
@@ -528,22 +529,22 @@ int __libc_write_log(int priority, const char* tag, const char* msg) {
   return result;
 }
 
-int __libc_format_log_va_list(int priority, const char* tag, const char* format, va_list args) {
+int async_safe_format_log_va_list(int priority, const char* tag, const char* format, va_list args) {
   char buffer[1024];
   BufferOutputStream os(buffer, sizeof(buffer));
   out_vformat(os, format, args);
-  return __libc_write_log(priority, tag, buffer);
+  return async_safe_write_log(priority, tag, buffer);
 }
 
-int __libc_format_log(int priority, const char* tag, const char* format, ...) {
+int async_safe_format_log(int priority, const char* tag, const char* format, ...) {
   va_list args;
   va_start(args, format);
-  int result = __libc_format_log_va_list(priority, tag, format, args);
+  int result = async_safe_format_log_va_list(priority, tag, format, args);
   va_end(args);
   return result;
 }
 
-static void __libc_fatal_va_list(const char* prefix, const char* format, va_list args) {
+void async_safe_fatal_va_list(const char* prefix, const char* format, va_list args) {
   char msg[1024];
   BufferOutputStream os(msg, sizeof(msg));
 
@@ -556,29 +557,20 @@ static void __libc_fatal_va_list(const char* prefix, const char* format, va_list
 
   // Log to stderr for the benefit of "adb shell" users and gtests.
   struct iovec iov[2] = {
-    { msg, os.total },
-    { const_cast<char*>("\n"), 1 },
+      {msg, os.total}, {const_cast<char*>("\n"), 1},
   };
   TEMP_FAILURE_RETRY(writev(2, iov, 2));
 
   // Log to the log for the benefit of regular app developers (whose stdout and stderr are closed).
-  __libc_write_log(ANDROID_LOG_FATAL, "libc", msg);
+  async_safe_write_log(ANDROID_LOG_FATAL, "libc", msg);
 
   android_set_abort_message(msg);
 }
 
-void __libc_fatal(const char* fmt, ...) {
-  va_list args;
-  va_start(args, fmt);
-  __libc_fatal_va_list(nullptr, fmt, args);
-  va_end(args);
-  abort();
-}
-
-void __fortify_fatal(const char* fmt, ...) {
+void async_safe_fatal(const char* fmt, ...) {
   va_list args;
   va_start(args, fmt);
-  __libc_fatal_va_list("FORTIFY", fmt, args);
+  async_safe_fatal_va_list(nullptr, fmt, args);
   va_end(args);
   abort();
 }
similarity index 62%
rename from libc/private/libc_logging.h
rename to libc/async_safe/include/async_safe/log.h
index 73bc9a5..f93f672 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifndef _LIBC_LOGGING_H
-#define _LIBC_LOGGING_H
+#ifndef _ASYNC_SAFE_LOG_LOG_H
+#define _ASYNC_SAFE_LOG_LOG_H
 
 #include <sys/cdefs.h>
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdint.h>
 
+// These functions do not allocate memory to send data to the log.
+
 __BEGIN_DECLS
 
 enum {
@@ -63,10 +65,16 @@ enum {
 };
 
 // Formats a message to the log (priority 'fatal'), then aborts.
-__noreturn void __libc_fatal(const char* _Nonnull, ...) __printflike(1, 2);
+__noreturn void async_safe_fatal(const char* _Nonnull fmt, ...) __printflike(1, 2);
 
-// Formats a message to the log (priority 'fatal'), prefixed by "FORTIFY: ", then aborts.
-__noreturn void __fortify_fatal(const char* _Nonnull, ...) __printflike(1, 2);
+// This function does return, so callers that want to abort, must do so themselves.
+#if defined(__arm__) || defined(__aarch64__) || defined(__x86_64__)
+void async_safe_fatal_va_list(
+    const char* _Nullable prefix, const char* _Nonnull fmt, va_list);
+#else // defined(__mips__) || defined(__i386__)
+void async_safe_fatal_va_list(
+    const char* _Nullable prefix, const char* _Nonnull fmt, va_list _Nonnull);
+#endif
 
 //
 // Formatting routines for the C library's internal debugging.
@@ -74,29 +82,31 @@ __noreturn void __fortify_fatal(const char* _Nonnull, ...) __printflike(1, 2);
 // These are async signal safe, so they can be called from signal handlers.
 //
 
-int __libc_format_buffer(char* _Nonnull buf, size_t size, const char* _Nonnull fmt, ...) __printflike(3, 4);
+int async_safe_format_buffer(char* _Nonnull buf, size_t size, const char* _Nonnull fmt, ...) __printflike(3, 4);
 
 #if defined(__arm__) || defined(__aarch64__) || defined(__x86_64__)
-int __libc_format_buffer_va_list(char* _Nonnull buffer, size_t buffer_size,
-                                 const char* _Nonnull format, va_list args);
+int async_safe_format_buffer_va_list(
+    char* _Nonnull buffer, size_t buffer_size, const char* _Nonnull format, va_list args);
 #else // defined(__mips__) || defined(__i386__)
-int __libc_format_buffer_va_list(char* _Nonnull buffer, size_t buffer_size,
-                                 const char* _Nonnull format, va_list _Nonnull args);
+int async_safe_format_buffer_va_list(
+    char* _Nonnull buffer, size_t buffer_size, const char* _Nonnull format, va_list _Nonnull args);
 #endif
 
-int __libc_format_fd(int fd, const char* _Nonnull format , ...) __printflike(2, 3);
-int __libc_format_log(int pri, const char* _Nonnull tag, const char* _Nonnull fmt, ...) __printflike(3, 4);
+int async_safe_format_fd(int fd, const char* _Nonnull format , ...) __printflike(2, 3);
+int async_safe_format_log(int pri, const char* _Nonnull tag, const char* _Nonnull fmt, ...) __printflike(3, 4);
 #if defined(__arm__) || defined(__aarch64__) || defined(__x86_64__)
-int __libc_format_log_va_list(int pri, const char* _Nonnull tag, const char* _Nonnull fmt, va_list ap);
+int async_safe_format_log_va_list(
+    int pri, const char* _Nonnull tag, const char* _Nonnull fmt, va_list ap);
 #else // defined(__mips__) || defined(__i386__)
-int __libc_format_log_va_list(int pri, const char* _Nonnull tag, const char* _Nonnull fmt, va_list _Nonnull ap);
+int async_safe_format_log_va_list(
+    int pri, const char* _Nonnull tag, const char* _Nonnull fmt, va_list _Nonnull ap);
 #endif
-int __libc_write_log(int pri, const char* _Nonnull tag, const char* _Nonnull msg);
+int async_safe_write_log(int pri, const char* _Nonnull tag, const char* _Nonnull msg);
 
 #define CHECK(predicate) \
   do { \
     if (!(predicate)) { \
-      __libc_fatal("%s:%d: %s CHECK '" #predicate "' failed", \
+      async_safe_fatal("%s:%d: %s CHECK '" #predicate "' failed", \
           __FILE__, __LINE__, __FUNCTION__); \
     } \
   } while(0)
index b117d72..a1071d2 100644 (file)
@@ -18,7 +18,8 @@
 #error NetdClient.cpp should NOT be included in static libc builds.
 #endif
 
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
+
 #include "private/NetdClientDispatch.h"
 
 #include <dlfcn.h>
@@ -53,6 +54,6 @@ static pthread_once_t netdClientInitOnce = PTHREAD_ONCE_INIT;
 
 extern "C" __LIBC_HIDDEN__ void netdClientInit() {
     if (pthread_once(&netdClientInitOnce, netdClientInitImpl)) {
-        __libc_format_log(ANDROID_LOG_ERROR, "netdClient", "Failed to initialize netd_client");
+        async_safe_format_log(ANDROID_LOG_ERROR, "netdClient", "Failed to initialize netd_client");
     }
 }
index 30b581f..00a4d90 100644 (file)
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include <private/libc_logging.h>
+#include <async_safe/log.h>
 
 extern "C" void __cxa_pure_virtual() {
-  __libc_fatal("Pure virtual function called. Are you calling virtual methods from a destructor?");
+  async_safe_fatal("Pure virtual function called. Are you calling virtual methods from a destructor?");
 }
index 27fcb35..32179bb 100644 (file)
@@ -29,5 +29,7 @@
 #include <signal.h>
 
 int __libc_current_sigrtmax(void) {
+  // If you change this, also change __ndk_legacy___libc_current_sigrtmax
+  // in <android/legacy_signal_inlines.h> to match.
   return __SIGRTMAX;
 }
index 7c93267..f3b2bf6 100644 (file)
@@ -34,5 +34,7 @@
 // __SIGRTMIN + 3 is reserved for triggering native stack dumps.
 
 int __libc_current_sigrtmin(void) {
+  // If you change this, also change __ndk_legacy___libc_current_sigrtmin
+  // in <android/legacy_signal_inlines.h> to match.
   return __SIGRTMIN + 4;
 }
index cb039cf..5f5a5f6 100644 (file)
 
 #include <stdlib.h>
 
+#include <async_safe/log.h>
+
 #include "private/bionic_ssp.h"
-#include "private/libc_logging.h"
 
 void __stack_chk_fail() {
-  __libc_fatal("stack corruption detected (-fstack-protector)");
+  async_safe_fatal("stack corruption detected (-fstack-protector)");
 }
index cf8fa8e..3ba83d1 100644 (file)
 
 #include <signal.h>
 #include <stdlib.h>
+#include <sys/syscall.h>
 #include <unistd.h>
 
 void abort() {
+  // Protect ourselves against stale cached PID/TID values by fetching them via syscall.
+  // http://b/37769298
+  pid_t pid = syscall(__NR_getpid);
+  pid_t tid = syscall(__NR_gettid);
+
   // Don't block SIGABRT to give any signal handler a chance; we ignore
   // any errors -- X311J doesn't allow abort to return anyway.
   sigset_t mask;
@@ -39,7 +45,8 @@ void abort() {
   sigdelset(&mask, SIGABRT);
   sigprocmask(SIG_SETMASK, &mask, NULL);
 
-  tgkill(getpid(), gettid(), SIGABRT);
+  // Use tgkill directly instead of raise, to avoid inserting spurious stack frames.
+  tgkill(pid, tid, SIGABRT);
 
   // If SIGABRT ignored, or caught and the handler returns,
   // remove the SIGABRT signal handler and raise SIGABRT again.
@@ -50,7 +57,7 @@ void abort() {
   sigaction(SIGABRT, &sa, &sa);
   sigprocmask(SIG_SETMASK, &mask, NULL);
 
-  tgkill(getpid(), gettid(), SIGABRT);
+  tgkill(pid, tid, SIGABRT);
 
   // If we get this far, just exit.
   _exit(127);
index 985fc38..41831cb 100644 (file)
 
 #include <assert.h>
 
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
 
 void __assert(const char* file, int line, const char* failed_expression) {
-  __libc_fatal("%s:%d: assertion \"%s\" failed", file, line, failed_expression);
+  async_safe_fatal("%s:%d: assertion \"%s\" failed", file, line, failed_expression);
 }
 
 void __assert2(const char* file, int line, const char* function, const char* failed_expression) {
-  __libc_fatal("%s:%d: %s: assertion \"%s\" failed", file, line, function, failed_expression);
+  async_safe_fatal("%s:%d: %s: assertion \"%s\" failed", file, line, function, failed_expression);
 }
 
 extern "C" __LIBC_HIDDEN__ void longjmperror() {
-  __libc_fatal("longjmp botch");
+  async_safe_fatal("longjmp botch");
 }
index ba3b4e1..a4842f6 100644 (file)
@@ -35,8 +35,9 @@
 #include <syscall.h>
 #include <unistd.h>
 
+#include <async_safe/log.h>
+
 #include "private/KernelArgumentBlock.h"
-#include "private/libc_logging.h"
 
 bool __libc_arc4random_has_unlimited_entropy() {
   static bool have_urandom = access("/dev/urandom", R_OK) == 0;
@@ -53,8 +54,8 @@ void __libc_safe_arc4random_buf(void* buf, size_t n, KernelArgumentBlock& args)
 
   static size_t at_random_bytes_consumed = 0;
   if (at_random_bytes_consumed + n > 16) {
-    __libc_fatal("ran out of AT_RANDOM bytes, have %zu, requested %zu",
-                 16 - at_random_bytes_consumed, n);
+    async_safe_fatal("ran out of AT_RANDOM bytes, have %zu, requested %zu",
+                     16 - at_random_bytes_consumed, n);
   }
 
   memcpy(buf, reinterpret_cast<char*>(args.getauxval(AT_RANDOM)) + at_random_bytes_consumed, n);
index 5699f6e..970a92b 100644 (file)
@@ -23,7 +23,6 @@
 #include "private/bionic_lock.h"
 #include "private/bionic_systrace.h"
 #include "private/CachedProperty.h"
-#include "private/libc_logging.h"
 
 #include <cutils/trace.h> // For ATRACE_TAG_BIONIC.
 
index c43eb90..2001106 100644 (file)
@@ -72,19 +72,25 @@ static int __execl(const char* name, const char* argv0, ExecVariant variant, va_
 int execl(const char* name, const char* arg, ...) {
   va_list ap;
   va_start(ap, arg);
-  return __execl(name, arg, kIsExecL, ap);
+  int result = __execl(name, arg, kIsExecL, ap);
+  va_end(ap);
+  return result;
 }
 
 int execle(const char* name, const char* arg, ...) {
   va_list ap;
   va_start(ap, arg);
-  return __execl(name, arg, kIsExecLE, ap);
+  int result = __execl(name, arg, kIsExecLE, ap);
+  va_end(ap);
+  return result;
 }
 
 int execlp(const char* name, const char* arg, ...) {
   va_list ap;
   va_start(ap, arg);
-  return __execl(name, arg, kIsExecLP, ap);
+  int result = __execl(name, arg, kIsExecLP, ap);
+  va_end(ap);
+  return result;
 }
 
 int execv(const char* name, char* const* argv) {
index 5d565c4..078a0b3 100644 (file)
@@ -41,7 +41,6 @@
 #include "private/bionic_macros.h"
 #include "private/grp_pwd.h"
 #include "private/ErrnoRestorer.h"
-#include "private/libc_logging.h"
 
 // Generated android_ids array
 #include "generated_android_ids.h"
index abc0eec..944a3f8 100644 (file)
@@ -33,7 +33,7 @@
 #include <pthread.h>
 #include <stdlib.h>
 
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
 
 // Allowed icu4c version numbers are in the range [44, 999].
 // Gingerbread's icu4c 4.4 is the minimum supported ICU version.
@@ -68,7 +68,7 @@ static bool __find_icu() {
   free(namelist);
 
   if (max_version == -1 || max_version < ICUDATA_VERSION_MIN) {
-    __libc_write_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't find an ICU .dat file");
+    async_safe_write_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't find an ICU .dat file");
     return false;
   }
 
@@ -76,7 +76,8 @@ static bool __find_icu() {
 
   g_libicuuc_handle = dlopen("libicuuc.so", RTLD_LOCAL);
   if (g_libicuuc_handle == nullptr) {
-    __libc_format_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't open libicuuc.so: %s", dlerror());
+    async_safe_format_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't open libicuuc.so: %s",
+                          dlerror());
     return false;
   }
 
@@ -93,7 +94,8 @@ void* __find_icu_symbol(const char* symbol_name) {
 
   void* symbol = dlsym(g_libicuuc_handle, versioned_symbol_name);
   if (symbol == nullptr) {
-    __libc_format_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't find %s", versioned_symbol_name);
+    async_safe_format_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't find %s",
+                          versioned_symbol_name);
   }
   return symbol;
 }
index fceb323..f7e8770 100644 (file)
@@ -26,6 +26,7 @@
 __BEGIN_DECLS
 
 struct mallinfo je_mallinfo();
+int je_mallopt(int, int);
 int je_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*);
 void je_malloc_disable();
 void je_malloc_enable();
index e33d560..266b966 100644 (file)
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <malloc.h>
 #include <sys/param.h>
 #include <unistd.h>
 
@@ -46,3 +47,38 @@ void* je_memalign_round_up_boundary(size_t boundary, size_t size) {
   }
   return je_memalign(boundary, size);
 }
+
+int je_mallopt(int param, int value) {
+  // The only parameter we currently understand is M_DECAY_TIME.
+  if (param == M_DECAY_TIME) {
+    // Only support setting the value to 1 or 0.
+    ssize_t decay_time;
+    if (value) {
+      decay_time = 1;
+    } else {
+      decay_time = 0;
+    }
+    // First get the total number of arenas.
+    unsigned narenas;
+    size_t sz = sizeof(unsigned);
+    if (je_mallctl("arenas.narenas", &narenas, &sz, nullptr, 0) != 0) {
+      return 0;
+    }
+
+    // Set the decay time for any arenas that will be created in the future.
+    if (je_mallctl("arenas.decay_time", nullptr, nullptr, &decay_time, sizeof(decay_time)) != 0) {
+      return 0;
+    }
+
+    // Change the decay on the already existing arenas.
+    char buffer[100];
+    for (unsigned i = 0; i < narenas; i++) {
+      snprintf(buffer, sizeof(buffer), "arena.%d.decay_time", i);
+      if (je_mallctl(buffer, nullptr, nullptr, &decay_time, sizeof(decay_time)) != 0) {
+        break;
+      }
+    }
+    return 1;
+  }
+  return 0;
+}
index 970a49c..e051762 100644 (file)
 #include <sys/time.h>
 #include <unistd.h>
 
+#include <async_safe/log.h>
+
 #include "private/KernelArgumentBlock.h"
 #include "private/WriteProtected.h"
 #include "private/bionic_auxv.h"
 #include "private/bionic_globals.h"
 #include "private/bionic_tls.h"
-#include "private/libc_logging.h"
 #include "private/thread_private.h"
 #include "pthread_internal.h"
 
@@ -69,7 +70,9 @@ __attribute__((__naked__)) static void __libc_int0x80() {
 __LIBC_HIDDEN__ void* __libc_sysinfo = reinterpret_cast<void*>(__libc_int0x80);
 
 __LIBC_HIDDEN__ void __libc_init_sysinfo(KernelArgumentBlock& args) {
-  __libc_sysinfo = reinterpret_cast<void*>(args.getauxval(AT_SYSINFO));
+  // Running under valgrind, AT_SYSINFO won't be set.
+  void* at_sysinfo = reinterpret_cast<void*>(args.getauxval(AT_SYSINFO));
+  if (at_sysinfo != nullptr) __libc_sysinfo = at_sysinfo;
 }
 
 // TODO: lose this function and just access __libc_sysinfo directly.
@@ -96,8 +99,8 @@ void __libc_init_globals(KernelArgumentBlock& args) {
 #if !defined(__LP64__)
 static void __check_max_thread_id() {
   if (gettid() > 65535) {
-    __libc_fatal("Limited by the size of pthread_mutex_t, 32 bit bionic libc only accepts "
-                 "pid <= 65535, but current pid is %d", gettid());
+    async_safe_fatal("Limited by the size of pthread_mutex_t, 32 bit bionic libc only accepts "
+                     "pid <= 65535, but current pid is %d", gettid());
   }
 }
 #endif
@@ -303,11 +306,11 @@ static void __initialize_personality() {
 #if !defined(__LP64__)
   int old_value = personality(0xffffffff);
   if (old_value == -1) {
-    __libc_fatal("error getting old personality value: %s", strerror(errno));
+    async_safe_fatal("error getting old personality value: %s", strerror(errno));
   }
 
   if (personality((static_cast<unsigned int>(old_value) & ~PER_MASK) | PER_LINUX32) == -1) {
-    __libc_fatal("error setting PER_LINUX32 personality: %s", strerror(errno));
+    async_safe_fatal("error setting PER_LINUX32 personality: %s", strerror(errno));
   }
 #endif
 }
index 3fceb71..1f201d1 100644 (file)
@@ -68,6 +68,7 @@ static constexpr MallocDispatch __libc_malloc_default_dispatch
     Malloc(iterate),
     Malloc(malloc_disable),
     Malloc(malloc_enable),
+    Malloc(mallopt),
   };
 
 // In a VM process, this is set to 1 after fork()ing out of zygote.
@@ -101,6 +102,14 @@ extern "C" struct mallinfo mallinfo() {
   return Malloc(mallinfo)();
 }
 
+extern "C" int mallopt(int param, int value) {
+  auto _mallopt = __libc_globals->malloc_dispatch.mallopt;
+  if (__predict_false(_mallopt != nullptr)) {
+    return _mallopt(param, value);
+  }
+  return Malloc(mallopt)(param, value);
+}
+
 extern "C" void* malloc(size_t bytes) {
   auto _malloc = __libc_globals->malloc_dispatch.malloc;
   if (__predict_false(_malloc != nullptr)) {
@@ -167,7 +176,7 @@ extern "C" void* valloc(size_t bytes) {
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <private/libc_logging.h>
+#include <async_safe/log.h>
 #include <sys/system_properties.h>
 
 extern "C" int __cxa_atexit(void (*func)(void *), void *arg, void *dso);
@@ -188,9 +197,9 @@ static ssize_t (*g_debug_malloc_backtrace_func)(void*, uintptr_t*, size_t);
 // Log functions
 // =============================================================================
 #define error_log(format, ...)  \
-    __libc_format_log(ANDROID_LOG_ERROR, "libc", (format), ##__VA_ARGS__ )
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc", (format), ##__VA_ARGS__ )
 #define info_log(format, ...)  \
-    __libc_format_log(ANDROID_LOG_INFO, "libc", (format), ##__VA_ARGS__ )
+    async_safe_format_log(ANDROID_LOG_INFO, "libc", (format), ##__VA_ARGS__ )
 // =============================================================================
 
 // =============================================================================
@@ -247,6 +256,10 @@ static bool InitMalloc(void* malloc_impl_handler, MallocDispatch* table, const c
                                           prefix, "mallinfo")) {
     return false;
   }
+  if (!InitMallocFunction<MallocMallopt>(malloc_impl_handler, &table->mallopt,
+                                         prefix, "mallopt")) {
+    return false;
+  }
   if (!InitMallocFunction<MallocMalloc>(malloc_impl_handler, &table->malloc,
                                         prefix, "malloc")) {
     return false;
index 29565a2..dbacf18 100644 (file)
 #include <wchar.h>
 
 #include "private/bionic_macros.h"
-#include "private/libc_logging.h"
 
 extern "C" {
 
 // LP64 doesn't need to support any legacy cruft.
 #if !defined(__LP64__)
 
+// By the time any NDK-built code is running, there are plenty of threads.
+int __isthreaded = 1;
+
 // These were accidentally declared in <unistd.h> because we stupidly used to inline
 // getpagesize() and __getpageshift(). Needed for backwards compatibility with old NDK apps.
 unsigned int __page_size = PAGE_SIZE;
index 76c46ee..9499ff5 100644 (file)
 #include <errno.h>
 #include <stdlib.h>
 
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
 
 const std::nothrow_t std::nothrow = {};
 
 void* operator new(std::size_t size) {
     void* p = malloc(size);
     if (p == NULL) {
-        __libc_fatal("new failed to allocate %zu bytes", size);
+        async_safe_fatal("new failed to allocate %zu bytes", size);
     }
     return p;
 }
@@ -34,7 +34,7 @@ void* operator new(std::size_t size) {
 void* operator new[](std::size_t size) {
     void* p = malloc(size);
     if (p == NULL) {
-        __libc_fatal("new[] failed to allocate %zu bytes", size);
+        async_safe_fatal("new[] failed to allocate %zu bytes", size);
     }
     return p;
 }
index 2daa21f..6d179c4 100644 (file)
@@ -31,7 +31,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-#include "private/libc_logging.h"
+#include "private/bionic_fortify.h"
 
 extern "C" int __openat(int, const char*, int, int);
 
index cfa58fc..4b6a8f2 100644 (file)
 #include <sys/resource.h>
 #include <unistd.h>
 
+#include <async_safe/log.h>
+
 #include "private/bionic_string_utils.h"
 #include "private/ErrnoRestorer.h"
-#include "private/libc_logging.h"
 #include "pthread_internal.h"
 
 int pthread_attr_init(pthread_attr_t* attr) {
@@ -117,12 +118,12 @@ int pthread_attr_setstack(pthread_attr_t* attr, void* stack_base, size_t stack_s
 static uintptr_t __get_main_stack_startstack() {
   FILE* fp = fopen("/proc/self/stat", "re");
   if (fp == nullptr) {
-    __libc_fatal("couldn't open /proc/self/stat: %s", strerror(errno));
+    async_safe_fatal("couldn't open /proc/self/stat: %s", strerror(errno));
   }
 
   char line[BUFSIZ];
   if (fgets(line, sizeof(line), fp) == nullptr) {
-    __libc_fatal("couldn't read /proc/self/stat: %s", strerror(errno));
+    async_safe_fatal("couldn't read /proc/self/stat: %s", strerror(errno));
   }
 
   fclose(fp);
@@ -138,7 +139,7 @@ static uintptr_t __get_main_stack_startstack() {
              "%*u %*u %*u %*u %*u %*u %*u "
              "%*d %*d %*d %*d %*d %*d "
              "%*u %*u %*d %*u %*u %*u %" SCNuPTR, &startstack) != 1) {
-    __libc_fatal("couldn't parse /proc/self/stat");
+    async_safe_fatal("couldn't parse /proc/self/stat");
   }
 
   return startstack;
@@ -163,7 +164,7 @@ static int __pthread_attr_getstack_main_thread(void** stack_base, size_t* stack_
   // Hunt for the region that contains that address.
   FILE* fp = fopen("/proc/self/maps", "re");
   if (fp == nullptr) {
-    __libc_fatal("couldn't open /proc/self/maps");
+    async_safe_fatal("couldn't open /proc/self/maps");
   }
   char line[BUFSIZ];
   while (fgets(line, sizeof(line), fp) != NULL) {
@@ -177,7 +178,7 @@ static int __pthread_attr_getstack_main_thread(void** stack_base, size_t* stack_
       }
     }
   }
-  __libc_fatal("Stack not found in /proc/self/maps");
+  async_safe_fatal("Stack not found in /proc/self/maps");
 }
 
 int pthread_attr_getstack(const pthread_attr_t* attr, void** stack_base, size_t* stack_size) {
index 6b3e148..9197aa3 100644 (file)
 
 #include "pthread_internal.h"
 
+#include <async_safe/log.h>
+
 #include "private/bionic_macros.h"
 #include "private/bionic_prctl.h"
 #include "private/bionic_ssp.h"
 #include "private/bionic_tls.h"
-#include "private/libc_logging.h"
 #include "private/ErrnoRestorer.h"
 
 // x86 uses segment descriptors rather than a direct pointer to TLS.
@@ -48,8 +49,6 @@
 void __init_user_desc(struct user_desc*, bool, void*);
 #endif
 
-extern "C" int __isthreaded;
-
 // This code is used both by each new pthread and the code that initializes the main thread.
 void __init_tls(pthread_internal_t* thread) {
   // Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
@@ -60,13 +59,13 @@ void __init_tls(pthread_internal_t* thread) {
   size_t allocation_size = BIONIC_TLS_SIZE + 2 * PAGE_SIZE;
   void* allocation = mmap(nullptr, allocation_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
   if (allocation == MAP_FAILED) {
-    __libc_fatal("failed to allocate TLS");
+    async_safe_fatal("failed to allocate TLS");
   }
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, allocation, allocation_size, "bionic TLS guard page");
 
   thread->bionic_tls = reinterpret_cast<bionic_tls*>(static_cast<char*>(allocation) + PAGE_SIZE);
   if (mprotect(thread->bionic_tls, BIONIC_TLS_SIZE, PROT_READ | PROT_WRITE) != 0) {
-    __libc_fatal("failed to mprotect TLS");
+    async_safe_fatal("failed to mprotect TLS");
   }
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, thread->bionic_tls, BIONIC_TLS_SIZE, "bionic TLS");
 }
@@ -118,8 +117,8 @@ int __init_thread(pthread_internal_t* thread) {
       // For backwards compatibility reasons, we only report failures on 64-bit devices.
       error = errno;
 #endif
-      __libc_format_log(ANDROID_LOG_WARN, "libc",
-                        "pthread_create sched_setscheduler call failed: %s", strerror(errno));
+      async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                            "pthread_create sched_setscheduler call failed: %s", strerror(errno));
     }
   }
 
@@ -134,7 +133,7 @@ static void* __create_thread_mapped_space(size_t mmap_size, size_t stack_guard_s
   int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
   void* space = mmap(NULL, mmap_size, prot, flags, -1, 0);
   if (space == MAP_FAILED) {
-    __libc_format_log(ANDROID_LOG_WARN,
+    async_safe_format_log(ANDROID_LOG_WARN,
                       "libc",
                       "pthread_create failed: couldn't allocate %zu-bytes mapped space: %s",
                       mmap_size, strerror(errno));
@@ -144,9 +143,9 @@ static void* __create_thread_mapped_space(size_t mmap_size, size_t stack_guard_s
   // Stack is at the lower end of mapped space, stack guard region is at the lower end of stack.
   // Set the stack guard region to PROT_NONE, so we can detect thread stack overflow.
   if (mprotect(space, stack_guard_size, PROT_NONE) == -1) {
-    __libc_format_log(ANDROID_LOG_WARN, "libc",
-                      "pthread_create failed: couldn't mprotect PROT_NONE %zu-byte stack guard region: %s",
-                      stack_guard_size, strerror(errno));
+    async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                          "pthread_create failed: couldn't mprotect PROT_NONE %zu-byte stack guard region: %s",
+                          stack_guard_size, strerror(errno));
     munmap(space, mmap_size);
     return NULL;
   }
@@ -229,9 +228,6 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
                    void* (*start_routine)(void*), void* arg) {
   ErrnoRestorer errno_restorer;
 
-  // Inform the rest of the C library that at least one thread was created.
-  __isthreaded = 1;
-
   pthread_attr_t thread_attr;
   if (attr == NULL) {
     pthread_attr_init(&thread_attr);
@@ -281,7 +277,8 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
     if (thread->mmap_size != 0) {
       munmap(thread->attr.stack_base, thread->mmap_size);
     }
-    __libc_format_log(ANDROID_LOG_WARN, "libc", "pthread_create failed: clone failed: %s", strerror(errno));
+    async_safe_format_log(ANDROID_LOG_WARN, "libc", "pthread_create failed: clone failed: %s",
+                          strerror(errno));
     return clone_errno;
   }
 
index 5819bc1..abd403b 100644 (file)
 #include <string.h>
 #include <sys/mman.h>
 
+#include <async_safe/log.h>
+
 #include "private/bionic_futex.h"
 #include "private/bionic_sdk_version.h"
 #include "private/bionic_tls.h"
-#include "private/libc_logging.h"
 
 static pthread_internal_t* g_thread_list = nullptr;
 static pthread_rwlock_t g_thread_list_lock = PTHREAD_RWLOCK_INITIALIZER;
@@ -116,9 +117,9 @@ pthread_internal_t* __pthread_internal_find(pthread_t thread_id) {
       // addresses might sometimes contain threads or things that look enough like
       // threads for us to do some real damage by continuing.
       // TODO: try getting rid of this when Treble lets us keep vendor blobs on an old API level.
-      __libc_format_log(ANDROID_LOG_WARN, "libc", "invalid pthread_t (0) passed to libc");
+      async_safe_format_log(ANDROID_LOG_WARN, "libc", "invalid pthread_t (0) passed to libc");
     } else {
-      __libc_fatal("invalid pthread_t %p passed to libc", thread);
+      async_safe_fatal("invalid pthread_t %p passed to libc", thread);
     }
   }
   return nullptr;
index b134b5a..1f204d4 100644 (file)
  */
 
 #include <errno.h>
-#include <pthread.h>
 #include <signal.h>
+#include <unistd.h>
+#include <sys/syscall.h>
 
 int raise(int sig) {
-  int rc = pthread_kill(pthread_self(), sig);
-  if (rc != 0) {
-    errno = rc;
-    return -1;
-  }
-  return 0;
+  // Protect ourselves against stale cached PID/TID values by fetching them via syscall.
+  // http://b/37769298
+  pid_t pid = syscall(__NR_getpid);
+  pid_t tid = syscall(__NR_gettid);
+  return tgkill(pid, tid, sig);
 }
index 4fa68c2..41a439f 100644 (file)
 #include <sys/auxv.h>
 #include <sys/cdefs.h>
 
+#include <async_safe/log.h>
+
 #include "private/bionic_arc4random.h"
 #include "private/bionic_globals.h"
-#include "private/libc_logging.h"
 #include "private/KernelArgumentBlock.h"
 
 void __libc_init_setjmp_cookie(libc_globals* globals, KernelArgumentBlock& args) {
@@ -49,7 +50,7 @@ void __libc_init_setjmp_cookie(libc_globals* globals, KernelArgumentBlock& args)
 
 extern "C" __LIBC_HIDDEN__ long __bionic_setjmp_cookie_get(long sigflag) {
   if (sigflag & ~1) {
-    __libc_fatal("unexpected sigflag value: %ld", sigflag);
+    async_safe_fatal("unexpected sigflag value: %ld", sigflag);
   }
 
   return __libc_globals->setjmp_cookie | sigflag;
@@ -58,12 +59,12 @@ extern "C" __LIBC_HIDDEN__ long __bionic_setjmp_cookie_get(long sigflag) {
 // Aborts if cookie doesn't match, returns the signal flag otherwise.
 extern "C" __LIBC_HIDDEN__ long __bionic_setjmp_cookie_check(long cookie) {
   if (__libc_globals->setjmp_cookie != (cookie & ~1)) {
-    __libc_fatal("setjmp cookie mismatch");
+    async_safe_fatal("setjmp cookie mismatch");
   }
 
   return cookie & 1;
 }
 
 extern "C" __LIBC_HIDDEN__ long __bionic_setjmp_checksum_mismatch() {
-  __libc_fatal("setjmp checksum mismatch");
+  async_safe_fatal("setjmp checksum mismatch");
 }
index a0a0809..dad3fb3 100644 (file)
@@ -12,8 +12,9 @@
 #include <signal.h>
 #include <stdio.h>
 
+#include <async_safe/log.h>
+
 #include "private/ErrnoRestorer.h"
-#include "private/libc_logging.h"
 
 struct Pair {
   int code;
@@ -57,7 +58,7 @@ int strerror_r(int error_number, char* buf, size_t buf_len) {
   if (error_name != NULL) {
     length = strlcpy(buf, error_name, buf_len);
   } else {
-    length = __libc_format_buffer(buf, buf_len, "Unknown error %d", error_number);
+    length = async_safe_format_buffer(buf, buf_len, "Unknown error %d", error_number);
   }
   if (length >= buf_len) {
     errno_restorer.override(ERANGE);
index 8e3f34f..9424573 100644 (file)
@@ -19,7 +19,7 @@
 #include <string.h>
 #include <syslog.h>
 
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
 
 static const char* syslog_log_tag = NULL;
 static int syslog_priority_mask = 0xff;
@@ -109,7 +109,7 @@ void vsyslog(int priority, const char* fmt, va_list args) {
     *dst = '\0';
   }
 
-  // We can't let __libc_format_log do the formatting because it doesn't support
+  // We can't let async_safe_format_log do the formatting because it doesn't support
   // all the printf functionality.
   char log_line[1024];
   vsnprintf(log_line, sizeof(log_line), log_fmt, args);
@@ -118,5 +118,5 @@ void vsyslog(int priority, const char* fmt, va_list args) {
     free(const_cast<char*>(log_fmt));
   }
 
-  __libc_format_log(android_log_priority, log_tag, "%s", log_line);
+  async_safe_format_log(android_log_priority, log_tag, "%s", log_line);
 }
index 9fb03ac..a958699 100644 (file)
 #include <sys/_system_properties.h>
 #include <sys/system_properties.h>
 
+#include <async_safe/log.h>
+
 #include "private/ErrnoRestorer.h"
 #include "private/bionic_futex.h"
 #include "private/bionic_lock.h"
 #include "private/bionic_macros.h"
 #include "private/bionic_sdk_version.h"
-#include "private/libc_logging.h"
 
 static constexpr int PROP_FILENAME_MAX = 1024;
 
@@ -227,8 +228,8 @@ static prop_area* map_prop_area_rw(const char* filename, const char* context,
 
   if (context) {
     if (fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0) != 0) {
-      __libc_format_log(ANDROID_LOG_ERROR, "libc",
-                        "fsetxattr failed to set context (%s) for \"%s\"", context, filename);
+      async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                            "fsetxattr failed to set context (%s) for \"%s\"", context, filename);
       /*
        * fsetxattr() will fail during system properties tests due to selinux policy.
        * We do not want to create a custom policy for the tester, so we will continue in
@@ -640,9 +641,9 @@ static int send_prop_msg(const prop_msg* msg) {
       // ms so callers who do read-after-write can reliably see
       // what they've written.  Most of the time.
       // TODO: fix the system properties design.
-      __libc_format_log(ANDROID_LOG_WARN, "libc",
-                        "Property service has timed out while trying to set \"%s\" to \"%s\"",
-                        msg->name, msg->value);
+      async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                            "Property service has timed out while trying to set \"%s\" to \"%s\"",
+                            msg->name, msg->value);
       result = 0;
     }
   }
@@ -806,7 +807,8 @@ bool context_node::open(bool access_rw, bool* fsetxattr_failed) {
   }
 
   char filename[PROP_FILENAME_MAX];
-  int len = __libc_format_buffer(filename, sizeof(filename), "%s/%s", property_filename, context_);
+  int len = async_safe_format_buffer(filename, sizeof(filename), "%s/%s", property_filename,
+                                     context_);
   if (len < 0 || len > PROP_FILENAME_MAX) {
     lock_.unlock();
     return false;
@@ -841,7 +843,8 @@ void context_node::reset_access() {
 
 bool context_node::check_access() {
   char filename[PROP_FILENAME_MAX];
-  int len = __libc_format_buffer(filename, sizeof(filename), "%s/%s", property_filename, context_);
+  int len = async_safe_format_buffer(filename, sizeof(filename), "%s/%s", property_filename,
+                                     context_);
   if (len < 0 || len > PROP_FILENAME_MAX) {
     return false;
   }
@@ -864,7 +867,8 @@ void context_node::unmap() {
 static bool map_system_property_area(bool access_rw, bool* fsetxattr_failed) {
   char filename[PROP_FILENAME_MAX];
   int len =
-      __libc_format_buffer(filename, sizeof(filename), "%s/properties_serial", property_filename);
+      async_safe_format_buffer(filename, sizeof(filename), "%s/properties_serial",
+                               property_filename);
   if (len < 0 || len > PROP_FILENAME_MAX) {
     __system_property_area__ = nullptr;
     return false;
@@ -1152,7 +1156,7 @@ const prop_info* __system_property_find(const char* name) {
 
   prop_area* pa = get_prop_area_for_name(name);
   if (!pa) {
-    __libc_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
     return nullptr;
   }
 
@@ -1184,11 +1188,11 @@ int __system_property_read(const prop_info* pi, char* name, char* value) {
       if (name != nullptr) {
         size_t namelen = strlcpy(name, pi->name, PROP_NAME_MAX);
         if (namelen >= PROP_NAME_MAX) {
-          __libc_format_log(ANDROID_LOG_ERROR, "libc",
-                            "The property name length for \"%s\" is >= %d;"
-                            " please use __system_property_read_callback"
-                            " to read this property. (the name is truncated to \"%s\")",
-                            pi->name, PROP_NAME_MAX - 1, name);
+          async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                                "The property name length for \"%s\" is >= %d;"
+                                " please use __system_property_read_callback"
+                                " to read this property. (the name is truncated to \"%s\")",
+                                pi->name, PROP_NAME_MAX - 1, name);
         }
       }
       return len;
@@ -1239,17 +1243,17 @@ static void detect_protocol_version() {
   char value[PROP_VALUE_MAX];
   if (__system_property_get(kServiceVersionPropertyName, value) == 0) {
     g_propservice_protocol_version = kProtocolVersion1;
-    __libc_format_log(ANDROID_LOG_WARN, "libc",
-                      "Using old property service protocol (\"%s\" is not set)",
-                      kServiceVersionPropertyName);
+    async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                          "Using old property service protocol (\"%s\" is not set)",
+                          kServiceVersionPropertyName);
   } else {
     uint32_t version = static_cast<uint32_t>(atoll(value));
     if (version >= kProtocolVersion2) {
       g_propservice_protocol_version = kProtocolVersion2;
     } else {
-      __libc_format_log(ANDROID_LOG_WARN, "libc",
-                        "Using old property service protocol (\"%s\"=\"%s\")",
-                        kServiceVersionPropertyName, value);
+      async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                            "Using old property service protocol (\"%s\"=\"%s\")",
+                            kServiceVersionPropertyName, value);
       g_propservice_protocol_version = kProtocolVersion1;
     }
   }
@@ -1280,49 +1284,49 @@ int __system_property_set(const char* key, const char* value) {
     PropertyServiceConnection connection;
     if (!connection.IsValid()) {
       errno = connection.GetLastError();
-      __libc_format_log(ANDROID_LOG_WARN,
-                        "libc",
-                        "Unable to set property \"%s\" to \"%s\": connection failed; errno=%d (%s)",
-                        key,
-                        value,
-                        errno,
-                        strerror(errno));
+      async_safe_format_log(ANDROID_LOG_WARN,
+                            "libc",
+                            "Unable to set property \"%s\" to \"%s\": connection failed; errno=%d (%s)",
+                            key,
+                            value,
+                            errno,
+                            strerror(errno));
       return -1;
     }
 
     SocketWriter writer(&connection);
     if (!writer.WriteUint32(PROP_MSG_SETPROP2).WriteString(key).WriteString(value).Send()) {
       errno = connection.GetLastError();
-      __libc_format_log(ANDROID_LOG_WARN,
-                        "libc",
-                        "Unable to set property \"%s\" to \"%s\": write failed; errno=%d (%s)",
-                        key,
-                        value,
-                        errno,
-                        strerror(errno));
+      async_safe_format_log(ANDROID_LOG_WARN,
+                            "libc",
+                            "Unable to set property \"%s\" to \"%s\": write failed; errno=%d (%s)",
+                            key,
+                            value,
+                            errno,
+                            strerror(errno));
       return -1;
     }
 
     int result = -1;
     if (!connection.RecvInt32(&result)) {
       errno = connection.GetLastError();
-      __libc_format_log(ANDROID_LOG_WARN,
-                        "libc",
-                        "Unable to set property \"%s\" to \"%s\": recv failed; errno=%d (%s)",
-                        key,
-                        value,
-                        errno,
-                        strerror(errno));
+      async_safe_format_log(ANDROID_LOG_WARN,
+                            "libc",
+                            "Unable to set property \"%s\" to \"%s\": recv failed; errno=%d (%s)",
+                            key,
+                            value,
+                            errno,
+                            strerror(errno));
       return -1;
     }
 
     if (result != PROP_SUCCESS) {
-      __libc_format_log(ANDROID_LOG_WARN,
-                        "libc",
-                        "Unable to set property \"%s\" to \"%s\": error code: 0x%x",
-                        key,
-                        value,
-                        result);
+      async_safe_format_log(ANDROID_LOG_WARN,
+                            "libc",
+                            "Unable to set property \"%s\" to \"%s\": error code: 0x%x",
+                            key,
+                            value,
+                            result);
       return -1;
     }
 
@@ -1377,7 +1381,7 @@ int __system_property_add(const char* name, unsigned int namelen, const char* va
   prop_area* pa = get_prop_area_for_name(name);
 
   if (!pa) {
-    __libc_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
     return -1;
   }
 
index 82e0ddf..9c65570 100644 (file)
@@ -47,7 +47,7 @@
 #include "resolv_netid.h"
 #include "res_private.h"
 
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
 
 /* This code implements a small and *simple* DNS resolver cache.
  *
 
 #define XLOG(...) ({ \
     if (DEBUG) { \
-        __libc_format_log(ANDROID_LOG_DEBUG,"libc",__VA_ARGS__); \
+        async_safe_format_log(ANDROID_LOG_DEBUG,"libc",__VA_ARGS__); \
     } else { \
         ((void)0); \
     } \
index 71cc852..3b94fcf 100644 (file)
@@ -114,7 +114,7 @@ __RCSID("$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $");
 
 #include <resolv_cache.h>
 
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
 
 #ifndef DE_CONST
 #define DE_CONST(c,v)   v = ((c) ? \
@@ -568,7 +568,7 @@ res_nsend(res_state statp,
                        }
 
                        if (DBG) {
-                               __libc_format_log(ANDROID_LOG_DEBUG, "libc",
+                               async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
                                        "used send_vc %d\n", n);
                        }
 
@@ -580,7 +580,7 @@ res_nsend(res_state statp,
                } else {
                        /* Use datagrams. */
                        if (DBG) {
-                               __libc_format_log(ANDROID_LOG_DEBUG, "libc", "using send_dg\n");
+                               async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "using send_dg\n");
                        }
 
                        n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
@@ -595,7 +595,7 @@ res_nsend(res_state statp,
                        }
 
                        if (DBG) {
-                               __libc_format_log(ANDROID_LOG_DEBUG, "libc", "used send_dg %d\n",n);
+                               async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "used send_dg %d\n",n);
                        }
 
                        if (n < 0)
@@ -603,7 +603,7 @@ res_nsend(res_state statp,
                        if (n == 0)
                                goto next_ns;
                        if (DBG) {
-                               __libc_format_log(ANDROID_LOG_DEBUG, "libc", "time=%ld\n",
+                               async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "time=%ld\n",
                                                  time(NULL));
                        }
                        if (v_circuit)
@@ -743,7 +743,7 @@ static int get_timeout(const res_state statp, const int ns)
                timeout = 1;
        }
        if (DBG) {
-               __libc_format_log(ANDROID_LOG_DEBUG, "libc", "using timeout of %d sec\n", timeout);
+               async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "using timeout of %d sec\n", timeout);
        }
 
        return timeout;
@@ -768,7 +768,7 @@ send_vc(res_state statp,
        void *tmp;
 
        if (DBG) {
-               __libc_format_log(ANDROID_LOG_DEBUG, "libc", "using send_vc\n");
+               async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "using send_vc\n");
        }
 
        nsap = get_nsaddr(statp, (size_t)ns);
@@ -997,7 +997,7 @@ connect_with_timeout(int sock, const struct sockaddr *nsap, socklen_t salen, int
                timeout = evConsTime((long)sec, 0L);
                finish = evAddTime(now, timeout);
                if (DBG) {
-                       __libc_format_log(ANDROID_LOG_DEBUG, "libc", "  %d send_vc\n", sock);
+                       async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "  %d send_vc\n", sock);
                }
 
                res = retrying_select(sock, &rset, &wset, &finish);
@@ -1008,7 +1008,7 @@ connect_with_timeout(int sock, const struct sockaddr *nsap, socklen_t salen, int
 done:
        fcntl(sock, F_SETFL, origflags);
        if (DBG) {
-               __libc_format_log(ANDROID_LOG_DEBUG, "libc",
+               async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
                        "  %d connect_with_timeout returning %d\n", sock, res);
        }
        return res;
@@ -1024,7 +1024,7 @@ retrying_select(const int sock, fd_set *readset, fd_set *writeset, const struct
 
 retry:
        if (DBG) {
-               __libc_format_log(ANDROID_LOG_DEBUG, "libc", "  %d retrying_select\n", sock);
+               async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "  %d retrying_select\n", sock);
        }
 
        now = evNowTime();
@@ -1044,7 +1044,7 @@ retry:
        n = pselect(sock + 1, readset, writeset, NULL, &timeout, NULL);
        if (n == 0) {
                if (DBG) {
-                       __libc_format_log(ANDROID_LOG_DEBUG, " libc",
+                       async_safe_format_log(ANDROID_LOG_DEBUG, " libc",
                                "  %d retrying_select timeout\n", sock);
                }
                errno = ETIMEDOUT;
@@ -1054,7 +1054,7 @@ retry:
                if (errno == EINTR)
                        goto retry;
                if (DBG) {
-                       __libc_format_log(ANDROID_LOG_DEBUG, "libc",
+                       async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
                                "  %d retrying_select got error %d\n",sock, n);
                }
                return n;
@@ -1064,7 +1064,7 @@ retry:
                if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) {
                        errno = error;
                        if (DBG) {
-                               __libc_format_log(ANDROID_LOG_DEBUG, "libc",
+                               async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
                                        "  %d retrying_select dot error2 %d\n", sock, errno);
                        }
 
@@ -1072,7 +1072,7 @@ retry:
                }
        }
        if (DBG) {
-               __libc_format_log(ANDROID_LOG_DEBUG, "libc",
+               async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
                        "  %d retrying_select returning %d\n",sock, n);
        }
 
index 4ed168c..94124ff 100644 (file)
@@ -41,9 +41,9 @@
 #define DEBUG 0
 
 #if DEBUG
-#  include "private/libc_logging.h"
+#  include <async_safe/log.h>
 #  include <unistd.h>  /* for gettid() */
-#  define D(...) __libc_format_log(ANDROID_LOG_DEBUG,"libc", __VA_ARGS__)
+#  define D(...) async_safe_format_log(ANDROID_LOG_DEBUG,"libc", __VA_ARGS__)
 #else
 #  define D(...)  do{}while(0)
 #endif
index 99c79e4..97d54d2 100644 (file)
 #include <arpa/nameser.h>
 #include <string.h>
 
-#include "resolv_stats.h"
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
+
 #include "isc/eventlib.h"
+#include "resolv_stats.h"
 
 #define DBG 0
 
@@ -38,7 +39,7 @@ void
 _res_stats_set_sample(struct __res_sample* sample, time_t now, int rcode, int rtt)
 {
     if (DBG) {
-        __libc_format_log(ANDROID_LOG_INFO, "libc", "rcode = %d, sec = %d", rcode, rtt);
+        async_safe_format_log(ANDROID_LOG_INFO, "libc", "rcode = %d, sec = %d", rcode, rtt);
     }
     sample->at = now;
     sample->rcode = rcode;
@@ -128,14 +129,15 @@ _res_stats_usable_server(const struct __res_params* params, struct __res_stats*
     if (successes >= 0 && errors >= 0 && timeouts >= 0) {
         int total = successes + errors + timeouts;
         if (DBG) {
-            __libc_format_log(ANDROID_LOG_DEBUG, "libc", "NS stats: S %d + E %d + T %d + I %d "
+            async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "NS stats: S %d + E %d + T %d + I %d "
                  "= %d, rtt = %d, min_samples = %d\n", successes, errors, timeouts, internal_errors,
                  total, rtt_avg, params->min_samples);
         }
         if (total >= params->min_samples && (errors > 0 || timeouts > 0)) {
             int success_rate = successes * 100 / total;
             if (DBG) {
-                __libc_format_log(ANDROID_LOG_DEBUG, "libc", "success rate %d%%\n", success_rate);
+                async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "success rate %d%%\n",
+                                      success_rate);
             }
             if (success_rate < params->success_threshold) {
                 // evNowTime() is used here instead of time() to stay consistent with the rest of
@@ -146,13 +148,13 @@ _res_stats_usable_server(const struct __res_params* params, struct __res_stats*
                     // date has been reached, however the code for returning the ring buffer to its
                     // previous non-circular state would induce additional complexity.
                     if (DBG) {
-                        __libc_format_log(ANDROID_LOG_INFO, "libc",
+                        async_safe_format_log(ANDROID_LOG_INFO, "libc",
                             "samples stale, retrying server\n");
                     }
                     _res_stats_clear_samples(stats);
                 } else {
                     if (DBG) {
-                        __libc_format_log(ANDROID_LOG_INFO, "libc",
+                        async_safe_format_log(ANDROID_LOG_INFO, "libc",
                             "too many resolution errors, ignoring server\n");
                     }
                     return 0;
index afdaca8..a5d3a6f 100644 (file)
@@ -41,6 +41,25 @@ sighandler_t bsd_signal(int signum, sighandler_t handler) __REMOVED_IN(21);
 
 #if __ANDROID_API__ < __ANDROID_API_L__
 
+/* These weren't introduced until L. */
+int __libc_current_sigrtmax() __attribute__((__weak__)) __VERSIONER_NO_GUARD;
+int __libc_current_sigrtmin() __attribute__((__weak__)) __VERSIONER_NO_GUARD;
+
+static __inline int __ndk_legacy___libc_current_sigrtmax() {
+  if (__libc_current_sigrtmax) return __libc_current_sigrtmax();
+  return __SIGRTMAX; /* Should match __libc_current_sigrtmax. */
+}
+
+static __inline int __ndk_legacy___libc_current_sigrtmin() {
+  if (__libc_current_sigrtmin) return __libc_current_sigrtmin();
+  return __SIGRTMIN + 4; /* Should match __libc_current_sigrtmin. */
+}
+
+#undef SIGRTMAX
+#define SIGRTMAX __ndk_legacy___libc_current_sigrtmax()
+#undef SIGRTMIN
+#define SIGRTMIN __ndk_legacy___libc_current_sigrtmin()
+
 static __inline int sigismember(const sigset_t *set, int signum) {
   /* Signal numbers start at 1, but bit positions start at 0. */
   int bit = signum - 1;
index c36bc8d..4181006 100644 (file)
@@ -184,6 +184,12 @@ typedef struct {
 
 #define PT_GNU_RELRO 0x6474e552
 
+#undef ELF_ST_TYPE
+#define ELF_ST_TYPE(x) ((x) & 0xf)
+#define ELF_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf))
+#define ELF32_ST_INFO(b,t) ELF_ST_INFO(b,t)
+#define ELF64_ST_INFO(b,t) ELF_ST_INFO(b,t)
+
 #define STB_LOOS      10
 #define STB_HIOS      12
 #define STB_LOPROC    13
index 752ee72..b07a000 100644 (file)
 
 __BEGIN_DECLS
 
-#if defined(__clang__)
-/* clang should support alloc_size in the nearish future. */
-#if __has_attribute(alloc_size)
-#error "We should enable alloc_size for clang."
-#else
+// Remove the workaround once b/37423073 is fixed.
+#if defined(__clang__) && !__has_attribute(alloc_size)
 #define __BIONIC_ALLOC_SIZE(...)
-#endif
 #else
 #define __BIONIC_ALLOC_SIZE(...) __attribute__((__alloc_size__(__VA_ARGS__)))
 #endif
@@ -81,6 +77,11 @@ struct mallinfo mallinfo(void);
  */
 int malloc_info(int, FILE*) __INTRODUCED_IN(23);
 
+/* mallopt options */
+#define M_DECAY_TIME -100
+
+int mallopt(int, int) __INTRODUCED_IN_FUTURE;
+
 __END_DECLS
 
 #endif  /* LIBC_INCLUDE_MALLOC_H_ */
index 904c334..be0e22d 100644 (file)
 
 #include <linux/sem.h>
 
+__BEGIN_DECLS
+
 #define semid_ds semid64_ds
 
-__BEGIN_DECLS
+union semun {
+  int val;
+  struct semid_ds* buf;
+  unsigned short* array;
+  struct seminfo* __buf;
+  void* __pad;
+};
 
 int semctl(int, int, int, ...) __INTRODUCED_IN(26);
 int semget(key_t, int, int) __INTRODUCED_IN(26);
index c22f684..5198dbe 100644 (file)
@@ -70,6 +70,8 @@ kernel_token_replacements = {
     "semid_ds": "__kernel_legacy_semid_ds",
     "shmid_ds": "__kernel_legacy_shmid_ds",
     "ipc_perm": "__kernel_legacy_ipc_perm",
+    # The kernel semun isn't usable (https://github.com/android-ndk/ndk/issues/400).
+    "semun": "__kernel_legacy_semun",
     # The kernel's _NSIG/NSIG are one less than the userspace value, so we need to move them aside.
     "_NSIG": "_KERNEL__NSIG",
     "NSIG": "_KERNEL_NSIG",
index 6916556..df815db 100644 (file)
@@ -52,7 +52,7 @@ struct sembuf {
   short sem_flg;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 };
-union semun {
+union __kernel_legacy_semun {
   int val;
   struct __kernel_legacy_semid_ds __user * buf;
 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
index 5b94f80..a74027a 100644 (file)
@@ -1261,58 +1261,58 @@ LIBC_N { # introduced-arm64=24 introduced-mips=24 introduced-mips64=24 introduce
 
 LIBC_O {
   global:
-    __sendto_chk; # future
-    __system_property_read_callback; # future
-    __system_property_wait; # future
+    __sendto_chk; # introduced=26
+    __system_property_read_callback; # introduced=26
+    __system_property_wait; # introduced=26
     bsd_signal; # arm x86 mips versioned=26
-    catclose; # future
-    catgets; # future
-    catopen; # future
-    ctermid; # future
-    endgrent; # future
-    endpwent; # future
-    futimes; # future
-    futimesat; # future
-    getdomainname; # future
-    getgrent; # future
-    getpwent; # future
-    getsubopt; # future
-    hasmntopt; # future
-    lutimes; # future
-    mblen; # future
-    msgctl; # future
-    msgget; # future
-    msgrcv; # future
-    msgsnd; # future
-    nl_langinfo; # future
-    nl_langinfo_l; # future
-    pthread_getname_np; # future
-    quotactl; # future
-    semctl; # future
-    semget; # future
-    semop; # future
-    semtimedop; # future
-    setdomainname; # future
-    setgrent; # future
-    setpwent; # future
-    shmat; # future
-    shmctl; # future
-    shmdt; # future
-    shmget; # future
-    sighold; # future
-    sigignore; # future
-    sigpause; # future
-    sigrelse; # future
-    sigset; # future
-    strtod_l; # future
-    strtof_l; # future
-    strtol_l; # future
-    strtoul_l; # future
-    sync_file_range; # future
-    towctrans; # future
-    towctrans_l; # future
-    wctrans; # future
-    wctrans_l; # future
+    catclose; # introduced=26
+    catgets; # introduced=26
+    catopen; # introduced=26
+    ctermid; # introduced=26
+    endgrent; # introduced=26
+    endpwent; # introduced=26
+    futimes; # introduced=26
+    futimesat; # introduced=26
+    getdomainname; # introduced=26
+    getgrent; # introduced=26
+    getpwent; # introduced=26
+    getsubopt; # introduced=26
+    hasmntopt; # introduced=26
+    lutimes; # introduced=26
+    mblen; # introduced=26
+    msgctl; # introduced=26
+    msgget; # introduced=26
+    msgrcv; # introduced=26
+    msgsnd; # introduced=26
+    nl_langinfo; # introduced=26
+    nl_langinfo_l; # introduced=26
+    pthread_getname_np; # introduced=26
+    quotactl; # introduced=26
+    semctl; # introduced=26
+    semget; # introduced=26
+    semop; # introduced=26
+    semtimedop; # introduced=26
+    setdomainname; # introduced=26
+    setgrent; # introduced=26
+    setpwent; # introduced=26
+    shmat; # introduced=26
+    shmctl; # introduced=26
+    shmdt; # introduced=26
+    shmget; # introduced=26
+    sighold; # introduced=26
+    sigignore; # introduced=26
+    sigpause; # introduced=26
+    sigrelse; # introduced=26
+    sigset; # introduced=26
+    strtod_l; # introduced=26
+    strtof_l; # introduced=26
+    strtol_l; # introduced=26
+    strtoul_l; # introduced=26
+    sync_file_range; # introduced=26
+    towctrans; # introduced=26
+    towctrans_l; # introduced=26
+    wctrans; # introduced=26
+    wctrans_l; # introduced=26
 } LIBC_N;
 
 LIBC_PRIVATE {
@@ -1552,4 +1552,5 @@ LIBC_PLATFORM {
     malloc_disable;
     malloc_enable;
     malloc_iterate;
+    mallopt;
 } LIBC_O;
index cd1aff6..34d3429 100644 (file)
@@ -1184,57 +1184,57 @@ LIBC_N { # introduced-arm64=24 introduced-mips=24 introduced-mips64=24 introduce
 
 LIBC_O {
   global:
-    __sendto_chk; # future
-    __system_property_read_callback; # future
-    __system_property_wait; # future
-    catclose; # future
-    catgets; # future
-    catopen; # future
-    ctermid; # future
-    endgrent; # future
-    endpwent; # future
-    futimes; # future
-    futimesat; # future
-    getdomainname; # future
-    getgrent; # future
-    getpwent; # future
-    getsubopt; # future
-    hasmntopt; # future
-    lutimes; # future
-    mblen; # future
-    msgctl; # future
-    msgget; # future
-    msgrcv; # future
-    msgsnd; # future
-    nl_langinfo; # future
-    nl_langinfo_l; # future
-    pthread_getname_np; # future
-    quotactl; # future
-    semctl; # future
-    semget; # future
-    semop; # future
-    semtimedop; # future
-    setdomainname; # future
-    setgrent; # future
-    setpwent; # future
-    shmat; # future
-    shmctl; # future
-    shmdt; # future
-    shmget; # future
-    sighold; # future
-    sigignore; # future
-    sigpause; # future
-    sigrelse; # future
-    sigset; # future
-    strtod_l; # future
-    strtof_l; # future
-    strtol_l; # future
-    strtoul_l; # future
-    sync_file_range; # future
-    towctrans; # future
-    towctrans_l; # future
-    wctrans; # future
-    wctrans_l; # future
+    __sendto_chk; # introduced=26
+    __system_property_read_callback; # introduced=26
+    __system_property_wait; # introduced=26
+    catclose; # introduced=26
+    catgets; # introduced=26
+    catopen; # introduced=26
+    ctermid; # introduced=26
+    endgrent; # introduced=26
+    endpwent; # introduced=26
+    futimes; # introduced=26
+    futimesat; # introduced=26
+    getdomainname; # introduced=26
+    getgrent; # introduced=26
+    getpwent; # introduced=26
+    getsubopt; # introduced=26
+    hasmntopt; # introduced=26
+    lutimes; # introduced=26
+    mblen; # introduced=26
+    msgctl; # introduced=26
+    msgget; # introduced=26
+    msgrcv; # introduced=26
+    msgsnd; # introduced=26
+    nl_langinfo; # introduced=26
+    nl_langinfo_l; # introduced=26
+    pthread_getname_np; # introduced=26
+    quotactl; # introduced=26
+    semctl; # introduced=26
+    semget; # introduced=26
+    semop; # introduced=26
+    semtimedop; # introduced=26
+    setdomainname; # introduced=26
+    setgrent; # introduced=26
+    setpwent; # introduced=26
+    shmat; # introduced=26
+    shmctl; # introduced=26
+    shmdt; # introduced=26
+    shmget; # introduced=26
+    sighold; # introduced=26
+    sigignore; # introduced=26
+    sigpause; # introduced=26
+    sigrelse; # introduced=26
+    sigset; # introduced=26
+    strtod_l; # introduced=26
+    strtof_l; # introduced=26
+    strtol_l; # introduced=26
+    strtoul_l; # introduced=26
+    sync_file_range; # introduced=26
+    towctrans; # introduced=26
+    towctrans_l; # introduced=26
+    wctrans; # introduced=26
+    wctrans_l; # introduced=26
 } LIBC_N;
 
 LIBC_PRIVATE {
@@ -1269,4 +1269,5 @@ LIBC_PLATFORM {
     malloc_disable;
     malloc_enable;
     malloc_iterate;
+    mallopt;
 } LIBC_O;
index bdfd3b8..aac876d 100644 (file)
@@ -1245,58 +1245,58 @@ LIBC_N { # introduced-arm64=24 introduced-mips=24 introduced-mips64=24 introduce
 
 LIBC_O {
   global:
-    __sendto_chk; # future
-    __system_property_read_callback; # future
-    __system_property_wait; # future
+    __sendto_chk; # introduced=26
+    __system_property_read_callback; # introduced=26
+    __system_property_wait; # introduced=26
     bsd_signal; # arm x86 mips versioned=26
-    catclose; # future
-    catgets; # future
-    catopen; # future
-    ctermid; # future
-    endgrent; # future
-    endpwent; # future
-    futimes; # future
-    futimesat; # future
-    getdomainname; # future
-    getgrent; # future
-    getpwent; # future
-    getsubopt; # future
-    hasmntopt; # future
-    lutimes; # future
-    mblen; # future
-    msgctl; # future
-    msgget; # future
-    msgrcv; # future
-    msgsnd; # future
-    nl_langinfo; # future
-    nl_langinfo_l; # future
-    pthread_getname_np; # future
-    quotactl; # future
-    semctl; # future
-    semget; # future
-    semop; # future
-    semtimedop; # future
-    setdomainname; # future
-    setgrent; # future
-    setpwent; # future
-    shmat; # future
-    shmctl; # future
-    shmdt; # future
-    shmget; # future
-    sighold; # future
-    sigignore; # future
-    sigpause; # future
-    sigrelse; # future
-    sigset; # future
-    strtod_l; # future
-    strtof_l; # future
-    strtol_l; # future
-    strtoul_l; # future
-    sync_file_range; # future
-    towctrans; # future
-    towctrans_l; # future
-    wctrans; # future
-    wctrans_l; # future
+    catclose; # introduced=26
+    catgets; # introduced=26
+    catopen; # introduced=26
+    ctermid; # introduced=26
+    endgrent; # introduced=26
+    endpwent; # introduced=26
+    futimes; # introduced=26
+    futimesat; # introduced=26
+    getdomainname; # introduced=26
+    getgrent; # introduced=26
+    getpwent; # introduced=26
+    getsubopt; # introduced=26
+    hasmntopt; # introduced=26
+    lutimes; # introduced=26
+    mblen; # introduced=26
+    msgctl; # introduced=26
+    msgget; # introduced=26
+    msgrcv; # introduced=26
+    msgsnd; # introduced=26
+    nl_langinfo; # introduced=26
+    nl_langinfo_l; # introduced=26
+    pthread_getname_np; # introduced=26
+    quotactl; # introduced=26
+    semctl; # introduced=26
+    semget; # introduced=26
+    semop; # introduced=26
+    semtimedop; # introduced=26
+    setdomainname; # introduced=26
+    setgrent; # introduced=26
+    setpwent; # introduced=26
+    shmat; # introduced=26
+    shmctl; # introduced=26
+    shmdt; # introduced=26
+    shmget; # introduced=26
+    sighold; # introduced=26
+    sigignore; # introduced=26
+    sigpause; # introduced=26
+    sigrelse; # introduced=26
+    sigset; # introduced=26
+    strtod_l; # introduced=26
+    strtof_l; # introduced=26
+    strtol_l; # introduced=26
+    strtoul_l; # introduced=26
+    sync_file_range; # introduced=26
+    towctrans; # introduced=26
+    towctrans_l; # introduced=26
+    wctrans; # introduced=26
+    wctrans_l; # introduced=26
 } LIBC_N;
 
 LIBC_PRIVATE {
@@ -1393,4 +1393,5 @@ LIBC_PLATFORM {
     malloc_disable;
     malloc_enable;
     malloc_iterate;
+    mallopt;
 } LIBC_O;
index cd1aff6..34d3429 100644 (file)
@@ -1184,57 +1184,57 @@ LIBC_N { # introduced-arm64=24 introduced-mips=24 introduced-mips64=24 introduce
 
 LIBC_O {
   global:
-    __sendto_chk; # future
-    __system_property_read_callback; # future
-    __system_property_wait; # future
-    catclose; # future
-    catgets; # future
-    catopen; # future
-    ctermid; # future
-    endgrent; # future
-    endpwent; # future
-    futimes; # future
-    futimesat; # future
-    getdomainname; # future
-    getgrent; # future
-    getpwent; # future
-    getsubopt; # future
-    hasmntopt; # future
-    lutimes; # future
-    mblen; # future
-    msgctl; # future
-    msgget; # future
-    msgrcv; # future
-    msgsnd; # future
-    nl_langinfo; # future
-    nl_langinfo_l; # future
-    pthread_getname_np; # future
-    quotactl; # future
-    semctl; # future
-    semget; # future
-    semop; # future
-    semtimedop; # future
-    setdomainname; # future
-    setgrent; # future
-    setpwent; # future
-    shmat; # future
-    shmctl; # future
-    shmdt; # future
-    shmget; # future
-    sighold; # future
-    sigignore; # future
-    sigpause; # future
-    sigrelse; # future
-    sigset; # future
-    strtod_l; # future
-    strtof_l; # future
-    strtol_l; # future
-    strtoul_l; # future
-    sync_file_range; # future
-    towctrans; # future
-    towctrans_l; # future
-    wctrans; # future
-    wctrans_l; # future
+    __sendto_chk; # introduced=26
+    __system_property_read_callback; # introduced=26
+    __system_property_wait; # introduced=26
+    catclose; # introduced=26
+    catgets; # introduced=26
+    catopen; # introduced=26
+    ctermid; # introduced=26
+    endgrent; # introduced=26
+    endpwent; # introduced=26
+    futimes; # introduced=26
+    futimesat; # introduced=26
+    getdomainname; # introduced=26
+    getgrent; # introduced=26
+    getpwent; # introduced=26
+    getsubopt; # introduced=26
+    hasmntopt; # introduced=26
+    lutimes; # introduced=26
+    mblen; # introduced=26
+    msgctl; # introduced=26
+    msgget; # introduced=26
+    msgrcv; # introduced=26
+    msgsnd; # introduced=26
+    nl_langinfo; # introduced=26
+    nl_langinfo_l; # introduced=26
+    pthread_getname_np; # introduced=26
+    quotactl; # introduced=26
+    semctl; # introduced=26
+    semget; # introduced=26
+    semop; # introduced=26
+    semtimedop; # introduced=26
+    setdomainname; # introduced=26
+    setgrent; # introduced=26
+    setpwent; # introduced=26
+    shmat; # introduced=26
+    shmctl; # introduced=26
+    shmdt; # introduced=26
+    shmget; # introduced=26
+    sighold; # introduced=26
+    sigignore; # introduced=26
+    sigpause; # introduced=26
+    sigrelse; # introduced=26
+    sigset; # introduced=26
+    strtod_l; # introduced=26
+    strtof_l; # introduced=26
+    strtol_l; # introduced=26
+    strtoul_l; # introduced=26
+    sync_file_range; # introduced=26
+    towctrans; # introduced=26
+    towctrans_l; # introduced=26
+    wctrans; # introduced=26
+    wctrans_l; # introduced=26
 } LIBC_N;
 
 LIBC_PRIVATE {
@@ -1269,4 +1269,5 @@ LIBC_PLATFORM {
     malloc_disable;
     malloc_enable;
     malloc_iterate;
+    mallopt;
 } LIBC_O;
index dd2ecca..682f2c4 100644 (file)
@@ -1243,58 +1243,58 @@ LIBC_N { # introduced-arm64=24 introduced-mips=24 introduced-mips64=24 introduce
 
 LIBC_O {
   global:
-    __sendto_chk; # future
-    __system_property_read_callback; # future
-    __system_property_wait; # future
+    __sendto_chk; # introduced=26
+    __system_property_read_callback; # introduced=26
+    __system_property_wait; # introduced=26
     bsd_signal; # arm x86 mips versioned=26
-    catclose; # future
-    catgets; # future
-    catopen; # future
-    ctermid; # future
-    endgrent; # future
-    endpwent; # future
-    futimes; # future
-    futimesat; # future
-    getdomainname; # future
-    getgrent; # future
-    getpwent; # future
-    getsubopt; # future
-    hasmntopt; # future
-    lutimes; # future
-    mblen; # future
-    msgctl; # future
-    msgget; # future
-    msgrcv; # future
-    msgsnd; # future
-    nl_langinfo; # future
-    nl_langinfo_l; # future
-    pthread_getname_np; # future
-    quotactl; # future
-    semctl; # future
-    semget; # future
-    semop; # future
-    semtimedop; # future
-    setdomainname; # future
-    setgrent; # future
-    setpwent; # future
-    shmat; # future
-    shmctl; # future
-    shmdt; # future
-    shmget; # future
-    sighold; # future
-    sigignore; # future
-    sigpause; # future
-    sigrelse; # future
-    sigset; # future
-    strtod_l; # future
-    strtof_l; # future
-    strtol_l; # future
-    strtoul_l; # future
-    sync_file_range; # future
-    towctrans; # future
-    towctrans_l; # future
-    wctrans; # future
-    wctrans_l; # future
+    catclose; # introduced=26
+    catgets; # introduced=26
+    catopen; # introduced=26
+    ctermid; # introduced=26
+    endgrent; # introduced=26
+    endpwent; # introduced=26
+    futimes; # introduced=26
+    futimesat; # introduced=26
+    getdomainname; # introduced=26
+    getgrent; # introduced=26
+    getpwent; # introduced=26
+    getsubopt; # introduced=26
+    hasmntopt; # introduced=26
+    lutimes; # introduced=26
+    mblen; # introduced=26
+    msgctl; # introduced=26
+    msgget; # introduced=26
+    msgrcv; # introduced=26
+    msgsnd; # introduced=26
+    nl_langinfo; # introduced=26
+    nl_langinfo_l; # introduced=26
+    pthread_getname_np; # introduced=26
+    quotactl; # introduced=26
+    semctl; # introduced=26
+    semget; # introduced=26
+    semop; # introduced=26
+    semtimedop; # introduced=26
+    setdomainname; # introduced=26
+    setgrent; # introduced=26
+    setpwent; # introduced=26
+    shmat; # introduced=26
+    shmctl; # introduced=26
+    shmdt; # introduced=26
+    shmget; # introduced=26
+    sighold; # introduced=26
+    sigignore; # introduced=26
+    sigpause; # introduced=26
+    sigrelse; # introduced=26
+    sigset; # introduced=26
+    strtod_l; # introduced=26
+    strtof_l; # introduced=26
+    strtol_l; # introduced=26
+    strtoul_l; # introduced=26
+    sync_file_range; # introduced=26
+    towctrans; # introduced=26
+    towctrans_l; # introduced=26
+    wctrans; # introduced=26
+    wctrans_l; # introduced=26
 } LIBC_N;
 
 LIBC_PRIVATE {
@@ -1392,4 +1392,5 @@ LIBC_PLATFORM {
     malloc_disable;
     malloc_enable;
     malloc_iterate;
+    mallopt;
 } LIBC_O;
index cd1aff6..34d3429 100644 (file)
@@ -1184,57 +1184,57 @@ LIBC_N { # introduced-arm64=24 introduced-mips=24 introduced-mips64=24 introduce
 
 LIBC_O {
   global:
-    __sendto_chk; # future
-    __system_property_read_callback; # future
-    __system_property_wait; # future
-    catclose; # future
-    catgets; # future
-    catopen; # future
-    ctermid; # future
-    endgrent; # future
-    endpwent; # future
-    futimes; # future
-    futimesat; # future
-    getdomainname; # future
-    getgrent; # future
-    getpwent; # future
-    getsubopt; # future
-    hasmntopt; # future
-    lutimes; # future
-    mblen; # future
-    msgctl; # future
-    msgget; # future
-    msgrcv; # future
-    msgsnd; # future
-    nl_langinfo; # future
-    nl_langinfo_l; # future
-    pthread_getname_np; # future
-    quotactl; # future
-    semctl; # future
-    semget; # future
-    semop; # future
-    semtimedop; # future
-    setdomainname; # future
-    setgrent; # future
-    setpwent; # future
-    shmat; # future
-    shmctl; # future
-    shmdt; # future
-    shmget; # future
-    sighold; # future
-    sigignore; # future
-    sigpause; # future
-    sigrelse; # future
-    sigset; # future
-    strtod_l; # future
-    strtof_l; # future
-    strtol_l; # future
-    strtoul_l; # future
-    sync_file_range; # future
-    towctrans; # future
-    towctrans_l; # future
-    wctrans; # future
-    wctrans_l; # future
+    __sendto_chk; # introduced=26
+    __system_property_read_callback; # introduced=26
+    __system_property_wait; # introduced=26
+    catclose; # introduced=26
+    catgets; # introduced=26
+    catopen; # introduced=26
+    ctermid; # introduced=26
+    endgrent; # introduced=26
+    endpwent; # introduced=26
+    futimes; # introduced=26
+    futimesat; # introduced=26
+    getdomainname; # introduced=26
+    getgrent; # introduced=26
+    getpwent; # introduced=26
+    getsubopt; # introduced=26
+    hasmntopt; # introduced=26
+    lutimes; # introduced=26
+    mblen; # introduced=26
+    msgctl; # introduced=26
+    msgget; # introduced=26
+    msgrcv; # introduced=26
+    msgsnd; # introduced=26
+    nl_langinfo; # introduced=26
+    nl_langinfo_l; # introduced=26
+    pthread_getname_np; # introduced=26
+    quotactl; # introduced=26
+    semctl; # introduced=26
+    semget; # introduced=26
+    semop; # introduced=26
+    semtimedop; # introduced=26
+    setdomainname; # introduced=26
+    setgrent; # introduced=26
+    setpwent; # introduced=26
+    shmat; # introduced=26
+    shmctl; # introduced=26
+    shmdt; # introduced=26
+    shmget; # introduced=26
+    sighold; # introduced=26
+    sigignore; # introduced=26
+    sigpause; # introduced=26
+    sigrelse; # introduced=26
+    sigset; # introduced=26
+    strtod_l; # introduced=26
+    strtof_l; # introduced=26
+    strtol_l; # introduced=26
+    strtoul_l; # introduced=26
+    sync_file_range; # introduced=26
+    towctrans; # introduced=26
+    towctrans_l; # introduced=26
+    wctrans; # introduced=26
+    wctrans_l; # introduced=26
 } LIBC_N;
 
 LIBC_PRIVATE {
@@ -1269,4 +1269,5 @@ LIBC_PLATFORM {
     malloc_disable;
     malloc_enable;
     malloc_iterate;
+    mallopt;
 } LIBC_O;
index 708c101..b071b90 100644 (file)
@@ -13,9 +13,10 @@ cc_library_static {
 
     stl: "libc++_static",
 
-    static_libs: ["libc_logging"],
+    whole_static_libs: ["libasync_safe"],
 
     include_dirs: ["bionic/libc"],
+
     export_include_dirs: ["."],
 
     sanitize: {
@@ -29,7 +30,6 @@ cc_library_static {
         "-Werror",
         "-Wno-error=format-zero-length",
     ],
-
 }
 
 // ==============================================================
@@ -61,9 +61,9 @@ cc_library {
     },
 
     static_libs: [
+        "libasync_safe",
         "libbase",
         "libc_malloc_debug_backtrace",
-        "libc_logging",
     ],
 
     multilib: {
@@ -89,7 +89,6 @@ cc_library {
         "-fno-stack-protector",
         "-Wno-error=format-zero-length",
     ],
-
 }
 
 // ==============================================================
@@ -118,7 +117,7 @@ cc_test {
     whole_static_libs: ["libc_malloc_debug"],
 
     local_include_dirs: ["tests"],
-    include_dirs: ["bionic/libc"],
+    include_dirs: ["bionic/libc", "bionic/libc/async_safe/include"],
 
     shared_libs: ["libbase"],
 
@@ -127,5 +126,4 @@ cc_test {
         "-Werror",
         "-Wno-error=format-zero-length",
     ],
-
 }
index 75a255c..88f5a1d 100644 (file)
@@ -158,13 +158,13 @@ std::string backtrace_string(const uintptr_t* frames, size_t frame_count) {
       char* demangled_symbol = __cxa_demangle(symbol, nullptr, nullptr, nullptr);
       const char* best_name = (demangled_symbol != nullptr) ? demangled_symbol : symbol;
 
-      __libc_format_buffer(buf, sizeof(buf),
-          "          #%02zd  pc %" PAD_PTR "  %s (%s+%" PRIuPTR ")\n", frame_num,
+      async_safe_format_buffer(
+          buf, sizeof(buf), "          #%02zd  pc %" PAD_PTR "  %s (%s+%" PRIuPTR ")\n", frame_num,
           rel_pc, soname, best_name, frames[frame_num] - offset);
       free(demangled_symbol);
     } else {
-      __libc_format_buffer(buf, sizeof(buf),
-          "          #%02zd  pc %" PAD_PTR "  %s\n", frame_num, rel_pc, soname);
+      async_safe_format_buffer(
+          buf, sizeof(buf), "          #%02zd  pc %" PAD_PTR "  %s\n", frame_num, rel_pc, soname);
     }
     str += buf;
   }
index 4df0408..ed4b541 100644 (file)
 #ifndef MALLOC_DEBUG_LOG_H
 #define MALLOC_DEBUG_LOG_H
 
-#include <private/libc_logging.h>
+#include <async_safe/log.h>
 
 // =============================================================================
 // log functions
 // =============================================================================
 #define debug_log(format, ...)  \
-    __libc_format_log(ANDROID_LOG_DEBUG, "malloc_debug", (format), ##__VA_ARGS__ )
+    async_safe_format_log(ANDROID_LOG_DEBUG, "malloc_debug", (format), ##__VA_ARGS__ )
 #define error_log(format, ...)  \
-    __libc_format_log(ANDROID_LOG_ERROR, "malloc_debug", (format), ##__VA_ARGS__ )
+    async_safe_format_log(ANDROID_LOG_ERROR, "malloc_debug", (format), ##__VA_ARGS__ )
 #define error_log_string(str)  \
-    __libc_write_log(ANDROID_LOG_ERROR, "malloc_debug", (str))
+    async_safe_write_log(ANDROID_LOG_ERROR, "malloc_debug", (str))
 #define info_log(format, ...)  \
-    __libc_format_log(ANDROID_LOG_INFO, "malloc_debug", (format), ##__VA_ARGS__ )
+    async_safe_format_log(ANDROID_LOG_INFO, "malloc_debug", (format), ##__VA_ARGS__ )
 
 #endif  // MALLOC_DEBUG_LOG_H
index a985ef9..59bb102 100644 (file)
@@ -13,6 +13,7 @@ LIBC_MALLOC_DEBUG {
     debug_malloc_disable;
     debug_malloc_enable;
     debug_malloc_usable_size;
+    debug_mallopt;
     debug_memalign;
     debug_posix_memalign;
     debug_pvalloc;
index 1a6b30f..ec9d840 100644 (file)
@@ -13,6 +13,7 @@ LIBC_MALLOC_DEBUG {
     debug_malloc_disable;
     debug_malloc_enable;
     debug_malloc_usable_size;
+    debug_mallopt;
     debug_memalign;
     debug_posix_memalign;
     debug_realloc;
index addb5d4..014d385 100644 (file)
@@ -77,6 +77,7 @@ void* debug_memalign(size_t alignment, size_t bytes);
 void* debug_realloc(void* pointer, size_t bytes);
 void* debug_calloc(size_t nmemb, size_t bytes);
 struct mallinfo debug_mallinfo();
+int debug_mallopt(int param, int value);
 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);
@@ -639,6 +640,10 @@ struct mallinfo debug_mallinfo() {
   return g_dispatch->mallinfo();
 }
 
+int debug_mallopt(int param, int value) {
+  return g_dispatch->mallopt(param, value);
+}
+
 int debug_posix_memalign(void** memptr, size_t alignment, size_t size) {
   if (DebugCallsDisabled()) {
     return g_dispatch->posix_memalign(memptr, alignment, size);
index 194d42b..fb64e3e 100644 (file)
@@ -44,7 +44,7 @@ std::string getFakeLogPrint() {
   return g_fake_log_print;
 }
 
-extern "C" int __libc_format_log(int priority, const char* tag, const char* format, ...) {
+extern "C" int async_safe_format_log(int priority, const char* tag, const char* format, ...) {
   g_fake_log_print += std::to_string(priority) + ' ';
   g_fake_log_print += tag;
   g_fake_log_print += ' ';
index 219c21e..4fdba2e 100644 (file)
@@ -58,6 +58,7 @@ void debug_get_malloc_leak_info(uint8_t**, size_t*, size_t*, size_t*, size_t*);
 void debug_free_malloc_leak_info(uint8_t*);
 
 struct mallinfo debug_mallinfo();
+int debug_mallopt(int, int);
 
 #if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
 void* debug_pvalloc(size_t);
@@ -128,6 +129,7 @@ MallocDispatch MallocDebugTest::dispatch = {
   nullptr,
   nullptr,
   nullptr,
+  mallopt,
 };
 
 void VerifyAllocCalls() {
@@ -1474,6 +1476,20 @@ TEST_F(MallocDebugTest, debug_mallinfo) {
   ASSERT_STREQ("", getFakeLogPrint().c_str());
 }
 
+TEST_F(MallocDebugTest, debug_mallopt) {
+  Init("guard");
+
+  void* pointer = debug_malloc(150);
+  ASSERT_TRUE(pointer != nullptr);
+
+  EXPECT_EQ(0, debug_mallopt(-1000, 1));
+
+  debug_free(pointer);
+
+  ASSERT_STREQ("", getFakeLogBuf().c_str());
+  ASSERT_STREQ("", getFakeLogPrint().c_str());
+}
+
 TEST_F(MallocDebugTest, debug_posix_memalign) {
   Init("guard");
 
index 1133e2a..20afdec 100644 (file)
 #include <sys/mman.h>
 #include <sys/user.h>
 
+#include <async_safe/log.h>
+
 #include "private/bionic_macros.h"
 #include "private/bionic_prctl.h"
-#include "private/libc_logging.h"
 
 template <typename T>
 union WriteProtectedContents {
@@ -57,7 +58,7 @@ class WriteProtected {
     memset(&contents, 0, sizeof(contents));
 
     if (mprotect(&contents, PAGE_SIZE, PROT_READ)) {
-      __libc_fatal("failed to make WriteProtected nonwritable in initialize");
+      async_safe_fatal("failed to make WriteProtected nonwritable in initialize");
     }
   }
 
@@ -72,13 +73,13 @@ class WriteProtected {
   template <typename Mutator>
   void mutate(Mutator mutator) {
     if (mprotect(&contents, PAGE_SIZE, PROT_READ | PROT_WRITE) != 0) {
-      __libc_fatal("failed to make WriteProtected writable in mutate: %s",
-                   strerror(errno));
+      async_safe_fatal("failed to make WriteProtected writable in mutate: %s",
+                       strerror(errno));
     }
     mutator(&contents.value);
     if (mprotect(&contents, PAGE_SIZE, PROT_READ) != 0) {
-      __libc_fatal("failed to make WriteProtected nonwritable in mutate: %s",
-                   strerror(errno));
+      async_safe_fatal("failed to make WriteProtected nonwritable in mutate: %s",
+                       strerror(errno));
     }
   }
 };
index df810ca..8591117 100644 (file)
  * SUCH DAMAGE.
  */
 
-#include "private/libc_logging.h"
-
 #include <poll.h> // For struct pollfd.
+#include <stdarg.h>
+#include <stdlib.h>
 #include <sys/select.h> // For struct fd_set.
 
+#include <async_safe/log.h>
+
+static inline __noreturn void __fortify_fatal(const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  async_safe_fatal_va_list("FORTIFY", fmt, args);
+  va_end(args);
+  abort();
+}
+
 //
 // Common helpers.
 //
index 02a092f..cdae466 100644 (file)
@@ -45,6 +45,7 @@ typedef void* (*MallocRealloc)(void*, size_t);
 typedef int (*MallocIterate)(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*);
 typedef void (*MallocMallocDisable)();
 typedef void (*MallocMallocEnable)();
+typedef int (*MallocMallopt)(int, int);
 
 #if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
 typedef void* (*MallocPvalloc)(size_t);
@@ -69,6 +70,7 @@ struct MallocDispatch {
   MallocIterate iterate;
   MallocMallocDisable malloc_disable;
   MallocMallocEnable malloc_enable;
+  MallocMallopt mallopt;
 } __attribute__((aligned(32)));
 
 #endif
index f073d01..83b6111 100644 (file)
@@ -5,59 +5,61 @@
 
 #include "seccomp_bpfs.h"
 const sock_filter mips64_filter[] = {
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5000, 0, 82),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5168, 41, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5089, 21, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5038, 11, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5023, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5008, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5000, 0, 84),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5164, 41, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5077, 21, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5034, 11, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5008, 5, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5005, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5003, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5002, 75, 74), //read|write
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5004, 74, 73), //close
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5020, 73, 72), //lseek|mmap|mprotect|munmap|brk|rt_sigaction|rt_sigprocmask|ioctl|pread64|pwrite64|readv|writev
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5034, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5031, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5028, 70, 69), //sched_yield|mremap|msync|mincore|madvise
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5032, 69, 68), //dup
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5037, 68, 67), //nanosleep|getitimer|setitimer
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5070, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5057, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5043, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5042, 64, 63), //getpid|sendfile|socket|connect
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5056, 63, 62), //sendto|recvfrom|sendmsg|recvmsg|shutdown|bind|listen|getsockname|getpeername|socketpair|setsockopt|getsockopt|clone
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5002, 77, 76), //read|write
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5004, 76, 75), //close
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5006, 75, 74), //fstat
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5031, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5023, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5020, 72, 71), //lseek|mmap|mprotect|munmap|brk|rt_sigaction|rt_sigprocmask|ioctl|pread64|pwrite64|readv|writev
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5028, 71, 70), //sched_yield|mremap|msync|mincore|madvise
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5032, 70, 69), //dup
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5057, 5, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5043, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5038, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5037, 66, 65), //nanosleep|getitimer|setitimer
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5042, 65, 64), //getpid|sendfile|socket|connect
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5056, 64, 63), //sendto|recvfrom|sendmsg|recvmsg|shutdown|bind|listen|getsockname|getpeername|socketpair|setsockopt|getsockopt|clone
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5070, 1, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5062, 62, 61), //execve|exit|wait4|kill|uname
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5077, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5076, 60, 59), //fcntl|flock|fsync|fdatasync|truncate|ftruncate
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5080, 59, 58), //getcwd|chdir|fchdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5134, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5110, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5093, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5091, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5090, 54, 53), //fchmod
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5092, 53, 52), //fchown
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5076, 61, 60), //fcntl|flock|fsync|fdatasync|truncate|ftruncate
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5132, 9, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5093, 5, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5091, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5089, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5080, 56, 55), //getcwd|chdir|fchdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5090, 55, 54), //fchmod
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5092, 54, 53), //fchown
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5110, 1, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5109, 52, 51), //umask|gettimeofday|getrlimit|getrusage|sysinfo|times|ptrace|getuid|syslog|getgid|setuid|setgid|geteuid|getegid|setpgid|getppid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5132, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5130, 50, 49), //setsid|setreuid|setregid|getgroups|setgroups|setresuid|getresuid|setresgid|getresgid|getpgid|setfsuid|setfsgid|getsid|capget|capset|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|sigaltstack
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5133, 49, 48), //personality
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5153, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5151, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5137, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5136, 45, 44), //statfs|fstatfs
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5150, 44, 43), //getpriority|setpriority|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|mlock|munlock|mlockall|munlockall
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5130, 51, 50), //setsid|setreuid|setregid|getgroups|setgroups|setresuid|getresuid|setresgid|getresgid|getpgid|setfsuid|setfsgid|getsid|capget|capset|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|sigaltstack
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5151, 5, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5137, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5134, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5133, 47, 46), //personality
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5136, 46, 45), //statfs|fstatfs
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5150, 45, 44), //getpriority|setpriority|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|mlock|munlock|mlockall|munlockall
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5153, 1, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5152, 43, 42), //pivot_root
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5164, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5162, 41, 40), //prctl|adjtimex|setrlimit|chroot|sync|acct|settimeofday|mount|umount2
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5167, 40, 39), //reboot|sethostname|setdomainname
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5244, 19, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5208, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5194, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5178, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5172, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5170, 34, 33), //init_module|delete_module
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5173, 33, 32), //quotactl
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5193, 32, 31), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5205, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5197, 30, 29), //futex|sched_setaffinity|sched_getaffinity
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5162, 42, 41), //prctl|adjtimex|setrlimit|chroot|sync|acct|settimeofday|mount|umount2
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5244, 21, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5208, 11, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5178, 5, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5172, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5168, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5167, 36, 35), //reboot|sethostname|setdomainname
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5170, 35, 34), //init_module|delete_module
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5173, 34, 33), //quotactl
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5205, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5194, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5193, 31, 30), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5198, 30, 29), //futex|sched_setaffinity|sched_getaffinity|cacheflush
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5206, 29, 28), //exit_group
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5237, 5, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5215, 3, 0),
@@ -70,11 +72,11 @@ BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5238, 21, 20), //waitid
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5243, 20, 19), //set_thread_area
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5297, 9, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5271, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5253, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5252, 3, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5247, 1, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5246, 15, 14), //inotify_add_watch|inotify_rm_watch
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5251, 14, 13), //openat|mkdirat|mknodat|fchownat
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5267, 13, 12), //unlinkat|renameat|linkat|symlinkat|readlinkat|fchmodat|faccessat|pselect6|ppoll|unshare|splice|sync_file_range|tee|vmsplice
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5267, 13, 12), //newfstatat|unlinkat|renameat|linkat|symlinkat|readlinkat|fchmodat|faccessat|pselect6|ppoll|unshare|splice|sync_file_range|tee|vmsplice
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5279, 1, 0),
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5276, 11, 10), //getcpu|epoll_pwait|ioprio_set|ioprio_get|utimensat
 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5295, 10, 9), //fallocate|timerfd_create|timerfd_gettime|timerfd_settime|signalfd4|eventfd2|epoll_create1|dup3|pipe2|inotify_init1|preadv|pwritev|rt_tgsigqueueinfo|perf_event_open|accept4|recvmmsg
index fd2179b..fe83af0 100644 (file)
@@ -51,10 +51,10 @@ static const size_t secondary_filter_size = x86_filter_size;
 #elif defined __mips__ || defined __mips64__
 
 #define DUAL_ARCH
-#define PRIMARY_ARCH AUDIT_ARCH_MIPS64
+#define PRIMARY_ARCH AUDIT_ARCH_MIPSEL64
 static const struct sock_filter* primary_filter = mips64_filter;
 static const size_t primary_filter_size = mips64_filter_size;
-#define SECONDARY_ARCH AUDIT_ARCH_MIPS
+#define SECONDARY_ARCH AUDIT_ARCH_MIPSEL
 static const struct sock_filter* secondary_filter = mips_filter;
 static const size_t secondary_filter_size = mips_filter_size;
 
index f2f58c6..ebc705c 100644 (file)
@@ -31,8 +31,9 @@
 #include <errno.h>
 #include <stdlib.h>
 
+#include <async_safe/log.h>
+
 #include "local.h"
-#include "private/libc_logging.h"
 
 size_t __fbufsize(FILE* fp) {
   return fp->_bf._size;
@@ -83,7 +84,7 @@ int __fsetlocking(FILE* fp, int type) {
 
   if (type != FSETLOCKING_INTERNAL && type != FSETLOCKING_BYCALLER) {
     // The API doesn't let us report an error, so blow up.
-    __libc_fatal("Bad type (%d) passed to __fsetlocking", type);
+    async_safe_fatal("Bad type (%d) passed to __fsetlocking", type);
   }
 
   _EXT(fp)->_caller_handles_locking = (type == FSETLOCKING_BYCALLER);
index 10ce674..510cb83 100644 (file)
@@ -1,4 +1,3 @@
-/*     $OpenBSD: exit.c,v 1.12 2007/09/03 14:40:16 millert Exp $ */
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
  * SUCH DAMAGE.
  */
 
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <stdlib.h>
 #include <unistd.h>
 
-/*
- * This variable is zero until a process has created a thread.
- * It is used to avoid calling locking functions in libc when they
- * are not required. By default, libc is intended to be(come)
- * thread-safe, but without a (significant) penalty to non-threaded
- * processes.
- */
-int     __isthreaded    = 0;
-
-/* BEGIN android-added: using __cxa_finalize and __cxa_thread_finalize */
 extern void __cxa_finalize(void* dso_handle);
 extern void __cxa_thread_finalize();
-/* END android-added */
 
-/*
- * Exit, flushing stdio buffers if necessary.
- */
-void
-exit(int status)
-{
-  /* BEGIN android-added: call thread_local d-tors */
+void exit(int status) {
   __cxa_thread_finalize();
-  /* END android-added */
-
-       /*
-        * Call functions registered by atexit() or _cxa_atexit()
-        * (including the stdio cleanup routine) and then _exit().
-        */
-       __cxa_finalize(NULL);
-       _exit(status);
+  __cxa_finalize(NULL);
+  _exit(status);
 }
index 0d70c81..d006045 100644 (file)
@@ -27,8 +27,9 @@
 #include <pthread.h>
 #include <signal.h>
 
+#include <async_safe/log.h>
+
 #include "private/bionic_prctl.h"
-#include "private/libc_logging.h"
 
 // Android gets these from "thread_private.h".
 #include "thread_private.h"
@@ -47,7 +48,7 @@ extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void
 static inline void
 _getentropy_fail(void)
 {
-       __libc_fatal("getentropy failed");
+       async_safe_fatal("getentropy failed");
 }
 
 volatile sig_atomic_t _rs_forked;
index caea45a..bec860b 100644 (file)
@@ -81,7 +81,4 @@ __LIBC_HIDDEN__ extern const short _C_tolower_[];
 __LIBC_HIDDEN__ extern char* __findenv(const char*, int, int*);
 __LIBC_HIDDEN__ extern char* _mktemp(char*);
 
-/* TODO: hide this when android_support.a is fixed (http://b/16298580).*/
-/*__LIBC_HIDDEN__*/ extern int __isthreaded;
-
 #endif
index c0dcd5d..668f008 100644 (file)
@@ -47,4 +47,5 @@ LIBC_PLATFORM {
     android_init_anonymous_namespace;
     android_create_namespace;
     android_link_namespaces;
+    android_get_exported_namespace;
 } LIBC_N;
index 3b797f7..8270fe9 100644 (file)
@@ -46,4 +46,5 @@ LIBC_PLATFORM {
     android_init_anonymous_namespace;
     android_create_namespace;
     android_link_namespaces;
+    android_get_exported_namespace;
 } LIBC_N;
index 6a95629..1a65b67 100644 (file)
@@ -94,6 +94,9 @@ bool __loader_android_link_namespaces(
 __attribute__((__weak__, visibility("default")))
 void __loader_android_dlwarning(void* obj, void (*f)(void*, const char*));
 
+__attribute__((__weak__, visibility("default")))
+struct android_namespace_t* __loader_android_get_exported_namespace(const char* name);
+
 // Proxy calls to bionic loader
 void* dlopen(const char* filename, int flag) {
   const void* caller_addr = __builtin_return_address(0);
@@ -128,6 +131,11 @@ _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) {
 }
 #endif
 
+/*
+ * This needs to be defined as weak because it is also defined in libc.a.
+ * Without this, static executables will have a multiple definition error.
+ */
+__attribute__((__weak__))
 int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data), void* data) {
   return __loader_dl_iterate_phdr(cb, data);
 }
@@ -182,3 +190,7 @@ bool android_link_namespaces(struct android_namespace_t* namespace_from,
 void android_dlwarning(void* obj, void (*f)(void*, const char*)) {
   __loader_android_dlwarning(obj, f);
 }
+
+struct android_namespace_t* android_get_exported_namespace(const char* name) {
+  return __loader_android_get_exported_namespace(name);
+}
index 245e016..a4c6483 100644 (file)
@@ -46,4 +46,5 @@ LIBC_PLATFORM {
     android_init_anonymous_namespace;
     android_create_namespace;
     android_link_namespaces;
+    android_get_exported_namespace;
 } LIBC_N;
index 3b797f7..8270fe9 100644 (file)
@@ -46,4 +46,5 @@ LIBC_PLATFORM {
     android_init_anonymous_namespace;
     android_create_namespace;
     android_link_namespaces;
+    android_get_exported_namespace;
 } LIBC_N;
index 3b797f7..8270fe9 100644 (file)
@@ -46,4 +46,5 @@ LIBC_PLATFORM {
     android_init_anonymous_namespace;
     android_create_namespace;
     android_link_namespaces;
+    android_get_exported_namespace;
 } LIBC_N;
index 3b797f7..8270fe9 100644 (file)
@@ -46,4 +46,5 @@ LIBC_PLATFORM {
     android_init_anonymous_namespace;
     android_create_namespace;
     android_link_namespaces;
+    android_get_exported_namespace;
 } LIBC_N;
index 3b797f7..8270fe9 100644 (file)
@@ -46,4 +46,5 @@ LIBC_PLATFORM {
     android_init_anonymous_namespace;
     android_create_namespace;
     android_link_namespaces;
+    android_get_exported_namespace;
 } LIBC_N;
index d617189..efd91ac 100644 (file)
@@ -9,6 +9,8 @@ cc_library_static {
 
     // We need to access Bionic private headers in the linker.
     include_dirs: ["bionic/libc"],
+
+    static_libs: ["libasync_safe"],
 }
 
 cc_binary {
index 0bc5a31..6195d40 100644 (file)
@@ -214,6 +214,10 @@ bool __android_link_namespaces(android_namespace_t* namespace_from,
   return success;
 }
 
+android_namespace_t* __android_get_exported_namespace(const char* name) {
+  return get_exported_namespace(name);
+}
+
 void __cfi_fail(uint64_t CallSiteTypeId, void* Ptr, void *DiagData, void *CallerPc) {
   CFIShadowWriter::CfiFail(CallSiteTypeId, Ptr, DiagData, CallerPc);
 }
@@ -256,9 +260,13 @@ static const char ANDROID_LIBDL_STRTAB[] =
   // 4*
   // 0000000 000111111111122222222223333 333333444444444455 555555556666666666777777777788888 888889999999999
   // 0123456 789012345678901234567890123 456789012345678901 234567890123456789012345678901234 567890123456789
-    "dlvsym\0__loader_android_dlwarning\0__loader_cfi_fail\0__loader_android_link_namespaces\0"
+    "dlvsym\0__loader_android_dlwarning\0__loader_cfi_fail\0__loader_android_link_namespaces\0__loader_androi"
+  // 5*
+  // 0000000000111111111122222 22222
+  // 0123456789012345678901234 56789
+    "d_get_exported_namespace\0"
 #if defined(__arm__)
-  // 485
+  // 525
     "__loader_dl_unwind_find_exidx\0"
 #endif
     ;
@@ -286,8 +294,9 @@ static ElfW(Sym) g_libdl_symtab[] = {
   ELFW(SYM_INITIALIZER)(407, &__android_dlwarning, 1),
   ELFW(SYM_INITIALIZER)(434, &__cfi_fail, 1),
   ELFW(SYM_INITIALIZER)(452, &__android_link_namespaces, 1),
+  ELFW(SYM_INITIALIZER)(485, &__android_get_exported_namespace, 1),
 #if defined(__arm__)
-  ELFW(SYM_INITIALIZER)(485, &__dl_unwind_find_exidx, 1),
+  ELFW(SYM_INITIALIZER)(525, &__dl_unwind_find_exidx, 1),
 #endif
 };
 
@@ -304,9 +313,9 @@ static ElfW(Sym) g_libdl_symtab[] = {
 // Note that adding any new symbols here requires stubbing them out in libdl.
 static unsigned g_libdl_buckets[1] = { 1 };
 #if defined(__arm__)
-static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0 };
+static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0 };
 #else
-static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0 };
+static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0 };
 #endif
 
 static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8)));
index 11a00f7..8e7a141 100644 (file)
@@ -46,6 +46,8 @@
 
 #include <android-base/scopeguard.h>
 
+#include <async_safe/log.h>
+
 // Private C library headers.
 
 #include "linker.h"
@@ -73,6 +75,7 @@
 #define ELF_ST_TYPE(x) (static_cast<uint32_t>(x) & 0xf)
 
 static android_namespace_t* g_anonymous_namespace = &g_default_namespace;
+static std::unordered_map<std::string, android_namespace_t*> g_exported_namespaces;
 
 static LinkerTypeAllocator<soinfo> g_soinfo_allocator;
 static LinkerTypeAllocator<LinkedListEntry<soinfo>> g_soinfo_links_allocator;
@@ -343,7 +346,7 @@ static void parse_LD_LIBRARY_PATH(const char* path) {
 
 static bool realpath_fd(int fd, std::string* realpath) {
   std::vector<char> buf(PATH_MAX), proc_self_fd(PATH_MAX);
-  __libc_format_buffer(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd);
+  async_safe_format_buffer(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd);
   if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) {
     PRINT("readlink(\"%s\") failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd);
     return false;
@@ -492,7 +495,7 @@ ProtectedDataGuard::ProtectedDataGuard() {
   }
 
   if (ref_count_ == 0) { // overflow
-    __libc_fatal("Too many nested calls to dlopen()");
+    async_safe_fatal("Too many nested calls to dlopen()");
   }
 }
 
@@ -991,7 +994,7 @@ static int open_library_in_zipfile(ZipArchiveCache* zip_archive_cache,
 }
 
 static bool format_path(char* buf, size_t buf_size, const char* path, const char* name) {
-  int n = __libc_format_buffer(buf, buf_size, "%s/%s", path, name);
+  int n = async_safe_format_buffer(buf, buf_size, "%s/%s", path, name);
   if (n < 0 || n >= static_cast<int>(buf_size)) {
     PRINT("Warning: ignoring very long library path: %s/%s", path, name);
     return false;
@@ -1077,7 +1080,7 @@ static int open_library(android_namespace_t* ns,
   }
 
   // TODO(dimitry): workaround for http://b/26394120 (the grey-list)
-  if (fd == -1 && ns != &g_default_namespace && is_greylisted(ns, name, needed_by)) {
+  if (fd == -1 && ns->is_greylist_enabled() && is_greylisted(ns, name, needed_by)) {
     // try searching for it on default_namespace default_library_path
     fd = open_library_on_paths(zip_archive_cache, name, file_offset,
                                g_default_namespace.get_default_library_paths(), realpath);
@@ -1780,7 +1783,7 @@ static void soinfo_unload(soinfo* soinfos[], size_t count) {
       }
     } else {
 #if !defined(__work_around_b_24465209__)
-      __libc_fatal("soinfo for \"%s\"@%p has no version", si->get_realpath(), si);
+      async_safe_fatal("soinfo for \"%s\"@%p has no version", si->get_realpath(), si);
 #else
       PRINT("warning: soinfo for \"%s\"@%p has no version", si->get_realpath(), si);
       for_each_dt_needed(si, [&] (const char* library_name) {
@@ -1854,8 +1857,8 @@ void do_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
   }
 
   if (buffer_size < required_size) {
-    __libc_fatal("android_get_LD_LIBRARY_PATH failed, buffer too small: "
-                 "buffer len %zu, required len %zu", buffer_size, required_size);
+    async_safe_fatal("android_get_LD_LIBRARY_PATH failed, buffer too small: "
+                     "buffer len %zu, required len %zu", buffer_size, required_size);
   }
 
   char* end = buffer;
@@ -2181,18 +2184,37 @@ android_namespace_t* create_namespace(const void* caller_addr,
   android_namespace_t* ns = new (g_namespace_allocator.alloc()) android_namespace_t();
   ns->set_name(name);
   ns->set_isolated((type & ANDROID_NAMESPACE_TYPE_ISOLATED) != 0);
-  ns->set_ld_library_paths(std::move(ld_library_paths));
-  ns->set_default_library_paths(std::move(default_library_paths));
-  ns->set_permitted_paths(std::move(permitted_paths));
+  ns->set_greylist_enabled((type & ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED) != 0);
 
   if ((type & ANDROID_NAMESPACE_TYPE_SHARED) != 0) {
+    // append parent namespace paths.
+    std::copy(parent_namespace->get_ld_library_paths().begin(),
+              parent_namespace->get_ld_library_paths().end(),
+              back_inserter(ld_library_paths));
+
+    std::copy(parent_namespace->get_default_library_paths().begin(),
+              parent_namespace->get_default_library_paths().end(),
+              back_inserter(default_library_paths));
+
+    std::copy(parent_namespace->get_permitted_paths().begin(),
+              parent_namespace->get_permitted_paths().end(),
+              back_inserter(permitted_paths));
+
     // If shared - clone the parent namespace
     add_soinfos_to_namespace(parent_namespace->soinfo_list(), ns);
+    // and copy parent namespace links
+    for (auto& link : parent_namespace->linked_namespaces()) {
+      ns->add_linked_namespace(link.linked_namespace(), link.shared_lib_sonames());
+    }
   } else {
     // If not shared - copy only the shared group
     add_soinfos_to_namespace(get_shared_group(parent_namespace), ns);
   }
 
+  ns->set_ld_library_paths(std::move(ld_library_paths));
+  ns->set_default_library_paths(std::move(default_library_paths));
+  ns->set_permitted_paths(std::move(permitted_paths));
+
   return ns;
 }
 
@@ -3470,6 +3492,9 @@ void init_default_namespace(const char* executable_path) {
     ns->set_permitted_paths(ns_config->permitted_paths());
 
     namespaces[ns_config->name()] = ns;
+    if (ns_config->visible()) {
+      g_exported_namespaces[ns_config->name()] = ns;
+    }
   }
 
   // 3. Establish links between namespaces
@@ -3494,3 +3519,16 @@ void init_default_namespace(const char* executable_path) {
 
   set_application_target_sdk_version(config->target_sdk_version());
 }
+
+// This function finds a namespace exported in ld.config.txt by its name.
+// A namespace can be exported by setting .visible property to true.
+android_namespace_t* get_exported_namespace(const char* name) {
+  if (name == nullptr) {
+    return nullptr;
+  }
+  auto it = g_exported_namespaces.find(std::string(name));
+  if (it == g_exported_namespaces.end()) {
+    return nullptr;
+  }
+  return it->second;
+}
index d5d4980..ae1ae3c 100644 (file)
@@ -38,7 +38,6 @@
 #include <unistd.h>
 
 #include "private/bionic_page.h"
-#include "private/libc_logging.h"
 #include "linked_list.h"
 #include "linker_common_types.h"
 #include "linker_logger.h"
@@ -156,6 +155,12 @@ enum {
    * permitted_path from the caller's namespace.
    */
   ANDROID_NAMESPACE_TYPE_SHARED = 2,
+
+  /* This flag instructs linker to enable grey-list workaround for the namespace.
+   * See http://b/26394120 for details.
+   */
+  ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000,
+
   ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED |
                                            ANDROID_NAMESPACE_TYPE_ISOLATED,
 };
@@ -173,4 +178,6 @@ bool link_namespaces(android_namespace_t* namespace_from,
                      android_namespace_t* namespace_to,
                      const char* shared_lib_sonames);
 
+android_namespace_t* get_exported_namespace(const char* name);
+
 #endif
index 723ea2b..fd6f496 100644 (file)
@@ -37,6 +37,8 @@
 #include <sys/mman.h>
 #include <unistd.h>
 
+#include <async_safe/log.h>
+
 #include "private/bionic_prctl.h"
 
 //
@@ -149,7 +151,7 @@ void LinkerSmallObjectAllocator::free(void* ptr) {
   ssize_t offset = reinterpret_cast<uintptr_t>(ptr) - sizeof(page_info);
 
   if (offset % block_size_ != 0) {
-    __libc_fatal("invalid pointer: %p (block_size=%zd)", ptr, block_size_);
+    async_safe_fatal("invalid pointer: %p (block_size=%zd)", ptr, block_size_);
   }
 
   memset(ptr, 0, block_size_);
@@ -180,7 +182,7 @@ linker_vector_t::iterator LinkerSmallObjectAllocator::find_page_record(void* ptr
 
   if (it == page_records_.end() || it->page_addr != addr) {
     // not found...
-    __libc_fatal("page record for %p was not found (block_size=%zd)", ptr, block_size_);
+    async_safe_fatal("page record for %p was not found (block_size=%zd)", ptr, block_size_);
   }
 
   return it;
@@ -203,7 +205,7 @@ void LinkerSmallObjectAllocator::alloc_page() {
   void* map_ptr = mmap(nullptr, PAGE_SIZE,
       PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
   if (map_ptr == MAP_FAILED) {
-    __libc_fatal("mmap failed");
+    async_safe_fatal("mmap failed");
   }
 
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, PAGE_SIZE, "linker_alloc_small_objects");
@@ -248,7 +250,7 @@ void* LinkerMemoryAllocator::alloc_mmap(size_t size) {
       PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
 
   if (map_ptr == MAP_FAILED) {
-    __libc_fatal("mmap failed");
+    async_safe_fatal("mmap failed");
   }
 
   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, allocated_size, "linker_alloc_lob");
@@ -283,7 +285,7 @@ void* LinkerMemoryAllocator::alloc(size_t size) {
 page_info* LinkerMemoryAllocator::get_page_info(void* ptr) {
   page_info* info = reinterpret_cast<page_info*>(PAGE_START(reinterpret_cast<size_t>(ptr)));
   if (memcmp(info->signature, kSignature, sizeof(kSignature)) != 0) {
-    __libc_fatal("invalid pointer %p (page signature mismatch)", ptr);
+    async_safe_fatal("invalid pointer %p (page signature mismatch)", ptr);
   }
 
   return info;
@@ -308,7 +310,7 @@ void* LinkerMemoryAllocator::realloc(void* ptr, size_t size) {
   } else {
     LinkerSmallObjectAllocator* allocator = get_small_object_allocator(info->type);
     if (allocator != info->allocator_addr) {
-      __libc_fatal("invalid pointer %p (page signature mismatch)", ptr);
+      async_safe_fatal("invalid pointer %p (page signature mismatch)", ptr);
     }
 
     old_size = allocator->get_block_size();
@@ -336,7 +338,7 @@ void LinkerMemoryAllocator::free(void* ptr) {
   } else {
     LinkerSmallObjectAllocator* allocator = get_small_object_allocator(info->type);
     if (allocator != info->allocator_addr) {
-      __libc_fatal("invalid pointer %p (invalid allocator address for the page)", ptr);
+      async_safe_fatal("invalid pointer %p (invalid allocator address for the page)", ptr);
     }
 
     allocator->free(ptr);
@@ -345,7 +347,7 @@ void LinkerMemoryAllocator::free(void* ptr) {
 
 LinkerSmallObjectAllocator* LinkerMemoryAllocator::get_small_object_allocator(uint32_t type) {
   if (type < kSmallObjectMinSizeLog2 || type > kSmallObjectMaxSizeLog2) {
-    __libc_fatal("invalid type: %u", type);
+    async_safe_fatal("invalid type: %u", type);
   }
 
   initialize_allocators();
index beffc52..80ae508 100644 (file)
@@ -37,8 +37,9 @@
 
 #include <vector>
 
+#include <async_safe/log.h>
+
 #include "private/bionic_prctl.h"
-#include "private/libc_logging.h"
 
 const uint32_t kSmallObjectMaxSizeLog2 = 10;
 const uint32_t kSmallObjectMinSizeLog2 = 4;
@@ -92,7 +93,7 @@ class linker_vector_allocator {
     if (ptr == MAP_FAILED) {
       // Spec says we need to throw std::bad_alloc here but because our
       // code does not support exception handling anyways - we are going to abort.
-      __libc_fatal("mmap failed");
+      async_safe_fatal("mmap failed");
     }
 
     prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, size, "linker_alloc_vector");
index a12cfbe..0a9aeab 100644 (file)
@@ -36,6 +36,8 @@
 #include <android-base/scopeguard.h>
 #include <android-base/strings.h>
 
+#include <async_safe/log.h>
+
 #include <stdlib.h>
 
 #include <string>
@@ -149,7 +151,7 @@ static std::string create_error_msg(const char* file,
                                     size_t lineno,
                                     const std::string& msg) {
   char buf[1024];
-  __libc_format_buffer(buf, sizeof(buf), "%s:%zu: error: %s", file, lineno, msg.c_str());
+  async_safe_format_buffer(buf, sizeof(buf), "%s:%zu: error: %s", file, lineno, msg.c_str());
 
   return std::string(buf);
 }
@@ -328,7 +330,7 @@ class Properties {
     params.push_back({ "LIB", kLibParamValue });
     if (target_sdk_version_ != 0) {
       char buf[16];
-      __libc_format_buffer(buf, sizeof(buf), "%d", target_sdk_version_);
+      async_safe_format_buffer(buf, sizeof(buf), "%d", target_sdk_version_);
       params.push_back({ "SDK_VER", buf });
     }
 
@@ -456,6 +458,7 @@ bool Config::read_binary_config(const char* ld_config_file_path,
     }
 
     ns_config->set_isolated(properties.get_bool(property_name_prefix + ".isolated"));
+    ns_config->set_visible(properties.get_bool(property_name_prefix + ".visible"));
 
     // these are affected by is_asan flag
     if (is_asan) {
index 4ec8b26..6f8bffb 100644 (file)
@@ -62,7 +62,7 @@ class NamespaceLinkConfig {
 class NamespaceConfig {
  public:
   explicit NamespaceConfig(const std::string& name)
-      : name_(name), isolated_(false)
+      : name_(name), isolated_(false), visible_(false)
   {}
 
   const char* name() const {
@@ -73,6 +73,10 @@ class NamespaceConfig {
     return isolated_;
   }
 
+  bool visible() const {
+    return visible_;
+  }
+
   const std::vector<std::string>& search_paths() const {
     return search_paths_;
   }
@@ -93,6 +97,10 @@ class NamespaceConfig {
     isolated_ = isolated;
   }
 
+  void set_visible(bool visible) {
+    visible_ = visible;
+  }
+
   void set_search_paths(std::vector<std::string>&& search_paths) {
     search_paths_ = search_paths;
   }
@@ -103,6 +111,7 @@ class NamespaceConfig {
  private:
   const std::string name_;
   bool isolated_;
+  bool visible_;
   std::vector<std::string> search_paths_;
   std::vector<std::string> permitted_paths_;
   std::vector<NamespaceLinkConfig> namespace_links_;
index 42796e9..7ceab08 100644 (file)
  * To enable/disable specific debug options, change the defines above
  *********************************************************************/
 
-#include "private/libc_logging.h"
 #include <unistd.h>
 
+#include <async_safe/log.h>
+
 __LIBC_HIDDEN__ extern int g_ld_debug_verbosity;
 
 #if LINKER_DEBUG_TO_LOG
 #define _PRINTVF(v, x...) \
     do { \
-      if (g_ld_debug_verbosity > (v)) __libc_format_log(5-(v), "linker", x); \
+      if (g_ld_debug_verbosity > (v)) async_safe_format_log(5-(v), "linker", x); \
     } while (0)
 #else /* !LINKER_DEBUG_TO_LOG */
 #define _PRINTVF(v, x...) \
     do { \
-      if (g_ld_debug_verbosity > (v)) { __libc_format_fd(1, x); write(1, "\n", 1); } \
+      if (g_ld_debug_verbosity > (v)) { async_safe_format_fd(1, x); write(1, "\n", 1); } \
     } while (0)
 #endif /* !LINKER_DEBUG_TO_LOG */
 
index 1ed479c..d8134af 100644 (file)
 
 #include <unordered_map>
 
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
 
 #define DL_ERR(fmt, x...) \
     do { \
-      __libc_format_buffer(linker_get_error_buffer(), linker_get_error_buffer_size(), fmt, ##x); \
+      async_safe_format_buffer(linker_get_error_buffer(), linker_get_error_buffer_size(), fmt, ##x); \
       /* If LD_DEBUG is set high enough, log every dlerror(3) message. */ \
     } while (false)
 
 #define DL_WARN(fmt, x...) \
     do { \
-      __libc_format_log(ANDROID_LOG_WARN, "linker", fmt, ##x); \
-      __libc_format_fd(2, "WARNING: linker: "); \
-      __libc_format_fd(2, fmt, ##x); \
-      __libc_format_fd(2, "\n"); \
+      async_safe_format_log(ANDROID_LOG_WARN, "linker", fmt, ##x); \
+      async_safe_format_fd(2, "WARNING: linker: "); \
+      async_safe_format_fd(2, fmt, ##x); \
+      async_safe_format_fd(2, "\n"); \
     } while (false)
 
 #define DL_ERR_AND_LOG(fmt, x...) \
index e7b23e0..11e0f40 100644 (file)
@@ -26,8 +26,8 @@
  * SUCH DAMAGE.
  */
 
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
 
 void* __find_icu_symbol(const char* symbol_name __attribute__((__unused__))) {
-  __libc_fatal("__find_icu_symbol should not be called in the linker");
+  async_safe_fatal("__find_icu_symbol should not be called in the linker");
 }
index 717667c..4c6603b 100644 (file)
 #include <string>
 #include <vector>
 
+#include <async_safe/log.h>
+
 #include "android-base/strings.h"
 #include "private/CachedProperty.h"
-#include "private/libc_logging.h"
 
 LinkerLogger g_linker_logger;
 bool g_greylist_disabled = false;
@@ -59,8 +60,8 @@ static uint32_t ParseProperty(const std::string& value) {
     } else if (o == "dlsym") {
       flags |= kLogDlsym;
     } else {
-      __libc_format_log(ANDROID_LOG_WARN, "linker", "Ignoring unknown debug.ld option \"%s\"",
-                        o.c_str());
+      async_safe_format_log(ANDROID_LOG_WARN, "linker", "Ignoring unknown debug.ld option \"%s\"",
+                            o.c_str());
     }
   }
 
@@ -95,8 +96,8 @@ void LinkerLogger::ResetState() {
   bool old_value = g_greylist_disabled;
   g_greylist_disabled = (strcmp(greylist_disabled.Get(), "true") == 0);
   if (g_greylist_disabled != old_value) {
-    __libc_format_log(ANDROID_LOG_INFO, "linker", "%s greylist",
-                      g_greylist_disabled ? "Disabling" : "Enabling");
+    async_safe_format_log(ANDROID_LOG_INFO, "linker", "%s greylist",
+                          g_greylist_disabled ? "Disabling" : "Enabling");
   }
 
   flags_ = 0;
@@ -124,6 +125,6 @@ void LinkerLogger::Log(uint32_t type, const char* format, ...) {
 
   va_list ap;
   va_start(ap, format);
-  __libc_format_log_va_list(ANDROID_LOG_DEBUG, "linker", format, ap);
+  async_safe_format_log_va_list(ANDROID_LOG_DEBUG, "linker", format, ap);
   va_end(ap);
 }
index 40f82a1..3d26e91 100644 (file)
@@ -45,6 +45,8 @@
 #include "debuggerd/handler.h"
 #endif
 
+#include <async_safe/log.h>
+
 #include <vector>
 
 extern void __libc_init_globals(KernelArgumentBlock&);
@@ -189,7 +191,7 @@ static const char* get_executable_path() {
     char path[PATH_MAX];
     ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path));
     if (path_len == -1 || path_len >= static_cast<ssize_t>(sizeof(path))) {
-      __libc_fatal("readlink('/proc/self/exe') failed: %s", strerror(errno));
+      async_safe_fatal("readlink('/proc/self/exe') failed: %s", strerror(errno));
     }
     executable_path = std::string(path, path_len);
   }
@@ -267,13 +269,13 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
   // the executable could be unlinked by this point and it should
   // not cause a crash (see http://b/31084669)
   if (TEMP_FAILURE_RETRY(stat("/proc/self/exe", &file_stat)) != 0) {
-    __libc_fatal("unable to stat \"/proc/self/exe\": %s", strerror(errno));
+    async_safe_fatal("unable to stat \"/proc/self/exe\": %s", strerror(errno));
   }
 
   const char* executable_path = get_executable_path();
   soinfo* si = soinfo_alloc(&g_default_namespace, executable_path, &file_stat, 0, RTLD_GLOBAL);
   if (si == nullptr) {
-    __libc_fatal("Couldn't allocate soinfo: out of memory?");
+    async_safe_fatal("Couldn't allocate soinfo: out of memory?");
   }
 
   /* bootstrap the link map, the main exe always needs to be first */
@@ -319,7 +321,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
     // tombstone for them. The tombstone never provided any detail relevant to
     // fixing the problem anyway, and the utility of drawing extra attention
     // to the problem is non-existent at this late date.
-    __libc_format_fd(STDERR_FILENO,
+    async_safe_format_fd(STDERR_FILENO,
                      "\"%s\": error: Android 5.0 and later only support "
                      "position-independent executables (-fPIE).\n",
                      g_argv[0]);
@@ -335,7 +337,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
   init_default_namespace(executable_path);
 
   if (!si->prelink_image()) {
-    __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
+    async_safe_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
   }
 
   // add somain to global group
@@ -369,10 +371,10 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
                       nullptr,
                       true /* add_as_children */,
                       true /* search_linked_namespaces */)) {
-    __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
+    async_safe_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
   } else if (needed_libraries_count == 0) {
     if (!si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr)) {
-      __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
+      async_safe_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
     }
     si->increment_ref_count();
   }
@@ -380,7 +382,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
   add_vdso(args);
 
   if (!get_cfi_shadow()->InitialLinkDone(solist)) {
-    __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
+    async_safe_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", g_argv[0], linker_get_error_buffer());
   }
 
   si->call_pre_init_constructors();
@@ -464,7 +466,7 @@ static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf) {
 }
 
 static void __linker_cannot_link(const char* argv0) {
-  __libc_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", argv0, linker_get_error_buffer());
+  async_safe_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", argv0, linker_get_error_buffer());
 }
 
 /*
@@ -546,7 +548,7 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) {
   // This happens when user tries to run 'adb shell /system/bin/linker'
   // see also https://code.google.com/p/android/issues/detail?id=63174
   if (reinterpret_cast<ElfW(Addr)>(&_start) == entry_point) {
-    __libc_format_fd(STDOUT_FILENO,
+    async_safe_format_fd(STDOUT_FILENO,
                      "This is %s, the helper program for dynamic executables.\n",
                      args.argv[0]);
     exit(0);
index f8852e1..472c4e8 100644 (file)
@@ -32,7 +32,7 @@
 #include <sys/cdefs.h>
 #include <unistd.h>
 
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
 
 static LinkerMemoryAllocator g_linker_allocator;
 static pid_t fallback_tid = 0;
@@ -41,7 +41,7 @@ static pid_t fallback_tid = 0;
 // case the linker heap is corrupted. Do not use this function.
 extern "C" void __linker_enable_fallback_allocator() {
   if (fallback_tid != 0) {
-    __libc_fatal("attempted to use currently-in-use fallback allocator");
+    async_safe_fatal("attempted to use currently-in-use fallback allocator");
   }
 
   fallback_tid = gettid();
@@ -49,7 +49,7 @@ extern "C" void __linker_enable_fallback_allocator() {
 
 extern "C" void __linker_disable_fallback_allocator() {
   if (fallback_tid == 0) {
-    __libc_fatal("attempted to disable unused fallback allocator");
+    async_safe_fatal("attempted to disable unused fallback allocator");
   }
 
   fallback_tid = 0;
index e7d9b2e..1099b6b 100644 (file)
@@ -48,6 +48,10 @@ struct android_namespace_link_t {
     return linked_namespace_;
   }
 
+  const std::unordered_set<std::string>& shared_lib_sonames() const {
+    return shared_lib_sonames_;
+  }
+
   bool is_accessible(const char* soname) const {
     return shared_lib_sonames_.find(soname) != shared_lib_sonames_.end();
   }
@@ -59,7 +63,7 @@ struct android_namespace_link_t {
 
 struct android_namespace_t {
  public:
-  android_namespace_t() : name_(nullptr), is_isolated_(false) {}
+  android_namespace_t() : name_(nullptr), is_isolated_(false), is_greylist_enabled_(false) {}
 
   const char* get_name() const { return name_; }
   void set_name(const char* name) { name_ = name; }
@@ -67,6 +71,9 @@ struct android_namespace_t {
   bool is_isolated() const { return is_isolated_; }
   void set_isolated(bool isolated) { is_isolated_ = isolated; }
 
+  bool is_greylist_enabled() const { return is_greylist_enabled_; }
+  void set_greylist_enabled(bool enabled) { is_greylist_enabled_ = enabled; }
+
   const std::vector<std::string>& get_ld_library_paths() const {
     return ld_library_paths_;
   }
@@ -132,6 +139,7 @@ struct android_namespace_t {
  private:
   const char* name_;
   bool is_isolated_;
+  bool is_greylist_enabled_;
   std::vector<std::string> ld_library_paths_;
   std::vector<std::string> default_library_paths_;
   std::vector<std::string> permitted_paths_;
index 74b69e4..01e127d 100644 (file)
@@ -31,6 +31,8 @@
 
 #include <stdint.h>
 
+#include <async_safe/log.h>
+
 #include "linker_debug.h"
 
 // Helper classes for decoding LEB128, used in packed relocation data.
@@ -50,7 +52,7 @@ class sleb128_decoder {
 
     do {
       if (current_ >= end_) {
-        __libc_fatal("sleb128_decoder ran out of bounds");
+        async_safe_fatal("sleb128_decoder ran out of bounds");
       }
       byte = *current_++;
       value |= (static_cast<size_t>(byte & 127) << shift);
index 1d59dbb..fbff7cf 100644 (file)
@@ -34,6 +34,8 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include <async_safe/log.h>
+
 #include "linker_debug.h"
 #include "linker_globals.h"
 #include "linker_logger.h"
@@ -636,7 +638,7 @@ ElfW(Addr) soinfo::resolve_symbol_address(const ElfW(Sym)* s) const {
 
 const char* soinfo::get_string(ElfW(Word) index) const {
   if (has_min_version(1) && (index >= strtab_size_)) {
-    __libc_fatal("%s: strtab out of bounds error; STRSZ=%zd, name=%d",
+    async_safe_fatal("%s: strtab out of bounds error; STRSZ=%zd, name=%d",
         get_realpath(), strtab_size_, index);
   }
 
index 61c43c9..8284bea 100644 (file)
@@ -51,9 +51,6 @@ LOCAL_SRC_FILES := \
   ../linker_config.cpp \
   ../linker_utils.cpp \
 
-# for __libc_fatal
-LOCAL_SRC_FILES += ../../libc/bionic/libc_logging.cpp
-
-LOCAL_STATIC_LIBRARIES += libbase
+LOCAL_STATIC_LIBRARIES += libasync_safe libbase
 
 include $(BUILD_NATIVE_TEST)
index 418cbda..5e51113 100644 (file)
@@ -58,6 +58,7 @@ static const char* config_str =
   "namespace.default.links = system\n"
   "namespace.default.link.system.shared_libs = libc.so:libm.so:libdl.so:libstdc++.so\n"
   "namespace.system.isolated = true\n"
+  "namespace.system.visible = true\n"
   "namespace.system.search.paths = /system/${LIB}\n"
   "namespace.system.permitted.paths = /system/${LIB}\n"
   "namespace.system.asan.search.paths = /data:/system/${LIB}\n"
@@ -137,6 +138,7 @@ static void run_linker_config_smoke_test(bool is_asan) {
   ASSERT_TRUE(default_ns_config != nullptr);
 
   ASSERT_TRUE(default_ns_config->isolated());
+  ASSERT_FALSE(default_ns_config->visible());
   ASSERT_EQ(kExpectedDefaultSearchPath, default_ns_config->search_paths());
   ASSERT_EQ(kExpectedDefaultPermittedPath, default_ns_config->permitted_paths());
 
@@ -163,6 +165,7 @@ static void run_linker_config_smoke_test(bool is_asan) {
   ASSERT_TRUE(ns_system != nullptr) << "system namespace was not found";
 
   ASSERT_TRUE(ns_system->isolated());
+  ASSERT_TRUE(ns_system->visible());
   ASSERT_EQ(kExpectedSystemSearchPath, ns_system->search_paths());
   ASSERT_EQ(kExpectedSystemPermittedPath, ns_system->permitted_paths());
 }
index 27cc954..4605267 100644 (file)
@@ -52,12 +52,14 @@ cc_test_library {
     defaults: ["bionic_tests_defaults"],
     srcs: [
         "arpa_inet_test.cpp",
+        "async_safe_test.cpp",
         "assert_test.cpp",
         "buffer_tests.cpp",
         "bug_26110743_test.cpp",
         "complex_test.cpp",
         "ctype_test.cpp",
         "dirent_test.cpp",
+        "elf_test.cpp",
         "endian_test.cpp",
         "error_test.cpp",
         "eventfd_test.cpp",
@@ -71,7 +73,6 @@ cc_test_library {
         "inttypes_test.cpp",
         "langinfo_test.cpp",
         "leak_test.cpp",
-        "libc_logging_test.cpp",
         "libgen_basename_test.cpp",
         "libgen_test.cpp",
         "linux_swab_test.cpp",
@@ -150,6 +151,12 @@ cc_test_library {
         "external/tinyxml2",
     ],
 
+    target: {
+        android: {
+            whole_static_libs: ["libasync_safe"],
+        },
+    },
+
     static_libs: [
         "libtinyxml2",
         "liblog",
similarity index 55%
rename from tests/libc_logging_test.cpp
rename to tests/async_safe_test.cpp
index 4150483..3d6fcaa 100644 (file)
 #include <gtest/gtest.h>
 
 #if defined(__BIONIC__)
-#include "../libc/bionic/libc_logging.cpp"
-extern int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...);
+#include <async_safe/log.h>
 #endif // __BIONIC__
 
-TEST(libc_logging, smoke) {
+TEST(async_safe_log, smoke) {
 #if defined(__BIONIC__)
   char buf[BUFSIZ];
 
-  __libc_format_buffer(buf, sizeof(buf), "a");
+  async_safe_format_buffer(buf, sizeof(buf), "a");
   EXPECT_STREQ("a", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "%%");
+  async_safe_format_buffer(buf, sizeof(buf), "%%");
   EXPECT_STREQ("%", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "01234");
+  async_safe_format_buffer(buf, sizeof(buf), "01234");
   EXPECT_STREQ("01234", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%sb", "01234");
+  async_safe_format_buffer(buf, sizeof(buf), "a%sb", "01234");
   EXPECT_STREQ("a01234b", buf);
 
   char* s = NULL;
-  __libc_format_buffer(buf, sizeof(buf), "a%sb", s);
+  async_safe_format_buffer(buf, sizeof(buf), "a%sb", s);
   EXPECT_STREQ("a(null)b", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "aa%scc", "bb");
+  async_safe_format_buffer(buf, sizeof(buf), "aa%scc", "bb");
   EXPECT_STREQ("aabbcc", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%cc", 'b');
+  async_safe_format_buffer(buf, sizeof(buf), "a%cc", 'b');
   EXPECT_STREQ("abc", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%db", 1234);
+  async_safe_format_buffer(buf, sizeof(buf), "a%db", 1234);
   EXPECT_STREQ("a1234b", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%db", -8123);
+  async_safe_format_buffer(buf, sizeof(buf), "a%db", -8123);
   EXPECT_STREQ("a-8123b", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%hdb", static_cast<short>(0x7fff0010));
+  async_safe_format_buffer(buf, sizeof(buf), "a%hdb", static_cast<short>(0x7fff0010));
   EXPECT_STREQ("a16b", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%hhdb", static_cast<char>(0x7fffff10));
+  async_safe_format_buffer(buf, sizeof(buf), "a%hhdb", static_cast<char>(0x7fffff10));
   EXPECT_STREQ("a16b", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%lldb", 0x1000000000LL);
+  async_safe_format_buffer(buf, sizeof(buf), "a%lldb", 0x1000000000LL);
   EXPECT_STREQ("a68719476736b", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%ldb", 70000L);
+  async_safe_format_buffer(buf, sizeof(buf), "a%ldb", 70000L);
   EXPECT_STREQ("a70000b", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%pb", reinterpret_cast<void*>(0xb0001234));
+  async_safe_format_buffer(buf, sizeof(buf), "a%pb", reinterpret_cast<void*>(0xb0001234));
   EXPECT_STREQ("a0xb0001234b", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%xz", 0x12ab);
+  async_safe_format_buffer(buf, sizeof(buf), "a%xz", 0x12ab);
   EXPECT_STREQ("a12abz", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%Xz", 0x12ab);
+  async_safe_format_buffer(buf, sizeof(buf), "a%Xz", 0x12ab);
   EXPECT_STREQ("a12ABz", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%08xz", 0x123456);
+  async_safe_format_buffer(buf, sizeof(buf), "a%08xz", 0x123456);
   EXPECT_STREQ("a00123456z", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%5dz", 1234);
+  async_safe_format_buffer(buf, sizeof(buf), "a%5dz", 1234);
   EXPECT_STREQ("a 1234z", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%05dz", 1234);
+  async_safe_format_buffer(buf, sizeof(buf), "a%05dz", 1234);
   EXPECT_STREQ("a01234z", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%8dz", 1234);
+  async_safe_format_buffer(buf, sizeof(buf), "a%8dz", 1234);
   EXPECT_STREQ("a    1234z", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%-8dz", 1234);
+  async_safe_format_buffer(buf, sizeof(buf), "a%-8dz", 1234);
   EXPECT_STREQ("a1234    z", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "A%-11sZ", "abcdef");
+  async_safe_format_buffer(buf, sizeof(buf), "A%-11sZ", "abcdef");
   EXPECT_STREQ("Aabcdef     Z", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "A%s:%dZ", "hello", 1234);
+  async_safe_format_buffer(buf, sizeof(buf), "A%s:%dZ", "hello", 1234);
   EXPECT_STREQ("Ahello:1234Z", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%03d:%d:%02dz", 5, 5, 5);
+  async_safe_format_buffer(buf, sizeof(buf), "a%03d:%d:%02dz", 5, 5, 5);
   EXPECT_STREQ("a005:5:05z", buf);
 
   void* p = NULL;
-  __libc_format_buffer(buf, sizeof(buf), "a%d,%pz", 5, p);
+  async_safe_format_buffer(buf, sizeof(buf), "a%d,%pz", 5, p);
   EXPECT_STREQ("a5,0x0z", buf);
 
-  __libc_format_buffer(buf, sizeof(buf), "a%lld,%d,%d,%dz", 0x1000000000LL, 6, 7, 8);
+  async_safe_format_buffer(buf, sizeof(buf), "a%lld,%d,%d,%dz", 0x1000000000LL, 6, 7, 8);
   EXPECT_STREQ("a68719476736,6,7,8z", buf);
 #else // __BIONIC__
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
 
-TEST(libc_logging, d_INT_MAX) {
+TEST(async_safe_log, d_INT_MAX) {
 #if defined(__BIONIC__)
   char buf[BUFSIZ];
-  __libc_format_buffer(buf, sizeof(buf), "%d", INT_MAX);
+  async_safe_format_buffer(buf, sizeof(buf), "%d", INT_MAX);
   EXPECT_STREQ("2147483647", buf);
 #else // __BIONIC__
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
 
-TEST(libc_logging, d_INT_MIN) {
+TEST(async_safe_log, d_INT_MIN) {
 #if defined(__BIONIC__)
   char buf[BUFSIZ];
-  __libc_format_buffer(buf, sizeof(buf), "%d", INT_MIN);
+  async_safe_format_buffer(buf, sizeof(buf), "%d", INT_MIN);
   EXPECT_STREQ("-2147483648", buf);
 #else // __BIONIC__
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
 
-TEST(libc_logging, ld_LONG_MAX) {
+TEST(async_safe_log, ld_LONG_MAX) {
 #if defined(__BIONIC__)
   char buf[BUFSIZ];
-  __libc_format_buffer(buf, sizeof(buf), "%ld", LONG_MAX);
+  async_safe_format_buffer(buf, sizeof(buf), "%ld", LONG_MAX);
 #if defined(__LP64__)
   EXPECT_STREQ("9223372036854775807", buf);
 #else
@@ -143,10 +142,10 @@ TEST(libc_logging, ld_LONG_MAX) {
 #endif // __BIONIC__
 }
 
-TEST(libc_logging, ld_LONG_MIN) {
+TEST(async_safe_log, ld_LONG_MIN) {
 #if defined(__BIONIC__)
   char buf[BUFSIZ];
-  __libc_format_buffer(buf, sizeof(buf), "%ld", LONG_MIN);
+  async_safe_format_buffer(buf, sizeof(buf), "%ld", LONG_MIN);
 #if defined(__LP64__)
   EXPECT_STREQ("-9223372036854775808", buf);
 #else
@@ -157,32 +156,32 @@ TEST(libc_logging, ld_LONG_MIN) {
 #endif // __BIONIC__
 }
 
-TEST(libc_logging, lld_LLONG_MAX) {
+TEST(async_safe_log, lld_LLONG_MAX) {
 #if defined(__BIONIC__)
   char buf[BUFSIZ];
-  __libc_format_buffer(buf, sizeof(buf), "%lld", LLONG_MAX);
+  async_safe_format_buffer(buf, sizeof(buf), "%lld", LLONG_MAX);
   EXPECT_STREQ("9223372036854775807", buf);
 #else // __BIONIC__
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
 
-TEST(libc_logging, lld_LLONG_MIN) {
+TEST(async_safe_log, lld_LLONG_MIN) {
 #if defined(__BIONIC__)
   char buf[BUFSIZ];
-  __libc_format_buffer(buf, sizeof(buf), "%lld", LLONG_MIN);
+  async_safe_format_buffer(buf, sizeof(buf), "%lld", LLONG_MIN);
   EXPECT_STREQ("-9223372036854775808", buf);
 #else // __BIONIC__
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
 
-TEST(libc_logging, buffer_overrun) {
+TEST(async_safe_log, buffer_overrun) {
 #if defined(__BIONIC__)
   char buf[BUFSIZ];
-  ASSERT_EQ(11, __libc_format_buffer(buf, sizeof(buf), "hello %s", "world"));
+  ASSERT_EQ(11, async_safe_format_buffer(buf, sizeof(buf), "hello %s", "world"));
   EXPECT_STREQ("hello world", buf);
-  ASSERT_EQ(11, __libc_format_buffer(buf, 8, "hello %s", "world"));
+  ASSERT_EQ(11, async_safe_format_buffer(buf, 8, "hello %s", "world"));
   EXPECT_STREQ("hello w", buf);
 #else // __BIONIC__
   GTEST_LOG_(INFO) << "This test does nothing.\n";
index 6b943ce..dea92ee 100644 (file)
@@ -55,6 +55,12 @@ enum {
    * permitted_path from the caller's namespace.
    */
   ANDROID_NAMESPACE_TYPE_SHARED = 2,
+
+  /* This flag instructs linker to enable grey-list workaround for the namespace.
+   * See http://b/26394120 for details.
+   */
+  ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000,
+
   ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED |
                                            ANDROID_NAMESPACE_TYPE_ISOLATED,
 };
index 35dff2a..e3ee7d7 100644 (file)
@@ -26,6 +26,7 @@
 #include <unistd.h>
 
 #include <android/dlext.h>
+#include <android-base/strings.h>
 
 #include <linux/memfd.h>
 #include <sys/mman.h>
@@ -464,7 +465,8 @@ protected:
     EXPECT_EQ(1729U, *taxicab_number);
   }
 
-  void SpawnChildrenAndMeasurePss(const char* lib, bool share_relro, size_t* pss_out);
+  void SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file, bool share_relro,
+                                  size_t* pss_out);
 
   android_dlextinfo extinfo_;
 };
@@ -510,19 +512,23 @@ TEST_F(DlExtRelroSharingTest, VerifyMemorySaving) {
   ASSERT_NOERROR(pipe(pipefd));
 
   size_t without_sharing, with_sharing;
-  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, false, &without_sharing));
-  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, true, &with_sharing));
+  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.filename, false, &without_sharing));
+  ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(kLibName, tf.filename, true, &with_sharing));
+  ASSERT_LT(with_sharing, without_sharing);
 
-  // We expect the sharing to save at least 10% of the total PSS. In practice
-  // it saves 40%+ for this test.
-  size_t expected_size = without_sharing - (without_sharing/10);
-  EXPECT_LT(with_sharing, expected_size);
+  // We expect the sharing to save at least 50% of the library's total PSS.
+  // In practice it saves 80%+ for this library in the test.
+  size_t pss_saved = without_sharing - with_sharing;
+  size_t expected_min_saved = without_sharing / 2;
+
+  EXPECT_LT(expected_min_saved, pss_saved);
 
   // Use destructor of tf to close and unlink the file.
   tf.fd = extinfo_.relro_fd;
 }
 
-void getPss(pid_t pid, size_t* pss_out) {
+void GetPss(bool shared_relro, const char* lib, const char* relro_file, pid_t pid,
+            size_t* total_pss) {
   pm_kernel_t* kernel;
   ASSERT_EQ(0, pm_kernel_create(&kernel));
 
@@ -533,21 +539,28 @@ void getPss(pid_t pid, size_t* pss_out) {
   size_t num_maps;
   ASSERT_EQ(0, pm_process_maps(process, &maps, &num_maps));
 
-  size_t total_pss = 0;
-  for (size_t i = 0; i < num_maps; i++) {
-    pm_memusage_t usage;
-    ASSERT_EQ(0, pm_map_usage(maps[i], &usage));
-    total_pss += usage.pss;
+  // Calculate total PSS of the library.
+  *total_pss = 0;
+  bool saw_relro_file = false;
+  for (size_t i = 0; i < num_maps; ++i) {
+    if (android::base::EndsWith(maps[i]->name, lib) || strcmp(maps[i]->name, relro_file) == 0) {
+      if (strcmp(maps[i]->name, relro_file) == 0) saw_relro_file = true;
+
+      pm_memusage_t usage;
+      ASSERT_EQ(0, pm_map_usage(maps[i], &usage));
+      *total_pss += usage.pss;
+    }
   }
-  *pss_out = total_pss;
 
   free(maps);
   pm_process_destroy(process);
   pm_kernel_destroy(kernel);
+
+  if (shared_relro) ASSERT_TRUE(saw_relro_file);
 }
 
-void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, bool share_relro,
-                                                       size_t* pss_out) {
+void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, const char* relro_file,
+                                                       bool share_relro, size_t* pss_out) {
   const int CHILDREN = 20;
 
   // Create children
@@ -600,11 +613,11 @@ void DlExtRelroSharingTest::SpawnChildrenAndMeasurePss(const char* lib, bool sha
     childpipe[i] = parent_done_pipe[1];
   }
 
-  // Sum the PSS of all the children
+  // Sum the PSS of tested library of all the children
   size_t total_pss = 0;
   for (int i=0; i<CHILDREN; ++i) {
     size_t child_pss;
-    ASSERT_NO_FATAL_FAILURE(getPss(child_pids[i], &child_pss));
+    ASSERT_NO_FATAL_FAILURE(GetPss(share_relro, lib, relro_file, child_pids[i], &child_pss));
     total_pss += child_pss;
   }
   *pss_out = total_pss;
@@ -1037,7 +1050,7 @@ TEST(dlext, ns_unload_between_namespaces) {
             "\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
 }
 
-TEST(dlext, ns_greylist) {
+TEST(dlext, ns_greylist_enabled) {
   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
 
   const std::string ns_search_path = get_testlib_root() + "/private_namespace_libs";
@@ -1046,7 +1059,7 @@ TEST(dlext, ns_greylist) {
           android_create_namespace("namespace",
                                    nullptr,
                                    ns_search_path.c_str(),
-                                   ANDROID_NAMESPACE_TYPE_ISOLATED,
+                                   ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED,
                                    nullptr,
                                    nullptr);
 
@@ -1075,6 +1088,31 @@ TEST(dlext, ns_greylist) {
   ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
 }
 
+TEST(dlext, ns_greylist_disabled_by_default) {
+  ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
+
+  const std::string ns_search_path = get_testlib_root() + "/private_namespace_libs";
+
+  android_namespace_t* ns =
+          android_create_namespace("namespace",
+                                   nullptr,
+                                   ns_search_path.c_str(),
+                                   ANDROID_NAMESPACE_TYPE_ISOLATED,
+                                   nullptr,
+                                   nullptr);
+
+  ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
+
+  android_dlextinfo extinfo;
+  extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
+  extinfo.library_namespace = ns;
+
+  android_set_application_target_sdk_version(__ANDROID_API_M__);
+  void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
+  ASSERT_TRUE(handle == nullptr);
+  ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
+}
+
 TEST(dlext, ns_cyclic_namespaces) {
   // Test that ns1->ns2->ns1 link does not break the loader
   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
@@ -1350,6 +1388,70 @@ TEST(dlext, ns_shared) {
   dlclose(handle2);
 }
 
+TEST(dlext, ns_shared_links_and_paths) {
+  // Create parent namespace (isolated, not shared)
+  android_namespace_t* ns_isolated =
+          android_create_namespace("private_isolated",
+                                   nullptr,
+                                   (get_testlib_root() + "/private_namespace_libs").c_str(),
+                                   ANDROID_NAMESPACE_TYPE_ISOLATED,
+                                   (get_testlib_root() + "/public_namespace_libs").c_str(),
+                                   nullptr);
+  ASSERT_TRUE(ns_isolated != nullptr) << dlerror();
+  ASSERT_TRUE(android_link_namespaces(ns_isolated, nullptr, g_core_shared_libs.c_str())) << dlerror();
+
+  // Create shared namespace with ns_isolated parent
+  android_namespace_t* ns_shared =
+          android_create_namespace("private_shared",
+                                   nullptr,
+                                   nullptr,
+                                   ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED,
+                                   nullptr,
+                                   ns_isolated);
+  ASSERT_TRUE(ns_shared != nullptr) << dlerror();
+
+  // 1. Load a library in ns_shared to check that it has inherited
+  // search path and the link to the default namespace.
+  android_dlextinfo extinfo;
+  extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
+  extinfo.library_namespace = ns_shared;
+
+  {
+    void* handle = android_dlopen_ext("libnstest_private.so", RTLD_NOW, &extinfo);
+    ASSERT_TRUE(handle != nullptr) << dlerror();
+    const char** ns_private_extern_string = static_cast<const char**>(dlsym(handle, "g_private_extern_string"));
+    ASSERT_TRUE(ns_private_extern_string != nullptr) << dlerror();
+    ASSERT_STREQ("This string is from private namespace", *ns_private_extern_string);
+
+    dlclose(handle);
+  }
+  // 2. Load another test library by absolute path to check that
+  // it has inherited permitted_when_isolated_path
+  {
+    void* handle = android_dlopen_ext(
+            (get_testlib_root() + "/public_namespace_libs/libnstest_public.so").c_str(),
+            RTLD_NOW,
+            &extinfo);
+
+    ASSERT_TRUE(handle != nullptr) << dlerror();
+    const char** ns_public_extern_string = static_cast<const char**>(dlsym(handle, "g_public_extern_string"));
+    ASSERT_TRUE(ns_public_extern_string != nullptr) << dlerror();
+    ASSERT_STREQ("This string is from public namespace", *ns_public_extern_string);
+
+    dlclose(handle);
+  }
+
+  // 3. Check that it is still isolated.
+  {
+    void* handle = android_dlopen_ext(
+            (get_testlib_root() + "/libtest_empty.so").c_str(),
+            RTLD_NOW,
+            &extinfo);
+
+    ASSERT_TRUE(handle == nullptr);
+  }
+}
+
 TEST(dlext, ns_shared_dlclose) {
   android_set_application_target_sdk_version(42U); // something > 23
 
index 4ff324e..4901d50 100644 (file)
@@ -247,6 +247,40 @@ TEST(dlfcn, dlopen_by_soname) {
 
 // mips doesn't support ifuncs
 #if !defined(__mips__)
+TEST(dlfcn, ifunc_variable) {
+  typedef const char* (*fn_ptr)();
+
+  // ifunc's choice depends on whether IFUNC_CHOICE has a value
+  // first check the set case
+  setenv("IFUNC_CHOICE", "set", 1);
+  // preload libtest_ifunc_variable_impl.so
+  void* handle_impl = dlopen("libtest_ifunc_variable_impl.so", RTLD_NOW);
+  void* handle = dlopen("libtest_ifunc_variable.so", RTLD_NOW);
+  ASSERT_TRUE(handle != nullptr) << dlerror();
+  const char** foo_ptr = reinterpret_cast<const char**>(dlsym(handle, "foo"));
+  fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
+  ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
+  ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
+  ASSERT_EQ(strncmp("set", *foo_ptr, 3), 0);
+  ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0);
+  dlclose(handle);
+  dlclose(handle_impl);
+
+  // then check the unset case
+  unsetenv("IFUNC_CHOICE");
+  handle_impl = dlopen("libtest_ifunc_variable_impl.so", RTLD_NOW);
+  handle = dlopen("libtest_ifunc_variable.so", RTLD_NOW);
+  ASSERT_TRUE(handle != nullptr) << dlerror();
+  foo_ptr = reinterpret_cast<const char**>(dlsym(handle, "foo"));
+  foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
+  ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
+  ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
+  ASSERT_EQ(strncmp("unset", *foo_ptr, 5), 0);
+  ASSERT_EQ(strncmp("unset", foo_library_ptr(), 5), 0);
+  dlclose(handle);
+  dlclose(handle_impl);
+}
+
 TEST(dlfcn, ifunc) {
   typedef const char* (*fn_ptr)();
 
@@ -254,11 +288,11 @@ TEST(dlfcn, ifunc) {
   // first check the set case
   setenv("IFUNC_CHOICE", "set", 1);
   void* handle = dlopen("libtest_ifunc.so", RTLD_NOW);
-  ASSERT_TRUE(handle != nullptr);
+  ASSERT_TRUE(handle != nullptr) << dlerror();
   fn_ptr foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
   fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
-  ASSERT_TRUE(foo_ptr != nullptr);
-  ASSERT_TRUE(foo_library_ptr != nullptr);
+  ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
+  ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
   ASSERT_EQ(strncmp("set", foo_ptr(), 3), 0);
   ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0);
   dlclose(handle);
@@ -266,22 +300,17 @@ TEST(dlfcn, ifunc) {
   // then check the unset case
   unsetenv("IFUNC_CHOICE");
   handle = dlopen("libtest_ifunc.so", RTLD_NOW);
-  ASSERT_TRUE(handle != nullptr);
+  ASSERT_TRUE(handle != nullptr) << dlerror();
   foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
   foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
-  ASSERT_TRUE(foo_ptr != nullptr);
-  ASSERT_TRUE(foo_library_ptr != nullptr);
+  ASSERT_TRUE(foo_ptr != nullptr) << dlerror();
+  ASSERT_TRUE(foo_library_ptr != nullptr) << dlerror();
   ASSERT_EQ(strncmp("unset", foo_ptr(), 5), 0);
-  ASSERT_EQ(strncmp("unset", foo_library_ptr(), 3), 0);
+  ASSERT_EQ(strncmp("unset", foo_library_ptr(), 5), 0);
   dlclose(handle);
 }
 
-// ld.gold for arm produces incorrect binary (see http://b/27930475 for details)
-#if defined(__arm__)
-TEST(dlfcn, KNOWN_FAILURE_ON_BIONIC(ifunc_ctor_call)) {
-#else
 TEST(dlfcn, ifunc_ctor_call) {
-#endif
   typedef const char* (*fn_ptr)();
 
   void* handle = dlopen("libtest_ifunc.so", RTLD_NOW);
@@ -296,12 +325,7 @@ TEST(dlfcn, ifunc_ctor_call) {
   dlclose(handle);
 }
 
-// ld.gold for arm produces incorrect binary (see http://b/27930475 for details)
-#if defined(__arm__)
-TEST(dlfcn, KNOWN_FAILURE_ON_BIONIC(ifunc_ctor_call_rtld_lazy)) {
-#else
 TEST(dlfcn, ifunc_ctor_call_rtld_lazy) {
-#endif
   typedef const char* (*fn_ptr)();
 
   void* handle = dlopen("libtest_ifunc.so", RTLD_LAZY);
diff --git a/tests/elf_test.cpp b/tests/elf_test.cpp
new file mode 100644 (file)
index 0000000..ad7cdfa
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <elf.h>
+
+#include <gtest/gtest.h>
+
+// https://github.com/android-ndk/ndk/issues/377
+TEST(elf, have_ELF_ST_INFO_macros) {
+  uint8_t info;
+
+  // 0x0f
+  info = ELF32_ST_INFO(STB_LOCAL, STT_HIPROC);
+  ASSERT_EQ(STB_LOCAL, ELF32_ST_BIND(info));
+  ASSERT_EQ(STT_HIPROC, ELF32_ST_TYPE(info));
+
+  // 0x0f
+  info = ELF64_ST_INFO(STB_LOCAL, STT_HIPROC);
+  ASSERT_EQ(STB_LOCAL, ELF64_ST_BIND(info));
+  ASSERT_EQ(STT_HIPROC, ELF64_ST_TYPE(info));
+
+  // 0xf0
+  info = ELF32_ST_INFO(STB_LOCAL, STT_HIPROC);
+  ASSERT_EQ(STB_LOCAL, ELF32_ST_BIND(info));
+  ASSERT_EQ(STT_HIPROC, ELF32_ST_TYPE(info));
+
+  // 0xf0
+  info = ELF64_ST_INFO(STB_LOCAL, STT_HIPROC);
+  ASSERT_EQ(STB_LOCAL, ELF64_ST_BIND(info));
+  ASSERT_EQ(STT_HIPROC, ELF64_ST_TYPE(info));
+}
index 67103e1..984a657 100644 (file)
@@ -219,7 +219,6 @@ TEST_F(DEATHTEST, memchr_fortified2) {
 #endif // __BIONIC__
 }
 
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strlcpy_fortified2) {
 #if defined(__BIONIC__)
   foo myfoo;
@@ -231,7 +230,6 @@ TEST_F(DEATHTEST, strlcpy_fortified2) {
 #endif // __BIONIC__
 }
 
-// this buffer overflow. TODO: Fix clang.
 TEST_F(DEATHTEST, strlcat_fortified2) {
 #if defined(__BIONIC__)
   foo myfoo;
@@ -407,11 +405,8 @@ TEST_F(DEATHTEST, sprintf_fortified) {
   ASSERT_FORTIFY(sprintf(buf, "%s", source_buf));
 }
 
-#ifdef __clang__
-// Exists upstream, but hasn't been pulled in yet.
-#if __has_attribute(alloc_size)
-#error "Reenable this test"
-#endif
+#ifdef __clang__ && !__has_attribute(alloc_size)
+// TODO: remove this after Clang prebuilt rebase.
 #else
 // This test is disabled in clang because clang doesn't properly detect
 // this buffer overflow. TODO: Fix clang.
index 5f28321..227b6d1 100644 (file)
@@ -1065,7 +1065,7 @@ static bool PickOptions(std::vector<char*>& args, IsolationTestOptions& options)
       gtest_filter_str = "-bionic_selftest*";
     } else {
       // Find if '-' for NEGATIVE_PATTERNS exists.
-      if (gtest_filter_str.find("-") != std::string::npos) {
+      if (gtest_filter_str.find('-') != std::string::npos) {
         gtest_filter_str += ":bionic_selftest*";
       } else {
         gtest_filter_str += ":-bionic_selftest*";
index 9ddb2ff..a356640 100644 (file)
@@ -49,28 +49,61 @@ static size_t GetMappingSize() {
   return result;
 }
 
-#define LEAK_TEST(test_case_name, test_name)                                                 \
-  static void __leak_test__##test_case_name##__##test_name();                                \
-  TEST(test_case_name, test_name) {                                                          \
-    auto previous_size = GetMappingSize();                                                   \
-    __leak_test__##test_case_name##__##test_name();                                          \
-    auto current_size = GetMappingSize();                                                    \
-    if (current_size > previous_size) {                                                      \
-      FAIL() << "increase in process map size: " << previous_size << " -> " << current_size; \
-    }                                                                                        \
-  }                                                                                          \
-  static void __leak_test__##test_case_name##__##test_name()
-
-LEAK_TEST(leak, smoke) {
-  // Do nothing.
+static void WaitUntilAllExited(pid_t* pids, size_t pid_count) {
+  // Wait until all children have exited.
+  bool alive = true;
+  while (alive) {
+    alive = false;
+    for (size_t i = 0; i < pid_count; ++i) {
+      if (pids[i] != 0) {
+        if (kill(pids[i], 0) == 0) {
+          alive = true;
+        } else {
+          EXPECT_EQ(errno, ESRCH);
+          pids[i] = 0;  // Skip in next loop.
+        }
+      }
+    }
+  }
 }
 
-LEAK_TEST(leak, xfail) {
-  UNUSED(mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
+class LeakChecker {
+ public:
+  LeakChecker() {
+    Reset();
+  }
+
+  ~LeakChecker() {
+    Check();
+  }
+
+  void Reset() {
+    previous_size_ = GetMappingSize();
+  }
+
+  void DumpTo(std::ostream& os) const {
+    os << previous_size_;
+  }
+
+ private:
+  size_t previous_size_;
+
+  void Check() {
+    auto current_size = GetMappingSize();
+    if (current_size > previous_size_) {
+      FAIL() << "increase in process map size: " << previous_size_ << " -> " << current_size;
+    }
+  }
+};
+
+std::ostream& operator<<(std::ostream& os, const LeakChecker& lc) {
+  lc.DumpTo(os);
+  return os;
 }
 
 // http://b/36045112
-LEAK_TEST(pthread_leak, join) {
+TEST(pthread_leak, join) {
+  LeakChecker lc;
   for (int i = 0; i < 100; ++i) {
     pthread_t thread;
     ASSERT_EQ(0, pthread_create(&thread, nullptr, [](void*) -> void* { return nullptr; }, nullptr));
@@ -79,22 +112,42 @@ LEAK_TEST(pthread_leak, join) {
 }
 
 // http://b/36045112
-LEAK_TEST(pthread_leak, detach) {
-  pthread_barrier_t barrier;
-  constexpr int thread_count = 100;
-  ASSERT_EQ(0, pthread_barrier_init(&barrier, nullptr, thread_count + 1));
-  for (int i = 0; i < thread_count; ++i) {
-    pthread_t thread;
-    const auto thread_function = +[](void* barrier) -> void* {
-      pthread_barrier_wait(static_cast<pthread_barrier_t*>(barrier));
-      return nullptr;
-    };
-    ASSERT_EQ(0, pthread_create(&thread, nullptr, thread_function, &barrier));
-    ASSERT_EQ(0, pthread_detach(thread));
+TEST(pthread_leak, detach) {
+  LeakChecker lc;
+
+  for (size_t pass = 0; pass < 2; ++pass) {
+    pthread_barrier_t barrier;
+    constexpr int thread_count = 100;
+    ASSERT_EQ(pthread_barrier_init(&barrier, nullptr, thread_count + 1), 0);
+
+    // Start child threads.
+    struct thread_data { pthread_barrier_t* barrier; pid_t* tid; };
+    pid_t tids[thread_count];
+    for (int i = 0; i < thread_count; ++i) {
+      thread_data* td = new thread_data{&barrier, &tids[i]};
+      const auto thread_function = +[](void* ptr) -> void* {
+        thread_data* data = static_cast<thread_data*>(ptr);
+        *data->tid = gettid();
+        pthread_barrier_wait(data->barrier);
+        // Doing this delete allocates new VMAs for jemalloc bookkeeping,
+        // but the two-pass nature of this test means we can check that
+        // it's a pool rather than an unbounded leak.
+        delete data;
+        return nullptr;
+      };
+      pthread_t thread;
+      ASSERT_EQ(0, pthread_create(&thread, nullptr, thread_function, td));
+      ASSERT_EQ(0, pthread_detach(thread));
+    }
+
+    pthread_barrier_wait(&barrier);
+    ASSERT_EQ(pthread_barrier_destroy(&barrier), 0);
+
+    WaitUntilAllExited(tids, arraysize(tids));
+
+    // houdini keeps a thread pool, so we ignore the first pass while the
+    // pool fills, but then on the second pass require that the "pool" isn't
+    // actually an unbounded leak. https://issuetracker.google.com/37920774.
+    if (pass == 0) lc.Reset();
   }
-
-  pthread_barrier_wait(&barrier);
-
-  // Give the threads some time to exit.
-  std::this_thread::sleep_for(100ms);
 }
index a031fe9..973a8d2 100644 (file)
@@ -272,10 +272,8 @@ cc_test_library {
 cc_test_library {
     name: "libtest_ifunc",
     defaults: ["bionic_testlib_defaults"],
-    srcs: ["dlopen_testlib_ifunc.c"],
+    srcs: ["dlopen_testlib_ifunc.cpp"],
 
-    // TODO(dimitry): clang does not support ifunc attribute
-    clang: false,
     arch: {
         mips: {
             enabled: false,
@@ -284,6 +282,64 @@ cc_test_library {
             enabled: false,
         },
     },
+
+    target: {
+        android: {
+            shared_libs: ["libdl"],
+        },
+        host: {
+            host_ldlibs: ["-ldl"],
+        },
+    },
+}
+
+cc_test_library {
+    name: "libtest_ifunc_variable",
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["dlopen_testlib_ifunc_variable.cpp"],
+    shared_libs: [ "libtest_ifunc_variable_impl" ],
+
+    arch: {
+        mips: {
+            enabled: false,
+        },
+        mips64: {
+            enabled: false,
+        },
+    },
+
+    target: {
+        android: {
+            shared_libs: ["libdl"],
+        },
+        host: {
+            host_ldlibs: ["-ldl"],
+        },
+    },
+}
+
+cc_test_library {
+    name: "libtest_ifunc_variable_impl",
+    defaults: ["bionic_testlib_defaults"],
+    srcs: ["dlopen_testlib_ifunc_variable_impl.cpp"],
+
+    arch: {
+        mips: {
+            enabled: false,
+        },
+        mips64: {
+            enabled: false,
+        },
+    },
+
+    target: {
+        android: {
+            shared_libs: ["libdl"],
+        },
+        host: {
+            host_ldlibs: ["-ldl"],
+        },
+    },
 }
 
 // -----------------------------------------------------------------------------
index 37499ba..0220ae2 100644 (file)
@@ -22,55 +22,47 @@ BIONIC_TESTS_ZIPALIGN := $(HOST_OUT_EXECUTABLES)/bionic_tests_zipalign
 
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE := libdlext_test_zip_zipaligned
 LOCAL_MODULE_SUFFIX := .zip
-LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE_PATH := $($(bionic_2nd_arch_prefix)TARGET_OUT_DATA_NATIVE_TESTS)/bionic-loader-test-libs/libdlext_test_zip
 LOCAL_2ND_ARCH_VAR_PREFIX := $(bionic_2nd_arch_prefix)
 
 include $(BUILD_SYSTEM)/base_rules.mk
 
 my_shared_libs := \
-  $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libdlext_test_zip.so \
-  $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libatest_simple_zip.so
+  $(call intermediates-dir-for,SHARED_LIBRARIES,libdlext_test_zip,,,$(bionic_2nd_arch_prefix))/libdlext_test_zip.so \
+  $(call intermediates-dir-for,SHARED_LIBRARIES,libatest_simple_zip,,,$(bionic_2nd_arch_prefix))/libatest_simple_zip.so
 
-$(LOCAL_BUILT_MODULE) : $(my_shared_libs) | $(BIONIC_TESTS_ZIPALIGN)
+$(LOCAL_BUILT_MODULE): PRIVATE_SHARED_LIBS := $(my_shared_libs)
+$(LOCAL_BUILT_MODULE): $(my_shared_libs) $(BIONIC_TESTS_ZIPALIGN)
        @echo "Aligning zip: $@"
        $(hide) rm -rf $(dir $@) && mkdir -p $(dir $@)/libdir
-       $(hide) cp $^ $(dir $@)/libdir
+       $(hide) cp $(PRIVATE_SHARED_LIBS) $(dir $@)/libdir
        $(hide) (cd $(dir $@) && touch empty_file.txt && zip -qrD0 $(notdir $@).unaligned empty_file.txt libdir/*.so)
        $(hide) $(BIONIC_TESTS_ZIPALIGN) 4096 $@.unaligned $@
 
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE := libdlext_test_runpath_zip_zipaligned
 LOCAL_MODULE_SUFFIX := .zip
-LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE_PATH := $($(bionic_2nd_arch_prefix)TARGET_OUT_DATA_NATIVE_TESTS)/bionic-loader-test-libs/libdlext_test_runpath_zip
 LOCAL_2ND_ARCH_VAR_PREFIX := $(bionic_2nd_arch_prefix)
 
 include $(BUILD_SYSTEM)/base_rules.mk
-my_shared_libs := \
-  $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_d_zip.so \
-  $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_b.so \
-  $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_a.so \
-  $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_c.so \
-  $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_x.so
-
+lib_d := $(call intermediates-dir-for,SHARED_LIBRARIES,libtest_dt_runpath_d_zip,,,$(bionic_2nd_arch_prefix))/libtest_dt_runpath_d_zip.so
+lib_a := $(call intermediates-dir-for,SHARED_LIBRARIES,libtest_dt_runpath_a,,,$(bionic_2nd_arch_prefix))/libtest_dt_runpath_a.so
+lib_b := $(call intermediates-dir-for,SHARED_LIBRARIES,libtest_dt_runpath_b,,,$(bionic_2nd_arch_prefix))/libtest_dt_runpath_b.so
+lib_c := $(call intermediates-dir-for,SHARED_LIBRARIES,libtest_dt_runpath_c,,,$(bionic_2nd_arch_prefix))/libtest_dt_runpath_c.so
+lib_x := $(call intermediates-dir-for,SHARED_LIBRARIES,libtest_dt_runpath_x,,,$(bionic_2nd_arch_prefix))/libtest_dt_runpath_x.so
 
-$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_D := \
-  $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_d_zip.so
-$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_A := \
-  $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_a.so
-$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_B := \
-  $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_b.so
-$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_C := \
-  $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_c.so
-$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_X := \
-  $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libtest_dt_runpath_x.so
-$(LOCAL_BUILT_MODULE) : $(my_shared_libs) | $(BIONIC_TESTS_ZIPALIGN)
+$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_D := $(lib_d)
+$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_A := $(lib_a)
+$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_B := $(lib_b)
+$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_C := $(lib_c)
+$(LOCAL_BUILT_MODULE) : PRIVATE_LIB_X := $(lib_x)
+$(LOCAL_BUILT_MODULE) : $(lib_d) $(lib_a) $(lib_b) $(lib_c) $(lib_x) $(BIONIC_TESTS_ZIPALIGN)
        @echo "Aligning zip: $@"
        $(hide) rm -rf $(dir $@) && mkdir -p $(dir $@)/libdir && \
     mkdir -p $(dir $@)/libdir/dt_runpath_a && mkdir -p $(dir $@)/libdir/dt_runpath_b_c_x
index 8e31474..56183ba 100644 (file)
@@ -142,7 +142,7 @@ int main(int argc, char* argv[]) {
   if (return_value != 0) {
     CloseArchive(handle);
     fprintf(stderr, "Unable to open '%s': %s\n", argv[2], ErrorCodeString(return_value));
-    return false;
+    return 1;
   }
 
   FILE* zip_dst = fopen(argv[3], "we");
similarity index 65%
rename from tests/libs/dlopen_testlib_ifunc.c
rename to tests/libs/dlopen_testlib_ifunc.cpp
index b68a3dd..f8acba7 100644 (file)
  * limitations under the License.
  */
 
+#include <dlfcn.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 
-static int g_flag = 0;
+static uintptr_t g_flag = 0;
 
 static void __attribute__((constructor)) init_flag() {
-  g_flag = 1;
+  g_flag = reinterpret_cast<uintptr_t>(dlsym(RTLD_DEFAULT, "dlsym"));
 }
 
 static const char* is_ctor_called() __attribute__ ((ifunc("is_ctor_called_ifun")));
 
-const char* foo() __attribute__ ((ifunc ("foo_ifunc")));
+extern "C" const char* foo() __attribute__ ((ifunc ("foo_ifunc")));
 
 // Static linker creates GLOBAL/IFUNC symbol and JUMP_SLOT relocation type for plt segment
-const char* is_ctor_called_jump_slot() __attribute__ ((ifunc("is_ctor_called_ifun")));
+extern "C" const char* is_ctor_called_jump_slot() __attribute__ ((ifunc("is_ctor_called_ifun")));
 
-const char* is_ctor_called_irelative() {
+extern "C" const char* is_ctor_called_irelative() {
   // Call internal ifunc-resolved function with IRELATIVE reloc
   return is_ctor_called();
 }
 
-const char* return_true() {
+extern "C" const char* return_true() {
   return "true";
 }
 
-const char* return_false() {
+extern "C" const char* return_false() {
   return "false";
 }
 
-const char* f1() {
+extern "C" const char* f1() {
   return "unset";
 }
 
-const char* f2() {
+extern "C" const char* f2() {
   return "set";
 }
 
-void* is_ctor_called_ifun() {
+typedef const char* (*fn_ptr)();
+
+extern "C" fn_ptr is_ctor_called_ifun() {
   return g_flag == 0 ? return_false : return_true;
 }
 
-void* foo_ifunc() {
+extern "C" fn_ptr foo_ifunc() {
    char* choice = getenv("IFUNC_CHOICE");
    return choice == NULL ? f1 : f2;
 }
 
-const char* foo_library() {
+extern "C" const char* foo_library() {
    return foo();
 }
diff --git a/tests/libs/dlopen_testlib_ifunc_variable.cpp b/tests/libs/dlopen_testlib_ifunc_variable.cpp
new file mode 100644 (file)
index 0000000..a1f1ab6
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern "C" const char* foo;
+
+extern "C" const char* foo_library() {
+   return foo;
+}
diff --git a/tests/libs/dlopen_testlib_ifunc_variable_impl.cpp b/tests/libs/dlopen_testlib_ifunc_variable_impl.cpp
new file mode 100644 (file)
index 0000000..a550fef
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dlfcn.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static uintptr_t g_flag = 0;
+
+static void __attribute__((constructor)) init_flag() {
+  g_flag = reinterpret_cast<uintptr_t>(dlsym(RTLD_DEFAULT, "dlsym"));
+}
+
+static const char* is_ctor_called() __attribute__ ((ifunc("is_ctor_called_ifun")));
+
+extern "C" const char* foo() __attribute__ ((ifunc ("foo_ifunc")));
+
+// Static linker creates GLOBAL/IFUNC symbol and JUMP_SLOT relocation type for plt segment
+extern "C" const char* is_ctor_called_jump_slot() __attribute__ ((ifunc("is_ctor_called_ifun")));
+
+extern "C" const char* is_ctor_called_irelative() {
+  // Call internal ifunc-resolved function with IRELATIVE reloc
+  return is_ctor_called();
+}
+
+extern "C" const char* var_true = "true";
+extern "C" const char* var_false = "false";
+
+extern "C" const char* v1 = "unset";
+extern "C" const char* v2 = "set";
+
+extern "C" void* is_ctor_called_ifun() {
+  return g_flag == 0 ? &var_false : &var_true;
+}
+
+extern "C" void* foo_ifunc() {
+   char* choice = getenv("IFUNC_CHOICE");
+   return choice == NULL ? &v1 : &v2;
+}
index 8fba1c4..a7b9d52 100644 (file)
@@ -500,3 +500,10 @@ TEST(malloc, verify_alignment) {
   delete[] values_64;
   delete[] values_ldouble;
 }
+
+TEST(malloc, mallopt_smoke) {
+  errno = 0;
+  ASSERT_EQ(0, mallopt(-1000, 1));
+  // mallopt doesn't set errno.
+  ASSERT_EQ(0, errno);
+}
index 87b4c81..d64bc48 100755 (executable)
@@ -1963,8 +1963,9 @@ static void BarrierTestHelper(BarrierTestHelperArg* arg) {
     } else {
       ASSERT_EQ(0, result);
     }
-    arg->data->finished_mask |= (1 << arg->id);
-    if (arg->data->finished_mask == ((1 << arg->data->thread_count) - 1)) {
+    int mask = arg->data->finished_mask.fetch_or(1 << arg->id);
+    mask |= 1 << arg->id;
+    if (mask == ((1 << arg->data->thread_count) - 1)) {
       ASSERT_EQ(1, arg->data->serial_thread_count);
       arg->data->finished_iteration_count++;
       arg->data->finished_mask = 0;
index 1f2cb96..c47bc4f 100755 (executable)
@@ -8,7 +8,6 @@ if [ "$1" = glibc ]; then
         cd ${ANDROID_BUILD_TOP}
         export ANDROID_DATA=${TARGET_OUT_DATA}
         export ANDROID_ROOT=${TARGET_OUT}
-        export LD_LIBRARY_PATH=${HOST_OUT}/obj/lib/
         ${HOST_OUT}/nativetest64/bionic-unit-tests-glibc/bionic-unit-tests-glibc $@
     )
     exit 0
index 385fe33..0d42b05 100644 (file)
@@ -1372,20 +1372,56 @@ TEST(STRING_TEST, memcmp_overread) {
   RunCmpBufferOverreadTest(DoMemcmpTest, DoMemcmpFailTest);
 }
 
+static void DoMemchrTest(uint8_t* buf, size_t len) {
+  if (len >= 1) {
+    int value = len % 128;
+    int search_value = (len % 128) + 1;
+    memset(buf, value, len);
+    // The buffer does not contain the search value.
+    ASSERT_EQ(nullptr, memchr(buf, search_value, len));
+    if (len >= 2) {
+      buf[0] = search_value;
+      // The search value is the first element in the buffer.
+      ASSERT_EQ(&buf[0], memchr(buf, search_value, len));
+
+      buf[0] = value;
+      buf[len - 1] = search_value;
+      // The search value is the last element in the buffer.
+      ASSERT_EQ(&buf[len - 1], memchr(buf, search_value, len));
+    }
+  }
+}
+
+TEST(STRING_TEST, memchr_align) {
+  RunSingleBufferAlignTest(MEDIUM, DoMemchrTest);
+}
+
+TEST(STRING_TEST, memchr_overread) {
+  RunSingleBufferOverreadTest(DoMemchrTest);
+}
+
 static void DoStrchrTest(uint8_t* buf, size_t len) {
   if (len >= 1) {
     char value = 32 + (len % 96);
     char search_value = 33 + (len % 96);
     memset(buf, value, len - 1);
-    buf[len-1] = '\0';
-    ASSERT_EQ(NULL, strchr(reinterpret_cast<char*>(buf), search_value));
-    ASSERT_EQ(reinterpret_cast<char*>(&buf[len-1]), strchr(reinterpret_cast<char*>(buf), '\0'));
+    buf[len - 1] = '\0';
+    // The buffer does not contain the search value.
+    ASSERT_EQ(nullptr, strchr(reinterpret_cast<char*>(buf), search_value));
+    // Search for the special '\0' character.
+    ASSERT_EQ(reinterpret_cast<char*>(&buf[len - 1]), strchr(reinterpret_cast<char*>(buf), '\0'));
     if (len >= 2) {
       buf[0] = search_value;
-      ASSERT_EQ(reinterpret_cast<char*>(&buf[0]), strchr(reinterpret_cast<char*>(buf), search_value));
+      // The search value is the first element in the buffer.
+      ASSERT_EQ(reinterpret_cast<char*>(&buf[0]), strchr(reinterpret_cast<char*>(buf),
+                                                         search_value));
+
       buf[0] = value;
-      buf[len-2] = search_value;
-      ASSERT_EQ(reinterpret_cast<char*>(&buf[len-2]), strchr(reinterpret_cast<char*>(buf), search_value));
+      buf[len - 2] = search_value;
+      // The search value is the second to last element in the buffer.
+      // The last element is the '\0' character.
+      ASSERT_EQ(reinterpret_cast<char*>(&buf[len - 2]), strchr(reinterpret_cast<char*>(buf),
+                                                               search_value));
     }
   }
 }
@@ -1398,6 +1434,40 @@ TEST(STRING_TEST, strchr_overread) {
   RunSingleBufferOverreadTest(DoStrchrTest);
 }
 
+static void DoStrrchrTest(uint8_t* buf, size_t len) {
+  if (len >= 1) {
+    char value = 32 + (len % 96);
+    char search_value = 33 + (len % 96);
+    memset(buf, value, len - 1);
+    buf[len - 1] = '\0';
+    // The buffer does not contain the search value.
+    ASSERT_EQ(nullptr, strrchr(reinterpret_cast<char*>(buf), search_value));
+    // Search for the special '\0' character.
+    ASSERT_EQ(reinterpret_cast<char*>(&buf[len - 1]), strrchr(reinterpret_cast<char*>(buf), '\0'));
+    if (len >= 2) {
+      buf[0] = search_value;
+      // The search value is the first element in the buffer.
+      ASSERT_EQ(reinterpret_cast<char*>(&buf[0]), strrchr(reinterpret_cast<char*>(buf),
+                                                          search_value));
+
+      buf[0] = value;
+      buf[len - 2] = search_value;
+      // The search value is the second to last element in the buffer.
+      // The last element is the '\0' character.
+      ASSERT_EQ(reinterpret_cast<char*>(&buf[len - 2]), strrchr(reinterpret_cast<char*>(buf),
+                                                                search_value));
+    }
+  }
+}
+
+TEST(STRING_TEST, strrchr_align) {
+  RunSingleBufferAlignTest(MEDIUM, DoStrrchrTest);
+}
+
+TEST(STRING_TEST, strrchr_overread) {
+  RunSingleBufferOverreadTest(DoStrrchrTest);
+}
+
 static void TestBasename(const char* in, const char* expected_out) {
   errno = 0;
   const char* out = basename(in);
index 69638be..00322ec 100644 (file)
@@ -266,7 +266,7 @@ TEST(sys_ptrace, watchpoint_imprecise) {
   ASSERT_EQ(0, sigaction(SIGALRM, &action, &oldaction)) << strerror(errno);
   alarm(5);
 
-  run_watchpoint_test<Uint128_t>(watchpoint_imprecise_child, 8, 8);
+  run_watchpoint_test<Uint128_t>(watchpoint_imprecise_child, 8, sizeof(void*));
 
   ASSERT_EQ(0, sigaction(SIGALRM, &oldaction, nullptr)) << strerror(errno);
 }
index d8d83c5..eaf2b8f 100644 (file)
@@ -98,3 +98,19 @@ TEST(sys_sem, semtimedop_failure) {
   ASSERT_EQ(-1, semtimedop(-1, nullptr, 0, nullptr));
   ASSERT_TRUE(errno == EINVAL || errno == ENOSYS);
 }
+
+TEST(sys_sem, union_semun) {
+  // https://github.com/android-ndk/ndk/issues/400
+#if defined(__BIONIC__)
+  semun arg;
+  semid_ds i1;
+  seminfo i2;
+  unsigned short a[] = { 1u, 2u };
+  arg.val = 123;
+  arg.buf = &i1;
+  arg.array = a;
+  arg.__buf = &i2;
+#else
+  // glibc already mostly removed this cruft (although it's still in <linux/sem.h>).
+#endif
+}
index 2e9b994..81df350 100644 (file)
@@ -45,6 +45,8 @@
 
 #if defined(__linux__)
 
+#include <sys/sysmacros.h>
+
 struct map_record {
   uintptr_t addr_start;
   uintptr_t addr_end;
diff --git a/tools/versioner/dependencies b/tools/versioner/dependencies
new file mode 120000 (symlink)
index 0000000..4ec3391
--- /dev/null
@@ -0,0 +1 @@
+../../libc/versioner-dependencies
\ No newline at end of file
index 215dc3c..1b631b6 100644 (file)
@@ -42,6 +42,7 @@
 #include <llvm/ADT/IntrusiveRefCntPtr.h>
 #include <llvm/ADT/SmallVector.h>
 #include <llvm/ADT/StringRef.h>
+#include <llvm/Config/config.h>
 
 #include "Arch.h"
 #include "DeclarationDatabase.h"
@@ -237,7 +238,14 @@ void compileHeader(llvm::IntrusiveRefCntPtr<clang::vfs::FileSystem> vfs,
   }
 
   clang::CompilerInstance Compiler;
+
+// Remove the workaround once b/35936936 is fixed.
+#if LLVM_VERSION_MAJOR >= 5
+  Compiler.setInvocation(std::move(invocation));
+#else
   Compiler.setInvocation(invocation.release());
+#endif
+
   Compiler.setDiagnostics(diags.get());
   Compiler.setVirtualFileSystem(vfs);
 
index 59d41da..735ea04 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <llvm/ADT/StringRef.h>
 
+#include <android-base/file.h>
 #include <android-base/macros.h>
 #include <android-base/parseint.h>
 
@@ -445,6 +446,12 @@ static void usage(bool help = false) {
   }
 }
 
+// versioner uses a prebuilt version of clang, which is not up-to-date wrt/
+// container annotations. So disable container overflow checking. b/37775238
+extern "C" const char* __asan_default_options() {
+  return "detect_container_overflow=0";
+}
+
 int main(int argc, char** argv) {
   std::string cwd = getWorkingDir() + "/";
   bool default_args = true;
@@ -570,8 +577,9 @@ int main(int argc, char** argv) {
       platform_dir = versioner_dir + "/platforms";
     }
   } else {
-    // Intentional leak.
-    header_dir = realpath(argv[optind], nullptr);
+    if (!android::base::Realpath(argv[optind], &header_dir)) {
+      err(1, "failed to get realpath for path '%s'", argv[optind]);
+    }
 
     if (argc - optind == 2) {
       dependency_dir = argv[optind + 1];