diff options
Diffstat (limited to 'debuggerd/libdebuggerd')
-rw-r--r-- | debuggerd/libdebuggerd/include/libdebuggerd/types.h | 3 | ||||
-rw-r--r-- | debuggerd/libdebuggerd/include/libdebuggerd/utility.h | 2 | ||||
-rw-r--r-- | debuggerd/libdebuggerd/tombstone.cpp | 14 | ||||
-rw-r--r-- | debuggerd/libdebuggerd/utility.cpp | 37 |
4 files changed, 49 insertions, 7 deletions
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h index 4f681c260..35c3fd646 100644 --- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h +++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h @@ -41,4 +41,7 @@ struct ProcessInfo { uintptr_t fdsan_table_address = 0; uintptr_t gwp_asan_state = 0; uintptr_t gwp_asan_metadata = 0; + + bool has_fault_address = false; + uintptr_t fault_address = 0; }; diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h index 75bac87d3..7bfcf5d6e 100644 --- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h +++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h @@ -93,4 +93,6 @@ 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*); +uintptr_t get_fault_address(const siginfo_t* siginfo, const ucontext_t* ucontext); + #endif // _DEBUGGERD_UTILITY_H diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp index 87bb8c5ed..e0168d539 100644 --- a/debuggerd/libdebuggerd/tombstone.cpp +++ b/debuggerd/libdebuggerd/tombstone.cpp @@ -154,16 +154,16 @@ static void dump_probable_cause(log_t* log, const siginfo_t* si, unwindstack::Ma } static void dump_signal_info(log_t* log, const ThreadInfo& thread_info, - unwindstack::Memory* process_memory) { + const ProcessInfo& process_info, unwindstack::Memory* process_memory) { char addr_desc[64]; // ", fault addr 0x1234" - if (signal_has_si_addr(thread_info.siginfo)) { - void* addr = thread_info.siginfo->si_addr; + if (process_info.has_fault_address) { + size_t addr = process_info.fault_address; if (thread_info.siginfo->si_signo == SIGILL) { uint32_t instruction = {}; - process_memory->Read(reinterpret_cast<uint64_t>(addr), &instruction, sizeof(instruction)); - snprintf(addr_desc, sizeof(addr_desc), "%p (*pc=%#08x)", addr, instruction); + process_memory->Read(addr, &instruction, sizeof(instruction)); + snprintf(addr_desc, sizeof(addr_desc), "0x%zx (*pc=%#08x)", addr, instruction); } else { - snprintf(addr_desc, sizeof(addr_desc), "%p", addr); + snprintf(addr_desc, sizeof(addr_desc), "0x%zx", addr); } } else { snprintf(addr_desc, sizeof(addr_desc), "--------"); @@ -384,7 +384,7 @@ static bool dump_thread(log_t* log, unwindstack::Unwinder* unwinder, const Threa dump_thread_info(log, thread_info); if (thread_info.siginfo) { - dump_signal_info(log, thread_info, unwinder->GetProcessMemory().get()); + dump_signal_info(log, thread_info, process_info, unwinder->GetProcessMemory().get()); } std::unique_ptr<GwpAsanCrashData> gwp_asan_crash_data; diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp index 0a1d2a4da..3bf28b6c2 100644 --- a/debuggerd/libdebuggerd/utility.cpp +++ b/debuggerd/libdebuggerd/utility.cpp @@ -449,3 +449,40 @@ void log_backtrace(log_t* log, unwindstack::Unwinder* unwinder, const char* pref _LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, unwinder->FormatFrame(i).c_str()); } } + +#if defined(__aarch64__) +#define FAR_MAGIC 0x46415201 + +struct far_context { + struct _aarch64_ctx head; + __u64 far; +}; +#endif + +uintptr_t get_fault_address(const siginfo_t* siginfo, const ucontext_t* ucontext) { + (void)ucontext; +#if defined(__aarch64__) + // This relies on a kernel patch: + // https://patchwork.kernel.org/patch/11435077/ + // that hasn't been accepted into the kernel yet. TODO(pcc): Update this to + // use the official interface once it lands. + auto* begin = reinterpret_cast<const char*>(ucontext->uc_mcontext.__reserved); + auto* end = begin + sizeof(ucontext->uc_mcontext.__reserved); + auto* ptr = begin; + while (1) { + auto* ctx = reinterpret_cast<const _aarch64_ctx*>(ptr); + if (ctx->magic == 0) { + break; + } + if (ctx->magic == FAR_MAGIC) { + auto* far_ctx = reinterpret_cast<const far_context*>(ctx); + return far_ctx->far; + } + ptr += ctx->size; + if (ctx->size % sizeof(void*) != 0 || ptr < begin || ptr >= end) { + break; + } + } +#endif + return reinterpret_cast<uintptr_t>(siginfo->si_addr); +} |