Merge "Disable return PAC in __pthread_start."
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 46d9e86..121b26f 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -331,6 +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.
+__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 0ff6f30..2f891a6 100644
--- a/tests/stack_unwinding_test.cpp
+++ b/tests/stack_unwinding_test.cpp
@@ -66,13 +66,28 @@
   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 @@
   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 @@
 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();
 }