Module Name: src Committed By: ryo Date: Tue Jun 7 23:55:25 UTC 2022
Modified Files: src/sys/arch/aarch64/aarch64: db_trace.c Log Message: Functionalize frame pointer backtrace. To generate a diff of this commit: cvs rdiff -u -r1.18 -r1.19 src/sys/arch/aarch64/aarch64/db_trace.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/aarch64/aarch64/db_trace.c diff -u src/sys/arch/aarch64/aarch64/db_trace.c:1.18 src/sys/arch/aarch64/aarch64/db_trace.c:1.19 --- src/sys/arch/aarch64/aarch64/db_trace.c:1.18 Tue Jun 7 08:08:31 2022 +++ src/sys/arch/aarch64/aarch64/db_trace.c Tue Jun 7 23:55:25 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: db_trace.c,v 1.18 2022/06/07 08:08:31 ryo Exp $ */ +/* $NetBSD: db_trace.c,v 1.19 2022/06/07 23:55:25 ryo Exp $ */ /* * Copyright (c) 2017 Ryo Shimizu <r...@nerv.org> @@ -28,7 +28,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.18 2022/06/07 08:08:31 ryo Exp $"); +__KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.19 2022/06/07 23:55:25 ryo Exp $"); #include <sys/param.h> #include <sys/bitops.h> @@ -598,11 +598,90 @@ db_sp_trace(struct trapframe *tf, db_add } } +static void +db_fp_trace(struct trapframe *tf, db_addr_t fp, db_expr_t count, int flags, + void (*pr)(const char *, ...) __printflike(1, 2)) +{ + uint64_t lr; + uint64_t lastlr, lastfp; + + if (tf != NULL) { + pr_frame(tf, pr); + lastfp = lastlr = lr = fp = 0; + + db_read_bytes((db_addr_t)&tf->tf_pc, sizeof(lr), (char *)&lr); + db_read_bytes((db_addr_t)&tf->tf_reg[29], sizeof(fp), (char *)&fp); + lr = aarch64_strip_pac(lr); + + pr_traceaddr("fp", fp, lr - 4, flags, pr); + } + + for (; (count > 0) && (fp != 0); count--) { + + lastfp = fp; + fp = lr = 0; + /* + * normal stack frame + * fp[0] saved fp(x29) value + * fp[1] saved lr(x30) value + */ + db_read_bytes(lastfp + 0, sizeof(fp), (char *)&fp); + db_read_bytes(lastfp + 8, sizeof(lr), (char *)&lr); + lr = aarch64_strip_pac(lr); + + if (lr == 0 || ((flags & TRACEFLAG_USERSPACE) == 0 && + IN_USER_VM_ADDRESS(lr))) + break; + + if (((char *)(lr - 4) == (char *)el0_trap) || + ((char *)(lr - 4) == (char *)el1_trap)) { + + tf = (struct trapframe *)fp; + + lastfp = (uint64_t)tf; + lastlr = lr; + lr = fp = 0; + db_read_bytes((db_addr_t)&tf->tf_pc, sizeof(lr), + (char *)&lr); + if (lr == 0) { + /* + * The exception may have been from a + * jump to null, so the null pc we + * would return to is useless. Try + * x[30] instead -- that will be the + * return address for the jump. + */ + db_read_bytes((db_addr_t)&tf->tf_reg[30], + sizeof(lr), (char *)&lr); + } + db_read_bytes((db_addr_t)&tf->tf_reg[29], sizeof(fp), + (char *)&fp); + lr = aarch64_strip_pac(lr); + + pr_traceaddr("tf", (db_addr_t)tf, lastlr - 4, flags, pr); + + if (lr == 0) + break; + + pr_frame(tf, pr); + tf = NULL; + + if ((flags & TRACEFLAG_USERSPACE) == 0 && + IN_USER_VM_ADDRESS(lr)) + break; + + pr_traceaddr("fp", fp, lr, flags, pr); + } else { + pr_traceaddr("fp", fp, lr - 4, flags, pr); + } + } +} + void db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif, void (*pr)(const char *, ...) __printflike(1, 2)) { - uint64_t lr, fp, lastlr, lastfp; + uint64_t fp; struct trapframe *tf = NULL; int flags = 0; bool trace_thread = false; @@ -734,78 +813,8 @@ db_stack_trace_print(db_expr_t addr, boo if (trace_sp) { /* trace $lr pushed to sp */ db_sp_trace(tf, fp, count, flags, pr); - return; - } - - /* trace $fp linked list */ - if (tf != NULL) { - pr_frame(tf, pr); - lastfp = lastlr = lr = fp = 0; - - db_read_bytes((db_addr_t)&tf->tf_pc, sizeof(lr), (char *)&lr); - db_read_bytes((db_addr_t)&tf->tf_reg[29], sizeof(fp), (char *)&fp); - lr = aarch64_strip_pac(lr); - - pr_traceaddr("fp", fp, lr - 4, flags, pr); - } - - for (; (count > 0) && (fp != 0); count--) { - - lastfp = fp; - fp = lr = 0; - /* - * normal stack frame - * fp[0] saved fp(x29) value - * fp[1] saved lr(x30) value - */ - db_read_bytes(lastfp + 0, sizeof(fp), (char *)&fp); - db_read_bytes(lastfp + 8, sizeof(lr), (char *)&lr); - lr = aarch64_strip_pac(lr); - - if (lr == 0 || ((flags & TRACEFLAG_USERSPACE) == 0 && - IN_USER_VM_ADDRESS(lr))) - break; - - if (((char *)(lr - 4) == (char *)el0_trap) || - ((char *)(lr - 4) == (char *)el1_trap)) { - - tf = (struct trapframe *)fp; - - lastfp = (uint64_t)tf; - lastlr = lr; - lr = fp = 0; - db_read_bytes((db_addr_t)&tf->tf_pc, sizeof(lr), - (char *)&lr); - if (lr == 0) { - /* - * The exception may have been from a - * jump to null, so the null pc we - * would return to is useless. Try - * x[30] instead -- that will be the - * return address for the jump. - */ - db_read_bytes((db_addr_t)&tf->tf_reg[30], - sizeof(lr), (char *)&lr); - } - db_read_bytes((db_addr_t)&tf->tf_reg[29], sizeof(fp), - (char *)&fp); - lr = aarch64_strip_pac(lr); - - pr_traceaddr("tf", (db_addr_t)tf, lastlr - 4, flags, pr); - - if (lr == 0) - break; - - pr_frame(tf, pr); - tf = NULL; - - if ((flags & TRACEFLAG_USERSPACE) == 0 && - IN_USER_VM_ADDRESS(lr)) - break; - - pr_traceaddr("fp", fp, lr, flags, pr); - } else { - pr_traceaddr("fp", fp, lr - 4, flags, pr); - } + } else { + /* trace $fp linked list */ + db_fp_trace(tf, fp, count, flags, pr); } }