1 1.6 skrll /* $NetBSD: db_trace.c,v 1.6 2023/10/06 11:45:16 skrll Exp $ */ 2 1.1 cherry 3 1.1 cherry /* Inspired by reading alpha/db_trace.c */ 4 1.1 cherry 5 1.1 cherry /*- 6 1.1 cherry * Copyright (c) 2006 The NetBSD Foundation, Inc. 7 1.1 cherry * All rights reserved. 8 1.1 cherry * 9 1.1 cherry * Author: Cherry G. Mathew 10 1.1 cherry * 11 1.1 cherry * Redistribution and use in source and binary forms, with or without 12 1.1 cherry * modification, are permitted provided that the following conditions 13 1.1 cherry * are met: 14 1.1 cherry * 1. Redistributions of source code must retain the above copyright 15 1.1 cherry * notice, this list of conditions and the following disclaimer. 16 1.1 cherry * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 cherry * notice, this list of conditions and the following disclaimer in the 18 1.1 cherry * documentation and/or other materials provided with the distribution. 19 1.1 cherry * 20 1.1 cherry * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.1 cherry * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.1 cherry * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.1 cherry * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.1 cherry * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.1 cherry * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.1 cherry * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.1 cherry * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.1 cherry * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 cherry * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 cherry * POSSIBILITY OF SUCH DAMAGE. 31 1.1 cherry */ 32 1.1 cherry 33 1.1 cherry 34 1.1 cherry #include "opt_ddb.h" 35 1.1 cherry 36 1.1 cherry #include <sys/param.h> 37 1.1 cherry #include <sys/proc.h> 38 1.1 cherry #include <sys/systm.h> 39 1.1 cherry 40 1.1 cherry #include <machine/cpufunc.h> 41 1.1 cherry #include <machine/md_var.h> 42 1.1 cherry #include <machine/db_machdep.h> 43 1.1 cherry 44 1.1 cherry #include <ddb/db_sym.h> 45 1.1 cherry #include <ddb/db_access.h> 46 1.1 cherry #include <ddb/db_output.h> 47 1.1 cherry #include <ddb/db_variables.h> 48 1.1 cherry #include <ddb/db_interface.h> 49 1.1 cherry 50 1.1 cherry #include <ia64/unwind/decode.h> 51 1.1 cherry #include <ia64/unwind/stackframe.h> 52 1.1 cherry 53 1.1 cherry #if 0 54 1.1 cherry #define UNWIND_DIAGNOSTIC 55 1.1 cherry #endif 56 1.1 cherry 57 1.1 cherry #define debug_frame_dump_XXX(uwf) \ 58 1.1 cherry printf("Frame Dump: \n bsp = 0x%lx \n pfs = 0x%lx, SOL(pfs) = %lu \n rp = 0x%lx \n", \ 59 1.1 cherry uwf->bsp, uwf->pfs, IA64_CFM_SOL(uwf->pfs), uwf->rp); \ 60 1.1 cherry 61 1.1 cherry void 62 1.1 cherry initunwindframe(struct unwind_frame *uwf, struct trapframe *tf); 63 1.1 cherry void 64 1.1 cherry rewindframe(struct unwind_frame *uwf, db_addr_t ip); 65 1.1 cherry 66 1.1 cherry void 67 1.2 thorpej db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count, 68 1.1 cherry const char *modif, void (*pr)(const char *, ...)) 69 1.1 cherry { 70 1.1 cherry char c; 71 1.1 cherry const char *cp = modif; 72 1.3 thorpej bool trace_thread = false; 73 1.3 thorpej bool trace_user = false; 74 1.1 cherry struct trapframe *tf; 75 1.1 cherry struct unwind_frame current_frame; 76 1.1 cherry db_addr_t ip; 77 1.1 cherry const char *name; 78 1.1 cherry db_sym_t sym; 79 1.1 cherry db_expr_t offset; 80 1.1 cherry 81 1.1 cherry while ((c = *cp++) != 0) { 82 1.1 cherry trace_thread |= c == 't'; 83 1.1 cherry trace_user |= c == 'u'; 84 1.1 cherry } 85 1.1 cherry 86 1.1 cherry if (trace_user) { 87 1.1 cherry (*pr)("User-space stack tracing not implemented yet. \n"); 88 1.1 cherry return; 89 1.1 cherry } 90 1.1 cherry if (!have_addr) { 91 1.1 cherry (*pr)("--Kernel Call Trace-- \n"); 92 1.1 cherry 93 1.1 cherry tf = DDB_REGS; 94 1.1 cherry ip = tf->tf_special.iip + ((tf->tf_special.psr >> 41) & 3); 95 1.1 cherry 96 1.1 cherry initunwindframe(¤t_frame, tf); 97 1.1 cherry 98 1.1 cherry #ifdef UNWIND_DIAGNOSTIC 99 1.1 cherry struct unwind_frame *uwf = ¤t_frame; 100 1.1 cherry debug_frame_dump_XXX(uwf); 101 1.1 cherry #endif 102 1.5 dholland KASSERT(ip >= kernstart); 103 1.1 cherry patchunwindframe(¤t_frame, ip - kernstart, kernstart); 104 1.1 cherry #ifdef UNWIND_DIAGNOSTIC 105 1.1 cherry debug_frame_dump_XXX(uwf); 106 1.1 cherry #endif 107 1.1 cherry /* Get into unwind loop. */ 108 1.1 cherry 109 1.1 cherry while(ip) { 110 1.1 cherry sym = db_search_symbol(ip, DB_STGY_ANY, &offset); 111 1.1 cherry db_symbol_values(sym, &name, NULL); 112 1.1 cherry (*pr)("%s(...)\n", name); 113 1.1 cherry 114 1.1 cherry ip = current_frame.rp; 115 1.1 cherry 116 1.1 cherry if(!ip) break; 117 1.1 cherry 118 1.1 cherry rewindframe(¤t_frame, ip); 119 1.1 cherry } 120 1.1 cherry 121 1.1 cherry return; 122 1.1 cherry 123 1.1 cherry 124 1.1 cherry } else (*pr) ("Unwind from arbitrary addresses unimplemented. \n"); 125 1.6 skrll 126 1.1 cherry 127 1.1 cherry if (trace_thread) { 128 1.1 cherry (*pr)("trace by pid unimplemented. \n"); 129 1.1 cherry return; 130 1.1 cherry } 131 1.1 cherry else { 132 1.1 cherry (*pr)("trace from arbitrary trap frame address unimplemented. \n"); 133 1.1 cherry } 134 1.1 cherry 135 1.1 cherry } 136 1.1 cherry 137 1.1 cherry extern db_addr_t ia64_unwindtab; 138 1.1 cherry extern vsize_t ia64_unwindtablen; 139 1.1 cherry 140 1.1 cherry 141 1.1 cherry /* Generates initial unwind frame context based on the contents 142 1.6 skrll * of the trap frame, by consulting the Unwind library 143 1.1 cherry * staterecord. If a register is of type enum UNSAVED, we fetch 144 1.1 cherry * the live value of the register from the trapframe. 145 1.1 cherry */ 146 1.1 cherry 147 1.1 cherry void 148 1.1 cherry initunwindframe(struct unwind_frame *uwf, struct trapframe *tf) 149 1.6 skrll 150 1.1 cherry { 151 1.1 cherry 152 1.1 cherry uwf->rp = tf->tf_special.rp; 153 1.1 cherry 154 1.1 cherry /* ndirty = bsp - bspstore: , not the same as the definition in the spec. 155 1.1 cherry * Gave me hell for a day! 156 1.1 cherry * see: ia64/exception.S: exception_save_restore: */ 157 1.1 cherry 158 1.1 cherry uwf->bsp = tf->tf_special.bspstore + tf->tf_special.ndirty; 159 1.1 cherry uwf->bsp = ia64_bsp_adjust_ret(uwf->bsp, IA64_CFM_SOF(tf->tf_special.cfm)); 160 1.1 cherry #ifdef UNWIND_DIAGNOSTIC 161 1.1 cherry printf("inituwframe(): SOF(cfm) = %lu \n", IA64_CFM_SOF(tf->tf_special.cfm)); 162 1.1 cherry #endif 163 1.1 cherry uwf->pfs = tf->tf_special.pfs; 164 1.1 cherry uwf->sp = uwf->psp = tf->tf_special.sp; 165 1.1 cherry 166 1.1 cherry 167 1.1 cherry } 168 1.1 cherry 169 1.1 cherry 170 1.6 skrll 171 1.6 skrll /* Single step the frame backward. 172 1.1 cherry * Assumes unwind_frame is setup already. 173 1.1 cherry */ 174 1.1 cherry 175 1.1 cherry void 176 1.1 cherry rewindframe(struct unwind_frame *uwf, db_addr_t ip) 177 1.1 cherry { 178 1.1 cherry /* XXX: Check for a stack switch */ 179 1.1 cherry 180 1.1 cherry uwf->bsp = ia64_bsp_adjust_ret(uwf->bsp, IA64_CFM_SOL(uwf->pfs)); 181 1.1 cherry uwf->sp = uwf->psp; 182 1.1 cherry 183 1.1 cherry /* Pre-stomp frame dump */ 184 1.1 cherry #ifdef UNWIND_DIAGNOSTIC 185 1.1 cherry debug_frame_dump_XXX(uwf); 186 1.1 cherry #endif 187 1.1 cherry 188 1.6 skrll /* Stomp on rp and pfs 189 1.1 cherry */ 190 1.5 dholland KASSERT(ip >= kernstart); 191 1.1 cherry patchunwindframe(uwf, ip - kernstart, kernstart); 192 1.1 cherry 193 1.1 cherry #ifdef UNWIND_DIAGNOSTIC 194 1.1 cherry debug_frame_dump_XXX(uwf); 195 1.1 cherry #endif 196 1.1 cherry 197 1.1 cherry } 198