From c8027933b339ab3221a606590a7e6dccb840723b Mon Sep 17 00:00:00 2001 From: Sijie Chen Date: Fri, 10 May 2024 18:40:48 +0000 Subject: [PATCH] Reland "[Berberis][CrashReporting] Dump guest thread inf..." Guest thread information will print out follow host thread. Revert submission 3081452-revert-3062926-CJGHTRPCBP Reason for revert: Will make the change base on the original CLs for a reland. Bug: b/321799516 Test: riscv64, checked tombstone file has wanted block. https://paste.googleplex.com/6282302317658112 Added arm64 support and tested arm64 unwinding in internal repo. https://paste.googleplex.com/6545612887818240 Change-Id: Ie54ad6f359d60283442adfcd9ee95f5a116e4b72 --- debuggerd/crash_dump.cpp | 36 +++++++++++++++++- .../include/libdebuggerd/tombstone.h | 8 +++- debuggerd/libdebuggerd/tombstone.cpp | 6 ++- debuggerd/libdebuggerd/tombstone_proto.cpp | 37 +++++++++++++++++-- .../libdebuggerd/tombstone_proto_to_text.cpp | 33 +++++++++++++++-- debuggerd/proto/tombstone.proto | 7 +++- 6 files changed, 112 insertions(+), 15 deletions(-) diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp index 6706650b9..852c159a5 100644 --- a/debuggerd/crash_dump.cpp +++ b/debuggerd/crash_dump.cpp @@ -81,6 +81,10 @@ using android::base::ErrnoRestorer; using android::base::StringPrintf; using android::base::unique_fd; +// This stores guest architecture. When the architecture is supported, tombstone file will output +// guest state information. +static Architecture g_guest_arch; + static bool pid_contains_tid(int pid_proc_fd, pid_t tid) { struct stat st; std::string task_path = StringPrintf("task/%d", tid); @@ -495,6 +499,8 @@ static void ReadGuestRegisters([[maybe_unused]] std::unique_ptrreset(unwindstack::RegsArm64::Read(&arm64_user_regs)); + + g_guest_arch = Architecture::ARM64; break; } case NATIVE_BRIDGE_ARCH_RISCV64: { @@ -505,6 +511,8 @@ static void ReadGuestRegisters([[maybe_unused]] std::unique_ptrreset(unwindstack::RegsRiscv64::Read(&riscv64_user_regs, tid)); + + g_guest_arch = Architecture::RISCV64; break; } #endif @@ -771,8 +779,32 @@ int main(int argc, char** argv) { { ATRACE_NAME("engrave_tombstone"); - engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info, - g_target_thread, process_info, &open_files, &amfd_data); + unwindstack::ArchEnum regs_arch = unwindstack::ARCH_UNKNOWN; + switch (g_guest_arch) { + case Architecture::ARM32: { + regs_arch = unwindstack::ARCH_ARM; + break; + } + case Architecture::ARM64: { + regs_arch = unwindstack::ARCH_ARM64; + break; + } + case Architecture::RISCV64: { + regs_arch = unwindstack::ARCH_RISCV64; + break; + } + default: { + } + } + if (regs_arch == unwindstack::ARCH_UNKNOWN) { + engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info, + g_target_thread, process_info, &open_files, &amfd_data); + } else { + unwindstack::AndroidRemoteUnwinder guest_unwinder(vm_pid, regs_arch); + engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info, + g_target_thread, process_info, &open_files, &amfd_data, &g_guest_arch, + &guest_unwinder); + } } } diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h index be999e04e..dfdfabdff 100644 --- a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h +++ b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h @@ -28,6 +28,7 @@ #include #include "open_files_list.h" +#include "tombstone.pb.h" #include "types.h" // Forward declarations @@ -54,14 +55,17 @@ void engrave_tombstone(android::base::unique_fd output_fd, android::base::unique unwindstack::AndroidUnwinder* unwinder, const std::map& thread_info, pid_t target_thread, const ProcessInfo& process_info, OpenFilesList* open_files, - std::string* amfd_data); + std::string* amfd_data, const Architecture* guest_arch = nullptr, + unwindstack::AndroidUnwinder* guest_unwinder = nullptr); void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_msg_address, siginfo_t* siginfo, ucontext_t* ucontext); void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder, const std::map& threads, pid_t target_thread, - const ProcessInfo& process_info, const OpenFilesList* open_files); + const ProcessInfo& process_info, const OpenFilesList* open_files, + const Architecture* guest_arch, + unwindstack::AndroidUnwinder* guest_unwinder); bool tombstone_proto_to_text( const Tombstone& tombstone, diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp index 5a416d643..0ce55738a 100644 --- a/debuggerd/libdebuggerd/tombstone.cpp +++ b/debuggerd/libdebuggerd/tombstone.cpp @@ -125,10 +125,12 @@ void engrave_tombstone(unique_fd output_fd, unique_fd proto_fd, unwindstack::AndroidUnwinder* unwinder, const std::map& threads, pid_t target_thread, const ProcessInfo& process_info, OpenFilesList* open_files, - std::string* amfd_data) { + std::string* amfd_data, const Architecture* guest_arch, + unwindstack::AndroidUnwinder* guest_unwinder) { // Don't copy log messages to tombstone unless this is a development device. Tombstone tombstone; - engrave_tombstone_proto(&tombstone, unwinder, threads, target_thread, process_info, open_files); + engrave_tombstone_proto(&tombstone, unwinder, threads, target_thread, process_info, open_files, + guest_arch, guest_unwinder); if (proto_fd != -1) { if (!tombstone.SerializeToFileDescriptor(proto_fd.get())) { diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp index 5546b7bcc..3e8ab6ea5 100644 --- a/debuggerd/libdebuggerd/tombstone_proto.cpp +++ b/debuggerd/libdebuggerd/tombstone_proto.cpp @@ -482,7 +482,8 @@ static void dump_thread_backtrace(std::vector& frames, T } static void dump_thread(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder, - const ThreadInfo& thread_info, bool memory_dump = false) { + const ThreadInfo& thread_info, bool memory_dump = false, + unwindstack::AndroidUnwinder* guest_unwinder = nullptr) { Thread thread; thread.set_id(thread_info.tid); @@ -509,6 +510,27 @@ static void dump_thread(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwi auto& threads = *tombstone->mutable_threads(); threads[thread_info.tid] = thread; + + if (guest_unwinder) { + if (!thread_info.guest_registers) { + async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG, + "No guest state registers information for tid %d", thread_info.tid); + return; + } + Thread guest_thread; + unwindstack::AndroidUnwinderData guest_data; + guest_data.saved_initial_regs = std::make_optional>(); + if (guest_unwinder->Unwind(thread_info.guest_registers.get(), guest_data)) { + dump_thread_backtrace(guest_data.frames, guest_thread); + } else { + async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, + "Unwind guest state registers failed for tid %d: Error %s", + thread_info.tid, guest_data.GetErrorString().c_str()); + } + dump_registers(guest_unwinder, *guest_data.saved_initial_regs, guest_thread, memory_dump); + auto& guest_threads = *tombstone->mutable_guest_threads(); + guest_threads[thread_info.tid] = guest_thread; + } } static void dump_mappings(Tombstone* tombstone, unwindstack::Maps* maps, @@ -686,10 +708,17 @@ static void dump_tags_around_fault_addr(Signal* signal, const Tombstone& tombsto void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder, const std::map& threads, pid_t target_tid, - const ProcessInfo& process_info, const OpenFilesList* open_files) { + const ProcessInfo& process_info, const OpenFilesList* open_files, + const Architecture* guest_arch, + unwindstack::AndroidUnwinder* guest_unwinder) { Tombstone result; result.set_arch(get_arch()); + if (guest_arch != nullptr) { + result.set_guest_arch(*guest_arch); + } else { + result.set_guest_arch(Architecture::NONE); + } result.set_build_fingerprint(android::base::GetProperty("ro.build.fingerprint", "unknown")); result.set_revision(android::base::GetProperty("ro.revision", "unknown")); result.set_timestamp(get_timestamp()); @@ -750,11 +779,11 @@ void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* dump_abort_message(&result, unwinder->GetProcessMemory(), process_info); dump_crash_details(&result, unwinder->GetProcessMemory(), process_info); // Dump the target thread, but save the memory around the registers. - dump_thread(&result, unwinder, target_thread, /* memory_dump */ true); + dump_thread(&result, unwinder, target_thread, /* memory_dump */ true, guest_unwinder); for (const auto& [tid, thread_info] : threads) { if (tid != target_tid) { - dump_thread(&result, unwinder, thread_info); + dump_thread(&result, unwinder, thread_info, /* memory_dump */ false, guest_unwinder); } } diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp index 08c1cc0da..19007194e 100644 --- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp +++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp @@ -79,8 +79,8 @@ static std::string describe_pac_enabled_keys(long value) { return describe_end(value, desc); } -static const char* abi_string(const Tombstone& tombstone) { - switch (tombstone.arch()) { +static const char* abi_string(const Architecture& arch) { + switch (arch) { case Architecture::ARM32: return "arm"; case Architecture::ARM64: @@ -578,11 +578,28 @@ void print_logs(CallbackType callback, const Tombstone& tombstone, int tail) { } } +static void print_guest_thread(CallbackType callback, const Tombstone& tombstone, + const Thread& guest_thread, pid_t tid, bool should_log) { + CBS("--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---"); + CBS("Guest thread information for tid: %d", tid); + print_thread_registers(callback, tombstone, guest_thread, should_log); + + CBS(""); + CB(true, "%d total frames", guest_thread.current_backtrace().size()); + CB(true, "backtrace:"); + print_backtrace(callback, tombstone, guest_thread.current_backtrace(), should_log); + + print_thread_memory_dump(callback, tombstone, guest_thread); +} + bool tombstone_proto_to_text(const Tombstone& tombstone, CallbackType callback) { CBL("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***"); CBL("Build fingerprint: '%s'", tombstone.build_fingerprint().c_str()); CBL("Revision: '%s'", tombstone.revision().c_str()); - CBL("ABI: '%s'", abi_string(tombstone)); + CBL("ABI: '%s'", abi_string(tombstone.arch())); + if (tombstone.guest_arch() != Architecture::NONE) { + CBL("Guest architecture: '%s'", abi_string(tombstone.guest_arch())); + } CBL("Timestamp: %s", tombstone.timestamp().c_str()); CBL("Process uptime: %ds", tombstone.process_uptime()); @@ -607,6 +624,12 @@ bool tombstone_proto_to_text(const Tombstone& tombstone, CallbackType callback) print_logs(callback, tombstone, 50); + const auto& guest_threads = tombstone.guest_threads(); + auto main_guest_thread_it = guest_threads.find(tombstone.tid()); + if (main_guest_thread_it != threads.end()) { + print_guest_thread(callback, tombstone, main_guest_thread_it->second, tombstone.tid(), true); + } + // protobuf's map is unordered, so sort the keys first. std::set thread_ids; for (const auto& [tid, _] : threads) { @@ -618,6 +641,10 @@ bool tombstone_proto_to_text(const Tombstone& tombstone, CallbackType callback) for (const auto& tid : thread_ids) { CBS("--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---"); print_thread(callback, tombstone, threads.find(tid)->second); + auto guest_thread_it = guest_threads.find(tid); + if (guest_thread_it != guest_threads.end()) { + print_guest_thread(callback, tombstone, guest_thread_it->second, tid, false); + } } if (tombstone.open_fds().size() > 0) { diff --git a/debuggerd/proto/tombstone.proto b/debuggerd/proto/tombstone.proto index e70d525ee..6f9cd9612 100644 --- a/debuggerd/proto/tombstone.proto +++ b/debuggerd/proto/tombstone.proto @@ -22,6 +22,7 @@ message CrashDetail { message Tombstone { Architecture arch = 1; + Architecture guest_arch = 24; string build_fingerprint = 2; string revision = 3; string timestamp = 4; @@ -42,6 +43,7 @@ message Tombstone { repeated Cause causes = 15; map threads = 16; + map guest_threads = 25; repeated MemoryMapping memory_mappings = 17; repeated LogBuffer log_buffers = 18; repeated FD open_fds = 19; @@ -49,7 +51,7 @@ message Tombstone { uint32 page_size = 22; bool has_been_16kb_mode = 23; - reserved 24 to 999; + reserved 26 to 999; } enum Architecture { @@ -58,8 +60,9 @@ enum Architecture { X86 = 2; X86_64 = 3; RISCV64 = 4; + NONE = 5; - reserved 5 to 999; + reserved 6 to 999; } message Signal {