summaryrefslogtreecommitdiff
path: root/usr/src/cmd/mdb/intel/kmdb/kmdb_fault_isadep.c
blob: 63dea9376180012928e630da88aed8c9f6b78e97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

/*
 * Intel-specific portions of the debugger fault routines
 */

#include <sys/types.h>
#include <sys/stack.h>
#include <sys/frame.h>

#include <kmdb/kmdb_fault.h>
#include <kmdb/kmdb_asmutil.h>
#include <mdb/mdb_kreg.h>
#include <mdb/mdb.h>

#define	MAX_STACK_FRAMES	30

static void
print_frame(uintptr_t pc, int fnum, int safe)
{
	if (safe) {
		/*
		 * We exploded the first time around, so we want to try again,
		 * this time without symbol names
		 */
		mdb_iob_printf(mdb.m_err, "    [%2d] %?p()\n", fnum, pc);
	} else {
		mdb_iob_printf(mdb.m_err, "    [%2d] %?p %A()\n", fnum, pc, pc);
	}
}

static int
valid_frame(struct frame *fr)
{
	uintptr_t addr = (uintptr_t)fr;

	if (addr & (STACK_ALIGN - 1)) {
		mdb_iob_printf(mdb.m_err, "    mis-aligned frame (%p)\n", fr);
		return (0);
	}

	return (1);
}

static void
print_stack(kreg_t sp, int safe)
{
	struct frame *fr = (struct frame *)sp;
	int frnum = 1;

	while (fr != NULL && valid_frame(fr) && fr->fr_savpc != 0 &&
	    frnum < MAX_STACK_FRAMES) {
		print_frame(fr->fr_savpc, frnum, safe);

		fr = (struct frame *)fr->fr_savfp;
		frnum++;
	}
}

void
kmdb_print_stack(void)
{
	print_stack(get_fp(), FALSE); /* show sym names */
}

void
kmdb_fault_display(kreg_t trapno, kreg_t pc, kreg_t sp, int safe)
{
	mdb_iob_printf(mdb.m_err, "    trapno: %d, sp: %p, pc: %p", trapno,
	    sp, pc);
	if (!safe)
		mdb_iob_printf(mdb.m_err, " %A", pc);
	mdb_iob_printf(mdb.m_err, "\n\n");

	if (mdb.m_dseg == NULL || mdb.m_dsegsz == 0) {
		mdb_iob_printf(mdb.m_err,
		    "\t*** Stack trace omitted because debugger segment size\n"
		    "\t*** and/or length not set.\n");
		return;
	}

	if (!(sp - (uintptr_t)mdb.m_dseg < mdb.m_dsegsz)) {
		mdb_iob_printf(mdb.m_err,
		    "\t*** Stack trace omitted because sp (%p) isn't in the\n"
		    "\t*** debugger segment.\n", sp);
		return;
	}

	/*
	 * We were on a kmdb stack when we took this fault.  We're going to
	 * assume that there's nothing weird on the stack, and that, therefore,
	 * we can use a simple algorithm to dump it.
	 */

	print_stack(sp, safe);
}