Home | History | Annotate | Line # | Download | only in hppa
      1 /*	$NetBSD: db_trace.c,v 1.13 2013/10/19 14:03:04 skrll Exp $	*/
      2 
      3 /*	$OpenBSD: db_interface.c,v 1.16 2001/03/22 23:31:45 mickey Exp $	*/
      4 
      5 /*
      6  * Copyright (c) 1999-2003 Michael Shalayeff
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
     22  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     24  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     28  * THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include <sys/cdefs.h>
     32 __KERNEL_RCSID(0, "$NetBSD: db_trace.c,v 1.13 2013/10/19 14:03:04 skrll Exp $");
     33 
     34 #include <sys/param.h>
     35 #include <sys/systm.h>
     36 #include <sys/proc.h>
     37 
     38 #include <machine/db_machdep.h>
     39 
     40 #include <ddb/db_access.h>
     41 #include <ddb/db_sym.h>
     42 #include <ddb/db_interface.h>
     43 #include <ddb/db_proc.h>
     44 
     45 void
     46 db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
     47     const char *modif, void (*pr)(const char *, ...))
     48 {
     49 	register_t *fp, pc, rp;
     50 #if 0
     51 	bool kernel_only = true;
     52 #endif
     53 	bool trace_thread = false;
     54 	bool lwpaddr = false;
     55 	db_sym_t sym;
     56 	db_expr_t off;
     57 	const char *name;
     58 	const char *cp = modif;
     59 	char c;
     60 
     61 	if (count < 0)
     62 		count = 65536;
     63 
     64 	while ((c = *cp++) != 0) {
     65 		if (c == 'a') {
     66 			lwpaddr = true;
     67 			trace_thread = true;
     68 		}
     69 		if (c == 't')
     70 			trace_thread = true;
     71 #if 0
     72 		if (c == 'u')
     73 			kernel_only = false;
     74 #endif
     75 	}
     76 
     77 	if (!have_addr) {
     78 		fp = (register_t *)ddb_regs.tf_r3;
     79 		pc = ddb_regs.tf_iioq_head;
     80 		rp = ddb_regs.tf_rp;
     81 	} else {
     82 		if (trace_thread) {
     83 			proc_t p;
     84 			lwp_t l;
     85 			pid_t pid;
     86 
     87 			if (lwpaddr) {
     88 				db_read_bytes(addr, sizeof(l), (char *)&l);
     89 				db_read_bytes((db_addr_t)l.l_proc, sizeof(p),
     90 				    (char *)&p);
     91 				(*pr)("trace: pid %d ", p.p_pid);
     92 			} else {
     93 				proc_t *pp;
     94 
     95 				pid = (pid_t)addr;
     96 				(*pr)("trace: pid %d ", pid);
     97 				pp = db_proc_find(pid);
     98 				if (pp == NULL) {
     99 					(*pr)("not found\n");
    100 					return;
    101 				}
    102 				db_read_bytes((db_addr_t)pp, sizeof(p),
    103 				    (char *)&p);
    104 				addr = (db_addr_t)p.p_lwps.lh_first;
    105 				db_read_bytes(addr, sizeof(l), (char *)&l);
    106 			}
    107 			(*pr)("lid %d ", l.l_lid);
    108 #ifdef _KERNEL
    109 			if (l.l_proc == curproc && (lwp_t *)addr == curlwp) {
    110 				fp = (int *)ddb_regs.tf_r3;
    111 				pc = ddb_regs.tf_iioq_head;
    112 				rp = ddb_regs.tf_rp;
    113 			} else
    114 #endif
    115 			{
    116 				struct pcb *pcb = lwp_getpcb(&l);
    117 				register_t sp;
    118 				/* cpu_switchto fp, and return point */
    119 				db_read_bytes((db_addr_t)&pcb->pcb_ksp,
    120 				    sizeof(sp), (char *)&sp);
    121 				fp = (register_t *)(sp -
    122 				    (HPPA_FRAME_SIZE + 16*4));
    123 				pc = 0;
    124 
    125 				db_read_bytes((db_addr_t)&fp[-5], sizeof(rp),
    126 				    (char *)&rp);
    127 			}
    128 			(*pr)("at %p\n", fp);
    129 		} else {
    130 			pc = 0;
    131 			fp = (register_t *)addr;
    132 			db_read_bytes((db_addr_t)&fp[-5], sizeof(rp),
    133 			    (char *)&rp);
    134 		}
    135 	}
    136 
    137 	while (fp && count--) {
    138 		register_t *newfp;
    139 #ifdef DDB_DEBUG
    140 		pr(">> %08x %08x %08x\t", fp, pc, rp);
    141 #endif
    142 
    143 		if (USERMODE(pc))
    144 			return;
    145 
    146 		if (pc) {
    147 			sym = db_search_symbol(pc, DB_STGY_ANY, &off);
    148 			db_symbol_values (sym, &name, NULL);
    149 
    150 			pr("%s() at ", name);
    151 			db_printsym(pc, DB_STGY_PROC, pr);
    152 			pr("\n");
    153 		}
    154 
    155 		db_read_bytes((db_addr_t)&fp[0], sizeof(newfp), (char *)&newfp);
    156 
    157 		/*
    158 		 * if a terminal frame then report the trapframe and continue
    159 		 * after it (if not the last one).
    160 		 */
    161 		if (!newfp) {
    162 			register_t scargs[5];
    163 			struct trapframe tf, *ktf;
    164 			int scoff;
    165 
    166 			/* Stack space for syscall args */
    167 			scoff = HPPA_FRAME_ROUND(HPPA_FRAME_SIZE +
    168 			    HPPA_FRAME_MAXARGS);
    169 			ktf = (struct trapframe *)((char *)fp - scoff -
    170 			    sizeof(tf));
    171 
    172 			db_read_bytes((db_addr_t)((char *)fp - scoff),
    173 			     sizeof(scargs), (char *)&scargs);
    174 			db_read_bytes((db_addr_t)ktf, sizeof(tf), (char *)&tf);
    175 
    176 			if (tf.tf_flags & TFF_SYS)
    177 				pr("-- syscall #%d(%x, %x, %x, %x, ...) (%p)\n",
    178 				    tf.tf_t1, scargs[1], scargs[2],
    179 				    scargs[3], scargs[4], ktf);
    180 			else
    181 				pr("-- trap #%d (%p) %s\n", tf.tf_flags & 0x3f,
    182 				    ktf, (tf.tf_flags & T_USER)? " from user" :
    183 				    "");
    184 
    185 			if (!(tf.tf_flags & TFF_LAST)) {
    186 				fp = (register_t *)tf.tf_r3;
    187 				pc = tf.tf_iioq_head;
    188 				rp = tf.tf_rp;
    189 			} else {
    190 				pc = 0;
    191 				fp = 0;
    192 			}
    193 		} else {
    194 			/* next frame */
    195 			fp = newfp;
    196 			pc = rp;
    197 			db_read_bytes((db_addr_t)&fp[-5], sizeof(rp),
    198 			    (char *)&rp);
    199 		}
    200 	}
    201 
    202 	if (count && pc) {
    203 		db_printsym(pc, DB_STGY_XTRN, pr);
    204 		pr(":\n");
    205 	}
    206 }
    207