summaryrefslogtreecommitdiff
path: root/debuggerd/libdebuggerd/utility.cpp
diff options
context:
space:
mode:
authorPeter Collingbourne <pcc@google.com>2020-03-30 21:40:58 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2020-03-30 21:40:58 +0000
commitcd63cae6b206a067fab1afe78f7647f1f2cb1513 (patch)
tree04e72546f2968a86b41a1151a5c8639adb2e852f /debuggerd/libdebuggerd/utility.cpp
parent5677803cb7e78421f835513d088e24ccd6da6d87 (diff)
parentf03af8844acbd63f257c51577834d2c126a41f47 (diff)
Merge "Read fault address on arm64 using proposed kernel API."
Diffstat (limited to 'debuggerd/libdebuggerd/utility.cpp')
-rw-r--r--debuggerd/libdebuggerd/utility.cpp37
1 files changed, 37 insertions, 0 deletions
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);
+}