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