xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_frame.c (revision 5e989a96186a37eb528fb7bb4d28a150874ec799)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Utility routines to manage debugger frames and commands.  A debugger frame
30  * is used by each invocation of mdb_run() (the main parsing loop) to manage
31  * its state.  Refer to the comments in mdb.c for more information on frames.
32  * Each frame has a list of commands (that is, a dcmd, argument list, and
33  * optional address list) that represent a pipeline after it has been parsed.
34  */
35 
36 #include <mdb/mdb_debug.h>
37 #include <mdb/mdb_frame.h>
38 #include <mdb/mdb_modapi.h>
39 #include <mdb/mdb_err.h>
40 #include <mdb/mdb_lex.h>
41 #include <mdb/mdb_io.h>
42 #include <mdb/mdb.h>
43 
44 mdb_cmd_t *
45 mdb_cmd_create(mdb_idcmd_t *idcp, mdb_argvec_t *argv)
46 {
47 	mdb_cmd_t *cp = mdb_zalloc(sizeof (mdb_cmd_t), UM_NOSLEEP);
48 
49 	if (cp == NULL) {
50 		warn("failed to allocate memory for command");
51 		longjmp(mdb.m_frame->f_pcb, MDB_ERR_NOMEM);
52 	}
53 
54 	mdb_list_append(&mdb.m_frame->f_cmds, cp);
55 	mdb_argvec_copy(&cp->c_argv, argv);
56 	mdb_argvec_zero(argv);
57 	cp->c_dcmd = idcp;
58 
59 	return (cp);
60 }
61 
62 void
63 mdb_cmd_destroy(mdb_cmd_t *cp)
64 {
65 	mdb_addrvec_destroy(&cp->c_addrv);
66 	mdb_argvec_destroy(&cp->c_argv);
67 	mdb_vcb_purge(cp->c_vcbs);
68 	mdb_free(cp, sizeof (mdb_cmd_t));
69 }
70 
71 void
72 mdb_cmd_reset(mdb_cmd_t *cp)
73 {
74 	mdb_addrvec_destroy(&cp->c_addrv);
75 	mdb_vcb_purge(cp->c_vcbs);
76 	cp->c_vcbs = NULL;
77 }
78 
79 void
80 mdb_frame_reset(mdb_frame_t *fp)
81 {
82 	mdb_cmd_t *cp;
83 
84 	while ((cp = mdb_list_next(&fp->f_cmds)) != NULL) {
85 		mdb_list_delete(&fp->f_cmds, cp);
86 		mdb_cmd_destroy(cp);
87 	}
88 	fp->f_cp = NULL;
89 	fp->f_pcmd = NULL;
90 
91 	while (mdb_iob_stack_size(&fp->f_ostk) != 0) {
92 		mdb_iob_destroy(mdb.m_out);
93 		mdb.m_out = mdb_iob_stack_pop(&fp->f_ostk);
94 	}
95 
96 	mdb_wcb_purge(&fp->f_wcbs);
97 	mdb_recycle(&fp->f_mblks);
98 }
99 
100 void
101 mdb_frame_push(mdb_frame_t *fp)
102 {
103 	mdb_intr_disable();
104 
105 	if (mdb.m_fmark == NULL)
106 		mdb.m_fmark = fp;
107 
108 	mdb_lex_state_save(mdb.m_frame->f_lstate);
109 
110 	bzero(fp, sizeof (mdb_frame_t));
111 	mdb_lex_state_create(fp);
112 	mdb_list_append(&mdb.m_flist, fp);
113 
114 	fp->f_flags = mdb.m_flags & MDB_FL_VOLATILE;
115 	fp->f_pcmd = mdb.m_frame->f_pcmd;
116 	fp->f_id = mdb.m_fid++;
117 	mdb.m_frame->f_dot = mdb_nv_get_value(mdb.m_dot);
118 
119 	mdb.m_frame = fp;
120 	mdb.m_depth++;
121 
122 	mdb_dprintf(MDB_DBG_DSTK, "push frame <%u> mark=%p in=%s out=%s\n",
123 	    fp->f_id, (void *)mdb.m_fmark,
124 	    mdb_iob_name(mdb.m_in), mdb_iob_name(mdb.m_out));
125 
126 	mdb_intr_enable();
127 }
128 
129 void
130 mdb_frame_pop(mdb_frame_t *fp, int err)
131 {
132 	mdb_intr_disable();
133 
134 	ASSERT(mdb_iob_stack_size(&fp->f_istk) == 0);
135 	ASSERT(mdb_iob_stack_size(&fp->f_ostk) == 0);
136 	ASSERT(mdb_list_next(&fp->f_cmds) == NULL);
137 	ASSERT(fp->f_mblks == NULL);
138 	ASSERT(fp->f_wcbs == NULL);
139 
140 	mdb_dprintf(MDB_DBG_DSTK, "pop frame <%u> status=%s\n",
141 	    fp->f_id, mdb_err2str(err));
142 
143 	if (mdb.m_frame == fp) {
144 		mdb.m_flags &= ~MDB_FL_VOLATILE;
145 		mdb.m_flags |= fp->f_flags;
146 		mdb_frame_switch(mdb_list_prev(fp));
147 	}
148 
149 	if (mdb.m_fmark == fp)
150 		mdb.m_fmark = NULL;
151 
152 	mdb_lex_state_destroy(fp);
153 
154 	mdb_list_delete(&mdb.m_flist, fp);
155 	ASSERT(mdb.m_depth != 0);
156 	mdb.m_depth--;
157 
158 	mdb_intr_enable();
159 }
160 
161 void
162 mdb_frame_switch(mdb_frame_t *frame)
163 {
164 	mdb_lex_state_save(mdb.m_frame->f_lstate);
165 	mdb.m_frame->f_dot = mdb_nv_get_value(mdb.m_dot);
166 	mdb.m_frame = frame;
167 	mdb_lex_state_restore(mdb.m_frame->f_lstate);
168 	mdb_dprintf(MDB_DBG_DSTK, "switch to frame <%u>\n", mdb.m_frame->f_id);
169 
170 	mdb_nv_set_value(mdb.m_dot, frame->f_dot);
171 }
172 
173 void
174 mdb_frame_set_pipe(mdb_frame_t *frame)
175 {
176 	frame->pipe = TRUE;
177 }
178 
179 void
180 mdb_frame_clear_pipe(mdb_frame_t *frame)
181 {
182 	frame->pipe = FALSE;
183 }
184 
185 mdb_frame_t *
186 mdb_frame_pipe(void)
187 {
188 	mdb_frame_t *frame = mdb_list_prev(mdb.m_frame);
189 
190 	while (frame && frame->pipe == FALSE)
191 		frame = mdb_list_prev(frame);
192 
193 	return (frame);
194 }
195