4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2017 Joyent, Inc.
28 #include <mdb/mdb_modapi.h>
29 #include <mdb/mdb_ks.h>
31 #include <sys/types.h>
32 #include <sys/strsubr.h>
35 typedef struct pt_flags
{
40 static const struct pt_flags pf
[] = {
41 { "PTLOCK", "Master/slave pair is locked" },
42 { "PTMOPEN", "Master side is open" },
43 { "PTSOPEN", "Slave side is open" },
44 { "PTSTTY", "Slave side is tty" },
49 pt_parse_flag(const ptflags_t ftable
[], const char *arg
, uint32_t *flag
)
53 for (i
= 0; ftable
[i
].pt_name
!= NULL
; i
++) {
54 if (strcasecmp(arg
, ftable
[i
].pt_name
) == 0) {
64 pt_flag_usage(const ptflags_t ftable
[])
68 for (i
= 0; ftable
[i
].pt_name
!= NULL
; i
++)
69 mdb_printf("%12s %s\n",
70 ftable
[i
].pt_name
, ftable
[i
].pt_descr
);
76 ptms_pr_qinfo(char *buf
, size_t nbytes
, struct pt_ttys
*pt
, char *peername
,
77 queue_t
*peerq
, char *procname
)
79 (void) mdb_snprintf(buf
, nbytes
,
80 "pts/%d:%s: %p\nprocess: %d(%s)",
81 pt
->pt_minor
, peername
, peerq
, pt
->pt_pid
, procname
);
85 ptms(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
87 const int PT_FLGDELT
= (int)(sizeof (uintptr_t) * 2 + 5);
90 char c
[MAXCOMLEN
+ 1];
91 const char *flag
= NULL
, *not_flag
= NULL
;
93 uint_t verbose
= FALSE
;
94 uint32_t mask
= 0, not_mask
= 0;
96 if (!(flags
& DCMD_ADDRSPEC
))
97 return (mdb_walk_dcmd("ptms", "ptms", argc
, argv
));
99 if (mdb_getopts(argc
, argv
,
100 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
,
101 'f', MDB_OPT_STR
, &flag
,
102 'F', MDB_OPT_STR
, ¬_flag
, NULL
) != argc
)
105 if (DCMD_HDRSPEC(flags
) && flag
== NULL
&& not_flag
== NULL
) {
106 (void) mdb_printf("%?-s %s %s %?-s %?-s %3s %-6s %s\n",
107 "ADDR", "PTY", "FL", "MASTERQ", "SLAVEQ",
108 "ZID", "PID", "PROC");
111 if (flag
!= NULL
&& pt_parse_flag(pf
, flag
, &mask
) == -1) {
112 mdb_warn("unrecognized pty flag '%s'\n", flag
);
117 if (not_flag
!= NULL
&& pt_parse_flag(pf
, not_flag
, ¬_mask
) == -1) {
118 mdb_warn("unrecognized queue flag '%s'\n", flag
);
123 if (mdb_vread(&pt
, sizeof (pt
), addr
) == -1) {
124 mdb_warn("failed to read pty structure");
128 if (mask
!= 0 && !(pt
.pt_state
& mask
))
131 if (not_mask
!= 0 && (pt
.pt_state
& not_mask
))
135 * Options are specified for filtering, so If any option is specified on
136 * the command line, just print address and exit.
138 if (flag
!= NULL
|| not_flag
!= NULL
) {
139 mdb_printf("%0?p\n", addr
);
143 if (pt
.pt_pid
!= 0) {
144 if (mdb_pid2proc(pt
.pt_pid
, &p
) == 0)
145 (void) strcpy(c
, "<defunct>");
147 (void) strcpy(c
, p
.p_user
.u_comm
);
149 (void) strcpy(c
, "<unknown>");
151 (void) mdb_printf("%0?p %3d %2x %0?p %0?p %3d %6d %s\n",
152 addr
, pt
.pt_minor
, pt
.pt_state
, pt
.ptm_rdq
, pt
.pts_rdq
,
153 pt
.pt_zoneid
, pt
.pt_pid
, c
);
158 for (i
= 0; pf
[i
].pt_name
!= NULL
; i
++) {
159 if (!(pt
.pt_state
& (1 << i
)))
162 mdb_printf("%*s|\n%*s+--> ",
163 PT_FLGDELT
, "", PT_FLGDELT
, "");
166 mdb_printf("%*s ", PT_FLGDELT
, "");
168 mdb_printf("%-12s %s\n",
169 pf
[i
].pt_name
, pf
[i
].pt_descr
);
177 ptms_qinfo(const queue_t
*q
, char *buf
, size_t nbytes
, int ismaster
)
179 char c
[MAXCOMLEN
+ 1];
183 (void) mdb_vread(&pt
, sizeof (pt
), (uintptr_t)q
->q_ptr
);
185 if (pt
.pt_pid
!= 0) {
186 if (mdb_pid2proc(pt
.pt_pid
, &p
) == 0)
187 (void) strcpy(c
, "<defunct>");
189 (void) strcpy(c
, p
.p_user
.u_comm
);
191 (void) strcpy(c
, "<unknown>");
194 ptms_pr_qinfo(buf
, nbytes
, &pt
, "slave", pt
.pts_rdq
, c
);
196 ptms_pr_qinfo(buf
, nbytes
, &pt
, "master", pt
.ptm_rdq
, c
);
200 ptm_qinfo(const queue_t
*q
, char *buf
, size_t nbytes
)
202 ptms_qinfo(q
, buf
, nbytes
, 1);
206 pts_qinfo(const queue_t
*q
, char *buf
, size_t nbytes
)
208 ptms_qinfo(q
, buf
, nbytes
, 0);
212 ptms_walk_init(mdb_walk_state_t
*wsp
)
216 if (wsp
->walk_addr
!= (uintptr_t)NULL
) {
217 mdb_warn("ptms supports only global walks");
221 if (mdb_readvar(&wsp
->walk_addr
, "ptms_slots") == -1) {
222 mdb_warn("failed to read 'ptms_slots'");
226 if (mdb_readvar(&nslots
, "ptms_nslots") == -1) {
227 mdb_warn("failed to read 'ptms_nslots'");
232 * We remember the pointer value at the end of the array. When
233 * the walk gets there, we're done.
235 wsp
->walk_arg
= (((struct pt_ttys
**)wsp
->walk_addr
) + (nslots
- 1));
236 wsp
->walk_data
= mdb_alloc(sizeof (struct pt_ttys
), UM_SLEEP
);
242 ptms_walk_step(mdb_walk_state_t
*wsp
)
247 if (wsp
->walk_addr
> (uintptr_t)wsp
->walk_arg
)
250 if (mdb_vread(&ptr
, sizeof (struct pt_ttys
*), wsp
->walk_addr
) !=
251 (sizeof (struct pt_ttys
*))) {
252 mdb_warn("failed to read pt_ttys* at %p", wsp
->walk_addr
);
256 if (ptr
== (uintptr_t)NULL
) {
257 wsp
->walk_addr
+= sizeof (uintptr_t);
261 if (mdb_vread(wsp
->walk_data
, sizeof (struct pt_ttys
), ptr
) !=
262 sizeof (struct pt_ttys
)) {
263 mdb_warn("failed to read pt_ttys at %p", ptr
);
267 status
= wsp
->walk_callback(ptr
, wsp
->walk_data
, wsp
->walk_cbdata
);
268 wsp
->walk_addr
+= sizeof (uintptr_t);
274 ptms_walk_fini(mdb_walk_state_t
*wsp
)
276 mdb_free(wsp
->walk_data
, sizeof (struct pt_ttys
));
279 static const mdb_dcmd_t dcmds
[] = {
280 { "ptms", "?[-v] [-f flag] [-F flag]",
281 "print pseudo-terminal information", ptms
},
282 { "pty", "?[-v] [-f flag] [-F flag]",
283 "print pseudo-terminal information (alias of ::ptms", ptms
},
287 static const mdb_walker_t walkers
[] = {
288 { "ptms", "walk list of pseudo-tty's",
289 ptms_walk_init
, ptms_walk_step
, ptms_walk_fini
},
290 { "pty", "walk list of pseudo-tty's (alias of ::walk ptms)",
291 ptms_walk_init
, ptms_walk_step
, ptms_walk_fini
},
295 static const mdb_qops_t ptm_qops
= {
296 ptm_qinfo
, mdb_qrnext_default
, mdb_qwnext_default
299 static const mdb_qops_t pts_qops
= {
300 pts_qinfo
, mdb_qrnext_default
, mdb_qwnext_default
303 static const mdb_modinfo_t modinfo
= {
304 MDB_API_VERSION
, dcmds
, walkers
307 const mdb_modinfo_t
*
312 if (mdb_lookup_by_obj("ptm", "ptmwint", &sym
) == 0)
313 mdb_qops_install(&ptm_qops
, (uintptr_t)sym
.st_value
);
314 if (mdb_lookup_by_obj("pts", "ptswint", &sym
) == 0)
315 mdb_qops_install(&pts_qops
, (uintptr_t)sym
.st_value
);
325 if (mdb_lookup_by_obj("ptm", "ptmwint", &sym
) == 0)
326 mdb_qops_remove(&ptm_qops
, (uintptr_t)sym
.st_value
);
327 if (mdb_lookup_by_obj("pts", "ptswint", &sym
) == 0)
328 mdb_qops_remove(&pts_qops
, (uintptr_t)sym
.st_value
);