Merge "Add DF_1_ORIGIN to SUPPORTED_DT_FLAGS_1."
diff --git a/benchmarks/spawn/Android.bp b/benchmarks/spawn/Android.bp
index 89d22e3..61e7bf6 100644
--- a/benchmarks/spawn/Android.bp
+++ b/benchmarks/spawn/Android.bp
@@ -43,6 +43,9 @@
linux_glibc_x86: {
enabled: false,
},
+ linux_musl_x86: {
+ enabled: false,
+ },
},
}
@@ -103,6 +106,11 @@
"-Wl,--rpath,${ORIGIN}/../../lib64",
],
},
+ linux_musl_x86_64: {
+ ldflags: [
+ "-Wl,--rpath,${ORIGIN}/../../lib64",
+ ],
+ },
},
}
diff --git a/libc/Android.bp b/libc/Android.bp
index f132669..7175c77 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1724,7 +1724,7 @@
// special for arm
cflags: ["-DCRT_LEGACY_WORKAROUND"],
// For backwards-compatibility, some arm32 builtins are exported from libc.so.
- static_libs: ["libclang_rt.builtins-arm-android-exported"],
+ static_libs: ["libclang_rt.builtins-exported"],
},
// Arm 32 bit does not produce complete exidx unwind information
@@ -1754,7 +1754,7 @@
shared: {
// For backwards-compatibility, some x86 builtins are exported from libc.so.
- static_libs: ["libclang_rt.builtins-i686-android-exported"],
+ static_libs: ["libclang_rt.builtins-exported"],
},
// Leave the symbols in the shared library so that stack unwinders can produce
@@ -2615,10 +2615,6 @@
stl: "none",
}
-subdirs = [
- "bionic/scudo",
-]
-
// Export kernel uapi headers to be used in the musl sysroot.
// Also include the execinfo headers for the libexecinfo and the
// b64 headers for libb64 embedded in musl libc.
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 08fb187..121b26f 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -45,7 +45,6 @@
#include "private/bionic_defs.h"
#include "private/bionic_globals.h"
#include "platform/bionic/macros.h"
-#include "platform/bionic/pac.h"
#include "private/bionic_ssp.h"
#include "private/bionic_systrace.h"
#include "private/bionic_tls.h"
@@ -332,9 +331,11 @@
extern "C" int __rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t);
__attribute__((no_sanitize("hwaddress")))
+#ifdef __aarch64__
// This function doesn't return, but it does appear in stack traces. Avoid using return PAC in this
// function because we may end up resetting IA, which may confuse unwinders due to mismatching keys.
-__BIONIC_DISABLE_PAUTH
+__attribute__((target("branch-protection=bti")))
+#endif
static int __pthread_start(void* arg) {
pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(arg);
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp
index 90c9136..b982c0a 100644
--- a/libc/malloc_debug/PointerData.cpp
+++ b/libc/malloc_debug/PointerData.cpp
@@ -66,7 +66,8 @@
std::unordered_map<FrameKeyType, size_t> PointerData::key_to_index_ GUARDED_BY(
PointerData::frame_mutex_);
std::unordered_map<size_t, FrameInfoType> PointerData::frames_ GUARDED_BY(PointerData::frame_mutex_);
-std::unordered_map<size_t, std::vector<unwindstack::LocalFrameData>> PointerData::backtraces_info_ GUARDED_BY(PointerData::frame_mutex_);
+std::unordered_map<size_t, std::vector<unwindstack::FrameData>> PointerData::backtraces_info_
+ GUARDED_BY(PointerData::frame_mutex_);
constexpr size_t kBacktraceEmptyIndex = 1;
size_t PointerData::cur_hash_index_ GUARDED_BY(PointerData::frame_mutex_);
@@ -136,7 +137,7 @@
size_t PointerData::AddBacktrace(size_t num_frames) {
std::vector<uintptr_t> frames;
- std::vector<unwindstack::LocalFrameData> frames_info;
+ std::vector<unwindstack::FrameData> frames_info;
if (g_debug->config().options() & BACKTRACE_FULL) {
if (!Unwind(&frames, &frames_info, num_frames)) {
return kBacktraceEmptyIndex;
@@ -386,7 +387,7 @@
REQUIRES(pointer_mutex_, frame_mutex_) {
for (const auto& entry : pointers_) {
FrameInfoType* frame_info = nullptr;
- std::vector<unwindstack::LocalFrameData>* backtrace_info = nullptr;
+ std::vector<unwindstack::FrameData>* backtrace_info = nullptr;
size_t hash_index = entry.second.hash_index;
if (hash_index > kBacktraceEmptyIndex) {
auto frame_entry = frames_.find(hash_index);
diff --git a/libc/malloc_debug/PointerData.h b/libc/malloc_debug/PointerData.h
index 37d87db..92d2653 100644
--- a/libc/malloc_debug/PointerData.h
+++ b/libc/malloc_debug/PointerData.h
@@ -39,7 +39,7 @@
#include <vector>
#include <platform/bionic/macros.h>
-#include <unwindstack/LocalUnwinder.h>
+#include <unwindstack/Unwinder.h>
#include "OptionData.h"
#include "UnwindBacktrace.h"
@@ -109,7 +109,7 @@
size_t size;
bool zygote_child_alloc;
FrameInfoType* frame_info;
- std::vector<unwindstack::LocalFrameData>* backtrace_info;
+ std::vector<unwindstack::FrameData>* backtrace_info;
};
class PointerData : public OptionData {
@@ -181,7 +181,7 @@
static std::mutex frame_mutex_;
static std::unordered_map<FrameKeyType, size_t> key_to_index_;
static std::unordered_map<size_t, FrameInfoType> frames_;
- static std::unordered_map<size_t, std::vector<unwindstack::LocalFrameData>> backtraces_info_;
+ static std::unordered_map<size_t, std::vector<unwindstack::FrameData>> backtraces_info_;
static size_t cur_hash_index_;
static std::mutex free_pointer_mutex_;
diff --git a/libc/malloc_debug/README.md b/libc/malloc_debug/README.md
index da26d15..662f5f8 100644
--- a/libc/malloc_debug/README.md
+++ b/libc/malloc_debug/README.md
@@ -641,6 +641,13 @@
for the best way to use malloc debug in Android O or later on non-rooted
devices.
+**NOTE**: Android 12 introduced a bug that can cause the wrap.\<APP\> property to
+no longer work. Use the commands below so that the wrap.\<APP\> instructions will work:
+
+ adb shell setprop dalvik.vm.force-java-zygote-fork-loop true
+ adb shell stop
+ adb shell start
+
If you do have a rooted device, you can enable malloc debug for a specific
program/application (Android O or later):
diff --git a/libc/malloc_debug/UnwindBacktrace.cpp b/libc/malloc_debug/UnwindBacktrace.cpp
index a7036d9..f6c3e69 100644
--- a/libc/malloc_debug/UnwindBacktrace.cpp
+++ b/libc/malloc_debug/UnwindBacktrace.cpp
@@ -36,8 +36,12 @@
#include <vector>
#include <android-base/stringprintf.h>
-#include <unwindstack/LocalUnwinder.h>
#include <unwindstack/MapInfo.h>
+#include <unwindstack/Maps.h>
+#include <unwindstack/Memory.h>
+#include <unwindstack/Regs.h>
+#include <unwindstack/RegsGetLocal.h>
+#include <unwindstack/Unwinder.h>
#include "UnwindBacktrace.h"
#include "debug_log.h"
@@ -52,42 +56,56 @@
static pthread_once_t g_setup_once = PTHREAD_ONCE_INIT;
-static unwindstack::LocalUnwinder* g_unwinder;
-
-static void Setup() {
+static unwindstack::LocalUpdatableMaps* g_maps;
+static std::shared_ptr<unwindstack::Memory> g_process_memory;
#if defined(__LP64__)
- std::vector<std::string> skip_libraries{"/system/lib64/libunwindstack.so", "/system/lib64/libc_malloc_debug.so"};
+static std::vector<std::string> g_skip_libraries{"/system/lib64/libunwindstack.so",
+ "/system/lib64/libc_malloc_debug.so"};
#else
- std::vector<std::string> skip_libraries{"/system/lib/libunwindstack.so", "/system/lib/libc_malloc_debug.so"};
+static std::vector<std::string> g_skip_libraries{"/system/lib/libunwindstack.so",
+ "/system/lib/libc_malloc_debug.so"};
#endif
- g_unwinder = new unwindstack::LocalUnwinder(skip_libraries);
- g_unwinder->Init();
+static void Setup() {
+ g_maps = new unwindstack::LocalUpdatableMaps;
+ if (!g_maps->Parse()) {
+ delete g_maps;
+ g_maps = nullptr;
+ }
+
+ g_process_memory = unwindstack::Memory::CreateProcessMemoryThreadCached(getpid());
}
-bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::LocalFrameData>* frame_info, size_t max_frames) {
+bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::FrameData>* frame_info,
+ size_t max_frames) {
pthread_once(&g_setup_once, Setup);
- if (g_unwinder == nullptr) {
+ if (g_maps == nullptr) {
return false;
}
- if (!g_unwinder->Unwind(frame_info, max_frames)) {
+ std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
+ unwindstack::RegsGetLocal(regs.get());
+ unwindstack::Unwinder unwinder(max_frames, g_maps, regs.get(), g_process_memory);
+ unwinder.Unwind(&g_skip_libraries);
+ if (unwinder.NumFrames() == 0) {
frames->clear();
frame_info->clear();
return false;
}
+ *frame_info = unwinder.ConsumeFrames();
- for (const auto& frame : *frame_info) {
- frames->push_back(frame.pc);
+ frames->resize(frame_info->size());
+ for (size_t i = 0; i < frame_info->size(); i++) {
+ frames->at(i) = frame_info->at(i).pc;
}
return true;
}
-void UnwindLog(const std::vector<unwindstack::LocalFrameData>& frame_info) {
+void UnwindLog(const std::vector<unwindstack::FrameData>& frame_info) {
for (size_t i = 0; i < frame_info.size(); i++) {
- const unwindstack::LocalFrameData* info = &frame_info[i];
- std::shared_ptr<unwindstack::MapInfo> map_info = info->map_info;
+ const unwindstack::FrameData* info = &frame_info[i];
+ auto map_info = info->map_info;
std::string line = android::base::StringPrintf(" #%0zd pc %" PAD_PTR " ", i, info->rel_pc);
if (map_info != nullptr && map_info->offset() != 0) {
diff --git a/libc/malloc_debug/UnwindBacktrace.h b/libc/malloc_debug/UnwindBacktrace.h
index 4c6c8d4..7f89907 100644
--- a/libc/malloc_debug/UnwindBacktrace.h
+++ b/libc/malloc_debug/UnwindBacktrace.h
@@ -33,9 +33,10 @@
#include <string>
#include <vector>
-#include <unwindstack/LocalUnwinder.h>
#include <unwindstack/MapInfo.h>
+#include <unwindstack/Unwinder.h>
-bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::LocalFrameData>* info, size_t max_frames);
+bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::FrameData>* info,
+ size_t max_frames);
-void UnwindLog(const std::vector<unwindstack::LocalFrameData>& frame_info);
+void UnwindLog(const std::vector<unwindstack::FrameData>& frame_info);
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index d23ab15..9f38946 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -49,6 +49,7 @@
#include <platform/bionic/reserved_signals.h>
#include <private/MallocXmlElem.h>
#include <private/bionic_malloc_dispatch.h>
+#include <unwindstack/Unwinder.h>
#include "Config.h"
#include "DebugData.h"
@@ -193,7 +194,7 @@
void BacktraceAndLog() {
if (g_debug->config().options() & BACKTRACE_FULL) {
std::vector<uintptr_t> frames;
- std::vector<unwindstack::LocalFrameData> frames_info;
+ std::vector<unwindstack::FrameData> frames_info;
if (!Unwind(&frames, &frames_info, 256)) {
error_log(" Backtrace failed to get any frames.");
} else {
diff --git a/libc/malloc_debug/tests/backtrace_fake.cpp b/libc/malloc_debug/tests/backtrace_fake.cpp
index ad16c02..f54bae8 100644
--- a/libc/malloc_debug/tests/backtrace_fake.cpp
+++ b/libc/malloc_debug/tests/backtrace_fake.cpp
@@ -20,7 +20,7 @@
#include <vector>
#include <utility>
-#include <unwindstack/LocalUnwinder.h>
+#include <unwindstack/Unwinder.h>
#include "backtrace.h"
#include "backtrace_fake.h"
@@ -60,17 +60,17 @@
}
}
-static std::deque<std::vector<unwindstack::LocalFrameData>> g_fake_local_frame_data;
+static std::deque<std::vector<unwindstack::FrameData>> g_fake_local_frame_data;
void BacktraceUnwindFakeClearAll() {
g_fake_local_frame_data.clear();
}
-void BacktraceUnwindFake(const std::vector<unwindstack::LocalFrameData>& frames) {
+void BacktraceUnwindFake(const std::vector<unwindstack::FrameData>& frames) {
g_fake_local_frame_data.push_back(frames);
}
-bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::LocalFrameData>* info, size_t) {
+bool Unwind(std::vector<uintptr_t>* frames, std::vector<unwindstack::FrameData>* info, size_t) {
if (g_fake_local_frame_data.empty()) {
return false;
}
@@ -85,5 +85,4 @@
return true;
}
-void UnwindLog(const std::vector<unwindstack::LocalFrameData>& /*frame_info*/) {
-}
+void UnwindLog(const std::vector<unwindstack::FrameData>& /*frame_info*/) {}
diff --git a/libc/malloc_debug/tests/backtrace_fake.h b/libc/malloc_debug/tests/backtrace_fake.h
index a9ee97d..246fc61 100644
--- a/libc/malloc_debug/tests/backtrace_fake.h
+++ b/libc/malloc_debug/tests/backtrace_fake.h
@@ -21,12 +21,12 @@
#include <vector>
-#include <unwindstack/LocalUnwinder.h>
+#include <unwindstack/Unwinder.h>
void backtrace_fake_clear_all();
void backtrace_fake_add(const std::vector<uintptr_t>& ips);
void BacktraceUnwindFakeClearAll();
-void BacktraceUnwindFake(const std::vector<unwindstack::LocalFrameData>& frames);
+void BacktraceUnwindFake(const std::vector<unwindstack::FrameData>& frames);
#endif // MALLOC_DEBUG_TESTS_BACKTRACE_FAKE_H
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 7b58f31..46de3e9 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -44,6 +44,8 @@
#include <platform/bionic/macros.h>
#include <private/bionic_malloc_dispatch.h>
+#include <unwindstack/Unwinder.h>
+
#include "Config.h"
#include "malloc_debug.h"
@@ -1530,16 +1532,18 @@
if ((pid = fork()) == 0) {
std::shared_ptr<unwindstack::MapInfo> empty_map;
Init("backtrace=4 backtrace_full backtrace_dump_on_exit");
- BacktraceUnwindFake(std::vector<unwindstack::LocalFrameData>{
- {empty_map, 0x1100, 0x100, "fake1", 10}, {empty_map, 0x1200, 0x200, "fake2", 20}});
+ BacktraceUnwindFake(
+ std::vector<unwindstack::FrameData>{{0, 0x100, 0x1100, 0, "fake1", 10, empty_map},
+ {1, 0x200, 0x1200, 0, "fake2", 20, empty_map}});
std::shared_ptr<unwindstack::MapInfo> map_info =
unwindstack::MapInfo::Create(0x10000, 0x20000, 0, PROT_READ | PROT_EXEC, "/data/fake.so");
- BacktraceUnwindFake(std::vector<unwindstack::LocalFrameData>{
- {map_info, 0x1a000, 0xa000, "level1", 0}, {map_info, 0x1b000, 0xb000, "level2", 10}});
BacktraceUnwindFake(
- std::vector<unwindstack::LocalFrameData>{{empty_map, 0x1a000, 0xa000, "func1", 0},
- {empty_map, 0x1b000, 0xb000, "func2", 10},
- {empty_map, 0x1c000, 0xc000, "", 30}});
+ std::vector<unwindstack::FrameData>{{0, 0xa000, 0x1a000, 0, "level1", 0, map_info},
+ {1, 0xb000, 0x1b000, 0, "level2", 10, map_info}});
+ BacktraceUnwindFake(
+ std::vector<unwindstack::FrameData>{{0, 0xa000, 0x1a000, 0, "func1", 0, empty_map},
+ {1, 0xb000, 0x1b000, 0, "func2", 10, empty_map},
+ {2, 0xc000, 0x1c000, 0, "", 30, empty_map}});
std::vector<void*> pointers;
pointers.push_back(debug_malloc(300));
diff --git a/libc/platform/bionic/pac.h b/libc/platform/bionic/pac.h
index c311651..34efc48 100644
--- a/libc/platform/bionic/pac.h
+++ b/libc/platform/bionic/pac.h
@@ -29,7 +29,6 @@
#pragma once
#include <stddef.h>
-#include <sys/prctl.h>
inline uintptr_t __bionic_clear_pac_bits(uintptr_t ptr) {
#if defined(__aarch64__)
@@ -41,39 +40,3 @@
return ptr;
#endif
}
-
-#ifdef __aarch64__
-// The default setting for branch-protection enables both PAC and BTI, so by
-// overriding it to only enable BTI we disable PAC.
-#define __BIONIC_DISABLE_PAUTH __attribute__((target("branch-protection=bti")))
-#else
-#define __BIONIC_DISABLE_PAUTH
-#endif
-
-#ifdef __aarch64__
-// Disable PAC (i.e. make the signing and authentication instructions into no-ops) for the lifetime
-// of this object.
-class ScopedDisablePAC {
- int prev_enabled_keys_;
-
- public:
- // Disabling IA will invalidate the return address in this function if it is signed, so we need to
- // make sure that this function does not sign its return address. Likewise for the destructor.
- __BIONIC_DISABLE_PAUTH
- ScopedDisablePAC() {
- // These prctls will fail (resulting in a no-op, the intended behavior) if PAC is not supported.
- prev_enabled_keys_ = prctl(PR_PAC_GET_ENABLED_KEYS, 0, 0, 0, 0);
- prctl(PR_PAC_SET_ENABLED_KEYS, prev_enabled_keys_, 0, 0, 0);
- }
-
- __BIONIC_DISABLE_PAUTH
- ~ScopedDisablePAC() {
- prctl(PR_PAC_SET_ENABLED_KEYS, prev_enabled_keys_, prev_enabled_keys_, 0, 0);
- }
-};
-#else
-struct ScopedDisablePAC {
- // Silence unused variable warnings in non-aarch64 builds.
- ScopedDisablePAC() {}
-};
-#endif
diff --git a/libfdtrack/Android.bp b/libfdtrack/Android.bp
index fb28623..83ea7cb 100644
--- a/libfdtrack/Android.bp
+++ b/libfdtrack/Android.bp
@@ -38,4 +38,5 @@
whole_static_libs: ["libBionicCtsGtestMain"],
static_libs: ["liblog"],
test_suites: ["device-tests"],
+ runtime_libs: ["libfdtrack"],
}
diff --git a/libfdtrack/fdtrack.cpp b/libfdtrack/fdtrack.cpp
index 2e9cfbc..2d114f2 100644
--- a/libfdtrack/fdtrack.cpp
+++ b/libfdtrack/fdtrack.cpp
@@ -31,6 +31,8 @@
#include <array>
#include <mutex>
+#include <string>
+#include <string_view>
#include <thread>
#include <utility>
#include <vector>
@@ -43,11 +45,14 @@
#include <android-base/thread_annotations.h>
#include <async_safe/log.h>
#include <bionic/reserved_signals.h>
-#include <unwindstack/LocalUnwinder.h>
+#include <unwindstack/Maps.h>
+#include <unwindstack/Regs.h>
+#include <unwindstack/RegsGetLocal.h>
+#include <unwindstack/Unwinder.h>
struct FdEntry {
std::mutex mutex;
- std::vector<unwindstack::LocalFrameData> backtrace GUARDED_BY(mutex);
+ std::vector<unwindstack::FrameData> backtrace GUARDED_BY(mutex);
};
extern "C" void fdtrack_dump();
@@ -62,15 +67,21 @@
// Backtraces for the first 4k file descriptors ought to be enough to diagnose an fd leak.
static constexpr size_t kFdTableSize = 4096;
-// 32 frames, plus two to skip from fdtrack itself.
-static constexpr size_t kStackDepth = 34;
-static constexpr size_t kStackFrameSkip = 2;
+// Only unwind up to 32 frames outside of libfdtrack.so.
+static constexpr size_t kStackDepth = 32;
+
+// Skip any initial frames from libfdtrack.so.
+static std::vector<std::string> kSkipFdtrackLib [[clang::no_destroy]] = {"libfdtrack.so"};
static bool installed = false;
static std::array<FdEntry, kFdTableSize> stack_traces [[clang::no_destroy]];
-static unwindstack::LocalUnwinder& Unwinder() {
- static android::base::NoDestructor<unwindstack::LocalUnwinder> unwinder;
- return *unwinder.get();
+static unwindstack::LocalUpdatableMaps& Maps() {
+ static android::base::NoDestructor<unwindstack::LocalUpdatableMaps> maps;
+ return *maps.get();
+}
+static std::shared_ptr<unwindstack::Memory>& ProcessMemory() {
+ static android::base::NoDestructor<std::shared_ptr<unwindstack::Memory>> process_memory;
+ return *process_memory.get();
}
__attribute__((constructor)) static void ctor() {
@@ -89,7 +100,8 @@
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
sigaction(BIONIC_SIGNAL_FDTRACK, &sa, nullptr);
- if (Unwinder().Init()) {
+ if (Maps().Parse()) {
+ ProcessMemory() = unwindstack::Memory::CreateProcessMemoryThreadCached(getpid());
android_fdtrack_hook_t expected = nullptr;
installed = android_fdtrack_compare_exchange_hook(&expected, &fd_hook);
}
@@ -116,7 +128,12 @@
if (FdEntry* entry = GetFdEntry(event->fd); entry) {
std::lock_guard<std::mutex> lock(entry->mutex);
entry->backtrace.clear();
- Unwinder().Unwind(&entry->backtrace, kStackDepth);
+
+ std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
+ unwindstack::RegsGetLocal(regs.get());
+ unwindstack::Unwinder unwinder(kStackDepth, &Maps(), regs.get(), ProcessMemory());
+ unwinder.Unwind(&kSkipFdtrackLib);
+ entry->backtrace = unwinder.ConsumeFrames();
}
} else if (event->type == ANDROID_FDTRACK_EVENT_TYPE_CLOSE) {
if (FdEntry* entry = GetFdEntry(event->fd); entry) {
@@ -153,14 +170,13 @@
continue;
}
- for (size_t i = kStackFrameSkip; i < entry->backtrace.size(); ++i) {
- size_t j = i - kStackFrameSkip;
- function_names[j] = entry->backtrace[i].function_name.c_str();
- function_offsets[j] = entry->backtrace[i].function_offset;
+ for (size_t i = 0; i < entry->backtrace.size(); ++i) {
+ function_names[i] = entry->backtrace[i].function_name.c_str();
+ function_offsets[i] = entry->backtrace[i].function_offset;
}
- bool should_continue = callback(fd, function_names, function_offsets,
- entry->backtrace.size() - kStackFrameSkip, arg);
+ bool should_continue =
+ callback(fd, function_names, function_offsets, entry->backtrace.size(), arg);
entry->mutex.unlock();
@@ -200,8 +216,8 @@
size_t count = 0;
size_t stack_depth = 0;
- const char* function_names[kStackDepth - kStackFrameSkip];
- uint64_t function_offsets[kStackDepth - kStackFrameSkip];
+ const char* function_names[kStackDepth];
+ uint64_t function_offsets[kStackDepth];
};
struct StackList {
size_t count = 0;
diff --git a/libm/Android.bp b/libm/Android.bp
index 43d82d5..5622e8c 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -307,7 +307,7 @@
no_libcrt: true,
shared: {
// For backwards-compatibility, some arm32 builtins are exported from libm.so.
- static_libs: ["libclang_rt.builtins-arm-android-exported"],
+ static_libs: ["libclang_rt.builtins-exported"],
},
},
diff --git a/linker/Android.bp b/linker/Android.bp
index dbefcf6..d5e7367 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -28,16 +28,11 @@
name: "linker_wrapper",
host_supported: true,
device_supported: false,
+ enabled: false,
target: {
linux_bionic: {
enabled: true,
},
- linux_glibc: {
- enabled: false,
- },
- darwin: {
- enabled: false,
- },
},
cflags: [
diff --git a/tests/heap_tagging_level_test.cpp b/tests/heap_tagging_level_test.cpp
index cfb2490..c493e1d 100644
--- a/tests/heap_tagging_level_test.cpp
+++ b/tests/heap_tagging_level_test.cpp
@@ -81,10 +81,20 @@
#endif // defined(__BIONIC__)
}
+namespace {
#if defined(__BIONIC__) && defined(__aarch64__)
void ExitWithSiCode(int, siginfo_t* info, void*) {
_exit(info->si_code);
}
+
+template <typename Pred>
+class Or {
+ Pred A, B;
+
+ public:
+ Or(Pred A, Pred B) : A(A), B(B) {}
+ bool operator()(int exit_status) { return A(exit_status) || B(exit_status); }
+};
#endif
TEST(heap_tagging_level, sync_async_bad_accesses_die) {
@@ -94,6 +104,7 @@
}
std::unique_ptr<int[]> p = std::make_unique<int[]>(4);
+ volatile int sink ATTRIBUTE_UNUSED;
// We assume that scudo is used on all MTE enabled hardware; scudo inserts a header with a
// mismatching tag before each allocation.
@@ -104,6 +115,12 @@
p[-1] = 42;
},
testing::ExitedWithCode(SEGV_MTESERR), "");
+ EXPECT_EXIT(
+ {
+ ScopedSignalHandler ssh(SIGSEGV, ExitWithSiCode, SA_SIGINFO);
+ sink = p[-1];
+ },
+ testing::ExitedWithCode(SEGV_MTESERR), "");
EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC));
EXPECT_EXIT(
@@ -111,14 +128,21 @@
ScopedSignalHandler ssh(SIGSEGV, ExitWithSiCode, SA_SIGINFO);
p[-1] = 42;
},
- testing::ExitedWithCode(SEGV_MTEAERR), "");
+ Or(testing::ExitedWithCode(SEGV_MTESERR), testing::ExitedWithCode(SEGV_MTEAERR)), "");
+ EXPECT_EXIT(
+ {
+ ScopedSignalHandler ssh(SIGSEGV, ExitWithSiCode, SA_SIGINFO);
+ sink = p[-1];
+ },
+ Or(testing::ExitedWithCode(SEGV_MTESERR), testing::ExitedWithCode(SEGV_MTEAERR)), "");
EXPECT_TRUE(SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_NONE));
- volatile int oob ATTRIBUTE_UNUSED = p[-1];
+ sink = p[-1];
#else
GTEST_SKIP() << "bionic/arm64 only";
#endif
}
+} // namespace
TEST(heap_tagging_level, none_pointers_untagged) {
#if defined(__BIONIC__)
@@ -205,7 +229,9 @@
const char* kNoteSuffix[] = {"disabled", "async", "sync"};
const char* kExpectedOutputHWASAN[] = {".*tag-mismatch.*", ".*tag-mismatch.*",
".*tag-mismatch.*"};
- const char* kExpectedOutputMTE[] = {"normal exit\n", "SEGV_MTEAERR\n", "SEGV_MTESERR\n"};
+ // Note that we do not check the exact si_code of the "async" variant, as it may be auto-upgraded
+ // to asymm or even sync.
+ const char* kExpectedOutputMTE[] = {"normal exit\n", "SEGV_MTE[AS]ERR\n", "SEGV_MTESERR\n"};
const char* kExpectedOutputNonMTE[] = {"normal exit\n", "normal exit\n", "normal exit\n"};
const char** kExpectedOutput =
withHWASAN ? kExpectedOutputHWASAN : (withMTE ? kExpectedOutputMTE : kExpectedOutputNonMTE);
@@ -215,7 +241,6 @@
bool isStatic = std::get<1>(GetParam());
std::string helper_base = std::string("heap_tagging_") + (isStatic ? "static_" : "") +
kNoteSuffix[static_cast<int>(note)] + "_helper";
- fprintf(stderr, "=== %s\n", helper_base.c_str());
std::string helper = GetTestlibRoot() + "/" + helper_base;
chmod(helper.c_str(), 0755);
ExecTestHelper eth;
diff --git a/tests/libs/heap_tagging_helper.cpp b/tests/libs/heap_tagging_helper.cpp
index 1a970f2..16a8c8b 100644
--- a/tests/libs/heap_tagging_helper.cpp
+++ b/tests/libs/heap_tagging_helper.cpp
@@ -16,7 +16,9 @@
#include <signal.h>
#include <stdio.h>
+#include <sys/auxv.h>
#include <sys/cdefs.h>
+#include <sys/mman.h>
#include <unistd.h>
#include <memory>
@@ -37,6 +39,11 @@
_exit(0);
}
+void action2(int signo, siginfo_t* info __unused, void*) {
+ fprintf(stderr, "unexpected signal %d\n", signo);
+ _exit(0);
+}
+
__attribute__((optnone)) int main() {
struct sigaction sa = {};
sa.sa_sigaction = action;
@@ -47,6 +54,37 @@
volatile int oob = p[-1];
(void)oob;
+#if defined(__BIONIC__) && defined(__aarch64__)
+ // If we get here, bad access on system heap memory did not trigger a fault.
+ // This suggests that MTE is disabled. Make sure that explicitly tagged PROT_MTE memory does not
+ // trigger a fault either.
+ if (getauxval(AT_HWCAP2) & HWCAP2_MTE) {
+ sa.sa_sigaction = action2;
+ sigaction(SIGSEGV, &sa, nullptr);
+
+ size_t page_size = static_cast<size_t>(sysconf(_SC_PAGESIZE));
+ void* p = mmap(nullptr, page_size, PROT_READ | PROT_WRITE | PROT_MTE,
+ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+ if (!p) {
+ fprintf(stderr, "mmap failed\n");
+ return 1;
+ }
+
+ void* q = p;
+ __asm__ __volatile__(
+ ".arch_extension memtag\n"
+ "irg %[Ptr], %[Ptr], xzr\n"
+ "stg %[Ptr], [%[Ptr]]\n"
+ "addg %[Ptr], %[Ptr], 0, 1\n"
+ "str xzr, [%[Ptr]]\n"
+ : [Ptr] "+&r"(q)
+ :
+ : "memory");
+
+ munmap(p, page_size);
+ }
+#endif // __aarch64__
+
fprintf(stderr, "normal exit\n");
return 0;
}
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index e38dd60..87031f6 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -364,10 +364,13 @@
TEST_F(STDIO_DEATHTEST, snprintf_n) {
#if defined(__BIONIC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat"
// http://b/14492135 and http://b/31832608.
char buf[32];
int i = 1234;
EXPECT_DEATH(snprintf(buf, sizeof(buf), "a %n b", &i), "%n not allowed on Android");
+#pragma GCC diagnostic pop
#else
GTEST_SKIP() << "glibc does allow %n";
#endif