180709Sjake/*- 280709Sjake * Copyright (c) 2001 Jake Burkholder. 380709Sjake * All rights reserved. 480709Sjake * 580709Sjake * Redistribution and use in source and binary forms, with or without 680709Sjake * modification, are permitted provided that the following conditions 780709Sjake * are met: 880709Sjake * 1. Redistributions of source code must retain the above copyright 980709Sjake * notice, this list of conditions and the following disclaimer. 1080709Sjake * 2. Redistributions in binary form must reproduce the above copyright 1180709Sjake * notice, this list of conditions and the following disclaimer in the 1280709Sjake * documentation and/or other materials provided with the distribution. 1380709Sjake * 1481337Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1580709Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1680709Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1781337Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1880709Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1980709Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2080709Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2180709Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2280709Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2380709Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2480709Sjake * SUCH DAMAGE. 2580709Sjake */ 2680709Sjake 27155839Smarius#include <sys/cdefs.h> 28155839Smarius__FBSDID("$FreeBSD: releng/10.3/sys/sparc64/sparc64/db_trace.c 217265 2011-01-11 13:59:06Z jhb $"); 29155839Smarius 3080709Sjake#include <sys/param.h> 3180709Sjake#include <sys/systm.h> 32131952Smarcel#include <sys/kdb.h> 3380709Sjake#include <sys/proc.h> 34148666Sjeff#include <sys/stack.h> 3586525Sjake#include <sys/sysent.h> 3680709Sjake 3780709Sjake#include <vm/vm.h> 3880709Sjake#include <vm/vm_page.h> 3980709Sjake#include <vm/vm_map.h> 4080709Sjake 4180709Sjake#include <machine/cpu.h> 42138129Sdas#include <machine/pcb.h> 43174195Srwatson#include <machine/stack.h> 4480709Sjake#include <machine/trap.h> 4580709Sjake#include <machine/vmparam.h> 4680709Sjake 4780709Sjake#include <ddb/ddb.h> 4880709Sjake#include <ddb/db_access.h> 4980709Sjake#include <ddb/db_sym.h> 5080709Sjake#include <ddb/db_variables.h> 5180709Sjake#include <ddb/db_watch.h> 5280709Sjake 53131952Smarcelstatic db_varfcn_t db_frame; 54131952Smarcel 55131952Smarcel#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) 5680709Sjakestruct db_variable db_regs[] = { 57131952Smarcel { "g0", DB_OFFSET(tf_global[0]), db_frame }, 58131952Smarcel { "g1", DB_OFFSET(tf_global[1]), db_frame }, 59131952Smarcel { "g2", DB_OFFSET(tf_global[2]), db_frame }, 60131952Smarcel { "g3", DB_OFFSET(tf_global[3]), db_frame }, 61131952Smarcel { "g4", DB_OFFSET(tf_global[4]), db_frame }, 62131952Smarcel { "g5", DB_OFFSET(tf_global[5]), db_frame }, 63131952Smarcel { "g6", DB_OFFSET(tf_global[6]), db_frame }, 64131952Smarcel { "g7", DB_OFFSET(tf_global[7]), db_frame }, 65131952Smarcel { "i0", DB_OFFSET(tf_out[0]), db_frame }, 66131952Smarcel { "i1", DB_OFFSET(tf_out[1]), db_frame }, 67131952Smarcel { "i2", DB_OFFSET(tf_out[2]), db_frame }, 68131952Smarcel { "i3", DB_OFFSET(tf_out[3]), db_frame }, 69131952Smarcel { "i4", DB_OFFSET(tf_out[4]), db_frame }, 70131952Smarcel { "i5", DB_OFFSET(tf_out[5]), db_frame }, 71131952Smarcel { "i6", DB_OFFSET(tf_out[6]), db_frame }, 72131952Smarcel { "i7", DB_OFFSET(tf_out[7]), db_frame }, 73131952Smarcel { "tnpc", DB_OFFSET(tf_tnpc), db_frame }, 74131952Smarcel { "tpc", DB_OFFSET(tf_tpc), db_frame }, 75131952Smarcel { "tstate", DB_OFFSET(tf_tstate), db_frame }, 7680709Sjake}; 7780709Sjakestruct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); 7880709Sjake 79131952Smarcelstatic int 80131952Smarceldb_frame(struct db_variable *vp, db_expr_t *valuep, int op) 8180709Sjake{ 82131952Smarcel uint64_t *reg; 8380709Sjake 84131952Smarcel if (kdb_frame == NULL) 85131952Smarcel return (0); 86131952Smarcel reg = (uint64_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep); 87131952Smarcel if (op == DB_VAR_GET) 88131952Smarcel *valuep = *reg; 89131952Smarcel else 90131952Smarcel *reg = *valuep; 91131952Smarcel return (1); 92131952Smarcel} 93131952Smarcel 94131952Smarcel/* 95131952Smarcel * User stack trace (debugging aid). 96131952Smarcel */ 97131952Smarcelstatic void 98160312Sjhbdb_utrace(struct thread *td, struct trapframe *tf, int count) 99131952Smarcel{ 100131952Smarcel struct pcb *pcb; 101131952Smarcel db_addr_t sp, rsp, o7, pc; 102131952Smarcel int i, found; 103131952Smarcel 104131952Smarcel pcb = td->td_pcb; 105131952Smarcel sp = db_get_value((db_addr_t)&tf->tf_sp, sizeof(tf->tf_sp), FALSE); 106131952Smarcel o7 = db_get_value((db_addr_t)&tf->tf_out[7], sizeof(tf->tf_out[7]), 107131952Smarcel FALSE); 108131952Smarcel pc = db_get_value((db_addr_t)&tf->tf_tpc, sizeof(tf->tf_tpc), FALSE); 109131952Smarcel db_printf("user trace: trap %%o7=%#lx\n", o7); 110160312Sjhb while (count-- && sp != 0 && !db_pager_quit) { 111131952Smarcel db_printf("pc %#lx, sp %#lx\n", pc, sp); 112131952Smarcel /* First, check whether the frame is in the pcb. */ 113131952Smarcel found = 0; 114131952Smarcel for (i = 0; i < pcb->pcb_nsaved; i++) { 115131952Smarcel if (pcb->pcb_rwsp[i] == sp) { 116131952Smarcel found = 1; 117131952Smarcel sp = pcb->pcb_rw[i].rw_in[6]; 118131952Smarcel pc = pcb->pcb_rw[i].rw_in[7]; 119131952Smarcel break; 12088635Sjake } 12186525Sjake } 122131952Smarcel if (!found) { 123131952Smarcel rsp = sp + SPOFF; 124131952Smarcel sp = 0; 125131952Smarcel if (copyin((void *)(rsp + offsetof(struct frame, fr_fp)), 126131952Smarcel &sp, sizeof(sp)) != 0 || 127131952Smarcel copyin((void *)(rsp + offsetof(struct frame, fr_pc)), 128131952Smarcel &pc, sizeof(pc)) != 0) 129131952Smarcel break; 13080709Sjake } 13180709Sjake } 132131952Smarcel db_printf("done\n"); 13380709Sjake} 13480709Sjake 13581379Sjakestatic int 136160312Sjhbdb_print_trap(struct thread *td, struct trapframe *tf, int count) 13780709Sjake{ 13893028Sjake struct proc *p; 13986525Sjake const char *symname; 14086525Sjake c_db_sym_t sym; 14186525Sjake db_expr_t diff; 14286525Sjake db_addr_t func; 14386525Sjake db_addr_t tpc; 14480709Sjake u_long type; 14588635Sjake u_long sfar; 14688635Sjake u_long sfsr; 14788635Sjake u_long tar; 14888635Sjake u_long level; 14988635Sjake u_long pil; 15086525Sjake u_long code; 15193028Sjake u_long o7; 15288635Sjake int user; 15380709Sjake 15493028Sjake p = td->td_proc; 15588635Sjake type = db_get_value((db_addr_t)&tf->tf_type, 15688635Sjake sizeof(tf->tf_type), FALSE); 15786525Sjake db_printf("-- %s", trap_msg[type & ~T_KERNEL]); 15880709Sjake switch (type & ~T_KERNEL) { 15988635Sjake case T_DATA_PROTECTION: 16088635Sjake tar = (u_long)db_get_value((db_addr_t)&tf->tf_tar, 16188635Sjake sizeof(tf->tf_tar), FALSE); 16288635Sjake db_printf(" tar=%#lx", tar); 16388635Sjake /* fall through */ 16488635Sjake case T_DATA_EXCEPTION: 16588635Sjake case T_INSTRUCTION_EXCEPTION: 16688635Sjake case T_MEM_ADDRESS_NOT_ALIGNED: 16788635Sjake sfar = (u_long)db_get_value((db_addr_t)&tf->tf_sfar, 16888635Sjake sizeof(tf->tf_sfar), FALSE); 16988635Sjake sfsr = (u_long)db_get_value((db_addr_t)&tf->tf_sfsr, 17088635Sjake sizeof(tf->tf_sfsr), FALSE); 17188635Sjake db_printf(" sfar=%#lx sfsr=%#lx", sfar, sfsr); 17280709Sjake break; 17388635Sjake case T_DATA_MISS: 17488635Sjake case T_INSTRUCTION_MISS: 17588635Sjake tar = (u_long)db_get_value((db_addr_t)&tf->tf_tar, 17688635Sjake sizeof(tf->tf_tar), FALSE); 17788635Sjake db_printf(" tar=%#lx", tar); 17888635Sjake break; 17986525Sjake case T_SYSCALL: 18086525Sjake code = db_get_value((db_addr_t)&tf->tf_global[1], 18188635Sjake sizeof(tf->tf_global[1]), FALSE); 18286525Sjake db_printf(" (%ld", code); 18386525Sjake if (code >= 0 && code < p->p_sysent->sv_size) { 18486525Sjake func = (db_addr_t)p->p_sysent->sv_table[code].sy_call; 18586525Sjake sym = db_search_symbol(func, DB_STGY_ANY, &diff); 18686525Sjake if (sym != DB_SYM_NULL && diff == 0) { 18786525Sjake db_symbol_values(sym, &symname, NULL); 18886525Sjake db_printf(", %s, %s", p->p_sysent->sv_name, 18986525Sjake symname); 19086525Sjake } 19186525Sjake db_printf(")"); 19286525Sjake } 19386525Sjake break; 19488635Sjake case T_INTERRUPT: 19588635Sjake level = (u_long)db_get_value((db_addr_t)&tf->tf_level, 19688635Sjake sizeof(tf->tf_level), FALSE); 19788635Sjake pil = (u_long)db_get_value((db_addr_t)&tf->tf_pil, 19888635Sjake sizeof(tf->tf_pil), FALSE); 19988635Sjake db_printf(" level=%#lx pil=%#lx", level, pil); 20088635Sjake break; 20180709Sjake default: 20280709Sjake break; 20380709Sjake } 20493028Sjake o7 = (u_long)db_get_value((db_addr_t)&tf->tf_out[7], 20593028Sjake sizeof(tf->tf_out[7]), FALSE); 20693028Sjake db_printf(" %%o7=%#lx --\n", o7); 20788635Sjake user = (type & T_KERNEL) == 0; 20888635Sjake if (user) { 20988635Sjake tpc = db_get_value((db_addr_t)&tf->tf_tpc, 21088635Sjake sizeof(tf->tf_tpc), FALSE); 21188635Sjake db_printf("userland() at "); 21288635Sjake db_printsym(tpc, DB_STGY_PROC); 21388635Sjake db_printf("\n"); 214160312Sjhb db_utrace(td, tf, count); 21580709Sjake } 21688635Sjake return (user); 21780709Sjake} 21893028Sjake 219131952Smarcelstatic int 220131952Smarceldb_backtrace(struct thread *td, struct frame *fp, int count) 22193028Sjake{ 222131952Smarcel struct trapframe *tf; 223131952Smarcel const char *name; 224131952Smarcel c_db_sym_t sym; 225131952Smarcel db_expr_t offset; 226131952Smarcel db_expr_t value; 227131952Smarcel db_addr_t npc; 228131952Smarcel db_addr_t pc; 229131952Smarcel int trap; 230131952Smarcel int user; 23193028Sjake 232131952Smarcel if (count == -1) 233131952Smarcel count = 1024; 234131952Smarcel 235131952Smarcel trap = 0; 236131952Smarcel user = 0; 237131952Smarcel npc = 0; 238160312Sjhb while (count-- && !user && !db_pager_quit) { 239131952Smarcel pc = (db_addr_t)db_get_value((db_addr_t)&fp->fr_pc, 240131952Smarcel sizeof(fp->fr_pc), FALSE); 241131952Smarcel if (trap) { 242131952Smarcel pc = npc; 243131952Smarcel trap = 0; 24493028Sjake } 245131952Smarcel if (!INKERNEL((vm_offset_t)pc)) 246131952Smarcel break; 247131952Smarcel sym = db_search_symbol(pc, DB_STGY_ANY, &offset); 248131952Smarcel if (sym == C_DB_SYM_NULL) { 249131952Smarcel value = 0; 250131952Smarcel name = NULL; 251131952Smarcel } else 252131952Smarcel db_symbol_values(sym, &name, &value); 253131952Smarcel if (name == NULL) 254131952Smarcel name = "(null)"; 255131952Smarcel fp = (struct frame *)(db_get_value((db_addr_t)&fp->fr_fp, 256131952Smarcel sizeof(fp->fr_fp), FALSE) + SPOFF); 257155839Smarius if ((value > (u_long)tl_trap_begin && 258155839Smarius value < (u_long)tl_trap_end) || 259155839Smarius (value > (u_long)tl_text_begin && 260155839Smarius value < (u_long)tl_text_end)) { 261131952Smarcel tf = (struct trapframe *)(fp + 1); 262131952Smarcel npc = db_get_value((db_addr_t)&tf->tf_tpc, 263131952Smarcel sizeof(tf->tf_tpc), FALSE); 264160312Sjhb user = db_print_trap(td, tf, count); 265131952Smarcel trap = 1; 266131952Smarcel } else { 267131952Smarcel db_printf("%s() at ", name); 268131952Smarcel db_printsym(pc, DB_STGY_PROC); 269131952Smarcel db_printf("\n"); 27093028Sjake } 27193028Sjake } 272131952Smarcel return (0); 27393028Sjake} 274103646Sjhb 275103646Sjhbvoid 276131952Smarceldb_trace_self(void) 277131952Smarcel{ 278131952Smarcel 279184376Smarius db_backtrace(curthread, 280184376Smarius (struct frame *)__builtin_frame_address(1), -1); 281131952Smarcel} 282131952Smarcel 283131952Smarcelint 284131952Smarceldb_trace_thread(struct thread *td, int count) 285131952Smarcel{ 286131952Smarcel struct pcb *ctx; 287131952Smarcel 288131952Smarcel ctx = kdb_thr_ctx(td); 289184376Smarius return (db_backtrace(td, 290184376Smarius (struct frame *)(ctx->pcb_sp + SPOFF), count)); 291131952Smarcel} 292