Merge "Avoid explicit use of "10000" in build files."
diff --git a/apex/Android.bp b/apex/Android.bp
index 100430d..c6c4cbf 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -36,6 +36,9 @@
},
key: "com.android.runtime.key",
certificate: ":com.android.runtime.certificate",
+ prebuilts: [
+ "bionic-linker-config",
+ ],
}
sdk {
@@ -76,3 +79,10 @@
},
},
}
+
+prebuilt_etc {
+ name: "bionic-linker-config",
+ src: "linker.config.txt",
+ filename: "linker.config.txt",
+ installable: false,
+}
diff --git a/apex/linker.config.txt b/apex/linker.config.txt
new file mode 100644
index 0000000..7bac3d6
--- /dev/null
+++ b/apex/linker.config.txt
@@ -0,0 +1,6 @@
+# Extra linker configurations for bionic APEX
+# See https://android.googlesource.com/platform/system/linkerconfig/+/master/README.md#apex_etc_linker_config_txt
+
+[properties]
+# Set bionic APEX as force visible so bionic APEX namespace is accessible via android_get_exported_namespace
+visible = true
diff --git a/docs/fdtrack.md b/docs/fdtrack.md
new file mode 100644
index 0000000..5bc9860
--- /dev/null
+++ b/docs/fdtrack.md
@@ -0,0 +1,66 @@
+## fdtrack
+
+fdtrack consists of two parts: a set of hooks in bionic to register a callback
+that's invoked on file descriptor operations, and a library that implements a
+hook to perform and store backtraces for file descriptor creation.
+
+### bionic hooks
+bionic provides a header in the `bionic_libc_platform_headers` header_lib at <[bionic/fdtrack.h](https://android.googlesource.com/platform/bionic/+/refs/heads/master/libc/platform/bionic/fdtrack.h)>.
+Register a callback with `android_fdtrack_compare_exchange_hook` to receive
+callbacks upon file descriptor creation and destruction. This function can be
+called at any point in order to start capturing events, but be sure to properly
+handle unbalanced closes. This callback may be called from an async signal safe
+context, but not vfork (bionic tracks whether a thread is vforked, and chooses
+not to call callbacks when this is the case).
+
+### libfdtrack
+[libfdtrack](https://android.googlesource.com/platform/bionic/+/refs/heads/master/libfdtrack)
+implements a library that uses libunwindstack to unwind and store fd creation backtraces.
+
+
+#### Using libfdtrack
+libfdtrack registers its hook upon being loaded, so to start capturing
+backtraces, `dlopen("libfdtrack.so", RTLD_GLOBAL)` is all that's needed. To dump
+its output to logcat, either use `fdtrack_dump`, or send the signal
+`BIONIC_SIGNAL_FDTRACK` (available from `<bionic/reserved_signals.h>`) to the
+process. If you wish to iterate through the results programmatically,
+`fdtrack_iterate` can be used (warning: this interface is currently unstable,
+don't use it in code that can be used on multiple platform versions.)
+
+libfdtrack adds a significant amount of overhead, so for processes that are
+latency-critical like system_server, it's not feasible to always capture
+backtraces. Instead, if you can detect that an fd leak is ongoing, turning on
+backtraces for a while and then triggering a dump can be sufficient.
+system_server [implements this approach](https://android.googlesource.com/platform/frameworks/base/+/679f3e4242b8e018eb7df90ef433f81088a64fff%5E%21/),
+spawning a thread that regularly checks the count of fds in the process, turns
+on fdtrack when it hits a threshold, and then aborts after another threshold.
+This dumps the output to logcat, which will be available in both the tombstone
+and logcat from bugreports.
+
+#### Implementation details
+There are multiple methods to unwind in Android:
+
+ * libunwindstack
+ * Pros
+ * Primary method on the platform
+ * Able to unwind through ART
+ * Cons
+ * Uses malloc internally: unsafe unless a separate allocator is
+ statically-linked and steps are taken to prevent the unwind from being
+ interrupted by a signal
+ * Slow - infeasible to be used always in latency-sensitive processes
+ * `android_unsafe_frame_pointer_chase`
+ * Pros
+ * Definitely async signal safe
+ * Fast
+ * Cons
+ * Unable to unwind through ART because it doesn't maintain the frame pointer
+ * Requires -fno-omit-frame-pointer to be used on all code being unwound
+ through, which currently isn't the case on Android
+ * Frame layout is a mess on 32-bit ARM: the ARM standard, clang, and GCC
+ [all disagree](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92172)
+ * Chasing the frame pointer will often result in multiple frames inside the
+ same function
+
+libfdtrack chooses to use libunwindstack for now, since unwinding through ART
+is critical to being useful for the initial user, system_server.
diff --git a/libc/Android.bp b/libc/Android.bp
index f638292..61d99ac 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -62,6 +62,8 @@
cppflags: [],
include_dirs: [
"bionic/libc/async_safe/include",
+ // For android_filesystem_config.h.
+ "system/core/libcutils/include",
],
header_libs: [
@@ -1178,7 +1180,6 @@
},
},
whole_static_libs: [
- "libc_bionic_systrace",
"libsystemproperties",
],
cppflags: ["-Wold-style-cast"],
@@ -1238,6 +1239,7 @@
"bionic/pthread_setname_np.cpp",
"bionic/pthread_setschedparam.cpp",
"bionic/pthread_spinlock.cpp",
+ "bionic/sys_thread_properties.cpp",
// The following implementations depend on pthread data or implementation,
// so we can't include them in libc_ndk.a.
diff --git a/libc/NOTICE b/libc/NOTICE
index e8dc4e7..58d6679 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -1040,6 +1040,22 @@
-------------------------------------------------------------------
Copyright (C) 2020 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.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2020 The Android Open Source Project
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/libc/async_safe/async_safe_log.cpp b/libc/async_safe/async_safe_log.cpp
index 207035a..8b2a32b 100644
--- a/libc/async_safe/async_safe_log.cpp
+++ b/libc/async_safe/async_safe_log.cpp
@@ -30,6 +30,7 @@
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <linux/net.h>
#include <pthread.h>
#include <stdarg.h>
#include <stddef.h>
@@ -51,12 +52,22 @@
#include "private/ErrnoRestorer.h"
#include "private/ScopedPthreadMutexLocker.h"
-// Don't call libc's close, since it might call back into us as a result of fdsan.
+// Don't call libc's close or socket, since it might call back into us as a result of fdsan/fdtrack.
#pragma GCC poison close
static int __close(int fd) {
return syscall(__NR_close, fd);
}
+static int __socket(int domain, int type, int protocol) {
+#if defined(__i386__)
+ unsigned long args[3] = {static_cast<unsigned long>(domain), static_cast<unsigned long>(type),
+ static_cast<unsigned long>(protocol)};
+ return syscall(__NR_socketcall, SYS_SOCKET, &args);
+#else
+ return syscall(__NR_socket, domain, type, protocol);
+#endif
+}
+
// Must be kept in sync with frameworks/base/core/java/android/util/EventLog.java.
enum AndroidEventLogType {
EVENT_TYPE_INT = 0,
@@ -460,7 +471,7 @@
// 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));
+ int log_fd = TEMP_FAILURE_RETRY(__socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
if (log_fd == -1) {
return -1;
}
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
index 56a8488..95f46e9 100644
--- a/libc/bionic/__libc_init_main_thread.cpp
+++ b/libc/bionic/__libc_init_main_thread.cpp
@@ -101,6 +101,19 @@
__set_tcb_dtv(tcb, const_cast<TlsDtv*>(&zero_dtv));
}
+// This is public so that the zygote can call it too. It is not expected
+// to be useful otherwise.
+//
+// Note in particular that it is not possible to return from any existing
+// stack frame with stack protector enabled after this function is called.
+extern "C" void android_reset_stack_guards() {
+ // The TLS stack guard is set from the global, so ensure that we've initialized the global
+ // before we initialize the TLS. Dynamic executables will initialize their copy of the global
+ // stack protector from the one in the main thread's TLS.
+ __libc_safe_arc4random_buf(&__stack_chk_guard, sizeof(__stack_chk_guard));
+ __init_tcb_stack_guard(__get_bionic_tcb());
+}
+
// Finish initializing the main thread.
__BIONIC_WEAK_FOR_NATIVE_BRIDGE
extern "C" void __libc_init_main_thread_late() {
@@ -119,11 +132,7 @@
// User code should never see this; we'll compute it when asked.
pthread_attr_setstacksize(&main_thread.attr, 0);
- // The TLS stack guard is set from the global, so ensure that we've initialized the global
- // before we initialize the TLS. Dynamic executables will initialize their copy of the global
- // stack protector from the one in the main thread's TLS.
- __libc_safe_arc4random_buf(&__stack_chk_guard, sizeof(__stack_chk_guard));
- __init_tcb_stack_guard(__get_bionic_tcb());
+ android_reset_stack_guards();
__init_thread(&main_thread);
diff --git a/libc/bionic/bionic_allocator.cpp b/libc/bionic/bionic_allocator.cpp
index b6d6ba7..98183d4 100644
--- a/libc/bionic/bionic_allocator.cpp
+++ b/libc/bionic/bionic_allocator.cpp
@@ -394,6 +394,26 @@
}
}
+size_t BionicAllocator::get_chunk_size(void* ptr) {
+ if (ptr == nullptr) return 0;
+
+ page_info* info = get_page_info_unchecked(ptr);
+ if (memcmp(info->signature, kSignature, sizeof(kSignature)) != 0) {
+ // Invalid pointer (mismatched signature)
+ return 0;
+ }
+ if (info->type == kLargeObject) {
+ return info->allocated_size - (static_cast<char*>(ptr) - reinterpret_cast<char*>(info));
+ }
+
+ BionicSmallObjectAllocator* allocator = get_small_object_allocator(info->type);
+ if (allocator != info->allocator_addr) {
+ // Invalid pointer.
+ return 0;
+ }
+ return allocator->get_block_size();
+}
+
BionicSmallObjectAllocator* BionicAllocator::get_small_object_allocator(uint32_t type) {
if (type < kSmallObjectMinSizeLog2 || type > kSmallObjectMaxSizeLog2) {
async_safe_fatal("invalid type: %u", type);
diff --git a/libc/bionic/bionic_elf_tls.cpp b/libc/bionic/bionic_elf_tls.cpp
index 61d826c..d5fb05a 100644
--- a/libc/bionic/bionic_elf_tls.cpp
+++ b/libc/bionic/bionic_elf_tls.cpp
@@ -28,6 +28,7 @@
#include "private/bionic_elf_tls.h"
+#include <async_safe/CHECK.h>
#include <async_safe/log.h>
#include <string.h>
#include <sys/param.h>
@@ -269,6 +270,12 @@
continue;
}
}
+ if (modules.on_destruction_cb != nullptr) {
+ void* dtls_begin = dtv->modules[i];
+ void* dtls_end =
+ static_cast<void*>(static_cast<char*>(dtls_begin) + allocator.get_chunk_size(dtls_begin));
+ modules.on_destruction_cb(dtls_begin, dtls_end);
+ }
allocator.free(dtv->modules[i]);
dtv->modules[i] = nullptr;
}
@@ -297,6 +304,12 @@
memcpy(mod_ptr, segment.init_ptr, segment.init_size);
}
dtv->modules[module_idx] = mod_ptr;
+
+ // Reports the allocation to the listener, if any.
+ if (modules.on_creation_cb != nullptr) {
+ modules.on_creation_cb(mod_ptr,
+ static_cast<void*>(static_cast<char*>(mod_ptr) + segment.size));
+ }
}
return static_cast<char*>(mod_ptr) + ti->offset;
@@ -351,6 +364,14 @@
// This module's TLS memory is allocated statically, so don't free it here.
continue;
}
+
+ if (modules.on_destruction_cb != nullptr) {
+ void* dtls_begin = dtv->modules[i];
+ void* dtls_end =
+ static_cast<void*>(static_cast<char*>(dtls_begin) + allocator.get_chunk_size(dtls_begin));
+ modules.on_destruction_cb(dtls_begin, dtls_end);
+ }
+
allocator.free(dtv->modules[i]);
}
@@ -364,3 +385,22 @@
// Clear the DTV slot. The DTV must not be used again with this thread.
tcb->tls_slot(TLS_SLOT_DTV) = nullptr;
}
+
+// Invokes all the registered thread_exit callbacks, if any.
+void __notify_thread_exit_callbacks() {
+ TlsModules& modules = __libc_shared_globals()->tls_modules;
+ if (modules.first_thread_exit_callback == nullptr) {
+ // If there is no first_thread_exit_callback, there shouldn't be a tail.
+ CHECK(modules.thread_exit_callback_tail_node == nullptr);
+ return;
+ }
+
+ // Callbacks are supposed to be invoked in the reverse order
+ // in which they were registered.
+ CallbackHolder* node = modules.thread_exit_callback_tail_node;
+ while (node != nullptr) {
+ node->cb();
+ node = node->prev;
+ }
+ modules.first_thread_exit_callback();
+}
diff --git a/libc/bionic/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
index fd97712..0de51c5 100644
--- a/libc/bionic/bionic_systrace.cpp
+++ b/libc/bionic/bionic_systrace.cpp
@@ -14,52 +14,50 @@
* limitations under the License.
*/
+#include "private/bionic_systrace.h"
+
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "private/bionic_lock.h"
-#include "private/bionic_systrace.h"
-#include "private/CachedProperty.h"
-
#include <async_safe/log.h>
#include <cutils/trace.h> // For ATRACE_TAG_BIONIC.
+#include "private/CachedProperty.h"
+#include "private/bionic_lock.h"
+
#define WRITE_OFFSET 32
static Lock g_lock;
-static CachedProperty g_debug_atrace_tags_enableflags("debug.atrace.tags.enableflags");
-static uint64_t g_tags;
-static int g_trace_marker_fd = -1;
-static bool should_trace() {
+bool should_trace(const uint64_t enable_tags) {
+ static uint64_t tags_val;
+ static CachedProperty tags_prop(kTraceTagsProp);
g_lock.lock();
- if (g_debug_atrace_tags_enableflags.DidChange()) {
- g_tags = strtoull(g_debug_atrace_tags_enableflags.Get(), nullptr, 0);
+ if (tags_prop.DidChange()) {
+ tags_val = strtoull(tags_prop.Get(), nullptr, 0);
}
g_lock.unlock();
- return ((g_tags & ATRACE_TAG_BIONIC) != 0);
+ return tags_val & enable_tags;
}
-static int get_trace_marker_fd() {
+int get_trace_marker_fd() {
+ static int opened_trace_marker_fd = -1;
g_lock.lock();
- if (g_trace_marker_fd == -1) {
- g_trace_marker_fd = open("/sys/kernel/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
- if (g_trace_marker_fd == -1) {
- g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
+ if (opened_trace_marker_fd == -1) {
+ opened_trace_marker_fd = open("/sys/kernel/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
+ if (opened_trace_marker_fd == -1) {
+ opened_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
}
}
g_lock.unlock();
- return g_trace_marker_fd;
+ return opened_trace_marker_fd;
}
-void bionic_trace_begin(const char* message) {
- if (!should_trace()) {
- return;
- }
-
+// event could be 'B' for begin or 'E' for end.
+void output_trace(const char* message, const char event) {
int trace_marker_fd = get_trace_marker_fd();
if (trace_marker_fd == -1) {
return;
@@ -69,13 +67,22 @@
// kernel trace_marker.
int length = strlen(message);
char buf[length + WRITE_OFFSET];
- size_t len = async_safe_format_buffer(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
+ size_t len =
+ async_safe_format_buffer(buf, length + WRITE_OFFSET, "%c|%d|%s", event, getpid(), message);
// Tracing may stop just after checking property and before writing the message.
// So the write is acceptable to fail. See b/20666100.
TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
}
+void bionic_trace_begin(const char* message) {
+ if (!should_trace()) {
+ return;
+ }
+
+ output_trace(message);
+}
+
void bionic_trace_end() {
if (!should_trace()) {
return;
diff --git a/libc/bionic/fortify.cpp b/libc/bionic/fortify.cpp
index 3b804b0..88ae477 100644
--- a/libc/bionic/fortify.cpp
+++ b/libc/bionic/fortify.cpp
@@ -94,9 +94,6 @@
}
char* __fgets_chk(char* dst, int supplied_size, FILE* stream, size_t dst_len_from_compiler) {
- if (supplied_size < 0) {
- __fortify_fatal("fgets: buffer size %d < 0", supplied_size);
- }
__check_buffer_access("fgets", "write into", supplied_size, dst_len_from_compiler);
return fgets(dst, supplied_size, stream);
}
diff --git a/libc/bionic/gethostname.cpp b/libc/bionic/gethostname.cpp
index 962fea1..b780a2f 100644
--- a/libc/bionic/gethostname.cpp
+++ b/libc/bionic/gethostname.cpp
@@ -32,10 +32,8 @@
#include <unistd.h>
int gethostname(char* buf, size_t n) {
- struct utsname name;
- if (uname(&name) == -1) {
- return -1;
- }
+ utsname name = {};
+ uname(&name);
size_t name_length = static_cast<size_t>(strlen(name.nodename) + 1);
if (name_length > n) {
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index cf5423e..e3a447d 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -147,6 +147,7 @@
mod.first_generation = kTlsGenerationFirst;
modules.module_count = 1;
+ modules.static_module_count = 1;
modules.module_table = &mod;
} else {
layout.reserve_exe_segment_and_tcb(nullptr, progname);
diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp
index 3b873b3..81dab57 100644
--- a/libc/bionic/pthread_exit.cpp
+++ b/libc/bionic/pthread_exit.cpp
@@ -112,7 +112,6 @@
munmap(thread->shadow_call_stack_guard_region, SCS_GUARD_REGION_SIZE);
#endif
- // Free the ELF TLS DTV and all dynamically-allocated ELF TLS memory.
__free_dynamic_tls(__get_bionic_tcb());
if (old_state == THREAD_DETACHED) {
@@ -128,6 +127,7 @@
if (thread->mmap_size != 0) {
// We need to free mapped space for detached threads when they exit.
// That's not something we can do in C.
+ __notify_thread_exit_callbacks();
__hwasan_thread_exit();
_exit_with_stack_teardown(thread->mmap_base, thread->mmap_size);
}
@@ -135,6 +135,8 @@
// No need to free mapped space. Either there was no space mapped, or it is left for
// the pthread_join caller to clean up.
+ __notify_thread_exit_callbacks();
__hwasan_thread_exit();
+
__exit(0);
}
diff --git a/libc/bionic/strtol.cpp b/libc/bionic/strtol.cpp
index 63ac102..77f1d92 100644
--- a/libc/bionic/strtol.cpp
+++ b/libc/bionic/strtol.cpp
@@ -184,9 +184,7 @@
}
// Public API since L, but not in any header.
-extern "C" long long strtoq(const char* s, char** end, int base) {
- return strtoll(s, end, base);
-}
+__strong_alias(strtoq, strtoll);
unsigned long strtoul(const char* s, char** end, int base) {
return StrToU<unsigned long, ULONG_MAX>(s, end, base);
@@ -201,6 +199,4 @@
}
// Public API since L, but not in any header.
-extern "C" unsigned long long strtouq(const char* s, char** end, int base) {
- return strtoull(s, end, base);
-}
+__strong_alias(strtouq, strtoull);
diff --git a/libc/bionic/sys_thread_properties.cpp b/libc/bionic/sys_thread_properties.cpp
new file mode 100644
index 0000000..24d7551
--- /dev/null
+++ b/libc/bionic/sys_thread_properties.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2020 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 <sys/thread_properties.h>
+
+#include <async_safe/CHECK.h>
+#include <async_safe/log.h>
+
+#include <elf.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include <sys/ptrace.h>
+#include <sys/uio.h>
+#include <sys/user.h>
+
+#include "private/bionic_elf_tls.h"
+#include "private/bionic_globals.h"
+#include "private/bionic_tls.h"
+#include "pthread_internal.h"
+
+void __libc_get_static_tls_bounds(void** stls_begin, void** stls_end) {
+ const StaticTlsLayout& layout = __libc_shared_globals()->static_tls_layout;
+ *stls_begin = reinterpret_cast<char*>(__get_bionic_tcb()) - layout.offset_bionic_tcb();
+ *stls_end = reinterpret_cast<char*>(*stls_begin) + layout.size();
+}
+
+void __libc_register_thread_exit_callback(thread_exit_cb_t cb) {
+ TlsModules& modules = __libc_shared_globals()->tls_modules;
+
+ if (modules.first_thread_exit_callback == nullptr) {
+ modules.first_thread_exit_callback = cb;
+ return;
+ };
+
+ BionicAllocator& allocator = __libc_shared_globals()->tls_allocator;
+ CallbackHolder* new_node =
+ reinterpret_cast<CallbackHolder*>(allocator.alloc(sizeof(CallbackHolder)));
+ new_node->cb = cb;
+ new_node->prev = modules.thread_exit_callback_tail_node;
+ modules.thread_exit_callback_tail_node = new_node;
+}
+
+static inline __always_inline bionic_tcb* __get_bionic_tcb_for_thread(pid_t tid) {
+ // If tid is same as self, then we don't need ptrace.
+ if (gettid() == tid) return __get_bionic_tcb();
+
+ // Find the thread-pointer register for the given thread.
+ void** tp_reg = nullptr;
+
+#if defined(__x86_64__) || defined(__i386__)
+ struct user_regs_struct regs;
+ struct iovec pt_iov = {
+ .iov_base = ®s,
+ .iov_len = sizeof(regs),
+ };
+ if (ptrace(PTRACE_GETREGSET, tid, NT_PRSTATUS, &pt_iov) == 0) {
+#if defined(__x86_64__)
+ tp_reg = reinterpret_cast<void**>(regs.fs);
+#elif defined(__i386__)
+ tp_reg = reinterpret_cast<void**>(regs.xgs);
+#endif
+ }
+#elif defined(__aarch64__) || defined(__arm__)
+ uint64_t reg;
+ struct iovec pt_iov {
+ .iov_base = ®, .iov_len = sizeof(reg),
+ };
+
+ if (ptrace(PTRACE_GETREGSET, tid, NT_ARM_TLS, &pt_iov) == 0) {
+ tp_reg = reinterpret_cast<void**>(reg);
+ }
+#endif
+
+ if (tp_reg == nullptr) {
+ async_safe_write_log(ANDROID_LOG_FATAL, "libc",
+ "__get_bionic_tcb_for_thread failed to read thread register.");
+ }
+
+ return reinterpret_cast<bionic_tcb*>(&tp_reg[MIN_TLS_SLOT]);
+}
+
+void __libc_iterate_dynamic_tls(pid_t tid,
+ void (*cb)(void* __dynamic_tls_begin, void* __dynamic_tls_end,
+ size_t __dso_id, void* __arg),
+ void* arg) {
+ TlsModules& modules = __libc_shared_globals()->tls_modules;
+ bionic_tcb* const tcb = __get_bionic_tcb_for_thread(tid);
+ TlsDtv* const dtv = __get_tcb_dtv(tcb);
+ BionicAllocator& allocator = __libc_shared_globals()->tls_allocator;
+
+ for (size_t i = modules.static_module_count; i < dtv->count; ++i) {
+ void* dtls_begin = dtv->modules[i];
+ if (dtls_begin == nullptr) continue;
+ void* dtls_end =
+ static_cast<void*>(static_cast<char*>(dtls_begin) + allocator.get_chunk_size(dtls_begin));
+ size_t dso_id = __tls_module_idx_to_id(i);
+
+ cb(dtls_begin, dtls_end, dso_id, arg);
+ }
+}
+
+void __libc_register_dynamic_tls_listeners(dtls_listener_t on_creation,
+ dtls_listener_t on_destruction) {
+ TlsModules& tls_modules = __libc_shared_globals()->tls_modules;
+ tls_modules.on_creation_cb = on_creation;
+ tls_modules.on_destruction_cb = on_destruction;
+}
diff --git a/libc/bionic/system_property_set.cpp b/libc/bionic/system_property_set.cpp
index 212aafc..6823b6a 100644
--- a/libc/bionic/system_property_set.cpp
+++ b/libc/bionic/system_property_set.cpp
@@ -41,12 +41,13 @@
#include <sys/_system_properties.h>
#include <unistd.h>
-#include <async_safe/log.h>
#include <async_safe/CHECK.h>
+#include <async_safe/log.h>
+#include <system_properties/prop_trace.h>
-#include "private/bionic_defs.h"
#include "platform/bionic/macros.h"
#include "private/ScopedFd.h"
+#include "private/bionic_defs.h"
static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
static const char* kServiceVersionPropertyName = "ro.property_service.version";
@@ -249,6 +250,8 @@
if (key == nullptr) return -1;
if (value == nullptr) value = "";
+ SyspropTrace trace(key, value, nullptr /* prop_info */, PropertyAction::kPropertySet);
+
if (g_propservice_protocol_version == 0) {
detect_protocol_version();
}
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index 833fa59..a237254 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -170,6 +170,16 @@
* Available since API level 28.
*/
#define M_PURGE (-101)
+/*
+ * mallopt() option for per-thread memory initialization tuning.
+ * The value argument should be one of:
+ * 1: Disable automatic heap initialization and, where possible, memory tagging,
+ * on this thread.
+ * 0: Normal behavior.
+ *
+ * Available since API level 31.
+ */
+#define M_THREAD_DISABLE_MEM_INIT (-103)
/**
* mallopt() option to set the maximum number of items in the secondary
* cache of the scudo allocator.
diff --git a/libc/include/math.h b/libc/include/math.h
index 7efc83a..8c084b2 100644
--- a/libc/include/math.h
+++ b/libc/include/math.h
@@ -10,12 +10,10 @@
*/
/*
- * from: @(#)fdlibm.h 5.1 93/09/24
- * $FreeBSD$
+ * Originally based on fdlibm.h 5.1 via FreeBSD.
*/
-#ifndef _MATH_H_
-#define _MATH_H_
+#pragma once
#include <sys/cdefs.h>
#include <limits.h>
@@ -408,5 +406,3 @@
#endif
__END_DECLS
-
-#endif
diff --git a/libc/include/sys/procfs.h b/libc/include/sys/procfs.h
index 75a1e98..a082e97 100644
--- a/libc/include/sys/procfs.h
+++ b/libc/include/sys/procfs.h
@@ -26,16 +26,24 @@
* SUCH DAMAGE.
*/
-#ifndef _SYS_PROCFS_H_
-#define _SYS_PROCFS_H_
+#pragma once
#include <sys/cdefs.h>
+#include <sys/ptrace.h>
#include <sys/ucontext.h>
__BEGIN_DECLS
+#if defined(__arm__)
+#define ELF_NGREG (sizeof(struct user_regs) / sizeof(elf_greg_t))
+#elif defined(__aarch64__)
+#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t))
+#else
+#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
+#endif
+
typedef unsigned long elf_greg_t;
-typedef elf_greg_t elf_gregset_t[NGREG];
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
typedef fpregset_t elf_fpregset_t;
@@ -58,5 +66,3 @@
#define ELF_PRARGSZ 80
__END_DECLS
-
-#endif
diff --git a/libc/include/sys/thread_properties.h b/libc/include/sys/thread_properties.h
new file mode 100644
index 0000000..b5d30c7
--- /dev/null
+++ b/libc/include/sys/thread_properties.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+/**
+ * @file thread_properties.h
+ * @brief Thread properties API.
+ *
+ * https://sourceware.org/glibc/wiki/ThreadPropertiesAPI
+ * API for querying various properties of the current thread, used mostly by
+ * the sanitizers.
+ *
+ * Available since API level 31.
+ *
+ */
+
+#include <sys/cdefs.h>
+#include <unistd.h>
+
+__BEGIN_DECLS
+
+/**
+ * Gets the bounds of static TLS for the current thread.
+ *
+ * Available since API level 31.
+ */
+void __libc_get_static_tls_bounds(void** __static_tls_begin,
+ void** __static_tls_end) __INTRODUCED_IN(31);
+
+
+/**
+ * Registers callback to be called right before the thread is dead.
+ * The callbacks are chained, they are called in the order opposite to the order
+ * they were registered.
+ *
+ * The callbacks must be registered only before any threads were created.
+ * No signals may arrive during the calls to these callbacks.
+ * The callbacks may not access the thread's dynamic TLS because they will have
+ * been freed by the time these callbacks are invoked.
+ *
+ * Available since API level 31.
+ */
+void __libc_register_thread_exit_callback(void (*__cb)(void)) __INTRODUCED_IN(31);
+
+/**
+ * Iterates over all dynamic TLS chunks for the given thread.
+ * The thread should have been suspended. It is undefined-behaviour if there is concurrent
+ * modification of the target thread's dynamic TLS.
+ *
+ * Available since API level 31.
+ */
+void __libc_iterate_dynamic_tls(pid_t __tid,
+ void (*__cb)(void* __dynamic_tls_begin,
+ void* __dynamic_tls_end,
+ size_t __dso_id,
+ void* __arg),
+ void* __arg) __INTRODUCED_IN(31);
+
+/**
+ * Register on_creation and on_destruction callbacks, which will be called after a dynamic
+ * TLS creation and before a dynamic TLS destruction, respectively.
+ *
+ * Available since API level 31.
+ */
+void __libc_register_dynamic_tls_listeners(
+ void (*__on_creation)(void* __dynamic_tls_begin,
+ void* __dynamic_tls_end),
+ void (*__on_destruction)(void* __dynamic_tls_begin,
+ void* __dynamic_tls_end)) __INTRODUCED_IN(31);
+
+__END_DECLS
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 10732a1..a224eab 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1554,6 +1554,10 @@
global:
ffsl;
ffsll;
+ __libc_get_static_tls_bounds;
+ __libc_register_thread_exit_callback;
+ __libc_iterate_dynamic_tls;
+ __libc_register_dynamic_tls_listeners;
} LIBC_R;
LIBC_PRIVATE {
@@ -1766,4 +1770,5 @@
android_net_res_stats_get_info_for_net;
android_net_res_stats_aggregate;
android_net_res_stats_get_usable_servers;
+ android_reset_stack_guards;
} LIBC_Q;
diff --git a/libc/platform/bionic/mte_kernel.h b/libc/platform/bionic/mte_kernel.h
index e8ef2a5..d81480a 100644
--- a/libc/platform/bionic/mte_kernel.h
+++ b/libc/platform/bionic/mte_kernel.h
@@ -54,4 +54,6 @@
#define PTRACE_PEEKMTETAGS 33
#define PTRACE_POKEMTETAGS 34
+#define NT_ARM_TAGGED_ADDR_CTRL 0x409
+
#endif
diff --git a/libc/platform/scudo_platform_tls_slot.h b/libc/platform/scudo_platform_tls_slot.h
new file mode 100644
index 0000000..9d017c0
--- /dev/null
+++ b/libc/platform/scudo_platform_tls_slot.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "bionic/tls.h"
+
+inline uintptr_t *getPlatformAllocatorTlsSlot() {
+ return reinterpret_cast<uintptr_t*>(&__get_tls()[TLS_SLOT_SANITIZER]);
+}
diff --git a/libc/private/bionic_allocator.h b/libc/private/bionic_allocator.h
index c705ce4..342fd51 100644
--- a/libc/private/bionic_allocator.h
+++ b/libc/private/bionic_allocator.h
@@ -110,6 +110,11 @@
// Note that this implementation of realloc never shrinks allocation
void* realloc(void* ptr, size_t size);
void free(void* ptr);
+
+ // Returns the size of the given allocated heap chunk, if it is valid.
+ // Otherwise, this may return 0 or cause a segfault if the pointer is invalid.
+ size_t get_chunk_size(void* ptr);
+
private:
void* alloc_mmap(size_t align, size_t size);
inline void* alloc_impl(size_t align, size_t size);
diff --git a/libc/private/bionic_elf_tls.h b/libc/private/bionic_elf_tls.h
index fa1af76..e0ec7b5 100644
--- a/libc/private/bionic_elf_tls.h
+++ b/libc/private/bionic_elf_tls.h
@@ -111,6 +111,18 @@
void* soinfo_ptr = nullptr;
};
+// Signature of the callbacks that will be called after DTLS creation and
+// before DTLS destruction.
+typedef void (*dtls_listener_t)(void* dynamic_tls_begin, void* dynamic_tls_end);
+
+// Signature of the thread-exit callbacks.
+typedef void (*thread_exit_cb_t)(void);
+
+struct CallbackHolder {
+ thread_exit_cb_t cb;
+ CallbackHolder* prev;
+};
+
// Table of the ELF TLS modules. Either the dynamic linker or the static
// initialization code prepares this table, and it's then used during thread
// creation and for dynamic TLS lookups.
@@ -128,7 +140,20 @@
// Pointer to a block of TlsModule objects. The first module has ID 1 and
// is stored at index 0 in this table.
size_t module_count = 0;
+ size_t static_module_count = 0;
TlsModule* module_table = nullptr;
+
+ // Callback to be invoked after a dynamic TLS allocation.
+ dtls_listener_t on_creation_cb = nullptr;
+
+ // Callback to be invoked before a dynamic TLS deallocation.
+ dtls_listener_t on_destruction_cb = nullptr;
+
+ // The first thread-exit callback; inlined to avoid allocation.
+ thread_exit_cb_t first_thread_exit_callback = nullptr;
+
+ // The additional callbacks, if any.
+ CallbackHolder* thread_exit_callback_tail_node = nullptr;
};
void __init_static_tls(void* static_tls);
@@ -175,3 +200,4 @@
struct bionic_tcb;
void __free_dynamic_tls(bionic_tcb* tcb);
+void __notify_thread_exit_callbacks();
diff --git a/libc/private/bionic_ifuncs.h b/libc/private/bionic_ifuncs.h
index f175bec..e6b349a 100644
--- a/libc/private/bionic_ifuncs.h
+++ b/libc/private/bionic_ifuncs.h
@@ -40,9 +40,12 @@
#define IFUNC_ARGS ()
#endif
+// We can't have HWASAN enabled in resolvers because they may be called before HWASAN is
+// initialized.
#define DEFINE_IFUNC_FOR(name) \
name##_func name __attribute__((ifunc(#name "_resolver"))); \
__attribute__((visibility("hidden"))) \
+ __attribute__((no_sanitize("hwaddress"))) \
name##_func* name##_resolver IFUNC_ARGS
#define DECLARE_FUNC(type, name) \
diff --git a/libc/private/bionic_systrace.h b/libc/private/bionic_systrace.h
index dbe1739..6b11812 100644
--- a/libc/private/bionic_systrace.h
+++ b/libc/private/bionic_systrace.h
@@ -16,8 +16,12 @@
#pragma once
+#include <cutils/trace.h> // For ATRACE_TAG_BIONIC.
+
#include "platform/bionic/macros.h"
+static constexpr char kTraceTagsProp[] = "debug.atrace.tags.enableflags";
+
// Tracing class for bionic. To begin a trace at a specified point:
// ScopedTrace("Trace message");
// The trace will end when the contructor goes out of scope.
@@ -33,5 +37,9 @@
BIONIC_DISALLOW_COPY_AND_ASSIGN(ScopedTrace);
};
+int get_trace_marker_fd();
+bool should_trace(const uint64_t enable_tags = ATRACE_TAG_BIONIC);
+void output_trace(const char* message, const char event = 'B');
+
void bionic_trace_begin(const char* message);
void bionic_trace_end();
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index afc2c48..b8aced8 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -773,10 +773,7 @@
// Returns first argument, or nullptr if no characters were read.
// Does not return nullptr if n == 1.
char* fgets_unlocked(char* buf, int n, FILE* fp) {
- if (n <= 0) {
- errno = EINVAL;
- return nullptr;
- }
+ if (n <= 0) __fortify_fatal("fgets: buffer size %d <= 0", n);
_SET_ORIENTATION(fp, -1);
diff --git a/libc/system_properties/Android.bp b/libc/system_properties/Android.bp
index 8780dda..3846169 100644
--- a/libc/system_properties/Android.bp
+++ b/libc/system_properties/Android.bp
@@ -8,9 +8,11 @@
"contexts_serialized.cpp",
"prop_area.cpp",
"prop_info.cpp",
+ "prop_trace.cpp",
"system_properties.cpp",
],
whole_static_libs: [
+ "libc_bionic_systrace",
"libpropertyinfoparser",
],
header_libs: [
@@ -23,3 +25,20 @@
],
export_include_dirs: ["include"],
}
+
+cc_benchmark {
+ name: "property_context_lookup_benchmark",
+ srcs: [
+ "context_lookup_benchmark.cpp",
+ ],
+ include_dirs: [
+ "bionic/libc",
+ ],
+
+ shared_libs: ["libbase"],
+ static_libs: [
+ "libpropertyinfoserializer",
+ "libsystemproperties",
+ "libasync_safe",
+ ],
+}
diff --git a/libc/system_properties/context_lookup_benchmark.cpp b/libc/system_properties/context_lookup_benchmark.cpp
new file mode 100644
index 0000000..1564250
--- /dev/null
+++ b/libc/system_properties/context_lookup_benchmark.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2020 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 <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <benchmark/benchmark.h>
+#include <property_info_parser/property_info_parser.h>
+#include <property_info_serializer/property_info_serializer.h>
+#include <system_properties/contexts_split.h>
+
+#include "context_lookup_benchmark_data.h"
+
+using android::base::Split;
+using android::base::WriteStringToFd;
+using android::properties::BuildTrie;
+using android::properties::ParsePropertyInfoFile;
+using android::properties::PropertyInfoArea;
+using android::properties::PropertyInfoEntry;
+
+BENCHMARK_MAIN();
+
+class LegacyPropertyMapping : public ContextsSplit {
+ public:
+ LegacyPropertyMapping(const char* property_contexts) {
+ TemporaryFile file;
+ if (!WriteStringToFd(property_contexts, file.fd)) {
+ PLOG(FATAL) << "Could not write to temporary file";
+ }
+
+ if (!InitializePropertiesFromFile(file.path)) {
+ LOG(FATAL) << "Could not initialize properties";
+ }
+ }
+};
+
+static std::vector<std::string> PropertiesToLookup() {
+ std::vector<std::string> properties;
+ auto property_lines = Split(aosp_s_property_contexts, "\n");
+ for (const auto& line : property_lines) {
+ if (line.empty() || line[0] == '#') {
+ continue;
+ }
+
+ auto property = Split(line, " ")[0];
+ properties.push_back(property);
+ properties.push_back(property + "0");
+ properties.push_back(property + "A");
+ }
+ return properties;
+}
+
+static void LegacyLookupOreo(benchmark::State& state) {
+ LegacyPropertyMapping mapping(oreo_property_contexts);
+ auto properties = PropertiesToLookup();
+ for (auto _ : state) {
+ for (const auto& property : properties) {
+ benchmark::DoNotOptimize(mapping.GetPrefixNodeForName(property.c_str()));
+ }
+ }
+}
+BENCHMARK(LegacyLookupOreo);
+
+static void LegacyLookupS(benchmark::State& state) {
+ LegacyPropertyMapping mapping(aosp_s_property_contexts);
+ auto properties = PropertiesToLookup();
+ for (auto _ : state) {
+ for (const auto& property : properties) {
+ benchmark::DoNotOptimize(mapping.GetPrefixNodeForName(property.c_str()));
+ }
+ }
+}
+BENCHMARK(LegacyLookupS);
+
+static std::string CreateSerializedTrie(const char* input_file) {
+ std::vector<std::string> errors;
+ std::vector<PropertyInfoEntry> property_infos;
+ ParsePropertyInfoFile(input_file, false, &property_infos, &errors);
+
+ std::string serialized_trie;
+ std::string error;
+ if (!BuildTrie(property_infos, "u:object_r:default_prop:s0", "string", &serialized_trie,
+ &error)) {
+ LOG(FATAL) << "Could not build trie: " << error;
+ }
+ return serialized_trie;
+}
+
+static void TrieLookupOreo(benchmark::State& state) {
+ std::string serialized_trie = CreateSerializedTrie(oreo_property_contexts);
+ PropertyInfoArea* trie = reinterpret_cast<PropertyInfoArea*>(serialized_trie.data());
+ auto properties = PropertiesToLookup();
+ for (auto _ : state) {
+ for (const auto& property : properties) {
+ trie->GetPropertyInfo(property.c_str(), nullptr, nullptr);
+ }
+ }
+}
+BENCHMARK(TrieLookupOreo);
+
+static void TrieLookupS(benchmark::State& state) {
+ std::string serialized_trie = CreateSerializedTrie(aosp_s_property_contexts);
+ PropertyInfoArea* trie = reinterpret_cast<PropertyInfoArea*>(serialized_trie.data());
+ auto properties = PropertiesToLookup();
+ for (auto _ : state) {
+ for (const auto& property : properties) {
+ trie->GetPropertyInfo(property.c_str(), nullptr, nullptr);
+ }
+ }
+}
+BENCHMARK(TrieLookupS);
diff --git a/libc/system_properties/context_lookup_benchmark_data.h b/libc/system_properties/context_lookup_benchmark_data.h
new file mode 100644
index 0000000..3cc3257
--- /dev/null
+++ b/libc/system_properties/context_lookup_benchmark_data.h
@@ -0,0 +1,1012 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+static char oreo_property_contexts[] = R"(
+net.rmnet u:object_r:net_radio_prop:s0
+net.gprs u:object_r:net_radio_prop:s0
+net.ppp u:object_r:net_radio_prop:s0
+net.qmi u:object_r:net_radio_prop:s0
+net.lte u:object_r:net_radio_prop:s0
+net.cdma u:object_r:net_radio_prop:s0
+net.dns u:object_r:net_dns_prop:s0
+sys.usb.config u:object_r:system_radio_prop:s0
+ril. u:object_r:radio_prop:s0
+ro.ril. u:object_r:radio_prop:s0
+gsm. u:object_r:radio_prop:s0
+persist.radio u:object_r:radio_prop:s0
+net. u:object_r:system_prop:s0
+dev. u:object_r:system_prop:s0
+ro.runtime. u:object_r:system_prop:s0
+ro.runtime.firstboot u:object_r:firstboot_prop:s0
+hw. u:object_r:system_prop:s0
+ro.hw. u:object_r:system_prop:s0
+sys. u:object_r:system_prop:s0
+sys.cppreopt u:object_r:cppreopt_prop:s0
+sys.powerctl u:object_r:powerctl_prop:s0
+sys.usb.ffs. u:object_r:ffs_prop:s0
+service. u:object_r:system_prop:s0
+dhcp. u:object_r:dhcp_prop:s0
+dhcp.bt-pan.result u:object_r:pan_result_prop:s0
+bluetooth. u:object_r:bluetooth_prop:s0
+debug. u:object_r:debug_prop:s0
+debug.db. u:object_r:debuggerd_prop:s0
+dumpstate. u:object_r:dumpstate_prop:s0
+dumpstate.options u:object_r:dumpstate_options_prop:s0
+log. u:object_r:log_prop:s0
+log.tag u:object_r:log_tag_prop:s0
+log.tag.WifiHAL u:object_r:wifi_log_prop:s0
+security.perf_harden u:object_r:shell_prop:s0
+service.adb.root u:object_r:shell_prop:s0
+service.adb.tcp.port u:object_r:shell_prop:s0
+persist.audio. u:object_r:audio_prop:s0
+persist.bluetooth. u:object_r:bluetooth_prop:s0
+persist.debug. u:object_r:persist_debug_prop:s0
+persist.logd. u:object_r:logd_prop:s0
+persist.logd.security u:object_r:device_logging_prop:s0
+persist.logd.logpersistd u:object_r:logpersistd_logging_prop:s0
+logd.logpersistd u:object_r:logpersistd_logging_prop:s0
+persist.log.tag u:object_r:log_tag_prop:s0
+persist.mmc. u:object_r:mmc_prop:s0
+persist.sys. u:object_r:system_prop:s0
+persist.sys.safemode u:object_r:safemode_prop:s0
+ro.sys.safemode u:object_r:safemode_prop:s0
+persist.sys.audit_safemode u:object_r:safemode_prop:s0
+persist.service. u:object_r:system_prop:s0
+persist.service.bdroid. u:object_r:bluetooth_prop:s0
+persist.security. u:object_r:system_prop:s0
+persist.vendor.overlay. u:object_r:overlay_prop:s0
+ro.boot.vendor.overlay. u:object_r:overlay_prop:s0
+ro.boottime. u:object_r:boottime_prop:s0
+ro.serialno u:object_r:serialno_prop:s0
+ro.boot.btmacaddr u:object_r:bluetooth_prop:s0
+ro.boot.serialno u:object_r:serialno_prop:s0
+ro.bt. u:object_r:bluetooth_prop:s0
+# Boolean property set by system server upon boot indicating
+# if device owner is provisioned.
+ro.device_owner u:object_r:device_logging_prop:s0
+# selinux non-persistent properties
+selinux.restorecon_recursive u:object_r:restorecon_prop:s0
+# default property context
+* u:object_r:default_prop:s0
+# data partition encryption properties
+vold. u:object_r:vold_prop:s0
+ro.crypto. u:object_r:vold_prop:s0
+# ro.build.fingerprint is either set in /system/build.prop, or is
+# set at runtime by system_server.
+ro.build.fingerprint u:object_r:fingerprint_prop:s0
+ro.persistent_properties.ready u:object_r:persistent_properties_ready_prop:s0
+# ctl properties
+ctl.bootanim u:object_r:ctl_bootanim_prop:s0
+ctl.dumpstate u:object_r:ctl_dumpstate_prop:s0
+ctl.fuse_ u:object_r:ctl_fuse_prop:s0
+ctl.mdnsd u:object_r:ctl_mdnsd_prop:s0
+ctl.ril-daemon u:object_r:ctl_rildaemon_prop:s0
+ctl.bugreport u:object_r:ctl_bugreport_prop:s0
+ctl.console u:object_r:ctl_console_prop:s0
+ctl. u:object_r:ctl_default_prop:s0
+# NFC properties
+nfc. u:object_r:nfc_prop:s0
+# These properties are not normally set by processes other than init.
+# They are only distinguished here for setting by qemu-props on the
+# emulator/goldfish.
+config. u:object_r:config_prop:s0
+ro.config. u:object_r:config_prop:s0
+dalvik. u:object_r:dalvik_prop:s0
+ro.dalvik. u:object_r:dalvik_prop:s0
+# Shared between system server and wificond
+wlan. u:object_r:wifi_prop:s0
+# hwservicemanager properties
+hwservicemanager. u:object_r:hwservicemanager_prop:s0
+# ASAN install trigger
+asan.restore_reboot u:object_r:asan_reboot_prop:s0)";
+
+static char aosp_s_property_contexts[] = R"(
+net.rmnet u:object_r:net_radio_prop:s0
+net.gprs u:object_r:net_radio_prop:s0
+net.ppp u:object_r:net_radio_prop:s0
+net.qmi u:object_r:net_radio_prop:s0
+net.lte u:object_r:net_radio_prop:s0
+net.cdma u:object_r:net_radio_prop:s0
+net.dns u:object_r:net_dns_prop:s0
+ril. u:object_r:radio_prop:s0
+ro.ril. u:object_r:radio_prop:s0
+gsm. u:object_r:radio_prop:s0
+persist.radio u:object_r:radio_prop:s0
+
+net. u:object_r:system_prop:s0
+dev. u:object_r:system_prop:s0
+ro.runtime. u:object_r:system_prop:s0
+ro.runtime.firstboot u:object_r:firstboot_prop:s0
+hw. u:object_r:system_prop:s0
+ro.hw. u:object_r:system_prop:s0
+sys. u:object_r:system_prop:s0
+sys.audio. u:object_r:audio_prop:s0
+sys.init.perf_lsm_hooks u:object_r:init_perf_lsm_hooks_prop:s0
+sys.cppreopt u:object_r:cppreopt_prop:s0
+sys.lpdumpd u:object_r:lpdumpd_prop:s0
+sys.powerctl u:object_r:powerctl_prop:s0
+service. u:object_r:system_prop:s0
+dhcp. u:object_r:dhcp_prop:s0
+dhcp.bt-pan.result u:object_r:pan_result_prop:s0
+bluetooth. u:object_r:bluetooth_prop:s0
+
+debug. u:object_r:debug_prop:s0
+debug.db. u:object_r:debuggerd_prop:s0
+dumpstate. u:object_r:dumpstate_prop:s0
+dumpstate.options u:object_r:dumpstate_options_prop:s0
+init.svc_debug_pid. u:object_r:init_svc_debug_prop:s0
+llk. u:object_r:llkd_prop:s0
+khungtask. u:object_r:llkd_prop:s0
+ro.llk. u:object_r:llkd_prop:s0
+ro.khungtask. u:object_r:llkd_prop:s0
+log. u:object_r:log_prop:s0
+log.tag u:object_r:log_tag_prop:s0
+log.tag.WifiHAL u:object_r:wifi_log_prop:s0
+security.perf_harden u:object_r:shell_prop:s0
+service.adb.root u:object_r:shell_prop:s0
+service.adb.tls.port u:object_r:adbd_prop:s0
+persist.adb.wifi. u:object_r:adbd_prop:s0
+persist.adb.tls_server.enable u:object_r:system_adbd_prop:s0
+
+persist.audio. u:object_r:audio_prop:s0
+persist.bluetooth. u:object_r:bluetooth_prop:s0
+persist.nfc_cfg. u:object_r:nfc_prop:s0
+persist.debug. u:object_r:persist_debug_prop:s0
+logd. u:object_r:logd_prop:s0
+persist.logd. u:object_r:logd_prop:s0
+ro.logd. u:object_r:logd_prop:s0
+persist.logd.security u:object_r:device_logging_prop:s0
+persist.logd.logpersistd u:object_r:logpersistd_logging_prop:s0
+logd.logpersistd u:object_r:logpersistd_logging_prop:s0
+persist.log.tag u:object_r:log_tag_prop:s0
+persist.mmc. u:object_r:mmc_prop:s0
+persist.netd.stable_secret u:object_r:netd_stable_secret_prop:s0
+persist.pm.mock-upgrade u:object_r:mock_ota_prop:s0
+persist.sys. u:object_r:system_prop:s0
+persist.sys.safemode u:object_r:safemode_prop:s0
+persist.sys.theme u:object_r:theme_prop:s0
+persist.sys.fflag.override.settings_dynamic_system u:object_r:dynamic_system_prop:s0
+ro.sys.safemode u:object_r:safemode_prop:s0
+persist.sys.audit_safemode u:object_r:safemode_prop:s0
+persist.sys.dalvik.jvmtiagent u:object_r:system_jvmti_agent_prop:s0
+persist.service. u:object_r:system_prop:s0
+persist.service.bdroid. u:object_r:bluetooth_prop:s0
+persist.security. u:object_r:system_prop:s0
+persist.traced.enable u:object_r:traced_enabled_prop:s0
+traced.lazy. u:object_r:traced_lazy_prop:s0
+persist.heapprofd.enable u:object_r:heapprofd_enabled_prop:s0
+persist.traced_perf.enable u:object_r:traced_perf_enabled_prop:s0
+persist.vendor.overlay. u:object_r:overlay_prop:s0
+ro.boot.vendor.overlay. u:object_r:overlay_prop:s0
+ro.boottime. u:object_r:boottime_prop:s0
+ro.serialno u:object_r:serialno_prop:s0
+ro.boot.btmacaddr u:object_r:bluetooth_prop:s0
+ro.boot.serialno u:object_r:serialno_prop:s0
+ro.bt. u:object_r:bluetooth_prop:s0
+ro.boot.bootreason u:object_r:bootloader_boot_reason_prop:s0
+persist.sys.boot.reason u:object_r:last_boot_reason_prop:s0
+sys.boot.reason u:object_r:system_boot_reason_prop:s0
+sys.boot.reason.last u:object_r:last_boot_reason_prop:s0
+pm. u:object_r:pm_prop:s0
+test.sys.boot.reason u:object_r:test_boot_reason_prop:s0
+test.userspace_reboot.requested u:object_r:userspace_reboot_test_prop:s0
+sys.lmk. u:object_r:system_lmk_prop:s0
+sys.trace. u:object_r:system_trace_prop:s0
+
+# Fastbootd protocol control property
+fastbootd.protocol u:object_r:fastbootd_protocol_prop:s0 exact enum usb tcp
+
+# adbd protoctl configuration property
+service.adb.tcp.port u:object_r:adbd_config_prop:s0 exact int
+
+# Boolean property set by system server upon boot indicating
+# if device is fully owned by organization instead of being
+# a personal device.
+ro.organization_owned u:object_r:device_logging_prop:s0
+
+# selinux non-persistent properties
+selinux.restorecon_recursive u:object_r:restorecon_prop:s0
+
+# default property context
+* u:object_r:default_prop:s0
+
+# data partition encryption properties
+vold. u:object_r:vold_prop:s0
+ro.crypto. u:object_r:vold_prop:s0
+
+# ro.build.fingerprint is either set in /system/build.prop, or is
+# set at runtime by system_server.
+ro.build.fingerprint u:object_r:fingerprint_prop:s0 exact string
+
+ro.persistent_properties.ready u:object_r:persistent_properties_ready_prop:s0
+
+# ctl properties
+ctl.bootanim u:object_r:ctl_bootanim_prop:s0
+ctl.dumpstate u:object_r:ctl_dumpstate_prop:s0
+ctl.fuse_ u:object_r:ctl_fuse_prop:s0
+ctl.mdnsd u:object_r:ctl_mdnsd_prop:s0
+ctl.ril-daemon u:object_r:ctl_rildaemon_prop:s0
+ctl.bugreport u:object_r:ctl_bugreport_prop:s0
+ctl.console u:object_r:ctl_console_prop:s0
+ctl. u:object_r:ctl_default_prop:s0
+
+# Don't allow uncontrolled access to all services
+ctl.sigstop_on$ u:object_r:ctl_sigstop_prop:s0
+ctl.sigstop_off$ u:object_r:ctl_sigstop_prop:s0
+ctl.start$ u:object_r:ctl_start_prop:s0
+ctl.stop$ u:object_r:ctl_stop_prop:s0
+ctl.restart$ u:object_r:ctl_restart_prop:s0
+ctl.interface_start$ u:object_r:ctl_interface_start_prop:s0
+ctl.interface_stop$ u:object_r:ctl_interface_stop_prop:s0
+ctl.interface_restart$ u:object_r:ctl_interface_restart_prop:s0
+
+ # Restrict access to starting/stopping adbd
+ctl.start$adbd u:object_r:ctl_adbd_prop:s0
+ctl.stop$adbd u:object_r:ctl_adbd_prop:s0
+ctl.restart$adbd u:object_r:ctl_adbd_prop:s0
+
+# Restrict access to starting/stopping gsid.
+ctl.start$gsid u:object_r:ctl_gsid_prop:s0
+ctl.stop$gsid u:object_r:ctl_gsid_prop:s0
+ctl.restart$gsid u:object_r:ctl_gsid_prop:s0
+
+# Restrict access to stopping apexd.
+ctl.stop$apexd u:object_r:ctl_apexd_prop:s0
+
+# Restrict access to restart dumpstate
+ctl.interface_restart$android.hardware.dumpstate u:object_r:ctl_dumpstate_prop:s0
+
+# NFC properties
+nfc. u:object_r:nfc_prop:s0
+
+# These properties are not normally set by processes other than init.
+# They are only distinguished here for setting by qemu-props on the
+# emulator/goldfish.
+config. u:object_r:config_prop:s0
+ro.config. u:object_r:config_prop:s0
+dalvik. u:object_r:dalvik_prop:s0
+ro.dalvik. u:object_r:dalvik_prop:s0
+
+# Shared between system server and wificond
+wifi. u:object_r:wifi_prop:s0
+wlan. u:object_r:wifi_prop:s0
+
+# Lowpan properties
+lowpan. u:object_r:lowpan_prop:s0
+ro.lowpan. u:object_r:lowpan_prop:s0
+
+# heapprofd properties
+heapprofd. u:object_r:heapprofd_prop:s0
+
+# hwservicemanager properties
+hwservicemanager. u:object_r:hwservicemanager_prop:s0
+
+# Common default properties for vendor, odm, vendor_dlkm, and odm_dlkm.
+init.svc.odm. u:object_r:vendor_default_prop:s0
+init.svc.vendor. u:object_r:vendor_default_prop:s0
+ro.hardware. u:object_r:vendor_default_prop:s0
+ro.odm. u:object_r:vendor_default_prop:s0
+ro.vendor. u:object_r:vendor_default_prop:s0
+ro.vendor_dlkm. u:object_r:vendor_default_prop:s0
+ro.odm_dlkm. u:object_r:vendor_default_prop:s0
+odm. u:object_r:vendor_default_prop:s0
+persist.odm. u:object_r:vendor_default_prop:s0
+persist.vendor. u:object_r:vendor_default_prop:s0
+vendor. u:object_r:vendor_default_prop:s0
+
+# Properties that relate to time / time zone detection behavior.
+persist.time. u:object_r:time_prop:s0
+
+# Properties that relate to server configurable flags
+device_config.reset_performed u:object_r:device_config_reset_performed_prop:s0
+persist.device_config.activity_manager_native_boot. u:object_r:device_config_activity_manager_native_boot_prop:s0
+persist.device_config.attempted_boot_count u:object_r:device_config_boot_count_prop:s0
+persist.device_config.input_native_boot. u:object_r:device_config_input_native_boot_prop:s0
+persist.device_config.netd_native. u:object_r:device_config_netd_native_prop:s0
+persist.device_config.runtime_native. u:object_r:device_config_runtime_native_prop:s0
+persist.device_config.runtime_native_boot. u:object_r:device_config_runtime_native_boot_prop:s0
+persist.device_config.media_native. u:object_r:device_config_media_native_prop:s0
+persist.device_config.storage_native_boot. u:object_r:device_config_storage_native_boot_prop:s0
+persist.device_config.window_manager_native_boot. u:object_r:device_config_window_manager_native_boot_prop:s0
+persist.device_config.configuration. u:object_r:device_config_configuration_prop:s0
+
+# Properties that relate to legacy server configurable flags
+persist.device_config.global_settings.sys_traced u:object_r:device_config_sys_traced_prop:s0
+
+apexd. u:object_r:apexd_prop:s0
+persist.apexd. u:object_r:apexd_prop:s0
+
+bpf.progs_loaded u:object_r:bpf_progs_loaded_prop:s0
+
+gsid. u:object_r:gsid_prop:s0
+ro.gsid. u:object_r:gsid_prop:s0
+
+# Property for disabling NNAPI vendor extensions on product image (used on GSI /product image,
+# which can't use NNAPI vendor extensions).
+ro.nnapi.extensions.deny_on_product u:object_r:nnapi_ext_deny_product_prop:s0
+
+# Property that is set once ueventd finishes cold boot.
+ro.cold_boot_done u:object_r:cold_boot_done_prop:s0
+
+# Charger properties
+ro.charger. u:object_r:charger_prop:s0
+sys.boot_from_charger_mode u:object_r:charger_status_prop:s0 exact int
+ro.enable_boot_charger_mode u:object_r:charger_config_prop:s0 exact bool
+
+# Virtual A/B properties
+ro.virtual_ab.enabled u:object_r:virtual_ab_prop:s0
+ro.virtual_ab.retrofit u:object_r:virtual_ab_prop:s0
+
+ro.product.ab_ota_partitions u:object_r:ota_prop:s0 exact string
+# Property to set/clear the warm reset flag after an OTA update.
+ota.warm_reset u:object_r:ota_prop:s0
+
+# Module properties
+com.android.sdkext. u:object_r:module_sdkextensions_prop:s0
+persist.com.android.sdkext. u:object_r:module_sdkextensions_prop:s0
+
+# Userspace reboot properties
+sys.userspace_reboot.log. u:object_r:userspace_reboot_log_prop:s0
+persist.sys.userspace_reboot.log. u:object_r:userspace_reboot_log_prop:s0
+
+# Integer property which is used in libgui to configure the number of frames
+# tracked by buffer queue's frame event timing history. The property is set
+# by devices with video decoding pipelines long enough to overflow the default
+# history size.
+ro.lib_gui.frame_event_history_size u:object_r:bq_config_prop:s0
+
+af.fast_track_multiplier u:object_r:audio_config_prop:s0 exact int
+ro.af.client_heap_size_kbyte u:object_r:audio_config_prop:s0 exact int
+
+audio.camerasound.force u:object_r:audio_config_prop:s0 exact bool
+audio.deep_buffer.media u:object_r:audio_config_prop:s0 exact bool
+audio.offload.video u:object_r:audio_config_prop:s0 exact bool
+audio.offload.min.duration.secs u:object_r:audio_config_prop:s0 exact int
+
+ro.audio.ignore_effects u:object_r:audio_config_prop:s0 exact bool
+ro.audio.monitorRotation u:object_r:audio_config_prop:s0 exact bool
+
+persist.config.calibration_fac u:object_r:camera_calibration_prop:s0 exact string
+
+config.disable_cameraservice u:object_r:camera_config_prop:s0 exact bool
+
+camera.disable_zsl_mode u:object_r:camera_config_prop:s0 exact bool
+camera.fifo.disable u:object_r:camera_config_prop:s0 exact bool
+ro.camera.notify_nfc u:object_r:camera_config_prop:s0 exact bool
+ro.camera.enableLazyHal u:object_r:camera_config_prop:s0 exact bool
+
+# Should always_debuggable be bool? It's checked against the string "1".
+dalvik.vm.always_debuggable u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.appimageformat u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.backgroundgctype u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.boot-dex2oat-cpu-set u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.boot-dex2oat-threads u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.boot-image u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.checkjni u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.dex2oat-Xms u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.dex2oat-Xmx u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.dex2oat-cpu-set u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.dex2oat-filter u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.dex2oat-flags u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.dex2oat-max-image-block-size u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.dex2oat-minidebuginfo u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.dex2oat-resolve-startup-strings u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.dex2oat-threads u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.dex2oat-updatable-bcp-packages-file u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.dex2oat-very-large u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.dex2oat-swap u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.dex2oat64.enabled u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.dexopt.secondary u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.execution-mode u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.extra-opts u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.foreground-heap-growth-multiplier u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.gctype u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.heapgrowthlimit u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.heapmaxfree u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.heapminfree u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.heapsize u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.heapstartsize u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.heaptargetutilization u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.hot-startup-method-samples u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.image-dex2oat-Xms u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.image-dex2oat-Xmx u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.image-dex2oat-cpu-set u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.image-dex2oat-filter u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.image-dex2oat-flags u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.image-dex2oat-threads u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.isa.arm.features u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.arm.variant u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.arm64.features u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.arm64.variant u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.mips.features u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.mips.variant u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.mips64.features u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.mips64.variant u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.unknown.features u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.unknown.variant u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.x86.features u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.x86.variant u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.x86_64.features u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.x86_64.variant u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.jitinitialsize u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.jitmaxsize u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.jitprithreadweight u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.jitthreshold u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.jittransitionweight u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.jniopts u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.lockprof.threshold u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.method-trace u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.method-trace-file u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.method-trace-file-siz u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.method-trace-stream u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.profilesystemserver u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.profilebootclasspath u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.restore-dex2oat-cpu-set u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.restore-dex2oat-threads u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.usejit u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.usejitprofiles u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.zygote.max-boot-retry u:object_r:dalvik_config_prop:s0 exact int
+ro.zygote u:object_r:dalvik_config_prop:s0 exact string
+
+persist.sys.dalvik.vm.lib.2 u:object_r:dalvik_runtime_prop:s0 exact string
+
+keyguard.no_require_sim u:object_r:keyguard_config_prop:s0 exact bool
+
+media.recorder.show_manufacturer_and_model u:object_r:media_config_prop:s0 exact bool
+media.stagefright.cache-params u:object_r:media_config_prop:s0 exact string
+media.stagefright.thumbnail.prefer_hw_codecs u:object_r:media_config_prop:s0 exact bool
+persist.sys.media.avsync u:object_r:media_config_prop:s0 exact bool
+
+persist.bluetooth.a2dp_offload.cap u:object_r:bluetooth_a2dp_offload_prop:s0 exact string
+persist.bluetooth.a2dp_offload.disabled u:object_r:bluetooth_a2dp_offload_prop:s0 exact bool
+persist.bluetooth.bluetooth_audio_hal.disabled u:object_r:bluetooth_audio_hal_prop:s0 exact bool
+persist.bluetooth.btsnoopenable u:object_r:exported_bluetooth_prop:s0 exact bool
+
+persist.radio.multisim.config u:object_r:radio_control_prop:s0 exact string
+
+persist.sys.hdmi.keep_awake u:object_r:hdmi_config_prop:s0 exact bool
+ro.hdmi.cec_device_types u:object_r:hdmi_config_prop:s0 exact string
+ro.hdmi.device_type u:object_r:hdmi_config_prop:s0 exact string
+ro.hdmi.wake_on_hotplug u:object_r:hdmi_config_prop:s0 exact bool
+ro.hdmi.cec.source.send_standby_on_sleep u:object_r:hdmi_config_prop:s0 exact enum to_tv broadcast none
+
+pm.dexopt.ab-ota u:object_r:exported_pm_prop:s0 exact string
+pm.dexopt.bg-dexopt u:object_r:exported_pm_prop:s0 exact string
+pm.dexopt.boot u:object_r:exported_pm_prop:s0 exact string
+pm.dexopt.disable_bg_dexopt u:object_r:exported_pm_prop:s0 exact bool
+pm.dexopt.downgrade_after_inactive_days u:object_r:exported_pm_prop:s0 exact int
+pm.dexopt.first-boot u:object_r:exported_pm_prop:s0 exact string
+pm.dexopt.inactive u:object_r:exported_pm_prop:s0 exact string
+pm.dexopt.install u:object_r:exported_pm_prop:s0 exact string
+pm.dexopt.shared u:object_r:exported_pm_prop:s0 exact string
+
+ro.apk_verity.mode u:object_r:apk_verity_prop:s0 exact int
+
+ro.bluetooth.a2dp_offload.supported u:object_r:bluetooth_a2dp_offload_prop:s0 exact bool
+
+ro.boot.vendor.overlay.theme u:object_r:exported_overlay_prop:s0 exact string
+
+ro.bt.bdaddr_path u:object_r:exported_bluetooth_prop:s0 exact string
+
+ro.config.alarm_alert u:object_r:systemsound_config_prop:s0 exact string
+ro.config.alarm_vol_default u:object_r:systemsound_config_prop:s0 exact int
+ro.config.alarm_vol_steps u:object_r:systemsound_config_prop:s0 exact int
+ro.config.media_vol_default u:object_r:systemsound_config_prop:s0 exact int
+ro.config.media_vol_steps u:object_r:systemsound_config_prop:s0 exact int
+ro.config.notification_sound u:object_r:systemsound_config_prop:s0 exact string
+ro.config.ringtone u:object_r:systemsound_config_prop:s0 exact string
+ro.config.system_vol_default u:object_r:systemsound_config_prop:s0 exact int
+ro.config.system_vol_steps u:object_r:systemsound_config_prop:s0 exact int
+ro.config.vc_call_vol_default u:object_r:systemsound_config_prop:s0 exact int
+
+ro.control_privapp_permissions u:object_r:packagemanager_config_prop:s0 exact enum disable enforce log
+ro.cp_system_other_odex u:object_r:packagemanager_config_prop:s0 exact bool
+
+ro.crypto.allow_encrypt_override u:object_r:vold_config_prop:s0 exact bool
+ro.crypto.dm_default_key.options_format.version u:object_r:vold_config_prop:s0 exact int
+ro.crypto.fde_algorithm u:object_r:vold_config_prop:s0 exact string
+ro.crypto.fde_sector_size u:object_r:vold_config_prop:s0 exact int
+ro.crypto.scrypt_params u:object_r:vold_config_prop:s0 exact string
+ro.crypto.set_dun u:object_r:vold_config_prop:s0 exact bool
+ro.crypto.volume.contents_mode u:object_r:vold_config_prop:s0 exact string
+ro.crypto.volume.filenames_mode u:object_r:vold_config_prop:s0 exact string
+ro.crypto.volume.metadata.encryption u:object_r:vold_config_prop:s0 exact string
+ro.crypto.volume.metadata.method u:object_r:vold_config_prop:s0 exact string
+ro.crypto.volume.options u:object_r:vold_config_prop:s0 exact string
+
+ro.dalvik.vm.native.bridge u:object_r:dalvik_config_prop:s0 exact string
+
+external_storage.projid.enabled u:object_r:storage_config_prop:s0 exact bool
+external_storage.casefold.enabled u:object_r:storage_config_prop:s0 exact bool
+external_storage.sdcardfs.enabled u:object_r:storage_config_prop:s0 exact bool
+
+ro.config.per_app_memcg u:object_r:lmkd_config_prop:s0 exact bool
+ro.lmk.critical u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.critical_upgrade u:object_r:lmkd_config_prop:s0 exact bool
+ro.lmk.debug u:object_r:lmkd_config_prop:s0 exact bool
+ro.lmk.downgrade_pressure u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.kill_heaviest_task u:object_r:lmkd_config_prop:s0 exact bool
+ro.lmk.kill_timeout_ms u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.low u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.medium u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.psi_partial_stall_ms u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.psi_complete_stall_ms u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.swap_free_low_percentage u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.swap_util_max u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.thrashing_limit u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.thrashing_limit_decay u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.use_minfree_levels u:object_r:lmkd_config_prop:s0 exact bool
+ro.lmk.upgrade_pressure u:object_r:lmkd_config_prop:s0 exact int
+lmkd.reinit u:object_r:lmkd_prop:s0 exact int
+
+ro.media.xml_variant.codecs u:object_r:media_variant_prop:s0 exact string
+ro.media.xml_variant.codecs_performance u:object_r:media_variant_prop:s0 exact string
+ro.media.xml_variant.profiles u:object_r:media_variant_prop:s0 exact string
+
+ro.minui.default_rotation u:object_r:recovery_config_prop:s0 exact string
+ro.minui.overscan_percent u:object_r:recovery_config_prop:s0 exact int
+ro.minui.pixel_format u:object_r:recovery_config_prop:s0 exact string
+
+ro.oem_unlock_supported u:object_r:oem_unlock_prop:s0 exact int
+
+ro.rebootescrow.device u:object_r:rebootescrow_hal_prop:s0 exact string
+
+ro.storage_manager.enabled u:object_r:storagemanager_config_prop:s0 exact bool
+
+ro.vehicle.hal u:object_r:vehicle_hal_prop:s0 exact string
+
+ro.vendor.build.security_patch u:object_r:vendor_security_patch_level_prop:s0 exact string
+
+ro.zram.mark_idle_delay_mins u:object_r:zram_config_prop:s0 exact int
+ro.zram.first_wb_delay_mins u:object_r:zram_config_prop:s0 exact int
+ro.zram.periodic_wb_delay_hours u:object_r:zram_config_prop:s0 exact int
+zram.force_writeback u:object_r:zram_config_prop:s0 exact bool
+persist.sys.zram_enabled u:object_r:zram_control_prop:s0 exact bool
+
+sendbug.preferred.domain u:object_r:sendbug_config_prop:s0 exact string
+
+persist.sys.usb.usbradio.config u:object_r:usb_control_prop:s0 exact string
+
+sys.usb.config u:object_r:usb_control_prop:s0 exact string
+sys.usb.configfs u:object_r:usb_control_prop:s0 exact int
+sys.usb.controller u:object_r:usb_control_prop:s0 exact string
+sys.usb.state u:object_r:usb_control_prop:s0 exact string
+
+sys.usb.mtp.device_type u:object_r:usb_config_prop:s0 exact int
+
+sys.usb.config. u:object_r:usb_prop:s0
+
+sys.usb.ffs.aio_compat u:object_r:ffs_config_prop:s0 exact bool
+sys.usb.ffs.max_read u:object_r:ffs_config_prop:s0 exact int
+sys.usb.ffs.max_write u:object_r:ffs_config_prop:s0 exact int
+
+sys.usb.ffs.ready u:object_r:ffs_control_prop:s0 exact bool
+sys.usb.ffs.mtp.ready u:object_r:ffs_control_prop:s0 exact bool
+
+tombstoned.max_tombstone_count u:object_r:tombstone_config_prop:s0 exact int
+
+vold.post_fs_data_done u:object_r:vold_config_prop:s0 exact int
+
+apexd.status u:object_r:apexd_prop:s0 exact enum starting activated ready
+
+dev.bootcomplete u:object_r:boot_status_prop:s0 exact bool
+sys.boot_completed u:object_r:boot_status_prop:s0 exact bool
+
+persist.sys.device_provisioned u:object_r:provisioned_prop:s0 exact string
+
+persist.sys.theme u:object_r:theme_prop:s0 exact string
+
+sys.retaildemo.enabled u:object_r:retaildemo_prop:s0 exact int
+
+sys.user.0.ce_available u:object_r:exported3_system_prop:s0 exact bool
+
+aac_drc_boost u:object_r:aac_drc_prop:s0 exact int
+aac_drc_cut u:object_r:aac_drc_prop:s0 exact int
+aac_drc_enc_target_level u:object_r:aac_drc_prop:s0 exact int
+aac_drc_heavy u:object_r:aac_drc_prop:s0 exact int
+aac_drc_reference_level u:object_r:aac_drc_prop:s0 exact int
+ro.aac_drc_effect_type u:object_r:aac_drc_prop:s0 exact int
+
+build.version.extensions. u:object_r:module_sdkextensions_prop:s0 prefix int
+
+drm.64bit.enabled u:object_r:mediadrm_config_prop:s0 exact bool
+media.mediadrmservice.enable u:object_r:mediadrm_config_prop:s0 exact bool
+
+drm.service.enabled u:object_r:drm_service_config_prop:s0 exact bool
+
+dumpstate.dry_run u:object_r:exported_dumpstate_prop:s0 exact bool
+dumpstate.unroot u:object_r:exported_dumpstate_prop:s0 exact bool
+persist.dumpstate.verbose_logging.enabled u:object_r:hal_dumpstate_config_prop:s0 exact bool
+
+hal.instrumentation.enable u:object_r:hal_instrumentation_prop:s0 exact bool
+
+# default contexts only accessible by coredomain
+init.svc. u:object_r:init_service_status_private_prop:s0 prefix string
+
+# vendor-init-readable init service props
+init.svc.bugreport u:object_r:init_service_status_prop:s0 exact string
+init.svc.bugreportd u:object_r:init_service_status_prop:s0 exact string
+init.svc.console u:object_r:init_service_status_prop:s0 exact string
+init.svc.dumpstatez u:object_r:init_service_status_prop:s0 exact string
+init.svc.mediadrm u:object_r:init_service_status_prop:s0 exact string
+init.svc.statsd u:object_r:init_service_status_prop:s0 exact string
+init.svc.surfaceflinger u:object_r:init_service_status_prop:s0 exact string
+init.svc.tombstoned u:object_r:init_service_status_prop:s0 exact string
+init.svc.zygote u:object_r:init_service_status_prop:s0 exact string
+
+libc.debug.malloc.options u:object_r:libc_debug_prop:s0 exact string
+libc.debug.malloc.program u:object_r:libc_debug_prop:s0 exact string
+libc.debug.hooks.enable u:object_r:libc_debug_prop:s0 exact string
+
+net.redirect_socket_calls.hooked u:object_r:socket_hook_prop:s0 exact bool
+
+persist.sys.locale u:object_r:exported_system_prop:s0 exact string
+persist.sys.timezone u:object_r:exported_system_prop:s0 exact string
+persist.sys.test_harness u:object_r:test_harness_prop:s0 exact bool
+
+ro.arch u:object_r:build_prop:s0 exact string
+
+# ro.boot. properties are set based on kernel commandline arguments, which are vendor owned.
+ro.boot. u:object_r:bootloader_prop:s0
+ro.boot.avb_version u:object_r:bootloader_prop:s0 exact string
+ro.boot.baseband u:object_r:bootloader_prop:s0 exact string
+ro.boot.bootdevice u:object_r:bootloader_prop:s0 exact string
+ro.boot.bootloader u:object_r:bootloader_prop:s0 exact string
+ro.boot.boottime u:object_r:bootloader_prop:s0 exact string
+ro.boot.console u:object_r:bootloader_prop:s0 exact string
+ro.boot.hardware u:object_r:bootloader_prop:s0 exact string
+ro.boot.hardware.color u:object_r:bootloader_prop:s0 exact string
+ro.boot.hardware.sku u:object_r:bootloader_prop:s0 exact string
+ro.boot.keymaster u:object_r:bootloader_prop:s0 exact string
+ro.boot.mode u:object_r:bootloader_prop:s0 exact string
+ro.boot.revision u:object_r:bootloader_prop:s0 exact string
+ro.boot.vbmeta.avb_version u:object_r:bootloader_prop:s0 exact string
+ro.boot.verifiedbootstate u:object_r:bootloader_prop:s0 exact string
+ro.boot.veritymode u:object_r:bootloader_prop:s0 exact string
+
+# These ro.X properties are set to values of ro.boot.X by property_service.
+ro.baseband u:object_r:bootloader_prop:s0 exact string
+ro.bootloader u:object_r:bootloader_prop:s0 exact string
+ro.bootmode u:object_r:bootloader_prop:s0 exact string
+ro.hardware u:object_r:bootloader_prop:s0 exact string
+ro.revision u:object_r:bootloader_prop:s0 exact string
+
+ro.boot.dynamic_partitions u:object_r:exported_default_prop:s0 exact string
+ro.boot.dynamic_partitions_retrofit u:object_r:exported_default_prop:s0 exact string
+
+ro.build.date u:object_r:build_prop:s0 exact string
+ro.build.date.utc u:object_r:build_prop:s0 exact int
+ro.build.description u:object_r:build_prop:s0 exact string
+ro.build.display.id u:object_r:build_prop:s0 exact string
+ro.build.host u:object_r:build_prop:s0 exact string
+ro.build.id u:object_r:build_prop:s0 exact string
+ro.build.product u:object_r:build_prop:s0 exact string
+ro.build.system_root_image u:object_r:build_prop:s0 exact bool
+ro.build.tags u:object_r:build_prop:s0 exact string
+ro.build.type u:object_r:build_prop:s0 exact string
+ro.build.user u:object_r:build_prop:s0 exact string
+ro.build.version.base_os u:object_r:build_prop:s0 exact string
+ro.build.version.codename u:object_r:build_prop:s0 exact string
+ro.build.version.incremental u:object_r:build_prop:s0 exact string
+ro.build.version.preview_sdk u:object_r:build_prop:s0 exact int
+ro.build.version.release u:object_r:build_prop:s0 exact string
+ro.build.version.release_or_codename u:object_r:build_prop:s0 exact string
+ro.build.version.sdk u:object_r:build_prop:s0 exact int
+ro.build.version.security_patch u:object_r:build_prop:s0 exact string
+
+ro.debuggable u:object_r:build_prop:s0 exact bool
+
+ro.product.cpu.abi u:object_r:build_prop:s0 exact string
+ro.product.cpu.abilist u:object_r:build_prop:s0 exact string
+ro.product.cpu.abilist32 u:object_r:build_prop:s0 exact string
+ro.product.cpu.abilist64 u:object_r:build_prop:s0 exact string
+
+ro.adb.secure u:object_r:build_prop:s0 exact bool
+ro.secure u:object_r:build_prop:s0 exact int
+
+# These 5 properties are set by property_service
+ro.product.brand u:object_r:build_prop:s0 exact string
+ro.product.device u:object_r:build_prop:s0 exact string
+ro.product.manufacturer u:object_r:build_prop:s0 exact string
+ro.product.model u:object_r:build_prop:s0 exact string
+ro.product.name u:object_r:build_prop:s0 exact string
+
+# Sanitizer properties
+ro.sanitize.address u:object_r:build_prop:s0 exact bool
+ro.sanitize.cfi u:object_r:build_prop:s0 exact bool
+ro.sanitize.default-ub u:object_r:build_prop:s0 exact bool
+ro.sanitize.fuzzer u:object_r:build_prop:s0 exact bool
+ro.sanitize.hwaddress u:object_r:build_prop:s0 exact bool
+ro.sanitize.integer_overflow u:object_r:build_prop:s0 exact bool
+ro.sanitize.safe-stack u:object_r:build_prop:s0 exact bool
+ro.sanitize.scudo u:object_r:build_prop:s0 exact bool
+ro.sanitize.thread u:object_r:build_prop:s0 exact bool
+ro.sanitize.undefined u:object_r:build_prop:s0 exact bool
+
+# All odm build props are set by /odm/build.prop
+ro.odm.build.date u:object_r:build_odm_prop:s0 exact string
+ro.odm.build.date.utc u:object_r:build_odm_prop:s0 exact int
+ro.odm.build.fingerprint u:object_r:build_odm_prop:s0 exact string
+ro.odm.build.version.incremental u:object_r:build_odm_prop:s0 exact string
+
+ro.product.odm.brand u:object_r:build_odm_prop:s0 exact string
+ro.product.odm.device u:object_r:build_odm_prop:s0 exact string
+ro.product.odm.manufacturer u:object_r:build_odm_prop:s0 exact string
+ro.product.odm.model u:object_r:build_odm_prop:s0 exact string
+ro.product.odm.name u:object_r:build_odm_prop:s0 exact string
+
+# All vendor_dlkm build props are set by /vendor_dlkm/etc/build.prop
+ro.vendor_dlkm.build.date u:object_r:build_vendor_prop:s0 exact string
+ro.vendor_dlkm.build.date.utc u:object_r:build_vendor_prop:s0 exact int
+ro.vendor_dlkm.build.fingerprint u:object_r:build_vendor_prop:s0 exact string
+ro.vendor_dlkm.build.version.incremental u:object_r:build_vendor_prop:s0 exact string
+
+# All odm_dlkm build props are set by /odm_dlkm/etc/build.prop
+ro.odm_dlkm.build.date u:object_r:build_vendor_prop:s0 exact string
+ro.odm_dlkm.build.date.utc u:object_r:build_vendor_prop:s0 exact int
+ro.odm_dlkm.build.fingerprint u:object_r:build_vendor_prop:s0 exact string
+ro.odm_dlkm.build.version.incremental u:object_r:build_vendor_prop:s0 exact string
+
+# All vendor build props are set by /vendor/build.prop
+ro.vendor.build.date u:object_r:build_vendor_prop:s0 exact string
+ro.vendor.build.date.utc u:object_r:build_vendor_prop:s0 exact int
+ro.vendor.build.fingerprint u:object_r:build_vendor_prop:s0 exact string
+ro.vendor.build.version.incremental u:object_r:build_vendor_prop:s0 exact string
+ro.vendor.build.version.sdk u:object_r:build_vendor_prop:s0 exact int
+
+ro.product.board u:object_r:build_vendor_prop:s0 exact string
+ro.product.first_api_level u:object_r:build_vendor_prop:s0 exact int
+ro.product.vendor.brand u:object_r:build_vendor_prop:s0 exact string
+ro.product.vendor.device u:object_r:build_vendor_prop:s0 exact string
+ro.product.vendor.manufacturer u:object_r:build_vendor_prop:s0 exact string
+ro.product.vendor.model u:object_r:build_vendor_prop:s0 exact string
+ro.product.vendor.name u:object_r:build_vendor_prop:s0 exact string
+
+ro.crypto.state u:object_r:vold_status_prop:s0 exact enum encrypted unencrypted unsupported
+ro.crypto.type u:object_r:vold_status_prop:s0 exact enum block file none
+
+ro.property_service.version u:object_r:property_service_version_prop:s0 exact int
+
+ro.vendor.redirect_socket_calls u:object_r:vendor_socket_hook_prop:s0 exact bool
+
+service.bootanim.exit u:object_r:exported_system_prop:s0 exact int
+
+sys.init.userspace_reboot.in_progress u:object_r:userspace_reboot_exported_prop:s0 exact bool
+sys.use_memfd u:object_r:use_memfd_prop:s0 exact bool
+
+vold.decrypt u:object_r:vold_status_prop:s0 exact string
+
+aaudio.hw_burst_min_usec u:object_r:aaudio_config_prop:s0 exact int
+aaudio.minimum_sleep_usec u:object_r:aaudio_config_prop:s0 exact int
+aaudio.mixer_bursts u:object_r:aaudio_config_prop:s0 exact int
+aaudio.mmap_exclusive_policy u:object_r:aaudio_config_prop:s0 exact int
+aaudio.mmap_policy u:object_r:aaudio_config_prop:s0 exact int
+aaudio.wakeup_delay_usec u:object_r:aaudio_config_prop:s0 exact int
+
+persist.rcs.supported u:object_r:exported_default_prop:s0 exact int
+
+ro.bionic.2nd_arch u:object_r:cpu_variant_prop:s0 exact string
+ro.bionic.2nd_cpu_variant u:object_r:cpu_variant_prop:s0 exact string
+ro.bionic.arch u:object_r:cpu_variant_prop:s0 exact string
+ro.bionic.cpu_variant u:object_r:cpu_variant_prop:s0 exact string
+
+ro.board.platform u:object_r:exported_default_prop:s0 exact string
+
+ro.boot.fake_battery u:object_r:exported_default_prop:s0 exact int
+ro.boot.fstab_suffix u:object_r:exported_default_prop:s0 exact string
+ro.boot.hardware.revision u:object_r:exported_default_prop:s0 exact string
+ro.boot.product.hardware.sku u:object_r:exported_default_prop:s0 exact string
+ro.boot.product.vendor.sku u:object_r:exported_default_prop:s0 exact string
+ro.boot.slot_suffix u:object_r:exported_default_prop:s0 exact string
+
+ro.boringcrypto.hwrand u:object_r:exported_default_prop:s0 exact bool
+
+ro.build.ab_update u:object_r:exported_default_prop:s0 exact string
+ro.build.expect.baseband u:object_r:exported_default_prop:s0 exact string
+ro.build.expect.bootloader u:object_r:exported_default_prop:s0 exact string
+
+ro.carrier u:object_r:exported_default_prop:s0 exact string
+
+ro.config.low_ram u:object_r:exported_config_prop:s0 exact bool
+ro.config.vc_call_vol_steps u:object_r:exported_config_prop:s0 exact int
+
+ro.frp.pst u:object_r:exported_default_prop:s0 exact string
+
+ro.hardware.activity_recognition u:object_r:exported_default_prop:s0 exact string
+ro.hardware.audio u:object_r:exported_default_prop:s0 exact string
+ro.hardware.audio.a2dp u:object_r:exported_default_prop:s0 exact string
+ro.hardware.audio.hearing_aid u:object_r:exported_default_prop:s0 exact string
+ro.hardware.audio.primary u:object_r:exported_default_prop:s0 exact string
+ro.hardware.audio.usb u:object_r:exported_default_prop:s0 exact string
+ro.hardware.audio_policy u:object_r:exported_default_prop:s0 exact string
+ro.hardware.bootctrl u:object_r:exported_default_prop:s0 exact string
+ro.hardware.camera u:object_r:exported_default_prop:s0 exact string
+ro.hardware.consumerir u:object_r:exported_default_prop:s0 exact string
+ro.hardware.context_hub u:object_r:exported_default_prop:s0 exact string
+ro.hardware.egl u:object_r:exported_default_prop:s0 exact string
+ro.hardware.fingerprint u:object_r:exported_default_prop:s0 exact string
+ro.hardware.flp u:object_r:exported_default_prop:s0 exact string
+ro.hardware.gatekeeper u:object_r:exported_default_prop:s0 exact string
+ro.hardware.gps u:object_r:exported_default_prop:s0 exact string
+ro.hardware.gralloc u:object_r:exported_default_prop:s0 exact string
+ro.hardware.hdmi_cec u:object_r:exported_default_prop:s0 exact string
+ro.hardware.hwcomposer u:object_r:exported_default_prop:s0 exact string
+ro.hardware.input u:object_r:exported_default_prop:s0 exact string
+ro.hardware.keystore u:object_r:exported_default_prop:s0 exact string
+ro.hardware.keystore_desede u:object_r:exported_default_prop:s0 exact string
+ro.hardware.lights u:object_r:exported_default_prop:s0 exact string
+ro.hardware.local_time u:object_r:exported_default_prop:s0 exact string
+ro.hardware.memtrack u:object_r:exported_default_prop:s0 exact string
+ro.hardware.nfc u:object_r:exported_default_prop:s0 exact string
+ro.hardware.nfc_nci u:object_r:exported_default_prop:s0 exact string
+ro.hardware.nfc_tag u:object_r:exported_default_prop:s0 exact string
+ro.hardware.nvram u:object_r:exported_default_prop:s0 exact string
+ro.hardware.power u:object_r:exported_default_prop:s0 exact string
+ro.hardware.radio u:object_r:exported_default_prop:s0 exact string
+ro.hardware.sensors u:object_r:exported_default_prop:s0 exact string
+ro.hardware.sound_trigger u:object_r:exported_default_prop:s0 exact string
+ro.hardware.thermal u:object_r:exported_default_prop:s0 exact string
+ro.hardware.tv_input u:object_r:exported_default_prop:s0 exact string
+ro.hardware.type u:object_r:exported_default_prop:s0 exact string
+ro.hardware.vehicle u:object_r:exported_default_prop:s0 exact string
+ro.hardware.vibrator u:object_r:exported_default_prop:s0 exact string
+ro.hardware.virtual_device u:object_r:exported_default_prop:s0 exact string
+ro.hardware.vulkan u:object_r:exported_default_prop:s0 exact string
+
+ro.hwui.use_vulkan u:object_r:exported_default_prop:s0 exact bool
+
+ro.kernel.qemu u:object_r:exported_default_prop:s0 exact bool
+ro.kernel.qemu. u:object_r:exported_default_prop:s0
+ro.kernel.android.bootanim u:object_r:exported_default_prop:s0 exact int
+ro.kernel.ebpf.supported u:object_r:exported_default_prop:s0 exact bool
+
+ro.oem.key1 u:object_r:exported_default_prop:s0 exact string
+
+ro.product.vndk.version u:object_r:vndk_prop:s0 exact string
+
+ro.vndk.lite u:object_r:vndk_prop:s0 exact bool
+ro.vndk.version u:object_r:vndk_prop:s0 exact string
+
+ro.vts.coverage u:object_r:vts_config_prop:s0 exact int
+
+vts.native_server.on u:object_r:vts_status_prop:s0 exact bool
+
+wifi.active.interface u:object_r:wifi_hal_prop:s0 exact string
+wifi.aware.interface u:object_r:wifi_hal_prop:s0 exact string
+wifi.concurrent.interface u:object_r:wifi_hal_prop:s0 exact string
+wifi.direct.interface u:object_r:wifi_hal_prop:s0 exact string
+wifi.interface u:object_r:wifi_hal_prop:s0 exact string
+wlan.driver.status u:object_r:wifi_hal_prop:s0 exact enum ok unloaded
+
+ro.boot.wificountrycode u:object_r:wifi_config_prop:s0 exact string
+
+ro.apex.updatable u:object_r:exported_default_prop:s0 exact bool
+
+# Property to enable incremental feature
+ro.incremental.enable u:object_r:incremental_prop:s0
+
+# Properties to configure userspace reboot.
+init.userspace_reboot.is_supported u:object_r:userspace_reboot_config_prop:s0 exact bool
+init.userspace_reboot.sigkill.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
+init.userspace_reboot.sigterm.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
+init.userspace_reboot.started.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
+init.userspace_reboot.userdata_remount.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
+init.userspace_reboot.watchdog.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
+
+sys.shutdown.requested u:object_r:exported_system_prop:s0 exact string
+
+# surfaceflinger properties
+ro.surface_flinger.default_composition_dataspace u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.default_composition_pixel_format u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.force_hwc_copy_for_virtual_displays u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.has_HDR_display u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.has_wide_color_display u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.max_frame_buffer_acquired_buffers u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.max_graphics_height u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.max_graphics_width u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.max_virtual_display_dimension u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.primary_display_orientation u:object_r:surfaceflinger_prop:s0 exact enum ORIENTATION_0 ORIENTATION_180 ORIENTATION_270 ORIENTATION_90
+ro.surface_flinger.present_time_offset_from_vsync_ns u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.running_without_sync_framework u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.start_graphics_allocator_service u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.use_color_management u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.use_context_priority u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.use_vr_flinger u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.vsync_event_phase_offset_ns u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.vsync_sf_event_phase_offset_ns u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.wcg_composition_dataspace u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.wcg_composition_pixel_format u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.display_primary_red u:object_r:surfaceflinger_prop:s0 exact string
+ro.surface_flinger.display_primary_green u:object_r:surfaceflinger_prop:s0 exact string
+ro.surface_flinger.display_primary_blue u:object_r:surfaceflinger_prop:s0 exact string
+ro.surface_flinger.display_primary_white u:object_r:surfaceflinger_prop:s0 exact string
+ro.surface_flinger.protected_contents u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.set_idle_timer_ms u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.set_touch_timer_ms u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.set_display_power_timer_ms u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.support_kernel_idle_timer u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.use_smart_90_for_video u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.use_content_detection_for_refresh_rate u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.color_space_agnostic_dataspace u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.refresh_rate_switching u:object_r:surfaceflinger_prop:s0 exact bool
+
+ro.sf.disable_triple_buffer u:object_r:surfaceflinger_prop:s0 exact bool
+ro.sf.lcd_density u:object_r:surfaceflinger_prop:s0 exact int
+
+persist.sys.sf.color_mode u:object_r:surfaceflinger_color_prop:s0 exact int
+persist.sys.sf.color_saturation u:object_r:surfaceflinger_color_prop:s0 exact string
+persist.sys.sf.native_mode u:object_r:surfaceflinger_color_prop:s0 exact int
+
+# Binder cache properties. These are world-readable
+cache_key.app_inactive u:object_r:binder_cache_system_server_prop:s0
+cache_key.is_compat_change_enabled u:object_r:binder_cache_system_server_prop:s0
+cache_key.get_packages_for_uid u:object_r:binder_cache_system_server_prop:s0
+cache_key.has_system_feature u:object_r:binder_cache_system_server_prop:s0
+cache_key.is_interactive u:object_r:binder_cache_system_server_prop:s0
+cache_key.is_power_save_mode u:object_r:binder_cache_system_server_prop:s0
+cache_key.is_user_unlocked u:object_r:binder_cache_system_server_prop:s0
+cache_key.volume_list u:object_r:binder_cache_system_server_prop:s0
+cache_key.display_info u:object_r:binder_cache_system_server_prop:s0
+cache_key.location_enabled u:object_r:binder_cache_system_server_prop:s0
+cache_key.package_info u:object_r:binder_cache_system_server_prop:s0
+
+cache_key.bluetooth. u:object_r:binder_cache_bluetooth_server_prop:s0 prefix string
+cache_key.system_server. u:object_r:binder_cache_system_server_prop:s0 prefix string
+cache_key.telephony. u:object_r:binder_cache_telephony_server_prop:s0 prefix string
+
+gsm.sim.operator.numeric u:object_r:telephony_status_prop:s0 exact string
+persist.radio.airplane_mode_on u:object_r:telephony_status_prop:s0 exact bool
+
+ro.com.android.dataroaming u:object_r:telephony_config_prop:s0 exact bool
+ro.com.android.prov_mobiledata u:object_r:telephony_config_prop:s0 exact bool
+ro.radio.noril u:object_r:telephony_config_prop:s0 exact string
+ro.telephony.call_ring.multiple u:object_r:telephony_config_prop:s0 exact bool
+ro.telephony.default_cdma_sub u:object_r:telephony_config_prop:s0 exact int
+ro.telephony.default_network u:object_r:telephony_config_prop:s0 exact string
+ro.telephony.iwlan_operation_mode u:object_r:telephony_config_prop:s0 exact enum default legacy AP-assisted
+telephony.active_modems.max_count u:object_r:telephony_config_prop:s0 exact int
+telephony.lteOnCdmaDevice u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.volte_avail_ovr u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.vt_avail_ovr u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.wfc_avail_ovr u:object_r:telephony_config_prop:s0 exact int
+
+# System locale list filter configuration
+ro.localization.locale_filter u:object_r:localization_prop:s0 exact string
+
+# Graphics related properties
+ro.opengles.version u:object_r:graphics_config_prop:s0 exact int
+
+ro.gfx.driver.0 u:object_r:graphics_config_prop:s0 exact string
+ro.gfx.driver.1 u:object_r:graphics_config_prop:s0 exact string
+ro.gfx.angle.supported u:object_r:graphics_config_prop:s0 exact bool
+
+graphics.gpu.profiler.support u:object_r:graphics_config_prop:s0 exact bool
+graphics.gpu.profiler.vulkan_layer_apk u:object_r:graphics_config_prop:s0 exact string
+ )";
diff --git a/libc/system_properties/contexts_split.cpp b/libc/system_properties/contexts_split.cpp
index ccb5bcd..f71d70a 100644
--- a/libc/system_properties/contexts_split.cpp
+++ b/libc/system_properties/contexts_split.cpp
@@ -324,10 +324,16 @@
return true;
}
-prop_area* ContextsSplit::GetPropAreaForName(const char* name) {
+PrefixNode* ContextsSplit::GetPrefixNodeForName(const char* name) {
auto entry = ListFind(prefixes_, [name](PrefixNode* l) {
return l->prefix[0] == '*' || !strncmp(l->prefix, name, l->prefix_len);
});
+
+ return entry;
+}
+
+prop_area* ContextsSplit::GetPropAreaForName(const char* name) {
+ auto entry = GetPrefixNodeForName(name);
if (!entry) {
return nullptr;
}
diff --git a/libc/system_properties/include/system_properties/contexts_split.h b/libc/system_properties/include/system_properties/contexts_split.h
index acb18e3..1d954cc 100644
--- a/libc/system_properties/include/system_properties/contexts_split.h
+++ b/libc/system_properties/include/system_properties/contexts_split.h
@@ -47,7 +47,9 @@
virtual void ResetAccess() override;
virtual void FreeAndUnmap() override;
- private:
+ PrefixNode* GetPrefixNodeForName(const char* name);
+
+ protected:
bool MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed);
bool InitializePropertiesFromFile(const char* filename);
bool InitializeProperties();
diff --git a/libc/system_properties/include/system_properties/prop_trace.h b/libc/system_properties/include/system_properties/prop_trace.h
new file mode 100644
index 0000000..7c65a6d
--- /dev/null
+++ b/libc/system_properties/include/system_properties/prop_trace.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#include "platform/bionic/macros.h"
+
+#include "prop_info.h"
+
+// Tracing class for sysprop. To begin a trace at a specified point:
+// SyspropTrace trace ("prop_name", "prop_value");
+// The trace will end when the constructor goes out of scope.
+// For read-only properties (ro.*), also need to pass prop_info struct.
+
+enum class PropertyAction {
+ kPropertyFind = 0,
+ kPropertySet,
+ kPropertyGetReadOnly,
+ kPropertyGetReadWrite,
+};
+
+class __LIBC_HIDDEN__ SyspropTrace {
+ public:
+ explicit SyspropTrace(const char* prop_name, const char* prop_value, const prop_info* pi,
+ PropertyAction action);
+ ~SyspropTrace();
+
+ private:
+ const char* prop_name_;
+ const char* prop_value_;
+ const prop_info* prop_info_;
+ PropertyAction prop_action_;
+ bool output_trace_;
+
+ BIONIC_DISALLOW_COPY_AND_ASSIGN(SyspropTrace);
+};
diff --git a/libc/system_properties/prop_trace.cpp b/libc/system_properties/prop_trace.cpp
new file mode 100644
index 0000000..ac7ff94
--- /dev/null
+++ b/libc/system_properties/prop_trace.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2020 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 "system_properties/prop_trace.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "private/CachedProperty.h"
+#include "private/bionic_lock.h"
+#include "private/bionic_systrace.h"
+
+#include <async_safe/log.h>
+#include <cutils/trace.h> // For ATRACE_TAG_SYSPROP.
+
+#define PROP_TRACE_MSG_LENGTH 1024
+
+static bool should_trace_prop(const char* prop_name) {
+ // Should not trace kTraceTagsProp to avoid infinite recursion.
+ // Because the following g_trace_enable_flags.Get() will get the property value
+ // of kTraceTagsProp again, which in turn invokes should_trace_prop() here.
+ if (prop_name == nullptr || !strcmp(prop_name, kTraceTagsProp)) {
+ return false;
+ }
+
+ return should_trace(ATRACE_TAG_SYSPROP);
+}
+
+static void sysprop_trace_end() {
+ int trace_marker_fd = get_trace_marker_fd();
+ if (trace_marker_fd == -1) {
+ return;
+ }
+
+ TEMP_FAILURE_RETRY(write(trace_marker_fd, "E|", 2));
+}
+
+static void get_sysprop_trace_end(const prop_info* pi, const char* prop_value,
+ bool read_only = false) {
+ const char* output_value;
+ char message[PROP_TRACE_MSG_LENGTH];
+
+ if (read_only) {
+ if (pi->is_long()) {
+ output_value = pi->long_value();
+ } else {
+ output_value = pi->value;
+ }
+ } else {
+ output_value = prop_value;
+ }
+
+ snprintf(message, sizeof(message), "prop_get: %s, value: %s", pi->name,
+ output_value ? output_value : "null_value");
+ output_trace(message, 'E'); // 'E' for end.
+}
+
+SyspropTrace::SyspropTrace(const char* prop_name, const char* prop_value, const prop_info* pi,
+ PropertyAction action)
+ : prop_name_(prop_name),
+ prop_value_(prop_value),
+ prop_info_(pi),
+ prop_action_(action),
+ output_trace_(false) {
+ if (!should_trace_prop(prop_name)) {
+ return;
+ }
+
+ char message[PROP_TRACE_MSG_LENGTH];
+ if (prop_action_ == PropertyAction::kPropertyFind) {
+ snprintf(message, sizeof(message), "prop_find: %s", prop_name_);
+ } else if (prop_action_ == PropertyAction::kPropertySet) {
+ snprintf(message, sizeof(message), "prop_set: %s, value: %s", prop_name_,
+ prop_value_ ? prop_value_ : "null_value");
+ } else {
+ // For property get, the prop_value_ will be resolved then printed in the destructor.
+ snprintf(message, sizeof(message), "prop_get: %s", prop_name_);
+ }
+
+ output_trace(message, 'B'); // 'B' for begin.
+ output_trace_ = true;
+}
+
+SyspropTrace::~SyspropTrace() {
+ if (!output_trace_) {
+ return;
+ }
+ if (prop_action_ == PropertyAction::kPropertyFind ||
+ prop_action_ == PropertyAction::kPropertySet) {
+ sysprop_trace_end();
+ } else if (prop_action_ == PropertyAction::kPropertyGetReadOnly) {
+ get_sysprop_trace_end(prop_info_, prop_value_, true /* read_only */);
+ } else if (prop_action_ == PropertyAction::kPropertyGetReadWrite) {
+ get_sysprop_trace_end(prop_info_, prop_value_, false /* read_only */);
+ }
+ output_trace_ = false;
+}
diff --git a/libc/system_properties/system_properties.cpp b/libc/system_properties/system_properties.cpp
index 8404778..3fd20b7 100644
--- a/libc/system_properties/system_properties.cpp
+++ b/libc/system_properties/system_properties.cpp
@@ -46,6 +46,7 @@
#include "system_properties/context_node.h"
#include "system_properties/prop_area.h"
#include "system_properties/prop_info.h"
+#include "system_properties/prop_trace.h"
#define SERIAL_DIRTY(serial) ((serial)&1)
#define SERIAL_VALUE_LEN(serial) ((serial) >> 24)
@@ -127,6 +128,9 @@
return nullptr;
}
+ SyspropTrace trace(name, nullptr /* prop_value */, nullptr /* prop_info */,
+ PropertyAction::kPropertyFind);
+
prop_area* pa = contexts_->GetPropAreaForName(name);
if (!pa) {
async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
@@ -201,6 +205,10 @@
// Read only properties don't need to copy the value to a temporary buffer, since it can never
// change. We use relaxed memory order on the serial load for the same reason.
if (is_read_only(pi->name)) {
+ // The 2nd argument is not required for read-only property tracing, as the
+ // value can be obtained via pi->value or pi->long_value().
+ SyspropTrace trace(pi->name, nullptr /* prop_value */, pi /* prop_info */,
+ PropertyAction::kPropertyGetReadOnly);
uint32_t serial = load_const_atomic(&pi->serial, memory_order_relaxed);
if (pi->is_long()) {
callback(cookie, pi->name, pi->long_value(), serial);
@@ -211,6 +219,8 @@
}
char value_buf[PROP_VALUE_MAX];
+ SyspropTrace trace(pi->name, value_buf, pi /* prop_info */,
+ PropertyAction::kPropertyGetReadWrite);
uint32_t serial = ReadMutablePropertyValue(pi, value_buf);
callback(cookie, pi->name, value_buf, serial);
}
diff --git a/libc/tzcode/strptime.c b/libc/tzcode/strptime.c
index 41eaa9b..7e8e234 100644
--- a/libc/tzcode/strptime.c
+++ b/libc/tzcode/strptime.c
@@ -95,9 +95,22 @@
int century;
int relyear;
};
+
+static char gmt[] = { "GMT" };
+static char utc[] = { "UTC" };
+/* RFC-822/RFC-2822 */
+static const char * const nast[5] = {
+ "EST", "CST", "MST", "PST", "\0\0\0"
+};
+static const char * const nadt[5] = {
+ "EDT", "CDT", "MDT", "PDT", "\0\0\0"
+};
+
static int _conv_num(const unsigned char **, int *, int, int);
static unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
struct century_relyear *);
+static const u_char *_find_string(const u_char *, int *, const char * const *,
+ const char * const *, int);
char *
@@ -113,9 +126,10 @@
_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
{
unsigned char c;
- const unsigned char *bp;
+ const unsigned char *bp, *ep;
size_t len = 0;
- int alt_format, i;
+ int alt_format, i, offs;
+ int neg = 0;
bp = (unsigned char *)buf;
while ((c = *fmt) != '\0') {
@@ -432,6 +446,108 @@
return (NULL);
break;
+ case 'Z':
+ tzset();
+ if (strncmp((const char *)bp, gmt, 3) == 0) {
+ tm->tm_isdst = 0;
+ tm->tm_gmtoff = 0;
+ tm->tm_zone = gmt;
+ bp += 3;
+ } else if (strncmp((const char *)bp, utc, 3) == 0) {
+ tm->tm_isdst = 0;
+ tm->tm_gmtoff = 0;
+ tm->tm_zone = utc;
+ bp += 3;
+ } else {
+ ep = _find_string(bp, &i,
+ (const char * const *)tzname,
+ NULL, 2);
+ if (ep == NULL)
+ return (NULL);
+
+ tm->tm_isdst = i;
+ tm->tm_gmtoff = -(timezone);
+ tm->tm_zone = tzname[i];
+ bp = ep;
+ }
+ continue;
+
+ case 'z':
+ /*
+ * We recognize all ISO 8601 formats:
+ * Z = Zulu time/UTC
+ * [+-]hhmm
+ * [+-]hh:mm
+ * [+-]hh
+ * We recognize all RFC-822/RFC-2822 formats:
+ * UT|GMT
+ * North American : UTC offsets
+ * E[DS]T = Eastern : -4 | -5
+ * C[DS]T = Central : -5 | -6
+ * M[DS]T = Mountain: -6 | -7
+ * P[DS]T = Pacific : -7 | -8
+ */
+ while (isspace(*bp))
+ bp++;
+
+ switch (*bp++) {
+ case 'G':
+ if (*bp++ != 'M')
+ return NULL;
+ /*FALLTHROUGH*/
+ case 'U':
+ if (*bp++ != 'T')
+ return NULL;
+ /*FALLTHROUGH*/
+ case 'Z':
+ tm->tm_isdst = 0;
+ tm->tm_gmtoff = 0;
+ tm->tm_zone = utc;
+ continue;
+ case '+':
+ neg = 0;
+ break;
+ case '-':
+ neg = 1;
+ break;
+ default:
+ --bp;
+ ep = _find_string(bp, &i, nast, NULL, 4);
+ if (ep != NULL) {
+ tm->tm_gmtoff = (-5 - i) * SECSPERHOUR;
+ tm->tm_zone = (char *)nast[i];
+ bp = ep;
+ continue;
+ }
+ ep = _find_string(bp, &i, nadt, NULL, 4);
+ if (ep != NULL) {
+ tm->tm_isdst = 1;
+ tm->tm_gmtoff = (-4 - i) * SECSPERHOUR;
+ tm->tm_zone = (char *)nadt[i];
+ bp = ep;
+ continue;
+ }
+ return NULL;
+ }
+ if (!isdigit(bp[0]) || !isdigit(bp[1]))
+ return NULL;
+ offs = ((bp[0]-'0') * 10 + (bp[1]-'0')) * SECSPERHOUR;
+ bp += 2;
+ if (*bp == ':')
+ bp++;
+ if (isdigit(*bp)) {
+ offs += (*bp++ - '0') * 10 * SECSPERMIN;
+ if (!isdigit(*bp))
+ return NULL;
+ offs += (*bp++ - '0') * SECSPERMIN;
+ }
+ if (neg)
+ offs = -offs;
+ tm->tm_isdst = 0; /* XXX */
+ tm->tm_gmtoff = offs;
+ tm->tm_zone = NULL; /* XXX */
+ continue;
+
/*
* Miscellaneous conversions.
*/
@@ -468,28 +584,49 @@
return (unsigned char*)bp;
}
-
static int
_conv_num(const unsigned char **buf, int *dest, int llim, int ulim)
{
- int result = 0;
- int rulim = ulim;
+ int result = 0;
+ int rulim = ulim;
- if (**buf < '0' || **buf > '9')
- return (0);
+ if (**buf < '0' || **buf > '9')
+ return (0);
- /* we use rulim to break out of the loop when we run out of digits */
- do {
- result *= 10;
- result += *(*buf)++ - '0';
- rulim /= 10;
- } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+ /* we use rulim to break out of the loop when we run out of digits */
+ do {
+ result *= 10;
+ result += *(*buf)++ - '0';
+ rulim /= 10;
+ } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
- if (result < llim || result > ulim)
- return (0);
+ if (result < llim || result > ulim)
+ return (0);
- *dest = result;
- return (1);
+ *dest = result;
+ return (1);
+}
+
+static const u_char *
+_find_string(const u_char *bp, int *tgt, const char * const *n1,
+ const char * const *n2, int c)
+{
+ int i;
+ unsigned int len;
+
+ /* check full name - then abbreviated ones */
+ for (; n1 != NULL; n1 = n2, n2 = NULL) {
+ for (i = 0; i < c; i++, n1++) {
+ len = strlen(*n1);
+ if (strncasecmp(*n1, (const char *)bp, len) == 0) {
+ *tgt = i;
+ return bp + len;
+ }
+ }
+ }
+
+ /* Nothing matched */
+ return NULL;
}
char* strptime_l(const char* buf, const char* fmt, struct tm* tm, locale_t l) {
diff --git a/libm/x86/e_acos.S b/libm/x86/e_acos.S
index fa61853..04b1787 100644
--- a/libm/x86/e_acos.S
+++ b/libm/x86/e_acos.S
@@ -1925,5 +1925,5 @@
.type static_const_table,@object
.size static_const_table,6112
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/e_asin.S b/libm/x86/e_asin.S
index 5d7f331..6a3ff8e 100644
--- a/libm/x86/e_asin.S
+++ b/libm/x86/e_asin.S
@@ -1999,5 +1999,5 @@
.type static_const_table,@object
.size static_const_table,6096
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/e_atan2.S b/libm/x86/e_atan2.S
index 1efdf65..e491396 100644
--- a/libm/x86/e_atan2.S
+++ b/libm/x86/e_atan2.S
@@ -1217,5 +1217,5 @@
.type static_const_table,@object
.size static_const_table,3024
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/e_cosh.S b/libm/x86/e_cosh.S
index ecea8f4..567a9d0 100644
--- a/libm/x86/e_cosh.S
+++ b/libm/x86/e_cosh.S
@@ -1345,5 +1345,5 @@
.type static_const_table,@object
.size static_const_table,4256
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/e_hypot.S b/libm/x86/e_hypot.S
index 6a143e5..8422024 100644
--- a/libm/x86/e_hypot.S
+++ b/libm/x86/e_hypot.S
@@ -216,5 +216,5 @@
.type static_const_table,@object
.size static_const_table,32
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/e_log10.S b/libm/x86/e_log10.S
index 09b2952..473cea3 100644
--- a/libm/x86/e_log10.S
+++ b/libm/x86/e_log10.S
@@ -791,5 +791,5 @@
.type static_const_table,@object
.size static_const_table,2160
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/e_sinh.S b/libm/x86/e_sinh.S
index d6b04b5..b9a2930 100644
--- a/libm/x86/e_sinh.S
+++ b/libm/x86/e_sinh.S
@@ -1403,5 +1403,5 @@
.type static_const_table,@object
.size static_const_table,4280
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/libm_reduce_pi04l.S b/libm/x86/libm_reduce_pi04l.S
index af6a7d0..25976ea 100644
--- a/libm/x86/libm_reduce_pi04l.S
+++ b/libm/x86/libm_reduce_pi04l.S
@@ -3714,5 +3714,5 @@
.type __4onpi_31l,@object
.size __4onpi_31l,6444
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/libm_sincos_huge.S b/libm/x86/libm_sincos_huge.S
index b43d193..4601b87 100644
--- a/libm/x86/libm_sincos_huge.S
+++ b/libm/x86/libm_sincos_huge.S
@@ -664,5 +664,5 @@
.size _ones,16
.data
.hidden __libm_reduce_pi04l
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/libm_tancot_huge.S b/libm/x86/libm_tancot_huge.S
index 80f16d5..cdaa820 100644
--- a/libm/x86/libm_tancot_huge.S
+++ b/libm/x86/libm_tancot_huge.S
@@ -746,5 +746,5 @@
.size _GP,144
.data
.hidden __libm_reduce_pi04l
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/s_atan.S b/libm/x86/s_atan.S
index c4413f1..71ca4db 100644
--- a/libm/x86/s_atan.S
+++ b/libm/x86/s_atan.S
@@ -930,5 +930,5 @@
.type static_const_table,@object
.size static_const_table,2704
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/s_cbrt.S b/libm/x86/s_cbrt.S
index 0c98c99..53d3cc2 100644
--- a/libm/x86/s_cbrt.S
+++ b/libm/x86/s_cbrt.S
@@ -734,5 +734,5 @@
.type static_const_table,@object
.size static_const_table,2000
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/s_cos.S b/libm/x86/s_cos.S
index fd5ef5d..e47c63e 100644
--- a/libm/x86/s_cos.S
+++ b/libm/x86/s_cos.S
@@ -888,5 +888,5 @@
.size static_const_table,2256
.data
.hidden __libm_sincos_huge
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/s_expm1.S b/libm/x86/s_expm1.S
index 1f9e87b..1816f59 100644
--- a/libm/x86/s_expm1.S
+++ b/libm/x86/s_expm1.S
@@ -698,5 +698,5 @@
.type static_const_table,@object
.size static_const_table,1296
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/s_log1p.S b/libm/x86/s_log1p.S
index 7a6d845..de7b87b 100644
--- a/libm/x86/s_log1p.S
+++ b/libm/x86/s_log1p.S
@@ -823,5 +823,5 @@
.type static_const_table,@object
.size static_const_table,2192
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/s_sin.S b/libm/x86/s_sin.S
index 1e6cbd4..74d1b86 100644
--- a/libm/x86/s_sin.S
+++ b/libm/x86/s_sin.S
@@ -903,5 +903,5 @@
.size static_const_table,2288
.data
.hidden __libm_sincos_huge
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/s_tan.S b/libm/x86/s_tan.S
index 3ee2107..7935efe 100644
--- a/libm/x86/s_tan.S
+++ b/libm/x86/s_tan.S
@@ -1762,5 +1762,5 @@
.size static_const_table,5872
.data
.hidden __libm_tancot_huge
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86/s_tanh.S b/libm/x86/s_tanh.S
index 737bcbb..777519f 100644
--- a/libm/x86/s_tanh.S
+++ b/libm/x86/s_tanh.S
@@ -1357,5 +1357,5 @@
.type static_const_table,@object
.size static_const_table,4280
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
# End
diff --git a/libm/x86_64/e_acos.S b/libm/x86_64/e_acos.S
index d83c66b..57c910e 100644
--- a/libm/x86_64/e_acos.S
+++ b/libm/x86_64/e_acos.S
@@ -1934,7 +1934,7 @@
.type ONE_BY_2,@object
.size ONE_BY_2,8
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/e_asin.S b/libm/x86_64/e_asin.S
index 9f41c7c..4242543 100644
--- a/libm/x86_64/e_asin.S
+++ b/libm/x86_64/e_asin.S
@@ -2013,7 +2013,7 @@
.type cv,@object
.size cv,24
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/e_atan2.S b/libm/x86_64/e_atan2.S
index f9baea9..f0ba43c 100644
--- a/libm/x86_64/e_atan2.S
+++ b/libm/x86_64/e_atan2.S
@@ -1219,7 +1219,7 @@
.type EXPMASK,@object
.size EXPMASK,8
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/e_cosh.S b/libm/x86_64/e_cosh.S
index 8cdbca6..97cb389 100644
--- a/libm/x86_64/e_cosh.S
+++ b/libm/x86_64/e_cosh.S
@@ -1349,7 +1349,7 @@
.type ONEMASK,@object
.size ONEMASK,8
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/e_hypot.S b/libm/x86_64/e_hypot.S
index 089b2b4..e46669f 100644
--- a/libm/x86_64/e_hypot.S
+++ b/libm/x86_64/e_hypot.S
@@ -191,7 +191,7 @@
.type static_const_table,@object
.size static_const_table,32
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/e_log10.S b/libm/x86_64/e_log10.S
index 4f43a36..86f86ce 100644
--- a/libm/x86_64/e_log10.S
+++ b/libm/x86_64/e_log10.S
@@ -784,7 +784,7 @@
.type coeff,@object
.size coeff,48
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/e_sinh.S b/libm/x86_64/e_sinh.S
index 4d8db63..d5f7b16 100644
--- a/libm/x86_64/e_sinh.S
+++ b/libm/x86_64/e_sinh.S
@@ -1407,7 +1407,7 @@
.type HALFMASK,@object
.size HALFMASK,8
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/s_atan.S b/libm/x86_64/s_atan.S
index 2453e10..d0e5d72 100644
--- a/libm/x86_64/s_atan.S
+++ b/libm/x86_64/s_atan.S
@@ -904,7 +904,7 @@
.type SGNMASK,@object
.size SGNMASK,8
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/s_cbrt.S b/libm/x86_64/s_cbrt.S
index 4aa4373..6b00f56 100644
--- a/libm/x86_64/s_cbrt.S
+++ b/libm/x86_64/s_cbrt.S
@@ -731,7 +731,7 @@
.type NEG_INF,@object
.size NEG_INF,8
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/s_cos.S b/libm/x86_64/s_cos.S
index ab5a0e1..3d9e402 100644
--- a/libm/x86_64/s_cos.S
+++ b/libm/x86_64/s_cos.S
@@ -1248,7 +1248,7 @@
.type NEG_ZERO,@object
.size NEG_ZERO,8
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/s_expm1.S b/libm/x86_64/s_expm1.S
index 9da1d9d..4b22f5a 100644
--- a/libm/x86_64/s_expm1.S
+++ b/libm/x86_64/s_expm1.S
@@ -704,7 +704,7 @@
.type HIGHMASK,@object
.size HIGHMASK,8
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/s_log1p.S b/libm/x86_64/s_log1p.S
index 1ff2d39..27fab74 100644
--- a/libm/x86_64/s_log1p.S
+++ b/libm/x86_64/s_log1p.S
@@ -806,7 +806,7 @@
.type coeff2,@object
.size coeff2,48
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/s_sin.S b/libm/x86_64/s_sin.S
index 2f93a34..fb54a2a 100644
--- a/libm/x86_64/s_sin.S
+++ b/libm/x86_64/s_sin.S
@@ -1273,7 +1273,7 @@
.type NEG_ZERO,@object
.size NEG_ZERO,8
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/s_tan.S b/libm/x86_64/s_tan.S
index 74cb044..4fa12e3 100644
--- a/libm/x86_64/s_tan.S
+++ b/libm/x86_64/s_tan.S
@@ -2212,7 +2212,7 @@
.type NEG_ZERO,@object
.size NEG_ZERO,8
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/libm/x86_64/s_tanh.S b/libm/x86_64/s_tanh.S
index 2c8f9bf..a76a5c2 100644
--- a/libm/x86_64/s_tanh.S
+++ b/libm/x86_64/s_tanh.S
@@ -1369,7 +1369,7 @@
.type TWOMASK,@object
.size TWOMASK,8
.data
- .section .note.GNU-stack, ""
+ .section .note.GNU-stack, "",@progbits
// -- Begin DWARF2 SEGMENT .eh_frame
.section .eh_frame,"a",@progbits
.eh_frame_seg:
diff --git a/linker/Android.bp b/linker/Android.bp
index 08b2c7b..a51b73f 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -39,6 +39,9 @@
"linker_wrapper.cpp",
],
arch: {
+ arm64: {
+ srcs: ["arch/arm64/begin.S"],
+ },
x86_64: {
srcs: ["arch/x86_64/begin.S"],
},
diff --git a/linker/linker_tls.cpp b/linker/linker_tls.cpp
index d2edbb3..97892f4 100644
--- a/linker/linker_tls.cpp
+++ b/linker/linker_tls.cpp
@@ -128,6 +128,8 @@
void linker_finalize_static_tls() {
g_static_tls_finished = true;
__libc_shared_globals()->static_tls_layout.finish_layout();
+ TlsModules& modules = __libc_shared_globals()->tls_modules;
+ modules.static_module_count = modules.module_count;
}
void register_soinfo_tls(soinfo* si) {
diff --git a/tests/Android.bp b/tests/Android.bp
index 7e6e742..8760256 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -44,6 +44,7 @@
// For glibc.
"-D__STDC_LIMIT_MACROS",
],
+ header_libs: ["libcutils_headers"],
// Ensure that the tests exercise shadow call stack support and
// the hint space PAC/BTI instructions.
arch: {
@@ -422,6 +423,7 @@
"sys_uio_test.cpp",
"sys_un_test.cpp",
"sys_vfs_test.cpp",
+ "sys_wait_test.cpp",
"sys_xattr_test.cpp",
"system_properties_test.cpp",
"system_properties_test2.cpp",
diff --git a/tests/dirent_test.cpp b/tests/dirent_test.cpp
index 378aea4..56929d1 100644
--- a/tests/dirent_test.cpp
+++ b/tests/dirent_test.cpp
@@ -113,6 +113,18 @@
ASSERT_EQ(unsorted_name_list, unsorted_name_list_at64);
}
+static int is_version_filter(const dirent* de) {
+ return !strcmp(de->d_name, "version");
+}
+
+TEST(dirent, scandir_filter) {
+ dirent** entries;
+ errno = 0;
+ ASSERT_EQ(1, scandir("/proc", &entries, is_version_filter, nullptr));
+ ASSERT_STREQ("version", entries[0]->d_name);
+ free(entries);
+}
+
TEST(dirent, scandir_ENOENT) {
dirent** entries;
errno = 0;
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 6907abe..3ca0223 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -204,8 +204,9 @@
foo myfoo;
volatile int asize = sizeof(myfoo.a) + 1;
memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
- ASSERT_FORTIFY(printf("%s", memchr(myfoo.a, 'a', asize)));
- ASSERT_FORTIFY(printf("%s", memchr(static_cast<const void*>(myfoo.a), 'a', asize)));
+ ASSERT_FORTIFY(printf("%s", static_cast<const char*>(memchr(myfoo.a, 'a', asize))));
+ ASSERT_FORTIFY(printf(
+ "%s", static_cast<const char*>(memchr(static_cast<const void*>(myfoo.a), 'a', asize))));
#else // __BIONIC__
GTEST_SKIP() << "glibc is broken";
#endif // __BIONIC__
@@ -216,8 +217,9 @@
foo myfoo;
volatile int asize = sizeof(myfoo.a) + 1;
memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
- ASSERT_FORTIFY(printf("%s", memrchr(myfoo.a, 'a', asize)));
- ASSERT_FORTIFY(printf("%s", memrchr(static_cast<const void*>(myfoo.a), 'a', asize)));
+ ASSERT_FORTIFY(printf("%s", static_cast<const char*>(memrchr(myfoo.a, 'a', asize))));
+ ASSERT_FORTIFY(printf(
+ "%s", static_cast<const char*>(memrchr(static_cast<const void*>(myfoo.a), 'a', asize))));
#else // __BIONIC__
GTEST_SKIP() << "glibc is broken";
#endif // __BIONIC__
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index 99117e4..bf65720 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -820,6 +820,24 @@
#endif
}
+TEST(grp, getgrouplist) {
+#if defined(__BIONIC__)
+ // Query the number of groups.
+ int ngroups = 0;
+ ASSERT_EQ(-1, getgrouplist("root", 123, nullptr, &ngroups));
+ ASSERT_EQ(1, ngroups);
+
+ // Query the specific groups (just the one you pass in on Android).
+ ngroups = 8;
+ gid_t groups[ngroups];
+ ASSERT_EQ(1, getgrouplist("root", 123, groups, &ngroups));
+ ASSERT_EQ(1, ngroups);
+ ASSERT_EQ(123u, groups[0]);
+#else
+ GTEST_SKIP() << "bionic-only test (groups too unpredictable)";
+#endif
+}
+
#if defined(__BIONIC__)
static void TestAidNamePrefix(const std::string& file_path) {
std::string file_contents;
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index fcf4497..ef4fddd 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -79,6 +79,22 @@
shared_libs: ["libtest_elftls_shared_var"],
}
+cc_test {
+ name: "thread_exit_cb_helper.cpp",
+ defaults: ["bionic_testlib_defaults"],
+ srcs: ["thread_exit_cb_helper.cpp"],
+ cflags: ["-fno-emulated-tls"],
+}
+
+cc_test {
+ name: "tls_properties_helper",
+ defaults: ["bionic_testlib_defaults"],
+ srcs: ["tls_properties_helper.cpp"],
+ cflags: ["-fno-emulated-tls"],
+ shared_libs: ["libtest_elftls_shared_var"],
+}
+
+
cc_test_library {
name: "libtest_elftls_dynamic_filler_1",
defaults: ["bionic_testlib_defaults"],
diff --git a/tests/libs/thread_exit_cb_helper.cpp b/tests/libs/thread_exit_cb_helper.cpp
new file mode 100644
index 0000000..8ec1398
--- /dev/null
+++ b/tests/libs/thread_exit_cb_helper.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+// Prevent tests from being compiled with glibc because thread_properties.h
+// only exists in Bionic.
+#if defined(__BIONIC__)
+
+#include <stdio.h>
+#include <sys/thread_properties.h>
+
+// Helper binary for testing thread_exit_cb registration.
+
+void exit_cb_1() {
+ printf("exit_cb_1 called ");
+}
+
+void exit_cb_2() {
+ printf("exit_cb_2 called ");
+}
+
+void exit_cb_3() {
+ printf("exit_cb_3 called");
+}
+
+void test_register_thread_exit_cb() {
+ // Register the exit-cb in reverse order (3,2,1)
+ // so that they'd be called in 1,2,3 order.
+ __libc_register_thread_exit_callback(&exit_cb_3);
+ __libc_register_thread_exit_callback(&exit_cb_2);
+ __libc_register_thread_exit_callback(&exit_cb_1);
+}
+
+int main() {
+ test_register_thread_exit_cb();
+ return 0;
+}
+#else
+int main() {
+ return 0;
+}
+#endif // __BIONIC__
diff --git a/tests/libs/tls_properties_helper.cpp b/tests/libs/tls_properties_helper.cpp
new file mode 100644
index 0000000..3f8d118
--- /dev/null
+++ b/tests/libs/tls_properties_helper.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+// Prevent tests from being compiled with glibc because thread_properties.h
+// only exists in Bionic.
+#if defined(__BIONIC__)
+
+#include <sys/thread_properties.h>
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h> // for gettid
+
+// Helper binary to use TLS-related functions in thread_properties
+
+// Tests __get_static_tls_bound.
+thread_local int local_var;
+void test_static_tls_bounds() {
+ local_var = 123;
+ void* start_addr = nullptr;
+ void* end_addr = nullptr;
+
+ __libc_get_static_tls_bounds(reinterpret_cast<void**>(&start_addr),
+ reinterpret_cast<void**>(&end_addr));
+ assert(start_addr != nullptr);
+ assert(end_addr != nullptr);
+
+ assert(&local_var >= start_addr && &local_var < end_addr);
+
+ printf("done_get_static_tls_bounds\n");
+}
+
+// Tests iterate_dynamic tls chunks.
+// Export a var from the shared so.
+__thread char large_tls_var[4 * 1024 * 1024];
+void test_iter_tls() {
+ void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
+
+ int i = 0;
+ auto cb = [&](void* dtls_begin, void* dtls_end, size_t dso_id, void* arg) {
+ printf("iterate_cb i = %d\n", i++);
+ };
+ __libc_iterate_dynamic_tls(gettid(), cb, nullptr);
+ printf("done_iterate_dynamic_tls\n");
+}
+
+int main() {
+ test_static_tls_bounds();
+ test_iter_tls();
+ return 0;
+}
+
+#else
+int main() {
+ return 0;
+}
+#endif // __BIONIC__
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index 55bd149..d692cf9 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -84,6 +84,24 @@
free(ptr);
}
+TEST(malloc, calloc_mem_init_disabled) {
+#if defined(__BIONIC__)
+ // calloc should still zero memory if mem-init is disabled.
+ // With jemalloc the mallopts will fail but that shouldn't affect the
+ // execution of the test.
+ mallopt(M_THREAD_DISABLE_MEM_INIT, 1);
+ size_t alloc_len = 100;
+ char *ptr = reinterpret_cast<char*>(calloc(1, alloc_len));
+ for (size_t i = 0; i < alloc_len; i++) {
+ ASSERT_EQ(0, ptr[i]);
+ }
+ free(ptr);
+ mallopt(M_THREAD_DISABLE_MEM_INIT, 0);
+#else
+ GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
TEST(malloc, calloc_illegal) {
SKIP_WITH_HWASAN;
errno = 0;
diff --git a/tests/netinet_ether_test.cpp b/tests/netinet_ether_test.cpp
index faa3db4..af020ec 100644
--- a/tests/netinet_ether_test.cpp
+++ b/tests/netinet_ether_test.cpp
@@ -34,7 +34,7 @@
TEST(netinet_ether, ether_aton_r__ether_ntoa_r) {
ether_addr addr;
memset(&addr, 0, sizeof(addr));
- ether_addr* a = ether_aton_r("12:34:56:78:9a:bc", &addr);
+ ether_addr* a = ether_aton_r("12:34:56:78:9a:Bc", &addr);
ASSERT_EQ(&addr, a);
ASSERT_EQ(0x12, addr.ether_addr_octet[0]);
ASSERT_EQ(0x34, addr.ether_addr_octet[1]);
@@ -49,3 +49,11 @@
ASSERT_EQ(buf, p);
ASSERT_STREQ("12:34:56:78:9a:bc", buf);
}
+
+TEST(netinet_ether, ether_aton_r_failures) {
+ ether_addr addr;
+ ASSERT_TRUE(ether_aton_r("12:34:56:78:9a;bc", &addr) == nullptr);
+ ASSERT_TRUE(ether_aton_r("12:34:56:78:9a:bc ", &addr) == nullptr);
+ ASSERT_TRUE(ether_aton_r("g2:34:56:78:9a:bc ", &addr) == nullptr);
+ ASSERT_TRUE(ether_aton_r("1G:34:56:78:9a:bc ", &addr) == nullptr);
+}
diff --git a/tests/netinet_in_test.cpp b/tests/netinet_in_test.cpp
index 2606082..437e180 100644
--- a/tests/netinet_in_test.cpp
+++ b/tests/netinet_in_test.cpp
@@ -31,8 +31,15 @@
static constexpr uint64_t be64 = 0xf0debc9a78563412;
TEST(netinet_in, bindresvport) {
- // This isn't something we can usually test, so just check the symbol's there.
+ // This isn't something we can usually test (because you need to be root),
+ // so just check the symbol's there.
ASSERT_EQ(-1, bindresvport(-1, nullptr));
+
+ // Only AF_INET is supported.
+ sockaddr_in sin = {.sin_family = AF_INET6};
+ errno = 0;
+ ASSERT_EQ(-1, bindresvport(-1, &sin));
+ ASSERT_EQ(EPFNOSUPPORT, errno);
}
TEST(netinet_in, in6addr_any) {
diff --git a/tests/sched_test.cpp b/tests/sched_test.cpp
index 9309a7f..03e8062 100644
--- a/tests/sched_test.cpp
+++ b/tests/sched_test.cpp
@@ -301,3 +301,7 @@
// don't behave as POSIX specifies. http://b/26203902.
ASSERT_EQ(0, sched_setscheduler(getpid(), original_policy, &p));
}
+
+TEST(sched, sched_getaffinity_failure) {
+ ASSERT_EQ(-1, sched_getaffinity(getpid(), 0, nullptr));
+}
diff --git a/tests/search_test.cpp b/tests/search_test.cpp
index 1509199..8b8359d 100644
--- a/tests/search_test.cpp
+++ b/tests/search_test.cpp
@@ -114,6 +114,11 @@
ASSERT_EQ(3U, g_free_calls);
}
+TEST(search, tdestroy_null) {
+ // It's okay to pass a null node, and your callback will not be called.
+ tdestroy(nullptr, nullptr);
+}
+
struct pod_node {
explicit pod_node(int i) : i(i) {}
int i;
@@ -285,3 +290,26 @@
AssertEntry(e, "a", "B");
hdestroy_r(&h2);
}
+
+TEST(search, hsearch_resizing) {
+ ASSERT_NE(0, hcreate(1));
+
+ std::vector<char*> entries;
+ // Add enough entries to ensure that we've had to resize.
+ for (char ch = ' '; ch <= '~'; ++ch) {
+ char* p;
+ asprintf(&p, "%c", ch);
+ ENTRY e;
+ e.data = e.key = p;
+ ASSERT_TRUE(hsearch(e, ENTER) != nullptr);
+ entries.push_back(p);
+ }
+
+ // Check they're all there.
+ for (auto& p : entries) {
+ ENTRY* e = hsearch(ENTRY{.key = p, .data = nullptr}, FIND);
+ AssertEntry(e, p, p);
+ }
+
+ for (auto& p : entries) free(p);
+}
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index f6eca05..c21c3b8 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -371,6 +371,11 @@
#endif
}
+TEST(STDIO_TEST, snprintf_measure) {
+ char buf[16];
+ ASSERT_EQ(11, snprintf(buf, 0, "Hello %s", "world"));
+}
+
TEST(STDIO_TEST, snprintf_smoke) {
char buf[BUFSIZ];
@@ -1155,7 +1160,6 @@
free(p1);
}
-
TEST(STDIO_TEST, sscanf_mlc) {
// This is so useless that clang doesn't even believe it exists...
#pragma clang diagnostic push
@@ -1189,7 +1193,6 @@
#pragma clang diagnostic pop
}
-
TEST(STDIO_TEST, sscanf_ms) {
CheckScanfM(sscanf, "hello", "%ms", 1, "hello");
CheckScanfM(sscanf, "hello", "%4ms", 1, "hell");
@@ -2533,6 +2536,16 @@
eth.Run([&]() { exit(puts("a b c")); }, 0, "a b c\n");
}
+TEST(STDIO_TEST, putchar) {
+ ExecTestHelper eth;
+ eth.Run([&]() { exit(putchar('A')); }, 65, "A");
+}
+
+TEST(STDIO_TEST, putchar_unlocked) {
+ ExecTestHelper eth;
+ eth.Run([&]() { exit(putchar('B')); }, 66, "B");
+}
+
TEST(STDIO_TEST, unlocked) {
TemporaryFile tf;
@@ -2733,3 +2746,73 @@
ASSERT_NE(0, RENAME_WHITEOUT);
#endif
}
+
+TEST(STDIO_TEST, fdopen_failures) {
+ FILE* fp;
+ int fd = open("/proc/version", O_RDONLY);
+ ASSERT_TRUE(fd != -1);
+
+ // Nonsense mode.
+ errno = 0;
+ fp = fdopen(fd, "nonsense");
+ ASSERT_TRUE(fp == nullptr);
+ ASSERT_EQ(EINVAL, errno);
+
+ // Mode that isn't a subset of the fd's actual mode.
+ errno = 0;
+ fp = fdopen(fd, "w");
+ ASSERT_TRUE(fp == nullptr);
+ ASSERT_EQ(EINVAL, errno);
+
+ // Can't set append on the underlying fd.
+ errno = 0;
+ fp = fdopen(fd, "a");
+ ASSERT_TRUE(fp == nullptr);
+ ASSERT_EQ(EINVAL, errno);
+
+ // Bad fd.
+ errno = 0;
+ fp = fdopen(-1, "re");
+ ASSERT_TRUE(fp == nullptr);
+ ASSERT_EQ(EBADF, errno);
+
+ close(fd);
+}
+
+TEST(STDIO_TEST, fmemopen_invalid_mode) {
+ errno = 0;
+ FILE* fp = fmemopen(nullptr, 16, "nonsense");
+ ASSERT_TRUE(fp == nullptr);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(STDIO_TEST, fopen_invalid_mode) {
+ errno = 0;
+ FILE* fp = fopen("/proc/version", "nonsense");
+ ASSERT_TRUE(fp == nullptr);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(STDIO_TEST, freopen_invalid_mode) {
+ FILE* fp = fopen("/proc/version", "re");
+ ASSERT_TRUE(fp != nullptr);
+
+ errno = 0;
+ fp = freopen("/proc/version", "nonsense", fp);
+ ASSERT_TRUE(fp == nullptr);
+ ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(STDIO_TEST, asprintf_smoke) {
+ char* p = nullptr;
+ ASSERT_EQ(11, asprintf(&p, "hello %s", "world"));
+ ASSERT_STREQ("hello world", p);
+ free(p);
+}
+
+TEST(STDIO_TEST, fopen_ENOENT) {
+ errno = 0;
+ FILE* fp = fopen("/proc/does-not-exist", "re");
+ ASSERT_TRUE(fp == nullptr);
+ ASSERT_EQ(ENOENT, errno);
+}
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 3f1ec86..c7b2ad8 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -800,10 +800,25 @@
ASSERT_EQ(T(0), fn("123", &end_p, 37));
ASSERT_EQ(EINVAL, errno);
+ // Both leading + or - are always allowed (even for the strtou* family).
+ ASSERT_EQ(T(-123), fn("-123", &end_p, 10));
+ ASSERT_EQ(T(123), fn("+123", &end_p, 10));
+
// If we see "0x" *not* followed by a hex digit, we shouldn't swallow the 'x'.
ASSERT_EQ(T(0), fn("0xy", &end_p, 16));
ASSERT_EQ('x', *end_p);
+ // Hexadecimal (both the 0x and the digits) is case-insensitive.
+ ASSERT_EQ(T(0xab), fn("0xab", &end_p, 0));
+ ASSERT_EQ(T(0xab), fn("0Xab", &end_p, 0));
+ ASSERT_EQ(T(0xab), fn("0xAB", &end_p, 0));
+ ASSERT_EQ(T(0xab), fn("0XAB", &end_p, 0));
+ ASSERT_EQ(T(0xab), fn("0xAb", &end_p, 0));
+ ASSERT_EQ(T(0xab), fn("0XAb", &end_p, 0));
+
+ // Octal lives! (Sadly.)
+ ASSERT_EQ(T(0666), fn("0666", &end_p, 0));
+
if (std::numeric_limits<T>::is_signed) {
// Minimum (such as -128).
std::string min{std::to_string(std::numeric_limits<T>::min())};
@@ -878,6 +893,18 @@
CheckStrToInt(strtoumax);
}
+TEST(stdlib, atoi) {
+ // Implemented using strtol in bionic, so extensive testing unnecessary.
+ ASSERT_EQ(123, atoi("123four"));
+ ASSERT_EQ(0, atoi("hello"));
+}
+
+TEST(stdlib, atol) {
+ // Implemented using strtol in bionic, so extensive testing unnecessary.
+ ASSERT_EQ(123L, atol("123four"));
+ ASSERT_EQ(0L, atol("hello"));
+}
+
TEST(stdlib, abs) {
ASSERT_EQ(INT_MAX, abs(-INT_MAX));
ASSERT_EQ(INT_MAX, abs(INT_MAX));
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index fd7a551..22be852 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -64,6 +64,11 @@
ASSERT_STREQ("Unknown error 134", strerror(EHWPOISON + 1));
}
+TEST(STRING_TEST, strerror_l) {
+ // bionic just forwards to strerror(3).
+ ASSERT_STREQ("Success", strerror_l(0, LC_GLOBAL_LOCALE));
+}
+
#if defined(__BIONIC__)
static void* ConcurrentStrErrorFn(void*) {
bool equal = (strcmp("Unknown error 2002", strerror(2002)) == 0);
@@ -1607,6 +1612,13 @@
ASSERT_TRUE(strcoll("aac", "aab") > 0);
}
+TEST(STRING_TEST, strcoll_l_smoke) {
+ // bionic just forwards to strcoll(3).
+ ASSERT_TRUE(strcoll_l("aab", "aac", LC_GLOBAL_LOCALE) < 0);
+ ASSERT_TRUE(strcoll_l("aab", "aab", LC_GLOBAL_LOCALE) == 0);
+ ASSERT_TRUE(strcoll_l("aac", "aab", LC_GLOBAL_LOCALE) > 0);
+}
+
TEST(STRING_TEST, strxfrm_smoke) {
const char* src1 = "aab";
char dst1[16] = {};
@@ -1628,6 +1640,16 @@
ASSERT_TRUE(strcmp(dst1, dst2) < 0);
}
+TEST(STRING_TEST, strxfrm_l_smoke) {
+ // bionic just forwards to strxfrm(3), so this is a subset of the
+ // strxfrm test.
+ const char* src1 = "aab";
+ char dst1[16] = {};
+ ASSERT_EQ(strxfrm_l(dst1, src1, 0, LC_GLOBAL_LOCALE), 3U);
+ ASSERT_STREQ(dst1, "");
+ ASSERT_EQ(strxfrm_l(dst1, src1, sizeof(dst1), LC_GLOBAL_LOCALE), 3U);
+}
+
TEST(STRING_TEST, memccpy_smoke) {
char dst[32];
diff --git a/tests/sys_procfs_test.cpp b/tests/sys_procfs_test.cpp
index 8054869..5e0a0b0 100644
--- a/tests/sys_procfs_test.cpp
+++ b/tests/sys_procfs_test.cpp
@@ -18,7 +18,7 @@
#include <sys/procfs.h>
-TEST(sys_procfs, smoke) {
+TEST(sys_procfs, types) {
elf_greg_t reg;
memset(®, 0, sizeof(reg));
@@ -37,3 +37,16 @@
static_assert(sizeof(prgregset_t) == sizeof(elf_gregset_t), "");
static_assert(sizeof(prfpregset_t) == sizeof(elf_fpregset_t), "");
}
+
+TEST(sys_procfs, constants) {
+ // NGREG != ELF_NGREG (https://github.com/android/ndk/issues/1347)
+ static_assert(sizeof(gregset_t) / sizeof(greg_t) == NGREG);
+
+#if defined(__arm__)
+ static_assert(sizeof(user_regs) / sizeof(elf_greg_t) == ELF_NGREG);
+#elif defined(__aarch64__)
+ static_assert(sizeof(user_pt_regs) / sizeof(elf_greg_t) == ELF_NGREG);
+#else
+ static_assert(sizeof(user_regs_struct) / sizeof(elf_greg_t) == ELF_NGREG);
+#endif
+}
diff --git a/tests/sys_thread_properties_test.cpp b/tests/sys_thread_properties_test.cpp
new file mode 100644
index 0000000..cf1a6ba
--- /dev/null
+++ b/tests/sys_thread_properties_test.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 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 "gtest_globals.h"
+#include "utils.h"
+
+TEST(thread_properties_test, iterate_dts) {
+#if defined(__BIONIC__)
+ const char expected_out[] =
+ "got test_static_tls_bounds\niterate_cb i = 0\ndone_iterate_dynamic_tls\n";
+ std::string helper = GetTestLibRoot() + "tls_properties_helper/tls_properties_helper";
+ chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607
+
+ ExecTestHelper eth;
+ eth.SetArgs({helper.c_str(), nullptr});
+ eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, expected_out);
+#endif
+}
+
+TEST(thread_properties_test, thread_exit_cb) {
+#if defined(__BIONIC__)
+ // tests/libs/thread_exit_cb_helper.cpp
+ const char expected_out[] = "exit_cb_1 called exit_cb_2 called exit_cb_3 called";
+ std::string helper = GetTestLibRoot() + "thread_exit_cb_helper/thread_exit_cb_helper";
+ chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607
+
+ ExecTestHelper eth;
+ eth.SetArgs({helper.c_str(), nullptr});
+ eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, expected_out);
+
+#endif
+}
diff --git a/tests/sys_vfs_test.cpp b/tests/sys_vfs_test.cpp
index a521967..f82f505 100644
--- a/tests/sys_vfs_test.cpp
+++ b/tests/sys_vfs_test.cpp
@@ -44,12 +44,26 @@
Check(sb);
}
+TEST(sys_vfs, statfs_failure) {
+ struct statfs sb;
+ errno = 0;
+ ASSERT_EQ(-1, statfs("/does-not-exist", &sb));
+ ASSERT_EQ(ENOENT, errno);
+}
+
TEST(sys_vfs, statfs64) {
struct statfs64 sb;
ASSERT_EQ(0, statfs64("/proc", &sb));
Check(sb);
}
+TEST(sys_vfs, statfs64_failure) {
+ struct statfs64 sb;
+ errno = 0;
+ ASSERT_EQ(-1, statfs64("/does-not-exist", &sb));
+ ASSERT_EQ(ENOENT, errno);
+}
+
TEST(sys_vfs, fstatfs) {
struct statfs sb;
int fd = open("/proc", O_RDONLY);
@@ -58,6 +72,13 @@
Check(sb);
}
+TEST(sys_vfs, fstatfs_failure) {
+ struct statfs sb;
+ errno = 0;
+ ASSERT_EQ(-1, fstatfs(-1, &sb));
+ ASSERT_EQ(EBADF, errno);
+}
+
TEST(sys_vfs, fstatfs64) {
struct statfs64 sb;
int fd = open("/proc", O_RDONLY);
@@ -65,3 +86,10 @@
close(fd);
Check(sb);
}
+
+TEST(sys_vfs, fstatfs64_failure) {
+ struct statfs sb;
+ errno = 0;
+ ASSERT_EQ(-1, fstatfs(-1, &sb));
+ ASSERT_EQ(EBADF, errno);
+}
diff --git a/tests/sys_wait_test.cpp b/tests/sys_wait_test.cpp
new file mode 100644
index 0000000..c006972
--- /dev/null
+++ b/tests/sys_wait_test.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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 <sys/wait.h>
+
+TEST(sys_wait, waitid) {
+ pid_t pid = fork();
+ ASSERT_NE(pid, -1);
+
+ if (pid == 0) _exit(66);
+
+ siginfo_t si = {};
+ ASSERT_EQ(0, waitid(P_PID, pid, &si, WEXITED));
+ ASSERT_EQ(pid, si.si_pid);
+ ASSERT_EQ(66, si.si_status);
+ ASSERT_EQ(CLD_EXITED, si.si_code);
+}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 5a977c2..b1de0a4 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -363,6 +363,105 @@
EXPECT_TRUE(memcmp(&tm, &zero, sizeof(tm)) == 0);
}
+TEST(time, strptime_Z) {
+#if defined(__BIONIC__)
+ // glibc doesn't handle %Z at all.
+ // The BSDs only handle hard-coded "GMT" and "UTC", plus whatever two strings
+ // are in the global `tzname` (which correspond to the current $TZ).
+ struct tm tm;
+ setenv("TZ", "Europe/Berlin", 1);
+
+ // "GMT" always works.
+ tm = {};
+ ASSERT_EQ('\0', *strptime("GMT", "%Z", &tm));
+ EXPECT_STREQ("GMT", tm.tm_zone);
+ EXPECT_EQ(0, tm.tm_isdst);
+ EXPECT_EQ(0, tm.tm_gmtoff);
+
+ // As does "UTC".
+ tm = {};
+ ASSERT_EQ('\0', *strptime("UTC", "%Z", &tm));
+ EXPECT_STREQ("UTC", tm.tm_zone);
+ EXPECT_EQ(0, tm.tm_isdst);
+ EXPECT_EQ(0, tm.tm_gmtoff);
+
+ // Europe/Berlin is known as "CET" when there's no DST.
+ tm = {};
+ ASSERT_EQ('\0', *strptime("CET", "%Z", &tm));
+ EXPECT_STREQ("CET", tm.tm_zone);
+ EXPECT_EQ(0, tm.tm_isdst);
+ EXPECT_EQ(3600, tm.tm_gmtoff);
+
+ // Europe/Berlin is known as "CEST" when there's no DST.
+ tm = {};
+ ASSERT_EQ('\0', *strptime("CEST", "%Z", &tm));
+ EXPECT_STREQ("CEST", tm.tm_zone);
+ EXPECT_EQ(1, tm.tm_isdst);
+ EXPECT_EQ(3600, tm.tm_gmtoff);
+
+ // And as long as we're in Europe/Berlin, those are the only time zone
+ // abbreviations that are recognized.
+ tm = {};
+ ASSERT_TRUE(strptime("PDT", "%Z", &tm) == nullptr);
+#endif
+}
+
+TEST(time, strptime_z) {
+ struct tm tm;
+ setenv("TZ", "Europe/Berlin", 1);
+
+ // "UT" is what RFC822 called UTC.
+ tm = {};
+ ASSERT_EQ('\0', *strptime("UT", "%z", &tm));
+ EXPECT_STREQ("UTC", tm.tm_zone);
+ EXPECT_EQ(0, tm.tm_isdst);
+ EXPECT_EQ(0, tm.tm_gmtoff);
+ // "GMT" is RFC822's other name for UTC.
+ tm = {};
+ ASSERT_EQ('\0', *strptime("GMT", "%z", &tm));
+ EXPECT_STREQ("UTC", tm.tm_zone);
+ EXPECT_EQ(0, tm.tm_isdst);
+ EXPECT_EQ(0, tm.tm_gmtoff);
+
+ // "Z" ("Zulu") is a synonym for UTC.
+ tm = {};
+ ASSERT_EQ('\0', *strptime("Z", "%z", &tm));
+ EXPECT_STREQ("UTC", tm.tm_zone);
+ EXPECT_EQ(0, tm.tm_isdst);
+ EXPECT_EQ(0, tm.tm_gmtoff);
+
+ // "PST"/"PDT" and the other common US zone abbreviations are all supported.
+ tm = {};
+ ASSERT_EQ('\0', *strptime("PST", "%z", &tm));
+ EXPECT_STREQ("PST", tm.tm_zone);
+ EXPECT_EQ(0, tm.tm_isdst);
+ EXPECT_EQ(-28800, tm.tm_gmtoff);
+ tm = {};
+ ASSERT_EQ('\0', *strptime("PDT", "%z", &tm));
+ EXPECT_STREQ("PDT", tm.tm_zone);
+ EXPECT_EQ(1, tm.tm_isdst);
+ EXPECT_EQ(-25200, tm.tm_gmtoff);
+
+ // +-hh
+ tm = {};
+ ASSERT_EQ('\0', *strptime("+01", "%z", &tm));
+ EXPECT_EQ(3600, tm.tm_gmtoff);
+ EXPECT_TRUE(tm.tm_zone == nullptr);
+ EXPECT_EQ(0, tm.tm_isdst);
+ // +-hhmm
+ tm = {};
+ ASSERT_EQ('\0', *strptime("+0130", "%z", &tm));
+ EXPECT_EQ(5400, tm.tm_gmtoff);
+ EXPECT_TRUE(tm.tm_zone == nullptr);
+ EXPECT_EQ(0, tm.tm_isdst);
+ // +-hh:mm
+ tm = {};
+ ASSERT_EQ('\0', *strptime("+01:30", "%z", &tm));
+ EXPECT_EQ(5400, tm.tm_gmtoff);
+ EXPECT_TRUE(tm.tm_zone == nullptr);
+ EXPECT_EQ(0, tm.tm_isdst);
+}
+
void SetTime(timer_t t, time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
itimerspec ts;
ts.it_value.tv_sec = value_s;
@@ -1008,4 +1107,5 @@
TEST(time, difftime) {
ASSERT_EQ(1.0, difftime(1, 0));
+ ASSERT_EQ(-1.0, difftime(0, 1));
}
diff --git a/tests/utils.h b/tests/utils.h
index c1b7f65..acd8bc6 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -78,13 +78,8 @@
static inline bool running_with_native_bridge() {
#if defined(__BIONIC__)
-#if defined(__arm__)
- static const prop_info* pi = __system_property_find("ro.dalvik.vm.isa.arm");
+ static const prop_info* pi = __system_property_find("ro.dalvik.vm.isa." ABI_STRING);
return pi != nullptr;
-#elif defined(__aarch64__)
- static const prop_info* pi = __system_property_find("ro.dalvik.vm.isa.arm64");
- return pi != nullptr;
-#endif
#endif
return false;
}
diff --git a/tools/versioner/src/Driver.cpp b/tools/versioner/src/Driver.cpp
index 184c3d4..adf93c3 100644
--- a/tools/versioner/src/Driver.cpp
+++ b/tools/versioner/src/Driver.cpp
@@ -42,6 +42,7 @@
#include <llvm/ADT/SmallVector.h>
#include <llvm/ADT/StringRef.h>
#include <llvm/Option/Option.h>
+#include <llvm/Support/Host.h>
#include <llvm/Support/VirtualFileSystem.h>
#include "Arch.h"