aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Collingbourne <pcc@google.com>2021-06-04 14:35:13 -0700
committerPeter Collingbourne <pcc@google.com>2021-06-08 18:41:36 -0700
commit9a1b7d124353afd76447ea2a9dea1903cc10b335 (patch)
treea2f0eb27c3a9a218aed1f18291ecc310ea063a5b
parenta3b1926d75c2e46083429ae1e952035480dc3221 (diff)
downloadbionic-9a1b7d124353afd76447ea2a9dea1903cc10b335.tar.gz
Disable return PAC in __pthread_start.
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. Bug: 189808795 Change-Id: I953da9078acd1d43eb7a47fb11f75caa0099fa12 Merged-In: I953da9078acd1d43eb7a47fb11f75caa0099fa12
-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();
}