Merge "Add tests for dynamic ELF TLS"
diff --git a/libc/bionic/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
index bac3d88..6182ed8 100644
--- a/libc/bionic/bionic_systrace.cpp
+++ b/libc/bionic/bionic_systrace.cpp
@@ -82,7 +82,7 @@
return;
}
- TEMP_FAILURE_RETRY(write(trace_marker_fd, "E", 1));
+ TEMP_FAILURE_RETRY(write(trace_marker_fd, "E|", 2));
}
ScopedTrace::ScopedTrace(const char* message) : called_end_(false) {
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index d1aa1ea..fc65e15 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -562,13 +562,7 @@
}
}
-static void* LoadSharedLibrary(const char* shared_lib, const char* prefix, MallocDispatch* dispatch_table) {
- void* impl_handle = dlopen(shared_lib, RTLD_NOW | RTLD_LOCAL);
- if (impl_handle == nullptr) {
- error_log("%s: Unable to open shared library %s: %s", getprogname(), shared_lib, dlerror());
- return nullptr;
- }
-
+static bool InitSharedLibrary(void* impl_handle, const char* shared_lib, const char* prefix, MallocDispatch* dispatch_table) {
static constexpr const char* names[] = {
"initialize",
"finalize",
@@ -583,48 +577,61 @@
g_functions[i] = dlsym(impl_handle, symbol);
if (g_functions[i] == nullptr) {
error_log("%s: %s routine not found in %s", getprogname(), symbol, shared_lib);
- dlclose(impl_handle);
ClearGlobalFunctions();
- return nullptr;
+ return false;
}
}
if (!InitMallocFunctions(impl_handle, dispatch_table, prefix)) {
- dlclose(impl_handle);
ClearGlobalFunctions();
+ return false;
+ }
+ return true;
+}
+
+static void* LoadSharedLibrary(const char* shared_lib, const char* prefix, MallocDispatch* dispatch_table) {
+ void* impl_handle = dlopen(shared_lib, RTLD_NOW | RTLD_LOCAL);
+ if (impl_handle == nullptr) {
+ error_log("%s: Unable to open shared library %s: %s", getprogname(), shared_lib, dlerror());
return nullptr;
}
+ if (!InitSharedLibrary(impl_handle, shared_lib, prefix, dispatch_table)) {
+ dlclose(impl_handle);
+ impl_handle = nullptr;
+ }
+
return impl_handle;
}
// A function pointer to heapprofds init function. Used to re-initialize
// heapprofd. This will start a new profiling session and tear down the old
// one in case it is still active.
-static _Atomic init_func_t g_heapprofd_init_func = nullptr;
+static _Atomic (void*) g_heapprofd_handle = nullptr;
static void install_hooks(libc_globals* globals, const char* options,
const char* prefix, const char* shared_lib) {
- init_func_t init_func = atomic_load(&g_heapprofd_init_func);
- if (init_func != nullptr) {
- init_func(&__libc_malloc_default_dispatch, &gMallocLeakZygoteChild, options);
- info_log("%s: malloc %s re-enabled", getprogname(), prefix);
- return;
- }
-
MallocDispatch dispatch_table;
- void* impl_handle = LoadSharedLibrary(shared_lib, prefix, &dispatch_table);
- if (impl_handle == nullptr) {
- return;
+
+ void* impl_handle = atomic_load(&g_heapprofd_handle);
+ if (impl_handle != nullptr) {
+ if (!InitSharedLibrary(impl_handle, shared_lib, prefix, &dispatch_table)) {
+ return;
+ }
+ } else {
+ impl_handle = LoadSharedLibrary(shared_lib, prefix, &dispatch_table);
+ if (impl_handle == nullptr) {
+ return;
+ }
}
- init_func = reinterpret_cast<init_func_t>(g_functions[FUNC_INITIALIZE]);
+ init_func_t init_func = reinterpret_cast<init_func_t>(g_functions[FUNC_INITIALIZE]);
if (!init_func(&__libc_malloc_default_dispatch, &gMallocLeakZygoteChild, options)) {
+ error_log("%s: failed to enable malloc %s", getprogname(), prefix);
dlclose(impl_handle);
ClearGlobalFunctions();
return;
}
- atomic_store(&g_heapprofd_init_func, init_func);
// We assign free first explicitly to prevent the case where we observe a
// alloc, but miss the corresponding free because of initialization order.
//
@@ -636,6 +643,7 @@
// _Atomic. Assigning to an _Atomic is an atomic_store operation.
// The assignment is done in declaration order.
globals->malloc_dispatch = dispatch_table;
+ atomic_store(&g_heapprofd_handle, impl_handle);
info_log("%s: malloc %s enabled", getprogname(), prefix);
@@ -761,6 +769,18 @@
// =============================================================================
#if !defined(LIBC_STATIC)
+bool MallocDispatchReset() {
+ if (!atomic_exchange(&g_heapprofd_init_in_progress, true)) {
+ __libc_globals.mutate([](libc_globals* globals) {
+ globals->malloc_dispatch = __libc_malloc_default_dispatch;
+ });
+ atomic_store(&g_heapprofd_init_in_progress, false);
+ return true;
+ }
+ errno = EAGAIN;
+ return false;
+}
+
// Marks this process as a profileable zygote child.
bool HandleInitZygoteChildProfiling() {
atomic_store_explicit(&gMallocZygoteChildProfileable, true,
@@ -777,6 +797,10 @@
#else
+bool MallocDispatchReset() {
+ return true;
+}
+
bool HandleInitZygoteChildProfiling() {
return true;
}
@@ -791,6 +815,13 @@
}
return HandleInitZygoteChildProfiling();
}
+ if (opcode == M_RESET_HOOKS) {
+ if (arg != nullptr || arg_size != 0) {
+ errno = EINVAL;
+ return false;
+ }
+ return MallocDispatchReset();
+ }
errno = ENOTSUP;
return false;
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index d80906c..b8784b8 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -44,6 +44,7 @@
#include "private/bionic_globals.h"
#include "private/bionic_macros.h"
#include "private/bionic_ssp.h"
+#include "private/bionic_systrace.h"
#include "private/bionic_tls.h"
#include "private/ErrnoRestorer.h"
@@ -347,6 +348,7 @@
ErrnoRestorer errno_restorer;
pthread_attr_t thread_attr;
+ ScopedTrace trace("pthread_create");
if (attr == nullptr) {
pthread_attr_init(&thread_attr);
} else {
diff --git a/libc/bionic/pthread_join.cpp b/libc/bionic/pthread_join.cpp
index 9aad458..8e4ca59 100644
--- a/libc/bionic/pthread_join.cpp
+++ b/libc/bionic/pthread_join.cpp
@@ -30,10 +30,12 @@
#include "private/bionic_defs.h"
#include "private/bionic_futex.h"
+#include "private/bionic_systrace.h"
#include "pthread_internal.h"
__BIONIC_WEAK_FOR_NATIVE_BRIDGE
int pthread_join(pthread_t t, void** return_value) {
+ ScopedTrace trace("pthread_join");
if (t == pthread_self()) {
return EDEADLK;
}
diff --git a/libc/private/bionic_malloc.h b/libc/private/bionic_malloc.h
index a9fa22d..5f4a75d 100644
--- a/libc/private/bionic_malloc.h
+++ b/libc/private/bionic_malloc.h
@@ -32,11 +32,13 @@
// Opcodes for android_mallopt.
-// Marks the calling process as a profileable zygote child, possibly
-// initializing profiling infrastructure.
enum {
+ // Marks the calling process as a profileable zygote child, possibly
+ // initializing profiling infrastructure.
M_INIT_ZYGOTE_CHILD_PROFILING = 1,
#define M_INIT_ZYGOTE_CHILD_PROFILING M_INIT_ZYGOTE_CHILD_PROFILING
+ M_RESET_HOOKS = 2,
+#define M_RESET_HOOKS M_RESET_HOOKS
};
// Manipulates bionic-specific handling of memory allocation APIs such as
diff --git a/libc/symbol_ordering b/libc/symbol_ordering
index 5b365f0..b672b35 100644
--- a/libc/symbol_ordering
+++ b/libc/symbol_ordering
@@ -86,7 +86,6 @@
__realloc_hook
__free_hook
__memalign_hook
-_ZL21g_heapprofd_init_func
je_malloc_conf
malloc_initializer
a0
diff --git a/tests/Android.bp b/tests/Android.bp
index b979f32..b374c27 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -384,7 +384,7 @@
"libdl_test.cpp",
],
static_libs: [
- "libpagemap",
+ "libmeminfo",
"libziparchive",
"libLLVMObject",
"libLLVMBitReader",
@@ -469,7 +469,7 @@
static_libs: [
// The order of these libraries matters, do not shuffle them.
"libbase",
- "libpagemap",
+ "libmeminfo",
"libziparchive",
"libz",
"libutils",
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 34013a7..c9ecd2e 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -36,7 +36,7 @@
#include <sys/vfs.h>
#include <sys/wait.h>
-#include <pagemap/pagemap.h>
+#include <meminfo/procmeminfo.h>
#include <ziparchive/zip_archive.h>
#include "gtest_globals.h"
@@ -488,33 +488,23 @@
void GetPss(bool shared_relro, const char* lib, const char* relro_file, pid_t pid,
size_t* total_pss) {
- pm_kernel_t* kernel;
- ASSERT_EQ(0, pm_kernel_create(&kernel));
-
- pm_process_t* process;
- ASSERT_EQ(0, pm_process_create(kernel, pid, &process));
-
- pm_map_t** maps;
- size_t num_maps;
- ASSERT_EQ(0, pm_process_maps(process, &maps, &num_maps));
+ android::meminfo::ProcMemInfo proc_mem(pid);
+ const std::vector<android::meminfo::Vma>& maps = proc_mem.Maps();
+ ASSERT_GT(maps.size(), 0UL);
// Calculate total PSS of the library.
*total_pss = 0;
bool saw_relro_file = false;
- for (size_t i = 0; i < num_maps; ++i) {
- if (android::base::EndsWith(maps[i]->name, lib) || strcmp(maps[i]->name, relro_file) == 0) {
- if (strcmp(maps[i]->name, relro_file) == 0) saw_relro_file = true;
+ for (auto& vma : maps) {
+ if (android::base::EndsWith(vma.name, lib) || (vma.name == relro_file)) {
+ if (vma.name == relro_file) {
+ saw_relro_file = true;
+ }
- pm_memusage_t usage;
- ASSERT_EQ(0, pm_map_usage(maps[i], &usage));
- *total_pss += usage.pss;
+ *total_pss += vma.usage.pss;
}
}
- free(maps);
- pm_process_destroy(process);
- pm_kernel_destroy(kernel);
-
if (shared_relro) ASSERT_TRUE(saw_relro_file);
}
diff --git a/tests/headers/posix/signal_h.c b/tests/headers/posix/signal_h.c
index 661b55e..c2e544e 100644
--- a/tests/headers/posix/signal_h.c
+++ b/tests/headers/posix/signal_h.c
@@ -53,7 +53,7 @@
STRUCT_MEMBER(struct sigevent, int, sigev_signo);
STRUCT_MEMBER(struct sigevent, union sigval, sigev_value);
STRUCT_MEMBER_FUNCTION_POINTER(struct sigevent, void (*f)(union sigval), sigev_notify_function);
-#if defined(__BIONIC__) || defined(__GLIBC__)
+#if defined(__BIONIC__)
STRUCT_MEMBER(struct sigevent, void*, sigev_notify_attributes);
#else
STRUCT_MEMBER(struct sigevent, pthread_attr_t*, sigev_notify_attributes);
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 1c57264..9c6b975 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <sys/mman.h>
#include <sys/prctl.h>
+#include <sys/resource.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>