12a12f85aSJeremy Jones /*
22a12f85aSJeremy Jones  * This file and its contents are supplied under the terms of the
32a12f85aSJeremy Jones  * Common Development and Distribution License ("CDDL"), version 1.0.
42a12f85aSJeremy Jones  * You may only use this file in accordance with the terms of version
52a12f85aSJeremy Jones  * 1.0 of the CDDL.
62a12f85aSJeremy Jones  *
72a12f85aSJeremy Jones  * A full copy of the text of the CDDL should have accompanied this
82a12f85aSJeremy Jones  * source.  A copy of the CDDL is also available via the Internet at
92a12f85aSJeremy Jones  * http://www.illumos.org/license/CDDL.
102a12f85aSJeremy Jones  */
112a12f85aSJeremy Jones /*
122a12f85aSJeremy Jones  * Copyright (c) 2013 by Delphix. All rights reserved.
132a12f85aSJeremy Jones  */
142a12f85aSJeremy Jones 
152a12f85aSJeremy Jones /*
162a12f85aSJeremy Jones  * This file implements the mdb ::gcore command.  The command relies on the
172a12f85aSJeremy Jones  * libproc Pgcore function to actually generate the core file but we provide
182a12f85aSJeremy Jones  * our own ops vector to populate data required by Pgcore.  The ops vector
192a12f85aSJeremy Jones  * function implementations simulate the functionality implemented by procfs.
202a12f85aSJeremy Jones  * The data provided by some of the ops vector functions is not complete
212a12f85aSJeremy Jones  * (missing data is documented in function headers) but there is enough
222a12f85aSJeremy Jones  * information to generate a core file that can be loaded into mdb.
232a12f85aSJeremy Jones  *
2469a119caSChristopher Siden  * Currently only x86 is supported. ISA-dependent functions are implemented
2569a119caSChristopher Siden  * in gcore_isadep.c.
262a12f85aSJeremy Jones  */
272a12f85aSJeremy Jones 
282a12f85aSJeremy Jones #ifndef _KMDB
292a12f85aSJeremy Jones 
302a12f85aSJeremy Jones /*
312a12f85aSJeremy Jones  * The kernel has its own definition of exit which has a different signature
322a12f85aSJeremy Jones  * than the user space definition.  This seems to be the standard way to deal
332a12f85aSJeremy Jones  * with this.
342a12f85aSJeremy Jones  */
352a12f85aSJeremy Jones #define	exit kern_exit
362a12f85aSJeremy Jones 
372a12f85aSJeremy Jones #include <mdb/mdb_modapi.h>
382a12f85aSJeremy Jones #include <mdb/mdb_param.h>
392a12f85aSJeremy Jones #include <mdb/mdb_ks.h>
402a12f85aSJeremy Jones #include <mdb/mdb_ctf.h>
412a12f85aSJeremy Jones #include <mdb/mdb_debug.h>
4269a119caSChristopher Siden #include <mdb/mdb_gcore.h>
432a12f85aSJeremy Jones 
442a12f85aSJeremy Jones #include <sys/class.h>
452a12f85aSJeremy Jones #include <sys/cpuvar.h>
462a12f85aSJeremy Jones #include <sys/proc.h>
472a12f85aSJeremy Jones #include <sys/lgrp.h>
482a12f85aSJeremy Jones #include <sys/pool.h>
492a12f85aSJeremy Jones #include <sys/project.h>
502a12f85aSJeremy Jones #include <sys/regset.h>
512a12f85aSJeremy Jones #include <sys/schedctl.h>
522a12f85aSJeremy Jones #include <sys/session.h>
532a12f85aSJeremy Jones #include <sys/syscall.h>
542a12f85aSJeremy Jones #include <sys/task.h>
552a12f85aSJeremy Jones #include <sys/var.h>
562a12f85aSJeremy Jones #include <sys/privregs.h>
572a12f85aSJeremy Jones #include <sys/fault.h>
582a12f85aSJeremy Jones #include <sys/sysmacros.h>
592a12f85aSJeremy Jones #include <sys/wait.h>
602a12f85aSJeremy Jones #include <vm/seg.h>
612a12f85aSJeremy Jones #include <vm/vpage.h>
622a12f85aSJeremy Jones #include <fs/proc/prdata.h>
632a12f85aSJeremy Jones 
642a12f85aSJeremy Jones #undef exit
652a12f85aSJeremy Jones 
662a12f85aSJeremy Jones #include <stdio.h>
672a12f85aSJeremy Jones #include <stdbool.h>
682a12f85aSJeremy Jones #include <string.h>
692a12f85aSJeremy Jones #include <libproc.h>
7064e4e50aSKeith M Wesolowski #include <errno.h>
712a12f85aSJeremy Jones 
722a12f85aSJeremy Jones #include "avl.h"
732a12f85aSJeremy Jones 
742a12f85aSJeremy Jones #ifdef _LP64
752a12f85aSJeremy Jones #define	LSPAN(type)	(P2ROUNDUP(sizeof (type), 16))
762a12f85aSJeremy Jones #else
772a12f85aSJeremy Jones #define	LSPAN(type)	(P2ROUNDUP(sizeof (type), 8))
782a12f85aSJeremy Jones #endif
792a12f85aSJeremy Jones 
802a12f85aSJeremy Jones #define	vpgtob(n)	((n) * sizeof (struct vpage))
812a12f85aSJeremy Jones 
822a12f85aSJeremy Jones /* Macros to invoke gcore seg operations */
832a12f85aSJeremy Jones #define	GSOP_INIT(_gs)		(_gs)->gs_ops->gsop_init((_gs))
842a12f85aSJeremy Jones #define	GSOP_FINI(_gs)		(_gs)->gs_ops->gsop_fini((_gs))
852a12f85aSJeremy Jones #define	GSOP_INCORE(_gs, _addr, _eaddr)	\
862a12f85aSJeremy Jones 	(_gs)->gs_ops->gsop_incore((_gs), (_addr), (_eaddr))
872a12f85aSJeremy Jones #define	GSOP_GETPROT(_gs, _addr)	\
882a12f85aSJeremy Jones 	(_gs)->gs_ops->gsop_getprot((_gs), (_addr))
892a12f85aSJeremy Jones #define	GSOP_GETOFFSET(_gs, _addr)	\
902a12f85aSJeremy Jones 	(_gs)->gs_ops->gsop_getoffset((_gs), (_addr))
912a12f85aSJeremy Jones #define	GSOP_GETTYPE(_gs, _addr)	\
922a12f85aSJeremy Jones 	(_gs)->gs_ops->gsop_gettype((_gs), (_addr))
932a12f85aSJeremy Jones #define	GSOP_NAME(_gs, _name, _size)	\
942a12f85aSJeremy Jones 	(_gs)->gs_ops->gsop_name((_gs), (_name), (_size))
952a12f85aSJeremy Jones #define	GSOP_NORESERVE(_gs)		\
962a12f85aSJeremy Jones 	(_gs)->gs_ops->gsop_noreserve((_gs))
972a12f85aSJeremy Jones 
982a12f85aSJeremy Jones #ifdef GCORE_DEBUG
992a12f85aSJeremy Jones #define	dprintf(...)	mdb_printf(__VA_ARGS__)
1002a12f85aSJeremy Jones #else
1012a12f85aSJeremy Jones #define	dprintf(...)
1022a12f85aSJeremy Jones #endif
1032a12f85aSJeremy Jones 
1042a12f85aSJeremy Jones /* Callback function type for processing lwp entries */
1052a12f85aSJeremy Jones typedef int (*lwp_callback_t)(mdb_proc_t *, lwpent_t *, void *);
1062a12f85aSJeremy Jones 
1072a12f85aSJeremy Jones /* Private data */
1082a12f85aSJeremy Jones static uintptr_t gcore_segvn_ops;
1092a12f85aSJeremy Jones static priv_impl_info_t prinfo;
1102a12f85aSJeremy Jones static sclass_t *gcore_sclass;
1112a12f85aSJeremy Jones static uintptr_t gcore_kas;
1122a12f85aSJeremy Jones static boolean_t gcore_initialized = B_FALSE;
1132a12f85aSJeremy Jones 
1142a12f85aSJeremy Jones typedef int (*gsop_init_t)(gcore_seg_t *);
1152a12f85aSJeremy Jones typedef void (*gsop_fini_t)(gcore_seg_t *);
1162a12f85aSJeremy Jones typedef u_offset_t (*gsop_incore_t)(gcore_seg_t *, u_offset_t, u_offset_t);
1172a12f85aSJeremy Jones typedef uint_t (*gsop_getprot_t)(gcore_seg_t *, u_offset_t);
1182a12f85aSJeremy Jones typedef int (*gsop_getoffset_t)(gcore_seg_t *, u_offset_t);
1192a12f85aSJeremy Jones typedef void (*gsop_name_t)(gcore_seg_t *, char *name, size_t size);
1202a12f85aSJeremy Jones typedef int (*gsop_gettype_t)(gcore_seg_t *, u_offset_t);
1212a12f85aSJeremy Jones typedef boolean_t (*gsop_noreserve_t)(gcore_seg_t *);
1222a12f85aSJeremy Jones 
1232a12f85aSJeremy Jones typedef struct gcore_segops {
1242a12f85aSJeremy Jones 	gsop_init_t		gsop_init;
1252a12f85aSJeremy Jones 	gsop_fini_t		gsop_fini;
1262a12f85aSJeremy Jones 	gsop_incore_t		gsop_incore;
1272a12f85aSJeremy Jones 	gsop_getprot_t		gsop_getprot;
1282a12f85aSJeremy Jones 	gsop_getoffset_t	gsop_getoffset;
1292a12f85aSJeremy Jones 	gsop_name_t		gsop_name;
1302a12f85aSJeremy Jones 	gsop_gettype_t		gsop_gettype;
1312a12f85aSJeremy Jones 	gsop_noreserve_t	gsop_noreserve;
1322a12f85aSJeremy Jones } gcore_segops_t;
1332a12f85aSJeremy Jones 
1342a12f85aSJeremy Jones static void map_list_free(prmap_node_t *);
1352a12f85aSJeremy Jones static uintptr_t gcore_prchoose(mdb_proc_t *);
1362a12f85aSJeremy Jones 
1372a12f85aSJeremy Jones /*
1382a12f85aSJeremy Jones  * Segvn ops
1392a12f85aSJeremy Jones  */
1402a12f85aSJeremy Jones static int gsvn_init(gcore_seg_t *);
1412a12f85aSJeremy Jones static void gsvn_fini(gcore_seg_t *);
1422a12f85aSJeremy Jones static u_offset_t gsvn_incore(gcore_seg_t *, u_offset_t, u_offset_t);
1432a12f85aSJeremy Jones static uint_t gsvn_getprot(gcore_seg_t *, u_offset_t);
1442a12f85aSJeremy Jones static int gsvn_getoffset(gcore_seg_t *, u_offset_t);
1452a12f85aSJeremy Jones static void gsvn_name(gcore_seg_t *, char *, size_t);
1462a12f85aSJeremy Jones static int gsvn_gettype(gcore_seg_t *, u_offset_t);
1472a12f85aSJeremy Jones static boolean_t gsvn_noreserve(gcore_seg_t *);
1482a12f85aSJeremy Jones 
1492a12f85aSJeremy Jones static gcore_segops_t gsvn_ops = {
1502a12f85aSJeremy Jones 	.gsop_init		= gsvn_init,
1512a12f85aSJeremy Jones 	.gsop_fini		= gsvn_fini,
1522a12f85aSJeremy Jones 	.gsop_incore		= gsvn_incore,
1532a12f85aSJeremy Jones 	.gsop_getprot		= gsvn_getprot,
1542a12f85aSJeremy Jones 	.gsop_getoffset		= gsvn_getoffset,
1552a12f85aSJeremy Jones 	.gsop_name		= gsvn_name,
1562a12f85aSJeremy Jones 	.gsop_gettype		= gsvn_gettype,
1572a12f85aSJeremy Jones 	.gsop_noreserve		= gsvn_noreserve
1582a12f85aSJeremy Jones };
1592a12f85aSJeremy Jones 
1602a12f85aSJeremy Jones static int
gsvn_init(gcore_seg_t * gs)1612a12f85aSJeremy Jones gsvn_init(gcore_seg_t *gs)
1622a12f85aSJeremy Jones {
1632a12f85aSJeremy Jones 	mdb_seg_t		*seg = gs->gs_seg;
1642a12f85aSJeremy Jones 	mdb_segvn_data_t	*svd = NULL;
1652a12f85aSJeremy Jones 	struct vpage		*vpage = NULL;
1662a12f85aSJeremy Jones 	size_t			nvpage = 0;
1672a12f85aSJeremy Jones 
168892ad162SToomas Soome 	if (seg->s_data != 0) {
1692a12f85aSJeremy Jones 		svd = mdb_alloc(sizeof (*svd), UM_SLEEP);
1702a12f85aSJeremy Jones 		if (mdb_ctf_vread(svd, "segvn_data_t", "mdb_segvn_data_t",
1712a12f85aSJeremy Jones 		    seg->s_data, 0) == -1) {
1722a12f85aSJeremy Jones 			goto error;
1732a12f85aSJeremy Jones 		}
1742a12f85aSJeremy Jones 
1752a12f85aSJeremy Jones 		if (svd->pageprot != 0) {
1762a12f85aSJeremy Jones 			nvpage = seg_pages(seg);
1772a12f85aSJeremy Jones 			dprintf("vpage count: %d\n", nvpage);
1782a12f85aSJeremy Jones 
1792a12f85aSJeremy Jones 			vpage = mdb_alloc(vpgtob(nvpage), UM_SLEEP);
1802a12f85aSJeremy Jones 			if (mdb_vread(vpage, vpgtob(nvpage),
1812a12f85aSJeremy Jones 			    (uintptr_t)svd->vpage) != vpgtob(nvpage)) {
1822a12f85aSJeremy Jones 				mdb_warn("Failed to read vpages from %p\n",
1832a12f85aSJeremy Jones 				    svd->vpage);
1842a12f85aSJeremy Jones 				goto error;
1852a12f85aSJeremy Jones 			}
1862a12f85aSJeremy Jones 
1872a12f85aSJeremy Jones 			svd->vpage = vpage;
1882a12f85aSJeremy Jones 		} else {
1892a12f85aSJeremy Jones 			svd->vpage = NULL;
1902a12f85aSJeremy Jones 		}
1912a12f85aSJeremy Jones 		gs->gs_data = svd;
1922a12f85aSJeremy Jones 	} else {
1932a12f85aSJeremy Jones 		gs->gs_data = NULL;
1942a12f85aSJeremy Jones 	}
1952a12f85aSJeremy Jones 
1962a12f85aSJeremy Jones 	return (0);
1972a12f85aSJeremy Jones 
1982a12f85aSJeremy Jones error:
1992a12f85aSJeremy Jones 	mdb_free(vpage, vpgtob(nvpage));
2002a12f85aSJeremy Jones 	mdb_free(svd, sizeof (*svd));
2012a12f85aSJeremy Jones 	return (-1);
2022a12f85aSJeremy Jones }
2032a12f85aSJeremy Jones 
2042a12f85aSJeremy Jones /*ARGSUSED*/
2052a12f85aSJeremy Jones static int
gsvn_getoffset(gcore_seg_t * gs,u_offset_t addr)2062a12f85aSJeremy Jones gsvn_getoffset(gcore_seg_t *gs, u_offset_t addr)
2072a12f85aSJeremy Jones {
2082a12f85aSJeremy Jones 	mdb_segvn_data_t	*svd = gs->gs_data;
2092a12f85aSJeremy Jones 	mdb_seg_t		*seg = gs->gs_seg;
2102a12f85aSJeremy Jones 
2112a12f85aSJeremy Jones 	return (svd->offset + (uintptr_t)(addr - seg->s_base));
2122a12f85aSJeremy Jones }
2132a12f85aSJeremy Jones 
2142a12f85aSJeremy Jones static void
gsvn_name(gcore_seg_t * gs,char * name,size_t size)2152a12f85aSJeremy Jones gsvn_name(gcore_seg_t *gs, char *name, size_t size)
2162a12f85aSJeremy Jones {
2172a12f85aSJeremy Jones 	mdb_segvn_data_t	*svd = gs->gs_data;
2182a12f85aSJeremy Jones 
2192a12f85aSJeremy Jones 	name[0] = '\0';
2202a12f85aSJeremy Jones 	if (svd->vp != 0) {
2212a12f85aSJeremy Jones 		mdb_seg_t	*seg = gs->gs_seg;
2222a12f85aSJeremy Jones 		mdb_as_t	as;
2232a12f85aSJeremy Jones 		mdb_proc_t	p;
2242a12f85aSJeremy Jones 		mdb_vnode_t	vn;
2252a12f85aSJeremy Jones 
2262a12f85aSJeremy Jones 		if (mdb_ctf_vread(&vn, "vnode_t", "mdb_vnode_t", svd->vp, 0)
2272a12f85aSJeremy Jones 		    == -1) {
2282a12f85aSJeremy Jones 			return;
2292a12f85aSJeremy Jones 		}
2302a12f85aSJeremy Jones 
2312a12f85aSJeremy Jones 		if (mdb_ctf_vread(&as, "struct as", "mdb_as_t", seg->s_as, 0)
2322a12f85aSJeremy Jones 		    == -1) {
2332a12f85aSJeremy Jones 			return;
2342a12f85aSJeremy Jones 		}
2352a12f85aSJeremy Jones 
2362a12f85aSJeremy Jones 		if (mdb_ctf_vread(&p, "proc_t", "mdb_proc_t", as.a_proc, 0)
2372a12f85aSJeremy Jones 		    == -1) {
2382a12f85aSJeremy Jones 			return;
2392a12f85aSJeremy Jones 		}
2402a12f85aSJeremy Jones 
2412a12f85aSJeremy Jones 		if (vn.v_type == VREG && svd->vp == p.p_exec) {
2422a12f85aSJeremy Jones 			(void) strncpy(name, "a.out", size);
2432a12f85aSJeremy Jones 		}
2442a12f85aSJeremy Jones 
2452a12f85aSJeremy Jones 		/*
2462a12f85aSJeremy Jones 		 * procfs has more logic here to construct a name using
2472a12f85aSJeremy Jones 		 * vfs/vnode identifiers but didn't seem worthwhile to add
2482a12f85aSJeremy Jones 		 * here.
2492a12f85aSJeremy Jones 		 */
2502a12f85aSJeremy Jones 	}
2512a12f85aSJeremy Jones }
2522a12f85aSJeremy Jones 
2532a12f85aSJeremy Jones /*ARGSUSED*/
2542a12f85aSJeremy Jones static int
gsvn_gettype(gcore_seg_t * gs,u_offset_t addr)2552a12f85aSJeremy Jones gsvn_gettype(gcore_seg_t *gs, u_offset_t addr)
2562a12f85aSJeremy Jones {
2572a12f85aSJeremy Jones 	return (0);
2582a12f85aSJeremy Jones }
2592a12f85aSJeremy Jones 
2602a12f85aSJeremy Jones static void
gsvn_fini(gcore_seg_t * gs)2612a12f85aSJeremy Jones gsvn_fini(gcore_seg_t *gs)
2622a12f85aSJeremy Jones {
2632a12f85aSJeremy Jones 	mdb_segvn_data_t	*svd = gs->gs_data;
2642a12f85aSJeremy Jones 
2652a12f85aSJeremy Jones 	if (svd != NULL) {
2662a12f85aSJeremy Jones 		if (svd->vpage != NULL) {
2672a12f85aSJeremy Jones 			size_t nvpage = seg_pages(gs->gs_seg);
2682a12f85aSJeremy Jones 
2692a12f85aSJeremy Jones 			mdb_free(svd->vpage, vpgtob(nvpage));
2702a12f85aSJeremy Jones 		}
2712a12f85aSJeremy Jones 		mdb_free(svd, sizeof (*svd));
2722a12f85aSJeremy Jones 	}
2732a12f85aSJeremy Jones }
2742a12f85aSJeremy Jones 
2752a12f85aSJeremy Jones static boolean_t
gsvn_noreserve(gcore_seg_t * gs)2762a12f85aSJeremy Jones gsvn_noreserve(gcore_seg_t *gs)
2772a12f85aSJeremy Jones {
2782a12f85aSJeremy Jones 	mdb_segvn_data_t	*svd = gs->gs_data;
2792a12f85aSJeremy Jones 
2802a12f85aSJeremy Jones 	if (svd == NULL) {
2812a12f85aSJeremy Jones 		return (B_FALSE);
2822a12f85aSJeremy Jones 	}
2832a12f85aSJeremy Jones 
2842a12f85aSJeremy Jones 	if (svd->flags & MAP_NORESERVE) {
2852a12f85aSJeremy Jones 		mdb_vnode_t vn;
2862a12f85aSJeremy Jones 
2872a12f85aSJeremy Jones 		if (svd->vp == 0) {
2882a12f85aSJeremy Jones 			return (B_TRUE);
2892a12f85aSJeremy Jones 		}
2902a12f85aSJeremy Jones 
2912a12f85aSJeremy Jones 		if (mdb_ctf_vread(&vn, "vnode_t", "mdb_vnode_t",
2922a12f85aSJeremy Jones 		    svd->vp, 0) == -1) {
2932a12f85aSJeremy Jones 			return (B_FALSE);
2942a12f85aSJeremy Jones 		}
2952a12f85aSJeremy Jones 
2962a12f85aSJeremy Jones 		if (vn.v_type != VREG) {
2972a12f85aSJeremy Jones 			return (B_TRUE);
2982a12f85aSJeremy Jones 		}
2992a12f85aSJeremy Jones 	}
3002a12f85aSJeremy Jones 
3012a12f85aSJeremy Jones 	return (B_FALSE);
3022a12f85aSJeremy Jones }
3032a12f85aSJeremy Jones 
3042a12f85aSJeremy Jones static uintptr_t
gcore_anon_get_ptr(uintptr_t ah_addr,ulong_t an_idx)3052a12f85aSJeremy Jones gcore_anon_get_ptr(uintptr_t ah_addr, ulong_t an_idx)
3062a12f85aSJeremy Jones {
3072a12f85aSJeremy Jones 	mdb_anon_hdr_t	ah;
3082a12f85aSJeremy Jones 	uintptr_t	anon_addr;
3092a12f85aSJeremy Jones 	uintptr_t	anon_ptr;
3102a12f85aSJeremy Jones 
3112a12f85aSJeremy Jones 	if (mdb_ctf_vread(&ah, "struct anon_hdr", "mdb_anon_hdr_t", ah_addr,
3122a12f85aSJeremy Jones 	    0) == -1) {
3132a12f85aSJeremy Jones 		return (0);
3142a12f85aSJeremy Jones 	}
3152a12f85aSJeremy Jones 
3162a12f85aSJeremy Jones 	/*
3172a12f85aSJeremy Jones 	 * Single level case.
3182a12f85aSJeremy Jones 	 */
3192a12f85aSJeremy Jones 	if ((ah.size <= ANON_CHUNK_SIZE) || (ah.flags & ANON_ALLOC_FORCE)) {
3202a12f85aSJeremy Jones 		anon_addr = ah.array_chunk + (sizeof (anon_ptr) * an_idx);
3212a12f85aSJeremy Jones 		if (mdb_vread(&anon_ptr, sizeof (anon_ptr), anon_addr) !=
3222a12f85aSJeremy Jones 		    sizeof (anon_ptr)) {
3232a12f85aSJeremy Jones 			mdb_warn("Failed to read anon_ptr from %p (1 level)\n",
3242a12f85aSJeremy Jones 			    anon_addr);
3252a12f85aSJeremy Jones 			return (0);
3262a12f85aSJeremy Jones 		}
3272a12f85aSJeremy Jones 
3282a12f85aSJeremy Jones 		return (anon_ptr & ANON_PTRMASK);
3292a12f85aSJeremy Jones 	}
3302a12f85aSJeremy Jones 
3312a12f85aSJeremy Jones 	/*
3322a12f85aSJeremy Jones 	 * 2 level case.
3332a12f85aSJeremy Jones 	 */
3342a12f85aSJeremy Jones 	anon_addr = ah.array_chunk + (sizeof (anon_ptr) *
3352a12f85aSJeremy Jones 	    (an_idx >> ANON_CHUNK_SHIFT));
3362a12f85aSJeremy Jones 
3372a12f85aSJeremy Jones 	if (mdb_vread(&anon_ptr, sizeof (anon_ptr), anon_addr) !=
3382a12f85aSJeremy Jones 	    sizeof (anon_ptr)) {
3392a12f85aSJeremy Jones 		mdb_warn("Failed to read anon_ptr from %p (2a level)\n",
3402a12f85aSJeremy Jones 		    anon_addr);
3412a12f85aSJeremy Jones 		return (0);
3422a12f85aSJeremy Jones 	}
3432a12f85aSJeremy Jones 
3442a12f85aSJeremy Jones 	if (anon_ptr == 0) {
3452a12f85aSJeremy Jones 		return (0);
3462a12f85aSJeremy Jones 	}
3472a12f85aSJeremy Jones 
3482a12f85aSJeremy Jones 	anon_addr = anon_ptr + (sizeof (anon_ptr) *
3492a12f85aSJeremy Jones 	    (an_idx & ANON_CHUNK_OFF));
3502a12f85aSJeremy Jones 	if (mdb_vread(&anon_ptr, sizeof (anon_ptr), anon_addr) !=
3512a12f85aSJeremy Jones 	    sizeof (anon_ptr)) {
3522a12f85aSJeremy Jones 		mdb_warn("Failed to read anon_ptr from %p (2b level)\n",
3532a12f85aSJeremy Jones 		    anon_addr);
3542a12f85aSJeremy Jones 		return (0);
3552a12f85aSJeremy Jones 	}
3562a12f85aSJeremy Jones 
3572a12f85aSJeremy Jones 	return (anon_ptr & ANON_PTRMASK);
3582a12f85aSJeremy Jones }
3592a12f85aSJeremy Jones 
3602a12f85aSJeremy Jones static void
gcore_anon_get(uintptr_t ahp,ulong_t an_index,uintptr_t * vp,u_offset_t * off)3612a12f85aSJeremy Jones gcore_anon_get(uintptr_t ahp, ulong_t an_index, uintptr_t *vp, u_offset_t *off)
3622a12f85aSJeremy Jones {
3632a12f85aSJeremy Jones 	mdb_anon_t	anon;
3642a12f85aSJeremy Jones 	uintptr_t	ap;
3652a12f85aSJeremy Jones 
3662a12f85aSJeremy Jones 	ap = gcore_anon_get_ptr(ahp, an_index);
3672a12f85aSJeremy Jones 	if (ap != 0) {
3682a12f85aSJeremy Jones 		if (mdb_ctf_vread(&anon, "struct anon", "mdb_anon_t", ap, 0) ==
3692a12f85aSJeremy Jones 		    -1) {
3702a12f85aSJeremy Jones 			return;
3712a12f85aSJeremy Jones 		}
3722a12f85aSJeremy Jones 
3732a12f85aSJeremy Jones 		*vp = anon.an_vp;
3742a12f85aSJeremy Jones 		*off = anon.an_off;
3752a12f85aSJeremy Jones 	} else {
3762a12f85aSJeremy Jones 		*vp = 0;
3772a12f85aSJeremy Jones 		*off = 0;
3782a12f85aSJeremy Jones 	}
3792a12f85aSJeremy Jones }
3802a12f85aSJeremy Jones 
3812a12f85aSJeremy Jones static u_offset_t
gsvn_incore(gcore_seg_t * gs,u_offset_t addr,u_offset_t eaddr)3822a12f85aSJeremy Jones gsvn_incore(gcore_seg_t *gs, u_offset_t addr, u_offset_t eaddr)
3832a12f85aSJeremy Jones {
3842a12f85aSJeremy Jones 	mdb_segvn_data_t	*svd = gs->gs_data;
3852a12f85aSJeremy Jones 	mdb_seg_t		*seg = gs->gs_seg;
3862a12f85aSJeremy Jones 	mdb_amp_t		amp;
3872a12f85aSJeremy Jones 	u_offset_t		offset;
3882a12f85aSJeremy Jones 	uintptr_t		vp;
3892a12f85aSJeremy Jones 	size_t			p, ep;
3902a12f85aSJeremy Jones 
3912a12f85aSJeremy Jones 	if (svd->amp != 0 && mdb_ctf_vread(&amp, "amp_t", "mdb_amp_t", svd->amp,
3922a12f85aSJeremy Jones 	    0) == -1) {
3932a12f85aSJeremy Jones 		return (eaddr);
3942a12f85aSJeremy Jones 	}
3952a12f85aSJeremy Jones 
3962a12f85aSJeremy Jones 	p = seg_page(seg, addr);
3972a12f85aSJeremy Jones 	ep = seg_page(seg, eaddr);
3982a12f85aSJeremy Jones 	for (; p < ep; p++, addr += PAGESIZE) {
3992a12f85aSJeremy Jones 		/* First check the anon map */
4002a12f85aSJeremy Jones 		if (svd->amp != 0) {
4012a12f85aSJeremy Jones 			gcore_anon_get(amp.ahp, svd->anon_index + p, &vp,
4022a12f85aSJeremy Jones 			    &offset);
4032a12f85aSJeremy Jones 			if (vp != 0 && mdb_page_lookup(vp, offset) != 0) {
4042a12f85aSJeremy Jones 				break;
4052a12f85aSJeremy Jones 			}
4062a12f85aSJeremy Jones 		}
4072a12f85aSJeremy Jones 
4082a12f85aSJeremy Jones 		/* Now check the segment's vnode */
4092a12f85aSJeremy Jones 		vp = svd->vp;
4102a12f85aSJeremy Jones 		offset = svd->offset + (addr - gs->gs_seg->s_base);
4112a12f85aSJeremy Jones 		if (mdb_page_lookup(vp, offset) != 0) {
4122a12f85aSJeremy Jones 			break;
4132a12f85aSJeremy Jones 		}
4142a12f85aSJeremy Jones 
4152a12f85aSJeremy Jones 		dprintf("amp: %p vp: %p addr: %p offset: %p not in core!\n",
4162a12f85aSJeremy Jones 		    svd->amp, svd->vp, addr, offset);
4172a12f85aSJeremy Jones 	}
4182a12f85aSJeremy Jones 
4192a12f85aSJeremy Jones 	return (addr);
4202a12f85aSJeremy Jones }
4212a12f85aSJeremy Jones 
4222a12f85aSJeremy Jones static uint_t
gsvn_getprot(gcore_seg_t * gs,u_offset_t addr)4232a12f85aSJeremy Jones gsvn_getprot(gcore_seg_t *gs, u_offset_t addr)
4242a12f85aSJeremy Jones {
4252a12f85aSJeremy Jones 	mdb_segvn_data_t	*svd = gs->gs_data;
4262a12f85aSJeremy Jones 	mdb_seg_t		*seg = gs->gs_seg;
4272a12f85aSJeremy Jones 
4282a12f85aSJeremy Jones 	if (svd->pageprot == 0) {
4292a12f85aSJeremy Jones 		return (svd->prot);
4302a12f85aSJeremy Jones 	}
4312a12f85aSJeremy Jones 
4322a12f85aSJeremy Jones 	dprintf("addr: %p pgno: %p\n", addr, seg_page(seg, addr));
4332a12f85aSJeremy Jones 	return (VPP_PROT(&svd->vpage[seg_page(seg, addr)]));
4342a12f85aSJeremy Jones }
4352a12f85aSJeremy Jones 
4362a12f85aSJeremy Jones /*
4372a12f85aSJeremy Jones  * Helper functions for constructing the process address space maps.
4382a12f85aSJeremy Jones  */
4392a12f85aSJeremy Jones /*ARGSUSED*/
4402a12f85aSJeremy Jones static int
as_segat_cb(uintptr_t seg_addr,const void * aw_buff,void * arg)4412a12f85aSJeremy Jones as_segat_cb(uintptr_t seg_addr, const void *aw_buff, void *arg)
4422a12f85aSJeremy Jones {
4432a12f85aSJeremy Jones 	as_segat_cbarg_t *as_segat_arg = arg;
4442a12f85aSJeremy Jones 	mdb_seg_t	seg;
4452a12f85aSJeremy Jones 
4462a12f85aSJeremy Jones 	if (mdb_ctf_vread(&seg, "struct seg", "mdb_seg_t", seg_addr, 0) == -1) {
4472a12f85aSJeremy Jones 		return (WALK_ERR);
4482a12f85aSJeremy Jones 	}
4492a12f85aSJeremy Jones 
4502a12f85aSJeremy Jones 	if (as_segat_arg->addr < seg.s_base) {
4512a12f85aSJeremy Jones 		return (WALK_NEXT);
4522a12f85aSJeremy Jones 	}
4532a12f85aSJeremy Jones 
4542a12f85aSJeremy Jones 	if (as_segat_arg->addr >= seg.s_base + seg.s_size) {
4552a12f85aSJeremy Jones 		return (WALK_NEXT);
4562a12f85aSJeremy Jones 	}
4572a12f85aSJeremy Jones 
4582a12f85aSJeremy Jones 	as_segat_arg->res = seg_addr;
4592a12f85aSJeremy Jones 	return (WALK_DONE);
4602a12f85aSJeremy Jones }
4612a12f85aSJeremy Jones 
4622a12f85aSJeremy Jones /*
4632a12f85aSJeremy Jones  * Find a segment containing addr.
4642a12f85aSJeremy Jones  */
4652a12f85aSJeremy Jones static uintptr_t
gcore_as_segat(uintptr_t as_addr,uintptr_t addr)4662a12f85aSJeremy Jones gcore_as_segat(uintptr_t as_addr, uintptr_t addr)
4672a12f85aSJeremy Jones {
4682a12f85aSJeremy Jones 	as_segat_cbarg_t as_segat_arg;
4692a12f85aSJeremy Jones 	uintptr_t	segtree_addr;
4702a12f85aSJeremy Jones 
4712a12f85aSJeremy Jones 	as_segat_arg.addr = addr;
4722a12f85aSJeremy Jones 	as_segat_arg.res = 0;
4732a12f85aSJeremy Jones 
4742a12f85aSJeremy Jones 	segtree_addr = as_addr + mdb_ctf_offsetof_by_name("struct as",
4752a12f85aSJeremy Jones 	    "a_segtree");
4762a12f85aSJeremy Jones 	(void) avl_walk_mdb(segtree_addr, as_segat_cb, &as_segat_arg);
4772a12f85aSJeremy Jones 
4782a12f85aSJeremy Jones 	return (as_segat_arg.res);
4792a12f85aSJeremy Jones }
4802a12f85aSJeremy Jones 
4812a12f85aSJeremy Jones static uintptr_t
gcore_break_seg(mdb_proc_t * p)4822a12f85aSJeremy Jones gcore_break_seg(mdb_proc_t *p)
4832a12f85aSJeremy Jones {
4842a12f85aSJeremy Jones 	uintptr_t addr = p->p_brkbase;
4852a12f85aSJeremy Jones 
4862a12f85aSJeremy Jones 	if (p->p_brkbase != 0)
4872a12f85aSJeremy Jones 		addr += p->p_brksize - 1;
4882a12f85aSJeremy Jones 
4892a12f85aSJeremy Jones 	return (gcore_as_segat(p->p_as, addr));
4902a12f85aSJeremy Jones }
4912a12f85aSJeremy Jones 
4922a12f85aSJeremy Jones static u_offset_t
gcore_vnode_size(uintptr_t vnode_addr)4932a12f85aSJeremy Jones gcore_vnode_size(uintptr_t vnode_addr)
4942a12f85aSJeremy Jones {
4952a12f85aSJeremy Jones 	mdb_vnode_t	vnode;
4962a12f85aSJeremy Jones 	mdb_vnodeops_t	vnodeops;
4972a12f85aSJeremy Jones 	char		vops_name[128];
4982a12f85aSJeremy Jones 
4992a12f85aSJeremy Jones 	if (mdb_ctf_vread(&vnode, "vnode_t", "mdb_vnode_t", vnode_addr, 0) ==
5002a12f85aSJeremy Jones 	    -1) {
5012a12f85aSJeremy Jones 		return (-1);
5022a12f85aSJeremy Jones 	}
5032a12f85aSJeremy Jones 
5042a12f85aSJeremy Jones 	if (mdb_ctf_vread(&vnodeops, "vnodeops_t", "mdb_vnodeops_t",
5052a12f85aSJeremy Jones 	    vnode.v_op, 0) == -1) {
5062a12f85aSJeremy Jones 		return (-1);
5072a12f85aSJeremy Jones 	}
5082a12f85aSJeremy Jones 
5092a12f85aSJeremy Jones 	if (mdb_readstr(vops_name, sizeof (vops_name), vnodeops.vnop_name) ==
5102a12f85aSJeremy Jones 	    -1) {
5112a12f85aSJeremy Jones 		mdb_warn("Failed to read vnop_name from %p\n",
5122a12f85aSJeremy Jones 		    vnodeops.vnop_name);
5132a12f85aSJeremy Jones 		return (-1);
5142a12f85aSJeremy Jones 	}
5152a12f85aSJeremy Jones 
5162a12f85aSJeremy Jones 	if (strcmp(vops_name, "zfs") == 0) {
5172a12f85aSJeremy Jones 		mdb_znode_t	znode;
5182a12f85aSJeremy Jones 
5192a12f85aSJeremy Jones 		if (mdb_ctf_vread(&znode, "znode_t", "mdb_znode_t",
5202a12f85aSJeremy Jones 		    vnode.v_data, 0) == -1) {
5212a12f85aSJeremy Jones 			return (-1);
5222a12f85aSJeremy Jones 		}
5232a12f85aSJeremy Jones 		return (znode.z_size);
5242a12f85aSJeremy Jones 	}
5252a12f85aSJeremy Jones 
5262a12f85aSJeremy Jones 	if (strcmp(vops_name, "tmpfs") == 0) {
5272a12f85aSJeremy Jones 		mdb_tmpnode_t	tnode;
5282a12f85aSJeremy Jones 
5292a12f85aSJeremy Jones 		if (mdb_ctf_vread(&tnode, "struct tmpnode", "mdb_tmpnode_t",
5302a12f85aSJeremy Jones 		    vnode.v_data, 0) == -1)  {
5312a12f85aSJeremy Jones 			return (-1);
5322a12f85aSJeremy Jones 		}
5332a12f85aSJeremy Jones 		return (tnode.tn_attr.va_size);
5342a12f85aSJeremy Jones 	}
5352a12f85aSJeremy Jones 
5362a12f85aSJeremy Jones 	/* Unknown file system type. */
5372a12f85aSJeremy Jones 	mdb_warn("Unknown fs type: %s\n", vops_name);
5382a12f85aSJeremy Jones 	return (-1);
5392a12f85aSJeremy Jones }
5402a12f85aSJeremy Jones 
5412a12f85aSJeremy Jones static uint64_t
gcore_pr_getsegsize(mdb_seg_t * seg)5422a12f85aSJeremy Jones gcore_pr_getsegsize(mdb_seg_t *seg)
5432a12f85aSJeremy Jones {
5442a12f85aSJeremy Jones 	uint64_t size = seg->s_size;
5452a12f85aSJeremy Jones 
5462a12f85aSJeremy Jones 	if (seg->s_ops == gcore_segvn_ops) {
5472a12f85aSJeremy Jones 		mdb_segvn_data_t svd;
5482a12f85aSJeremy Jones 
5492a12f85aSJeremy Jones 		if (mdb_ctf_vread(&svd, "segvn_data_t", "mdb_segvn_data_t",
5502a12f85aSJeremy Jones 		    seg->s_data, 0) == -1) {
5512a12f85aSJeremy Jones 			return (-1);
5522a12f85aSJeremy Jones 		}
5532a12f85aSJeremy Jones 
5542a12f85aSJeremy Jones 		if (svd.vp != 0) {
5552a12f85aSJeremy Jones 			u_offset_t fsize;
5562a12f85aSJeremy Jones 			u_offset_t offset;
5572a12f85aSJeremy Jones 
5582a12f85aSJeremy Jones 			fsize = gcore_vnode_size(svd.vp);
5592a12f85aSJeremy Jones 			if (fsize == -1) {
5602a12f85aSJeremy Jones 				return (-1);
5612a12f85aSJeremy Jones 			}
5622a12f85aSJeremy Jones 			offset = svd.offset;
5632a12f85aSJeremy Jones 
5642a12f85aSJeremy Jones 			if (fsize < offset) {
5652a12f85aSJeremy Jones 				fsize = 0;
5662a12f85aSJeremy Jones 			} else {
5672a12f85aSJeremy Jones 				fsize -= offset;
5682a12f85aSJeremy Jones 			}
5692a12f85aSJeremy Jones 
5702a12f85aSJeremy Jones 			fsize = roundup(fsize, PAGESIZE);
5712a12f85aSJeremy Jones 		}
5722a12f85aSJeremy Jones 
5732a12f85aSJeremy Jones 		return (size);
5742a12f85aSJeremy Jones 	}
5752a12f85aSJeremy Jones 
5762a12f85aSJeremy Jones 	return (size);
5772a12f85aSJeremy Jones }
5782a12f85aSJeremy Jones 
5792a12f85aSJeremy Jones /*ARGSUSED*/
5802a12f85aSJeremy Jones static int
gcore_getwatchprot_cb(uintptr_t node_addr,const void * aw_buff,void * arg)5812a12f85aSJeremy Jones gcore_getwatchprot_cb(uintptr_t node_addr, const void *aw_buff, void *arg)
5822a12f85aSJeremy Jones {
5832a12f85aSJeremy Jones 	getwatchprot_cbarg_t	*cbarg = arg;
5842a12f85aSJeremy Jones 
5852a12f85aSJeremy Jones 	if (mdb_ctf_vread(&cbarg->wp, "struct watched_page",
5862a12f85aSJeremy Jones 	    "mdb_watched_page_t", node_addr, 0) == -1) {
5872a12f85aSJeremy Jones 		return (WALK_ERR);
5882a12f85aSJeremy Jones 	}
5892a12f85aSJeremy Jones 
5902a12f85aSJeremy Jones 	if (cbarg->wp.wp_vaddr == cbarg->wp_vaddr) {
5912a12f85aSJeremy Jones 		cbarg->found = B_TRUE;
5922a12f85aSJeremy Jones 		return (WALK_DONE);
5932a12f85aSJeremy Jones 	}
5942a12f85aSJeremy Jones 
5952a12f85aSJeremy Jones 	return (WALK_NEXT);
5962a12f85aSJeremy Jones }
5972a12f85aSJeremy Jones 
5982a12f85aSJeremy Jones static void
gcore_getwatchprot(uintptr_t as_addr,u_offset_t addr,uint_t * prot)5992a12f85aSJeremy Jones gcore_getwatchprot(uintptr_t as_addr, u_offset_t addr, uint_t *prot)
6002a12f85aSJeremy Jones {
6012a12f85aSJeremy Jones 	getwatchprot_cbarg_t	cbarg;
6022a12f85aSJeremy Jones 	uintptr_t		wp_addr;
6032a12f85aSJeremy Jones 
6042a12f85aSJeremy Jones 	cbarg.wp_vaddr = (uintptr_t)addr & (uintptr_t)PAGEMASK;
6052a12f85aSJeremy Jones 	cbarg.found = B_FALSE;
6062a12f85aSJeremy Jones 
6072a12f85aSJeremy Jones 	wp_addr = as_addr + mdb_ctf_offsetof_by_name("struct as", "a_wpage");
6082a12f85aSJeremy Jones 	(void) avl_walk_mdb(wp_addr, gcore_getwatchprot_cb, &cbarg);
6092a12f85aSJeremy Jones 
6102a12f85aSJeremy Jones 	if (cbarg.found) {
6112a12f85aSJeremy Jones 		*prot = cbarg.wp.wp_oprot;
6122a12f85aSJeremy Jones 	}
6132a12f85aSJeremy Jones }
6142a12f85aSJeremy Jones 
6152a12f85aSJeremy Jones static u_offset_t
gcore_pr_nextprot(gcore_seg_t * gs,u_offset_t * saddrp,u_offset_t eaddr,uint_t * protp)6162a12f85aSJeremy Jones gcore_pr_nextprot(gcore_seg_t *gs, u_offset_t *saddrp, u_offset_t eaddr,
6172a12f85aSJeremy Jones     uint_t *protp)
6182a12f85aSJeremy Jones {
6192a12f85aSJeremy Jones 	uint_t		prot, nprot;
6202a12f85aSJeremy Jones 	u_offset_t	addr = *saddrp;
6212a12f85aSJeremy Jones 	uintptr_t	as_addr = gs->gs_seg->s_as;
6222a12f85aSJeremy Jones 	int		noreserve = 0;
6232a12f85aSJeremy Jones 
6242a12f85aSJeremy Jones 	noreserve = GSOP_NORESERVE(gs);
6252a12f85aSJeremy Jones 	dprintf("addr: %p noreserve: %d\n", addr, noreserve);
6262a12f85aSJeremy Jones 
6272a12f85aSJeremy Jones 	if (noreserve) {
6282a12f85aSJeremy Jones 		addr = GSOP_INCORE(gs, addr, eaddr);
6292a12f85aSJeremy Jones 		if (addr == eaddr) {
6302a12f85aSJeremy Jones 			prot = 0;
6312a12f85aSJeremy Jones 			*saddrp = addr;
6322a12f85aSJeremy Jones 			goto out;
6332a12f85aSJeremy Jones 		}
6342a12f85aSJeremy Jones 	}
6352a12f85aSJeremy Jones 
6362a12f85aSJeremy Jones 	prot = GSOP_GETPROT(gs, addr);
6372a12f85aSJeremy Jones 	gcore_getwatchprot(as_addr, addr, &prot);
6382a12f85aSJeremy Jones 	*saddrp = addr;
6392a12f85aSJeremy Jones 
6402a12f85aSJeremy Jones 	for (addr += PAGESIZE; addr < eaddr; addr += PAGESIZE) {
6412a12f85aSJeremy Jones 		/* Discontinuity */
6422a12f85aSJeremy Jones 		if (noreserve && GSOP_INCORE(gs, addr, eaddr) != addr) {
6432a12f85aSJeremy Jones 			goto out;
6442a12f85aSJeremy Jones 		}
6452a12f85aSJeremy Jones 
6462a12f85aSJeremy Jones 		nprot = GSOP_GETPROT(gs, addr);
6472a12f85aSJeremy Jones 		gcore_getwatchprot(as_addr, addr, &nprot);
6482a12f85aSJeremy Jones 
6492a12f85aSJeremy Jones 		if (nprot != prot) {
6502a12f85aSJeremy Jones 			break;
6512a12f85aSJeremy Jones 		}
6522a12f85aSJeremy Jones 	}
6532a12f85aSJeremy Jones 
6542a12f85aSJeremy Jones out:
6552a12f85aSJeremy Jones 	*protp = prot;
6562a12f85aSJeremy Jones 	return (addr);
6572a12f85aSJeremy Jones }
6582a12f85aSJeremy Jones 
6592a12f85aSJeremy Jones /*
6602a12f85aSJeremy Jones  * Get the page protection for the given start address.
6612a12f85aSJeremy Jones  *   - saddrp: in - start address
6622a12f85aSJeremy Jones  *	       out - contains address of first in core page
6632a12f85aSJeremy Jones  *   - naddrp: out - address of next in core page that has different protection
6642a12f85aSJeremy Jones  *   - eaddr: in - end address
6652a12f85aSJeremy Jones  */
6662a12f85aSJeremy Jones static uint_t
gcore_pr_getprot(gcore_seg_t * gs,u_offset_t * saddrp,u_offset_t * naddrp,u_offset_t eaddr)6672a12f85aSJeremy Jones gcore_pr_getprot(gcore_seg_t *gs, u_offset_t *saddrp, u_offset_t *naddrp,
6682a12f85aSJeremy Jones     u_offset_t eaddr)
6692a12f85aSJeremy Jones {
6702a12f85aSJeremy Jones 	u_offset_t	naddr;
6712a12f85aSJeremy Jones 	uint_t		prot;
6722a12f85aSJeremy Jones 
6732a12f85aSJeremy Jones 	dprintf("seg: %p saddr: %p eaddr: %p\n",
6742a12f85aSJeremy Jones 	    gs->gs_seg, *saddrp, eaddr);
6752a12f85aSJeremy Jones 
6762a12f85aSJeremy Jones 	naddr = gcore_pr_nextprot(gs, saddrp, eaddr, &prot);
6772a12f85aSJeremy Jones 
6782a12f85aSJeremy Jones 	dprintf("seg: %p saddr: %p naddr: %p eaddr: %p\n",
6792a12f85aSJeremy Jones 	    gs->gs_seg, *saddrp, naddr, eaddr);
6802a12f85aSJeremy Jones 
6812a12f85aSJeremy Jones 	*naddrp = naddr;
6822a12f85aSJeremy Jones 	return (prot);
6832a12f85aSJeremy Jones }
6842a12f85aSJeremy Jones 
6852a12f85aSJeremy Jones static gcore_seg_t *
gcore_seg_create(mdb_seg_t * seg)6862a12f85aSJeremy Jones gcore_seg_create(mdb_seg_t *seg)
6872a12f85aSJeremy Jones {
6882a12f85aSJeremy Jones 	gcore_seg_t	*gs;
6892a12f85aSJeremy Jones 
6902a12f85aSJeremy Jones 	gs = mdb_alloc(sizeof (*gs), UM_SLEEP);
6912a12f85aSJeremy Jones 	gs->gs_seg = seg;
6922a12f85aSJeremy Jones 	if (seg->s_ops == gcore_segvn_ops) {
6932a12f85aSJeremy Jones 		gs->gs_ops = &gsvn_ops;
6942a12f85aSJeremy Jones 	} else {
6952a12f85aSJeremy Jones 		mdb_warn("Unhandled segment type, ops: %p\n", seg->s_ops);
6962a12f85aSJeremy Jones 		goto error;
6972a12f85aSJeremy Jones 	}
6982a12f85aSJeremy Jones 
6992a12f85aSJeremy Jones 	if (GSOP_INIT(gs) != 0) {
7002a12f85aSJeremy Jones 		goto error;
7012a12f85aSJeremy Jones 	}
7022a12f85aSJeremy Jones 
7032a12f85aSJeremy Jones 	return (gs);
7042a12f85aSJeremy Jones 
7052a12f85aSJeremy Jones error:
7062a12f85aSJeremy Jones 	mdb_free(gs, sizeof (*gs));
7072a12f85aSJeremy Jones 	return (NULL);
7082a12f85aSJeremy Jones }
7092a12f85aSJeremy Jones 
7102a12f85aSJeremy Jones static void
gcore_seg_destroy(gcore_seg_t * gs)7112a12f85aSJeremy Jones gcore_seg_destroy(gcore_seg_t *gs)
7122a12f85aSJeremy Jones {
7132a12f85aSJeremy Jones 	GSOP_FINI(gs);
7142a12f85aSJeremy Jones 	mdb_free(gs, sizeof (*gs));
7152a12f85aSJeremy Jones }
7162a12f85aSJeremy Jones 
7172a12f85aSJeremy Jones /*ARGSUSED*/
7182a12f85aSJeremy Jones static int
read_maps_cb(uintptr_t seg_addr,const void * aw_buff,void * arg)7192a12f85aSJeremy Jones read_maps_cb(uintptr_t seg_addr, const void *aw_buff, void *arg)
7202a12f85aSJeremy Jones {
7212a12f85aSJeremy Jones 	read_maps_cbarg_t	*cbarg = arg;
7222a12f85aSJeremy Jones 	mdb_segvn_data_t	svd;
7232a12f85aSJeremy Jones 	mdb_seg_t		s;
7242a12f85aSJeremy Jones 	mdb_seg_t		*seg;
7252a12f85aSJeremy Jones 	uint_t			prot;
7262a12f85aSJeremy Jones 	gcore_seg_t		*gs;
7272a12f85aSJeremy Jones 	uintptr_t		eaddr;
7282a12f85aSJeremy Jones 	u_offset_t		saddr, baddr;
7292a12f85aSJeremy Jones 	prmap_node_t		*mnode;
7302a12f85aSJeremy Jones 	prmap_t			*mp;
7312a12f85aSJeremy Jones 
7322a12f85aSJeremy Jones 	if (mdb_ctf_vread(&s, "struct seg", "mdb_seg_t", seg_addr, 0) == -1) {
7332a12f85aSJeremy Jones 		return (WALK_ERR);
7342a12f85aSJeremy Jones 	}
7352a12f85aSJeremy Jones 	seg = &s;
7362a12f85aSJeremy Jones 	eaddr = seg->s_base + gcore_pr_getsegsize(seg);
7372a12f85aSJeremy Jones 
7382a12f85aSJeremy Jones 	if ((gs = gcore_seg_create(seg)) == NULL) {
7392a12f85aSJeremy Jones 		mdb_warn("gcore_seg_create failed!\n");
7402a12f85aSJeremy Jones 		return (WALK_ERR);
7412a12f85aSJeremy Jones 	}
7422a12f85aSJeremy Jones 
7432a12f85aSJeremy Jones 	/*
7442a12f85aSJeremy Jones 	 * Iterate from the base of the segment to its end, allocating a new
7452a12f85aSJeremy Jones 	 * prmap_node at each address boundary (baddr) between ranges that
7462a12f85aSJeremy Jones 	 * have different virtual memory protections.
7472a12f85aSJeremy Jones 	 */
7482a12f85aSJeremy Jones 	for (saddr = seg->s_base; saddr < eaddr; saddr = baddr) {
7492a12f85aSJeremy Jones 		prot = gcore_pr_getprot(gs, &saddr, &baddr, eaddr);
7502a12f85aSJeremy Jones 		if (saddr == eaddr) {
7512a12f85aSJeremy Jones 			break;
7522a12f85aSJeremy Jones 		}
7532a12f85aSJeremy Jones 
7542a12f85aSJeremy Jones 		mnode = mdb_alloc(sizeof (*mnode), UM_SLEEP);
7552a12f85aSJeremy Jones 		mnode->next = NULL;
7562a12f85aSJeremy Jones 		mp = &mnode->m;
7572a12f85aSJeremy Jones 
7582a12f85aSJeremy Jones 		if (cbarg->map_head == NULL) {
7592a12f85aSJeremy Jones 			cbarg->map_head = cbarg->map_tail = mnode;
7602a12f85aSJeremy Jones 		} else {
7612a12f85aSJeremy Jones 			cbarg->map_tail->next = mnode;
7622a12f85aSJeremy Jones 			cbarg->map_tail = mnode;
7632a12f85aSJeremy Jones 		}
7642a12f85aSJeremy Jones 		cbarg->map_len++;
7652a12f85aSJeremy Jones 
7662a12f85aSJeremy Jones 		mp->pr_vaddr = (uintptr_t)saddr;
7672a12f85aSJeremy Jones 		mp->pr_size = baddr - saddr;
7682a12f85aSJeremy Jones 		mp->pr_offset = GSOP_GETOFFSET(gs, saddr);
7692a12f85aSJeremy Jones 		mp->pr_mflags = 0;
7702a12f85aSJeremy Jones 		if (prot & PROT_READ)
7712a12f85aSJeremy Jones 			mp->pr_mflags |= MA_READ;
7722a12f85aSJeremy Jones 		if (prot & PROT_WRITE)
7732a12f85aSJeremy Jones 			mp->pr_mflags |= MA_WRITE;
7742a12f85aSJeremy Jones 		if (prot & PROT_EXEC)
7752a12f85aSJeremy Jones 			mp->pr_mflags |= MA_EXEC;
7762a12f85aSJeremy Jones 		if (GSOP_GETTYPE(gs, saddr) & MAP_SHARED)
7772a12f85aSJeremy Jones 			mp->pr_mflags |= MA_SHARED;
7782a12f85aSJeremy Jones 		if (GSOP_GETTYPE(gs, saddr) & MAP_NORESERVE)
7792a12f85aSJeremy Jones 			mp->pr_mflags |= MA_NORESERVE;
7802a12f85aSJeremy Jones 		if (seg->s_ops == gcore_segvn_ops) {
7812a12f85aSJeremy Jones 			if (mdb_ctf_vread(&svd, "segvn_data_t",
7822a12f85aSJeremy Jones 			    "mdb_segvn_data_t", seg->s_data, 0) == 0 &&
783892ad162SToomas Soome 			    svd.vp == 0) {
7842a12f85aSJeremy Jones 				mp->pr_mflags |= MA_ANON;
7852a12f85aSJeremy Jones 			}
7862a12f85aSJeremy Jones 		}
7872a12f85aSJeremy Jones 		if (seg_addr == cbarg->brkseg)
7882a12f85aSJeremy Jones 			mp->pr_mflags |= MA_BREAK;
7892a12f85aSJeremy Jones 		else if (seg_addr == cbarg->stkseg)
7902a12f85aSJeremy Jones 			mp->pr_mflags |= MA_STACK;
7912a12f85aSJeremy Jones 
7922a12f85aSJeremy Jones 		mp->pr_pagesize = PAGESIZE;
7932a12f85aSJeremy Jones 
7942a12f85aSJeremy Jones 		/*
7952a12f85aSJeremy Jones 		 * Manufacture a filename for the "object" dir.
7962a12f85aSJeremy Jones 		 */
7972a12f85aSJeremy Jones 		GSOP_NAME(gs, mp->pr_mapname, sizeof (mp->pr_mapname));
7982a12f85aSJeremy Jones 	}
7992a12f85aSJeremy Jones 
8002a12f85aSJeremy Jones 	gcore_seg_destroy(gs);
8012a12f85aSJeremy Jones 
8022a12f85aSJeremy Jones 	return (0);
8032a12f85aSJeremy Jones }
8042a12f85aSJeremy Jones 
8052a12f85aSJeremy Jones /*
8062a12f85aSJeremy Jones  * Helper functions for retrieving process and lwp state.
8072a12f85aSJeremy Jones  */
8082a12f85aSJeremy Jones static int
pcommon_init(mdb_proc_t * p,pcommon_t * pc)8092a12f85aSJeremy Jones pcommon_init(mdb_proc_t *p, pcommon_t *pc)
8102a12f85aSJeremy Jones {
8112a12f85aSJeremy Jones 	mdb_pid_t	pid;
8122a12f85aSJeremy Jones 	mdb_sess_t	sess;
8132a12f85aSJeremy Jones 	mdb_task_t	task;
8142a12f85aSJeremy Jones 	mdb_kproject_t	proj;
8152a12f85aSJeremy Jones 	mdb_zone_t	zone;
8162a12f85aSJeremy Jones 
8172a12f85aSJeremy Jones 	pc->pc_nlwp = p->p_lwpcnt;
8182a12f85aSJeremy Jones 	pc->pc_nzomb = p->p_zombcnt;
8192a12f85aSJeremy Jones 
8202a12f85aSJeremy Jones 	if (mdb_ctf_vread(&pid, "struct pid", "mdb_pid_t", p->p_pidp, 0) ==
8212a12f85aSJeremy Jones 	    -1) {
8222a12f85aSJeremy Jones 		return (-1);
8232a12f85aSJeremy Jones 	}
8242a12f85aSJeremy Jones 	pc->pc_pid = pid.pid_id;
8252a12f85aSJeremy Jones 	pc->pc_ppid = p->p_ppid;
8262a12f85aSJeremy Jones 
8272a12f85aSJeremy Jones 	if (mdb_ctf_vread(&pid, "struct pid", "mdb_pid_t", p->p_pgidp, 0) ==
8282a12f85aSJeremy Jones 	    -1) {
8292a12f85aSJeremy Jones 		return (-1);
8302a12f85aSJeremy Jones 	}
8312a12f85aSJeremy Jones 	pc->pc_pgid = pid.pid_id;
8322a12f85aSJeremy Jones 
8332a12f85aSJeremy Jones 	if (mdb_ctf_vread(&sess, "sess_t", "mdb_sess_t", p->p_sessp, 0) ==
8342a12f85aSJeremy Jones 	    -1) {
8352a12f85aSJeremy Jones 		return (-1);
8362a12f85aSJeremy Jones 	}
8372a12f85aSJeremy Jones 	if (mdb_ctf_vread(&pid, "struct pid", "mdb_pid_t", sess.s_sidp, 0) ==
8382a12f85aSJeremy Jones 	    -1) {
8392a12f85aSJeremy Jones 		return (-1);
8402a12f85aSJeremy Jones 	}
8412a12f85aSJeremy Jones 	pc->pc_sid = pid.pid_id;
8422a12f85aSJeremy Jones 
8432a12f85aSJeremy Jones 	if (mdb_ctf_vread(&task, "task_t", "mdb_task_t", p->p_task, 0) == -1) {
8442a12f85aSJeremy Jones 		return (-1);
8452a12f85aSJeremy Jones 	}
8462a12f85aSJeremy Jones 	pc->pc_taskid = task.tk_tkid;
8472a12f85aSJeremy Jones 
8482a12f85aSJeremy Jones 	if (mdb_ctf_vread(&proj, "kproject_t", "mdb_kproject_t", task.tk_proj,
8492a12f85aSJeremy Jones 	    0) == -1) {
8502a12f85aSJeremy Jones 		return (-1);
8512a12f85aSJeremy Jones 	}
8522a12f85aSJeremy Jones 	pc->pc_projid = proj.kpj_id;
8532a12f85aSJeremy Jones 
8542a12f85aSJeremy Jones 	if (mdb_ctf_vread(&zone, "zone_t", "mdb_zone_t", p->p_zone, 0) == -1) {
8552a12f85aSJeremy Jones 		return (-1);
8562a12f85aSJeremy Jones 	}
8572a12f85aSJeremy Jones 	pc->pc_zoneid = zone.zone_id;
8582a12f85aSJeremy Jones 
8592a12f85aSJeremy Jones 	switch (p->p_model) {
8602a12f85aSJeremy Jones 	case DATAMODEL_ILP32:
8612a12f85aSJeremy Jones 		pc->pc_dmodel = PR_MODEL_ILP32;
8622a12f85aSJeremy Jones 		break;
8632a12f85aSJeremy Jones 	case DATAMODEL_LP64:
8642a12f85aSJeremy Jones 		pc->pc_dmodel = PR_MODEL_LP64;
8652a12f85aSJeremy Jones 		break;
8662a12f85aSJeremy Jones 	}
8672a12f85aSJeremy Jones 
8682a12f85aSJeremy Jones 	return (0);
8692a12f85aSJeremy Jones }
8702a12f85aSJeremy Jones 
8712a12f85aSJeremy Jones static uintptr_t
gcore_prchoose(mdb_proc_t * p)8722a12f85aSJeremy Jones gcore_prchoose(mdb_proc_t *p)
8732a12f85aSJeremy Jones {
8742a12f85aSJeremy Jones 	mdb_kthread_t	kthr;
8752a12f85aSJeremy Jones 	mdb_kthread_t	*t = &kthr;
8762a12f85aSJeremy Jones 	ushort_t	t_istop_whystop = 0;
8772a12f85aSJeremy Jones 	ushort_t	t_istop_whatstop = 0;
878892ad162SToomas Soome 	uintptr_t	t_addr = 0;
879892ad162SToomas Soome 	uintptr_t	t_onproc = 0;	/* running on processor */
880892ad162SToomas Soome 	uintptr_t	t_run = 0;	/* runnable, on disp queue */
881892ad162SToomas Soome 	uintptr_t	t_sleep = 0;	/* sleeping */
882892ad162SToomas Soome 	uintptr_t	t_susp = 0;	/* suspended stop */
883892ad162SToomas Soome 	uintptr_t	t_jstop = 0;	/* jobcontrol stop, w/o directed stop */
884892ad162SToomas Soome 	uintptr_t	t_jdstop = 0;	/* jobcontrol stop with directed stop */
885892ad162SToomas Soome 	uintptr_t	t_req = 0;	/* requested stop */
886892ad162SToomas Soome 	uintptr_t	t_istop = 0;	/* event-of-interest stop */
887892ad162SToomas Soome 	uintptr_t	t_dtrace = 0;	/* DTrace stop */
8882a12f85aSJeremy Jones 
8892a12f85aSJeremy Jones 	/*
8902a12f85aSJeremy Jones 	 * If the agent lwp exists, it takes precedence over all others.
8912a12f85aSJeremy Jones 	 */
892892ad162SToomas Soome 	if ((t_addr = p->p_agenttp) != 0) {
8932a12f85aSJeremy Jones 		return (t_addr);
8942a12f85aSJeremy Jones 	}
8952a12f85aSJeremy Jones 
896892ad162SToomas Soome 	if ((t_addr = p->p_tlist) == 0) /* start at the head of the list */
8972a12f85aSJeremy Jones 		return (t_addr);
8982a12f85aSJeremy Jones 	do {		/* for each lwp in the process */
8992a12f85aSJeremy Jones 		if (mdb_ctf_vread(&kthr, "kthread_t", "mdb_kthread_t",
9002a12f85aSJeremy Jones 		    t_addr, 0) == -1) {
9012a12f85aSJeremy Jones 			return (0);
9022a12f85aSJeremy Jones 		}
9032a12f85aSJeremy Jones 
9042a12f85aSJeremy Jones 		if (VSTOPPED(t)) {	/* virtually stopped */
905892ad162SToomas Soome 			if (t_req == 0)
9062a12f85aSJeremy Jones 				t_req = t_addr;
9072a12f85aSJeremy Jones 			continue;
9082a12f85aSJeremy Jones 		}
9092a12f85aSJeremy Jones 
9102a12f85aSJeremy Jones 		switch (t->t_state) {
9112a12f85aSJeremy Jones 		default:
9122a12f85aSJeremy Jones 			return (0);
9132a12f85aSJeremy Jones 		case TS_SLEEP:
914892ad162SToomas Soome 			if (t_sleep == 0)
9152a12f85aSJeremy Jones 				t_sleep = t_addr;
9162a12f85aSJeremy Jones 			break;
9172a12f85aSJeremy Jones 		case TS_RUN:
9182a12f85aSJeremy Jones 		case TS_WAIT:
919892ad162SToomas Soome 			if (t_run == 0)
9202a12f85aSJeremy Jones 				t_run = t_addr;
9212a12f85aSJeremy Jones 			break;
9222a12f85aSJeremy Jones 		case TS_ONPROC:
923892ad162SToomas Soome 			if (t_onproc == 0)
9242a12f85aSJeremy Jones 				t_onproc = t_addr;
9252a12f85aSJeremy Jones 			break;
9262a12f85aSJeremy Jones 			/*
9272a12f85aSJeremy Jones 			 * Threads in the zombie state have the lowest
9282a12f85aSJeremy Jones 			 * priority when selecting a representative lwp.
9292a12f85aSJeremy Jones 			 */
9302a12f85aSJeremy Jones 		case TS_ZOMB:
9312a12f85aSJeremy Jones 			break;
9322a12f85aSJeremy Jones 		case TS_STOPPED:
9332a12f85aSJeremy Jones 			switch (t->t_whystop) {
9342a12f85aSJeremy Jones 			case PR_SUSPENDED:
935892ad162SToomas Soome 				if (t_susp == 0)
9362a12f85aSJeremy Jones 					t_susp = t_addr;
9372a12f85aSJeremy Jones 				break;
9382a12f85aSJeremy Jones 			case PR_JOBCONTROL:
9392a12f85aSJeremy Jones 				if (t->t_proc_flag & TP_PRSTOP) {
940892ad162SToomas Soome 					if (t_jdstop == 0)
9412a12f85aSJeremy Jones 						t_jdstop = t_addr;
9422a12f85aSJeremy Jones 				} else {
943892ad162SToomas Soome 					if (t_jstop == 0)
9442a12f85aSJeremy Jones 						t_jstop = t_addr;
9452a12f85aSJeremy Jones 				}
9462a12f85aSJeremy Jones 				break;
9472a12f85aSJeremy Jones 			case PR_REQUESTED:
948892ad162SToomas Soome 				if (t->t_dtrace_stop && t_dtrace == 0)
9492a12f85aSJeremy Jones 					t_dtrace = t_addr;
950892ad162SToomas Soome 				else if (t_req == 0)
9512a12f85aSJeremy Jones 					t_req = t_addr;
9522a12f85aSJeremy Jones 				break;
9532a12f85aSJeremy Jones 			case PR_SYSENTRY:
9542a12f85aSJeremy Jones 			case PR_SYSEXIT:
9552a12f85aSJeremy Jones 			case PR_SIGNALLED:
9562a12f85aSJeremy Jones 			case PR_FAULTED:
9572a12f85aSJeremy Jones 				/*
9582a12f85aSJeremy Jones 				 * Make an lwp calling exit() be the
9592a12f85aSJeremy Jones 				 * last lwp seen in the process.
9602a12f85aSJeremy Jones 				 */
961892ad162SToomas Soome 				if (t_istop == 0 ||
9622a12f85aSJeremy Jones 				    (t_istop_whystop == PR_SYSENTRY &&
9632a12f85aSJeremy Jones 				    t_istop_whatstop == SYS_exit)) {
9642a12f85aSJeremy Jones 					t_istop = t_addr;
9652a12f85aSJeremy Jones 					t_istop_whystop = t->t_whystop;
9662a12f85aSJeremy Jones 					t_istop_whatstop = t->t_whatstop;
9672a12f85aSJeremy Jones 				}
9682a12f85aSJeremy Jones 				break;
9692a12f85aSJeremy Jones 			case PR_CHECKPOINT:	/* can't happen? */
9702a12f85aSJeremy Jones 				break;
9712a12f85aSJeremy Jones 			default:
9722a12f85aSJeremy Jones 				return (0);
9732a12f85aSJeremy Jones 			}
9742a12f85aSJeremy Jones 			break;
9752a12f85aSJeremy Jones 		}
9762a12f85aSJeremy Jones 	} while ((t_addr = t->t_forw) != p->p_tlist);
9772a12f85aSJeremy Jones 
9782a12f85aSJeremy Jones 	if (t_onproc)
9792a12f85aSJeremy Jones 		t_addr = t_onproc;
9802a12f85aSJeremy Jones 	else if (t_run)
9812a12f85aSJeremy Jones 		t_addr = t_run;
9822a12f85aSJeremy Jones 	else if (t_sleep)
9832a12f85aSJeremy Jones 		t_addr = t_sleep;
9842a12f85aSJeremy Jones 	else if (t_jstop)
9852a12f85aSJeremy Jones 		t_addr = t_jstop;
9862a12f85aSJeremy Jones 	else if (t_jdstop)
9872a12f85aSJeremy Jones 		t_addr = t_jdstop;
9882a12f85aSJeremy Jones 	else if (t_istop)
9892a12f85aSJeremy Jones 		t_addr = t_istop;
9902a12f85aSJeremy Jones 	else if (t_dtrace)
9912a12f85aSJeremy Jones 		t_addr = t_dtrace;
9922a12f85aSJeremy Jones 	else if (t_req)
9932a12f85aSJeremy Jones 		t_addr = t_req;
9942a12f85aSJeremy Jones 	else if (t_susp)
9952a12f85aSJeremy Jones 		t_addr = t_susp;
9962a12f85aSJeremy Jones 	else			/* TS_ZOMB */
9972a12f85aSJeremy Jones 		t_addr = p->p_tlist;
9982a12f85aSJeremy Jones 
9992a12f85aSJeremy Jones 	return (t_addr);
10002a12f85aSJeremy Jones }
10012a12f85aSJeremy Jones 
10022a12f85aSJeremy Jones /*
10032a12f85aSJeremy Jones  * Fields not populated:
10042a12f85aSJeremy Jones  *   - pr_stype
10052a12f85aSJeremy Jones  *   - pr_oldpri
10062a12f85aSJeremy Jones  *   - pr_nice
10072a12f85aSJeremy Jones  *   - pr_time
10082a12f85aSJeremy Jones  *   - pr_pctcpu
10092a12f85aSJeremy Jones  *   - pr_cpu
10102a12f85aSJeremy Jones  */
10112a12f85aSJeremy Jones static int
gcore_prgetlwpsinfo(uintptr_t t_addr,mdb_kthread_t * t,lwpsinfo_t * psp)10122a12f85aSJeremy Jones gcore_prgetlwpsinfo(uintptr_t t_addr, mdb_kthread_t *t, lwpsinfo_t *psp)
10132a12f85aSJeremy Jones {
10142a12f85aSJeremy Jones 	char		c, state;
10152a12f85aSJeremy Jones 	mdb_cpu_t	cpu;
10162a12f85aSJeremy Jones 	mdb_lpl_t	lgrp;
10172a12f85aSJeremy Jones 	uintptr_t	str_addr;
10182a12f85aSJeremy Jones 
10192a12f85aSJeremy Jones 	bzero(psp, sizeof (*psp));
10202a12f85aSJeremy Jones 
10212a12f85aSJeremy Jones 	psp->pr_flag = 0;	/* lwpsinfo_t.pr_flag is deprecated */
10222a12f85aSJeremy Jones 	psp->pr_lwpid = t->t_tid;
10232a12f85aSJeremy Jones 	psp->pr_addr = t_addr;
10242a12f85aSJeremy Jones 	psp->pr_wchan = (uintptr_t)t->t_wchan;
10252a12f85aSJeremy Jones 
10262a12f85aSJeremy Jones 	/* map the thread state enum into a process state enum */
10272a12f85aSJeremy Jones 	state = VSTOPPED(t) ? TS_STOPPED : t->t_state;
10282a12f85aSJeremy Jones 	switch (state) {
10292a12f85aSJeremy Jones 	case TS_SLEEP:		state = SSLEEP;		c = 'S';	break;
10302a12f85aSJeremy Jones 	case TS_RUN:		state = SRUN;		c = 'R';	break;
10312a12f85aSJeremy Jones 	case TS_ONPROC:		state = SONPROC;	c = 'O';	break;
10322a12f85aSJeremy Jones 	case TS_ZOMB:		state = SZOMB;		c = 'Z';	break;
10332a12f85aSJeremy Jones 	case TS_STOPPED:	state = SSTOP;		c = 'T';	break;
10342a12f85aSJeremy Jones 	case TS_WAIT:		state = SWAIT;		c = 'W';	break;
10352a12f85aSJeremy Jones 	default:		state = 0;		c = '?';	break;
10362a12f85aSJeremy Jones 	}
10372a12f85aSJeremy Jones 	psp->pr_state = state;
10382a12f85aSJeremy Jones 	psp->pr_sname = c;
10392a12f85aSJeremy Jones 	psp->pr_syscall = t->t_sysnum;
10402a12f85aSJeremy Jones 	psp->pr_pri = t->t_pri;
10412a12f85aSJeremy Jones 	psp->pr_start.tv_sec = t->t_start;
10422a12f85aSJeremy Jones 	psp->pr_start.tv_nsec = 0L;
10432a12f85aSJeremy Jones 
10442a12f85aSJeremy Jones 	str_addr = (uintptr_t)gcore_sclass[t->t_cid].cl_name;
10452a12f85aSJeremy Jones 	if (mdb_readstr(psp->pr_clname, sizeof (psp->pr_clname) - 1, str_addr)
10462a12f85aSJeremy Jones 	    == -1) {
10472a12f85aSJeremy Jones 		mdb_warn("Failed to read string from %p\n", str_addr);
10482a12f85aSJeremy Jones 		return (-1);
10492a12f85aSJeremy Jones 	}
10502a12f85aSJeremy Jones 	bzero(psp->pr_name, sizeof (psp->pr_name));
10512a12f85aSJeremy Jones 
10522a12f85aSJeremy Jones 	if (mdb_ctf_vread(&cpu, "struct cpu", "mdb_cpu_t", t->t_cpu, 0) == -1) {
10532a12f85aSJeremy Jones 		return (-1);
10542a12f85aSJeremy Jones 	}
10552a12f85aSJeremy Jones 	psp->pr_onpro = cpu.cpu_id;
10562a12f85aSJeremy Jones 	psp->pr_bindpro = t->t_bind_cpu;
10572a12f85aSJeremy Jones 	psp->pr_bindpset = t->t_bind_pset;
10582a12f85aSJeremy Jones 
10592a12f85aSJeremy Jones 	if (mdb_ctf_vread(&lgrp, "lpl_t", "mdb_lpl_t", t->t_lpl, 0) == -1) {
10602a12f85aSJeremy Jones 		return (-1);
10612a12f85aSJeremy Jones 	}
10622a12f85aSJeremy Jones 	psp->pr_lgrp = lgrp.lpl_lgrpid;
10632a12f85aSJeremy Jones 
10642a12f85aSJeremy Jones 	return (0);
10652a12f85aSJeremy Jones }
10662a12f85aSJeremy Jones 
10672a12f85aSJeremy Jones /*ARGSUSED*/
10682a12f85aSJeremy Jones static int
gcore_lpsinfo_cb(mdb_proc_t * p,lwpent_t * lwent,void * data)10692a12f85aSJeremy Jones gcore_lpsinfo_cb(mdb_proc_t *p, lwpent_t *lwent, void *data)
10702a12f85aSJeremy Jones {
10712a12f85aSJeremy Jones 	lwpsinfo_t	*lpsinfo = data;
10722a12f85aSJeremy Jones 	uintptr_t	t_addr = (uintptr_t)lwent->le_thread;
10732a12f85aSJeremy Jones 	mdb_kthread_t	kthrd;
10742a12f85aSJeremy Jones 
10752a12f85aSJeremy Jones 	if (t_addr != 0) {
10762a12f85aSJeremy Jones 		if (mdb_ctf_vread(&kthrd, "kthread_t", "mdb_kthread_t", t_addr,
10772a12f85aSJeremy Jones 		    0) == -1) {
10782a12f85aSJeremy Jones 			return (-1);
10792a12f85aSJeremy Jones 		}
10802a12f85aSJeremy Jones 		return (gcore_prgetlwpsinfo(t_addr, &kthrd, lpsinfo));
10812a12f85aSJeremy Jones 	}
10822a12f85aSJeremy Jones 
10832a12f85aSJeremy Jones 	bzero(lpsinfo, sizeof (*lpsinfo));
10842a12f85aSJeremy Jones 	lpsinfo->pr_lwpid = lwent->le_lwpid;
10852a12f85aSJeremy Jones 	lpsinfo->pr_state = SZOMB;
10862a12f85aSJeremy Jones 	lpsinfo->pr_sname = 'Z';
10872a12f85aSJeremy Jones 	lpsinfo->pr_start.tv_sec = lwent->le_start;
10882a12f85aSJeremy Jones 	lpsinfo->pr_bindpro = PBIND_NONE;
10892a12f85aSJeremy Jones 	lpsinfo->pr_bindpset = PS_NONE;
10902a12f85aSJeremy Jones 	return (0);
10912a12f85aSJeremy Jones }
10922a12f85aSJeremy Jones 
10932a12f85aSJeremy Jones static void
gcore_schedctl_finish_sigblock(mdb_kthread_t * t)10942a12f85aSJeremy Jones gcore_schedctl_finish_sigblock(mdb_kthread_t *t)
10952a12f85aSJeremy Jones {
10962a12f85aSJeremy Jones 	mdb_sc_shared_t td;
10972a12f85aSJeremy Jones 	mdb_sc_shared_t *tdp;
10982a12f85aSJeremy Jones 
1099892ad162SToomas Soome 	if (t->t_schedctl == 0) {
11002a12f85aSJeremy Jones 		return;
11012a12f85aSJeremy Jones 	}
11022a12f85aSJeremy Jones 
11032a12f85aSJeremy Jones 	if (mdb_ctf_vread(&td, "sc_shared_t", "mdb_sc_shared_t", t->t_schedctl,
11042a12f85aSJeremy Jones 	    0) == -1) {
11052a12f85aSJeremy Jones 		return;
11062a12f85aSJeremy Jones 	}
11072a12f85aSJeremy Jones 	tdp = &td;
11082a12f85aSJeremy Jones 
11092a12f85aSJeremy Jones 	if (tdp->sc_sigblock) {
11102a12f85aSJeremy Jones 		t->t_hold.__sigbits[0] = FILLSET0 & ~CANTMASK0;
11112a12f85aSJeremy Jones 		t->t_hold.__sigbits[1] = FILLSET1 & ~CANTMASK1;
11122a12f85aSJeremy Jones 		t->t_hold.__sigbits[2] = FILLSET2 & ~CANTMASK2;
11132a12f85aSJeremy Jones 		tdp->sc_sigblock = 0;
11142a12f85aSJeremy Jones 	}
11152a12f85aSJeremy Jones }
11162a12f85aSJeremy Jones 
11172a12f85aSJeremy Jones static void
gcore_prgetaction(mdb_proc_t * p,user_t * up,uint_t sig,struct sigaction * sp)11182a12f85aSJeremy Jones gcore_prgetaction(mdb_proc_t *p, user_t *up, uint_t sig, struct sigaction *sp)
11192a12f85aSJeremy Jones {
11202a12f85aSJeremy Jones 	int nsig = NSIG;
11212a12f85aSJeremy Jones 
11222a12f85aSJeremy Jones 	bzero(sp, sizeof (*sp));
11232a12f85aSJeremy Jones 
11242a12f85aSJeremy Jones 	if (sig != 0 && (unsigned)sig < nsig) {
11252a12f85aSJeremy Jones 		sp->sa_handler = up->u_signal[sig-1];
11262a12f85aSJeremy Jones 		prassignset(&sp->sa_mask, &up->u_sigmask[sig-1]);
11272a12f85aSJeremy Jones 		if (sigismember(&up->u_sigonstack, sig))
11282a12f85aSJeremy Jones 			sp->sa_flags |= SA_ONSTACK;
11292a12f85aSJeremy Jones 		if (sigismember(&up->u_sigresethand, sig))
11302a12f85aSJeremy Jones 			sp->sa_flags |= SA_RESETHAND;
11312a12f85aSJeremy Jones 		if (sigismember(&up->u_sigrestart, sig))
11322a12f85aSJeremy Jones 			sp->sa_flags |= SA_RESTART;
11332a12f85aSJeremy Jones 		if (sigismember(&p->p_siginfo, sig))
11342a12f85aSJeremy Jones 			sp->sa_flags |= SA_SIGINFO;
11352a12f85aSJeremy Jones 		if (sigismember(&up->u_signodefer, sig))
11362a12f85aSJeremy Jones 			sp->sa_flags |= SA_NODEFER;
11372a12f85aSJeremy Jones 		if (sig == SIGCLD) {
11382a12f85aSJeremy Jones 			if (p->p_flag & SNOWAIT)
11392a12f85aSJeremy Jones 				sp->sa_flags |= SA_NOCLDWAIT;
11402a12f85aSJeremy Jones 			if ((p->p_flag & SJCTL) == 0)
11412a12f85aSJeremy Jones 				sp->sa_flags |= SA_NOCLDSTOP;
11422a12f85aSJeremy Jones 		}
11432a12f85aSJeremy Jones 	}
11442a12f85aSJeremy Jones }
11452a12f85aSJeremy Jones 
11462a12f85aSJeremy Jones static void
gcore_prgetprregs(mdb_klwp_t * lwp,prgregset_t prp)11472a12f85aSJeremy Jones gcore_prgetprregs(mdb_klwp_t *lwp, prgregset_t prp)
11482a12f85aSJeremy Jones {
11492a12f85aSJeremy Jones 	gcore_getgregs(lwp, prp);
11502a12f85aSJeremy Jones }
11512a12f85aSJeremy Jones 
11522a12f85aSJeremy Jones /*
11532a12f85aSJeremy Jones  * Field not populated:
11542a12f85aSJeremy Jones  *   - pr_tstamp
11552a12f85aSJeremy Jones  *   - pr_utime
11562a12f85aSJeremy Jones  *   - pr_stime
11572a12f85aSJeremy Jones  *   - pr_syscall
11582a12f85aSJeremy Jones  *   - pr_syarg
11592a12f85aSJeremy Jones  *   - pr_nsysarg
11602a12f85aSJeremy Jones  *   - pr_fpreg
11612a12f85aSJeremy Jones  */
11622a12f85aSJeremy Jones /*ARGSUSED*/
11632a12f85aSJeremy Jones static int
gcore_prgetlwpstatus(mdb_proc_t * p,uintptr_t t_addr,mdb_kthread_t * t,lwpstatus_t * sp,zone_t * zp)11642a12f85aSJeremy Jones gcore_prgetlwpstatus(mdb_proc_t *p, uintptr_t t_addr, mdb_kthread_t *t,
11652a12f85aSJeremy Jones     lwpstatus_t *sp, zone_t *zp)
11662a12f85aSJeremy Jones {
11672a12f85aSJeremy Jones 	uintptr_t	lwp_addr = ttolwp(t);
11682a12f85aSJeremy Jones 	mdb_klwp_t	lw;
11692a12f85aSJeremy Jones 	mdb_klwp_t	*lwp;
11702a12f85aSJeremy Jones 	ulong_t		instr;
11712a12f85aSJeremy Jones 	int		flags;
11722a12f85aSJeremy Jones 	uintptr_t	str_addr;
11732a12f85aSJeremy Jones 	struct pid	pid;
11742a12f85aSJeremy Jones 
11752a12f85aSJeremy Jones 	if (mdb_ctf_vread(&lw, "klwp_t", "mdb_klwp_t", lwp_addr, 0) == -1) {
11762a12f85aSJeremy Jones 		return (-1);
11772a12f85aSJeremy Jones 	}
11782a12f85aSJeremy Jones 	lwp = &lw;
11792a12f85aSJeremy Jones 
11802a12f85aSJeremy Jones 	bzero(sp, sizeof (*sp));
11812a12f85aSJeremy Jones 	flags = 0L;
11822a12f85aSJeremy Jones 	if (t->t_state == TS_STOPPED) {
11832a12f85aSJeremy Jones 		flags |= PR_STOPPED;
11842a12f85aSJeremy Jones 		if ((t->t_schedflag & TS_PSTART) == 0)
11852a12f85aSJeremy Jones 			flags |= PR_ISTOP;
11862a12f85aSJeremy Jones 	} else if (VSTOPPED(t)) {
11872a12f85aSJeremy Jones 		flags |= PR_STOPPED|PR_ISTOP;
11882a12f85aSJeremy Jones 	}
11892a12f85aSJeremy Jones 	if (!(flags & PR_ISTOP) && (t->t_proc_flag & TP_PRSTOP))
11902a12f85aSJeremy Jones 		flags |= PR_DSTOP;
11912a12f85aSJeremy Jones 	if (lwp->lwp_asleep)
11922a12f85aSJeremy Jones 		flags |= PR_ASLEEP;
11932a12f85aSJeremy Jones 	if (t_addr == p->p_agenttp)
11942a12f85aSJeremy Jones 		flags |= PR_AGENT;
11952a12f85aSJeremy Jones 	if (!(t->t_proc_flag & TP_TWAIT))
11962a12f85aSJeremy Jones 		flags |= PR_DETACH;
11972a12f85aSJeremy Jones 	if (t->t_proc_flag & TP_DAEMON)
11982a12f85aSJeremy Jones 		flags |= PR_DAEMON;
11992a12f85aSJeremy Jones 	if (p->p_proc_flag & P_PR_FORK)
12002a12f85aSJeremy Jones 		flags |= PR_FORK;
12012a12f85aSJeremy Jones 	if (p->p_proc_flag & P_PR_RUNLCL)
12022a12f85aSJeremy Jones 		flags |= PR_RLC;
12032a12f85aSJeremy Jones 	if (p->p_proc_flag & P_PR_KILLCL)
12042a12f85aSJeremy Jones 		flags |= PR_KLC;
12052a12f85aSJeremy Jones 	if (p->p_proc_flag & P_PR_ASYNC)
12062a12f85aSJeremy Jones 		flags |= PR_ASYNC;
12072a12f85aSJeremy Jones 	if (p->p_proc_flag & P_PR_BPTADJ)
12082a12f85aSJeremy Jones 		flags |= PR_BPTADJ;
12092a12f85aSJeremy Jones 	if (p->p_proc_flag & P_PR_PTRACE)
12102a12f85aSJeremy Jones 		flags |= PR_PTRACE;
12112a12f85aSJeremy Jones 	if (p->p_flag & SMSACCT)
12122a12f85aSJeremy Jones 		flags |= PR_MSACCT;
12132a12f85aSJeremy Jones 	if (p->p_flag & SMSFORK)
12142a12f85aSJeremy Jones 		flags |= PR_MSFORK;
12152a12f85aSJeremy Jones 	if (p->p_flag & SVFWAIT)
12162a12f85aSJeremy Jones 		flags |= PR_VFORKP;
12172a12f85aSJeremy Jones 
12182a12f85aSJeremy Jones 	if (mdb_vread(&pid, sizeof (struct pid), p->p_pgidp) != sizeof (pid)) {
12192a12f85aSJeremy Jones 		mdb_warn("Failed to read pid from %p\n", p->p_pgidp);
12202a12f85aSJeremy Jones 		return (-1);
12212a12f85aSJeremy Jones 	}
12222a12f85aSJeremy Jones 	if (pid.pid_pgorphaned)
12232a12f85aSJeremy Jones 		flags |= PR_ORPHAN;
12242a12f85aSJeremy Jones 	if (p->p_pidflag & CLDNOSIGCHLD)
12252a12f85aSJeremy Jones 		flags |= PR_NOSIGCHLD;
12262a12f85aSJeremy Jones 	if (p->p_pidflag & CLDWAITPID)
12272a12f85aSJeremy Jones 		flags |= PR_WAITPID;
12282a12f85aSJeremy Jones 	sp->pr_flags = flags;
12292a12f85aSJeremy Jones 	if (VSTOPPED(t)) {
12302a12f85aSJeremy Jones 		sp->pr_why   = PR_REQUESTED;
12312a12f85aSJeremy Jones 		sp->pr_what  = 0;
12322a12f85aSJeremy Jones 	} else {
12332a12f85aSJeremy Jones 		sp->pr_why   = t->t_whystop;
12342a12f85aSJeremy Jones 		sp->pr_what  = t->t_whatstop;
12352a12f85aSJeremy Jones 	}
12362a12f85aSJeremy Jones 	sp->pr_lwpid = t->t_tid;
12372a12f85aSJeremy Jones 	sp->pr_cursig  = lwp->lwp_cursig;
12382a12f85aSJeremy Jones 	prassignset(&sp->pr_lwppend, &t->t_sig);
12392a12f85aSJeremy Jones 	gcore_schedctl_finish_sigblock(t);
12402a12f85aSJeremy Jones 	prassignset(&sp->pr_lwphold, &t->t_hold);
12412a12f85aSJeremy Jones 	if (t->t_whystop == PR_FAULTED) {
12422a12f85aSJeremy Jones 		bcopy(&lwp->lwp_siginfo,
12432a12f85aSJeremy Jones 		    &sp->pr_info, sizeof (k_siginfo_t));
12442a12f85aSJeremy Jones 	} else if (lwp->lwp_curinfo) {
12452a12f85aSJeremy Jones 		mdb_sigqueue_t	sigq;
12462a12f85aSJeremy Jones 
12472a12f85aSJeremy Jones 		if (mdb_ctf_vread(&sigq, "sigqueue_t", "mdb_sigqueue_t",
12482a12f85aSJeremy Jones 		    lwp->lwp_curinfo, 0) == -1) {
12492a12f85aSJeremy Jones 			return (-1);
12502a12f85aSJeremy Jones 		}
12512a12f85aSJeremy Jones 		bcopy(&sigq.sq_info, &sp->pr_info, sizeof (k_siginfo_t));
12522a12f85aSJeremy Jones 	}
12532a12f85aSJeremy Jones 
12542a12f85aSJeremy Jones 	sp->pr_altstack = lwp->lwp_sigaltstack;
12552a12f85aSJeremy Jones 	gcore_prgetaction(p, PTOU(p), lwp->lwp_cursig, &sp->pr_action);
12562a12f85aSJeremy Jones 	sp->pr_oldcontext = lwp->lwp_oldcontext;
12572a12f85aSJeremy Jones 	sp->pr_ustack = lwp->lwp_ustack;
12582a12f85aSJeremy Jones 
12592a12f85aSJeremy Jones 	str_addr = (uintptr_t)gcore_sclass[t->t_cid].cl_name;
12602a12f85aSJeremy Jones 	if (mdb_readstr(sp->pr_clname, sizeof (sp->pr_clname) - 1, str_addr) ==
12612a12f85aSJeremy Jones 	    -1) {
12622a12f85aSJeremy Jones 		mdb_warn("Failed to read string from %p\n", str_addr);
12632a12f85aSJeremy Jones 		return (-1);
12642a12f85aSJeremy Jones 	}
12652a12f85aSJeremy Jones 
12662a12f85aSJeremy Jones 	/*
12672a12f85aSJeremy Jones 	 * Fetch the current instruction, if not a system process.
12682a12f85aSJeremy Jones 	 * We don't attempt this unless the lwp is stopped.
12692a12f85aSJeremy Jones 	 */
12702a12f85aSJeremy Jones 	if ((p->p_flag & SSYS) || p->p_as == gcore_kas)
12712a12f85aSJeremy Jones 		sp->pr_flags |= (PR_ISSYS|PR_PCINVAL);
12722a12f85aSJeremy Jones 	else if (!(flags & PR_STOPPED))
12732a12f85aSJeremy Jones 		sp->pr_flags |= PR_PCINVAL;
12742a12f85aSJeremy Jones 	else if (!gcore_prfetchinstr(lwp, &instr))
12752a12f85aSJeremy Jones 		sp->pr_flags |= PR_PCINVAL;
12762a12f85aSJeremy Jones 	else
12772a12f85aSJeremy Jones 		sp->pr_instr = instr;
12782a12f85aSJeremy Jones 
12792a12f85aSJeremy Jones 	if (gcore_prisstep(lwp))
12802a12f85aSJeremy Jones 		sp->pr_flags |= PR_STEP;
12812a12f85aSJeremy Jones 	gcore_prgetprregs(lwp, sp->pr_reg);
12822a12f85aSJeremy Jones 	if ((t->t_state == TS_STOPPED && t->t_whystop == PR_SYSEXIT) ||
12832a12f85aSJeremy Jones 	    (flags & PR_VFORKP)) {
12842a12f85aSJeremy Jones 		user_t *up;
12852a12f85aSJeremy Jones 		auxv_t *auxp;
12862a12f85aSJeremy Jones 		int i;
12872a12f85aSJeremy Jones 
12882a12f85aSJeremy Jones 		sp->pr_errno = gcore_prgetrvals(lwp, &sp->pr_rval1,
12892a12f85aSJeremy Jones 		    &sp->pr_rval2);
12902a12f85aSJeremy Jones 		if (sp->pr_errno == 0)
12912a12f85aSJeremy Jones 			sp->pr_errpriv = PRIV_NONE;
12922a12f85aSJeremy Jones 		else
12932a12f85aSJeremy Jones 			sp->pr_errpriv = lwp->lwp_badpriv;
12942a12f85aSJeremy Jones 
12952a12f85aSJeremy Jones 		if (t->t_sysnum == SYS_execve) {
12962a12f85aSJeremy Jones 			up = PTOU(p);
12972a12f85aSJeremy Jones 			sp->pr_sysarg[0] = 0;
12982a12f85aSJeremy Jones 			sp->pr_sysarg[1] = (uintptr_t)up->u_argv;
12992a12f85aSJeremy Jones 			sp->pr_sysarg[2] = (uintptr_t)up->u_envp;
1300*2b395c3cSAndy Fiddaman 			sp->pr_sysarg[3] = 0;
13012a12f85aSJeremy Jones 			for (i = 0, auxp = up->u_auxv;
13022a12f85aSJeremy Jones 			    i < sizeof (up->u_auxv) / sizeof (up->u_auxv[0]);
13032a12f85aSJeremy Jones 			    i++, auxp++) {
13042a12f85aSJeremy Jones 				if (auxp->a_type == AT_SUN_EXECNAME) {
13052a12f85aSJeremy Jones 					sp->pr_sysarg[0] =
13062a12f85aSJeremy Jones 					    (uintptr_t)auxp->a_un.a_ptr;
13072a12f85aSJeremy Jones 					break;
13082a12f85aSJeremy Jones 				}
13092a12f85aSJeremy Jones 			}
13102a12f85aSJeremy Jones 		}
13112a12f85aSJeremy Jones 	}
13122a12f85aSJeremy Jones 	return (0);
13132a12f85aSJeremy Jones }
13142a12f85aSJeremy Jones 
13152a12f85aSJeremy Jones static int
gcore_lstatus_cb(mdb_proc_t * p,lwpent_t * lwent,void * data)13162a12f85aSJeremy Jones gcore_lstatus_cb(mdb_proc_t *p, lwpent_t *lwent, void *data)
13172a12f85aSJeremy Jones {
13182a12f85aSJeremy Jones 	lwpstatus_t	*lstatus = data;
13192a12f85aSJeremy Jones 	uintptr_t	t_addr = (uintptr_t)lwent->le_thread;
13202a12f85aSJeremy Jones 	mdb_kthread_t	kthrd;
13212a12f85aSJeremy Jones 
1322892ad162SToomas Soome 	if (t_addr == 0) {
13232a12f85aSJeremy Jones 		return (1);
13242a12f85aSJeremy Jones 	}
13252a12f85aSJeremy Jones 
13262a12f85aSJeremy Jones 	if (mdb_ctf_vread(&kthrd, "kthread_t", "mdb_kthread_t", t_addr, 0)
13272a12f85aSJeremy Jones 	    == -1) {
13282a12f85aSJeremy Jones 		return (-1);
13292a12f85aSJeremy Jones 	}
13302a12f85aSJeremy Jones 
13312a12f85aSJeremy Jones 	return (gcore_prgetlwpstatus(p, t_addr, &kthrd, lstatus, NULL));
13322a12f85aSJeremy Jones }
13332a12f85aSJeremy Jones 
13342a12f85aSJeremy Jones static prheader_t *
gcore_walk_lwps(mdb_proc_t * p,lwp_callback_t callback,int nlwp,size_t ent_size)13352a12f85aSJeremy Jones gcore_walk_lwps(mdb_proc_t *p, lwp_callback_t callback, int nlwp,
13362a12f85aSJeremy Jones     size_t ent_size)
13372a12f85aSJeremy Jones {
13382a12f85aSJeremy Jones 	void		*ent;
13392a12f85aSJeremy Jones 	prheader_t	*php;
13402a12f85aSJeremy Jones 	lwpdir_t	*ldp;
13412a12f85aSJeremy Jones 	lwpdir_t	ld;
13422a12f85aSJeremy Jones 	lwpent_t	lwent;
13432a12f85aSJeremy Jones 	int		status;
13442a12f85aSJeremy Jones 	int		i;
13452a12f85aSJeremy Jones 
13462a12f85aSJeremy Jones 	php = calloc(1, sizeof (prheader_t) + nlwp * ent_size);
13472a12f85aSJeremy Jones 	if (php == NULL) {
13482a12f85aSJeremy Jones 		return (NULL);
13492a12f85aSJeremy Jones 	}
13502a12f85aSJeremy Jones 	php->pr_nent = nlwp;
13512a12f85aSJeremy Jones 	php->pr_entsize = ent_size;
13522a12f85aSJeremy Jones 
13532a12f85aSJeremy Jones 	ent = php + 1;
13542a12f85aSJeremy Jones 	for (ldp = (lwpdir_t *)p->p_lwpdir, i = 0; i < p->p_lwpdir_sz; i++,
13552a12f85aSJeremy Jones 	    ldp++) {
13562a12f85aSJeremy Jones 		if (mdb_vread(&ld, sizeof (ld), (uintptr_t)ldp) !=
13572a12f85aSJeremy Jones 		    sizeof (ld)) {
13582a12f85aSJeremy Jones 			mdb_warn("Failed to read lwpdir_t from %p\n", ldp);
13592a12f85aSJeremy Jones 			goto error;
13602a12f85aSJeremy Jones 		}
13612a12f85aSJeremy Jones 
13622a12f85aSJeremy Jones 		if (ld.ld_entry == NULL) {
13632a12f85aSJeremy Jones 			continue;
13642a12f85aSJeremy Jones 		}
13652a12f85aSJeremy Jones 
13662a12f85aSJeremy Jones 		if (mdb_vread(&lwent, sizeof (lwent), (uintptr_t)ld.ld_entry) !=
13672a12f85aSJeremy Jones 		    sizeof (lwent)) {
13682a12f85aSJeremy Jones 			mdb_warn("Failed to read lwpent_t from %p\n",
13692a12f85aSJeremy Jones 			    ld.ld_entry);
13702a12f85aSJeremy Jones 			goto error;
13712a12f85aSJeremy Jones 		}
13722a12f85aSJeremy Jones 
13732a12f85aSJeremy Jones 		status = callback(p, &lwent, ent);
13742a12f85aSJeremy Jones 		if (status == -1) {
13752a12f85aSJeremy Jones 			dprintf("lwp callback %p returned -1\n", callback);
13762a12f85aSJeremy Jones 			goto error;
13772a12f85aSJeremy Jones 		}
13782a12f85aSJeremy Jones 		if (status == 1) {
13792a12f85aSJeremy Jones 			dprintf("lwp callback %p returned 1\n", callback);
13802a12f85aSJeremy Jones 			continue;
13812a12f85aSJeremy Jones 		}
13822a12f85aSJeremy Jones 
13832a12f85aSJeremy Jones 		ent = (caddr_t)ent + ent_size;
13842a12f85aSJeremy Jones 	}
13852a12f85aSJeremy Jones 
13862a12f85aSJeremy Jones 	return (php);
13872a12f85aSJeremy Jones 
13882a12f85aSJeremy Jones error:
13892a12f85aSJeremy Jones 	free(php);
13902a12f85aSJeremy Jones 	return (NULL);
13912a12f85aSJeremy Jones }
13922a12f85aSJeremy Jones 
13932a12f85aSJeremy Jones /*
13942a12f85aSJeremy Jones  * Misc helper functions.
13952a12f85aSJeremy Jones  */
13962a12f85aSJeremy Jones /*
13972a12f85aSJeremy Jones  * convert code/data pair into old style wait status
13982a12f85aSJeremy Jones  */
13992a12f85aSJeremy Jones static int
gcore_wstat(int code,int data)14002a12f85aSJeremy Jones gcore_wstat(int code, int data)
14012a12f85aSJeremy Jones {
14022a12f85aSJeremy Jones 	int stat = (data & 0377);
14032a12f85aSJeremy Jones 
14042a12f85aSJeremy Jones 	switch (code) {
14052a12f85aSJeremy Jones 	case CLD_EXITED:
14062a12f85aSJeremy Jones 		stat <<= 8;
14072a12f85aSJeremy Jones 		break;
14082a12f85aSJeremy Jones 	case CLD_DUMPED:
14092a12f85aSJeremy Jones 		stat |= WCOREFLG;
14102a12f85aSJeremy Jones 		break;
14112a12f85aSJeremy Jones 	case CLD_KILLED:
14122a12f85aSJeremy Jones 		break;
14132a12f85aSJeremy Jones 	case CLD_TRAPPED:
14142a12f85aSJeremy Jones 	case CLD_STOPPED:
14152a12f85aSJeremy Jones 		stat <<= 8;
14162a12f85aSJeremy Jones 		stat |= WSTOPFLG;
14172a12f85aSJeremy Jones 		break;
14182a12f85aSJeremy Jones 	case CLD_CONTINUED:
14192a12f85aSJeremy Jones 		stat = WCONTFLG;
14202a12f85aSJeremy Jones 		break;
14212a12f85aSJeremy Jones 	default:
14222a12f85aSJeremy Jones 		mdb_warn("wstat: bad code %d\n", code);
14232a12f85aSJeremy Jones 	}
14242a12f85aSJeremy Jones 	return (stat);
14252a12f85aSJeremy Jones }
14262a12f85aSJeremy Jones 
14272a12f85aSJeremy Jones #if defined(__i386) || defined(__amd64)
14282a12f85aSJeremy Jones static void
gcore_usd_to_ssd(user_desc_t * usd,struct ssd * ssd,selector_t sel)14292a12f85aSJeremy Jones gcore_usd_to_ssd(user_desc_t *usd, struct ssd *ssd, selector_t sel)
14302a12f85aSJeremy Jones {
14312a12f85aSJeremy Jones 	ssd->bo = USEGD_GETBASE(usd);
14322a12f85aSJeremy Jones 	ssd->ls = USEGD_GETLIMIT(usd);
14332a12f85aSJeremy Jones 	ssd->sel = sel;
14342a12f85aSJeremy Jones 
14352a12f85aSJeremy Jones 	/*
14362a12f85aSJeremy Jones 	 * set type, dpl and present bits.
14372a12f85aSJeremy Jones 	 */
14382a12f85aSJeremy Jones 	ssd->acc1 = usd->usd_type;
14392a12f85aSJeremy Jones 	ssd->acc1 |= usd->usd_dpl << 5;
14402a12f85aSJeremy Jones 	ssd->acc1 |= usd->usd_p << (5 + 2);
14412a12f85aSJeremy Jones 
14422a12f85aSJeremy Jones 	/*
14432a12f85aSJeremy Jones 	 * set avl, DB and granularity bits.
14442a12f85aSJeremy Jones 	 */
14452a12f85aSJeremy Jones 	ssd->acc2 = usd->usd_avl;
14462a12f85aSJeremy Jones 
14472a12f85aSJeremy Jones #if defined(__amd64)
14482a12f85aSJeremy Jones 	ssd->acc2 |= usd->usd_long << 1;
14492a12f85aSJeremy Jones #else
14502a12f85aSJeremy Jones 	ssd->acc2 |= usd->usd_reserved << 1;
14512a12f85aSJeremy Jones #endif
14522a12f85aSJeremy Jones 
14532a12f85aSJeremy Jones 	ssd->acc2 |= usd->usd_def32 << (1 + 1);
14542a12f85aSJeremy Jones 	ssd->acc2 |= usd->usd_gran << (1 + 1 + 1);
14552a12f85aSJeremy Jones }
14562a12f85aSJeremy Jones #endif
14572a12f85aSJeremy Jones 
14582a12f85aSJeremy Jones static priv_set_t *
gcore_priv_getset(cred_t * cr,int set)14592a12f85aSJeremy Jones gcore_priv_getset(cred_t *cr, int set)
14602a12f85aSJeremy Jones {
14612a12f85aSJeremy Jones 	if ((CR_FLAGS(cr) & PRIV_AWARE) == 0) {
14622a12f85aSJeremy Jones 		switch (set) {
14632a12f85aSJeremy Jones 		case PRIV_EFFECTIVE:
14642a12f85aSJeremy Jones 			return (&CR_OEPRIV(cr));
14652a12f85aSJeremy Jones 		case PRIV_PERMITTED:
14662a12f85aSJeremy Jones 			return (&CR_OPPRIV(cr));
14672a12f85aSJeremy Jones 		}
14682a12f85aSJeremy Jones 	}
14692a12f85aSJeremy Jones 	return (&CR_PRIVS(cr)->crprivs[set]);
14702a12f85aSJeremy Jones }
14712a12f85aSJeremy Jones 
14722a12f85aSJeremy Jones static void
gcore_priv_getinfo(const cred_t * cr,void * buf)14732a12f85aSJeremy Jones gcore_priv_getinfo(const cred_t *cr, void *buf)
14742a12f85aSJeremy Jones {
14752a12f85aSJeremy Jones 	struct priv_info_uint *ii;
14762a12f85aSJeremy Jones 
14772a12f85aSJeremy Jones 	ii = buf;
14782a12f85aSJeremy Jones 	ii->val = CR_FLAGS(cr);
14792a12f85aSJeremy Jones 	ii->info.priv_info_size = (uint32_t)sizeof (*ii);
14802a12f85aSJeremy Jones 	ii->info.priv_info_type = PRIV_INFO_FLAGS;
14812a12f85aSJeremy Jones }
14822a12f85aSJeremy Jones 
14832a12f85aSJeremy Jones static void
map_list_free(prmap_node_t * n)14842a12f85aSJeremy Jones map_list_free(prmap_node_t *n)
14852a12f85aSJeremy Jones {
14862a12f85aSJeremy Jones 	prmap_node_t	*next;
14872a12f85aSJeremy Jones 
14882a12f85aSJeremy Jones 	while (n != NULL) {
14892a12f85aSJeremy Jones 		next = n->next;
14902a12f85aSJeremy Jones 		mdb_free(n, sizeof (*n));
14912a12f85aSJeremy Jones 		n = next;
14922a12f85aSJeremy Jones 	}
14932a12f85aSJeremy Jones }
14942a12f85aSJeremy Jones 
14952a12f85aSJeremy Jones /*
14962a12f85aSJeremy Jones  * Ops vector functions for ::gcore.
14972a12f85aSJeremy Jones  */
14982a12f85aSJeremy Jones /*ARGSUSED*/
14992a12f85aSJeremy Jones static ssize_t
Pread_gcore(struct ps_prochandle * P,void * buf,size_t n,uintptr_t addr,void * data)15002a12f85aSJeremy Jones Pread_gcore(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr,
15012a12f85aSJeremy Jones     void *data)
15022a12f85aSJeremy Jones {
15032a12f85aSJeremy Jones 	mdb_proc_t	*p = data;
15042a12f85aSJeremy Jones 	ssize_t		ret;
15052a12f85aSJeremy Jones 
15062a12f85aSJeremy Jones 	ret = mdb_aread(buf, n, addr, (void *)p->p_as);
15072a12f85aSJeremy Jones 	if (ret != n) {
15082a12f85aSJeremy Jones 		dprintf("%s: addr: %p len: %llx\n", __func__, addr, n);
15092a12f85aSJeremy Jones 		(void) memset(buf, 0, n);
15102a12f85aSJeremy Jones 		return (n);
15112a12f85aSJeremy Jones 	}
15122a12f85aSJeremy Jones 
15132a12f85aSJeremy Jones 	return (ret);
15142a12f85aSJeremy Jones }
15152a12f85aSJeremy Jones 
15162a12f85aSJeremy Jones /*ARGSUSED*/
15172a12f85aSJeremy Jones static ssize_t
Pwrite_gcore(struct ps_prochandle * P,const void * buf,size_t n,uintptr_t addr,void * data)15182a12f85aSJeremy Jones Pwrite_gcore(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr,
15192a12f85aSJeremy Jones     void *data)
15202a12f85aSJeremy Jones {
15212a12f85aSJeremy Jones 	dprintf("%s: addr: %p len: %llx\n", __func__, addr, n);
15222a12f85aSJeremy Jones 
15232a12f85aSJeremy Jones 	return (-1);
15242a12f85aSJeremy Jones }
15252a12f85aSJeremy Jones 
15262a12f85aSJeremy Jones /*ARGSUSED*/
15272a12f85aSJeremy Jones static int
Pread_maps_gcore(struct ps_prochandle * P,prmap_t ** Pmapp,ssize_t * nmapp,void * data)15282a12f85aSJeremy Jones Pread_maps_gcore(struct ps_prochandle *P, prmap_t **Pmapp, ssize_t *nmapp,
15292a12f85aSJeremy Jones     void *data)
15302a12f85aSJeremy Jones {
15312a12f85aSJeremy Jones 	mdb_proc_t	*p = data;
15322a12f85aSJeremy Jones 	read_maps_cbarg_t cbarg;
15332a12f85aSJeremy Jones 	prmap_node_t	*n;
15342a12f85aSJeremy Jones 	prmap_t		*pmap;
15352a12f85aSJeremy Jones 	uintptr_t	segtree_addr;
15362a12f85aSJeremy Jones 	int		error;
15372a12f85aSJeremy Jones 	int		i;
15382a12f85aSJeremy Jones 
15392a12f85aSJeremy Jones 	cbarg.p = p;
15402a12f85aSJeremy Jones 	cbarg.brkseg = gcore_break_seg(p);
15412a12f85aSJeremy Jones 	cbarg.stkseg = gcore_as_segat(p->p_as, gcore_prgetstackbase(p));
15422a12f85aSJeremy Jones 
15432a12f85aSJeremy Jones 	(void) memset(&cbarg, 0, sizeof (cbarg));
15442a12f85aSJeremy Jones 	segtree_addr = p->p_as + mdb_ctf_offsetof_by_name("struct as",
15452a12f85aSJeremy Jones 	    "a_segtree");
15462a12f85aSJeremy Jones 	error = avl_walk_mdb(segtree_addr, read_maps_cb, &cbarg);
15472a12f85aSJeremy Jones 	if (error != WALK_DONE) {
15482a12f85aSJeremy Jones 		return (-1);
15492a12f85aSJeremy Jones 	}
15502a12f85aSJeremy Jones 
15512a12f85aSJeremy Jones 	/* Conver the linked list into an array */
15522a12f85aSJeremy Jones 	pmap = malloc(cbarg.map_len * sizeof (*pmap));
15532a12f85aSJeremy Jones 	if (pmap == NULL) {
15542a12f85aSJeremy Jones 		map_list_free(cbarg.map_head);
15552a12f85aSJeremy Jones 		return (-1);
15562a12f85aSJeremy Jones 	}
15572a12f85aSJeremy Jones 
15582a12f85aSJeremy Jones 	for (i = 0, n = cbarg.map_head; i < cbarg.map_len; i++, n = n->next) {
15592a12f85aSJeremy Jones 		(void) memcpy(&pmap[i], &n->m, sizeof (prmap_t));
15602a12f85aSJeremy Jones 	}
15612a12f85aSJeremy Jones 	map_list_free(cbarg.map_head);
15622a12f85aSJeremy Jones 
15632a12f85aSJeremy Jones 	for (i = 0; i < cbarg.map_len; i++) {
15642a12f85aSJeremy Jones 		dprintf("pr_vaddr: %p pr_size: %llx, pr_name: %s "
15652a12f85aSJeremy Jones 		    "pr_offset: %p pr_mflags: 0x%x\n",
15662a12f85aSJeremy Jones 		    pmap[i].pr_vaddr, pmap[i].pr_size,
15672a12f85aSJeremy Jones 		    pmap[i].pr_mapname, pmap[i].pr_offset,
15682a12f85aSJeremy Jones 		    pmap[i].pr_mflags);
15692a12f85aSJeremy Jones 	}
15702a12f85aSJeremy Jones 
15712a12f85aSJeremy Jones 	*Pmapp = pmap;
15722a12f85aSJeremy Jones 	*nmapp = cbarg.map_len;
15732a12f85aSJeremy Jones 
15742a12f85aSJeremy Jones 	return (0);
15752a12f85aSJeremy Jones }
15762a12f85aSJeremy Jones 
15772a12f85aSJeremy Jones /*ARGSUSED*/
15782a12f85aSJeremy Jones static void
Pread_aux_gcore(struct ps_prochandle * P,auxv_t ** auxvp,int * nauxp,void * data)15792a12f85aSJeremy Jones Pread_aux_gcore(struct ps_prochandle *P, auxv_t **auxvp, int *nauxp, void *data)
15802a12f85aSJeremy Jones {
15812a12f85aSJeremy Jones 	mdb_proc_t	*p = data;
15822a12f85aSJeremy Jones 	auxv_t		*auxv;
15832a12f85aSJeremy Jones 	int		naux;
15842a12f85aSJeremy Jones 
15852a12f85aSJeremy Jones 	naux = __KERN_NAUXV_IMPL;
15862a12f85aSJeremy Jones 	auxv = calloc(naux + 1, sizeof (*auxv));
15872a12f85aSJeremy Jones 	if (auxv == NULL) {
15882a12f85aSJeremy Jones 		*auxvp = NULL;
15892a12f85aSJeremy Jones 		*nauxp = 0;
15902a12f85aSJeremy Jones 		return;
15912a12f85aSJeremy Jones 	}
15922a12f85aSJeremy Jones 
15932a12f85aSJeremy Jones 	(void) memcpy(auxv, p->p_user.u_auxv, naux * sizeof (*auxv));
15942a12f85aSJeremy Jones 
15952a12f85aSJeremy Jones 	*auxvp = auxv;
15962a12f85aSJeremy Jones 	*nauxp = naux;
15972a12f85aSJeremy Jones }
15982a12f85aSJeremy Jones 
15992a12f85aSJeremy Jones /*ARGSUSED*/
16002a12f85aSJeremy Jones static int
Pcred_gcore(struct ps_prochandle * P,prcred_t * prcp,int ngroups,void * data)16012a12f85aSJeremy Jones Pcred_gcore(struct ps_prochandle *P, prcred_t *prcp, int ngroups, void *data)
16022a12f85aSJeremy Jones {
16032a12f85aSJeremy Jones 	mdb_proc_t	*p = data;
16042a12f85aSJeremy Jones 	cred_t		cr;
16052a12f85aSJeremy Jones 	credgrp_t	crgrp;
16062a12f85aSJeremy Jones 	int		i;
16072a12f85aSJeremy Jones 
16082a12f85aSJeremy Jones 	if (mdb_vread(&cr, sizeof (cr), p->p_cred) != sizeof (cr)) {
16092a12f85aSJeremy Jones 		mdb_warn("Failed to read cred_t from %p\n", p->p_cred);
16102a12f85aSJeremy Jones 		return (-1);
16112a12f85aSJeremy Jones 	}
16122a12f85aSJeremy Jones 
16132a12f85aSJeremy Jones 	prcp->pr_euid = cr.cr_uid;
16142a12f85aSJeremy Jones 	prcp->pr_ruid = cr.cr_ruid;
16152a12f85aSJeremy Jones 	prcp->pr_suid = cr.cr_suid;
16162a12f85aSJeremy Jones 	prcp->pr_egid = cr.cr_gid;
16172a12f85aSJeremy Jones 	prcp->pr_rgid = cr.cr_rgid;
16182a12f85aSJeremy Jones 	prcp->pr_sgid = cr.cr_sgid;
16192a12f85aSJeremy Jones 
16202a12f85aSJeremy Jones 	if (cr.cr_grps == 0) {
16212a12f85aSJeremy Jones 		prcp->pr_ngroups = 0;
16222a12f85aSJeremy Jones 		return (0);
16232a12f85aSJeremy Jones 	}
16242a12f85aSJeremy Jones 
16252a12f85aSJeremy Jones 	if (mdb_vread(&crgrp, sizeof (crgrp), (uintptr_t)cr.cr_grps) !=
16262a12f85aSJeremy Jones 	    sizeof (crgrp)) {
16272a12f85aSJeremy Jones 		mdb_warn("Failed to read credgrp_t from %p\n", cr.cr_grps);
16282a12f85aSJeremy Jones 		return (-1);
16292a12f85aSJeremy Jones 	}
16302a12f85aSJeremy Jones 
16312a12f85aSJeremy Jones 	prcp->pr_ngroups = MIN(ngroups, crgrp.crg_ngroups);
16322a12f85aSJeremy Jones 	for (i = 0; i < prcp->pr_ngroups; i++) {
16332a12f85aSJeremy Jones 		prcp->pr_groups[i] = crgrp.crg_groups[i];
16342a12f85aSJeremy Jones 	}
16352a12f85aSJeremy Jones 
16362a12f85aSJeremy Jones 	return (0);
16372a12f85aSJeremy Jones }
16382a12f85aSJeremy Jones 
16392a12f85aSJeremy Jones /*ARGSUSED*/
16402a12f85aSJeremy Jones static int
Ppriv_gcore(struct ps_prochandle * P,prpriv_t ** pprv,void * data)16412a12f85aSJeremy Jones Ppriv_gcore(struct ps_prochandle *P, prpriv_t **pprv, void *data)
16422a12f85aSJeremy Jones {
16432a12f85aSJeremy Jones 	mdb_proc_t	*p = data;
16442a12f85aSJeremy Jones 	prpriv_t	*pp;
16452a12f85aSJeremy Jones 	cred_t		cr;
16462a12f85aSJeremy Jones 	priv_set_t	*psa;
16472a12f85aSJeremy Jones 	size_t		pprv_size;
16482a12f85aSJeremy Jones 	int		i;
16492a12f85aSJeremy Jones 
16502a12f85aSJeremy Jones 	pprv_size = sizeof (prpriv_t) + PRIV_SETBYTES - sizeof (priv_chunk_t) +
16512a12f85aSJeremy Jones 	    prinfo.priv_infosize;
16522a12f85aSJeremy Jones 
16532a12f85aSJeremy Jones 	pp = malloc(pprv_size);
16542a12f85aSJeremy Jones 	if (pp == NULL) {
16552a12f85aSJeremy Jones 		return (-1);
16562a12f85aSJeremy Jones 	}
16572a12f85aSJeremy Jones 
16582a12f85aSJeremy Jones 	if (mdb_vread(&cr, sizeof (cr), p->p_cred) != sizeof (cr)) {
16592a12f85aSJeremy Jones 		mdb_warn("Failed to read cred_t from %p\n", p->p_cred);
16602a12f85aSJeremy Jones 		free(pp);
16612a12f85aSJeremy Jones 		return (-1);
16622a12f85aSJeremy Jones 	}
16632a12f85aSJeremy Jones 
16642a12f85aSJeremy Jones 	pp->pr_nsets = PRIV_NSET;
16652a12f85aSJeremy Jones 	pp->pr_setsize = PRIV_SETSIZE;
16662a12f85aSJeremy Jones 	pp->pr_infosize = prinfo.priv_infosize;
16672a12f85aSJeremy Jones 
16682a12f85aSJeremy Jones 	psa = (priv_set_t *)pp->pr_sets;
16692a12f85aSJeremy Jones 	for (i = 0; i < PRIV_NSET; i++) {
16702a12f85aSJeremy Jones 		psa[i] = *gcore_priv_getset(&cr, i);
16712a12f85aSJeremy Jones 	}
16722a12f85aSJeremy Jones 
16732a12f85aSJeremy Jones 	gcore_priv_getinfo(&cr, (char *)pp + PRIV_PRPRIV_INFO_OFFSET(pp));
16742a12f85aSJeremy Jones 
16752a12f85aSJeremy Jones 	*pprv = pp;
16762a12f85aSJeremy Jones 	return (0);
16772a12f85aSJeremy Jones }
16782a12f85aSJeremy Jones 
16792a12f85aSJeremy Jones /*
16802a12f85aSJeremy Jones  * Fields not filled populated:
16812a12f85aSJeremy Jones  *   - pr_utime
16822a12f85aSJeremy Jones  *   - pr_stkbase
16832a12f85aSJeremy Jones  *   - pr_cutime
16842a12f85aSJeremy Jones  *   - pr_cstime
16852a12f85aSJeremy Jones  *   - pr_agentid
16862a12f85aSJeremy Jones  */
16872a12f85aSJeremy Jones /*ARGSUSED*/
16882a12f85aSJeremy Jones static void
Pstatus_gcore(struct ps_prochandle * P,pstatus_t * sp,void * data)16892a12f85aSJeremy Jones Pstatus_gcore(struct ps_prochandle *P, pstatus_t *sp, void *data)
16902a12f85aSJeremy Jones {
16912a12f85aSJeremy Jones 	mdb_proc_t	*p = data;
16922a12f85aSJeremy Jones 	uintptr_t	t_addr;
16932a12f85aSJeremy Jones 	mdb_kthread_t	kthr;
16942a12f85aSJeremy Jones 	mdb_kthread_t	*t;
16952a12f85aSJeremy Jones 	pcommon_t	pc;
16962a12f85aSJeremy Jones 
16972a12f85aSJeremy Jones 	t_addr = gcore_prchoose(p);
1698892ad162SToomas Soome 	if (t_addr != 0) {
16992a12f85aSJeremy Jones 		if (mdb_ctf_vread(&kthr, "kthread_t", "mdb_kthread_t", t_addr,
17002a12f85aSJeremy Jones 		    0) == -1) {
17012a12f85aSJeremy Jones 			return;
17022a12f85aSJeremy Jones 		}
17032a12f85aSJeremy Jones 		t = &kthr;
17042a12f85aSJeremy Jones 	}
17052a12f85aSJeremy Jones 
17062a12f85aSJeremy Jones 	/* just bzero the process part, prgetlwpstatus() does the rest */
17072a12f85aSJeremy Jones 	bzero(sp, sizeof (pstatus_t) - sizeof (lwpstatus_t));
17082a12f85aSJeremy Jones 
17092a12f85aSJeremy Jones 	if (pcommon_init(p, &pc) == -1) {
17102a12f85aSJeremy Jones 		return;
17112a12f85aSJeremy Jones 	}
17122a12f85aSJeremy Jones 	sp->pr_nlwp = pc.pc_nlwp;
17132a12f85aSJeremy Jones 	sp->pr_nzomb = pc.pc_nzomb;
17142a12f85aSJeremy Jones 	sp->pr_pid = pc.pc_pid;
17152a12f85aSJeremy Jones 	sp->pr_ppid = pc.pc_ppid;
17162a12f85aSJeremy Jones 	sp->pr_pgid = pc.pc_pgid;
17172a12f85aSJeremy Jones 	sp->pr_sid = pc.pc_sid;
17182a12f85aSJeremy Jones 	sp->pr_taskid = pc.pc_taskid;
17192a12f85aSJeremy Jones 	sp->pr_projid = pc.pc_projid;
17202a12f85aSJeremy Jones 	sp->pr_zoneid = pc.pc_zoneid;
17212a12f85aSJeremy Jones 	sp->pr_dmodel = pc.pc_dmodel;
17222a12f85aSJeremy Jones 
17232a12f85aSJeremy Jones 	prassignset(&sp->pr_sigpend, &p->p_sig);
17242a12f85aSJeremy Jones 	sp->pr_brkbase = p->p_brkbase;
17252a12f85aSJeremy Jones 	sp->pr_brksize = p->p_brksize;
17262a12f85aSJeremy Jones 	sp->pr_stkbase = gcore_prgetstackbase(p);
17272a12f85aSJeremy Jones 	sp->pr_stksize = p->p_stksize;
17282a12f85aSJeremy Jones 
17292a12f85aSJeremy Jones 	prassignset(&sp->pr_sigtrace, &p->p_sigmask);
17302a12f85aSJeremy Jones 	prassignset(&sp->pr_flttrace, &p->p_fltmask);
17312a12f85aSJeremy Jones 	prassignset(&sp->pr_sysentry, &PTOU(p)->u_entrymask);
17322a12f85aSJeremy Jones 	prassignset(&sp->pr_sysexit, &PTOU(p)->u_exitmask);
17332a12f85aSJeremy Jones 
17342a12f85aSJeremy Jones 	/* get the chosen lwp's status */
17352a12f85aSJeremy Jones 	gcore_prgetlwpstatus(p, t_addr, t, &sp->pr_lwp, NULL);
17362a12f85aSJeremy Jones 
17372a12f85aSJeremy Jones 	/* replicate the flags */
17382a12f85aSJeremy Jones 	sp->pr_flags = sp->pr_lwp.pr_flags;
17392a12f85aSJeremy Jones }
17402a12f85aSJeremy Jones 
17412a12f85aSJeremy Jones /*
17422a12f85aSJeremy Jones  * Fields not populated:
17432a12f85aSJeremy Jones  *   - pr_contract
17442a12f85aSJeremy Jones  *   - pr_addr
17452a12f85aSJeremy Jones  *   - pr_rtime
17462a12f85aSJeremy Jones  *   - pr_ctime
17472a12f85aSJeremy Jones  *   - pr_ttydev
17482a12f85aSJeremy Jones  *   - pr_pctcpu
17492a12f85aSJeremy Jones  *   - pr_size
17502a12f85aSJeremy Jones  *   - pr_rsize
17512a12f85aSJeremy Jones  *   - pr_pctmem
17522a12f85aSJeremy Jones  */
17532a12f85aSJeremy Jones /*ARGSUSED*/
17542a12f85aSJeremy Jones static const psinfo_t *
Ppsinfo_gcore(struct ps_prochandle * P,psinfo_t * psp,void * data)17552a12f85aSJeremy Jones Ppsinfo_gcore(struct ps_prochandle *P, psinfo_t *psp, void *data)
17562a12f85aSJeremy Jones {
17572a12f85aSJeremy Jones 	mdb_proc_t	*p = data;
17582a12f85aSJeremy Jones 	mdb_kthread_t	*t;
17592a12f85aSJeremy Jones 	mdb_pool_t	pool;
17602a12f85aSJeremy Jones 	cred_t		cr;
17612a12f85aSJeremy Jones 	uintptr_t	t_addr;
17622a12f85aSJeremy Jones 	pcommon_t	pc;
17632a12f85aSJeremy Jones 
1764892ad162SToomas Soome 	if ((t_addr = gcore_prchoose(p)) == 0) {
17652a12f85aSJeremy Jones 		bzero(psp, sizeof (*psp));
17662a12f85aSJeremy Jones 	} else {
17672a12f85aSJeremy Jones 		bzero(psp, sizeof (*psp) - sizeof (psp->pr_lwp));
17682a12f85aSJeremy Jones 	}
17692a12f85aSJeremy Jones 
17702a12f85aSJeremy Jones 	if (pcommon_init(p, &pc) == -1) {
17712a12f85aSJeremy Jones 		return (NULL);
17722a12f85aSJeremy Jones 	}
17732a12f85aSJeremy Jones 	psp->pr_nlwp = pc.pc_nlwp;
17742a12f85aSJeremy Jones 	psp->pr_nzomb = pc.pc_nzomb;
17752a12f85aSJeremy Jones 	psp->pr_pid = pc.pc_pid;
17762a12f85aSJeremy Jones 	psp->pr_ppid = pc.pc_ppid;
17772a12f85aSJeremy Jones 	psp->pr_pgid = pc.pc_pgid;
17782a12f85aSJeremy Jones 	psp->pr_sid = pc.pc_sid;
17792a12f85aSJeremy Jones 	psp->pr_taskid = pc.pc_taskid;
17802a12f85aSJeremy Jones 	psp->pr_projid = pc.pc_projid;
17812a12f85aSJeremy Jones 	psp->pr_dmodel = pc.pc_dmodel;
17822a12f85aSJeremy Jones 
17832a12f85aSJeremy Jones 	/*
17842a12f85aSJeremy Jones 	 * only export SSYS and SMSACCT; everything else is off-limits to
17852a12f85aSJeremy Jones 	 * userland apps.
17862a12f85aSJeremy Jones 	 */
17872a12f85aSJeremy Jones 	psp->pr_flag = p->p_flag & (SSYS | SMSACCT);
17882a12f85aSJeremy Jones 
17892a12f85aSJeremy Jones 	if (mdb_vread(&cr, sizeof (cr), p->p_cred) != sizeof (cr)) {
17902a12f85aSJeremy Jones 		mdb_warn("Failed to read cred_t from %p\n", p->p_cred);
17912a12f85aSJeremy Jones 		return (NULL);
17922a12f85aSJeremy Jones 	}
17932a12f85aSJeremy Jones 
17942a12f85aSJeremy Jones 	psp->pr_uid = cr.cr_ruid;
17952a12f85aSJeremy Jones 	psp->pr_euid = cr.cr_uid;
17962a12f85aSJeremy Jones 	psp->pr_gid = cr.cr_rgid;
17972a12f85aSJeremy Jones 	psp->pr_egid = cr.cr_gid;
17982a12f85aSJeremy Jones 
17992a12f85aSJeremy Jones 	if (mdb_ctf_vread(&pool, "pool_t", "mdb_pool_t", p->p_pool, 0) == -1) {
18002a12f85aSJeremy Jones 		return (NULL);
18012a12f85aSJeremy Jones 	}
18022a12f85aSJeremy Jones 	psp->pr_poolid = pool.pool_id;
18032a12f85aSJeremy Jones 
18042a12f85aSJeremy Jones 	if (t_addr == 0) {
18052a12f85aSJeremy Jones 		int wcode = p->p_wcode;
18062a12f85aSJeremy Jones 
18072a12f85aSJeremy Jones 		if (wcode)
18082a12f85aSJeremy Jones 			psp->pr_wstat = gcore_wstat(wcode, p->p_wdata);
18092a12f85aSJeremy Jones 		psp->pr_ttydev = PRNODEV;
18102a12f85aSJeremy Jones 		psp->pr_lwp.pr_state = SZOMB;
18112a12f85aSJeremy Jones 		psp->pr_lwp.pr_sname = 'Z';
18122a12f85aSJeremy Jones 		psp->pr_lwp.pr_bindpro = PBIND_NONE;
18132a12f85aSJeremy Jones 		psp->pr_lwp.pr_bindpset = PS_NONE;
18142a12f85aSJeremy Jones 	} else {
18152a12f85aSJeremy Jones 		mdb_kthread_t	kthr;
18162a12f85aSJeremy Jones 		user_t		*up = PTOU(p);
18172a12f85aSJeremy Jones 
18182a12f85aSJeremy Jones 		psp->pr_start = up->u_start;
18192a12f85aSJeremy Jones 		bcopy(up->u_comm, psp->pr_fname,
18202a12f85aSJeremy Jones 		    MIN(sizeof (up->u_comm), sizeof (psp->pr_fname)-1));
18212a12f85aSJeremy Jones 		bcopy(up->u_psargs, psp->pr_psargs,
18222a12f85aSJeremy Jones 		    MIN(PRARGSZ-1, PSARGSZ));
18232a12f85aSJeremy Jones 
18242a12f85aSJeremy Jones 		psp->pr_argc = up->u_argc;
18252a12f85aSJeremy Jones 		psp->pr_argv = up->u_argv;
18262a12f85aSJeremy Jones 		psp->pr_envp = up->u_envp;
18272a12f85aSJeremy Jones 
18282a12f85aSJeremy Jones 		/* get the chosen lwp's lwpsinfo */
18292a12f85aSJeremy Jones 		if (mdb_ctf_vread(&kthr, "kthread_t", "mdb_kthread_t", t_addr,
18302a12f85aSJeremy Jones 		    0) == -1) {
18312a12f85aSJeremy Jones 			return (NULL);
18322a12f85aSJeremy Jones 		}
18332a12f85aSJeremy Jones 		t = &kthr;
18342a12f85aSJeremy Jones 
18352a12f85aSJeremy Jones 		gcore_prgetlwpsinfo(t_addr, t, &psp->pr_lwp);
18362a12f85aSJeremy Jones 	}
18372a12f85aSJeremy Jones 
18382a12f85aSJeremy Jones 	return (NULL);
18392a12f85aSJeremy Jones }
18402a12f85aSJeremy Jones 
18412a12f85aSJeremy Jones /*ARGSUSED*/
18422a12f85aSJeremy Jones static prheader_t *
Plstatus_gcore(struct ps_prochandle * P,void * data)18432a12f85aSJeremy Jones Plstatus_gcore(struct ps_prochandle *P, void *data)
18442a12f85aSJeremy Jones {
18452a12f85aSJeremy Jones 	mdb_proc_t	*p = data;
18462a12f85aSJeremy Jones 	int		nlwp = p->p_lwpcnt;
18472a12f85aSJeremy Jones 	size_t		ent_size = LSPAN(lwpstatus_t);
18482a12f85aSJeremy Jones 
18492a12f85aSJeremy Jones 	return (gcore_walk_lwps(p, gcore_lstatus_cb, nlwp, ent_size));
18502a12f85aSJeremy Jones }
18512a12f85aSJeremy Jones 
18522a12f85aSJeremy Jones /*ARGSUSED*/
18532a12f85aSJeremy Jones static prheader_t *
Plpsinfo_gcore(struct ps_prochandle * P,void * data)18542a12f85aSJeremy Jones Plpsinfo_gcore(struct ps_prochandle *P, void *data)
18552a12f85aSJeremy Jones {
18562a12f85aSJeremy Jones 	mdb_proc_t	*p = data;
18572a12f85aSJeremy Jones 	int		nlwp = p->p_lwpcnt + p->p_zombcnt;
18582a12f85aSJeremy Jones 	size_t		ent_size = LSPAN(lwpsinfo_t);
18592a12f85aSJeremy Jones 
18602a12f85aSJeremy Jones 	return (gcore_walk_lwps(p, gcore_lpsinfo_cb, nlwp, ent_size));
18612a12f85aSJeremy Jones }
18622a12f85aSJeremy Jones 
18632a12f85aSJeremy Jones /*ARGSUSED*/
18642a12f85aSJeremy Jones static char *
Pplatform_gcore(struct ps_prochandle * P,char * s,size_t n,void * data)18652a12f85aSJeremy Jones Pplatform_gcore(struct ps_prochandle *P, char *s, size_t n, void *data)
18662a12f85aSJeremy Jones {
18672a12f85aSJeremy Jones 	char	platform[SYS_NMLN];
18682a12f85aSJeremy Jones 
18692a12f85aSJeremy Jones 	if (mdb_readvar(platform, "platform") == -1) {
18702a12f85aSJeremy Jones 		mdb_warn("failed to read platform!\n");
18712a12f85aSJeremy Jones 		return (NULL);
18722a12f85aSJeremy Jones 	}
18732a12f85aSJeremy Jones 	dprintf("platform: %s\n", platform);
18742a12f85aSJeremy Jones 
18752a12f85aSJeremy Jones 	(void) strncpy(s, platform, n);
18762a12f85aSJeremy Jones 	return (s);
18772a12f85aSJeremy Jones }
18782a12f85aSJeremy Jones 
18792a12f85aSJeremy Jones /*ARGSUSED*/
18802a12f85aSJeremy Jones static int
Puname_gcore(struct ps_prochandle * P,struct utsname * u,void * data)18812a12f85aSJeremy Jones Puname_gcore(struct ps_prochandle *P, struct utsname *u, void *data)
18822a12f85aSJeremy Jones {
18832a12f85aSJeremy Jones 	if (mdb_readvar(u, "utsname") != sizeof (*u)) {
18842a12f85aSJeremy Jones 		return (-1);
18852a12f85aSJeremy Jones 	}
18862a12f85aSJeremy Jones 
18872a12f85aSJeremy Jones 	return (0);
18882a12f85aSJeremy Jones }
18892a12f85aSJeremy Jones 
18902a12f85aSJeremy Jones /*ARGSUSED*/
18912a12f85aSJeremy Jones static char *
Pzonename_gcore(struct ps_prochandle * P,char * s,size_t n,void * data)18922a12f85aSJeremy Jones Pzonename_gcore(struct ps_prochandle *P, char *s, size_t n, void *data)
18932a12f85aSJeremy Jones {
18942a12f85aSJeremy Jones 	mdb_proc_t	*p = data;
18952a12f85aSJeremy Jones 	mdb_zone_t	zone;
18962a12f85aSJeremy Jones 
18972a12f85aSJeremy Jones 	if (mdb_ctf_vread(&zone, "zone_t", "mdb_zone_t", p->p_zone, 0) == -1) {
18982a12f85aSJeremy Jones 		return (NULL);
18992a12f85aSJeremy Jones 	}
19002a12f85aSJeremy Jones 
19012a12f85aSJeremy Jones 	if (mdb_readstr(s, n, zone.zone_name) == -1) {
19022a12f85aSJeremy Jones 		mdb_warn("Failed to read zone name from %p\n", zone.zone_name);
19032a12f85aSJeremy Jones 		return (NULL);
19042a12f85aSJeremy Jones 	}
19052a12f85aSJeremy Jones 
19062a12f85aSJeremy Jones 	return (s);
19072a12f85aSJeremy Jones }
19082a12f85aSJeremy Jones 
19092a12f85aSJeremy Jones /*ARGSUSED*/
19102a12f85aSJeremy Jones static char *
Pexecname_gcore(struct ps_prochandle * P,char * buf,size_t buflen,void * data)19112a12f85aSJeremy Jones Pexecname_gcore(struct ps_prochandle *P, char *buf, size_t buflen, void *data)
19122a12f85aSJeremy Jones {
19132a12f85aSJeremy Jones 	mdb_proc_t	*p = data;
19142a12f85aSJeremy Jones 	mdb_vnode_t	vn;
19152a12f85aSJeremy Jones 
19162a12f85aSJeremy Jones 	if (mdb_ctf_vread(&vn, "vnode_t", "mdb_vnode_t", p->p_exec, 0) == -1) {
19172a12f85aSJeremy Jones 		return (NULL);
19182a12f85aSJeremy Jones 	}
19192a12f85aSJeremy Jones 
19202a12f85aSJeremy Jones 	if (mdb_readstr(buf, buflen, vn.v_path) == -1) {
19212a12f85aSJeremy Jones 		mdb_warn("Failed to read vnode path from %p\n", vn.v_path);
19222a12f85aSJeremy Jones 		return (NULL);
19232a12f85aSJeremy Jones 	}
19242a12f85aSJeremy Jones 
19252a12f85aSJeremy Jones 	dprintf("execname: %s\n", buf);
19262a12f85aSJeremy Jones 
19272a12f85aSJeremy Jones 	return (buf);
19282a12f85aSJeremy Jones }
19292a12f85aSJeremy Jones 
19302a12f85aSJeremy Jones #if defined(__i386) || defined(__amd64)
19312a12f85aSJeremy Jones /*ARGSUSED*/
19322a12f85aSJeremy Jones static int
Pldt_gcore(struct ps_prochandle * P,struct ssd * pldt,int nldt,void * data)19332a12f85aSJeremy Jones Pldt_gcore(struct ps_prochandle *P, struct ssd *pldt, int nldt, void *data)
19342a12f85aSJeremy Jones {
19352a12f85aSJeremy Jones 	mdb_proc_t	*p = data;
19362a12f85aSJeremy Jones 	user_desc_t	*udp;
19372a12f85aSJeremy Jones 	user_desc_t	*ldts;
19382a12f85aSJeremy Jones 	size_t		ldt_size;
19392a12f85aSJeremy Jones 	int		i, limit;
19402a12f85aSJeremy Jones 
1941892ad162SToomas Soome 	if (p->p_ldt == 0) {
19422a12f85aSJeremy Jones 		return (0);
19432a12f85aSJeremy Jones 	}
19442a12f85aSJeremy Jones 
19452a12f85aSJeremy Jones 	limit = p->p_ldtlimit;
19462a12f85aSJeremy Jones 
19472a12f85aSJeremy Jones 	/* Is this call just to query the size ? */
19482a12f85aSJeremy Jones 	if (pldt == NULL || nldt == 0) {
19492a12f85aSJeremy Jones 		return (limit);
19502a12f85aSJeremy Jones 	}
19512a12f85aSJeremy Jones 
19522a12f85aSJeremy Jones 	ldt_size = limit * sizeof (*ldts);
19532a12f85aSJeremy Jones 	ldts = malloc(ldt_size);
19542a12f85aSJeremy Jones 	if (ldts == NULL) {
19552a12f85aSJeremy Jones 		mdb_warn("Failed to malloc ldts (size %lld)n", ldt_size);
19562a12f85aSJeremy Jones 		return (-1);
19572a12f85aSJeremy Jones 	}
19582a12f85aSJeremy Jones 
19592a12f85aSJeremy Jones 	if (mdb_vread(ldts, ldt_size, p->p_ldt) != ldt_size) {
19602a12f85aSJeremy Jones 		mdb_warn("Failed to read ldts from %p\n", p->p_ldt);
19612a12f85aSJeremy Jones 		free(ldts);
19622a12f85aSJeremy Jones 		return (-1);
19632a12f85aSJeremy Jones 	}
19642a12f85aSJeremy Jones 
19652a12f85aSJeremy Jones 	for (i = LDT_UDBASE, udp = &ldts[i]; i <= limit; i++, udp++) {
19662a12f85aSJeremy Jones 		if (udp->usd_type != 0 || udp->usd_dpl != 0 ||
19672a12f85aSJeremy Jones 		    udp->usd_p != 0) {
19682a12f85aSJeremy Jones 			gcore_usd_to_ssd(udp, pldt++, SEL_LDT(i));
19692a12f85aSJeremy Jones 		}
19702a12f85aSJeremy Jones 	}
19712a12f85aSJeremy Jones 
19722a12f85aSJeremy Jones 	free(ldts);
19732a12f85aSJeremy Jones 	return (limit);
19742a12f85aSJeremy Jones }
19752a12f85aSJeremy Jones #endif
19762a12f85aSJeremy Jones 
19772a12f85aSJeremy Jones static const ps_ops_t Pgcore_ops = {
19782a12f85aSJeremy Jones 	.pop_pread	= Pread_gcore,
19792a12f85aSJeremy Jones 	.pop_pwrite	= Pwrite_gcore,
19802a12f85aSJeremy Jones 	.pop_read_maps	= Pread_maps_gcore,
19812a12f85aSJeremy Jones 	.pop_read_aux	= Pread_aux_gcore,
19822a12f85aSJeremy Jones 	.pop_cred	= Pcred_gcore,
19832a12f85aSJeremy Jones 	.pop_priv	= Ppriv_gcore,
19842a12f85aSJeremy Jones 	.pop_psinfo	= Ppsinfo_gcore,
19852a12f85aSJeremy Jones 	.pop_status	= Pstatus_gcore,
19862a12f85aSJeremy Jones 	.pop_lstatus	= Plstatus_gcore,
19872a12f85aSJeremy Jones 	.pop_lpsinfo	= Plpsinfo_gcore,
19882a12f85aSJeremy Jones 	.pop_platform	= Pplatform_gcore,
19892a12f85aSJeremy Jones 	.pop_uname	= Puname_gcore,
19902a12f85aSJeremy Jones 	.pop_zonename	= Pzonename_gcore,
19912a12f85aSJeremy Jones 	.pop_execname	= Pexecname_gcore,
19922a12f85aSJeremy Jones #if defined(__i386) || defined(__amd64)
19932a12f85aSJeremy Jones 	.pop_ldt	= Pldt_gcore
19942a12f85aSJeremy Jones #endif
19952a12f85aSJeremy Jones };
19962a12f85aSJeremy Jones 
19972a12f85aSJeremy Jones /*ARGSUSED*/
19982a12f85aSJeremy Jones int
gcore_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)19992a12f85aSJeremy Jones gcore_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
20002a12f85aSJeremy Jones {
20012a12f85aSJeremy Jones 	struct ps_prochandle *P;
20022a12f85aSJeremy Jones 	char		core_name[MAXNAMELEN];
20032a12f85aSJeremy Jones 	mdb_proc_t	p;
20042a12f85aSJeremy Jones 	mdb_pid_t	pid;
20052a12f85aSJeremy Jones 
20062a12f85aSJeremy Jones 	if (!gcore_initialized) {
20072a12f85aSJeremy Jones 		mdb_warn("gcore unavailable\n");
20082a12f85aSJeremy Jones 		return (DCMD_ERR);
20092a12f85aSJeremy Jones 	}
20102a12f85aSJeremy Jones 
20112a12f85aSJeremy Jones 	if (mdb_ctf_vread(&p, "proc_t", "mdb_proc_t", addr, 0) == -1) {
20122a12f85aSJeremy Jones 		return (DCMD_ERR);
20132a12f85aSJeremy Jones 	}
20142a12f85aSJeremy Jones 
20152a12f85aSJeremy Jones 	if (p.p_flag & SSYS) {
20162a12f85aSJeremy Jones 		mdb_warn("'%s' is a system process\n", p.p_user.u_comm);
20172a12f85aSJeremy Jones 		return (DCMD_ERR);
20182a12f85aSJeremy Jones 	}
20192a12f85aSJeremy Jones 
20202a12f85aSJeremy Jones 	if (mdb_ctf_vread(&pid, "struct pid", "mdb_pid_t", p.p_pidp, 0)
20212a12f85aSJeremy Jones 	    == -1) {
20222a12f85aSJeremy Jones 		return (DCMD_ERR);
20232a12f85aSJeremy Jones 	}
20242a12f85aSJeremy Jones 
20252a12f85aSJeremy Jones 	if ((P = Pgrab_ops(pid.pid_id, &p, &Pgcore_ops, PGRAB_INCORE)) ==
20262a12f85aSJeremy Jones 	    NULL) {
20272a12f85aSJeremy Jones 		mdb_warn("Failed to initialize proc handle");
20282a12f85aSJeremy Jones 		return (DCMD_ERR);
20292a12f85aSJeremy Jones 	}
20302a12f85aSJeremy Jones 
20312a12f85aSJeremy Jones 	(void) snprintf(core_name, sizeof (core_name), "core.%s.%d",
20322a12f85aSJeremy Jones 	    p.p_user.u_comm, pid.pid_id);
20332a12f85aSJeremy Jones 
203464e4e50aSKeith M Wesolowski 	if (Pgcore(P, core_name, CC_CONTENT_DEFAULT) != 0) {
203564e4e50aSKeith M Wesolowski 		mdb_warn("Failed to generate core file: %d", errno);
20362a12f85aSJeremy Jones 		Pfree(P);
20372a12f85aSJeremy Jones 		return (DCMD_ERR);
20382a12f85aSJeremy Jones 	}
20392a12f85aSJeremy Jones 
20402a12f85aSJeremy Jones 	Pfree(P);
20412a12f85aSJeremy Jones 	mdb_printf("Created core file: %s\n", core_name);
20422a12f85aSJeremy Jones 
20432a12f85aSJeremy Jones 	return (0);
20442a12f85aSJeremy Jones }
20452a12f85aSJeremy Jones 
20462a12f85aSJeremy Jones void
gcore_init(void)20472a12f85aSJeremy Jones gcore_init(void)
20482a12f85aSJeremy Jones {
20492a12f85aSJeremy Jones 	GElf_Sym	sym;
20502a12f85aSJeremy Jones 	uintptr_t	priv_info_addr;
20512a12f85aSJeremy Jones 
20522a12f85aSJeremy Jones 	if (mdb_lookup_by_name("segvn_ops", &sym) == -1) {
20532a12f85aSJeremy Jones 		mdb_warn("Failed to lookup symbol 'segvn_ops'\n");
20542a12f85aSJeremy Jones 		return;
20552a12f85aSJeremy Jones 	}
20562a12f85aSJeremy Jones 	gcore_segvn_ops = sym.st_value;
20572a12f85aSJeremy Jones 
20582a12f85aSJeremy Jones 	if (mdb_readvar(&priv_info_addr, "priv_info") == -1) {
20592a12f85aSJeremy Jones 		mdb_warn("Failed to read variable 'priv_info'\n");
20602a12f85aSJeremy Jones 		return;
20612a12f85aSJeremy Jones 	}
20622a12f85aSJeremy Jones 
20632a12f85aSJeremy Jones 	if (mdb_vread(&prinfo, sizeof (prinfo), priv_info_addr) == -1) {
20642a12f85aSJeremy Jones 		mdb_warn("Failed to read prinfo from %p\n", priv_info_addr);
20652a12f85aSJeremy Jones 		return;
20662a12f85aSJeremy Jones 	}
20672a12f85aSJeremy Jones 
20682a12f85aSJeremy Jones 	if (mdb_lookup_by_name("sclass", &sym) == -1) {
20692a12f85aSJeremy Jones 		mdb_warn("Failed to lookup symbol 'segvn_ops'\n");
20702a12f85aSJeremy Jones 		return;
20712a12f85aSJeremy Jones 	}
20722a12f85aSJeremy Jones 
20732a12f85aSJeremy Jones 	gcore_sclass = mdb_zalloc(sym.st_size, UM_SLEEP);
20742a12f85aSJeremy Jones 	if (mdb_vread(gcore_sclass, sym.st_size, sym.st_value) != sym.st_size) {
20752a12f85aSJeremy Jones 		mdb_warn("Failed to read sclass' from %p\n", sym.st_value);
20762a12f85aSJeremy Jones 		return;
20772a12f85aSJeremy Jones 	}
20782a12f85aSJeremy Jones 
20792a12f85aSJeremy Jones 	if (mdb_lookup_by_name("kas", &sym) == -1) {
20802a12f85aSJeremy Jones 		mdb_warn("Failed to lookup symbol 'kas'\n");
20812a12f85aSJeremy Jones 		return;
20822a12f85aSJeremy Jones 	}
20832a12f85aSJeremy Jones 	gcore_kas = sym.st_value;
20842a12f85aSJeremy Jones 
20852a12f85aSJeremy Jones 	gcore_initialized = B_TRUE;
20862a12f85aSJeremy Jones }
20872a12f85aSJeremy Jones 
20882a12f85aSJeremy Jones #endif /* _KMDB */
2089