From cfe0f9e1d1efc00397d62f06e6565f0f44121cd9 Mon Sep 17 00:00:00 2001 From: kettenis Date: Tue, 12 Mar 2024 13:32:53 +0000 Subject: [PATCH] Fix the "fake" frame that we create alongside the trapframe. This fixes backtraces through trap franes. Adjust the code that prints backtraces in ddb as the old code now tries to access a userland address. ok mpi@ --- sys/arch/arm64/arm64/db_trace.c | 44 ++++++++++++++++++++++++-------- sys/arch/arm64/arm64/exception.S | 7 +++-- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/sys/arch/arm64/arm64/db_trace.c b/sys/arch/arm64/arm64/db_trace.c index 0fcfa138f3e..cd460530a5a 100644 --- a/sys/arch/arm64/arm64/db_trace.c +++ b/sys/arch/arm64/arm64/db_trace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: db_trace.c,v 1.15 2023/06/17 08:13:56 kettenis Exp $ */ +/* $OpenBSD: db_trace.c,v 1.16 2024/03/12 13:32:53 kettenis Exp $ */ /* $NetBSD: db_trace.c,v 1.8 2003/01/17 22:28:48 thorpej Exp $ */ /* @@ -97,8 +97,13 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count, while (count-- && frame != 0) { lastframe = frame; - sym = db_search_symbol(lastlr, DB_STGY_ANY, &offset); - db_symbol_values(sym, &name, NULL); + if (INKERNEL(frame)) { + sym = db_search_symbol(lastlr, DB_STGY_ANY, &offset); + db_symbol_values(sym, &name, NULL); + } else { + sym = NULL; + name = NULL; + } if (name == NULL || strcmp(name, "end") == 0) { (*pr)("%llx at 0x%lx", lastlr, lr - 4); @@ -108,13 +113,6 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count, } (*pr)("\n"); - // can we detect traps ? - db_read_bytes(frame, sizeof(vaddr_t), (char *)&frame); - if (frame == 0) - break; - lastlr = lr; - db_read_bytes(frame + 8, sizeof(vaddr_t), (char *)&lr); - if (name != NULL) { if ((strcmp (name, "handle_el0_irq") == 0) || (strcmp (name, "handle_el1_irq") == 0)) { @@ -125,15 +123,39 @@ db_stack_trace_print(db_expr_t addr, int have_addr, db_expr_t count, (*pr)("--- trap ---\n"); } } + + lastframe = frame; + db_read_bytes(frame, sizeof(vaddr_t), (char *)&frame); + + if (frame == 0) { + /* end of chain */ + break; + } + if (INKERNEL(frame)) { + /* staying in kernel */ if (frame <= lastframe) { (*pr)("Bad frame pointer: 0x%lx\n", frame); break; } + } else if (INKERNEL(lastframe)) { + /* switch from user to kernel */ + if (kernel_only) { + (*pr)("end of kernel\n"); + break; /* kernel stack only */ + } } else { - if (kernel_only) + /* in user */ + if (frame <= lastframe) { + (*pr)("Bad user frame pointer: 0x%lx\n", + frame); break; + } } + + lastlr = lr; + db_read_bytes(frame + 8, sizeof(vaddr_t), (char *)&lr); + --count; } } diff --git a/sys/arch/arm64/arm64/exception.S b/sys/arch/arm64/arm64/exception.S index 1a1ff5fb6d1..101de9ef803 100644 --- a/sys/arch/arm64/arm64/exception.S +++ b/sys/arch/arm64/arm64/exception.S @@ -1,4 +1,4 @@ -/* $OpenBSD: exception.S,v 1.16 2023/12/26 09:19:15 kettenis Exp $ */ +/* $OpenBSD: exception.S,v 1.17 2024/03/12 13:32:53 kettenis Exp $ */ /*- * Copyright (c) 2014 Andrew Turner * All rights reserved. @@ -38,7 +38,6 @@ sub sp, sp, #128 .endif sub sp, sp, #(TF_SIZE + 16) - stp x29, x30, [sp, #(TF_SIZE)] stp x28, x29, [sp, #(TF_X + 28 * 8)] stp x26, x27, [sp, #(TF_X + 26 * 8)] stp x24, x25, [sp, #(TF_X + 24 * 8)] @@ -59,11 +58,11 @@ .if \el == 0 mrs x18, sp_el0 .endif - mov fp, x18 stp x10, x11, [sp, #(TF_ELR)] stp x18, lr, [sp, #(TF_SP)] + stp fp, x10, [sp, #(TF_SIZE)] mrs x18, tpidr_el1 - add x29, sp, #(TF_SIZE) + add fp, sp, #(TF_SIZE) .endm .macro restore_registers el -- 2.20.1