diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp index 43942742e..a4bb8b5bd 100644 --- a/debuggerd/debuggerd_test.cpp +++ b/debuggerd/debuggerd_test.cpp @@ -340,7 +340,12 @@ TEST_F(CrasherTest, smoke) { std::string result; ConsumeFd(std::move(output_fd), &result); - ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0xdead)"); +#ifdef __LP64__ + ASSERT_MATCH(result, + R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x000000000000dead)"); +#else + ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0000dead)"); +#endif if (mte_supported()) { // Test that the default TAGGED_ADDR_CTRL value is set. @@ -370,8 +375,7 @@ TEST_F(CrasherTest, tagged_fault_addr) { // The address can either be tagged (new kernels) or untagged (old kernels). ASSERT_MATCH( - result, - R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr (0x100000000000dead|0xdead))"); + result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x[01]00000000000dead)"); } // Marked as weak to prevent the compiler from removing the malloc in the caller. In theory, the @@ -422,6 +426,12 @@ static void SetTagCheckingLevelSync() { abort(); } } + +static void SetTagCheckingLevelAsync() { + if (mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_ASYNC) == 0) { + abort(); + } +} #endif // Number of iterations required to reliably guarantee a GWP-ASan crash. @@ -653,6 +663,36 @@ TEST_P(SizeParamCrasherTest, mte_underflow) { #endif } +TEST_F(CrasherTest, mte_async) { +#if defined(__aarch64__) + if (!mte_supported()) { + GTEST_SKIP() << "Requires MTE"; + } + + int intercept_result; + unique_fd output_fd; + StartProcess([&]() { + SetTagCheckingLevelAsync(); + volatile int* p = (volatile int*)malloc(16); + p[-1] = 42; + }); + + StartIntercept(&output_fd); + FinishCrasher(); + AssertDeath(SIGSEGV); + FinishIntercept(&intercept_result); + + ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; + + std::string result; + ConsumeFd(std::move(output_fd), &result); + + ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 8 \(SEGV_MTEAERR\), fault addr --------)"); +#else + GTEST_SKIP() << "Requires aarch64"; +#endif +} + TEST_F(CrasherTest, mte_multiple_causes) { #if defined(__aarch64__) if (!mte_supported()) { @@ -703,7 +743,7 @@ TEST_F(CrasherTest, mte_multiple_causes) { for (const auto& result : log_sources) { ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))"); ASSERT_THAT(result, HasSubstr("Note: multiple potential causes for this crash were detected, " - "listing them in decreasing order of probability.")); + "listing them in decreasing order of likelihood.")); // Adjacent untracked allocations may cause us to see the wrong underflow here (or only // overflows), so we can't match explicitly for an underflow message. ASSERT_MATCH(result, @@ -890,7 +930,7 @@ TEST_F(CrasherTest, LD_PRELOAD) { std::string result; ConsumeFd(std::move(output_fd), &result); - ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0xdead)"); + ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+dead)"); } TEST_F(CrasherTest, abort) { @@ -1940,7 +1980,7 @@ TEST_F(CrasherTest, fault_address_before_first_map) { std::string result; ConsumeFd(std::move(output_fd), &result); - ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x1024)"); + ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+1024)"); ASSERT_MATCH(result, R"(\nmemory map \(.*\):\n)"); @@ -1970,8 +2010,8 @@ TEST_F(CrasherTest, fault_address_after_last_map) { std::string result; ConsumeFd(std::move(output_fd), &result); - std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr )"; - match_str += android::base::StringPrintf("0x%" PRIxPTR, crash_uptr); + std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)"; + match_str += format_full_pointer(crash_uptr); ASSERT_MATCH(result, match_str); ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)"); @@ -2018,8 +2058,8 @@ TEST_F(CrasherTest, fault_address_between_maps) { std::string result; ConsumeFd(std::move(output_fd), &result); - std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr )"; - match_str += android::base::StringPrintf("%p", middle_ptr); + std::string match_str = R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x)"; + match_str += format_full_pointer(reinterpret_cast(middle_ptr)); ASSERT_MATCH(result, match_str); ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)"); @@ -2056,8 +2096,8 @@ TEST_F(CrasherTest, fault_address_in_map) { std::string result; ConsumeFd(std::move(output_fd), &result); - std::string match_str = R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\), fault addr )"; - match_str += android::base::StringPrintf("%p", ptr); + std::string match_str = R"(signal 11 \(SIGSEGV\), code 2 \(SEGV_ACCERR\), fault addr 0x)"; + match_str += format_full_pointer(reinterpret_cast(ptr)); ASSERT_MATCH(result, match_str); ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)"); @@ -2181,7 +2221,7 @@ TEST_F(CrasherTest, verify_dex_pc_with_function_name) { ConsumeFd(std::move(output_fd), &result); // Verify the process crashed properly. - ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0)"); + ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0*)"); // Now verify that the dex_pc frame includes a proper function name. ASSERT_MATCH(result, R"( \[anon:dex\] \(Main\.\\+2)"); diff --git a/debuggerd/libdebuggerd/scudo.cpp b/debuggerd/libdebuggerd/scudo.cpp index f4690bac3..a89f3850d 100644 --- a/debuggerd/libdebuggerd/scudo.cpp +++ b/debuggerd/libdebuggerd/scudo.cpp @@ -135,7 +135,7 @@ void ScudoCrashData::DumpCause(log_t* log, unwindstack::Unwinder* unwinder) cons if (error_info_.reports[1].error_type != UNKNOWN) { _LOG(log, logtype::HEADER, "\nNote: multiple potential causes for this crash were detected, listing them in " - "decreasing order of probability.\n"); + "decreasing order of likelihood.\n"); } size_t report_num = 0; diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp index 681b963a7..c248faed0 100644 --- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp +++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp @@ -292,6 +292,7 @@ static void print_tag_dump(CallbackType callback, const Tombstone& tombstone) { static void print_main_thread(CallbackType callback, const Tombstone& tombstone, const Thread& thread) { + int word_size = pointer_width(tombstone); print_thread_header(callback, tombstone, thread, true); const Signal& signal_info = tombstone.signal_info(); @@ -307,7 +308,7 @@ static void print_main_thread(CallbackType callback, const Tombstone& tombstone, } else { std::string fault_addr_desc; if (signal_info.has_fault_address()) { - fault_addr_desc = StringPrintf("0x%" PRIx64, signal_info.fault_address()); + fault_addr_desc = StringPrintf("0x%0*" PRIx64, 2 * word_size, signal_info.fault_address()); } else { fault_addr_desc = "--------"; } @@ -331,7 +332,7 @@ static void print_main_thread(CallbackType callback, const Tombstone& tombstone, if (tombstone.causes_size() > 1) { CBS(""); CBL("Note: multiple potential causes for this crash were detected, listing them in decreasing " - "order of probability."); + "order of likelihood."); } for (const Cause& cause : tombstone.causes()) { @@ -369,7 +370,6 @@ static void print_main_thread(CallbackType callback, const Tombstone& tombstone, return; } - int word_size = pointer_width(tombstone); const auto format_pointer = [word_size](uint64_t ptr) -> std::string { if (word_size == 8) { uint64_t top = ptr >> 32; diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp index a7506b760..4370130cc 100644 --- a/debuggerd/libdebuggerd/utility.cpp +++ b/debuggerd/libdebuggerd/utility.cpp @@ -275,9 +275,10 @@ bool signal_has_si_addr(const siginfo_t* si) { case SIGBUS: case SIGFPE: case SIGILL: - case SIGSEGV: case SIGTRAP: return true; + case SIGSEGV: + return si->si_code != SEGV_MTEAERR; default: return false; }