Move libc_log code into libasync_safe.
This library is used by a number of different libraries in the system.
Make it easy for platform libraries to use this library and create
an actual exported include file.
Change the names of the functions to reflect the new name of the library.
Run clang_format on the async_safe_log.cpp file since the formatting is
all over the place.
Bug: 31919199
Test: Compiled for angler/bullhead, and booted.
Test: Ran bionic unit tests.
Test: Ran the malloc debug tests.
Change-Id: I8071bf690c17b0ea3bc8dc5749cdd5b6ad58478a
diff --git a/libc/Android.bp b/libc/Android.bp
index 590fd28..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: {
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/__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/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;