xref: /onnv-gate/usr/src/lib/libproc/common/Plwpregs.c (revision 2712:f74a135872bc)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*2712Snn35248  * Common Development and Distribution License (the "License").
6*2712Snn35248  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*2712Snn35248  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <sys/types.h>
290Sstevel@tonic-gate #include <sys/uio.h>
300Sstevel@tonic-gate #include <string.h>
310Sstevel@tonic-gate #include <errno.h>
32*2712Snn35248 #include <limits.h>
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include "Pcontrol.h"
350Sstevel@tonic-gate #include "P32ton.h"
360Sstevel@tonic-gate 
370Sstevel@tonic-gate /*
380Sstevel@tonic-gate  * This file implements the routines to read and write per-lwp register
390Sstevel@tonic-gate  * information from either a live process or core file opened with libproc.
400Sstevel@tonic-gate  * We build up a few common routines for reading and writing register
410Sstevel@tonic-gate  * information, and then the public functions are all trivial calls to these.
420Sstevel@tonic-gate  */
430Sstevel@tonic-gate 
440Sstevel@tonic-gate /*
450Sstevel@tonic-gate  * Utility function to return a pointer to the structure of cached information
460Sstevel@tonic-gate  * about an lwp in the core file, given its lwpid.
470Sstevel@tonic-gate  */
480Sstevel@tonic-gate static lwp_info_t *
getlwpcore(struct ps_prochandle * P,lwpid_t lwpid)490Sstevel@tonic-gate getlwpcore(struct ps_prochandle *P, lwpid_t lwpid)
500Sstevel@tonic-gate {
510Sstevel@tonic-gate 	lwp_info_t *lwp = list_next(&P->core->core_lwp_head);
520Sstevel@tonic-gate 	uint_t i;
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	for (i = 0; i < P->core->core_nlwp; i++, lwp = list_next(lwp)) {
550Sstevel@tonic-gate 		if (lwp->lwp_id == lwpid)
560Sstevel@tonic-gate 			return (lwp);
570Sstevel@tonic-gate 	}
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 	errno = EINVAL;
600Sstevel@tonic-gate 	return (NULL);
610Sstevel@tonic-gate }
620Sstevel@tonic-gate 
630Sstevel@tonic-gate /*
640Sstevel@tonic-gate  * Utility function to open and read the contents of a per-lwp /proc file.
650Sstevel@tonic-gate  * This function is used to slurp in lwpstatus, xregs, and asrs.
660Sstevel@tonic-gate  */
670Sstevel@tonic-gate static int
getlwpfile(struct ps_prochandle * P,lwpid_t lwpid,const char * fbase,void * rp,size_t n)680Sstevel@tonic-gate getlwpfile(struct ps_prochandle *P, lwpid_t lwpid,
690Sstevel@tonic-gate     const char *fbase, void *rp, size_t n)
700Sstevel@tonic-gate {
71*2712Snn35248 	char fname[PATH_MAX];
720Sstevel@tonic-gate 	int fd;
730Sstevel@tonic-gate 
74*2712Snn35248 	(void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%d/%s",
75*2712Snn35248 	    procfs_path, (int)P->status.pr_pid, (int)lwpid, fbase);
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 	if ((fd = open(fname, O_RDONLY)) >= 0) {
780Sstevel@tonic-gate 		if (read(fd, rp, n) > 0) {
790Sstevel@tonic-gate 			(void) close(fd);
800Sstevel@tonic-gate 			return (0);
810Sstevel@tonic-gate 		}
820Sstevel@tonic-gate 		(void) close(fd);
830Sstevel@tonic-gate 	}
840Sstevel@tonic-gate 	return (-1);
850Sstevel@tonic-gate }
860Sstevel@tonic-gate 
870Sstevel@tonic-gate /*
880Sstevel@tonic-gate  * Get the lwpstatus_t for an lwp from either the live process or our
890Sstevel@tonic-gate  * cached information from the core file.  This is used to get the
900Sstevel@tonic-gate  * general-purpose registers or floating point registers.
910Sstevel@tonic-gate  */
920Sstevel@tonic-gate int
getlwpstatus(struct ps_prochandle * P,lwpid_t lwpid,lwpstatus_t * lps)930Sstevel@tonic-gate getlwpstatus(struct ps_prochandle *P, lwpid_t lwpid, lwpstatus_t *lps)
940Sstevel@tonic-gate {
950Sstevel@tonic-gate 	lwp_info_t *lwp;
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	/*
980Sstevel@tonic-gate 	 * For both live processes and cores, our job is easy if the lwpid
990Sstevel@tonic-gate 	 * matches that of the representative lwp:
1000Sstevel@tonic-gate 	 */
1010Sstevel@tonic-gate 	if (P->status.pr_lwp.pr_lwpid == lwpid) {
1020Sstevel@tonic-gate 		(void) memcpy(lps, &P->status.pr_lwp, sizeof (lwpstatus_t));
1030Sstevel@tonic-gate 		return (0);
1040Sstevel@tonic-gate 	}
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	/*
1070Sstevel@tonic-gate 	 * If this is a live process, then just read the information out
1080Sstevel@tonic-gate 	 * of the per-lwp status file:
1090Sstevel@tonic-gate 	 */
1100Sstevel@tonic-gate 	if (P->state != PS_DEAD) {
1110Sstevel@tonic-gate 		return (getlwpfile(P, lwpid, "lwpstatus",
1120Sstevel@tonic-gate 		    lps, sizeof (lwpstatus_t)));
1130Sstevel@tonic-gate 	}
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	/*
1160Sstevel@tonic-gate 	 * If this is a core file, we need to iterate through our list of
1170Sstevel@tonic-gate 	 * cached lwp information and then copy out the status.
1180Sstevel@tonic-gate 	 */
1190Sstevel@tonic-gate 	if (P->core != NULL && (lwp = getlwpcore(P, lwpid)) != NULL) {
1200Sstevel@tonic-gate 		(void) memcpy(lps, &lwp->lwp_status, sizeof (lwpstatus_t));
1210Sstevel@tonic-gate 		return (0);
1220Sstevel@tonic-gate 	}
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 	return (-1);
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate /*
1280Sstevel@tonic-gate  * Utility function to modify lwp registers.  This is done using either the
1290Sstevel@tonic-gate  * process control file or per-lwp control file as necessary.
1300Sstevel@tonic-gate  */
1310Sstevel@tonic-gate static int
setlwpregs(struct ps_prochandle * P,lwpid_t lwpid,long cmd,const void * rp,size_t n)1320Sstevel@tonic-gate setlwpregs(struct ps_prochandle *P, lwpid_t lwpid, long cmd,
1330Sstevel@tonic-gate     const void *rp, size_t n)
1340Sstevel@tonic-gate {
1350Sstevel@tonic-gate 	iovec_t iov[2];
136*2712Snn35248 	char fname[PATH_MAX];
1370Sstevel@tonic-gate 	int fd;
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	if (P->state != PS_STOP) {
1400Sstevel@tonic-gate 		errno = EBUSY;
1410Sstevel@tonic-gate 		return (-1);
1420Sstevel@tonic-gate 	}
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate 	iov[0].iov_base = (caddr_t)&cmd;
1450Sstevel@tonic-gate 	iov[0].iov_len = sizeof (long);
1460Sstevel@tonic-gate 	iov[1].iov_base = (caddr_t)rp;
1470Sstevel@tonic-gate 	iov[1].iov_len = n;
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	/*
1500Sstevel@tonic-gate 	 * Writing the process control file writes the representative lwp.
1510Sstevel@tonic-gate 	 * Psync before we write to make sure we are consistent with the
1520Sstevel@tonic-gate 	 * primary interfaces.  Similarly, make sure to update P->status
1530Sstevel@tonic-gate 	 * afterward if we are modifying one of its register sets.
1540Sstevel@tonic-gate 	 */
1550Sstevel@tonic-gate 	if (P->status.pr_lwp.pr_lwpid == lwpid) {
1560Sstevel@tonic-gate 		Psync(P);
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 		if (writev(P->ctlfd, iov, 2) == -1)
1590Sstevel@tonic-gate 			return (-1);
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 		if (cmd == PCSREG)
1620Sstevel@tonic-gate 			(void) memcpy(P->status.pr_lwp.pr_reg, rp, n);
1630Sstevel@tonic-gate 		else if (cmd == PCSFPREG)
1640Sstevel@tonic-gate 			(void) memcpy(&P->status.pr_lwp.pr_fpreg, rp, n);
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 		return (0);
1670Sstevel@tonic-gate 	}
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	/*
1700Sstevel@tonic-gate 	 * If the lwp we want is not the representative lwp, we need to
1710Sstevel@tonic-gate 	 * open the ctl file for that specific lwp.
1720Sstevel@tonic-gate 	 */
173*2712Snn35248 	(void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%d/lwpctl",
174*2712Snn35248 	    procfs_path, (int)P->status.pr_pid, (int)lwpid);
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	if ((fd = open(fname, O_WRONLY)) >= 0) {
1770Sstevel@tonic-gate 		if (writev(fd, iov, 2) > 0) {
1780Sstevel@tonic-gate 			(void) close(fd);
1790Sstevel@tonic-gate 			return (0);
1800Sstevel@tonic-gate 		}
1810Sstevel@tonic-gate 		(void) close(fd);
1820Sstevel@tonic-gate 	}
1830Sstevel@tonic-gate 	return (-1);
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate int
Plwp_getregs(struct ps_prochandle * P,lwpid_t lwpid,prgregset_t gregs)1870Sstevel@tonic-gate Plwp_getregs(struct ps_prochandle *P, lwpid_t lwpid, prgregset_t gregs)
1880Sstevel@tonic-gate {
1890Sstevel@tonic-gate 	lwpstatus_t lps;
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 	if (getlwpstatus(P, lwpid, &lps) == -1)
1920Sstevel@tonic-gate 		return (-1);
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	(void) memcpy(gregs, lps.pr_reg, sizeof (prgregset_t));
1950Sstevel@tonic-gate 	return (0);
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate int
Plwp_setregs(struct ps_prochandle * P,lwpid_t lwpid,const prgregset_t gregs)1990Sstevel@tonic-gate Plwp_setregs(struct ps_prochandle *P, lwpid_t lwpid, const prgregset_t gregs)
2000Sstevel@tonic-gate {
2010Sstevel@tonic-gate 	return (setlwpregs(P, lwpid, PCSREG, gregs, sizeof (prgregset_t)));
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate int
Plwp_getfpregs(struct ps_prochandle * P,lwpid_t lwpid,prfpregset_t * fpregs)2050Sstevel@tonic-gate Plwp_getfpregs(struct ps_prochandle *P, lwpid_t lwpid, prfpregset_t *fpregs)
2060Sstevel@tonic-gate {
2070Sstevel@tonic-gate 	lwpstatus_t lps;
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	if (getlwpstatus(P, lwpid, &lps) == -1)
2100Sstevel@tonic-gate 		return (-1);
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	(void) memcpy(fpregs, &lps.pr_fpreg, sizeof (prfpregset_t));
2130Sstevel@tonic-gate 	return (0);
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate 
Plwp_setfpregs(struct ps_prochandle * P,lwpid_t lwpid,const prfpregset_t * fpregs)2160Sstevel@tonic-gate int Plwp_setfpregs(struct ps_prochandle *P, lwpid_t lwpid,
2170Sstevel@tonic-gate     const prfpregset_t *fpregs)
2180Sstevel@tonic-gate {
2190Sstevel@tonic-gate 	return (setlwpregs(P, lwpid, PCSFPREG, fpregs, sizeof (prfpregset_t)));
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate #if defined(sparc) || defined(__sparc)
2230Sstevel@tonic-gate int
Plwp_getxregs(struct ps_prochandle * P,lwpid_t lwpid,prxregset_t * xregs)2240Sstevel@tonic-gate Plwp_getxregs(struct ps_prochandle *P, lwpid_t lwpid, prxregset_t *xregs)
2250Sstevel@tonic-gate {
2260Sstevel@tonic-gate 	lwp_info_t *lwp;
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	if (P->state == PS_IDLE) {
2290Sstevel@tonic-gate 		errno = ENODATA;
2300Sstevel@tonic-gate 		return (-1);
2310Sstevel@tonic-gate 	}
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 	if (P->state != PS_DEAD) {
2340Sstevel@tonic-gate 		if (P->state != PS_STOP) {
2350Sstevel@tonic-gate 			errno = EBUSY;
2360Sstevel@tonic-gate 			return (-1);
2370Sstevel@tonic-gate 		}
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 		return (getlwpfile(P, lwpid, "xregs",
2400Sstevel@tonic-gate 		    xregs, sizeof (prxregset_t)));
2410Sstevel@tonic-gate 	}
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_xregs != NULL) {
2440Sstevel@tonic-gate 		(void) memcpy(xregs, lwp->lwp_xregs, sizeof (prxregset_t));
2450Sstevel@tonic-gate 		return (0);
2460Sstevel@tonic-gate 	}
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 	if (lwp != NULL)
2490Sstevel@tonic-gate 		errno = ENODATA;
2500Sstevel@tonic-gate 	return (-1);
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate int
Plwp_setxregs(struct ps_prochandle * P,lwpid_t lwpid,const prxregset_t * xregs)2540Sstevel@tonic-gate Plwp_setxregs(struct ps_prochandle *P, lwpid_t lwpid, const prxregset_t *xregs)
2550Sstevel@tonic-gate {
2560Sstevel@tonic-gate 	return (setlwpregs(P, lwpid, PCSXREG, xregs, sizeof (prxregset_t)));
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate int
Plwp_getgwindows(struct ps_prochandle * P,lwpid_t lwpid,gwindows_t * gwins)2600Sstevel@tonic-gate Plwp_getgwindows(struct ps_prochandle *P, lwpid_t lwpid, gwindows_t *gwins)
2610Sstevel@tonic-gate {
2620Sstevel@tonic-gate 	lwp_info_t *lwp;
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	if (P->state == PS_IDLE) {
2650Sstevel@tonic-gate 		errno = ENODATA;
2660Sstevel@tonic-gate 		return (-1);
2670Sstevel@tonic-gate 	}
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	if (P->state != PS_DEAD) {
2700Sstevel@tonic-gate 		if (P->state != PS_STOP) {
2710Sstevel@tonic-gate 			errno = EBUSY;
2720Sstevel@tonic-gate 			return (-1);
2730Sstevel@tonic-gate 		}
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 		return (getlwpfile(P, lwpid, "gwindows",
2760Sstevel@tonic-gate 		    gwins, sizeof (gwindows_t)));
2770Sstevel@tonic-gate 	}
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 	if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_gwins != NULL) {
2800Sstevel@tonic-gate 		*gwins = *lwp->lwp_gwins;
2810Sstevel@tonic-gate 		return (0);
2820Sstevel@tonic-gate 	}
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 	if (lwp != NULL)
2850Sstevel@tonic-gate 		errno = ENODATA;
2860Sstevel@tonic-gate 	return (-1);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate #if defined(__sparcv9)
2900Sstevel@tonic-gate int
Plwp_getasrs(struct ps_prochandle * P,lwpid_t lwpid,asrset_t asrs)2910Sstevel@tonic-gate Plwp_getasrs(struct ps_prochandle *P, lwpid_t lwpid, asrset_t asrs)
2920Sstevel@tonic-gate {
2930Sstevel@tonic-gate 	lwp_info_t *lwp;
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	if (P->state == PS_IDLE) {
2960Sstevel@tonic-gate 		errno = ENODATA;
2970Sstevel@tonic-gate 		return (-1);
2980Sstevel@tonic-gate 	}
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	if (P->state != PS_DEAD) {
3010Sstevel@tonic-gate 		if (P->state != PS_STOP) {
3020Sstevel@tonic-gate 			errno = EBUSY;
3030Sstevel@tonic-gate 			return (-1);
3040Sstevel@tonic-gate 		}
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 		return (getlwpfile(P, lwpid, "asrs", asrs, sizeof (asrset_t)));
3070Sstevel@tonic-gate 	}
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_asrs != NULL) {
3100Sstevel@tonic-gate 		(void) memcpy(asrs, lwp->lwp_asrs, sizeof (asrset_t));
3110Sstevel@tonic-gate 		return (0);
3120Sstevel@tonic-gate 	}
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	if (lwp != NULL)
3150Sstevel@tonic-gate 		errno = ENODATA;
3160Sstevel@tonic-gate 	return (-1);
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate int
Plwp_setasrs(struct ps_prochandle * P,lwpid_t lwpid,const asrset_t asrs)3210Sstevel@tonic-gate Plwp_setasrs(struct ps_prochandle *P, lwpid_t lwpid, const asrset_t asrs)
3220Sstevel@tonic-gate {
3230Sstevel@tonic-gate 	return (setlwpregs(P, lwpid, PCSASRS, asrs, sizeof (asrset_t)));
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate #endif	/* __sparcv9 */
3260Sstevel@tonic-gate #endif	/* __sparc */
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate int
Plwp_getpsinfo(struct ps_prochandle * P,lwpid_t lwpid,lwpsinfo_t * lps)3290Sstevel@tonic-gate Plwp_getpsinfo(struct ps_prochandle *P, lwpid_t lwpid, lwpsinfo_t *lps)
3300Sstevel@tonic-gate {
3310Sstevel@tonic-gate 	lwp_info_t *lwp;
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	if (P->state == PS_IDLE) {
3340Sstevel@tonic-gate 		errno = ENODATA;
3350Sstevel@tonic-gate 		return (-1);
3360Sstevel@tonic-gate 	}
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	if (P->state != PS_DEAD) {
3390Sstevel@tonic-gate 		return (getlwpfile(P, lwpid, "lwpsinfo",
3400Sstevel@tonic-gate 		    lps, sizeof (lwpsinfo_t)));
3410Sstevel@tonic-gate 	}
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 	if ((lwp = getlwpcore(P, lwpid)) != NULL) {
3440Sstevel@tonic-gate 		(void) memcpy(lps, &lwp->lwp_psinfo, sizeof (lwpsinfo_t));
3450Sstevel@tonic-gate 		return (0);
3460Sstevel@tonic-gate 	}
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 	return (-1);
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate int
Plwp_stack(struct ps_prochandle * P,lwpid_t lwpid,stack_t * stkp)3520Sstevel@tonic-gate Plwp_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp)
3530Sstevel@tonic-gate {
3540Sstevel@tonic-gate 	uintptr_t addr;
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 	if (P->state == PS_IDLE) {
3570Sstevel@tonic-gate 		errno = ENODATA;
3580Sstevel@tonic-gate 		return (-1);
3590Sstevel@tonic-gate 	}
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	if (P->state != PS_DEAD) {
3620Sstevel@tonic-gate 		lwpstatus_t ls;
3630Sstevel@tonic-gate 		if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)
3640Sstevel@tonic-gate 			return (-1);
3650Sstevel@tonic-gate 		addr = ls.pr_ustack;
3660Sstevel@tonic-gate 	} else {
3670Sstevel@tonic-gate 		lwp_info_t *lwp;
3680Sstevel@tonic-gate 		if ((lwp = getlwpcore(P, lwpid)) == NULL)
3690Sstevel@tonic-gate 			return (-1);
3700Sstevel@tonic-gate 		addr = lwp->lwp_status.pr_ustack;
3710Sstevel@tonic-gate 	}
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 	if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
3750Sstevel@tonic-gate 		if (Pread(P, stkp, sizeof (*stkp), addr) != sizeof (*stkp))
3760Sstevel@tonic-gate 			return (-1);
3770Sstevel@tonic-gate #ifdef _LP64
3780Sstevel@tonic-gate 	} else {
3790Sstevel@tonic-gate 		stack32_t stk32;
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate 		if (Pread(P, &stk32, sizeof (stk32), addr) != sizeof (stk32))
3820Sstevel@tonic-gate 			return (-1);
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 		stack_32_to_n(&stk32, stkp);
3850Sstevel@tonic-gate #endif
3860Sstevel@tonic-gate 	}
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	return (0);
3890Sstevel@tonic-gate }
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate int
Plwp_main_stack(struct ps_prochandle * P,lwpid_t lwpid,stack_t * stkp)3920Sstevel@tonic-gate Plwp_main_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp)
3930Sstevel@tonic-gate {
3940Sstevel@tonic-gate 	uintptr_t addr;
3950Sstevel@tonic-gate 	lwpstatus_t ls;
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	if (P->state == PS_IDLE) {
3980Sstevel@tonic-gate 		errno = ENODATA;
3990Sstevel@tonic-gate 		return (-1);
4000Sstevel@tonic-gate 	}
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	if (P->state != PS_DEAD) {
4030Sstevel@tonic-gate 		if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)
4040Sstevel@tonic-gate 			return (-1);
4050Sstevel@tonic-gate 	} else {
4060Sstevel@tonic-gate 		lwp_info_t *lwp;
4070Sstevel@tonic-gate 		if ((lwp = getlwpcore(P, lwpid)) == NULL)
4080Sstevel@tonic-gate 			return (-1);
4090Sstevel@tonic-gate 		ls = lwp->lwp_status;
4100Sstevel@tonic-gate 	}
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 	addr = ls.pr_ustack;
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 	/*
4150Sstevel@tonic-gate 	 * Read out the current stack; if the SS_ONSTACK flag is set then
4160Sstevel@tonic-gate 	 * this LWP is operating on the alternate signal stack. We can
4170Sstevel@tonic-gate 	 * recover the original stack from pr_oldcontext.
4180Sstevel@tonic-gate 	 */
4190Sstevel@tonic-gate 	if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
4200Sstevel@tonic-gate 		if (Pread(P, stkp, sizeof (*stkp), addr) != sizeof (*stkp))
4210Sstevel@tonic-gate 			return (-1);
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 		if (stkp->ss_flags & SS_ONSTACK)
4240Sstevel@tonic-gate 			goto on_altstack;
4250Sstevel@tonic-gate #ifdef _LP64
4260Sstevel@tonic-gate 	} else {
4270Sstevel@tonic-gate 		stack32_t stk32;
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 		if (Pread(P, &stk32, sizeof (stk32), addr) != sizeof (stk32))
4300Sstevel@tonic-gate 			return (-1);
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 		if (stk32.ss_flags & SS_ONSTACK)
4330Sstevel@tonic-gate 			goto on_altstack;
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 		stack_32_to_n(&stk32, stkp);
4360Sstevel@tonic-gate #endif
4370Sstevel@tonic-gate 	}
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 	return (0);
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate on_altstack:
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 	if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
4440Sstevel@tonic-gate 		ucontext_t *ctxp = (void *)ls.pr_oldcontext;
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 		if (Pread(P, stkp, sizeof (*stkp),
4470Sstevel@tonic-gate 		    (uintptr_t)&ctxp->uc_stack) != sizeof (*stkp))
4480Sstevel@tonic-gate 			return (-1);
4490Sstevel@tonic-gate #ifdef _LP64
4500Sstevel@tonic-gate 	} else {
4510Sstevel@tonic-gate 		ucontext32_t *ctxp = (void *)ls.pr_oldcontext;
4520Sstevel@tonic-gate 		stack32_t stk32;
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 		if (Pread(P, &stk32, sizeof (stk32),
4550Sstevel@tonic-gate 		    (uintptr_t)&ctxp->uc_stack) != sizeof (stk32))
4560Sstevel@tonic-gate 			return (-1);
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 		stack_32_to_n(&stk32, stkp);
4590Sstevel@tonic-gate #endif
4600Sstevel@tonic-gate 	}
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	return (0);
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate int
Plwp_alt_stack(struct ps_prochandle * P,lwpid_t lwpid,stack_t * stkp)4660Sstevel@tonic-gate Plwp_alt_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp)
4670Sstevel@tonic-gate {
4680Sstevel@tonic-gate 	if (P->state == PS_IDLE) {
4690Sstevel@tonic-gate 		errno = ENODATA;
4700Sstevel@tonic-gate 		return (-1);
4710Sstevel@tonic-gate 	}
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 	if (P->state != PS_DEAD) {
4740Sstevel@tonic-gate 		lwpstatus_t ls;
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 		if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)
4770Sstevel@tonic-gate 			return (-1);
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 		if (ls.pr_altstack.ss_flags & SS_DISABLE) {
4800Sstevel@tonic-gate 			errno = ENODATA;
4810Sstevel@tonic-gate 			return (-1);
4820Sstevel@tonic-gate 		}
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 		*stkp = ls.pr_altstack;
4850Sstevel@tonic-gate 	} else {
4860Sstevel@tonic-gate 		lwp_info_t *lwp;
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 		if ((lwp = getlwpcore(P, lwpid)) == NULL)
4890Sstevel@tonic-gate 			return (-1);
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 		if (lwp->lwp_status.pr_altstack.ss_flags & SS_DISABLE) {
4920Sstevel@tonic-gate 			errno = ENODATA;
4930Sstevel@tonic-gate 			return (-1);
4940Sstevel@tonic-gate 		}
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 		*stkp = lwp->lwp_status.pr_altstack;
4970Sstevel@tonic-gate 	}
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 	return (0);
5000Sstevel@tonic-gate }
501