xref: /illumos-gate/usr/src/cmd/mdb/common/modules/ipc/ipc.c (revision cf01ae8a)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5b2eb1770Sudpa  * Common Development and Distribution License (the "License").
6b2eb1770Sudpa  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22eb9fe4caSDavid Valin  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
277c478bd9Sstevel@tonic-gate #include <mdb/mdb_ks.h>
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <sys/mman.h>
317c478bd9Sstevel@tonic-gate #include <sys/project.h>
327c478bd9Sstevel@tonic-gate #include <sys/ipc_impl.h>
337c478bd9Sstevel@tonic-gate #include <sys/shm_impl.h>
347c478bd9Sstevel@tonic-gate #include <sys/sem_impl.h>
357c478bd9Sstevel@tonic-gate #include <sys/msg_impl.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include <vm/anon.h>
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #define	CMN_HDR_START	"%<u>"
407c478bd9Sstevel@tonic-gate #define	CMN_HDR_END	"%</u>\n"
417c478bd9Sstevel@tonic-gate #define	CMN_INDENT	(4)
427c478bd9Sstevel@tonic-gate #define	CMN_INACTIVE	"%s facility inactive.\n"
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate  * Bitmap data for page protection flags suitable for use with %b.
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate const mdb_bitmask_t prot_flag_bits[] = {
487c478bd9Sstevel@tonic-gate 	{ "PROT_READ", PROT_READ, PROT_READ },
497c478bd9Sstevel@tonic-gate 	{ "PROT_WRITE", PROT_WRITE, PROT_WRITE },
507c478bd9Sstevel@tonic-gate 	{ "PROT_EXEC", PROT_EXEC, PROT_EXEC },
517c478bd9Sstevel@tonic-gate 	{ "PROT_USER", PROT_USER, PROT_USER },
527c478bd9Sstevel@tonic-gate 	{ NULL, 0, 0 }
537c478bd9Sstevel@tonic-gate };
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate static void
printtime_nice(const char * str,time_t time)567c478bd9Sstevel@tonic-gate printtime_nice(const char *str, time_t time)
577c478bd9Sstevel@tonic-gate {
587c478bd9Sstevel@tonic-gate 	if (time)
597c478bd9Sstevel@tonic-gate 		mdb_printf("%s%Y\n", str, time);
607c478bd9Sstevel@tonic-gate 	else
617c478bd9Sstevel@tonic-gate 		mdb_printf("%sn/a\n", str);
627c478bd9Sstevel@tonic-gate }
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate  * Print header common to all IPC types.
667c478bd9Sstevel@tonic-gate  */
677c478bd9Sstevel@tonic-gate static void
ipcperm_header()687c478bd9Sstevel@tonic-gate ipcperm_header()
697c478bd9Sstevel@tonic-gate {
707c478bd9Sstevel@tonic-gate 	mdb_printf(CMN_HDR_START "%?s %5s %5s %8s %5s %5s %6s %5s %5s %5s %5s"
717c478bd9Sstevel@tonic-gate 	    CMN_HDR_END, "ADDR", "REF", "ID", "KEY", "MODE", "PRJID", "ZONEID",
727c478bd9Sstevel@tonic-gate 	    "OWNER", "GROUP", "CREAT", "CGRP");
737c478bd9Sstevel@tonic-gate }
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate /*
767c478bd9Sstevel@tonic-gate  * Print data common to all IPC types.
777c478bd9Sstevel@tonic-gate  */
787c478bd9Sstevel@tonic-gate static void
ipcperm_print(uintptr_t addr,kipc_perm_t * perm)797c478bd9Sstevel@tonic-gate ipcperm_print(uintptr_t addr, kipc_perm_t *perm)
807c478bd9Sstevel@tonic-gate {
817c478bd9Sstevel@tonic-gate 	kproject_t proj;
827c478bd9Sstevel@tonic-gate 	int res;
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	res = mdb_vread(&proj, sizeof (kproject_t), (uintptr_t)perm->ipc_proj);
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	if (res == -1)
877c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read kproject_t at %#p", perm->ipc_proj);
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	mdb_printf("%0?p %5d %5d", addr, perm->ipc_ref, perm->ipc_id);
907c478bd9Sstevel@tonic-gate 	if (perm->ipc_key)
917c478bd9Sstevel@tonic-gate 		mdb_printf(" %8x", perm->ipc_key);
927c478bd9Sstevel@tonic-gate 	else
937c478bd9Sstevel@tonic-gate 		mdb_printf(" %8s", "private");
947c478bd9Sstevel@tonic-gate 	mdb_printf(" %5#o", perm->ipc_mode & 07777);
957c478bd9Sstevel@tonic-gate 	if (res == -1)
967c478bd9Sstevel@tonic-gate 		mdb_printf(" %5s %5s", "<flt>", "<flt>");
977c478bd9Sstevel@tonic-gate 	else
987c478bd9Sstevel@tonic-gate 		mdb_printf(" %5d %6d", proj.kpj_id, proj.kpj_zoneid);
997c478bd9Sstevel@tonic-gate 	mdb_printf(" %5d %5d %5d %5d\n", perm->ipc_uid, perm->ipc_gid,
1007c478bd9Sstevel@tonic-gate 	    perm->ipc_cuid, perm->ipc_cgid);
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1057c478bd9Sstevel@tonic-gate static int
ipcperm(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1067c478bd9Sstevel@tonic-gate ipcperm(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	kipc_perm_t perm;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
1117c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags))
1147c478bd9Sstevel@tonic-gate 		ipcperm_header();
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	if (mdb_vread(&perm, sizeof (kipc_perm_t), addr) == -1) {
1177c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read kipc_perm_t at %#lx", addr);
1187c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
1197c478bd9Sstevel@tonic-gate 	}
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	ipcperm_print(addr, &perm);
1227c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
1237c478bd9Sstevel@tonic-gate }
1247c478bd9Sstevel@tonic-gate 
1252c5b6df1Sdv 
126eb9fe4caSDavid Valin #define	MSG_SND_SIZE 0x1
1272c5b6df1Sdv static int
msgq_check_for_waiters(list_t * walk_this,int min,int max,int copy_wait,uintptr_t addr,int flag)128eb9fe4caSDavid Valin msgq_check_for_waiters(list_t *walk_this, int min, int max,
129*cf01ae8aSToomas Soome     int copy_wait, uintptr_t addr, int flag)
1302c5b6df1Sdv {
1312c5b6df1Sdv 	int found = 0;
1322c5b6df1Sdv 	int ii;
133f03c4264Sdv 	msgq_wakeup_t *walker, next;
1342c5b6df1Sdv 	uintptr_t head;
1352c5b6df1Sdv 
1362c5b6df1Sdv 	for (ii = min; ii < max; ii++) {
1372c5b6df1Sdv 		head = ((ulong_t)addr) + sizeof (list_t)*ii +
1382c5b6df1Sdv 		    sizeof (list_node_t);
1392c5b6df1Sdv 		if (head != (uintptr_t)walk_this[ii].list_head.list_next) {
1402c5b6df1Sdv 			walker =
1412c5b6df1Sdv 			    (msgq_wakeup_t *)walk_this[ii].list_head.list_next;
1422c5b6df1Sdv 			while (head != (uintptr_t)walker) {
1432c5b6df1Sdv 				if (mdb_vread(&next, sizeof (msgq_wakeup_t),
1442c5b6df1Sdv 				    (uintptr_t)walker) == -1) {
1452c5b6df1Sdv 					mdb_warn(
1462c5b6df1Sdv 					    "Failed to read message queue\n");
147eb9fe4caSDavid Valin 					return (found);
148eb9fe4caSDavid Valin 				}
149eb9fe4caSDavid Valin 
150eb9fe4caSDavid Valin 				if (flag & MSG_SND_SIZE) {
151eb9fe4caSDavid Valin 					mdb_printf("%15lx\t%6d\t%15lx\t%15d\n",
152eb9fe4caSDavid Valin 					    next.msgw_thrd, next.msgw_type,
153eb9fe4caSDavid Valin 					    walker + (uintptr_t)
154eb9fe4caSDavid Valin 					    OFFSETOF(msgq_wakeup_t,
155eb9fe4caSDavid Valin 					    msgw_wake_cv), next.msgw_snd_size);
156eb9fe4caSDavid Valin 				} else {
157eb9fe4caSDavid Valin 					mdb_printf("%15lx\t%6d\t%15lx\t%15s\n",
158eb9fe4caSDavid Valin 					    next.msgw_thrd, next.msgw_type,
159eb9fe4caSDavid Valin 					    walker + (uintptr_t)
160eb9fe4caSDavid Valin 					    OFFSETOF(msgq_wakeup_t,
161eb9fe4caSDavid Valin 					    msgw_wake_cv),
162eb9fe4caSDavid Valin 					    (copy_wait ? "yes":"no"));
1632c5b6df1Sdv 				}
1642c5b6df1Sdv 				found++;
1652c5b6df1Sdv 				walker =
1662c5b6df1Sdv 				    (msgq_wakeup_t *)next.msgw_list.list_next;
1672c5b6df1Sdv 			}
1682c5b6df1Sdv 		}
1692c5b6df1Sdv 	}
1702c5b6df1Sdv 	return (found);
1712c5b6df1Sdv }
1722c5b6df1Sdv 
1737c478bd9Sstevel@tonic-gate static void
msq_print(kmsqid_t * msqid,uintptr_t addr)1747c478bd9Sstevel@tonic-gate msq_print(kmsqid_t *msqid, uintptr_t addr)
1757c478bd9Sstevel@tonic-gate {
1762c5b6df1Sdv 	int	total = 0;
177b2eb1770Sudpa 
1787c478bd9Sstevel@tonic-gate 	mdb_printf("&list: %-?p\n", addr + OFFSETOF(kmsqid_t, msg_list));
1797c478bd9Sstevel@tonic-gate 	mdb_printf("cbytes: 0t%lu    qnum: 0t%lu    qbytes: 0t%lu"
1807c478bd9Sstevel@tonic-gate 	    "    qmax: 0t%lu\n", msqid->msg_cbytes, msqid->msg_qnum,
1817c478bd9Sstevel@tonic-gate 	    msqid->msg_qbytes, msqid->msg_qmax);
1827c478bd9Sstevel@tonic-gate 	mdb_printf("lspid: 0t%d    lrpid: 0t%d\n",
1837c478bd9Sstevel@tonic-gate 	    (int)msqid->msg_lspid, (int)msqid->msg_lrpid);
1847c478bd9Sstevel@tonic-gate 	printtime_nice("stime: ", msqid->msg_stime);
1857c478bd9Sstevel@tonic-gate 	printtime_nice("rtime: ", msqid->msg_rtime);
1867c478bd9Sstevel@tonic-gate 	printtime_nice("ctime: ", msqid->msg_ctime);
187b2eb1770Sudpa 	mdb_printf("snd_cnt: 0t%lld    snd_cv: %hd (%p)\n",
188b2eb1770Sudpa 	    msqid->msg_snd_cnt, msqid->msg_snd_cv._opaque,
189b2eb1770Sudpa 	    addr + (uintptr_t)OFFSETOF(kmsqid_t, msg_snd_cv));
1902c5b6df1Sdv 	mdb_printf("Blocked recievers\n");
1912c5b6df1Sdv 	mdb_printf("%15s\t%6s\t%15s\t%15s\n", "Thread Addr",
1922c5b6df1Sdv 	    "Type", "cv addr", "copyout-wait?");
193eb9fe4caSDavid Valin 	total += msgq_check_for_waiters(&msqid->msg_cpy_block,
194eb9fe4caSDavid Valin 	    0, 1, 1, addr + OFFSETOF(kmsqid_t, msg_cpy_block), 0);
195eb9fe4caSDavid Valin 	total += msgq_check_for_waiters(msqid->msg_wait_snd_ngt,
1962c5b6df1Sdv 	    0, MSG_MAX_QNUM + 1, 0,
197eb9fe4caSDavid Valin 	    addr + OFFSETOF(kmsqid_t, msg_wait_snd_ngt), 0);
198eb9fe4caSDavid Valin 	mdb_printf("Blocked senders\n");
199eb9fe4caSDavid Valin 	total += msgq_check_for_waiters(&msqid->msg_wait_rcv,
200eb9fe4caSDavid Valin 	    0, 1, 1, addr + OFFSETOF(kmsqid_t, msg_wait_rcv),
201eb9fe4caSDavid Valin 	    MSG_SND_SIZE);
202eb9fe4caSDavid Valin 	mdb_printf("%15s\t%6s\t%15s\t%15s\n", "Thread Addr",
203eb9fe4caSDavid Valin 	    "Type", "cv addr", "Msg Size");
204eb9fe4caSDavid Valin 	total += msgq_check_for_waiters(msqid->msg_wait_snd,
205eb9fe4caSDavid Valin 	    0, MSG_MAX_QNUM + 1, 0, addr + OFFSETOF(kmsqid_t,
206eb9fe4caSDavid Valin 	    msg_wait_snd), 0);
2072c5b6df1Sdv 	mdb_printf("Total number of waiters: %d\n", total);
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
2127c478bd9Sstevel@tonic-gate static void
shm_print(kshmid_t * shmid,uintptr_t addr)2137c478bd9Sstevel@tonic-gate shm_print(kshmid_t *shmid, uintptr_t addr)
2147c478bd9Sstevel@tonic-gate {
2157c478bd9Sstevel@tonic-gate 	shmatt_t nattch;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	nattch = shmid->shm_perm.ipc_ref - (IPC_FREE(&shmid->shm_perm) ? 0 : 1);
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	mdb_printf(CMN_HDR_START "%10s %?s %5s %7s %7s %7s %7s" CMN_HDR_END,
2207c478bd9Sstevel@tonic-gate 	    "SEGSZ", "AMP", "LKCNT", "LPID", "CPID", "NATTCH", "CNATTCH");
2217c478bd9Sstevel@tonic-gate 	mdb_printf("%10#lx %?p %5u %7d %7d %7lu %7lu\n",
2227c478bd9Sstevel@tonic-gate 	    shmid->shm_segsz, shmid->shm_amp, shmid->shm_lkcnt,
2237c478bd9Sstevel@tonic-gate 	    (int)shmid->shm_lpid, (int)shmid->shm_cpid, nattch,
2247c478bd9Sstevel@tonic-gate 	    shmid->shm_ismattch);
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	printtime_nice("atime: ", shmid->shm_atime);
2277c478bd9Sstevel@tonic-gate 	printtime_nice("dtime: ", shmid->shm_dtime);
2287c478bd9Sstevel@tonic-gate 	printtime_nice("ctime: ", shmid->shm_ctime);
2297c478bd9Sstevel@tonic-gate 	mdb_printf("sptinfo: %-?p    sptseg: %-?p\n",
2307c478bd9Sstevel@tonic-gate 	    shmid->shm_sptinfo, shmid->shm_sptseg);
2317c478bd9Sstevel@tonic-gate 	mdb_printf("sptprot: <%lb>\n", shmid->shm_sptprot, prot_flag_bits);
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
2367c478bd9Sstevel@tonic-gate static void
sem_print(ksemid_t * semid,uintptr_t addr)2377c478bd9Sstevel@tonic-gate sem_print(ksemid_t *semid, uintptr_t addr)
2387c478bd9Sstevel@tonic-gate {
2397c478bd9Sstevel@tonic-gate 	mdb_printf("base: %-?p    nsems: 0t%u\n",
2407c478bd9Sstevel@tonic-gate 	    semid->sem_base, semid->sem_nsems);
2417c478bd9Sstevel@tonic-gate 	printtime_nice("otime: ", semid->sem_otime);
2427c478bd9Sstevel@tonic-gate 	printtime_nice("ctime: ", semid->sem_ctime);
2437c478bd9Sstevel@tonic-gate 	mdb_printf("binary: %s\n", semid->sem_binary ? "yes" : "no");
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate typedef struct ipc_ops_vec {
2477c478bd9Sstevel@tonic-gate 	char	*iv_wcmd;	/* walker name		*/
2487c478bd9Sstevel@tonic-gate 	char	*iv_ocmd;	/* output dcmd		*/
2497c478bd9Sstevel@tonic-gate 	char	*iv_service;	/* service pointer	*/
2507c478bd9Sstevel@tonic-gate 	void	(*iv_print)(void *, uintptr_t); /* output callback */
2517c478bd9Sstevel@tonic-gate 	size_t	iv_idsize;
2527c478bd9Sstevel@tonic-gate } ipc_ops_vec_t;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate ipc_ops_vec_t msq_ops_vec = {
2557c478bd9Sstevel@tonic-gate 	"msq",
2567c478bd9Sstevel@tonic-gate 	"kmsqid",
2577c478bd9Sstevel@tonic-gate 	"msq_svc",
2587c478bd9Sstevel@tonic-gate 	(void(*)(void *, uintptr_t))msq_print,
2597c478bd9Sstevel@tonic-gate 	sizeof (kmsqid_t)
2607c478bd9Sstevel@tonic-gate };
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate ipc_ops_vec_t shm_ops_vec = {
2637c478bd9Sstevel@tonic-gate 	"shm",
2647c478bd9Sstevel@tonic-gate 	"kshmid",
2657c478bd9Sstevel@tonic-gate 	"shm_svc",
2667c478bd9Sstevel@tonic-gate 	(void(*)(void *, uintptr_t))shm_print,
2677c478bd9Sstevel@tonic-gate 	sizeof (kshmid_t)
2687c478bd9Sstevel@tonic-gate };
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate ipc_ops_vec_t sem_ops_vec = {
2717c478bd9Sstevel@tonic-gate 	"sem",
2727c478bd9Sstevel@tonic-gate 	"ksemid",
2737c478bd9Sstevel@tonic-gate 	"sem_svc",
2747c478bd9Sstevel@tonic-gate 	(void(*)(void *, uintptr_t))sem_print,
2757c478bd9Sstevel@tonic-gate 	sizeof (ksemid_t)
2767c478bd9Sstevel@tonic-gate };
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate /*
2807c478bd9Sstevel@tonic-gate  * Generic IPC data structure display code
2817c478bd9Sstevel@tonic-gate  */
2827c478bd9Sstevel@tonic-gate static int
ds_print(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv,ipc_ops_vec_t * iv)2837c478bd9Sstevel@tonic-gate ds_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
2847c478bd9Sstevel@tonic-gate     ipc_ops_vec_t *iv)
2857c478bd9Sstevel@tonic-gate {
2867c478bd9Sstevel@tonic-gate 	void *iddata;
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC)) {
2897c478bd9Sstevel@tonic-gate 		uint_t oflags = 0;
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 		if (mdb_getopts(argc, argv, 'l', MDB_OPT_SETBITS, 1, &oflags,
2927c478bd9Sstevel@tonic-gate 		    NULL) != argc)
2937c478bd9Sstevel@tonic-gate 			return (DCMD_USAGE);
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 		if (mdb_walk_dcmd(iv->iv_wcmd, oflags ? iv->iv_ocmd : "ipcperm",
2967c478bd9Sstevel@tonic-gate 		    argc, argv) == -1) {
2977c478bd9Sstevel@tonic-gate 			mdb_warn("can't walk '%s'", iv->iv_wcmd);
2987c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
2997c478bd9Sstevel@tonic-gate 		}
3007c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	iddata = mdb_alloc(iv->iv_idsize, UM_SLEEP | UM_GC);
3047c478bd9Sstevel@tonic-gate 	if (mdb_vread(iddata, iv->iv_idsize, addr) == -1) {
3057c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read %s at %#lx", iv->iv_ocmd, addr);
3067c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
3077c478bd9Sstevel@tonic-gate 	}
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	if (!DCMD_HDRSPEC(flags) && iv->iv_print)
3107c478bd9Sstevel@tonic-gate 		mdb_printf("\n");
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags) || iv->iv_print)
3137c478bd9Sstevel@tonic-gate 		ipcperm_header();
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	ipcperm_print(addr, (struct kipc_perm *)iddata);
3167c478bd9Sstevel@tonic-gate 	if (iv->iv_print) {
3177c478bd9Sstevel@tonic-gate 		mdb_inc_indent(CMN_INDENT);
3187c478bd9Sstevel@tonic-gate 		iv->iv_print(iddata, addr);
3197c478bd9Sstevel@tonic-gate 		mdb_dec_indent(CMN_INDENT);
3207c478bd9Sstevel@tonic-gate 	}
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate /*
3277c478bd9Sstevel@tonic-gate  * Stubs to call ds_print with the appropriate ops vector
3287c478bd9Sstevel@tonic-gate  */
3297c478bd9Sstevel@tonic-gate static int
cmd_kshmid(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3307c478bd9Sstevel@tonic-gate cmd_kshmid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3317c478bd9Sstevel@tonic-gate {
3327c478bd9Sstevel@tonic-gate 	return (ds_print(addr, flags, argc, argv, &shm_ops_vec));
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate static int
cmd_kmsqid(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3377c478bd9Sstevel@tonic-gate cmd_kmsqid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3387c478bd9Sstevel@tonic-gate {
3397c478bd9Sstevel@tonic-gate 	return (ds_print(addr, flags, argc, argv, &msq_ops_vec));
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate static int
cmd_ksemid(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3437c478bd9Sstevel@tonic-gate cmd_ksemid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate 	return (ds_print(addr, flags, argc, argv, &sem_ops_vec));
3467c478bd9Sstevel@tonic-gate }
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate /*
3497c478bd9Sstevel@tonic-gate  * Generic IPC walker
3507c478bd9Sstevel@tonic-gate  */
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate static int
ds_walk_init(mdb_walk_state_t * wsp)3537c478bd9Sstevel@tonic-gate ds_walk_init(mdb_walk_state_t *wsp)
3547c478bd9Sstevel@tonic-gate {
3557c478bd9Sstevel@tonic-gate 	ipc_ops_vec_t	*iv = wsp->walk_arg;
3567c478bd9Sstevel@tonic-gate 
357892ad162SToomas Soome 	if (wsp->walk_arg != NULL && wsp->walk_addr != 0)
3587c478bd9Sstevel@tonic-gate 		mdb_printf("ignoring provided address\n");
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	if (wsp->walk_arg)
3617c478bd9Sstevel@tonic-gate 		if (mdb_readvar(&wsp->walk_addr, iv->iv_service) == -1) {
3627c478bd9Sstevel@tonic-gate 			mdb_printf("failed to read '%s'; module not present\n",
3637c478bd9Sstevel@tonic-gate 			    iv->iv_service);
3647c478bd9Sstevel@tonic-gate 			return (WALK_DONE);
3657c478bd9Sstevel@tonic-gate 		}
3667c478bd9Sstevel@tonic-gate 	else
3677c478bd9Sstevel@tonic-gate 		wsp->walk_addr = wsp->walk_addr +
3687c478bd9Sstevel@tonic-gate 		    OFFSETOF(ipc_service_t, ipcs_usedids);
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	if (mdb_layered_walk("list", wsp) == -1)
3717c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate static int
ds_walk_step(mdb_walk_state_t * wsp)3787c478bd9Sstevel@tonic-gate ds_walk_step(mdb_walk_state_t *wsp)
3797c478bd9Sstevel@tonic-gate {
3807c478bd9Sstevel@tonic-gate 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
3817c478bd9Sstevel@tonic-gate 	    wsp->walk_cbdata));
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate /*
3857c478bd9Sstevel@tonic-gate  * Generic IPC ID/key to pointer code
3867c478bd9Sstevel@tonic-gate  */
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate static int
ipcid_impl(uintptr_t svcptr,uintptr_t id,uintptr_t * addr)3897c478bd9Sstevel@tonic-gate ipcid_impl(uintptr_t svcptr, uintptr_t id, uintptr_t *addr)
3907c478bd9Sstevel@tonic-gate {
3917c478bd9Sstevel@tonic-gate 	ipc_service_t service;
3927c478bd9Sstevel@tonic-gate 	kipc_perm_t perm;
3937c478bd9Sstevel@tonic-gate 	ipc_slot_t slot;
3947c478bd9Sstevel@tonic-gate 	uintptr_t slotptr;
3957c478bd9Sstevel@tonic-gate 	uint_t index;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	if (id > INT_MAX) {
3987c478bd9Sstevel@tonic-gate 		mdb_warn("id out of range\n");
3997c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4007c478bd9Sstevel@tonic-gate 	}
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	if (mdb_vread(&service, sizeof (ipc_service_t), svcptr) == -1) {
4037c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read ipc_service_t at %#lx", svcptr);
4047c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4057c478bd9Sstevel@tonic-gate 	}
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	index = (uint_t)id & (service.ipcs_tabsz - 1);
4087c478bd9Sstevel@tonic-gate 	slotptr = (uintptr_t)(service.ipcs_table + index);
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	if (mdb_vread(&slot, sizeof (ipc_slot_t), slotptr) == -1) {
4117c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read ipc_slot_t at %#lx", slotptr);
4127c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4137c478bd9Sstevel@tonic-gate 	}
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	if (slot.ipct_data == NULL)
4167c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	if (mdb_vread(&perm, sizeof (kipc_perm_t),
4197c478bd9Sstevel@tonic-gate 	    (uintptr_t)slot.ipct_data) == -1) {
4207c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read kipc_perm_t at %#p",
4217c478bd9Sstevel@tonic-gate 		    slot.ipct_data);
4227c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4237c478bd9Sstevel@tonic-gate 	}
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	if (perm.ipc_id != (uint_t)id)
4267c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 	*addr = (uintptr_t)slot.ipct_data;
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate typedef struct findkey_data {
4357c478bd9Sstevel@tonic-gate 	key_t fk_key;
4367c478bd9Sstevel@tonic-gate 	uintptr_t fk_addr;
4377c478bd9Sstevel@tonic-gate 	boolean_t fk_found;
4387c478bd9Sstevel@tonic-gate } findkey_data_t;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate static int
findkey(uintptr_t addr,kipc_perm_t * perm,findkey_data_t * arg)4417c478bd9Sstevel@tonic-gate findkey(uintptr_t addr, kipc_perm_t *perm, findkey_data_t *arg)
4427c478bd9Sstevel@tonic-gate {
4437c478bd9Sstevel@tonic-gate 	if (perm->ipc_key == arg->fk_key) {
4447c478bd9Sstevel@tonic-gate 		arg->fk_found = B_TRUE;
4457c478bd9Sstevel@tonic-gate 		arg->fk_addr = addr;
4467c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
4477c478bd9Sstevel@tonic-gate 	}
4487c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate static int
ipckey_impl(uintptr_t svcptr,uintptr_t key,uintptr_t * addr)4527c478bd9Sstevel@tonic-gate ipckey_impl(uintptr_t svcptr, uintptr_t key, uintptr_t *addr)
4537c478bd9Sstevel@tonic-gate {
4547c478bd9Sstevel@tonic-gate 	ipc_service_t	service;
4557c478bd9Sstevel@tonic-gate 	findkey_data_t	fkdata;
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	if ((key == IPC_PRIVATE) || (key > INT_MAX)) {
4587c478bd9Sstevel@tonic-gate 		mdb_warn("key out of range\n");
4597c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4607c478bd9Sstevel@tonic-gate 	}
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	if (mdb_vread(&service, sizeof (ipc_service_t), svcptr) == -1) {
4637c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read ipc_service_t at %#lx", svcptr);
4647c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4657c478bd9Sstevel@tonic-gate 	}
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 	fkdata.fk_key = (key_t)key;
4687c478bd9Sstevel@tonic-gate 	fkdata.fk_found = B_FALSE;
4697c478bd9Sstevel@tonic-gate 	if ((mdb_pwalk("avl", (mdb_walk_cb_t)findkey, &fkdata,
4707c478bd9Sstevel@tonic-gate 	    svcptr + OFFSETOF(ipc_service_t, ipcs_keys)) == -1) ||
4717c478bd9Sstevel@tonic-gate 	    !fkdata.fk_found)
4727c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	*addr = fkdata.fk_addr;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate static int
ipckeyid(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv,int (* fp)(uintptr_t,uintptr_t,uintptr_t *))4807c478bd9Sstevel@tonic-gate ipckeyid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
4817c478bd9Sstevel@tonic-gate     int(*fp)(uintptr_t, uintptr_t, uintptr_t *))
4827c478bd9Sstevel@tonic-gate {
4837c478bd9Sstevel@tonic-gate 	uintmax_t val;
4847c478bd9Sstevel@tonic-gate 	uintptr_t raddr;
4857c478bd9Sstevel@tonic-gate 	int result;
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC) || (argc != 1))
4887c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	if (argv[0].a_type == MDB_TYPE_IMMEDIATE)
4917c478bd9Sstevel@tonic-gate 		val = argv[0].a_un.a_val;
4927c478bd9Sstevel@tonic-gate 	else if (argv[0].a_type == MDB_TYPE_STRING)
4937c478bd9Sstevel@tonic-gate 		val = mdb_strtoull(argv[0].a_un.a_str);
4947c478bd9Sstevel@tonic-gate 	else
4957c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	result = fp(addr, val, &raddr);
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 	if (result == DCMD_OK)
5007c478bd9Sstevel@tonic-gate 		mdb_printf("%lx", raddr);
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	return (result);
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate static int
ipckey(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5067c478bd9Sstevel@tonic-gate ipckey(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5077c478bd9Sstevel@tonic-gate {
5087c478bd9Sstevel@tonic-gate 	return (ipckeyid(addr, flags, argc, argv, ipckey_impl));
5097c478bd9Sstevel@tonic-gate }
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate static int
ipcid(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5127c478bd9Sstevel@tonic-gate ipcid(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5137c478bd9Sstevel@tonic-gate {
5147c478bd9Sstevel@tonic-gate 	return (ipckeyid(addr, flags, argc, argv, ipcid_impl));
5157c478bd9Sstevel@tonic-gate }
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate static int
ds_ptr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv,ipc_ops_vec_t * iv)5187c478bd9Sstevel@tonic-gate ds_ptr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv,
5197c478bd9Sstevel@tonic-gate     ipc_ops_vec_t *iv)
5207c478bd9Sstevel@tonic-gate {
5217c478bd9Sstevel@tonic-gate 	uint_t		kflag = FALSE;
5227c478bd9Sstevel@tonic-gate 	uintptr_t	svcptr, raddr;
5237c478bd9Sstevel@tonic-gate 	int		result;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
5267c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
5297c478bd9Sstevel@tonic-gate 	    'k', MDB_OPT_SETBITS, TRUE, &kflag, NULL) != argc)
5307c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 	if (mdb_readvar(&svcptr, iv->iv_service) == -1) {
5337c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read '%s'; module not present\n",
5347c478bd9Sstevel@tonic-gate 		    iv->iv_service);
5357c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
5367c478bd9Sstevel@tonic-gate 	}
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	result = kflag ? ipckey_impl(svcptr, addr, &raddr) :
5397c478bd9Sstevel@tonic-gate 	    ipcid_impl(svcptr, addr, &raddr);
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	if (result == DCMD_OK)
5427c478bd9Sstevel@tonic-gate 		mdb_printf("%lx", raddr);
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 	return (result);
5457c478bd9Sstevel@tonic-gate }
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate /*
5487c478bd9Sstevel@tonic-gate  * Stubs to call ds_ptr with the appropriate ops vector
5497c478bd9Sstevel@tonic-gate  */
5507c478bd9Sstevel@tonic-gate static int
id2shm(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5517c478bd9Sstevel@tonic-gate id2shm(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5527c478bd9Sstevel@tonic-gate {
5537c478bd9Sstevel@tonic-gate 	return (ds_ptr(addr, flags, argc, argv, &shm_ops_vec));
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate static int
id2msq(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5577c478bd9Sstevel@tonic-gate id2msq(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5587c478bd9Sstevel@tonic-gate {
5597c478bd9Sstevel@tonic-gate 	return (ds_ptr(addr, flags, argc, argv, &msq_ops_vec));
5607c478bd9Sstevel@tonic-gate }
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate static int
id2sem(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5637c478bd9Sstevel@tonic-gate id2sem(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5647c478bd9Sstevel@tonic-gate {
5657c478bd9Sstevel@tonic-gate 	return (ds_ptr(addr, flags, argc, argv, &sem_ops_vec));
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate /*
5707c478bd9Sstevel@tonic-gate  * The message queue contents walker
5717c478bd9Sstevel@tonic-gate  */
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate static int
msg_walk_init(mdb_walk_state_t * wsp)5747c478bd9Sstevel@tonic-gate msg_walk_init(mdb_walk_state_t *wsp)
5757c478bd9Sstevel@tonic-gate {
5767c478bd9Sstevel@tonic-gate 	wsp->walk_addr += OFFSETOF(kmsqid_t, msg_list);
5777c478bd9Sstevel@tonic-gate 	if (mdb_layered_walk("list", wsp) == -1)
5787c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
5817c478bd9Sstevel@tonic-gate }
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate static int
msg_walk_step(mdb_walk_state_t * wsp)5847c478bd9Sstevel@tonic-gate msg_walk_step(mdb_walk_state_t *wsp)
5857c478bd9Sstevel@tonic-gate {
5867c478bd9Sstevel@tonic-gate 	return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer,
5877c478bd9Sstevel@tonic-gate 	    wsp->walk_cbdata));
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate /*
5917c478bd9Sstevel@tonic-gate  * The "::ipcs" command itself.  Just walks each IPC type in turn.
5927c478bd9Sstevel@tonic-gate  */
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5957c478bd9Sstevel@tonic-gate static int
ipcs(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)5967c478bd9Sstevel@tonic-gate ipcs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5977c478bd9Sstevel@tonic-gate {
5987c478bd9Sstevel@tonic-gate 	uint_t	oflags = 0;
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	if ((flags & DCMD_ADDRSPEC) || mdb_getopts(argc, argv, 'l',
6017c478bd9Sstevel@tonic-gate 	    MDB_OPT_SETBITS, 1, &oflags, NULL) != argc)
6027c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	mdb_printf("Message queues:\n");
6057c478bd9Sstevel@tonic-gate 	if (mdb_walk_dcmd("msq", oflags ? "kmsqid" : "ipcperm", argc, argv) ==
6067c478bd9Sstevel@tonic-gate 	    -1) {
6077c478bd9Sstevel@tonic-gate 		mdb_warn("can't walk 'msq'");
6087c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
6097c478bd9Sstevel@tonic-gate 	}
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	mdb_printf("\nShared memory:\n");
6127c478bd9Sstevel@tonic-gate 	if (mdb_walk_dcmd("shm", oflags ? "kshmid" : "ipcperm", argc, argv) ==
6137c478bd9Sstevel@tonic-gate 	    -1) {
6147c478bd9Sstevel@tonic-gate 		mdb_warn("can't walk 'shm'");
6157c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
6167c478bd9Sstevel@tonic-gate 	}
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 	mdb_printf("\nSemaphores:\n");
6197c478bd9Sstevel@tonic-gate 	if (mdb_walk_dcmd("sem", oflags ? "ksemid" : "ipcperm", argc, argv) ==
6207c478bd9Sstevel@tonic-gate 	    -1) {
6217c478bd9Sstevel@tonic-gate 		mdb_warn("can't walk 'sem'");
6227c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
6237c478bd9Sstevel@tonic-gate 	}
6247c478bd9Sstevel@tonic-gate 
6257c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
6267c478bd9Sstevel@tonic-gate }
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate static int
msgprint(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)6297c478bd9Sstevel@tonic-gate msgprint(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
6307c478bd9Sstevel@tonic-gate {
6317c478bd9Sstevel@tonic-gate 	struct msg message;
6327c478bd9Sstevel@tonic-gate 	uint_t	lflag = FALSE;
6337c478bd9Sstevel@tonic-gate 	long	type = 0;
6347c478bd9Sstevel@tonic-gate 	char	*tflag = NULL;
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC) || (mdb_getopts(argc, argv,
6377c478bd9Sstevel@tonic-gate 	    'l', MDB_OPT_SETBITS, TRUE, &lflag,
6387c478bd9Sstevel@tonic-gate 	    't', MDB_OPT_STR, &tflag, NULL) != argc))
6397c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	/*
6427c478bd9Sstevel@tonic-gate 	 * Handle negative values.
6437c478bd9Sstevel@tonic-gate 	 */
6447c478bd9Sstevel@tonic-gate 	if (tflag != NULL) {
6457c478bd9Sstevel@tonic-gate 		if (*tflag == '-') {
6467c478bd9Sstevel@tonic-gate 			tflag++;
6477c478bd9Sstevel@tonic-gate 			type = -1;
6487c478bd9Sstevel@tonic-gate 		} else {
6497c478bd9Sstevel@tonic-gate 			type = 1;
6507c478bd9Sstevel@tonic-gate 		}
6517c478bd9Sstevel@tonic-gate 		type *= mdb_strtoull(tflag);
6527c478bd9Sstevel@tonic-gate 	}
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	if (DCMD_HDRSPEC(flags))
6557c478bd9Sstevel@tonic-gate 		mdb_printf("%<u>%?s %?s %8s %8s %8s%</u>\n",
6567c478bd9Sstevel@tonic-gate 		    "ADDR", "TEXT", "SIZE", "TYPE", "REF");
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	if (mdb_vread(&message, sizeof (struct msg), addr) == -1) {
6597c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read msg at %#lx", addr);
6607c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
6617c478bd9Sstevel@tonic-gate 	}
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	/*
6647c478bd9Sstevel@tonic-gate 	 * If we are meeting our type contraints, display the message.
6657c478bd9Sstevel@tonic-gate 	 * If -l was specified, we will also display the message
6667c478bd9Sstevel@tonic-gate 	 * contents.
6677c478bd9Sstevel@tonic-gate 	 */
6687c478bd9Sstevel@tonic-gate 	if ((type == 0) ||
6697c478bd9Sstevel@tonic-gate 	    (type > 0 && message.msg_type == type) ||
6707c478bd9Sstevel@tonic-gate 	    (type < 0 && message.msg_type <= -type)) {
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 		if (lflag && !DCMD_HDRSPEC(flags))
6737c478bd9Sstevel@tonic-gate 			mdb_printf("\n");
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 		mdb_printf("%0?lx %?p %8ld %8ld %8ld\n", addr, message.msg_addr,
6767c478bd9Sstevel@tonic-gate 		    message.msg_size, message.msg_type, message.msg_copycnt);
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 		if (lflag) {
6797c478bd9Sstevel@tonic-gate 			mdb_printf("\n");
6807c478bd9Sstevel@tonic-gate 			mdb_inc_indent(CMN_INDENT);
6817c478bd9Sstevel@tonic-gate 			if (mdb_dumpptr(
6827c478bd9Sstevel@tonic-gate 			    (uintptr_t)message.msg_addr, message.msg_size,
6837c478bd9Sstevel@tonic-gate 			    MDB_DUMP_RELATIVE | MDB_DUMP_TRIM |
6847c478bd9Sstevel@tonic-gate 			    MDB_DUMP_ASCII | MDB_DUMP_HEADER |
685*cf01ae8aSToomas Soome 			    MDB_DUMP_GROUP(4), NULL, NULL)) {
6867c478bd9Sstevel@tonic-gate 				mdb_dec_indent(CMN_INDENT);
6877c478bd9Sstevel@tonic-gate 				return (DCMD_ERR);
6887c478bd9Sstevel@tonic-gate 			}
6897c478bd9Sstevel@tonic-gate 			mdb_dec_indent(CMN_INDENT);
6907c478bd9Sstevel@tonic-gate 		}
6917c478bd9Sstevel@tonic-gate 	}
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
6947c478bd9Sstevel@tonic-gate }
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate /*
6977c478bd9Sstevel@tonic-gate  * MDB module linkage
6987c478bd9Sstevel@tonic-gate  */
6997c478bd9Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = {
7007c478bd9Sstevel@tonic-gate 	/* Generic routines */
7017c478bd9Sstevel@tonic-gate 	{ "ipcperm", ":", "display an IPC perm structure", ipcperm },
7027c478bd9Sstevel@tonic-gate 	{ "ipcid", ":id", "perform an IPC id lookup", ipcid },
7037c478bd9Sstevel@tonic-gate 	{ "ipckey", ":key", "perform an IPC key lookup", ipckey },
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 	/* Specific routines */
7067c478bd9Sstevel@tonic-gate 	{ "kshmid", "?[-l]", "display a struct kshmid", cmd_kshmid },
7077c478bd9Sstevel@tonic-gate 	{ "kmsqid", "?[-l]", "display a struct kmsqid", cmd_kmsqid },
7087c478bd9Sstevel@tonic-gate 	{ "ksemid", "?[-l]", "display a struct ksemid", cmd_ksemid },
7097c478bd9Sstevel@tonic-gate 	{ "msg", ":[-l] [-t type]", "display contents of a message", msgprint },
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 	/* Convenience routines */
7127c478bd9Sstevel@tonic-gate 	{ "id2shm", ":[-k]", "convert shared memory ID to pointer", id2shm },
7137c478bd9Sstevel@tonic-gate 	{ "id2msq", ":[-k]", "convert message queue ID to pointer", id2msq },
7147c478bd9Sstevel@tonic-gate 	{ "id2sem", ":[-k]", "convert semaphore ID to pointer", id2sem },
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 	{ "ipcs", "[-l]", "display System V IPC information", ipcs },
7177c478bd9Sstevel@tonic-gate 	{ NULL }
7187c478bd9Sstevel@tonic-gate };
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate static const mdb_walker_t walkers[] = {
7217c478bd9Sstevel@tonic-gate 	{ "ipcsvc", "walk a System V IPC service",
7227c478bd9Sstevel@tonic-gate 		ds_walk_init, ds_walk_step },
7237c478bd9Sstevel@tonic-gate 	{ "shm", "walk the active shmid_ds structures",
7247c478bd9Sstevel@tonic-gate 		ds_walk_init, ds_walk_step, NULL, &shm_ops_vec },
7257c478bd9Sstevel@tonic-gate 	{ "msq", "walk the active msqid_ds structures",
7267c478bd9Sstevel@tonic-gate 		ds_walk_init, ds_walk_step, NULL, &msq_ops_vec },
7277c478bd9Sstevel@tonic-gate 	{ "sem", "walk the active semid_ds structures",
7287c478bd9Sstevel@tonic-gate 		ds_walk_init, ds_walk_step, NULL, &sem_ops_vec },
7297c478bd9Sstevel@tonic-gate 	{ "msgqueue", "walk messages on a message queue",
7307c478bd9Sstevel@tonic-gate 		msg_walk_init, msg_walk_step },
7317c478bd9Sstevel@tonic-gate 	{ NULL }
7327c478bd9Sstevel@tonic-gate };
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate const mdb_modinfo_t *
_mdb_init(void)7377c478bd9Sstevel@tonic-gate _mdb_init(void)
7387c478bd9Sstevel@tonic-gate {
7397c478bd9Sstevel@tonic-gate 	return (&modinfo);
7407c478bd9Sstevel@tonic-gate }
741