Esempio n. 1
0
void
db_show_all_slocks(void)
{
	unsigned int	i, index;
	int		mycpu = cpu_number();
	usimple_lock_t	l;

	if (uslock_stack_enabled == FALSE)
		return;

#if	0
	if (!mach_slocks_init)
		iprintf("WARNING: simple locks stack may not be accurate\n");
#endif
	assert(uslock_stack_index[mycpu] >= 0);
	assert(uslock_stack_index[mycpu] <= USLOCK_STACK_DEPTH);
	index = uslock_stack_index[mycpu];
	for (i = 0; i < index; ++i) {
		l = uslock_stack[mycpu][i];
		iprintf("%d: ", i);
		db_printsym((vm_offset_t)l, DB_STGY_ANY);
		printf(" <ETAP type 0x%x> ", l->debug.etap_type);
		if (l->debug.lock_pc != INVALID_PC) {
			printf(" locked by ");
			db_printsym((int)l->debug.lock_pc, DB_STGY_PROC);
		}
		printf("\n");
	}
}
Esempio n. 2
0
void
kobjserver_stats(void)
{
    register unsigned int i, n = sizeof(mig_e)/sizeof(rpc_subsystem_t);
    register unsigned int howmany;
    register mach_msg_id_t j, pos, nentry, range;
	
    db_printf("Kobject server call counts:\n");
    for (i = 0; i < n; i++) {
	db_printf("  ");
	db_printsym((vm_offset_t)mig_e[i], DB_STGY_ANY);
	db_printf(":\n");
	range = mig_e[i]->end - mig_e[i]->start;
	if (!mig_e[i]->start || range < 0) continue;

	for  (j = 0; j < range; j++) {
	    nentry = j + mig_e[i]->start;	
	    for (pos = MIG_HASH(nentry) % MAX_MIG_ENTRIES, howmany = 1;
		 mig_buckets[pos].num;
		 pos = ++pos % MAX_MIG_ENTRIES, howmany++) {
		    if (mig_buckets[pos].num == nentry)
			bucket_stats_print(&mig_buckets[pos]);
	    }
	}
    }
}
Esempio n. 3
0
void
db_print_loc_and_inst(db_addr_t loc)
{
	db_printsym(loc, DB_STGY_PROC, db_printf);
	db_printf(":\t");
	(void) db_disasm(loc, FALSE);
}
Esempio n. 4
0
void db_show_all_slocks(void)
{
	int i;
	struct simple_locks_info *info;
	simple_lock_t l;

	for (i = 0; i < simple_locks_taken; i++) {
		info = &simple_locks_info[i];
		db_printf("%d: ", i);
		db_printsym(info->l, DB_STGY_ANY);
#if defined(__i386__)
		db_printf(" locked by ");
		db_printsym(info->ra, DB_STGY_PROC);
#endif
		db_printf("\n");
	}
}
Esempio n. 5
0
/*ARGSUSED*/
void
db_write_cmd(db_expr_t	address, boolean_t have_addr, db_expr_t count,
    char *modif)
{
	db_addr_t	addr;
	db_expr_t	old_value;
	db_expr_t	new_value;
	int		size;
	boolean_t	wrote_one = FALSE;
	char		tmpfmt[28];

	addr = (db_addr_t) address;

	switch (modif[0]) {
	case 'b':
		size = 1;
		break;
	case 'h':
		size = 2;
		break;
	case 'l':
	case '\0':
		size = 4;
		break;
#ifdef __LP64__
	case 'q':
		size = 8;
		break;
#endif
	default:
		size = -1;
		db_error("Unknown size\n");
		/*NOTREACHED*/
	}

	while (db_expression(&new_value)) {
		old_value = db_get_value(addr, size, FALSE);
		db_printsym(addr, DB_STGY_ANY, db_printf);
		db_printf("\t\t%s\t", db_format(tmpfmt, sizeof tmpfmt,
		    old_value, DB_FORMAT_N, 0, 8));
		db_printf("=\t%s\n",  db_format(tmpfmt, sizeof tmpfmt,
		    new_value, DB_FORMAT_N, 0, 8));
		db_put_value(addr, size, new_value);
		addr += size;

		wrote_one = TRUE;
	}

	if (!wrote_one) {
		db_error("Nothing written.\n");
		/*NOTREACHED*/
	}

	db_next = addr;
	db_prev = addr - size;

	db_skip_to_eol();
}
Esempio n. 6
0
void
bucket_stats_print(mig_hash_t *bucket)
{
	if (bucket->callcount) {
		db_printf("    ");
		db_printsym((vm_offset_t)bucket->routine, DB_STGY_ANY);
		db_printf(" (%d):\t%d\n", bucket->num, bucket->callcount);
	}
}
/*ARGSUSED*/
void
db_write_cmd(db_expr_t address, bool have_addr,
    db_expr_t count, const char *modif)
{
	db_addr_t	addr;
	db_expr_t	old_value;
	db_expr_t	new_value;
	int		size;
	bool		wrote_one;
	bool		show_old_val;

	addr = (db_addr_t) address;
	wrote_one = false;
	show_old_val = islower((unsigned char)modif[0]);

	switch (tolower((unsigned char)modif[0])) {
	case 'b':
		size = 1;
		break;
	case 'h':
		size = 2;
		break;
	case 'l':
	case '\0':
		size = 4;
		break;
	default:
		size = -1;
		db_error("Unknown size\n");
		/*NOTREACHED*/
	}

	while (db_expression(&new_value)) {
		db_printsym(addr, DB_STGY_ANY, db_printf);
		if (show_old_val) {
			old_value = db_get_value(addr, size, false);
			db_printf("\t\t%s = ", db_num_to_str(old_value));
			db_printf("%s\n", db_num_to_str(new_value));
		}
		else
			db_printf("\t\t= %s\n", db_num_to_str(new_value));
		db_put_value(addr, size, new_value);
		addr += size;

		wrote_one = true;
	}

	if (!wrote_one) {
		db_error("Nothing written.\n");
		/*NOTREACHED*/
	}

	db_next = addr;
	db_prev = addr - size;

	db_skip_to_eol();
}
Esempio n. 8
0
void
db_print_mutex (
	mutex_t		* addr)
{
	db_printf ("%08x %6d %7d",
		   addr, *addr, addr->lck_mtx.lck_mtx_waiters);
#if	MACH_LDEBUG
	db_printf (" %08x ", addr->thread);
	db_printsym (addr->pc, DB_STGY_ANY);
#endif	/* MACH_LDEBUG */
	db_printf ("\n");
}
Esempio n. 9
0
void
db_print_simple_lock (
	simple_lock_t	addr)
{

	db_printf ("%08x %3d", addr, *hw_lock_addr(addr->interlock));
#if	USLOCK_DEBUG
	db_printf (" %08x", addr->debug.lock_thread);
	db_printf (" %08x ", addr->debug.duration[1]);
	db_printsym ((int)addr->debug.lock_pc, DB_STGY_ANY);
#endif	/* USLOCK_DEBUG */
	db_printf ("\n");
}
Esempio n. 10
0
/*ARGSUSED*/
void
db_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
    const char *modif)
{
	db_expr_t	value;

	if (modif[0] != '\0')
		db_print_format = modif[0];

	switch (db_print_format) {
	case 'a':
		db_printsym((db_addr_t)addr, DB_STGY_ANY, db_printf);
		break;
	case 'r':
		{
			char tbuf[24];

			db_format_radix(tbuf, 24, addr, false);
			db_printf("%11s", tbuf);
			break;
		}
	case 'x':
		db_printf("%16" DDB_EXPR_FMT "x", addr);
		break;
	case 'z':
		{
			char tbuf[24];

			db_format_hex(tbuf, 24, addr, false);
			db_printf("%8s", tbuf);
			break;
		}
	case 'd':
		db_printf("%11" DDB_EXPR_FMT "d", addr);
		break;
	case 'u':
		db_printf("%11" DDB_EXPR_FMT "u", addr);
		break;
	case 'o':
		db_printf("%15" DDB_EXPR_FMT "o", addr);
		break;
	case 'c':
		value = addr & 0xFF;
		if (value >= ' ' && value <= '~')
			db_printf("%c", (char)value);
		else
			db_printf("\\%03o", (int)value);
		break;
	}
	db_printf("\n");
}
Esempio n. 11
0
/*ARGSUSED*/
void
db_write_cmd(db_expr_t address, boolean_t have_addr, db_expr_t count,
	     char *modif)
{
	db_addr_t	addr;
	db_expr_t	old_value;
	db_expr_t	new_value;
	int	size;
	boolean_t	wrote_one = FALSE;

	addr = (db_addr_t) address;

	switch (modif[0]) {
	    case 'b':
		size = 1;
		break;
	    case 'h':
		size = 2;
		break;
	    case 'l':
	    case '\0':
		size = 4;
		break;
	    default:
		db_error("Unknown size\n");
		return;
	}

	while (db_expression(&new_value)) {
	    old_value = db_get_value(addr, size, FALSE);
	    db_printsym(addr, DB_STGY_ANY);
	    db_printf("\t\t%s = ", db_num_to_str(old_value));
	    db_printf("%s\n", db_num_to_str(new_value));
	    db_put_value(addr, size, new_value);
	    addr += size;

	    wrote_one = TRUE;
	}

	if (!wrote_one)
	    db_error("Nothing written.\n");

	db_next = addr;
	db_prev = addr - size;

	db_skip_to_eol();
}
Esempio n. 12
0
/*
 * List breakpoints.
 */
void
db_list_breakpoints(void)
{
	db_breakpoint_t	bkpt;

	if (db_breakpoint_list == NULL) {
		db_printf("No breakpoints set\n");
		return;
	}

	db_printf(" Count    Address\n");
	for (bkpt = db_breakpoint_list; bkpt != 0; bkpt = bkpt->link) {
		db_printf(" %5d    ", bkpt->init_count);
		db_printsym(bkpt->address, DB_STGY_PROC, db_printf);
		db_printf("\n");
	}
}
Esempio n. 13
0
/*ARGSUSED*/
void
db_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
{
	db_expr_t	value;
	char		tmpfmt[28];

	if (modif[0] != '\0')
		db_print_format = modif[0];

	switch (db_print_format) {
	case 'a':
		db_printsym((db_addr_t)addr, DB_STGY_ANY, db_printf);
		break;
	case 'r':
		db_printf("%s", db_format(tmpfmt, sizeof tmpfmt, addr,
		    DB_FORMAT_R, 0, sizeof(db_expr_t) * 2 * 6 / 5));
		break;
	case 'x':
		db_printf("%*lx", sizeof(db_expr_t) * 2, addr);
		break;
	case 'z':
		db_printf("%s", db_format(tmpfmt, sizeof tmpfmt, addr,
		    DB_FORMAT_Z, 0, sizeof(db_expr_t) * 2));
		break;
	case 'd':
		db_printf("%*ld", sizeof(db_expr_t) * 2 * 6 / 5, addr);
		break;
	case 'u':
		db_printf("%*lu", sizeof(db_expr_t) * 2 * 6 / 5, addr);
		break;
	case 'o':
		db_printf("%*lo", sizeof(db_expr_t) * 2 * 4 / 3, addr);
		break;
	case 'c':
		value = addr & 0xFF;
		if (value >= ' ' && value <= '~')
			db_printf("%c", value);
		else
			db_printf("\\%03o", value);
		break;
	}
	db_printf("\n");
}
Esempio n. 14
0
void
db_print_address(char *seg, int size, struct i_addr *addrp)
{
	if (addrp->is_reg) {
		db_printf("%s", db_reg[size][addrp->disp]);
		return;
	}

	if (seg)
		db_printf("%s:", seg);

	db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY, db_printf);
	if (addrp->base != 0 || addrp->index != 0) {
		db_printf("(");
		if (addrp->base)
			db_printf("%s", addrp->base);
		if (addrp->index)
			db_printf(",%s,%d", addrp->index, 1<<addrp->ss);
		db_printf(")");
	}
}
Esempio n. 15
0
static void
db_print_address(const char *seg, int size, int rex, struct i_addr *addrp)
{
	if (addrp->is_reg) {
	    db_printf("%s", db_reg[rex != 0 ? 1 : 0][(size == LONG && (rex & REX_W)) ? QUAD : size][addrp->disp]);
	    return;
	}

	if (seg) {
	    db_printf("%s:", seg);
	}

	if (addrp->disp != 0 || (addrp->base == NULL && addrp->index == NULL))
		db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY);
	if (addrp->base != NULL || addrp->index != NULL) {
	    db_printf("(");
	    if (addrp->base)
		db_printf("%s", addrp->base);
	    if (addrp->index)
		db_printf(",%s,%d", addrp->index, 1<<addrp->ss);
	    db_printf(")");
	}
}
Esempio n. 16
0
static void
db_examine(db_addr_t addr, char *fmt, int count)
{
	int		i, c;
	db_expr_t	value;
	int		size;
	int		width;
	int		bytes;
	char *		fp;
	char		tbuf[24];

	while (--count >= 0) {
		fp = fmt;
		size = 4;
		width = 12;
		while ((c = *fp++) != 0) {
			if (db_print_position() == 0) {
				/* Always print the address. */
				db_printsym(addr, DB_STGY_ANY, db_printf);
				db_printf(":\t");
				db_prev = addr;
			}
			switch (c) {
			case 'b':	/* byte */
				size = 1;
				width = 4;
				break;
			case 'h':	/* half-word */
				size = 2;
				width = 8;
				break;
			case 'l':	/* long-word */
				size = 4;
				width = 12;
				break;
			case 'q':
				if (sizeof(db_expr_t) != sizeof(uint64_t)) {
					size = -1;
					db_error("q not supported\n");
					/*NOTREACHED*/
				}
			case 'L':	/* implementation maximum */
				size = sizeof value;
				width = 12 * (sizeof value / 4);
				break;
			case 'a':	/* address */
				db_printf("= 0x%lx\n", (long)addr);
				break;
			case 'r':	/* signed, current radix */
				value = db_get_value(addr, size, true);
				addr += size;
				db_format_radix(tbuf, 24, value, false);
				db_printf("%-*s", width, tbuf);
				break;
			case 'x':	/* unsigned hex */
				value = db_get_value(addr, size, false);
				addr += size;
				db_printf("%-*" DDB_EXPR_FMT "x", width, value);
				break;
			case 'm':	/* hex dump */
				/*
				 * Print off in chunks of size. Try to print 16
				 * bytes at a time into 4 columns. This
				 * loops modify's count extra times in order
				 * to get the nicely formatted lines.
				 */

				bytes = 0;
				do {
					for (i = 0; i < size; i++) {
						value =
 						    db_get_value(addr+bytes, 1,
							false);
						db_printf(
						    "%02" DDB_EXPR_FMT "x",
						    value);
						bytes++;
						if (!(bytes % 4))
							db_printf(" ");
					}
				} while ((bytes != 16) && count--);
				/* True up the columns before continuing */
				for (i = 4; i >= (bytes / 4); i--)
					db_printf ("\t");
				/* Print chars,  use . for non-printable's. */
				while (bytes--) {
					value = db_get_value(addr, 1, false);
					addr += 1;
					if (value >= ' ' && value <= '~')
						db_printf("%c", (char)value);
					else
						db_printf(".");
				}
				db_printf("\n");
				break;
			case 'z':	/* signed hex */
				value = db_get_value(addr, size, true);
				addr += size;
				db_format_hex(tbuf, 24, value, false);
				db_printf("%-*s", width, tbuf);
				break;
			case 'd':	/* signed decimal */
				value = db_get_value(addr, size, true);
				addr += size;
				db_printf("%-*" DDB_EXPR_FMT "d", width, value);
				break;
			case 'u':	/* unsigned decimal */
				value = db_get_value(addr, size, false);
				addr += size;
				db_printf("%-*" DDB_EXPR_FMT "u", width, value);
				break;
			case 'o':	/* unsigned octal */
				value = db_get_value(addr, size, false);
				addr += size;
				db_printf("%-*" DDB_EXPR_FMT "o", width, value);
				break;
			case 'c':	/* character */
				value = db_get_value(addr, 1, false);
				addr += 1;
				if (value >= ' ' && value <= '~')
					db_printf("%c", (char)value);
				else
					db_printf("\\%03o", (int)value);
				break;
			case 's':	/* null-terminated string */
				for (;;) {
					value = db_get_value(addr, 1, false);
					addr += 1;
					if (value == 0)
						break;
					if (value >= ' ' && value <= '~')
						db_printf("%c", (char)value);
					else
						db_printf("\\%03o", (int)value);
				}
				break;
			case 'i':	/* instruction */
				addr = db_disasm(addr, false);
				break;
			case 'I':	/* instruction, alternate form */
				addr = db_disasm(addr, true);
				break;
			default:
				break;
			}
			if (db_print_position() != 0)
				db_end_line();
		}
	}
	db_next = addr;
}
Esempio n. 17
0
/*
 *	Frame tracing.
 */
static int
db_backtrace(struct thread *td, db_addr_t fp, int count)
{
	db_addr_t stackframe, lr, *args;
	boolean_t kernel_only = TRUE;
	boolean_t full = FALSE;

#if 0
	{
		register char *cp = modif;
		register char c;

		while ((c = *cp++) != 0) {
			if (c == 't')
				trace_thread = TRUE;
			if (c == 'u')
				kernel_only = FALSE;
			if (c == 'f')
				full = TRUE;
		}
	}
#endif

	stackframe = fp;

	while (!db_pager_quit) {
		if (stackframe < PAGE_SIZE)
			break;

		/*
		 * Locate the next frame by grabbing the backchain ptr
		 * from frame[0]
		 */
		stackframe = *(db_addr_t *)stackframe;

	next_frame:
	    #ifdef __powerpc64__
		/* The saved arg values start at frame[6] */
		args = (db_addr_t *)(stackframe + 48);
	    #else
		/* The saved arg values start at frame[2] */
		args = (db_addr_t *)(stackframe + 8);
	    #endif

		if (stackframe < PAGE_SIZE)
			break;

	        if (count-- == 0)
			break;

		/*
		 * Extract link register from frame and subtract
		 * 4 to convert into calling address (as opposed to
		 * return address)
		 */
	    #ifdef __powerpc64__
		lr = *(db_addr_t *)(stackframe + 16) - 4;
	    #else
		lr = *(db_addr_t *)(stackframe + 4) - 4;
	    #endif
		if ((lr & 3) || (lr < 0x100)) {
			db_printf("saved LR(0x%zx) is invalid.", lr);
			break;
		}

		#ifdef __powerpc64__
		db_printf("0x%016lx: ", stackframe);
		#else
		db_printf("0x%08x: ", stackframe);
		#endif

		/*
		 * The trap code labels the return addresses from the
		 * call to C code as 'trapexit' and 'asttrapexit. Use this
		 * to determine if the callframe has to traverse a saved
		 * trap context
		 */
		if ((lr + CALLOFFSET == (db_addr_t) &trapexit) ||
		    (lr + CALLOFFSET == (db_addr_t) &asttrapexit)) {
			const char *trapstr;
			struct trapframe *tf = (struct trapframe *)(args);
			db_printf("%s ", tf->srr1 & PSL_PR ? "user" : "kernel");
			switch (tf->exc) {
			case EXC_DSI:
				/* XXX take advantage of the union. */
				db_printf("DSI %s trap @ %#zx by ",
				    (tf->cpu.aim.dsisr & DSISR_STORE) ? "write"
				    : "read", tf->dar);
				goto print_trap;
			case EXC_ALI:
				/* XXX take advantage of the union. */
				db_printf("ALI trap @ %#zx (xSR %#x) ",
				    tf->dar, (uint32_t)tf->cpu.aim.dsisr);
				goto print_trap;
#ifdef __powerpc64__
			case EXC_DSE:
				db_printf("DSE trap @ %#zx by ", tf->dar);
				goto print_trap;
			case EXC_ISE:
				db_printf("ISE trap @ %#zx by ", tf->srr0);
				goto print_trap;
#endif
			case EXC_ISI: trapstr = "ISI"; break;
			case EXC_PGM: trapstr = "PGM"; break;
			case EXC_SC: trapstr = "SC"; break;
			case EXC_EXI: trapstr = "EXI"; break;
			case EXC_MCHK: trapstr = "MCHK"; break;
#if !defined(BOOKE)
			case EXC_VEC: trapstr = "VEC"; break;
			case EXC_FPA: trapstr = "FPA"; break;
			case EXC_BPT: trapstr = "BPT"; break;
			case EXC_TRC: trapstr = "TRC"; break;
			case EXC_RUNMODETRC: trapstr = "RUNMODETRC"; break;
			case EXC_SMI: trapstr = "SMI"; break;
			case EXC_RST: trapstr = "RST"; break;
#endif
			case EXC_FPU: trapstr = "FPU"; break;
			case EXC_DECR: trapstr = "DECR"; break;
			case EXC_PERF: trapstr = "PERF"; break;
			case EXC_VSX: trapstr = "VSX"; break;
			default: trapstr = NULL; break;
			}
			if (trapstr != NULL) {
				db_printf("%s trap by ", trapstr);
			} else {
				db_printf("trap %#zx by ", tf->exc);
			}

		   print_trap:
			lr = (db_addr_t) tf->srr0;
			db_printsym(lr, DB_STGY_ANY);
			db_printf(": srr1=%#zx\n", tf->srr1);
			db_printf("%-10s  r1=%#zx cr=%#x xer=%#x ctr=%#zx",
			    "", tf->fixreg[1], (uint32_t)tf->cr,
			    (uint32_t)tf->xer, tf->ctr);
#ifdef __powerpc64__
			db_printf(" r2=%#zx", tf->fixreg[2]);
#endif
			if (tf->exc == EXC_DSI)
				db_printf(" sr=%#x",
				    (uint32_t)tf->cpu.aim.dsisr);
			db_printf("\n");
			stackframe = (db_addr_t) tf->fixreg[1];
			if (kernel_only && (tf->srr1 & PSL_PR))
				break;
			goto next_frame;
		}

		db_printf("at ");
		db_printsym(lr, DB_STGY_PROC);
		if (full)
			/* Print all the args stored in that stackframe. */
			db_printf("(%zx, %zx, %zx, %zx, %zx, %zx, %zx, %zx)",
				args[0], args[1], args[2], args[3],
				args[4], args[5], args[6], args[7]);
		db_printf("\n");
	}

	return (0);
}
Esempio n. 18
0
void
db_examine(db_addr_t addr, char *fmt, int count)
{
	int		c;
	db_expr_t	value;
	int		size;
	int		width;
	char *		fp;
	char		tmpfmt[28];

	while (--count >= 0) {
		fp = fmt;
		size = 4;
		width = 12;
		while ((c = *fp++) != 0) {
			if (db_print_position() == 0) {
				/* Always print the address. */
				db_printsym(addr, DB_STGY_ANY, db_printf);
				db_printf(":\t");
				db_prev = addr;
			}
			switch (c) {
			case 'b':	/* byte */
				size = 1;
				width = 4;
				break;
			case 'h':	/* half-word */
				size = 2;
				width = 8;
				break;
			case 'l':	/* long-word */
				size = 4;
				width = 12;
				break;
#ifdef __LP64__
			case 'q':	/* quad-word */
				size = 8;
				width = 20;
				break;
#endif
			case 'a':	/* address */
				db_printf("= 0x%lx\n", (long)addr);
				break;
			case 'r':	/* signed, current radix */
				value = db_get_value(addr, size, TRUE);
				addr += size;
				db_format(tmpfmt, sizeof tmpfmt,
				    (long)value, DB_FORMAT_R, 0, width);
				db_printf("%-*s", width, tmpfmt);
				break;
			case 'x':	/* unsigned hex */
				value = db_get_value(addr, size, FALSE);
				addr += size;
				db_printf("%-*lx", width, (long)value);
				break;
			case 'z':	/* signed hex */
				value = db_get_value(addr, size, TRUE);
				addr += size;
				db_format(tmpfmt, sizeof tmpfmt,
				    (long)value, DB_FORMAT_Z, 0, width);
				db_printf("%-*s", width, tmpfmt);
				break;
			case 'd':	/* signed decimal */
				value = db_get_value(addr, size, TRUE);
				addr += size;
				db_printf("%-*ld", width, (long)value);
				break;
			case 'u':	/* unsigned decimal */
				value = db_get_value(addr, size, FALSE);
				addr += size;
				db_printf("%-*lu", width, (long)value);
				break;
			case 'o':	/* unsigned octal */
				value = db_get_value(addr, size, FALSE);
				addr += size;
				db_printf("%-*lo", width, value);
				break;
			case 'c':	/* character */
				value = db_get_value(addr, 1, FALSE);
				addr += 1;
				if (value >= ' ' && value <= '~')
					db_printf("%c", value);
				else
					db_printf("\\%03o", value);
				break;
			case 's':	/* null-terminated string */
				for (;;) {
					value = db_get_value(addr, 1, FALSE);
					addr += 1;
					if (value == 0)
						break;
					if (value >= ' ' && value <= '~')
						db_printf("%c", value);
					else
						db_printf("\\%03o", value);
				}
				break;
			case 'i':	/* instruction */
				addr = db_disasm(addr, FALSE);
				break;
			case 'I':	/* instruction, alternate form */
				addr = db_disasm(addr, TRUE);
				break;
			default:
				break;
			}
			if (db_print_position() != 0)
				db_end_line(width);
		}
	}
	db_next = addr;
}
Esempio n. 19
0
static void
db_disasm_printaddr(vm_offset_t address)
{

	db_printsym((db_addr_t)address, DB_STGY_ANY);
}
Esempio n. 20
0
void
db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count,
    char *modif, int (*pr)(const char *, ...))
{
	struct x86_64_frame *frame, *lastframe;
	long		*argp;
	db_addr_t	callpc;
	int		is_trap = 0;
	boolean_t	kernel_only = TRUE;
	boolean_t	trace_thread = FALSE;

#if 0
	if (!db_trace_symbols_found)
		db_find_trace_symbols();
#endif

	{
		char *cp = modif;
		char c;

		while ((c = *cp++) != 0) {
			if (c == 't')
				trace_thread = TRUE;
			if (c == 'u')
				kernel_only = FALSE;
		}
	}

	if (!have_addr) {
		frame = (struct x86_64_frame *)ddb_regs.tf_rbp;
		callpc = (db_addr_t)ddb_regs.tf_rip;
	} else {
#if 0
		if (trace_thread) {
			struct proc *p;
			struct user *u;
			struct lwp *l;
			(*pr)("trace: pid %d ", (int)addr);
			p = pfind(addr);
			if (p == NULL) {
				(*pr)("not found\n");
				return;
			}
			l = proc_representative_lwp(p);
			if (!(l->l_flag&L_INMEM)) {
				(*pr)("swapped out\n");
				return;
			}
			u = l->l_addr;
			frame = (struct x86_64_frame *) u->u_pcb.pcb_rbp;
			(*pr)("at %p\n", frame);
		} else
#endif
			frame = (struct x86_64_frame *)addr;
		callpc = (db_addr_t)
			 db_get_value((db_addr_t)&frame->f_retaddr, 8, FALSE);
		frame = (struct x86_64_frame *)frame->f_frame;
	}

	lastframe = 0;
	while (count && frame != 0) {
		int		narg;
		char *	name;
		db_expr_t	offset;
		db_sym_t	sym;
#define MAXNARG	16
		char	*argnames[MAXNARG], **argnp = NULL;

		sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
		db_symbol_values(sym, &name, NULL);

		if (lastframe == 0 && sym == NULL) {
			/* Symbol not found, peek at code */
			long	instr = db_get_value(callpc, 8, FALSE);

			offset = 1;
			if ((instr & 0x00ffffff) == 0x00e58955 ||
					/* enter: pushl %ebp, movl %esp, %ebp */
			    (instr & 0x0000ffff) == 0x0000e589
					/* enter+1: movl %esp, %ebp */) {
				offset = 0;
			}
		}
		if (INKERNEL(frame) && name) {
#ifdef __ELF__
			if (!strcmp(name, "trap")) {
				is_trap = TRAP;
			} else if (!strcmp(name, "syscall")) {
				is_trap = SYSCALL;
			} else if (name[0] == 'X') {
				if (!strncmp(name, "Xintr", 5) ||
				    !strncmp(name, "Xresume", 7) ||
				    !strncmp(name, "Xstray", 6) ||
				    !strncmp(name, "Xhold", 5) ||
				    !strncmp(name, "Xrecurse", 8) ||
				    !strcmp(name, "Xdoreti") ||
				    !strncmp(name, "Xsoft", 5)) {
					is_trap = INTERRUPT;
				} else
					goto normal;
			} else
				goto normal;
			narg = 0;
#else
			if (!strcmp(name, "_trap")) {
				is_trap = TRAP;
			} else if (!strcmp(name, "_syscall")) {
				is_trap = SYSCALL;
			} else if (name[0] == '_' && name[1] == 'X') {
				if (!strncmp(name, "_Xintr", 6) ||
				    !strncmp(name, "_Xresume", 8) ||
				    !strncmp(name, "_Xstray", 7) ||
				    !strncmp(name, "_Xhold", 6) ||
				    !strncmp(name, "_Xrecurse", 9) ||
				    !strcmp(name, "_Xdoreti") ||
				    !strncmp(name, "_Xsoft", 6)) {
					is_trap = INTERRUPT;
				} else
					goto normal;
			} else
				goto normal;
			narg = 0;
#endif /* __ELF__ */
		} else {
		normal:
			is_trap = NONE;
			narg = MAXNARG;
			if (db_sym_numargs(sym, &narg, argnames))
				argnp = argnames;
			else
				narg = db_numargs(frame);
		}

		(*pr)("%s(", name);

		if (lastframe == 0 && offset == 0 && !have_addr) {
			/*
			 * We have a breakpoint before the frame is set up
			 * Use %esp instead
			 */
			argp = &((struct x86_64_frame *)(ddb_regs.tf_rsp-8))->f_arg0;
		} else {
			argp = &frame->f_arg0;
		}

		while (narg) {
			if (argnp)
				(*pr)("%s=", *argnp++);
			(*pr)("%lx", db_get_value((db_addr_t)argp, 8, FALSE));
			argp++;
			if (--narg != 0)
				(*pr)(",");
		}
		(*pr)(") at ");
		db_printsym(callpc, DB_STGY_PROC, pr);
		(*pr)("\n");

		if (lastframe == 0 && offset == 0 && !have_addr) {
			/* Frame really belongs to next callpc */
			lastframe = (struct x86_64_frame *)(ddb_regs.tf_rsp-8);
			callpc = (db_addr_t)
				 db_get_value((db_addr_t)&lastframe->f_retaddr,
				    8, FALSE);
			continue;
		}

		lastframe = frame;
		db_nextframe(&frame, &callpc, &frame->f_arg0, is_trap, pr);

		if (frame == 0) {
			/* end of chain */
			break;
		}
		if (INKERNEL(frame)) {
			/* staying in kernel */
			if (frame <= lastframe) {
				(*pr)("Bad frame pointer: %p\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 {
			/* in user */
			if (frame <= lastframe) {
				(*pr)("Bad user frame pointer: %p\n",
					  frame);
				break;
			}
		}
		--count;
	}
	(*pr)("end trace frame: 0x%lx, count: %d\n", frame, count);

	if (count && is_trap != NONE) {
		db_printsym(callpc, DB_STGY_XTRN, pr);
		(*pr)(":\n");
	}
}
Esempio n. 21
0
void
db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count,
    char *modif, int (*pr)(const char *, ...))
{
	struct callframe *frame, *lastframe;
	long		*argp, *arg0;
	db_addr_t	callpc;
	int		is_trap = 0;
	boolean_t	kernel_only = TRUE;
	boolean_t	trace_proc = FALSE;

	{
		char *cp = modif;
		char c;

		while ((c = *cp++) != 0) {
			if (c == 'p')
				trace_proc = TRUE;
			if (c == 'u')
				kernel_only = FALSE;
		}
	}

	if (!have_addr) {
		frame = (struct callframe *)ddb_regs.tf_rbp;
		callpc = (db_addr_t)ddb_regs.tf_rip;
	} else {
		if (trace_proc) {
			struct proc *p = pfind((pid_t)addr);
			if (p == NULL) {
				(*pr) ("db_trace.c: process not found\n");
				return;
			}
			frame = (struct callframe *)p->p_addr->u_pcb.pcb_rbp;
		} else {
			frame = (struct callframe *)addr;
		}
		callpc = (db_addr_t)
			 db_get_value((db_addr_t)&frame->f_retaddr, 8, FALSE);
		frame = (struct callframe *)frame->f_frame;
	}

	lastframe = 0;
	while (count && frame != 0) {
		int		narg;
		char *	name;
		db_expr_t	offset;
		db_sym_t	sym;

		sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
		db_symbol_values(sym, &name, NULL);

		if (lastframe == 0 && sym == NULL) {
			/* Symbol not found, peek at code */
			long	instr = db_get_value(callpc, 8, FALSE);

			offset = 1;
			if ((instr & 0x00ffffff) == 0x00e58955 ||
					/* enter: pushl %ebp, movl %esp, %ebp */
			    (instr & 0x0000ffff) == 0x0000e589
					/* enter+1: movl %esp, %ebp */) {
				offset = 0;
			}
		}
		if (INKERNEL(callpc) && name) {
			if (!strcmp(name, "trap")) {
				is_trap = TRAP;
			} else if (!strcmp(name, "ast")) {
				is_trap = AST;
			} else if (!strcmp(name, "syscall")) {
				is_trap = SYSCALL;
			} else if (name[0] == 'X') {
				if (!strncmp(name, "Xintr", 5) ||
				    !strncmp(name, "Xresume", 7) ||
				    !strncmp(name, "Xrecurse", 8) ||
				    !strcmp(name, "Xdoreti") ||
				    !strncmp(name, "Xsoft", 5)) {
					is_trap = INTERRUPT;
				} else
					goto normal;
			} else
				goto normal;
			narg = 0;
		} else {
		normal:
			is_trap = NONE;
			narg = db_numargs(frame);
		}

		(*pr)("%s(", name);

		if (lastframe == 0 && offset == 0 && !have_addr) {
			/*
			 * We have a breakpoint before the frame is set up
			 * Use %rsp instead
			 */
			arg0 =
			    &((struct callframe *)(ddb_regs.tf_rsp-8))->f_arg0;
		} else {
			arg0 = &frame->f_arg0;
		}

		for (argp = arg0; narg > 0; ) {
			(*pr)("%lx", db_get_value((db_addr_t)argp, 8, FALSE));
			argp++;
			if (--narg != 0)
				(*pr)(",");
		}
		(*pr)(") at ");
		db_printsym(callpc, DB_STGY_PROC, pr);
		(*pr)("\n");

		if (lastframe == 0 && offset == 0 && !have_addr && !is_trap) {
			/* Frame really belongs to next callpc */
			lastframe = (struct callframe *)(ddb_regs.tf_rsp-8);
			callpc = (db_addr_t)
				 db_get_value((db_addr_t)&lastframe->f_retaddr,
				    8, FALSE);
			continue;
		}

		if (is_trap == INTERRUPT) {
			/*
			 * Interrupt routines don't update %rbp, so it still
			 * points to the frame that was interrupted.  Pull
			 * back to just above lastframe so we can find the
			 * trapframe as with syscalls and traps.
			 */
			frame = (struct callframe *)&lastframe->f_retaddr;
			arg0 = &frame->f_arg0;
		}

		lastframe = frame;
		db_nextframe(&frame, &callpc, arg0, is_trap, pr);

		if (frame == 0) {
			/* end of chain */
			break;
		}
		if (INKERNEL(frame)) {
			/* staying in kernel */
			if (frame <= lastframe) {
				(*pr)("Bad frame pointer: %p\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 {
			/* in user */
			if (frame <= lastframe) {
				(*pr)("Bad user frame pointer: %p\n",
					  frame);
				break;
			}
		}
		--count;
	}
	(*pr)("end trace frame: 0x%lx, count: %d\n", frame, count);

	if (count && is_trap != NONE) {
		db_printsym(callpc, DB_STGY_XTRN, pr);
		(*pr)(":\n");
	}
}
Esempio n. 22
0
static void
db_disasm_printaddr(db_expr_t address)
{

	db_printsym((db_addr_t)address, DB_STGY_ANY, db_printf);
}
Esempio n. 23
0
void
db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
		     const char *modif, void (*pr)(const char *, ...))
{
	long *frame, *lastframe;
	long *retaddr, *arg0;
	long		*argp;
	db_addr_t	callpc;
	int		is_trap;
	bool		kernel_only = true;
	bool		trace_thread = false;
	bool		lwpaddr = false;

#if 0
	if (!db_trace_symbols_found)
		db_find_trace_symbols();
#endif

	{
		const char *cp = modif;
		char c;

		while ((c = *cp++) != 0) {
			if (c == 'a') {
				lwpaddr = true;
				trace_thread = true;
			}
			if (c == 't')
				trace_thread = true;
			if (c == 'u')
				kernel_only = false;
		}
	}

	if (!have_addr) {
		frame = (long *)ddb_regs.tf_rbp;
		callpc = (db_addr_t)ddb_regs.tf_rip;
	} else {
		if (trace_thread) {
			struct proc *p;
			struct user *u;
			struct lwp *l;
			if (lwpaddr) {
				l = (struct lwp *)addr;
				p = l->l_proc;
				(*pr)("trace: pid %d ", p->p_pid);
			} else {
				(*pr)("trace: pid %d ", (int)addr);
				p = p_find(addr, PFIND_LOCKED);
				if (p == NULL) {
					(*pr)("not found\n");
					return;
				}
				l = LIST_FIRST(&p->p_lwps);
				KASSERT(l != NULL);
			}
			(*pr)("lid %d ", l->l_lid);
			if (!(l->l_flag & LW_INMEM)) {
				(*pr)("swapped out\n");
				return;
			}
			u = l->l_addr;
			if (p == curproc && l == curlwp) {
				frame = (long *)ddb_regs.tf_rbp;
				callpc = (db_addr_t)ddb_regs.tf_rip;
				(*pr)("at %p\n", frame);
			} else {
				frame = (long *)u->u_pcb.pcb_rbp;
				callpc = (db_addr_t)
				    db_get_value((long)(frame + 1), 8, false);
				(*pr)("at %p\n", frame);
				frame = (long *)*frame; /* XXXfvdl db_get_value? */
			}
		} else {
			frame = (long *)addr;
			callpc = (db_addr_t)
			    db_get_value((long)(frame + 1), 8, false);
			frame = (long *)*frame; /* XXXfvdl db_get_value? */
		}
	}
	retaddr = frame + 1;
	arg0 = frame + 2;

	lastframe = 0;
	while (count && frame != 0) {
		int		narg;
		const char *	name;
		db_expr_t	offset;
		db_sym_t	sym;
		char	*argnames[16], **argnp = NULL;
		db_addr_t	lastcallpc;

		name = "?";
		is_trap = NONE;
		offset = 0;
		sym = db_frame_info(frame, callpc, &name, &offset, &is_trap,
				    &narg);

		if (lastframe == 0 && sym == (db_sym_t)0) {
			/* Symbol not found, peek at code */
			u_long	instr = db_get_value(callpc, 4, false);

			offset = 1;
			if (instr  == 0xe5894855 ||
					/* enter: pushq %rbp, movq %rsp, %rbp */
			    (instr & 0x00ffffff) == 0x0048e589
					/* enter+1: movq %rsp, %rbp */) {
				offset = 0;
			}
		}

		if (is_trap == NONE) {
			if (db_sym_numargs(sym, &narg, argnames))
				argnp = argnames;
			else
				narg = db_numargs(frame);
		}

		(*pr)("%s(", name);

		if (lastframe == 0 && offset == 0 && !have_addr) {
			/*
			 * We have a breakpoint before the frame is set up
			 * Use %rsp instead
			 */
			argp = &((struct x86_64_frame *)(ddb_regs.tf_rsp-8))->f_arg0;
		} else {
			argp = frame + 2;
		}

		while (narg) {
			if (argnp)
				(*pr)("%s=", *argnp++);
			(*pr)("%lx", db_get_value((long)argp, 8, false));
			argp++;
			if (--narg != 0)
				(*pr)(",");
		}
		(*pr)(") at ");
		db_printsym(callpc, DB_STGY_PROC, pr);
		(*pr)("\n");

		if (lastframe == 0 && offset == 0 && !have_addr) {
			/* Frame really belongs to next callpc */
			struct x86_64_frame *fp = (void *)(ddb_regs.tf_rsp-8);

			lastframe = (long *)fp;
			callpc = (db_addr_t)
			    db_get_value((db_addr_t)&fp->f_retaddr, 8, false);
			continue;
		}

		lastframe = frame;
		lastcallpc = callpc;
		if (!db_nextframe(&frame, &retaddr, &arg0,
		   &callpc, frame + 2, is_trap, pr))
			break;

		if (INKERNEL((long)frame)) {
			/* staying in kernel */
			if (frame < lastframe ||
			    (frame == lastframe && callpc == lastcallpc)) {
				(*pr)("Bad frame pointer: %p\n", frame);
				break;
			}
		} else if (INKERNEL((long)lastframe)) {
			/* switch from user to kernel */
			if (kernel_only)
				break;	/* kernel stack only */
		} else {
			/* in user */
			if (frame <= lastframe) {
				(*pr)("Bad user frame pointer: %p\n",
					  frame);
				break;
			}
		}
		--count;
	}

	if (count && is_trap != NONE) {
		db_printsym(callpc, DB_STGY_XTRN, pr);
		(*pr)(":\n");
	}
}
Esempio n. 24
0
/* 
 * Figure out the next frame up in the call stack.  
 * For trap(), we print the address of the faulting instruction and 
 *   proceed with the calling frame.  We return the ip that faulted.
 *   If the trap was caused by jumping through a bogus pointer, then
 *   the next line in the backtrace will list some random function as 
 *   being called.  It should get the argument list correct, though.  
 *   It might be possible to dig out from the next frame up the name
 *   of the function that faulted, but that could get hairy.
 */
int
db_nextframe(long **nextframe, long **retaddr, long **arg0, db_addr_t *ip,
	     long *argp, int is_trap, void (*pr)(const char *, ...))
{
	struct trapframe *tf;
	struct x86_64_frame *fp;
	struct intrframe *ifp;
	int traptype, trapno, err, i;

	switch (is_trap) {
	    case NONE:
		*ip = (db_addr_t)
			db_get_value((long)*retaddr, 8, false);
		fp = (struct x86_64_frame *)
			db_get_value((long)*nextframe, 8, false);
		if (fp == NULL)
			return 0;
		*nextframe = (long *)&fp->f_frame;
		*retaddr = (long *)&fp->f_retaddr;
		*arg0 = (long *)&fp->f_arg0;
		break;

	    case TRAP:
	    case SYSCALL:
	    case INTERRUPT:
	    default:

		/* The only argument to trap() or syscall() is the trapframe. */
		tf = (struct trapframe *)argp;
		switch (is_trap) {
		case TRAP:
			(*pr)("--- trap (number %"DDB_EXPR_FMT"u) ---\n",
				db_get_value((long)&tf->tf_trapno, 8, false));
			break;
		case SYSCALL:
			(*pr)("--- syscall (number %"DDB_EXPR_FMT"u) ---\n",
				db_get_value((long)&tf->tf_rax, 8, false));
			break;
		case INTERRUPT:
			(*pr)("--- interrupt ---\n");
			break;
		}
		*ip = (db_addr_t)db_get_value((long)&tf->tf_rip, 8, false);
		fp = (struct x86_64_frame *)
			db_get_value((long)&tf->tf_rbp, 8, false);
		if (fp == NULL)
			return 0;
		*nextframe = (long *)&fp->f_frame;
		*retaddr = (long *)&fp->f_retaddr;
		*arg0 = (long *)&fp->f_arg0;
		break;
	}

	/*
	 * A bit of a hack. Since %rbp may be used in the stub code,
	 * walk the stack looking for a valid interrupt frame. Such
	 * a frame can be recognized by always having
	 * err 0 or IREENT_MAGIC and trapno T_ASTFLT.
	 */
	if (db_frame_info(*nextframe, (db_addr_t)*ip, NULL, NULL, &traptype,
	    NULL) != (db_sym_t)0
	    && traptype == INTERRUPT) {
		for (i = 0; i < 4; i++) {
			ifp = (struct intrframe *)(argp + i);
			err = db_get_value((long)&ifp->if_tf.tf_err,
			    sizeof(long), false);
			trapno = db_get_value((long)&ifp->if_tf.tf_trapno,
			    sizeof(long), false);
			if ((err == 0 || err == IREENT_MAGIC)
			    && trapno == T_ASTFLT) {
				*nextframe = (long *)ifp - 1;
				break;
			}
		}
		if (i == 4) {
			(*pr)("DDB lost frame for ");
			db_printsym(*ip, DB_STGY_ANY, pr);
			(*pr)(", trying %p\n",argp);
			*nextframe = argp;
		}
	}
	return 1;
}
Esempio n. 25
0
void
db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
    const char *modif, void (*pr)(const char *, ...))
{
	register_t *fp, pc, rp;
	bool kernel_only = true;
	bool trace_thread = false;
	bool lwpaddr = false;
	db_sym_t sym;
	db_expr_t off;
	const char *name;
	const char *cp = modif;
	char c;

	if (count < 0)
		count = 65536;

	while ((c = *cp++) != 0) {
		if (c == 'a') {
			lwpaddr = true;
			trace_thread = true;
		}
		if (c == 't')
			trace_thread = true;
		if (c == 'u')
			kernel_only = false;
	}

	if (!have_addr) {
		fp = (register_t *)ddb_regs.tf_r3;
		pc = ddb_regs.tf_iioq_head;
		rp = ddb_regs.tf_rp;
	} else {
		if (trace_thread) {
			struct proc *p;
			struct user *u;
			struct lwp *l;
			if (lwpaddr) {
				l = (struct lwp *)addr;
				p = l->l_proc;
				(*pr)("trace: pid %d ", p->p_pid);
			} else {
				(*pr)("trace: pid %d ", (int)addr);
				p = p_find(addr, PFIND_LOCKED);
				if (p == NULL) {
					(*pr)("not found\n");
					return;
				}
				l = LIST_FIRST(&p->p_lwps);
				KASSERT(l != NULL);
			}
			(*pr)("lid %d ", l->l_lid);
			if (!(l->l_flag & LW_INMEM)) {
				(*pr)("swapped out\n");
				return;
			}
			u = l->l_addr;
			if (p == curproc && l == curlwp) {
				fp = (int *)ddb_regs.tf_r3;
				pc = ddb_regs.tf_iioq_head;
				rp = ddb_regs.tf_rp;
			} else {
				/* cpu_switchto fp, and return point */
				fp = (int *)(u->u_pcb.pcb_ksp -
				    (HPPA_FRAME_SIZE + 16*4));
				pc = 0;
				rp = fp[-5];
			}
			(*pr)("at %p\n", fp);
		} else {
			pc = 0;
			fp = (register_t *)addr;
			rp = fp[-5];
		}
	}

	while (fp && count--) {

#ifdef DDB_DEBUG
		pr(">> %08x %08x %08x\t", fp, pc, rp);
#endif

		if (USERMODE(pc))
			return;

		sym = db_search_symbol(pc, DB_STGY_ANY, &off);
		db_symbol_values (sym, &name, NULL);

		pr("%s() at ", name);
		db_printsym(pc, DB_STGY_PROC, pr);
		pr("\n");

		/* XXX NH - unwind info here */
		/* aue = ue_find(pc); */

		/*
		 * get rp?
		 * fp -= ue_total_frame_size(aue)
		 */

		/*
		 * if a terminal frame then report the trapframe
		 * and continue after it (if not the last one).
		 */
		if (!fp[0]) {
			register_t *scargs;
			struct trapframe *tf;
			int scoff;

			/* Stack space for syscall args */
			scoff = HPPA_FRAME_ROUND(HPPA_FRAME_SIZE + HPPA_FRAME_MAXARGS);

			scargs = (register_t *)((char *)fp - scoff);
			tf = (struct trapframe *)((char *)scargs - sizeof(*tf));

			if (tf->tf_flags & TFF_SYS)
				pr("-- syscall #%d(%x, %x, %x, %x, ...)\n",
				    tf->tf_t1, scargs[1], scargs[2],
				    scargs[3], scargs[4]);
			else
				pr("-- trap #%d%s\n", tf->tf_flags & 0x3f,
				    (tf->tf_flags & T_USER)? " from user" : "");

			if (!(tf->tf_flags & TFF_LAST)) {
				fp = (register_t *)tf->tf_r3;
				pc = tf->tf_iioq_head;
				rp = tf->tf_rp;
			} else {
				pc = 0;
				fp = 0;
			}
		} else {
			/* next frame */
			fp = (register_t *)fp[0];
			pc = rp;
			rp = fp[-5];
		}
	}

	if (count && pc) {
		db_printsym(pc, DB_STGY_XTRN, pr);
		pr(":\n");
	}
}
Esempio n. 26
0
void
db_stack_trace_print(db_expr_t addr, bool have_addr,
		     db_expr_t count, const char *modif,
		     void (*pr)(const char *, ...))
{
	struct frame	*frame, *prevframe;
	db_addr_t	pc;
	bool		kernel_only = true;
	bool		trace_thread = false;
	bool		lwpaddr = false;
	const char	*cp = modif;
	char		c;

	if (ddb_cpuinfo == NULL)
		ddb_cpuinfo = curcpu();

	while ((c = *cp++) != 0) {
		if (c == 'a') {
			lwpaddr = true;
			trace_thread = true;
		}
		if (c == 't')
			trace_thread = true;
		if (c == 'u')
			kernel_only = false;
	}

	if (!have_addr) {
		frame = (struct frame *)DDB_TF->tf_out[6];
		pc = DDB_TF->tf_pc;
	} else {
		if (trace_thread) {
			struct proc *p;
			struct user *u;
			struct lwp *l;
			if (lwpaddr) {
				l = (struct lwp *)addr;
				p = l->l_proc;
				(*pr)("trace: pid %d ", p->p_pid);
			} else {
				(*pr)("trace: pid %d ", (int)addr);
				p = p_find(addr, PFIND_LOCKED);
				if (p == NULL) {
					(*pr)("not found\n");
					return;
				}
				l = LIST_FIRST(&p->p_lwps);
				KASSERT(l != NULL);
			}
			(*pr)("lid %d ", l->l_lid);
			if ((l->l_flag & LW_INMEM) == 0) {
				(*pr)("swapped out\n");
				return;
			}
			u = l->l_addr;
			frame = (struct frame *)u->u_pcb.pcb_sp;
			pc = u->u_pcb.pcb_pc;
			(*pr)("at %p\n", frame);
		} else {
			frame = (struct frame *)addr;
			pc = 0;
		}
	}

	while (count--) {
		int		i;
		db_expr_t	offset;
		const char	*name;
		db_addr_t	prevpc;

#define FR(framep,field) (INKERNEL(framep)			\
				? (u_int)(framep)->field	\
				: fuword(&(framep)->field))

		/* Fetch return address and arguments frame */
		prevpc = (db_addr_t)FR(frame, fr_pc);
		prevframe = (struct frame *)FR(frame, fr_fp);

		/*
		 * Switch to frame that contains arguments
		 */
		if (prevframe == NULL || (!INKERNEL(prevframe) && kernel_only))
			return;

		if ((ONINTSTACK(frame) && !ONINTSTACK(prevframe)) ||
		    (INKERNEL(frame) && !INKERNEL(prevframe))) {
			/* We're crossing a trap frame; pc = %l1 */
			prevpc = (db_addr_t)FR(frame, fr_local[1]);
		}

		name = NULL;
		if (INKERNEL(pc))
			db_find_sym_and_offset(pc, &name, &offset);
		if (name == NULL)
			(*pr)("0x%lx(", pc);
		else
			(*pr)("%s(", name);

		/*
		 * Print %i0..%i5, hope these still reflect the
		 * actual arguments somewhat...
		 */
		for (i = 0; i < 6; i++)
			(*pr)("0x%x%s", FR(frame, fr_arg[i]),
				(i < 5) ? ", " : ") at ");
		if (INKERNEL(prevpc))
			db_printsym(prevpc, DB_STGY_PROC, pr);
		else
			(*pr)("0x%lx", prevpc);
		(*pr)("\n");

		pc = prevpc;
		frame = prevframe;
	}
}