Merge changes Ia7200bf0,I86999bb7
* changes:
versioner: fix leak.
versioner: add symlink for dependencies.
diff --git a/libc/Android.bp b/libc/Android.bp
index e8175f4..b2ebe09 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -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 @@
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: [],
@@ -1346,7 +1350,6 @@
"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 +1708,7 @@
"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 +1720,6 @@
"bionic/NetdClient.cpp",
"arch-common/bionic/crtend_so.S",
],
- whole_static_libs: ["libjemalloc"],
},
required: ["tzdata"],
@@ -1740,7 +1742,7 @@
// you wanted!
shared_libs: ["libdl"],
- whole_static_libs: ["libc_common"],
+ whole_static_libs: ["libc_common", "libjemalloc"],
nocrt: true,
@@ -1793,19 +1795,6 @@
}
// ========================================================
-// 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 +1807,7 @@
],
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 +2063,7 @@
}
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 +2071,14 @@
}
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",
diff --git a/libc/arch-arm/bionic/atexit_legacy.c b/libc/arch-arm/bionic/atexit_legacy.c
index c0d704d..7254017 100644
--- a/libc/arch-arm/bionic/atexit_legacy.c
+++ b/libc/arch-arm/bionic/atexit_legacy.c
@@ -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 @@
*/
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));
diff --git a/libc/arch-mips/bionic/cacheflush.cpp b/libc/arch-mips/bionic/cacheflush.cpp
index 98c0bd4..380ad90 100644
--- a/libc/arch-mips/bionic/cacheflush.cpp
+++ b/libc/arch-mips/bionic/cacheflush.cpp
@@ -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 @@
// 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;
diff --git a/libc/async_safe/Android.bp b/libc/async_safe/Android.bp
new file mode 100644
index 0000000..9e36d97
--- /dev/null
+++ b/libc/async_safe/Android.bp
@@ -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"],
+}
diff --git a/libc/async_safe/async_safe_log.cpp b/libc/async_safe/async_safe_log.cpp
new file mode 100644
index 0000000..372f385
--- /dev/null
+++ b/libc/async_safe/async_safe_log.cpp
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/un.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,
+};
+
+struct BufferOutputStream {
+ public:
+ BufferOutputStream(char* buffer, size_t size) : total(0) {
+ buffer_ = buffer;
+ end_ = buffer + size - 1;
+ pos_ = buffer_;
+ pos_[0] = '\0';
+ }
+
+ ~BufferOutputStream() {}
+
+ void Send(const char* data, int len) {
+ if (len < 0) {
+ len = strlen(data);
+ }
+
+ total += len;
+
+ while (len > 0) {
+ int avail = end_ - pos_;
+ if (avail == 0) {
+ return;
+ }
+ if (avail > len) {
+ avail = len;
+ }
+ memcpy(pos_, data, avail);
+ pos_ += avail;
+ pos_[0] = '\0';
+ len -= avail;
+ }
+ }
+
+ size_t total;
+
+ private:
+ char* buffer_;
+ char* pos_;
+ char* end_;
+};
+
+struct FdOutputStream {
+ public:
+ explicit FdOutputStream(int fd) : total(0), fd_(fd) {}
+
+ void Send(const char* data, int len) {
+ if (len < 0) {
+ len = strlen(data);
+ }
+
+ total += len;
+
+ while (len > 0) {
+ int rc = TEMP_FAILURE_RETRY(write(fd_, data, len));
+ if (rc == -1) {
+ return;
+ }
+ data += rc;
+ len -= rc;
+ }
+ }
+
+ size_t total;
+
+ private:
+ int fd_;
+};
+
+/*** formatted output implementation
+ ***/
+
+/* Parse a decimal string from 'format + *ppos',
+ * return the value, and writes the new position past
+ * the decimal string in '*ppos' on exit.
+ *
+ * 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');
+
+ if (d >= 10U) {
+ break;
+ }
+
+ result = result * 10 + d;
+ p++;
+ }
+ *ppos = p - format;
+ return result;
+}
+
+// Writes number 'value' in base 'base' into buffer 'buf' of size 'buf_size' bytes.
+// Assumes that buf_size > 0.
+static void format_unsigned(char* buf, size_t buf_size, uint64_t value, int base, bool caps) {
+ char* p = buf;
+ char* end = buf + buf_size - 1;
+
+ // Generate digit string in reverse order.
+ while (value) {
+ unsigned d = value % base;
+ value /= base;
+ if (p != end) {
+ char ch;
+ if (d < 10) {
+ ch = '0' + d;
+ } else {
+ ch = (caps ? 'A' : 'a') + (d - 10);
+ }
+ *p++ = ch;
+ }
+ }
+
+ // Special case for 0.
+ if (p == buf) {
+ if (p != end) {
+ *p++ = '0';
+ }
+ }
+ *p = '\0';
+
+ // Reverse digit string in-place.
+ size_t length = p - buf;
+ for (size_t i = 0, j = length - 1; i < j; ++i, --j) {
+ char ch = buf[i];
+ buf[i] = buf[j];
+ buf[j] = ch;
+ }
+}
+
+static void format_integer(char* buf, size_t buf_size, uint64_t value, char conversion) {
+ // Decode the conversion specifier.
+ int is_signed = (conversion == 'd' || conversion == 'i' || conversion == 'o');
+ int base = 10;
+ if (conversion == 'x' || conversion == 'X') {
+ base = 16;
+ } else if (conversion == 'o') {
+ base = 8;
+ }
+ bool caps = (conversion == 'X');
+
+ if (is_signed && static_cast<int64_t>(value) < 0) {
+ buf[0] = '-';
+ buf += 1;
+ buf_size -= 1;
+ value = static_cast<uint64_t>(-static_cast<int64_t>(value));
+ }
+ format_unsigned(buf, buf_size, value, base, caps);
+}
+
+template <typename Out>
+static void SendRepeat(Out& o, char ch, int count) {
+ char pad[8];
+ memset(pad, ch, sizeof(pad));
+
+ const int pad_size = static_cast<int>(sizeof(pad));
+ while (count > 0) {
+ int avail = count;
+ if (avail > pad_size) {
+ avail = pad_size;
+ }
+ o.Send(pad, avail);
+ count -= avail;
+ }
+}
+
+/* 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;
+
+ 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 (;;) {
+ 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 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:;
+ }
+
+ /* 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");
+ }
+
+ /* if we are here, 'str' points to the content that must be
+ * outputted. handle padding and alignment now */
+
+ slen = strlen(str);
+
+ if (sign != '\0' || prec != -1) {
+ __assert(__FILE__, __LINE__, "sign/precision unsupported");
+ }
+
+ 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 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);
+ out_vformat(os, format, args);
+ va_end(args);
+ return os.total;
+}
+
+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 async_safe_format_fd(int fd, const char* format, ...) {
+ FdOutputStream os(fd);
+ va_list args;
+ va_start(args, format);
+ out_vformat(os, format, args);
+ va_end(args);
+ return os.total;
+}
+
+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);
+ vec[1].iov_base = const_cast<char*>(": ");
+ vec[1].iov_len = 2;
+ vec[2].iov_base = const_cast<char*>(msg);
+ vec[2].iov_len = strlen(msg);
+ vec[3].iov_base = const_cast<char*>("\n");
+ vec[3].iov_len = 1;
+
+ int result = TEMP_FAILURE_RETRY(writev(STDERR_FILENO, vec, 4));
+ return result;
+}
+
+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
+ // found that all logd crashes thus far have had no problem stuffing
+ // the UNIX domain socket and moving on so not critical *today*.
+
+ int log_fd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
+ if (log_fd == -1) {
+ return -1;
+ }
+
+ union {
+ struct sockaddr addr;
+ struct sockaddr_un addrUn;
+ } u;
+ memset(&u, 0, sizeof(u));
+ u.addrUn.sun_family = AF_UNIX;
+ strlcpy(u.addrUn.sun_path, "/dev/socket/logdw", sizeof(u.addrUn.sun_path));
+
+ if (TEMP_FAILURE_RETRY(connect(log_fd, &u.addr, sizeof(u.addrUn))) != 0) {
+ close(log_fd);
+ return -1;
+ }
+
+ return log_fd;
+}
+
+static clockid_t log_clockid() {
+ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ ScopedPthreadMutexLocker locker(&mutex);
+
+ static CachedProperty ro_logd_timestamp("ro.logd.timestamp");
+ static CachedProperty persist_logd_timestamp("persist.logd.timestamp");
+
+ char ch = persist_logd_timestamp.Get()[0];
+ if (ch == '\0') ch = ro_logd_timestamp.Get()[0];
+
+ return (tolower(ch) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
+}
+
+struct log_time { // Wire format
+ uint32_t tv_sec;
+ uint32_t tv_nsec;
+};
+
+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 write_stderr(tag, msg);
+ }
+
+ iovec vec[6];
+ char log_id = (priority == ANDROID_LOG_FATAL) ? LOG_ID_CRASH : LOG_ID_MAIN;
+ vec[0].iov_base = &log_id;
+ vec[0].iov_len = sizeof(log_id);
+ uint16_t tid = gettid();
+ vec[1].iov_base = &tid;
+ vec[1].iov_len = sizeof(tid);
+ timespec ts;
+ clock_gettime(log_clockid(), &ts);
+ log_time realtime_ts;
+ realtime_ts.tv_sec = ts.tv_sec;
+ realtime_ts.tv_nsec = ts.tv_nsec;
+ vec[2].iov_base = &realtime_ts;
+ vec[2].iov_len = sizeof(realtime_ts);
+
+ vec[3].iov_base = &priority;
+ vec[3].iov_len = 1;
+ vec[4].iov_base = const_cast<char*>(tag);
+ vec[4].iov_len = strlen(tag) + 1;
+ vec[5].iov_base = const_cast<char*>(msg);
+ vec[5].iov_len = strlen(msg) + 1;
+
+ int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0])));
+ close(main_log_fd);
+ return result;
+}
+
+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 async_safe_write_log(priority, tag, buffer);
+}
+
+int async_safe_format_log(int priority, const char* tag, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ int result = async_safe_format_log_va_list(priority, tag, format, args);
+ va_end(args);
+ return result;
+}
+
+void async_safe_fatal_va_list(const char* prefix, const char* format, va_list args) {
+ char msg[1024];
+ BufferOutputStream os(msg, sizeof(msg));
+
+ if (prefix) {
+ os.Send(prefix, strlen(prefix));
+ os.Send(": ", 2);
+ }
+
+ out_vformat(os, format, args);
+
+ // Log to stderr for the benefit of "adb shell" users and gtests.
+ struct iovec iov[2] = {
+ {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).
+ async_safe_write_log(ANDROID_LOG_FATAL, "libc", msg);
+
+ android_set_abort_message(msg);
+}
+
+void async_safe_fatal(const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ async_safe_fatal_va_list(nullptr, fmt, args);
+ va_end(args);
+ abort();
+}
diff --git a/libc/private/libc_logging.h b/libc/async_safe/include/async_safe/log.h
similarity index 61%
rename from libc/private/libc_logging.h
rename to libc/async_safe/include/async_safe/log.h
index 73bc9a5..f93f672 100644
--- a/libc/private/libc_logging.h
+++ b/libc/async_safe/include/async_safe/log.h
@@ -26,14 +26,16 @@
* 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 @@
};
// 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 @@
// 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)
diff --git a/libc/bionic/NetdClient.cpp b/libc/bionic/NetdClient.cpp
index b117d72..a1071d2 100644
--- a/libc/bionic/NetdClient.cpp
+++ b/libc/bionic/NetdClient.cpp
@@ -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 @@
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");
}
}
diff --git a/libc/bionic/__cxa_pure_virtual.cpp b/libc/bionic/__cxa_pure_virtual.cpp
index 30b581f..00a4d90 100644
--- a/libc/bionic/__cxa_pure_virtual.cpp
+++ b/libc/bionic/__cxa_pure_virtual.cpp
@@ -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?");
}
diff --git a/libc/bionic/__libc_current_sigrtmax.cpp b/libc/bionic/__libc_current_sigrtmax.cpp
index 27fcb35..32179bb 100644
--- a/libc/bionic/__libc_current_sigrtmax.cpp
+++ b/libc/bionic/__libc_current_sigrtmax.cpp
@@ -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;
}
diff --git a/libc/bionic/__libc_current_sigrtmin.cpp b/libc/bionic/__libc_current_sigrtmin.cpp
index 7c93267..f3b2bf6 100644
--- a/libc/bionic/__libc_current_sigrtmin.cpp
+++ b/libc/bionic/__libc_current_sigrtmin.cpp
@@ -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;
}
diff --git a/libc/bionic/__stack_chk_fail.cpp b/libc/bionic/__stack_chk_fail.cpp
index cb039cf..5f5a5f6 100644
--- a/libc/bionic/__stack_chk_fail.cpp
+++ b/libc/bionic/__stack_chk_fail.cpp
@@ -28,9 +28,10 @@
#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)");
}
diff --git a/libc/bionic/assert.cpp b/libc/bionic/assert.cpp
index 985fc38..41831cb 100644
--- a/libc/bionic/assert.cpp
+++ b/libc/bionic/assert.cpp
@@ -30,16 +30,16 @@
#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");
}
diff --git a/libc/bionic/bionic_arc4random.cpp b/libc/bionic/bionic_arc4random.cpp
index ba3b4e1..a4842f6 100644
--- a/libc/bionic/bionic_arc4random.cpp
+++ b/libc/bionic/bionic_arc4random.cpp
@@ -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 @@
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);
diff --git a/libc/bionic/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
index 5699f6e..970a92b 100644
--- a/libc/bionic/bionic_systrace.cpp
+++ b/libc/bionic/bionic_systrace.cpp
@@ -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.
diff --git a/libc/bionic/grp_pwd.cpp b/libc/bionic/grp_pwd.cpp
index 5d565c4..078a0b3 100644
--- a/libc/bionic/grp_pwd.cpp
+++ b/libc/bionic/grp_pwd.cpp
@@ -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"
diff --git a/libc/bionic/icu.cpp b/libc/bionic/icu.cpp
index abc0eec..944a3f8 100644
--- a/libc/bionic/icu.cpp
+++ b/libc/bionic/icu.cpp
@@ -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 @@
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 @@
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* 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;
}
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 970a49c..d267b68 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -41,12 +41,13 @@
#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"
@@ -96,8 +97,8 @@
#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 +304,11 @@
#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
}
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
deleted file mode 100644
index 54664d9..0000000
--- a/libc/bionic/libc_logging.cpp
+++ /dev/null
@@ -1,584 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-// 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 <fcntl.h>
-#include <pthread.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/un.h>
-#include <time.h>
-#include <unistd.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,
-};
-
-struct BufferOutputStream {
- public:
- BufferOutputStream(char* buffer, size_t size) : total(0) {
- buffer_ = buffer;
- end_ = buffer + size - 1;
- pos_ = buffer_;
- pos_[0] = '\0';
- }
-
- ~BufferOutputStream() {
- }
-
- void Send(const char* data, int len) {
- if (len < 0) {
- len = strlen(data);
- }
-
- total += len;
-
- while (len > 0) {
- int avail = end_ - pos_;
- if (avail == 0) {
- return;
- }
- if (avail > len) {
- avail = len;
- }
- memcpy(pos_, data, avail);
- pos_ += avail;
- pos_[0] = '\0';
- len -= avail;
- }
- }
-
- size_t total;
-
- private:
- char* buffer_;
- char* pos_;
- char* end_;
-};
-
-struct FdOutputStream {
- public:
- explicit FdOutputStream(int fd) : total(0), fd_(fd) {
- }
-
- void Send(const char* data, int len) {
- if (len < 0) {
- len = strlen(data);
- }
-
- total += len;
-
- while (len > 0) {
- int rc = TEMP_FAILURE_RETRY(write(fd_, data, len));
- if (rc == -1) {
- return;
- }
- data += rc;
- len -= rc;
- }
- }
-
- size_t total;
-
- private:
- int fd_;
-};
-
-/*** formatted output implementation
- ***/
-
-/* Parse a decimal string from 'format + *ppos',
- * return the value, and writes the new position past
- * the decimal string in '*ppos' on exit.
- *
- * 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');
-
- if (d >= 10U) {
- break;
- }
-
- result = result*10 + d;
- p++;
- }
- *ppos = p - format;
- return result;
-}
-
-// Writes number 'value' in base 'base' into buffer 'buf' of size 'buf_size' bytes.
-// Assumes that buf_size > 0.
-static void format_unsigned(char* buf, size_t buf_size, uint64_t value, int base, bool caps) {
- char* p = buf;
- char* end = buf + buf_size - 1;
-
- // Generate digit string in reverse order.
- while (value) {
- unsigned d = value % base;
- value /= base;
- if (p != end) {
- char ch;
- if (d < 10) {
- ch = '0' + d;
- } else {
- ch = (caps ? 'A' : 'a') + (d - 10);
- }
- *p++ = ch;
- }
- }
-
- // Special case for 0.
- if (p == buf) {
- if (p != end) {
- *p++ = '0';
- }
- }
- *p = '\0';
-
- // Reverse digit string in-place.
- size_t length = p - buf;
- for (size_t i = 0, j = length - 1; i < j; ++i, --j) {
- char ch = buf[i];
- buf[i] = buf[j];
- buf[j] = ch;
- }
-}
-
-static void format_integer(char* buf, size_t buf_size, uint64_t value, char conversion) {
- // Decode the conversion specifier.
- int is_signed = (conversion == 'd' || conversion == 'i' || conversion == 'o');
- int base = 10;
- if (conversion == 'x' || conversion == 'X') {
- base = 16;
- } else if (conversion == 'o') {
- base = 8;
- }
- bool caps = (conversion == 'X');
-
- if (is_signed && static_cast<int64_t>(value) < 0) {
- buf[0] = '-';
- buf += 1;
- buf_size -= 1;
- value = static_cast<uint64_t>(-static_cast<int64_t>(value));
- }
- format_unsigned(buf, buf_size, value, base, caps);
-}
-
-template <typename Out>
-static void SendRepeat(Out& o, char ch, int count) {
- char pad[8];
- memset(pad, ch, sizeof(pad));
-
- const int pad_size = static_cast<int>(sizeof(pad));
- while (count > 0) {
- int avail = count;
- if (avail > pad_size) {
- avail = pad_size;
- }
- o.Send(pad, avail);
- count -= avail;
- }
-}
-
-/* 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;
-
- 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 (;;) {
- 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 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:
- ;
- }
-
- /* 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");
- }
-
- /* if we are here, 'str' points to the content that must be
- * outputted. handle padding and alignment now */
-
- slen = strlen(str);
-
- if (sign != '\0' || prec != -1) {
- __assert(__FILE__, __LINE__, "sign/precision unsupported");
- }
-
- 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, ...) {
- BufferOutputStream os(buffer, buffer_size);
- va_list args;
- va_start(args, format);
- out_vformat(os, format, args);
- va_end(args);
- return os.total;
-}
-
-int __libc_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, ...) {
- FdOutputStream os(fd);
- va_list args;
- va_start(args, format);
- out_vformat(os, format, args);
- va_end(args);
- return os.total;
-}
-
-static int __libc_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);
- vec[1].iov_base = const_cast<char*>(": ");
- vec[1].iov_len = 2;
- vec[2].iov_base = const_cast<char*>(msg);
- vec[2].iov_len = strlen(msg);
- vec[3].iov_base = const_cast<char*>("\n");
- vec[3].iov_len = 1;
-
- int result = TEMP_FAILURE_RETRY(writev(STDERR_FILENO, vec, 4));
- return result;
-}
-
-static int __libc_open_log_socket() {
- // ToDo: Ideally we want this to fail if the gid of the current
- // process is AID_LOGD, but will have to wait until we have
- // registered this in private/android_filesystem_config.h. We have
- // found that all logd crashes thus far have had no problem stuffing
- // the UNIX domain socket and moving on so not critical *today*.
-
- int log_fd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
- if (log_fd == -1) {
- return -1;
- }
-
- union {
- struct sockaddr addr;
- struct sockaddr_un addrUn;
- } u;
- memset(&u, 0, sizeof(u));
- u.addrUn.sun_family = AF_UNIX;
- strlcpy(u.addrUn.sun_path, "/dev/socket/logdw", sizeof(u.addrUn.sun_path));
-
- if (TEMP_FAILURE_RETRY(connect(log_fd, &u.addr, sizeof(u.addrUn))) != 0) {
- close(log_fd);
- return -1;
- }
-
- return log_fd;
-}
-
-static clockid_t __android_log_clockid() {
- static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- ScopedPthreadMutexLocker locker(&mutex);
-
- static CachedProperty ro_logd_timestamp("ro.logd.timestamp");
- static CachedProperty persist_logd_timestamp("persist.logd.timestamp");
-
- char ch = persist_logd_timestamp.Get()[0];
- if (ch == '\0') ch = ro_logd_timestamp.Get()[0];
-
- return (tolower(ch) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
-}
-
-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();
- if (main_log_fd == -1) {
- // Try stderr instead.
- return __libc_write_stderr(tag, msg);
- }
-
- iovec vec[6];
- char log_id = (priority == ANDROID_LOG_FATAL) ? LOG_ID_CRASH : LOG_ID_MAIN;
- vec[0].iov_base = &log_id;
- vec[0].iov_len = sizeof(log_id);
- uint16_t tid = gettid();
- vec[1].iov_base = &tid;
- vec[1].iov_len = sizeof(tid);
- timespec ts;
- clock_gettime(__android_log_clockid(), &ts);
- log_time realtime_ts;
- realtime_ts.tv_sec = ts.tv_sec;
- realtime_ts.tv_nsec = ts.tv_nsec;
- vec[2].iov_base = &realtime_ts;
- vec[2].iov_len = sizeof(realtime_ts);
-
- vec[3].iov_base = &priority;
- vec[3].iov_len = 1;
- vec[4].iov_base = const_cast<char*>(tag);
- vec[4].iov_len = strlen(tag) + 1;
- vec[5].iov_base = const_cast<char*>(msg);
- vec[5].iov_len = strlen(msg) + 1;
-
- int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0])));
- close(main_log_fd);
- return result;
-}
-
-int __libc_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);
-}
-
-int __libc_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);
- va_end(args);
- return result;
-}
-
-static void __libc_fatal_va_list(const char* prefix, const char* format, va_list args) {
- char msg[1024];
- BufferOutputStream os(msg, sizeof(msg));
-
- if (prefix) {
- os.Send(prefix, strlen(prefix));
- os.Send(": ", 2);
- }
-
- out_vformat(os, format, args);
-
- // Log to stderr for the benefit of "adb shell" users and gtests.
- struct iovec iov[2] = {
- { 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);
-
- 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, ...) {
- va_list args;
- va_start(args, fmt);
- __libc_fatal_va_list("FORTIFY", fmt, args);
- va_end(args);
- abort();
-}
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 3fceb71..18c998d 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -167,7 +167,7 @@
#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 +188,9 @@
// 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__ )
// =============================================================================
// =============================================================================
diff --git a/libc/bionic/ndk_cruft.cpp b/libc/bionic/ndk_cruft.cpp
index 29565a2..016b476 100644
--- a/libc/bionic/ndk_cruft.cpp
+++ b/libc/bionic/ndk_cruft.cpp
@@ -46,7 +46,6 @@
#include <wchar.h>
#include "private/bionic_macros.h"
-#include "private/libc_logging.h"
extern "C" {
diff --git a/libc/bionic/new.cpp b/libc/bionic/new.cpp
index 76c46ee..9499ff5 100644
--- a/libc/bionic/new.cpp
+++ b/libc/bionic/new.cpp
@@ -19,14 +19,14 @@
#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* 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;
}
diff --git a/libc/bionic/open.cpp b/libc/bionic/open.cpp
index 2daa21f..6d179c4 100644
--- a/libc/bionic/open.cpp
+++ b/libc/bionic/open.cpp
@@ -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);
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp
index cfa58fc..4b6a8f2 100644
--- a/libc/bionic/pthread_attr.cpp
+++ b/libc/bionic/pthread_attr.cpp
@@ -33,9 +33,10 @@
#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 @@
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 @@
"%*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 @@
// 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 @@
}
}
}
- __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) {
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 6b3e148..9f4481f 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -35,11 +35,12 @@
#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.
@@ -60,13 +61,13 @@
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 +119,8 @@
// 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 +135,7 @@
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 +145,9 @@
// 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;
}
@@ -281,7 +282,8 @@
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;
}
diff --git a/libc/bionic/pthread_internal.cpp b/libc/bionic/pthread_internal.cpp
index 5819bc1..abd403b 100644
--- a/libc/bionic/pthread_internal.cpp
+++ b/libc/bionic/pthread_internal.cpp
@@ -33,10 +33,11 @@
#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 @@
// 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;
diff --git a/libc/bionic/setjmp_cookie.cpp b/libc/bionic/setjmp_cookie.cpp
index 4fa68c2..41a439f 100644
--- a/libc/bionic/setjmp_cookie.cpp
+++ b/libc/bionic/setjmp_cookie.cpp
@@ -34,9 +34,10 @@
#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 @@
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 @@
// 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");
}
diff --git a/libc/bionic/strerror_r.cpp b/libc/bionic/strerror_r.cpp
index a0a0809..dad3fb3 100644
--- a/libc/bionic/strerror_r.cpp
+++ b/libc/bionic/strerror_r.cpp
@@ -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 @@
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);
diff --git a/libc/bionic/syslog.cpp b/libc/bionic/syslog.cpp
index 8e3f34f..9424573 100644
--- a/libc/bionic/syslog.cpp
+++ b/libc/bionic/syslog.cpp
@@ -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 @@
*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 @@
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);
}
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index 9fb03ac..a958699 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -54,12 +54,13 @@
#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 @@
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 @@
// 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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
}
diff --git a/libc/dns/resolv/res_cache.c b/libc/dns/resolv/res_cache.c
index 82e0ddf..9c65570 100644
--- a/libc/dns/resolv/res_cache.c
+++ b/libc/dns/resolv/res_cache.c
@@ -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.
*
@@ -155,7 +155,7 @@
#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); \
} \
diff --git a/libc/dns/resolv/res_send.c b/libc/dns/resolv/res_send.c
index f53da5f..586bb8f 100644
--- a/libc/dns/resolv/res_send.c
+++ b/libc/dns/resolv/res_send.c
@@ -114,7 +114,7 @@
#include <resolv_cache.h>
-#include "private/libc_logging.h"
+#include <async_safe/log.h>
#ifndef DE_CONST
#define DE_CONST(c,v) v = ((c) ? \
@@ -564,7 +564,7 @@
}
if (DBG) {
- __libc_format_log(ANDROID_LOG_DEBUG, "libc",
+ async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
"used send_vc %d\n", n);
}
@@ -576,7 +576,7 @@
} 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,
@@ -591,7 +591,7 @@
}
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)
@@ -599,7 +599,7 @@
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)
@@ -739,7 +739,7 @@
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;
@@ -764,7 +764,7 @@
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);
@@ -993,7 +993,7 @@
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);
@@ -1004,7 +1004,7 @@
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;
@@ -1020,7 +1020,7 @@
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();
@@ -1040,7 +1040,7 @@
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;
@@ -1050,7 +1050,7 @@
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;
@@ -1060,7 +1060,7 @@
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);
}
@@ -1068,7 +1068,7 @@
}
}
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);
}
diff --git a/libc/dns/resolv/res_state.c b/libc/dns/resolv/res_state.c
index 4ed168c..94124ff 100644
--- a/libc/dns/resolv/res_state.c
+++ b/libc/dns/resolv/res_state.c
@@ -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
diff --git a/libc/dns/resolv/res_stats.c b/libc/dns/resolv/res_stats.c
index 99c79e4..97d54d2 100644
--- a/libc/dns/resolv/res_stats.c
+++ b/libc/dns/resolv/res_stats.c
@@ -18,9 +18,10 @@
#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 @@
_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 @@
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 @@
// 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;
diff --git a/libc/include/android/legacy_signal_inlines.h b/libc/include/android/legacy_signal_inlines.h
index afdaca8..a5d3a6f 100644
--- a/libc/include/android/legacy_signal_inlines.h
+++ b/libc/include/android/legacy_signal_inlines.h
@@ -41,6 +41,25 @@
#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;
diff --git a/libc/include/elf.h b/libc/include/elf.h
index c36bc8d..4181006 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -184,6 +184,12 @@
#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
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index 752ee72..412e3f0 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -23,13 +23,9 @@
__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
diff --git a/libc/kernel/tools/defaults.py b/libc/kernel/tools/defaults.py
index 620bb31..c22f684 100644
--- a/libc/kernel/tools/defaults.py
+++ b/libc/kernel/tools/defaults.py
@@ -26,6 +26,9 @@
"CONFIG_64BIT": "__LP64__",
"CONFIG_X86_32": "__i386__",
"__EXPORTED_HEADERS__": "1",
+ "__HAVE_BUILTIN_BSWAP16__": "1",
+ "__HAVE_BUILTIN_BSWAP32__": "1",
+ "__HAVE_BUILTIN_BSWAP64__": "1",
}
# define to true if you want to remove all defined(CONFIG_FOO) tests
@@ -77,14 +80,14 @@
"udphdr": "__kernel_udphdr",
# The kernel's struct epoll_event just has __u64 for the data.
"epoll_event": "__kernel_uapi_epoll_event",
+ # This causes problems when trying to export the headers for the ndk.
+ "__attribute_const__": "__attribute__((__const__))",
}
-# this is the set of known static inline functions that we want to keep
-# in the final ARM headers. this is only used to keep optimized byteswapping
-# static functions and stuff like that.
-# TODO: this isn't working!
+# This is the set of known static inline functions that we want to keep
+# in the final kernel headers.
kernel_known_arm_statics = set(
- [ "___arch__swab32", # asm-arm/byteorder.h
+ [
]
)
@@ -99,8 +102,7 @@
)
kernel_known_x86_statics = set(
- [ "___arch__swab32", # asm-x86/byteorder.h
- "___arch__swab64", # asm-x86/byteorder.h
+ [
]
)
@@ -108,6 +110,26 @@
[
"ipt_get_target", # uapi/linux/netfilter_ipv4/ip_tables.h
"ip6t_get_target", # uapi/linux/netfilter_ipv6/ip6_tables.h
+ # Byte swapping inlines from uapi/linux/swab.h
+ # The below functions are the ones we are guaranting we export.
+ "__swab16",
+ "__swab32",
+ "__swab64",
+ "__swab16p",
+ "__swab32p",
+ "__swab64p",
+ "__swab16s",
+ "__swab32s",
+ "__swab64s",
+ "__swahw32",
+ "__swahb32",
+ "__swahw32p",
+ "__swahb32p",
+ "__swahw32s",
+ "__swahb32s",
+ # These are required to support the above functions.
+ "__fswahw32",
+ "__fswahb32",
]
)
diff --git a/libc/kernel/uapi/linux/swab.h b/libc/kernel/uapi/linux/swab.h
index a3387de..71aac11 100644
--- a/libc/kernel/uapi/linux/swab.h
+++ b/libc/kernel/uapi/linux/swab.h
@@ -41,70 +41,115 @@
#else
#endif
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+static inline __attribute__((__const__)) __u32 __fswahw32(__u32 val) {
#ifdef __arch_swahw32
+ return __arch_swahw32(val);
#else
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ return ___constant_swahw32(val);
#endif
+}
+static inline __attribute__((__const__)) __u32 __fswahb32(__u32 val) {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#ifdef __arch_swahb32
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ return __arch_swahb32(val);
#else
+ return ___constant_swahb32(val);
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif
-#ifdef __HAVE_BUILTIN_BSWAP16__
+}
#define __swab16(x) (__u16) __builtin_bswap16((__u16) (x))
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#else
-#define __swab16(x) (__builtin_constant_p((__u16) (x)) ? ___constant_swab16(x) : __fswab16(x))
-#endif
-#ifdef __HAVE_BUILTIN_BSWAP32__
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define __swab32(x) (__u32) __builtin_bswap32((__u32) (x))
-#else
-#define __swab32(x) (__builtin_constant_p((__u32) (x)) ? ___constant_swab32(x) : __fswab32(x))
-#endif
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#ifdef __HAVE_BUILTIN_BSWAP64__
#define __swab64(x) (__u64) __builtin_bswap64((__u64) (x))
-#else
-#define __swab64(x) (__builtin_constant_p((__u64) (x)) ? ___constant_swab64(x) : __fswab64(x))
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#endif
#define __swahw32(x) (__builtin_constant_p((__u32) (x)) ? ___constant_swahw32(x) : __fswahw32(x))
#define __swahb32(x) (__builtin_constant_p((__u32) (x)) ? ___constant_swahb32(x) : __fswahb32(x))
+static __always_inline __u16 __swab16p(const __u16 * p) {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#ifdef __arch_swab16p
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ return __arch_swab16p(p);
#else
+ return __swab16(* p);
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif
+}
+static __always_inline __u32 __swab32p(const __u32 * p) {
#ifdef __arch_swab32p
-#else
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ return __arch_swab32p(p);
+#else
+ return __swab32(* p);
#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+}
+static __always_inline __u64 __swab64p(const __u64 * p) {
#ifdef __arch_swab64p
-#else
-#endif
+ return __arch_swab64p(p);
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#else
+ return __swab64(* p);
+#endif
+}
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+static inline __u32 __swahw32p(const __u32 * p) {
#ifdef __arch_swahw32p
+ return __arch_swahw32p(p);
#else
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ return __swahw32(* p);
#endif
+}
+static inline __u32 __swahb32p(const __u32 * p) {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#ifdef __arch_swahb32p
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ return __arch_swahb32p(p);
#else
+ return __swahb32(* p);
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif
+}
+static inline void __swab16s(__u16 * p) {
#ifdef __arch_swab16s
-#else
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __arch_swab16s(p);
+#else
+ * p = __swab16p(p);
#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+}
+static __always_inline void __swab32s(__u32 * p) {
#ifdef __arch_swab32s
-#else
-#endif
+ __arch_swab32s(p);
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#else
+ * p = __swab32p(p);
+#endif
+}
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+static __always_inline void __swab64s(__u64 * p) {
#ifdef __arch_swab64s
+ __arch_swab64s(p);
#else
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ * p = __swab64p(p);
#endif
+}
+static inline void __swahw32s(__u32 * p) {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#ifdef __arch_swahw32s
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __arch_swahw32s(p);
#else
+ * p = __swahw32p(p);
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif
+}
+static inline void __swahb32s(__u32 * p) {
#ifdef __arch_swahb32s
-#else
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __arch_swahb32s(p);
+#else
+ * p = __swahb32p(p);
#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+}
#endif
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index 708c101..b071b90 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -13,9 +13,10 @@
stl: "libc++_static",
- static_libs: ["libc_logging"],
+ whole_static_libs: ["libasync_safe"],
include_dirs: ["bionic/libc"],
+
export_include_dirs: ["."],
sanitize: {
@@ -29,7 +30,6 @@
"-Werror",
"-Wno-error=format-zero-length",
],
-
}
// ==============================================================
@@ -61,9 +61,9 @@
},
static_libs: [
+ "libasync_safe",
"libbase",
"libc_malloc_debug_backtrace",
- "libc_logging",
],
multilib: {
@@ -89,7 +89,6 @@
"-fno-stack-protector",
"-Wno-error=format-zero-length",
],
-
}
// ==============================================================
@@ -118,7 +117,7 @@
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 @@
"-Werror",
"-Wno-error=format-zero-length",
],
-
}
diff --git a/libc/malloc_debug/backtrace.cpp b/libc/malloc_debug/backtrace.cpp
index 75a255c..88f5a1d 100644
--- a/libc/malloc_debug/backtrace.cpp
+++ b/libc/malloc_debug/backtrace.cpp
@@ -158,13 +158,13 @@
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;
}
diff --git a/libc/malloc_debug/debug_log.h b/libc/malloc_debug/debug_log.h
index 4df0408..ed4b541 100644
--- a/libc/malloc_debug/debug_log.h
+++ b/libc/malloc_debug/debug_log.h
@@ -29,18 +29,18 @@
#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
diff --git a/libc/malloc_debug/tests/log_fake.cpp b/libc/malloc_debug/tests/log_fake.cpp
index 194d42b..fb64e3e 100644
--- a/libc/malloc_debug/tests/log_fake.cpp
+++ b/libc/malloc_debug/tests/log_fake.cpp
@@ -44,7 +44,7 @@
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 += ' ';
diff --git a/libc/private/WriteProtected.h b/libc/private/WriteProtected.h
index 1133e2a..20afdec 100644
--- a/libc/private/WriteProtected.h
+++ b/libc/private/WriteProtected.h
@@ -23,9 +23,10 @@
#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 @@
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 @@
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));
}
}
};
diff --git a/libc/private/bionic_fortify.h b/libc/private/bionic_fortify.h
index df810ca..8591117 100644
--- a/libc/private/bionic_fortify.h
+++ b/libc/private/bionic_fortify.h
@@ -26,11 +26,21 @@
* 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.
//
diff --git a/libc/stdio/stdio_ext.cpp b/libc/stdio/stdio_ext.cpp
index f2f58c6..ebc705c 100644
--- a/libc/stdio/stdio_ext.cpp
+++ b/libc/stdio/stdio_ext.cpp
@@ -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 @@
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);
diff --git a/libc/upstream-openbsd/android/include/arc4random.h b/libc/upstream-openbsd/android/include/arc4random.h
index 0d70c81..d006045 100644
--- a/libc/upstream-openbsd/android/include/arc4random.h
+++ b/libc/upstream-openbsd/android/include/arc4random.h
@@ -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 @@
static inline void
_getentropy_fail(void)
{
- __libc_fatal("getentropy failed");
+ async_safe_fatal("getentropy failed");
}
volatile sig_atomic_t _rs_forked;
diff --git a/libdl/libdl.arm.map b/libdl/libdl.arm.map
index c0dcd5d..668f008 100644
--- a/libdl/libdl.arm.map
+++ b/libdl/libdl.arm.map
@@ -47,4 +47,5 @@
android_init_anonymous_namespace;
android_create_namespace;
android_link_namespaces;
+ android_get_exported_namespace;
} LIBC_N;
diff --git a/libdl/libdl.arm64.map b/libdl/libdl.arm64.map
index 3b797f7..8270fe9 100644
--- a/libdl/libdl.arm64.map
+++ b/libdl/libdl.arm64.map
@@ -46,4 +46,5 @@
android_init_anonymous_namespace;
android_create_namespace;
android_link_namespaces;
+ android_get_exported_namespace;
} LIBC_N;
diff --git a/libdl/libdl.c b/libdl/libdl.c
index 6a95629..1a65b67 100644
--- a/libdl/libdl.c
+++ b/libdl/libdl.c
@@ -94,6 +94,9 @@
__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 @@
}
#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 @@
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);
+}
diff --git a/libdl/libdl.map.txt b/libdl/libdl.map.txt
index 245e016..a4c6483 100644
--- a/libdl/libdl.map.txt
+++ b/libdl/libdl.map.txt
@@ -46,4 +46,5 @@
android_init_anonymous_namespace;
android_create_namespace;
android_link_namespaces;
+ android_get_exported_namespace;
} LIBC_N;
diff --git a/libdl/libdl.mips.map b/libdl/libdl.mips.map
index 3b797f7..8270fe9 100644
--- a/libdl/libdl.mips.map
+++ b/libdl/libdl.mips.map
@@ -46,4 +46,5 @@
android_init_anonymous_namespace;
android_create_namespace;
android_link_namespaces;
+ android_get_exported_namespace;
} LIBC_N;
diff --git a/libdl/libdl.mips64.map b/libdl/libdl.mips64.map
index 3b797f7..8270fe9 100644
--- a/libdl/libdl.mips64.map
+++ b/libdl/libdl.mips64.map
@@ -46,4 +46,5 @@
android_init_anonymous_namespace;
android_create_namespace;
android_link_namespaces;
+ android_get_exported_namespace;
} LIBC_N;
diff --git a/libdl/libdl.x86.map b/libdl/libdl.x86.map
index 3b797f7..8270fe9 100644
--- a/libdl/libdl.x86.map
+++ b/libdl/libdl.x86.map
@@ -46,4 +46,5 @@
android_init_anonymous_namespace;
android_create_namespace;
android_link_namespaces;
+ android_get_exported_namespace;
} LIBC_N;
diff --git a/libdl/libdl.x86_64.map b/libdl/libdl.x86_64.map
index 3b797f7..8270fe9 100644
--- a/libdl/libdl.x86_64.map
+++ b/libdl/libdl.x86_64.map
@@ -46,4 +46,5 @@
android_init_anonymous_namespace;
android_create_namespace;
android_link_namespaces;
+ android_get_exported_namespace;
} LIBC_N;
diff --git a/linker/Android.bp b/linker/Android.bp
index d617189..efd91ac 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -9,6 +9,8 @@
// We need to access Bionic private headers in the linker.
include_dirs: ["bionic/libc"],
+
+ static_libs: ["libasync_safe"],
}
cc_binary {
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 0bc5a31..6195d40 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -214,6 +214,10 @@
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 @@
// 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 @@
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 @@
// 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)));
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 39062e6..cd2c55b 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -36,6 +36,7 @@
#include <string.h>
#include <sys/mman.h>
#include <sys/param.h>
+#include <sys/vfs.h>
#include <unistd.h>
#include <new>
@@ -45,6 +46,8 @@
#include <android-base/scopeguard.h>
+#include <async_safe/log.h>
+
// Private C library headers.
#include "linker.h"
@@ -72,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;
@@ -342,7 +346,7 @@
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;
@@ -491,7 +495,7 @@
}
if (ref_count_ == 0) { // overflow
- __libc_fatal("Too many nested calls to dlopen()");
+ async_safe_fatal("Too many nested calls to dlopen()");
}
}
@@ -990,7 +994,7 @@
}
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;
@@ -1189,7 +1193,15 @@
return false;
}
- if (!ns->is_accessible(realpath)) {
+ struct statfs fs_stat;
+ if (TEMP_FAILURE_RETRY(fstatfs(task->get_fd(), &fs_stat)) != 0) {
+ DL_ERR("unable to fstatfs file for the library \"%s\": %s", name, strerror(errno));
+ return false;
+ }
+
+ // do not check accessibility using realpath if fd is located on tmpfs
+ // this enables use of memfd_create() for apps
+ if ((fs_stat.f_type != TMPFS_MAGIC) && (!ns->is_accessible(realpath))) {
// TODO(dimitry): workaround for http://b/26394120 - the grey-list
// TODO(dimitry) before O release: add a namespace attribute to have this enabled
@@ -1771,7 +1783,7 @@
}
} 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) {
@@ -1845,8 +1857,8 @@
}
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;
@@ -2172,18 +2184,36 @@
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));
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;
}
@@ -3461,6 +3491,9 @@
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
@@ -3485,3 +3518,16 @@
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;
+}
diff --git a/linker/linker.h b/linker/linker.h
index d5d4980..fdd7b66 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -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"
@@ -173,4 +172,6 @@
android_namespace_t* namespace_to,
const char* shared_lib_sonames);
+android_namespace_t* get_exported_namespace(const char* name);
+
#endif
diff --git a/linker/linker_allocator.cpp b/linker/linker_allocator.cpp
index 723ea2b..fd6f496 100644
--- a/linker/linker_allocator.cpp
+++ b/linker/linker_allocator.cpp
@@ -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 @@
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 @@
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* 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 @@
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 @@
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 @@
} 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 @@
} 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 @@
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();
diff --git a/linker/linker_allocator.h b/linker/linker_allocator.h
index beffc52..80ae508 100644
--- a/linker/linker_allocator.h
+++ b/linker/linker_allocator.h
@@ -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 @@
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");
diff --git a/linker/linker_config.cpp b/linker/linker_config.cpp
index a12cfbe..0a9aeab 100644
--- a/linker/linker_config.cpp
+++ b/linker/linker_config.cpp
@@ -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 @@
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 @@
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 @@
}
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) {
diff --git a/linker/linker_config.h b/linker/linker_config.h
index 4ec8b26..6f8bffb 100644
--- a/linker/linker_config.h
+++ b/linker/linker_config.h
@@ -62,7 +62,7 @@
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 @@
return isolated_;
}
+ bool visible() const {
+ return visible_;
+ }
+
const std::vector<std::string>& search_paths() const {
return search_paths_;
}
@@ -93,6 +97,10 @@
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 @@
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_;
diff --git a/linker/linker_debug.h b/linker/linker_debug.h
index 42796e9..7ceab08 100644
--- a/linker/linker_debug.h
+++ b/linker/linker_debug.h
@@ -54,20 +54,21 @@
* 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 */
diff --git a/linker/linker_globals.h b/linker/linker_globals.h
index 1ed479c..d8134af 100644
--- a/linker/linker_globals.h
+++ b/linker/linker_globals.h
@@ -34,20 +34,20 @@
#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...) \
diff --git a/linker/linker_libcxx_support.cpp b/linker/linker_libcxx_support.cpp
index e7b23e0..11e0f40 100644
--- a/linker/linker_libcxx_support.cpp
+++ b/linker/linker_libcxx_support.cpp
@@ -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");
}
diff --git a/linker/linker_logger.cpp b/linker/linker_logger.cpp
index 717667c..4c6603b 100644
--- a/linker/linker_logger.cpp
+++ b/linker/linker_logger.cpp
@@ -35,9 +35,10 @@
#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 @@
} 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 @@
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 @@
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);
}
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 40f82a1..3d26e91 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 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 @@
// 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);
diff --git a/linker/linker_memory.cpp b/linker/linker_memory.cpp
index f8852e1..472c4e8 100644
--- a/linker/linker_memory.cpp
+++ b/linker/linker_memory.cpp
@@ -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 @@
// 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_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;
diff --git a/linker/linker_namespaces.h b/linker/linker_namespaces.h
index e7d9b2e..c3260fd 100644
--- a/linker/linker_namespaces.h
+++ b/linker/linker_namespaces.h
@@ -48,6 +48,10 @@
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();
}
diff --git a/linker/linker_sleb128.h b/linker/linker_sleb128.h
index 74b69e4..01e127d 100644
--- a/linker/linker_sleb128.h
+++ b/linker/linker_sleb128.h
@@ -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 @@
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);
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index 1d59dbb..fbff7cf 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -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 @@
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);
}
diff --git a/linker/tests/Android.mk b/linker/tests/Android.mk
index 61c43c9..8284bea 100644
--- a/linker/tests/Android.mk
+++ b/linker/tests/Android.mk
@@ -51,9 +51,6 @@
../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)
diff --git a/linker/tests/linker_config_test.cpp b/linker/tests/linker_config_test.cpp
index 418cbda..5e51113 100644
--- a/linker/tests/linker_config_test.cpp
+++ b/linker/tests/linker_config_test.cpp
@@ -58,6 +58,7 @@
"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 @@
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 @@
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());
}
diff --git a/tests/Android.bp b/tests/Android.bp
index ae8d7fc..4605267 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -52,12 +52,14 @@
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,9 +73,9 @@
"inttypes_test.cpp",
"langinfo_test.cpp",
"leak_test.cpp",
- "libc_logging_test.cpp",
"libgen_basename_test.cpp",
"libgen_test.cpp",
+ "linux_swab_test.cpp",
"locale_test.cpp",
"malloc_test.cpp",
"math_test.cpp",
@@ -149,6 +151,12 @@
"external/tinyxml2",
],
+ target: {
+ android: {
+ whole_static_libs: ["libasync_safe"],
+ },
+ },
+
static_libs: [
"libtinyxml2",
"liblog",
@@ -256,6 +264,7 @@
"dl_test.cpp",
"dlfcn_symlink_support.cpp",
"dlfcn_test.cpp",
+ "link_test.cpp",
"pthread_dlfcn_test.cpp",
],
static_libs: [
diff --git a/tests/async_safe_test.cpp b/tests/async_safe_test.cpp
new file mode 100644
index 0000000..3d6fcaa
--- /dev/null
+++ b/tests/async_safe_test.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#if defined(__BIONIC__)
+#include <async_safe/log.h>
+#endif // __BIONIC__
+
+TEST(async_safe_log, smoke) {
+#if defined(__BIONIC__)
+ char buf[BUFSIZ];
+
+ async_safe_format_buffer(buf, sizeof(buf), "a");
+ EXPECT_STREQ("a", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "%%");
+ EXPECT_STREQ("%", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "01234");
+ EXPECT_STREQ("01234", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%sb", "01234");
+ EXPECT_STREQ("a01234b", buf);
+
+ char* s = NULL;
+ async_safe_format_buffer(buf, sizeof(buf), "a%sb", s);
+ EXPECT_STREQ("a(null)b", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "aa%scc", "bb");
+ EXPECT_STREQ("aabbcc", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%cc", 'b');
+ EXPECT_STREQ("abc", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%db", 1234);
+ EXPECT_STREQ("a1234b", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%db", -8123);
+ EXPECT_STREQ("a-8123b", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%hdb", static_cast<short>(0x7fff0010));
+ EXPECT_STREQ("a16b", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%hhdb", static_cast<char>(0x7fffff10));
+ EXPECT_STREQ("a16b", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%lldb", 0x1000000000LL);
+ EXPECT_STREQ("a68719476736b", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%ldb", 70000L);
+ EXPECT_STREQ("a70000b", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%pb", reinterpret_cast<void*>(0xb0001234));
+ EXPECT_STREQ("a0xb0001234b", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%xz", 0x12ab);
+ EXPECT_STREQ("a12abz", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%Xz", 0x12ab);
+ EXPECT_STREQ("a12ABz", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%08xz", 0x123456);
+ EXPECT_STREQ("a00123456z", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%5dz", 1234);
+ EXPECT_STREQ("a 1234z", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%05dz", 1234);
+ EXPECT_STREQ("a01234z", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%8dz", 1234);
+ EXPECT_STREQ("a 1234z", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%-8dz", 1234);
+ EXPECT_STREQ("a1234 z", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "A%-11sZ", "abcdef");
+ EXPECT_STREQ("Aabcdef Z", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "A%s:%dZ", "hello", 1234);
+ EXPECT_STREQ("Ahello:1234Z", buf);
+
+ async_safe_format_buffer(buf, sizeof(buf), "a%03d:%d:%02dz", 5, 5, 5);
+ EXPECT_STREQ("a005:5:05z", buf);
+
+ void* p = NULL;
+ async_safe_format_buffer(buf, sizeof(buf), "a%d,%pz", 5, p);
+ EXPECT_STREQ("a5,0x0z", buf);
+
+ 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(async_safe_log, d_INT_MAX) {
+#if defined(__BIONIC__)
+ char buf[BUFSIZ];
+ 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(async_safe_log, d_INT_MIN) {
+#if defined(__BIONIC__)
+ char buf[BUFSIZ];
+ 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(async_safe_log, ld_LONG_MAX) {
+#if defined(__BIONIC__)
+ char buf[BUFSIZ];
+ async_safe_format_buffer(buf, sizeof(buf), "%ld", LONG_MAX);
+#if defined(__LP64__)
+ EXPECT_STREQ("9223372036854775807", buf);
+#else
+ EXPECT_STREQ("2147483647", buf);
+#endif
+#else // __BIONIC__
+ GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif // __BIONIC__
+}
+
+TEST(async_safe_log, ld_LONG_MIN) {
+#if defined(__BIONIC__)
+ char buf[BUFSIZ];
+ async_safe_format_buffer(buf, sizeof(buf), "%ld", LONG_MIN);
+#if defined(__LP64__)
+ EXPECT_STREQ("-9223372036854775808", buf);
+#else
+ EXPECT_STREQ("-2147483648", buf);
+#endif
+#else // __BIONIC__
+ GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif // __BIONIC__
+}
+
+TEST(async_safe_log, lld_LLONG_MAX) {
+#if defined(__BIONIC__)
+ char buf[BUFSIZ];
+ 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(async_safe_log, lld_LLONG_MIN) {
+#if defined(__BIONIC__)
+ char buf[BUFSIZ];
+ 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(async_safe_log, buffer_overrun) {
+#if defined(__BIONIC__)
+ char buf[BUFSIZ];
+ ASSERT_EQ(11, async_safe_format_buffer(buf, sizeof(buf), "hello %s", "world"));
+ EXPECT_STREQ("hello world", buf);
+ 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";
+#endif // __BIONIC__
+}
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index a0226a6..cf642cd 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -24,9 +24,14 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+
#include <android/dlext.h>
+#include <android-base/strings.h>
+
+#include <linux/memfd.h>
#include <sys/mman.h>
#include <sys/types.h>
+#include <sys/vfs.h>
#include <sys/wait.h>
#include <pagemap/pagemap.h>
@@ -460,7 +465,8 @@
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_;
};
@@ -506,19 +512,23 @@
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));
@@ -529,21 +539,28 @@
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
@@ -596,11 +613,11 @@
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;
@@ -802,6 +819,98 @@
dlclose(handle2);
}
+TEST(dlext, dlopen_ext_use_o_tmpfile_fd) {
+ const std::string lib_path = get_testlib_root() + "/libtest_simple.so";
+
+ int tmpfd = TEMP_FAILURE_RETRY(
+ open(get_testlib_root().c_str(), O_TMPFILE | O_CLOEXEC | O_RDWR | O_EXCL));
+
+ // Ignore kernels without O_TMPFILE flag support
+ if (tmpfd == -1 && (errno == EISDIR || errno == EINVAL || errno == EOPNOTSUPP)) {
+ return;
+ }
+
+ ASSERT_TRUE(tmpfd != -1) << strerror(errno);
+
+ android_namespace_t* ns =
+ android_create_namespace("testing-o_tmpfile",
+ nullptr,
+ get_testlib_root().c_str(),
+ ANDROID_NAMESPACE_TYPE_ISOLATED,
+ nullptr,
+ nullptr);
+
+ ASSERT_DL_NOTNULL(ns);
+
+ ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
+
+ std::string content;
+ ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
+ ASSERT_TRUE(android::base::WriteStringToFd(content, tmpfd)) << strerror(errno);
+
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
+ extinfo.library_fd = tmpfd;
+ extinfo.library_namespace = ns;
+
+ void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
+
+ ASSERT_DL_NOTNULL(handle);
+
+ uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
+ ASSERT_DL_NOTNULL(taxicab_number);
+ EXPECT_EQ(1729U, *taxicab_number);
+ dlclose(handle);
+}
+
+TEST(dlext, dlopen_ext_use_memfd) {
+ const std::string lib_path = get_testlib_root() + "/libtest_simple.so";
+
+ // create memfd
+ int memfd = syscall(__NR_memfd_create, "foobar", MFD_CLOEXEC);
+ if (memfd == -1 && errno == ENOSYS) {
+ return;
+ }
+
+ ASSERT_TRUE(memfd != -1) << strerror(errno);
+
+ // Check st.f_type is TMPFS_MAGIC for memfd
+ struct statfs st;
+ ASSERT_TRUE(TEMP_FAILURE_RETRY(fstatfs(memfd, &st)) == 0) << strerror(errno);
+ ASSERT_EQ(static_cast<decltype(st.f_type)>(TMPFS_MAGIC), st.f_type);
+
+ android_namespace_t* ns =
+ android_create_namespace("testing-memfd",
+ nullptr,
+ get_testlib_root().c_str(),
+ ANDROID_NAMESPACE_TYPE_ISOLATED,
+ nullptr,
+ nullptr);
+
+ ASSERT_DL_NOTNULL(ns);
+
+ ASSERT_TRUE(android_link_namespaces(ns, nullptr, g_core_shared_libs.c_str())) << dlerror();
+
+ // read file into memfd backed one.
+ std::string content;
+ ASSERT_TRUE(android::base::ReadFileToString(lib_path, &content)) << strerror(errno);
+ ASSERT_TRUE(android::base::WriteStringToFd(content, memfd)) << strerror(errno);
+
+ android_dlextinfo extinfo;
+ extinfo.flags = ANDROID_DLEXT_USE_LIBRARY_FD | ANDROID_DLEXT_USE_NAMESPACE;
+ extinfo.library_fd = memfd;
+ extinfo.library_namespace = ns;
+
+ void* handle = android_dlopen_ext("foobar", RTLD_NOW, &extinfo);
+
+ ASSERT_DL_NOTNULL(handle);
+
+ uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
+ ASSERT_DL_NOTNULL(taxicab_number);
+ EXPECT_EQ(1729U, *taxicab_number);
+ dlclose(handle);
+}
+
TEST(dlext, ns_symbol_visibilty_one_namespace) {
static const char* root_lib = "libnstest_root.so";
ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
@@ -1254,6 +1363,70 @@
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
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 4ff324e..0ec4663 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -247,6 +247,40 @@
// 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 @@
// 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,13 +300,13 @@
// 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);
}
diff --git a/tests/elf_test.cpp b/tests/elf_test.cpp
new file mode 100644
index 0000000..ad7cdfa
--- /dev/null
+++ b/tests/elf_test.cpp
@@ -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));
+}
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 67103e1..984a657 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -219,7 +219,6 @@
#endif // __BIONIC__
}
-// this buffer overflow. TODO: Fix clang.
TEST_F(DEATHTEST, strlcpy_fortified2) {
#if defined(__BIONIC__)
foo myfoo;
@@ -231,7 +230,6 @@
#endif // __BIONIC__
}
-// this buffer overflow. TODO: Fix clang.
TEST_F(DEATHTEST, strlcat_fortified2) {
#if defined(__BIONIC__)
foo myfoo;
@@ -407,11 +405,8 @@
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.
diff --git a/tests/libc_logging_test.cpp b/tests/libc_logging_test.cpp
deleted file mode 100644
index 4150483..0000000
--- a/tests/libc_logging_test.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#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, ...);
-#endif // __BIONIC__
-
-TEST(libc_logging, smoke) {
-#if defined(__BIONIC__)
- char buf[BUFSIZ];
-
- __libc_format_buffer(buf, sizeof(buf), "a");
- EXPECT_STREQ("a", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "%%");
- EXPECT_STREQ("%", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "01234");
- EXPECT_STREQ("01234", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%sb", "01234");
- EXPECT_STREQ("a01234b", buf);
-
- char* s = NULL;
- __libc_format_buffer(buf, sizeof(buf), "a%sb", s);
- EXPECT_STREQ("a(null)b", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "aa%scc", "bb");
- EXPECT_STREQ("aabbcc", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%cc", 'b');
- EXPECT_STREQ("abc", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%db", 1234);
- EXPECT_STREQ("a1234b", buf);
-
- __libc_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));
- EXPECT_STREQ("a16b", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%hhdb", static_cast<char>(0x7fffff10));
- EXPECT_STREQ("a16b", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%lldb", 0x1000000000LL);
- EXPECT_STREQ("a68719476736b", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%ldb", 70000L);
- EXPECT_STREQ("a70000b", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%pb", reinterpret_cast<void*>(0xb0001234));
- EXPECT_STREQ("a0xb0001234b", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%xz", 0x12ab);
- EXPECT_STREQ("a12abz", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%Xz", 0x12ab);
- EXPECT_STREQ("a12ABz", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%08xz", 0x123456);
- EXPECT_STREQ("a00123456z", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%5dz", 1234);
- EXPECT_STREQ("a 1234z", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%05dz", 1234);
- EXPECT_STREQ("a01234z", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%8dz", 1234);
- EXPECT_STREQ("a 1234z", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "a%-8dz", 1234);
- EXPECT_STREQ("a1234 z", buf);
-
- __libc_format_buffer(buf, sizeof(buf), "A%-11sZ", "abcdef");
- EXPECT_STREQ("Aabcdef Z", buf);
-
- __libc_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);
- EXPECT_STREQ("a005:5:05z", buf);
-
- void* p = NULL;
- __libc_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);
- 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) {
-#if defined(__BIONIC__)
- char buf[BUFSIZ];
- __libc_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) {
-#if defined(__BIONIC__)
- char buf[BUFSIZ];
- __libc_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) {
-#if defined(__BIONIC__)
- char buf[BUFSIZ];
- __libc_format_buffer(buf, sizeof(buf), "%ld", LONG_MAX);
-#if defined(__LP64__)
- EXPECT_STREQ("9223372036854775807", buf);
-#else
- EXPECT_STREQ("2147483647", buf);
-#endif
-#else // __BIONIC__
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
-}
-
-TEST(libc_logging, ld_LONG_MIN) {
-#if defined(__BIONIC__)
- char buf[BUFSIZ];
- __libc_format_buffer(buf, sizeof(buf), "%ld", LONG_MIN);
-#if defined(__LP64__)
- EXPECT_STREQ("-9223372036854775808", buf);
-#else
- EXPECT_STREQ("-2147483648", buf);
-#endif
-#else // __BIONIC__
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
-}
-
-TEST(libc_logging, lld_LLONG_MAX) {
-#if defined(__BIONIC__)
- char buf[BUFSIZ];
- __libc_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) {
-#if defined(__BIONIC__)
- char buf[BUFSIZ];
- __libc_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) {
-#if defined(__BIONIC__)
- char buf[BUFSIZ];
- ASSERT_EQ(11, __libc_format_buffer(buf, sizeof(buf), "hello %s", "world"));
- EXPECT_STREQ("hello world", buf);
- ASSERT_EQ(11, __libc_format_buffer(buf, 8, "hello %s", "world"));
- EXPECT_STREQ("hello w", buf);
-#else // __BIONIC__
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
-}
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index a031fe9..973a8d2 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -272,10 +272,8 @@
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 @@
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"],
+ },
+ },
}
// -----------------------------------------------------------------------------
diff --git a/tests/libs/bionic_tests_zipalign.cpp b/tests/libs/bionic_tests_zipalign.cpp
index 8e31474..56183ba 100644
--- a/tests/libs/bionic_tests_zipalign.cpp
+++ b/tests/libs/bionic_tests_zipalign.cpp
@@ -142,7 +142,7 @@
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");
diff --git a/tests/libs/dlopen_testlib_ifunc.c b/tests/libs/dlopen_testlib_ifunc.cpp
similarity index 65%
rename from tests/libs/dlopen_testlib_ifunc.c
rename to tests/libs/dlopen_testlib_ifunc.cpp
index b68a3dd..f8acba7 100644
--- a/tests/libs/dlopen_testlib_ifunc.c
+++ b/tests/libs/dlopen_testlib_ifunc.cpp
@@ -14,52 +14,56 @@
* 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
index 0000000..a1f1ab6
--- /dev/null
+++ b/tests/libs/dlopen_testlib_ifunc_variable.cpp
@@ -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
index 0000000..a550fef
--- /dev/null
+++ b/tests/libs/dlopen_testlib_ifunc_variable_impl.cpp
@@ -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;
+}
diff --git a/tests/link_test.cpp b/tests/link_test.cpp
new file mode 100644
index 0000000..ac3ccb9
--- /dev/null
+++ b/tests/link_test.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gtest/gtest.h>
+
+#include <link.h>
+
+TEST(link, dl_iterate_phdr_early_exit) {
+ static size_t call_count = 0;
+ ASSERT_EQ(123, dl_iterate_phdr([](dl_phdr_info*, size_t, void*) { ++call_count; return 123; },
+ nullptr));
+ ASSERT_EQ(1u, call_count);
+}
+
+TEST(link, dl_iterate_phdr) {
+ struct Functor {
+ static int Callback(dl_phdr_info* i, size_t s, void* data) {
+ reinterpret_cast<Functor*>(data)->DoChecks(i, s);
+ return 0;
+ }
+ void DoChecks(dl_phdr_info* info, size_t s) {
+ ASSERT_EQ(sizeof(dl_phdr_info), s);
+
+ // TODO: why does the entry for the main executable have a null dlpi_addr and no name anyway?
+ if (++count == 1 && info->dlpi_addr == 0) return;
+
+ ASSERT_TRUE(info->dlpi_name != nullptr);
+
+ // Find the first PT_LOAD program header so we can find the ELF header.
+ for (ElfW(Half) i = 0; i < info->dlpi_phnum; ++i) {
+ const ElfW(Phdr)* phdr = reinterpret_cast<const ElfW(Phdr)*>(&info->dlpi_phdr[i]);
+ if (phdr->p_type == PT_LOAD) {
+ const ElfW(Ehdr)* ehdr = reinterpret_cast<const ElfW(Ehdr)*>(info->dlpi_addr +
+ phdr->p_vaddr);
+ // Does it look like an ELF file?
+ ASSERT_EQ(0, memcmp(ehdr, ELFMAG, SELFMAG));
+ // Does the e_phnum match what dl_iterate_phdr told us?
+ ASSERT_EQ(info->dlpi_phnum, ehdr->e_phnum);
+ break;
+ }
+ }
+ }
+ size_t count;
+ } f = {};
+ ASSERT_EQ(0, dl_iterate_phdr(Functor::Callback, &f));
+}
+
+#if __arm__
+static uintptr_t read_exidx_func(uintptr_t* entry) {
+ int32_t offset = *entry;
+ // Sign-extend from int31 to int32.
+ if ((offset & 0x40000000) != 0) {
+ offset += -0x7fffffff - 1;
+ }
+ return reinterpret_cast<uintptr_t>(entry) + offset;
+}
+__attribute__((__unused__)) static void another_function_in_same_ELF_file() {}
+#endif
+
+TEST(link, dl_unwind_find_exidx) {
+#if __arm__
+ int count = 0;
+ struct eit_entry_t {
+ uintptr_t one;
+ uintptr_t two;
+ };
+ eit_entry_t* entries = reinterpret_cast<eit_entry_t*>(dl_unwind_find_exidx(
+ reinterpret_cast<_Unwind_Ptr>(read_exidx_func), &count));
+ ASSERT_TRUE(entries != nullptr);
+ ASSERT_GT(count, 0);
+
+ // Sanity checks
+ uintptr_t func = reinterpret_cast<uintptr_t>(read_exidx_func);
+ bool found = false;
+ for (int i = 0; i < count; ++i) {
+ // Entries must have bit 31 clear.
+ ASSERT_TRUE((entries[i].one & (1<<31)) == 0);
+
+ uintptr_t exidx_func = read_exidx_func(&entries[i].one);
+
+ // If our function is compiled for thumb, exception table contains our address - 1.
+ if (func == exidx_func || func == exidx_func + 1) found = true;
+
+ // Entries must be sorted. Some addresses may appear twice if function
+ // is compiled for arm.
+ if (i > 0) {
+ EXPECT_GE(exidx_func, read_exidx_func(&entries[i - 1].one)) << i;
+ }
+ }
+ ASSERT_TRUE(found);
+#else
+ GTEST_LOG_(INFO) << "dl_unwind_find_exidx is an ARM-only API\n";
+#endif
+}
diff --git a/tests/linux_swab_test.cpp b/tests/linux_swab_test.cpp
new file mode 100644
index 0000000..6b964dc
--- /dev/null
+++ b/tests/linux_swab_test.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <linux/swab.h>
+
+// This test makes sure that references to all of the kernel swab
+// macros/inline functions that are exported work properly.
+// Verifies that any kernel header updates do not break these macros.
+TEST(swab, fswa) {
+ EXPECT_EQ(0x3412U, __swab16(0x1234));
+ EXPECT_EQ(0x78563412U, __swab32(0x12345678U));
+ EXPECT_EQ(0xbaefcdab78563412ULL, __swab64(0x12345678abcdefbaULL));
+
+ __u16 bval16 = 0x1234;
+ EXPECT_EQ(0x3412U, __swab16p(&bval16));
+ __u32 bval32 = 0x12345678U;
+ EXPECT_EQ(0x78563412U, __swab32p(&bval32));
+ __u64 bval64 = 0x12345678abcdefbaULL;
+ EXPECT_EQ(0xbaefcdab78563412ULL, __swab64p(&bval64));
+
+ __u16 sval16 = 0x1234;
+ __swab16s(&sval16);
+ EXPECT_EQ(0x3412U, sval16);
+ __u32 sval32 = 0x12345678U;
+ __swab32s(&sval32);
+ EXPECT_EQ(0x78563412U, sval32);
+ __u64 sval64 = 0x12345678abcdefbaULL;
+ __swab64s(&sval64);
+ EXPECT_EQ(0xbaefcdab78563412ULL, sval64);
+
+ EXPECT_EQ(0x56781234U, __swahw32(0x12345678U));
+ EXPECT_EQ(0x34127856U, __swahb32(0x12345678U));
+
+ __u32 hval32 = 0x12345678U;
+ EXPECT_EQ(0x56781234U, __swahw32p(&hval32));
+ hval32 = 0x12345678U;
+ EXPECT_EQ(0x34127856U, __swahb32p(&hval32));
+
+ __u32 hsval32 = 0x12345678U;
+ __swahw32s(&hsval32);
+ EXPECT_EQ(0x56781234U, hsval32);
+ hsval32 = 0x12345678U;
+ __swahb32s(&hsval32);
+ EXPECT_EQ(0x34127856U, hsval32);
+}
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 87b4c81..d64bc48 100755
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -1963,8 +1963,9 @@
} 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;
diff --git a/tests/sys_ptrace_test.cpp b/tests/sys_ptrace_test.cpp
index 69638be..00322ec 100644
--- a/tests/sys_ptrace_test.cpp
+++ b/tests/sys_ptrace_test.cpp
@@ -266,7 +266,7 @@
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);
}
diff --git a/tools/versioner/src/Driver.cpp b/tools/versioner/src/Driver.cpp
index 215dc3c..1b631b6 100644
--- a/tools/versioner/src/Driver.cpp
+++ b/tools/versioner/src/Driver.cpp
@@ -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 @@
}
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);
diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp
index b551709..735ea04 100644
--- a/tools/versioner/src/versioner.cpp
+++ b/tools/versioner/src/versioner.cpp
@@ -446,6 +446,12 @@
}
}
+// 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;