aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2021-06-09 16:33:12 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-06-09 16:33:12 +0000
commit07a37c4ba75e5c0317422583254e743d3404ec4c (patch)
treecdd69b84cc2f793888992f8fb76440dc2db17c72
parentd9a8756c70d014a1bc224348ec22574408289bde (diff)
parenteb5f5d8db6fcbda80ea3938627bcb1e8cc95666a (diff)
downloadbionic-07a37c4ba75e5c0317422583254e743d3404ec4c.tar.gz
Merge "Disable return PAC in __pthread_start." into sc-dev am: eb5f5d8db6
Original change: https://googleplex-android-review.googlesource.com/c/platform/bionic/+/14911776 Change-Id: I89177a114df75e6d05dea8c5a4f13b0db4839058
-rw-r--r--libc/bionic/pthread_create.cpp5
-rw-r--r--tests/stack_unwinding_test.cpp23
2 files changed, 24 insertions, 4 deletions
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 46d9e8672..121b26f82 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -331,6 +331,11 @@ void __set_stack_and_tls_vma_name(bool is_main_thread) {
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.
+__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/tests/stack_unwinding_test.cpp b/tests/stack_unwinding_test.cpp
index 0ff6f30a6..2f891a6e1 100644
--- a/tests/stack_unwinding_test.cpp
+++ b/tests/stack_unwinding_test.cpp
@@ -66,13 +66,28 @@ static int noinline unwind_one_frame_deeper() {
return count;
}
-TEST(stack_unwinding, easy) {
+static void UnwindTest() {
int count = 0;
_Unwind_Backtrace(FrameCounter, &count);
int deeper_count = unwind_one_frame_deeper();
ASSERT_EQ(count + 1, deeper_count);
}
+TEST(stack_unwinding, easy) {
+ UnwindTest();
+}
+
+TEST(stack_unwinding, thread) {
+ pthread_t thread;
+ ASSERT_EQ(0, pthread_create(&thread, nullptr, [](void*) -> void* {
+ UnwindTest();
+ return nullptr;
+ }, nullptr));
+ void *retval;
+ ASSERT_EQ(0, pthread_join(thread, &retval));
+ EXPECT_EQ(nullptr, retval);
+}
+
struct UnwindData {
volatile bool signal_handler_complete = false;
int expected_frame_count = 0;
@@ -98,7 +113,7 @@ static void verify_unwind_data(const UnwindData& unwind_data) {
EXPECT_EQ(unwind_data.handler_frame_count + 1, unwind_data.handler_one_deeper_frame_count);
}
-static void noinline UnwindTest() {
+static void noinline SignalUnwindTest() {
g_unwind_data = {};
_Unwind_Backtrace(FrameCounter, &g_unwind_data.expected_frame_count);
@@ -114,12 +129,12 @@ static void noinline UnwindTest() {
TEST(stack_unwinding, unwind_through_signal_frame) {
ScopedSignalHandler ssh(SIGUSR1, UnwindSignalHandler);
- UnwindTest();
+ SignalUnwindTest();
}
// On LP32, the SA_SIGINFO flag gets you __restore_rt instead of __restore.
TEST(stack_unwinding, unwind_through_signal_frame_SA_SIGINFO) {
ScopedSignalHandler ssh(SIGUSR1, UnwindSignalHandler, SA_SIGINFO);
- UnwindTest();
+ SignalUnwindTest();
}