Merge "CTS: allow continue to use the old AIDs on devices launch with P"
diff --git a/libc/arch-common/bionic/crtbrand.S b/libc/arch-common/bionic/crtbrand.S
index 4b4f99c..34d6480 100644
--- a/libc/arch-common/bionic/crtbrand.S
+++ b/libc/arch-common/bionic/crtbrand.S
@@ -33,7 +33,12 @@
.long 2f-1f // int32_t namesz
.long 3f-2f // int32_t descsz
.long 1 // int32_t type
+#ifdef __ANDROID__
1:.ascii "Android\0" // char name[]
2:.long PLATFORM_SDK_VERSION // int32_t android_api
+#else
+1:.ascii "LinuxBionic\0" // char name[]
+2:
+#endif
3:
.size abitag, .-abitag
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index 812884c..40f2a66 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -79,6 +79,18 @@
}
}
return 1;
+ } else if (param == M_PURGE) {
+ unsigned narenas;
+ size_t sz = sizeof(unsigned);
+ if (je_mallctl("arenas.narenas", &narenas, &sz, nullptr, 0) != 0) {
+ return 0;
+ }
+ char buffer[100];
+ snprintf(buffer, sizeof(buffer), "arena.%u.purge", narenas);
+ if (je_mallctl(buffer, nullptr, nullptr, nullptr, 0) != 0) {
+ return 0;
+ }
+ return 1;
}
return 0;
}
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index f5fbedf..58a9b1d 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -163,6 +163,7 @@
/** mallopt() option to set the decay time. Valid values are 0 and 1. */
#define M_DECAY_TIME -100
+#define M_PURGE -101
/**
* [mallopt(3)](http://man7.org/linux/man-pages/man3/mallopt.3.html) modifies
diff --git a/linker/linker.cpp b/linker/linker.cpp
index b605ed9..f085863 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1318,6 +1318,15 @@
}
}
+#if !defined(__ANDROID__)
+ // Bionic on the host currently uses some Android prebuilts, which don't set
+ // DT_RUNPATH with any relative paths, so they can't find their dependencies.
+ // b/118058804
+ if (si->get_dt_runpath().empty()) {
+ si->set_dt_runpath("$ORIGIN/../lib64:$ORIGIN/lib64");
+ }
+#endif
+
for_each_dt_needed(task->get_elf_reader(), [&](const char* name) {
load_tasks->push_back(LoadTask::create(name, si, ns, task->get_readers_map()));
});
diff --git a/linker/linker_wrapper.cpp b/linker/linker_wrapper.cpp
index 571d3ab..fc673aa 100644
--- a/linker/linker_wrapper.cpp
+++ b/linker/linker_wrapper.cpp
@@ -28,9 +28,27 @@
#include "private/KernelArgumentBlock.h"
-extern const char linker_code_start;
-extern const char original_start;
-extern const char linker_entry;
+extern const char linker_offset;
+
+// This will be replaced by host_bionic_inject, but must be non-zero
+// here so that it's placed in the data section.
+uintptr_t original_start = 42;
+
+/* Find the load bias and base address of an executable or shared object loaded
+ * by the kernel. The ELF file's PHDR table must have a PT_PHDR entry.
+ *
+ * A VDSO doesn't have a PT_PHDR entry in its PHDR table.
+ */
+static void get_elf_base_from_phdr(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+ ElfW(Addr)* base, ElfW(Addr)* load_bias) {
+ for (size_t i = 0; i < phdr_count; ++i) {
+ if (phdr_table[i].p_type == PT_PHDR) {
+ *load_bias = reinterpret_cast<ElfW(Addr)>(phdr_table) - phdr_table[i].p_vaddr;
+ *base = reinterpret_cast<ElfW(Addr)>(phdr_table) - phdr_table[i].p_offset;
+ return;
+ }
+ }
+}
/*
* This is the entry point for the linker wrapper, which finds
@@ -39,21 +57,26 @@
extern "C" ElfW(Addr) __linker_init(void* raw_args) {
KernelArgumentBlock args(raw_args);
- static uintptr_t linker_offset = reinterpret_cast<uintptr_t>(&linker_code_start);
- static uintptr_t linktime_addr = reinterpret_cast<uintptr_t>(&linktime_addr);
- ElfW(Addr) my_addr = reinterpret_cast<uintptr_t>(&linktime_addr) - linktime_addr;
+ ElfW(Addr) base_addr = 0;
+ ElfW(Addr) load_bias = 0;
+ get_elf_base_from_phdr(
+ reinterpret_cast<ElfW(Phdr)*>(args.getauxval(AT_PHDR)), args.getauxval(AT_PHNUM),
+ &base_addr, &load_bias);
- // Set AT_ENTRY to the proper entry point
+ ElfW(Addr) linker_addr = base_addr + reinterpret_cast<uintptr_t>(&linker_offset);
+ ElfW(Addr) linker_entry_offset = reinterpret_cast<ElfW(Ehdr)*>(linker_addr)->e_entry;
+
for (ElfW(auxv_t)* v = args.auxv; v->a_type != AT_NULL; ++v) {
if (v->a_type == AT_BASE) {
- v->a_un.a_val = my_addr + linker_offset;
+ // Set AT_BASE to the embedded linker
+ v->a_un.a_val = linker_addr;
}
if (v->a_type == AT_ENTRY) {
- v->a_un.a_val = my_addr + reinterpret_cast<uintptr_t>(&original_start);
+ // Set AT_ENTRY to the proper entry point
+ v->a_un.a_val = base_addr + original_start;
}
}
- // Return address of linker entry point -- may need to ensure that raw_args
- // was saved.
- return my_addr + linker_offset + reinterpret_cast<uintptr_t>(&linker_entry);
+ // Return address of linker entry point
+ return linker_addr + linker_entry_offset;
}