From c95047dd20845f06532531ce83e0bedc8ee96038 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Mon, 14 Mar 2022 15:02:11 -0700 Subject: [PATCH] Update for accurate unreadable elf files. The functionality moved from the Unwinder object to the MapInfo object and means that the individual unreadable files can be displayed now. Included adding the unreadable elfs per thread in the protobuf. Updated the unwinder test. Test: All unit tests pass. Change-Id: I7140bde16938736da005f926e10bbdb3dbc0f6f5 --- debuggerd/debuggerd_test.cpp | 6 ++++-- debuggerd/libdebuggerd/tombstone_proto.cpp | 24 ++++++++++++++++------ debuggerd/libdebuggerd/utility.cpp | 21 +++++++++++++++---- debuggerd/proto/tombstone.proto | 3 ++- 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp index 85adbeaa5..a5e2413d5 100644 --- a/debuggerd/debuggerd_test.cpp +++ b/debuggerd/debuggerd_test.cpp @@ -1825,9 +1825,9 @@ static bool CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) { TEST_F(CrasherTest, unreadable_elf) { int intercept_result; unique_fd output_fd; - StartProcess([]() { + std::string tmp_so_name; + StartProcess([&tmp_so_name]() { TemporaryDir td; - std::string tmp_so_name; if (!CopySharedLibrary(td.path, &tmp_so_name)) { _exit(1); } @@ -1857,6 +1857,8 @@ TEST_F(CrasherTest, unreadable_elf) { std::string result; ConsumeFd(std::move(output_fd), &result); ASSERT_MATCH(result, R"(NOTE: Function names and BuildId information is missing )"); + std::string match_str = "NOTE: " + tmp_so_name; + ASSERT_MATCH(result, match_str); } TEST(tombstoned, proto) { diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp index 3e31bb790..bee4a67c9 100644 --- a/debuggerd/libdebuggerd/tombstone_proto.cpp +++ b/debuggerd/libdebuggerd/tombstone_proto.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -419,18 +420,29 @@ static void dump_thread_backtrace(unwindstack::Unwinder* unwinder, Thread& threa return; } - if (unwinder->elf_from_memory_not_file()) { + unwinder->SetDisplayBuildID(true); + std::set unreadable_elf_files; + for (const auto& frame : unwinder->frames()) { + BacktraceFrame* f = thread.add_current_backtrace(); + fill_in_backtrace_frame(f, frame); + if (frame.map_info != nullptr && frame.map_info->ElfFileNotReadable()) { + unreadable_elf_files.emplace(frame.map_info->name()); + } + } + + if (!unreadable_elf_files.empty()) { + auto unreadable_elf_files_proto = thread.mutable_unreadable_elf_files(); auto backtrace_note = thread.mutable_backtrace_note(); *backtrace_note->Add() = "Function names and BuildId information is missing for some frames due"; *backtrace_note->Add() = "to unreadable libraries. For unwinds of apps, only shared libraries"; *backtrace_note->Add() = "found under the lib/ directory are readable."; *backtrace_note->Add() = "On this device, run setenforce 0 to make the libraries readable."; - } - unwinder->SetDisplayBuildID(true); - for (const auto& frame : unwinder->frames()) { - BacktraceFrame* f = thread.add_current_backtrace(); - fill_in_backtrace_frame(f, frame); + *backtrace_note->Add() = "Unreadable libraries:"; + for (auto& name : unreadable_elf_files) { + *backtrace_note->Add() = " " + name; + *unreadable_elf_files_proto->Add() = name; + } } } diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp index 543a67c94..ecd98a4c5 100644 --- a/debuggerd/libdebuggerd/utility.cpp +++ b/debuggerd/libdebuggerd/utility.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -483,7 +484,16 @@ std::string describe_pac_enabled_keys(long value) { } void log_backtrace(log_t* log, unwindstack::Unwinder* unwinder, const char* prefix) { - if (unwinder->elf_from_memory_not_file()) { + std::set unreadable_elf_files; + unwinder->SetDisplayBuildID(true); + for (const auto& frame : unwinder->frames()) { + if (frame.map_info != nullptr && frame.map_info->ElfFileNotReadable()) { + unreadable_elf_files.emplace(frame.map_info->name()); + } + } + + // Put the preamble ahead of the backtrace. + if (!unreadable_elf_files.empty()) { _LOG(log, logtype::BACKTRACE, "%sNOTE: Function names and BuildId information is missing for some frames due\n", prefix); _LOG(log, logtype::BACKTRACE, @@ -493,10 +503,13 @@ void log_backtrace(log_t* log, unwindstack::Unwinder* unwinder, const char* pref _LOG(log, logtype::BACKTRACE, "%sNOTE: On this device, run setenforce 0 to make the libraries readable.\n", prefix); #endif + _LOG(log, logtype::BACKTRACE, "%sNOTE: Unreadable libraries:\n", prefix); + for (auto& name : unreadable_elf_files) { + _LOG(log, logtype::BACKTRACE, "%sNOTE: %s\n", prefix, name.c_str()); + } } - unwinder->SetDisplayBuildID(true); - for (size_t i = 0; i < unwinder->NumFrames(); i++) { - _LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, unwinder->FormatFrame(i).c_str()); + for (const auto& frame : unwinder->frames()) { + _LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, unwinder->FormatFrame(frame).c_str()); } } diff --git a/debuggerd/proto/tombstone.proto b/debuggerd/proto/tombstone.proto index 40a942e5b..a0f2f82c6 100644 --- a/debuggerd/proto/tombstone.proto +++ b/debuggerd/proto/tombstone.proto @@ -123,12 +123,13 @@ message Thread { string name = 2; repeated Register registers = 3; repeated string backtrace_note = 7; + repeated string unreadable_elf_files = 9; repeated BacktraceFrame current_backtrace = 4; repeated MemoryDump memory_dump = 5; int64 tagged_addr_ctrl = 6; int64 pac_enabled_keys = 8; - reserved 9 to 999; + reserved 10 to 999; } message BacktraceFrame {