xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_frame.c (revision 2a8bcb4efb45d99ac41c94a75c396b362c414f7f)
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 /*
27  * Utility routines to manage debugger frames and commands.  A debugger frame
28  * is used by each invocation of mdb_run() (the main parsing loop) to manage
29  * its state.  Refer to the comments in mdb.c for more information on frames.
30  * Each frame has a list of commands (that is, a dcmd, argument list, and
31  * optional address list) that represent a pipeline after it has been parsed.
32  */
33 
34 #include <mdb/mdb_debug.h>
35 #include <mdb/mdb_frame.h>
36 #include <mdb/mdb_modapi.h>
37 #include <mdb/mdb_err.h>
38 #include <mdb/mdb_lex.h>
39 #include <mdb/mdb_io.h>
40 #include <mdb/mdb.h>
41 
42 mdb_cmd_t *
mdb_cmd_create(mdb_idcmd_t * idcp,mdb_argvec_t * argv)43 mdb_cmd_create(mdb_idcmd_t *idcp, mdb_argvec_t *argv)
44 {
45 	mdb_cmd_t *cp = mdb_zalloc(sizeof (mdb_cmd_t), UM_NOSLEEP);
46 
47 	if (cp == NULL) {
48 		warn("failed to allocate memory for command");
49 		longjmp(mdb.m_frame->f_pcb, MDB_ERR_NOMEM);
50 	}
51 
52 	mdb_list_append(&mdb.m_frame->f_cmds, cp);
53 	mdb_argvec_copy(&cp->c_argv, argv);
54 	mdb_argvec_zero(argv);
55 	cp->c_dcmd = idcp;
56 
57 	return (cp);
58 }
59 
60 void
mdb_cmd_destroy(mdb_cmd_t * cp)61 mdb_cmd_destroy(mdb_cmd_t *cp)
62 {
63 	mdb_addrvec_destroy(&cp->c_addrv);
64 	mdb_argvec_destroy(&cp->c_argv);
65 	mdb_vcb_purge(cp->c_vcbs);
66 	mdb_free(cp, sizeof (mdb_cmd_t));
67 }
68 
69 void
mdb_cmd_reset(mdb_cmd_t * cp)70 mdb_cmd_reset(mdb_cmd_t *cp)
71 {
72 	mdb_addrvec_destroy(&cp->c_addrv);
73 	mdb_vcb_purge(cp->c_vcbs);
74 	cp->c_vcbs = NULL;
75 }
76 
77 void
mdb_frame_reset(mdb_frame_t * fp)78 mdb_frame_reset(mdb_frame_t *fp)
79 {
80 	mdb_cmd_t *cp;
81 
82 	while ((cp = mdb_list_next(&fp->f_cmds)) != NULL) {
83 		mdb_list_delete(&fp->f_cmds, cp);
84 		mdb_cmd_destroy(cp);
85 	}
86 	fp->f_cp = NULL;
87 	fp->f_pcmd = NULL;
88 
89 	while (mdb_iob_stack_size(&fp->f_ostk) != 0) {
90 		mdb_iob_destroy(mdb.m_out);
91 		mdb.m_out = mdb_iob_stack_pop(&fp->f_ostk);
92 	}
93 
94 	mdb_wcb_purge(&fp->f_wcbs);
95 	mdb_recycle(&fp->f_mblks);
96 }
97 
98 void
mdb_frame_push(mdb_frame_t * fp)99 mdb_frame_push(mdb_frame_t *fp)
100 {
101 	mdb_intr_disable();
102 
103 	if (mdb.m_fmark == NULL)
104 		mdb.m_fmark = fp;
105 
106 	mdb_lex_state_save(mdb.m_frame->f_lstate);
107 
108 	bzero(fp, sizeof (mdb_frame_t));
109 	mdb_lex_state_create(fp);
110 	mdb_list_append(&mdb.m_flist, fp);
111 
112 	fp->f_flags = mdb.m_flags & MDB_FL_VOLATILE;
113 	fp->f_pcmd = mdb.m_frame->f_pcmd;
114 	fp->f_id = mdb.m_fid++;
115 	mdb.m_frame->f_dot = mdb_nv_get_value(mdb.m_dot);
116 
117 	mdb.m_frame = fp;
118 	mdb.m_depth++;
119 
120 	mdb_dprintf(MDB_DBG_DSTK, "push frame <%u> mark=%p in=%s out=%s\n",
121 	    fp->f_id, (void *)mdb.m_fmark,
122 	    mdb_iob_name(mdb.m_in), mdb_iob_name(mdb.m_out));
123 
124 	mdb_intr_enable();
125 }
126 
127 void
mdb_frame_pop(mdb_frame_t * fp,int err)128 mdb_frame_pop(mdb_frame_t *fp, int err)
129 {
130 	mdb_intr_disable();
131 
132 	ASSERT(mdb_iob_stack_size(&fp->f_istk) == 0);
133 	ASSERT(mdb_iob_stack_size(&fp->f_ostk) == 0);
134 	ASSERT(mdb_list_next(&fp->f_cmds) == NULL);
135 	ASSERT(fp->f_mblks == NULL);
136 	ASSERT(fp->f_wcbs == NULL);
137 
138 	mdb_dprintf(MDB_DBG_DSTK, "pop frame <%u> status=%s\n",
139 	    fp->f_id, mdb_err2str(err));
140 
141 	if (mdb.m_frame == fp) {
142 		mdb.m_flags &= ~MDB_FL_VOLATILE;
143 		mdb.m_flags |= fp->f_flags;
144 		mdb_frame_switch(mdb_list_prev(fp));
145 	}
146 
147 	if (mdb.m_fmark == fp)
148 		mdb.m_fmark = NULL;
149 
150 	mdb_lex_state_destroy(fp);
151 
152 	mdb_list_delete(&mdb.m_flist, fp);
153 	ASSERT(mdb.m_depth != 0);
154 	mdb.m_depth--;
155 
156 	mdb_intr_enable();
157 }
158 
159 void
mdb_frame_switch(mdb_frame_t * frame)160 mdb_frame_switch(mdb_frame_t *frame)
161 {
162 	mdb_lex_state_save(mdb.m_frame->f_lstate);
163 	mdb.m_frame->f_dot = mdb_nv_get_value(mdb.m_dot);
164 	mdb.m_frame = frame;
165 	mdb_lex_state_restore(mdb.m_frame->f_lstate);
166 	mdb_dprintf(MDB_DBG_DSTK, "switch to frame <%u>\n", mdb.m_frame->f_id);
167 
168 	mdb_nv_set_value(mdb.m_dot, frame->f_dot);
169 }
170 
171 void
mdb_frame_set_pipe(mdb_frame_t * frame)172 mdb_frame_set_pipe(mdb_frame_t *frame)
173 {
174 	frame->pipe = TRUE;
175 }
176 
177 void
mdb_frame_clear_pipe(mdb_frame_t * frame)178 mdb_frame_clear_pipe(mdb_frame_t *frame)
179 {
180 	frame->pipe = FALSE;
181 }
182 
183 mdb_frame_t *
mdb_frame_pipe(void)184 mdb_frame_pipe(void)
185 {
186 	mdb_frame_t *frame = mdb_list_prev(mdb.m_frame);
187 
188 	while (frame && frame->pipe == FALSE)
189 		frame = mdb_list_prev(frame);
190 
191 	return (frame);
192 }
193