diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp index 5bb1d75ad..967b9422c 100644 --- a/debuggerd/crash_dump.cpp +++ b/debuggerd/crash_dump.cpp @@ -502,15 +502,24 @@ int main(int argc, char** argv) { continue; } - struct iovec iov = { + struct iovec tagged_addr_iov = { &info.tagged_addr_ctrl, sizeof(info.tagged_addr_ctrl), }; if (ptrace(PTRACE_GETREGSET, thread, NT_ARM_TAGGED_ADDR_CTRL, - reinterpret_cast(&iov)) == -1) { + reinterpret_cast(&tagged_addr_iov)) == -1) { info.tagged_addr_ctrl = -1; } + struct iovec pac_enabled_keys_iov = { + &info.pac_enabled_keys, + sizeof(info.pac_enabled_keys), + }; + if (ptrace(PTRACE_GETREGSET, thread, NT_ARM_PAC_ENABLED_KEYS, + reinterpret_cast(&pac_enabled_keys_iov)) == -1) { + info.pac_enabled_keys = -1; + } + if (thread == g_target_thread) { // Read the thread's registers along with the rest of the crash info out of the pipe. ReadCrashInfo(input_pipe, &siginfo, &info.registers, &process_info); diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp index b10776786..2cf5b18df 100644 --- a/debuggerd/debuggerd_test.cpp +++ b/debuggerd/debuggerd_test.cpp @@ -173,6 +173,14 @@ static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, uniq *status = response.status; } +static bool pac_supported() { +#if defined(__aarch64__) + return getauxval(AT_HWCAP) & HWCAP_PACA; +#else + return false; +#endif +} + class CrasherTest : public ::testing::Test { public: pid_t crasher_pid = -1; @@ -357,6 +365,12 @@ TEST_F(CrasherTest, smoke) { ASSERT_MATCH(result, R"(tagged_addr_ctrl: 000000000007fff3)" R"( \(PR_TAGGED_ADDR_ENABLE, PR_MTE_TCF_SYNC, mask 0xfffe\))"); } + + if (pac_supported()) { + // Test that the default PAC_ENABLED_KEYS value is set. + ASSERT_MATCH(result, R"(pac_enabled_keys: 000000000000000f)" + R"( \(PR_PAC_APIAKEY, PR_PAC_APIBKEY, PR_PAC_APDAKEY, PR_PAC_APDBKEY\))"); + } } TEST_F(CrasherTest, tagged_fault_addr) { diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h index 086dc97da..a51e2769c 100644 --- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h +++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h @@ -25,6 +25,7 @@ struct ThreadInfo { std::unique_ptr registers; long tagged_addr_ctrl = -1; + long pac_enabled_keys = -1; pid_t uid; diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h index 002321f93..63e142f2c 100644 --- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h +++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h @@ -1,22 +1,20 @@ -/* system/debuggerd/utility.h -** -** Copyright 2008, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ +/* + * Copyright 2008, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -#ifndef _DEBUGGERD_UTILITY_H -#define _DEBUGGERD_UTILITY_H +#pragma once #include #include @@ -93,6 +91,7 @@ void get_signal_sender(char* buf, size_t n, const siginfo_t*); const char* get_signame(const siginfo_t*); const char* get_sigcode(const siginfo_t*); std::string describe_tagged_addr_ctrl(long ctrl); +std::string describe_pac_enabled_keys(long keys); // Number of bytes per MTE granule. constexpr size_t kTagGranuleSize = 16; @@ -100,5 +99,3 @@ constexpr size_t kTagGranuleSize = 16; // Number of rows and columns to display in an MTE tag dump. constexpr size_t kNumTagColumns = 16; constexpr size_t kNumTagRows = 16; - -#endif // _DEBUGGERD_UTILITY_H diff --git a/debuggerd/libdebuggerd/test/utility_test.cpp b/debuggerd/libdebuggerd/test/utility_test.cpp index 97328b7f7..dad338054 100644 --- a/debuggerd/libdebuggerd/test/utility_test.cpp +++ b/debuggerd/libdebuggerd/test/utility_test.cpp @@ -31,3 +31,12 @@ TEST(UtilityTest, describe_tagged_addr_ctrl) { describe_tagged_addr_ctrl(0xf0000000 | PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC | (0xfffe << PR_MTE_TAG_SHIFT))); } + +TEST(UtilityTest, describe_pac_enabled_keys) { + EXPECT_EQ("", describe_pac_enabled_keys(0)); + EXPECT_EQ(" (PR_PAC_APIAKEY)", describe_pac_enabled_keys(PR_PAC_APIAKEY)); + EXPECT_EQ(" (PR_PAC_APIAKEY, PR_PAC_APDBKEY)", + describe_pac_enabled_keys(PR_PAC_APIAKEY | PR_PAC_APDBKEY)); + EXPECT_EQ(" (PR_PAC_APIAKEY, PR_PAC_APDBKEY, unknown 0x1000)", + describe_pac_enabled_keys(PR_PAC_APIAKEY | PR_PAC_APDBKEY | 0x1000)); +} diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp index 714d6b2d6..b7d5bc452 100644 --- a/debuggerd/libdebuggerd/tombstone_proto.cpp +++ b/debuggerd/libdebuggerd/tombstone_proto.cpp @@ -353,6 +353,7 @@ static void dump_thread(Tombstone* tombstone, unwindstack::Unwinder* unwinder, thread.set_id(thread_info.tid); thread.set_name(thread_info.thread_name); thread.set_tagged_addr_ctrl(thread_info.tagged_addr_ctrl); + thread.set_pac_enabled_keys(thread_info.pac_enabled_keys); unwindstack::Maps* maps = unwinder->GetMaps(); unwindstack::Memory* memory = unwinder->GetProcessMemory().get(); diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp index de86b0a7e..026564112 100644 --- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp +++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp @@ -85,6 +85,10 @@ static void print_thread_header(CallbackType callback, const Tombstone& tombston CB(should_log, "tagged_addr_ctrl: %016" PRIx64 "%s", thread.tagged_addr_ctrl(), describe_tagged_addr_ctrl(thread.tagged_addr_ctrl()).c_str()); } + if (thread.pac_enabled_keys() != -1) { + CB(should_log, "pac_enabled_keys: %016" PRIx64 "%s", thread.pac_enabled_keys(), + describe_pac_enabled_keys(thread.pac_enabled_keys()).c_str()); + } } static void print_register_row(CallbackType callback, int word_size, diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp index 71f0c0927..543a67c94 100644 --- a/debuggerd/libdebuggerd/utility.cpp +++ b/debuggerd/libdebuggerd/utility.cpp @@ -446,31 +446,40 @@ const char* get_sigcode(const siginfo_t* si) { return "?"; } -std::string describe_tagged_addr_ctrl(long ctrl) { +#define DESCRIBE_FLAG(flag) \ + if (value & flag) { \ + desc += ", "; \ + desc += #flag; \ + value &= ~flag; \ + } + +static std::string describe_end(long value, std::string& desc) { + if (value) { + desc += StringPrintf(", unknown 0x%lx", value); + } + return desc.empty() ? "" : " (" + desc.substr(2) + ")"; +} + +std::string describe_tagged_addr_ctrl(long value) { std::string desc; - if (ctrl & PR_TAGGED_ADDR_ENABLE) { - desc += ", PR_TAGGED_ADDR_ENABLE"; - ctrl &= ~PR_TAGGED_ADDR_ENABLE; + DESCRIBE_FLAG(PR_TAGGED_ADDR_ENABLE); + DESCRIBE_FLAG(PR_MTE_TCF_SYNC); + DESCRIBE_FLAG(PR_MTE_TCF_ASYNC); + if (value & PR_MTE_TAG_MASK) { + desc += StringPrintf(", mask 0x%04lx", (value & PR_MTE_TAG_MASK) >> PR_MTE_TAG_SHIFT); + value &= ~PR_MTE_TAG_MASK; } - if (ctrl & PR_MTE_TCF_SYNC) { - desc += ", PR_MTE_TCF_SYNC"; - ctrl &= ~PR_MTE_TCF_SYNC; - } - if (ctrl & PR_MTE_TCF_ASYNC) { - desc += ", PR_MTE_TCF_ASYNC"; - ctrl &= ~PR_MTE_TCF_ASYNC; - } - if (ctrl & PR_MTE_TAG_MASK) { - desc += StringPrintf(", mask 0x%04lx", (ctrl & PR_MTE_TAG_MASK) >> PR_MTE_TAG_SHIFT); - ctrl &= ~PR_MTE_TAG_MASK; - } - if (ctrl) { - desc += StringPrintf(", unknown 0x%lx", ctrl); - } - if (desc.empty()) { - return ""; - } - return " (" + desc.substr(2) + ")"; + return describe_end(value, desc); +} + +std::string describe_pac_enabled_keys(long value) { + std::string desc; + DESCRIBE_FLAG(PR_PAC_APIAKEY); + DESCRIBE_FLAG(PR_PAC_APIBKEY); + DESCRIBE_FLAG(PR_PAC_APDAKEY); + DESCRIBE_FLAG(PR_PAC_APDBKEY); + DESCRIBE_FLAG(PR_PAC_APGAKEY); + return describe_end(value, desc); } void log_backtrace(log_t* log, unwindstack::Unwinder* unwinder, const char* prefix) { diff --git a/debuggerd/proto/tombstone.proto b/debuggerd/proto/tombstone.proto index a701212d8..40a942e5b 100644 --- a/debuggerd/proto/tombstone.proto +++ b/debuggerd/proto/tombstone.proto @@ -126,8 +126,9 @@ message Thread { repeated BacktraceFrame current_backtrace = 4; repeated MemoryDump memory_dump = 5; int64 tagged_addr_ctrl = 6; + int64 pac_enabled_keys = 8; - reserved 8 to 999; + reserved 9 to 999; } message BacktraceFrame {