[PATCH v2] arm64: symbolize user-space stack on SIGSEGV
Peter Collingbourne
pcc at google.com
Fri Nov 1 11:13:24 PDT 2024
On arm64, dump the userspace stack to the console when a SIGSEGV
occurs. Print filename+offset to allow symbolization.
This is a patch that I frequently need to apply locally in order to
debug segfaults that occur in environments where attaching a debugger
is infeasible.
Although I don't expect this patch to be applied to the mainline
kernel, I am posting it in case anyone else would find it useful
(and because I almost lost track of it recently, and I don't want to
have to write it again).
Signed-off-by: Peter Collingbourne <pcc at google.com>
---
v2:
- rebased to 6.12-rc5
arch/arm64/mm/fault.c | 36 +++++++++++++++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 8b281cf308b30..9391a0d44a99f 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -518,6 +518,38 @@ static bool is_write_abort(unsigned long esr)
return (esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM);
}
+static void symbolize_addr(const char *prefix, unsigned long addr)
+{
+ struct vm_area_struct *vma = find_vma(current->mm, addr);
+ if (vma && vma->vm_file) {
+ char buf[1024];
+ char *c = d_path(&vma->vm_file->f_path, buf, 1024);
+ printk(KERN_ERR "%s = 0x%lx (%s + 0x%lx)\n", prefix, addr, c,
+ addr - vma->vm_start + vma->vm_pgoff * PAGE_SIZE);
+ } else {
+ printk(KERN_ERR "%s = 0x%lx", prefix, addr);
+ }
+}
+
+static void symbolize_stack(void)
+{
+ int i;
+ unsigned long frame = current_pt_regs()->regs[29];
+
+ symbolize_addr("pc", current_pt_regs()->pc);
+ symbolize_addr("lr", current_pt_regs()->regs[30]);
+
+ for (i = 0; i != 64; ++i) {
+ unsigned long ret_addr;
+ unsafe_get_user(ret_addr, (unsigned long __user *)(frame + 8),
+ end);
+ symbolize_addr("ret_addr", ptrauth_strip_user_insn_pac(ret_addr));
+
+ unsafe_get_user(frame, (unsigned long __user *)frame, end);
+ }
+end:;
+}
+
static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
struct pt_regs *regs)
{
@@ -722,8 +754,10 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
/* Something tried to access memory that out of memory map */
if (si_code == SEGV_PKUERR)
arm64_force_sig_fault_pkey(far, inf->name, pkey);
- else
+ else {
+ symbolize_stack();
arm64_force_sig_fault(SIGSEGV, si_code, far, inf->name);
+ }
}
return 0;
--
2.47.0.163.g1226f6d8fa-goog
More information about the linux-arm-kernel
mailing list