17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
59acbbeafSnn35248 * Common Development and Distribution License (the "License").
69acbbeafSnn35248 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
229acbbeafSnn35248 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
26f971a346SBryan Cantrill /*
27ab618543SJohn Levon * Copyright 2018 Joyent, Inc.
282a12f85aSJeremy Jones * Copyright (c) 2013 by Delphix. All rights reserved.
29*ed093b41SRobert Mustacchi * Copyright 2023 Oxide Computer Company
30f971a346SBryan Cantrill */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/uio.h>
347c478bd9Sstevel@tonic-gate #include <string.h>
357c478bd9Sstevel@tonic-gate #include <errno.h>
369acbbeafSnn35248 #include <limits.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate #include "Pcontrol.h"
397c478bd9Sstevel@tonic-gate #include "P32ton.h"
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate * This file implements the routines to read and write per-lwp register
43*ed093b41SRobert Mustacchi * information from either a live process or core file opened with libproc. We
44*ed093b41SRobert Mustacchi * build up a few common routines for reading and writing register information,
45*ed093b41SRobert Mustacchi * and then the public functions are all trivial calls to these. It also
46*ed093b41SRobert Mustacchi * implements similar logic that is used with an lwp handle.
47*ed093b41SRobert Mustacchi *
48*ed093b41SRobert Mustacchi * The primary registers and floating point registers (e.g. regs,fpregs) are
49*ed093b41SRobert Mustacchi * retreived from the lwp and process status files. The library caches the
50*ed093b41SRobert Mustacchi * values of these files. When we perorm updates, we ensure that cached copies
51*ed093b41SRobert Mustacchi * are refreshed or updated as part of this.
527c478bd9Sstevel@tonic-gate */
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate * Utility function to return a pointer to the structure of cached information
567c478bd9Sstevel@tonic-gate * about an lwp in the core file, given its lwpid.
577c478bd9Sstevel@tonic-gate */
587c478bd9Sstevel@tonic-gate static lwp_info_t *
getlwpcore(struct ps_prochandle * P,lwpid_t lwpid)597c478bd9Sstevel@tonic-gate getlwpcore(struct ps_prochandle *P, lwpid_t lwpid)
607c478bd9Sstevel@tonic-gate {
612a12f85aSJeremy Jones core_info_t *core = P->data;
6250d4d24eSRobert Mustacchi lwp_info_t *lwp;
637c478bd9Sstevel@tonic-gate
6450d4d24eSRobert Mustacchi for (lwp = list_head(&core->core_lwp_head); lwp != NULL;
6550d4d24eSRobert Mustacchi lwp = list_next(&core->core_lwp_head, lwp)) {
667c478bd9Sstevel@tonic-gate if (lwp->lwp_id == lwpid)
677c478bd9Sstevel@tonic-gate return (lwp);
687c478bd9Sstevel@tonic-gate }
697c478bd9Sstevel@tonic-gate
70*ed093b41SRobert Mustacchi errno = ENOENT;
717c478bd9Sstevel@tonic-gate return (NULL);
727c478bd9Sstevel@tonic-gate }
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate * Utility function to open and read the contents of a per-lwp /proc file.
76*ed093b41SRobert Mustacchi * This function is used to slurp in lwpstatus, lwpname, lwpsinfo, spymaster,
77*ed093b41SRobert Mustacchi * and others.
787c478bd9Sstevel@tonic-gate */
797c478bd9Sstevel@tonic-gate static int
getlwpfile(struct ps_prochandle * P,lwpid_t lwpid,const char * fbase,void * rp,size_t n)807c478bd9Sstevel@tonic-gate getlwpfile(struct ps_prochandle *P, lwpid_t lwpid,
817c478bd9Sstevel@tonic-gate const char *fbase, void *rp, size_t n)
827c478bd9Sstevel@tonic-gate {
839acbbeafSnn35248 char fname[PATH_MAX];
847c478bd9Sstevel@tonic-gate int fd;
857c478bd9Sstevel@tonic-gate
869acbbeafSnn35248 (void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%d/%s",
879acbbeafSnn35248 procfs_path, (int)P->status.pr_pid, (int)lwpid, fbase);
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate if ((fd = open(fname, O_RDONLY)) >= 0) {
907c478bd9Sstevel@tonic-gate if (read(fd, rp, n) > 0) {
917c478bd9Sstevel@tonic-gate (void) close(fd);
927c478bd9Sstevel@tonic-gate return (0);
937c478bd9Sstevel@tonic-gate }
94*ed093b41SRobert Mustacchi
95*ed093b41SRobert Mustacchi int e = errno;
967c478bd9Sstevel@tonic-gate (void) close(fd);
97*ed093b41SRobert Mustacchi errno = e;
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate return (-1);
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate /*
103*ed093b41SRobert Mustacchi * This is a variant of getlwpfile that has three different semantics:
104*ed093b41SRobert Mustacchi *
105*ed093b41SRobert Mustacchi * o It will stat the file to determine the size and allocate that for the
106*ed093b41SRobert Mustacchi * caller.
107*ed093b41SRobert Mustacchi * o If the stat size is zero (e.g. traditional xregs behavior when
108*ed093b41SRobert Mustacchi * unsupported) then it will return the libproc ENODATA error.
109*ed093b41SRobert Mustacchi * o It is an error if not all the data is read.
110*ed093b41SRobert Mustacchi *
111*ed093b41SRobert Mustacchi * Currently this is just used by xregs.
112*ed093b41SRobert Mustacchi */
113*ed093b41SRobert Mustacchi static int
getlwpfile_alloc(struct ps_prochandle * P,lwpid_t lwpid,const char * fbase,void ** datap,size_t * sizep)114*ed093b41SRobert Mustacchi getlwpfile_alloc(struct ps_prochandle *P, lwpid_t lwpid, const char *fbase,
115*ed093b41SRobert Mustacchi void **datap, size_t *sizep)
116*ed093b41SRobert Mustacchi {
117*ed093b41SRobert Mustacchi char fname[PATH_MAX];
118*ed093b41SRobert Mustacchi int fd;
119*ed093b41SRobert Mustacchi
120*ed093b41SRobert Mustacchi (void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%d/%s",
121*ed093b41SRobert Mustacchi procfs_path, (int)P->status.pr_pid, (int)lwpid, fbase);
122*ed093b41SRobert Mustacchi
123*ed093b41SRobert Mustacchi if ((fd = open(fname, O_RDONLY)) >= 0) {
124*ed093b41SRobert Mustacchi int e;
125*ed093b41SRobert Mustacchi struct stat st;
126*ed093b41SRobert Mustacchi
127*ed093b41SRobert Mustacchi if (fstat(fd, &st) == 0) {
128*ed093b41SRobert Mustacchi prxregset_t *prx;
129*ed093b41SRobert Mustacchi
130*ed093b41SRobert Mustacchi if (st.st_size == 0) {
131*ed093b41SRobert Mustacchi errno = ENODATA;
132*ed093b41SRobert Mustacchi goto clean;
133*ed093b41SRobert Mustacchi }
134*ed093b41SRobert Mustacchi
135*ed093b41SRobert Mustacchi prx = malloc(st.st_size);
136*ed093b41SRobert Mustacchi if (prx == NULL) {
137*ed093b41SRobert Mustacchi goto clean;
138*ed093b41SRobert Mustacchi }
139*ed093b41SRobert Mustacchi
140*ed093b41SRobert Mustacchi if (read(fd, prx, st.st_size) == st.st_size) {
141*ed093b41SRobert Mustacchi (void) close(fd);
142*ed093b41SRobert Mustacchi *datap = prx;
143*ed093b41SRobert Mustacchi *sizep = st.st_size;
144*ed093b41SRobert Mustacchi return (0);
145*ed093b41SRobert Mustacchi }
146*ed093b41SRobert Mustacchi
147*ed093b41SRobert Mustacchi free(prx);
148*ed093b41SRobert Mustacchi }
149*ed093b41SRobert Mustacchi clean:
150*ed093b41SRobert Mustacchi e = errno;
151*ed093b41SRobert Mustacchi (void) close(fd);
152*ed093b41SRobert Mustacchi errno = e;
153*ed093b41SRobert Mustacchi }
154*ed093b41SRobert Mustacchi
155*ed093b41SRobert Mustacchi return (-1);
156*ed093b41SRobert Mustacchi }
157*ed093b41SRobert Mustacchi
158*ed093b41SRobert Mustacchi /*
1597c478bd9Sstevel@tonic-gate * Get the lwpstatus_t for an lwp from either the live process or our
1607c478bd9Sstevel@tonic-gate * cached information from the core file. This is used to get the
1617c478bd9Sstevel@tonic-gate * general-purpose registers or floating point registers.
1627c478bd9Sstevel@tonic-gate */
1637c478bd9Sstevel@tonic-gate int
getlwpstatus(struct ps_prochandle * P,lwpid_t lwpid,lwpstatus_t * lps)1647c478bd9Sstevel@tonic-gate getlwpstatus(struct ps_prochandle *P, lwpid_t lwpid, lwpstatus_t *lps)
1657c478bd9Sstevel@tonic-gate {
1667c478bd9Sstevel@tonic-gate lwp_info_t *lwp;
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate /*
1697c478bd9Sstevel@tonic-gate * For both live processes and cores, our job is easy if the lwpid
1707c478bd9Sstevel@tonic-gate * matches that of the representative lwp:
1717c478bd9Sstevel@tonic-gate */
1727c478bd9Sstevel@tonic-gate if (P->status.pr_lwp.pr_lwpid == lwpid) {
1737c478bd9Sstevel@tonic-gate (void) memcpy(lps, &P->status.pr_lwp, sizeof (lwpstatus_t));
1747c478bd9Sstevel@tonic-gate return (0);
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate /*
1787c478bd9Sstevel@tonic-gate * If this is a live process, then just read the information out
1797c478bd9Sstevel@tonic-gate * of the per-lwp status file:
1807c478bd9Sstevel@tonic-gate */
1817c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) {
1827c478bd9Sstevel@tonic-gate return (getlwpfile(P, lwpid, "lwpstatus",
1837c478bd9Sstevel@tonic-gate lps, sizeof (lwpstatus_t)));
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate /*
1877c478bd9Sstevel@tonic-gate * If this is a core file, we need to iterate through our list of
1887c478bd9Sstevel@tonic-gate * cached lwp information and then copy out the status.
1897c478bd9Sstevel@tonic-gate */
1902a12f85aSJeremy Jones if (P->data != NULL && (lwp = getlwpcore(P, lwpid)) != NULL) {
1917c478bd9Sstevel@tonic-gate (void) memcpy(lps, &lwp->lwp_status, sizeof (lwpstatus_t));
1927c478bd9Sstevel@tonic-gate return (0);
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate return (-1);
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate /*
199*ed093b41SRobert Mustacchi * libproc caches information about the registers for representative LWPs and
200*ed093b41SRobert Mustacchi * threads which we have the thread handle for. When we do a write to certain
201*ed093b41SRobert Mustacchi * files, we need to refresh state and take care of both the process and the
202*ed093b41SRobert Mustacchi * representative LWP's info. Because the xregs may or may not mutate the state
203*ed093b41SRobert Mustacchi * of the other regsiters, we just always do a refresh of the entire cached
204*ed093b41SRobert Mustacchi * psinfo.
205*ed093b41SRobert Mustacchi */
206*ed093b41SRobert Mustacchi static void
refresh_status(struct ps_prochandle * P,lwpid_t lwpid,struct ps_lwphandle * L,long cmd,const void * rp,size_t n)207*ed093b41SRobert Mustacchi refresh_status(struct ps_prochandle *P, lwpid_t lwpid, struct ps_lwphandle *L,
208*ed093b41SRobert Mustacchi long cmd, const void *rp, size_t n)
209*ed093b41SRobert Mustacchi {
210*ed093b41SRobert Mustacchi if (P->status.pr_lwp.pr_lwpid == lwpid) {
211*ed093b41SRobert Mustacchi if (cmd == PCSREG)
212*ed093b41SRobert Mustacchi (void) memcpy(P->status.pr_lwp.pr_reg, rp, n);
213*ed093b41SRobert Mustacchi else if (cmd == PCSFPREG)
214*ed093b41SRobert Mustacchi (void) memcpy(&P->status.pr_lwp.pr_fpreg, rp, n);
215*ed093b41SRobert Mustacchi else if (cmd == PCSXREG)
216*ed093b41SRobert Mustacchi (void) Pstopstatus(P, PCNULL, 0);
217*ed093b41SRobert Mustacchi }
218*ed093b41SRobert Mustacchi
219*ed093b41SRobert Mustacchi if (L != NULL) {
220*ed093b41SRobert Mustacchi if (cmd == PCSREG)
221*ed093b41SRobert Mustacchi (void) memcpy(&L->lwp_status.pr_reg, rp, n);
222*ed093b41SRobert Mustacchi else if (cmd == PCSFPREG)
223*ed093b41SRobert Mustacchi (void) memcpy(&L->lwp_status.pr_fpreg, rp, n);
224*ed093b41SRobert Mustacchi else if (cmd == PCSXREG)
225*ed093b41SRobert Mustacchi (void) Lstopstatus(L, PCNULL, 0);
226*ed093b41SRobert Mustacchi }
227*ed093b41SRobert Mustacchi }
228*ed093b41SRobert Mustacchi
229*ed093b41SRobert Mustacchi /*
2307c478bd9Sstevel@tonic-gate * Utility function to modify lwp registers. This is done using either the
231*ed093b41SRobert Mustacchi * process control file or per-lwp control file as necessary. This assumes that
232*ed093b41SRobert Mustacchi * we have a process-level hold on things, which may not always be true.
2337c478bd9Sstevel@tonic-gate */
2347c478bd9Sstevel@tonic-gate static int
setlwpregs_proc(struct ps_prochandle * P,lwpid_t lwpid,long cmd,const void * rp,size_t n)235*ed093b41SRobert Mustacchi setlwpregs_proc(struct ps_prochandle *P, lwpid_t lwpid, long cmd,
2367c478bd9Sstevel@tonic-gate const void *rp, size_t n)
2377c478bd9Sstevel@tonic-gate {
2387c478bd9Sstevel@tonic-gate iovec_t iov[2];
2399acbbeafSnn35248 char fname[PATH_MAX];
240*ed093b41SRobert Mustacchi struct ps_lwphandle *L;
241*ed093b41SRobert Mustacchi int fd = -1;
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate if (P->state != PS_STOP) {
2447c478bd9Sstevel@tonic-gate errno = EBUSY;
2457c478bd9Sstevel@tonic-gate return (-1);
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate iov[0].iov_base = (caddr_t)&cmd;
2497c478bd9Sstevel@tonic-gate iov[0].iov_len = sizeof (long);
2507c478bd9Sstevel@tonic-gate iov[1].iov_base = (caddr_t)rp;
2517c478bd9Sstevel@tonic-gate iov[1].iov_len = n;
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate /*
254*ed093b41SRobert Mustacchi * If we have an lwp handle for this thread, then make sure that we use
255*ed093b41SRobert Mustacchi * that to update the state so cached information is updated. We sync
256*ed093b41SRobert Mustacchi * the thread ahead of the process.
257*ed093b41SRobert Mustacchi */
258*ed093b41SRobert Mustacchi if ((L = Lfind(P, lwpid)) != NULL) {
259*ed093b41SRobert Mustacchi Lsync(L);
260*ed093b41SRobert Mustacchi fd = L->lwp_ctlfd;
261*ed093b41SRobert Mustacchi }
262*ed093b41SRobert Mustacchi
263*ed093b41SRobert Mustacchi /*
2647c478bd9Sstevel@tonic-gate * Writing the process control file writes the representative lwp.
2657c478bd9Sstevel@tonic-gate * Psync before we write to make sure we are consistent with the
2667c478bd9Sstevel@tonic-gate * primary interfaces. Similarly, make sure to update P->status
267*ed093b41SRobert Mustacchi * afterward if we are modifying one of its register sets. On some
268*ed093b41SRobert Mustacchi * platforms the xregs cover the base integer or floating point
269*ed093b41SRobert Mustacchi * registers. As a result, always refresh the representative LWP's
270*ed093b41SRobert Mustacchi * status.
2717c478bd9Sstevel@tonic-gate */
2727c478bd9Sstevel@tonic-gate if (P->status.pr_lwp.pr_lwpid == lwpid) {
2737c478bd9Sstevel@tonic-gate Psync(P);
274*ed093b41SRobert Mustacchi fd = P->ctlfd;
275*ed093b41SRobert Mustacchi }
2767c478bd9Sstevel@tonic-gate
277*ed093b41SRobert Mustacchi if (fd > -1) {
278*ed093b41SRobert Mustacchi if (writev(fd, iov, 2) == -1)
2797c478bd9Sstevel@tonic-gate return (-1);
280*ed093b41SRobert Mustacchi refresh_status(P, lwpid, L, cmd, rp, n);
2817c478bd9Sstevel@tonic-gate return (0);
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate * If the lwp we want is not the representative lwp, we need to
2867c478bd9Sstevel@tonic-gate * open the ctl file for that specific lwp.
2877c478bd9Sstevel@tonic-gate */
2889acbbeafSnn35248 (void) snprintf(fname, sizeof (fname), "%s/%d/lwp/%d/lwpctl",
2899acbbeafSnn35248 procfs_path, (int)P->status.pr_pid, (int)lwpid);
2907c478bd9Sstevel@tonic-gate
2917c478bd9Sstevel@tonic-gate if ((fd = open(fname, O_WRONLY)) >= 0) {
2927c478bd9Sstevel@tonic-gate if (writev(fd, iov, 2) > 0) {
2937c478bd9Sstevel@tonic-gate (void) close(fd);
2947c478bd9Sstevel@tonic-gate return (0);
2957c478bd9Sstevel@tonic-gate }
296*ed093b41SRobert Mustacchi int e = errno;
2977c478bd9Sstevel@tonic-gate (void) close(fd);
298*ed093b41SRobert Mustacchi errno = e;
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate return (-1);
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate
303*ed093b41SRobert Mustacchi /*
304*ed093b41SRobert Mustacchi * This is a variant of the above that only assumes we have a hold on the thread
305*ed093b41SRobert Mustacchi * as opposed to a process.
306*ed093b41SRobert Mustacchi */
307*ed093b41SRobert Mustacchi static int
setlwpregs_lwp(struct ps_lwphandle * L,long cmd,const void * rp,size_t n)308*ed093b41SRobert Mustacchi setlwpregs_lwp(struct ps_lwphandle *L, long cmd, const void *rp, size_t n)
309*ed093b41SRobert Mustacchi {
310*ed093b41SRobert Mustacchi iovec_t iov[2];
311*ed093b41SRobert Mustacchi
312*ed093b41SRobert Mustacchi if (L->lwp_state != PS_STOP) {
313*ed093b41SRobert Mustacchi errno = EBUSY;
314*ed093b41SRobert Mustacchi return (-1);
315*ed093b41SRobert Mustacchi }
316*ed093b41SRobert Mustacchi
317*ed093b41SRobert Mustacchi iov[0].iov_base = (caddr_t)&cmd;
318*ed093b41SRobert Mustacchi iov[0].iov_len = sizeof (long);
319*ed093b41SRobert Mustacchi iov[1].iov_base = (caddr_t)rp;
320*ed093b41SRobert Mustacchi iov[1].iov_len = n;
321*ed093b41SRobert Mustacchi
322*ed093b41SRobert Mustacchi Lsync(L);
323*ed093b41SRobert Mustacchi if (writev(L->lwp_ctlfd, iov, 2) == -1)
324*ed093b41SRobert Mustacchi return (-1);
325*ed093b41SRobert Mustacchi refresh_status(L->lwp_proc, L->lwp_id, L, cmd, rp, n);
326*ed093b41SRobert Mustacchi
327*ed093b41SRobert Mustacchi return (0);
328*ed093b41SRobert Mustacchi }
329*ed093b41SRobert Mustacchi
3307c478bd9Sstevel@tonic-gate int
Plwp_getregs(struct ps_prochandle * P,lwpid_t lwpid,prgregset_t gregs)3317c478bd9Sstevel@tonic-gate Plwp_getregs(struct ps_prochandle *P, lwpid_t lwpid, prgregset_t gregs)
3327c478bd9Sstevel@tonic-gate {
3337c478bd9Sstevel@tonic-gate lwpstatus_t lps;
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate if (getlwpstatus(P, lwpid, &lps) == -1)
3367c478bd9Sstevel@tonic-gate return (-1);
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate (void) memcpy(gregs, lps.pr_reg, sizeof (prgregset_t));
3397c478bd9Sstevel@tonic-gate return (0);
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate
3427c478bd9Sstevel@tonic-gate int
Lgetregs(struct ps_lwphandle * L,prgregset_t * gregs)343*ed093b41SRobert Mustacchi Lgetregs(struct ps_lwphandle *L, prgregset_t *gregs)
344*ed093b41SRobert Mustacchi {
345*ed093b41SRobert Mustacchi (void) memcpy(gregs, L->lwp_status.pr_reg, sizeof (prgregset_t));
346*ed093b41SRobert Mustacchi return (0);
347*ed093b41SRobert Mustacchi }
348*ed093b41SRobert Mustacchi
349*ed093b41SRobert Mustacchi int
Plwp_setregs(struct ps_prochandle * P,lwpid_t lwpid,const prgregset_t gregs)3507c478bd9Sstevel@tonic-gate Plwp_setregs(struct ps_prochandle *P, lwpid_t lwpid, const prgregset_t gregs)
3517c478bd9Sstevel@tonic-gate {
352*ed093b41SRobert Mustacchi return (setlwpregs_proc(P, lwpid, PCSREG, gregs, sizeof (prgregset_t)));
353*ed093b41SRobert Mustacchi }
354*ed093b41SRobert Mustacchi
355*ed093b41SRobert Mustacchi int
Lsetregs(struct ps_lwphandle * L,const prgregset_t * gregs)356*ed093b41SRobert Mustacchi Lsetregs(struct ps_lwphandle *L, const prgregset_t *gregs)
357*ed093b41SRobert Mustacchi {
358*ed093b41SRobert Mustacchi return (setlwpregs_lwp(L, PCSREG, gregs, sizeof (prgregset_t)));
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gate int
Plwp_getfpregs(struct ps_prochandle * P,lwpid_t lwpid,prfpregset_t * fpregs)3627c478bd9Sstevel@tonic-gate Plwp_getfpregs(struct ps_prochandle *P, lwpid_t lwpid, prfpregset_t *fpregs)
3637c478bd9Sstevel@tonic-gate {
3647c478bd9Sstevel@tonic-gate lwpstatus_t lps;
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate if (getlwpstatus(P, lwpid, &lps) == -1)
3677c478bd9Sstevel@tonic-gate return (-1);
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate (void) memcpy(fpregs, &lps.pr_fpreg, sizeof (prfpregset_t));
3707c478bd9Sstevel@tonic-gate return (0);
3717c478bd9Sstevel@tonic-gate }
3727c478bd9Sstevel@tonic-gate
373*ed093b41SRobert Mustacchi int
Lgetfpregs(struct ps_lwphandle * L,prfpregset_t * fpregs)374*ed093b41SRobert Mustacchi Lgetfpregs(struct ps_lwphandle *L, prfpregset_t *fpregs)
3757c478bd9Sstevel@tonic-gate {
376*ed093b41SRobert Mustacchi (void) memcpy(fpregs, &L->lwp_status.pr_fpreg, sizeof (prfpregset_t));
377*ed093b41SRobert Mustacchi return (0);
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate int
Plwp_setfpregs(struct ps_prochandle * P,lwpid_t lwpid,const prfpregset_t * fpregs)381*ed093b41SRobert Mustacchi Plwp_setfpregs(struct ps_prochandle *P, lwpid_t lwpid,
382*ed093b41SRobert Mustacchi const prfpregset_t *fpregs)
383*ed093b41SRobert Mustacchi {
384*ed093b41SRobert Mustacchi return (setlwpregs_proc(P, lwpid, PCSFPREG, fpregs,
385*ed093b41SRobert Mustacchi sizeof (prfpregset_t)));
386*ed093b41SRobert Mustacchi }
387*ed093b41SRobert Mustacchi
388*ed093b41SRobert Mustacchi int
Lsetfpregs(struct ps_lwphandle * L,const prfpregset_t * fpregs)389*ed093b41SRobert Mustacchi Lsetfpregs(struct ps_lwphandle *L, const prfpregset_t *fpregs)
390*ed093b41SRobert Mustacchi {
391*ed093b41SRobert Mustacchi return (setlwpregs_lwp(L, PCSFPREG, fpregs, sizeof (prfpregset_t)));
392*ed093b41SRobert Mustacchi }
393*ed093b41SRobert Mustacchi
394*ed093b41SRobert Mustacchi /*
395*ed093b41SRobert Mustacchi * The reason that this is structured to take both the size and the process
396*ed093b41SRobert Mustacchi * handle is so that way we have enough information to tie this back to its
397*ed093b41SRobert Mustacchi * underlying source and we can eventually use umem with this.
398*ed093b41SRobert Mustacchi */
399*ed093b41SRobert Mustacchi void
Plwp_freexregs(struct ps_prochandle * P __unused,prxregset_t * prx,size_t size __unused)400*ed093b41SRobert Mustacchi Plwp_freexregs(struct ps_prochandle *P __unused, prxregset_t *prx,
401*ed093b41SRobert Mustacchi size_t size __unused)
402*ed093b41SRobert Mustacchi {
403*ed093b41SRobert Mustacchi free(prx);
404*ed093b41SRobert Mustacchi }
405*ed093b41SRobert Mustacchi
406*ed093b41SRobert Mustacchi /*
407*ed093b41SRobert Mustacchi * Get a given thread's lwp registers. If this is a core file, we read it from
408*ed093b41SRobert Mustacchi * the cache. If this is a live process, we always read it from the underlying
409*ed093b41SRobert Mustacchi * file system because we do not currently cache xregs in libproc. sizep is the
410*ed093b41SRobert Mustacchi * resulting size of data we've allocated and for a live process is filled in
411*ed093b41SRobert Mustacchi * based on the /proc stat(2) information.
412*ed093b41SRobert Mustacchi */
413*ed093b41SRobert Mustacchi int
Plwp_getxregs(struct ps_prochandle * P,lwpid_t lwpid,prxregset_t ** xregs,size_t * sizep)414*ed093b41SRobert Mustacchi Plwp_getxregs(struct ps_prochandle *P, lwpid_t lwpid, prxregset_t **xregs,
415*ed093b41SRobert Mustacchi size_t *sizep)
4167c478bd9Sstevel@tonic-gate {
4177c478bd9Sstevel@tonic-gate lwp_info_t *lwp;
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) {
4207c478bd9Sstevel@tonic-gate errno = ENODATA;
4217c478bd9Sstevel@tonic-gate return (-1);
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) {
4257c478bd9Sstevel@tonic-gate if (P->state != PS_STOP) {
4267c478bd9Sstevel@tonic-gate errno = EBUSY;
4277c478bd9Sstevel@tonic-gate return (-1);
4287c478bd9Sstevel@tonic-gate }
4297c478bd9Sstevel@tonic-gate
430*ed093b41SRobert Mustacchi return (getlwpfile_alloc(P, lwpid, "xregs",
431*ed093b41SRobert Mustacchi (void **)xregs, sizep));
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate
434*ed093b41SRobert Mustacchi if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_xregs != NULL &&
435*ed093b41SRobert Mustacchi lwp->lwp_xregsize > 0) {
436*ed093b41SRobert Mustacchi *xregs = malloc(lwp->lwp_xregsize);
437*ed093b41SRobert Mustacchi if (*xregs == NULL)
438*ed093b41SRobert Mustacchi return (-1);
439*ed093b41SRobert Mustacchi (void) memcpy(*xregs, lwp->lwp_xregs, lwp->lwp_xregsize);
440*ed093b41SRobert Mustacchi *sizep = lwp->lwp_xregsize;
4417c478bd9Sstevel@tonic-gate return (0);
4427c478bd9Sstevel@tonic-gate }
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate if (lwp != NULL)
4457c478bd9Sstevel@tonic-gate errno = ENODATA;
4467c478bd9Sstevel@tonic-gate return (-1);
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate
4497c478bd9Sstevel@tonic-gate int
Lgetxregs(struct ps_lwphandle * L,prxregset_t ** xregs,size_t * sizep)450*ed093b41SRobert Mustacchi Lgetxregs(struct ps_lwphandle *L, prxregset_t **xregs, size_t *sizep)
4517c478bd9Sstevel@tonic-gate {
452*ed093b41SRobert Mustacchi lwp_info_t *lwp;
453*ed093b41SRobert Mustacchi
454*ed093b41SRobert Mustacchi if (L->lwp_state != PS_DEAD) {
455*ed093b41SRobert Mustacchi if (L->lwp_state != PS_STOP) {
456*ed093b41SRobert Mustacchi errno = EBUSY;
457*ed093b41SRobert Mustacchi return (-1);
458*ed093b41SRobert Mustacchi }
459*ed093b41SRobert Mustacchi return (getlwpfile_alloc(L->lwp_proc, L->lwp_id, "xregs",
460*ed093b41SRobert Mustacchi (void **)xregs, sizep));
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate
463*ed093b41SRobert Mustacchi if ((lwp = getlwpcore(L->lwp_proc, L->lwp_id)) != NULL &&
464*ed093b41SRobert Mustacchi lwp->lwp_xregs != NULL && lwp->lwp_xregsize > 0) {
465*ed093b41SRobert Mustacchi *xregs = malloc(lwp->lwp_xregsize);
466*ed093b41SRobert Mustacchi if (*xregs == NULL)
467*ed093b41SRobert Mustacchi return (-1);
468*ed093b41SRobert Mustacchi (void) memcpy(*xregs, lwp->lwp_xregs, lwp->lwp_xregsize);
469*ed093b41SRobert Mustacchi *sizep = lwp->lwp_xregsize;
470*ed093b41SRobert Mustacchi return (0);
471*ed093b41SRobert Mustacchi }
472*ed093b41SRobert Mustacchi
473*ed093b41SRobert Mustacchi if (lwp != NULL)
474*ed093b41SRobert Mustacchi errno = ENODATA;
475*ed093b41SRobert Mustacchi return (-1);
476*ed093b41SRobert Mustacchi }
477*ed093b41SRobert Mustacchi
478*ed093b41SRobert Mustacchi int
Plwp_setxregs(struct ps_prochandle * P,lwpid_t lwpid,const prxregset_t * xregs,size_t len)479*ed093b41SRobert Mustacchi Plwp_setxregs(struct ps_prochandle *P, lwpid_t lwpid, const prxregset_t *xregs,
480*ed093b41SRobert Mustacchi size_t len)
481*ed093b41SRobert Mustacchi {
482*ed093b41SRobert Mustacchi return (setlwpregs_proc(P, lwpid, PCSXREG, xregs, len));
483*ed093b41SRobert Mustacchi }
484*ed093b41SRobert Mustacchi
485*ed093b41SRobert Mustacchi int
Lsetxregs(struct ps_lwphandle * L,const prxregset_t * xregs,size_t len)486*ed093b41SRobert Mustacchi Lsetxregs(struct ps_lwphandle *L, const prxregset_t *xregs, size_t len)
487*ed093b41SRobert Mustacchi {
488*ed093b41SRobert Mustacchi return (setlwpregs_lwp(L, PCSXREG, xregs, len));
489*ed093b41SRobert Mustacchi }
490*ed093b41SRobert Mustacchi
491*ed093b41SRobert Mustacchi #if defined(sparc) || defined(__sparc)
4927c478bd9Sstevel@tonic-gate int
Plwp_getgwindows(struct ps_prochandle * P,lwpid_t lwpid,gwindows_t * gwins)4937c478bd9Sstevel@tonic-gate Plwp_getgwindows(struct ps_prochandle *P, lwpid_t lwpid, gwindows_t *gwins)
4947c478bd9Sstevel@tonic-gate {
4957c478bd9Sstevel@tonic-gate lwp_info_t *lwp;
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) {
4987c478bd9Sstevel@tonic-gate errno = ENODATA;
4997c478bd9Sstevel@tonic-gate return (-1);
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) {
5037c478bd9Sstevel@tonic-gate if (P->state != PS_STOP) {
5047c478bd9Sstevel@tonic-gate errno = EBUSY;
5057c478bd9Sstevel@tonic-gate return (-1);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate return (getlwpfile(P, lwpid, "gwindows",
5097c478bd9Sstevel@tonic-gate gwins, sizeof (gwindows_t)));
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_gwins != NULL) {
5137c478bd9Sstevel@tonic-gate *gwins = *lwp->lwp_gwins;
5147c478bd9Sstevel@tonic-gate return (0);
5157c478bd9Sstevel@tonic-gate }
5167c478bd9Sstevel@tonic-gate
5177c478bd9Sstevel@tonic-gate if (lwp != NULL)
5187c478bd9Sstevel@tonic-gate errno = ENODATA;
5197c478bd9Sstevel@tonic-gate return (-1);
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate
5227c478bd9Sstevel@tonic-gate #if defined(__sparcv9)
5237c478bd9Sstevel@tonic-gate int
Plwp_getasrs(struct ps_prochandle * P,lwpid_t lwpid,asrset_t asrs)5247c478bd9Sstevel@tonic-gate Plwp_getasrs(struct ps_prochandle *P, lwpid_t lwpid, asrset_t asrs)
5257c478bd9Sstevel@tonic-gate {
5267c478bd9Sstevel@tonic-gate lwp_info_t *lwp;
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) {
5297c478bd9Sstevel@tonic-gate errno = ENODATA;
5307c478bd9Sstevel@tonic-gate return (-1);
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) {
5347c478bd9Sstevel@tonic-gate if (P->state != PS_STOP) {
5357c478bd9Sstevel@tonic-gate errno = EBUSY;
5367c478bd9Sstevel@tonic-gate return (-1);
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate return (getlwpfile(P, lwpid, "asrs", asrs, sizeof (asrset_t)));
5407c478bd9Sstevel@tonic-gate }
5417c478bd9Sstevel@tonic-gate
5427c478bd9Sstevel@tonic-gate if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_asrs != NULL) {
5437c478bd9Sstevel@tonic-gate (void) memcpy(asrs, lwp->lwp_asrs, sizeof (asrset_t));
5447c478bd9Sstevel@tonic-gate return (0);
5457c478bd9Sstevel@tonic-gate }
5467c478bd9Sstevel@tonic-gate
5477c478bd9Sstevel@tonic-gate if (lwp != NULL)
5487c478bd9Sstevel@tonic-gate errno = ENODATA;
5497c478bd9Sstevel@tonic-gate return (-1);
5507c478bd9Sstevel@tonic-gate
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate int
Plwp_setasrs(struct ps_prochandle * P,lwpid_t lwpid,const asrset_t asrs)5547c478bd9Sstevel@tonic-gate Plwp_setasrs(struct ps_prochandle *P, lwpid_t lwpid, const asrset_t asrs)
5557c478bd9Sstevel@tonic-gate {
556*ed093b41SRobert Mustacchi return (setlwpregs_proc(P, lwpid, PCSASRS, asrs, sizeof (asrset_t)));
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate #endif /* __sparcv9 */
5597c478bd9Sstevel@tonic-gate #endif /* __sparc */
5607c478bd9Sstevel@tonic-gate
5617c478bd9Sstevel@tonic-gate int
Plwp_getpsinfo(struct ps_prochandle * P,lwpid_t lwpid,lwpsinfo_t * lps)5627c478bd9Sstevel@tonic-gate Plwp_getpsinfo(struct ps_prochandle *P, lwpid_t lwpid, lwpsinfo_t *lps)
5637c478bd9Sstevel@tonic-gate {
5647c478bd9Sstevel@tonic-gate lwp_info_t *lwp;
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) {
5677c478bd9Sstevel@tonic-gate errno = ENODATA;
5687c478bd9Sstevel@tonic-gate return (-1);
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate
5717c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) {
5727c478bd9Sstevel@tonic-gate return (getlwpfile(P, lwpid, "lwpsinfo",
5737c478bd9Sstevel@tonic-gate lps, sizeof (lwpsinfo_t)));
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate
5767c478bd9Sstevel@tonic-gate if ((lwp = getlwpcore(P, lwpid)) != NULL) {
5777c478bd9Sstevel@tonic-gate (void) memcpy(lps, &lwp->lwp_psinfo, sizeof (lwpsinfo_t));
5787c478bd9Sstevel@tonic-gate return (0);
5797c478bd9Sstevel@tonic-gate }
5807c478bd9Sstevel@tonic-gate
5817c478bd9Sstevel@tonic-gate return (-1);
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate int
Plwp_getname(struct ps_prochandle * P,lwpid_t lwpid,char * buf,size_t bufsize)585ab618543SJohn Levon Plwp_getname(struct ps_prochandle *P, lwpid_t lwpid,
586ab618543SJohn Levon char *buf, size_t bufsize)
587ab618543SJohn Levon {
588ab618543SJohn Levon char lwpname[THREAD_NAME_MAX];
589ab618543SJohn Levon char *from = NULL;
590ab618543SJohn Levon lwp_info_t *lwp;
591ab618543SJohn Levon
592ab618543SJohn Levon if (P->state == PS_IDLE) {
593ab618543SJohn Levon errno = ENODATA;
594ab618543SJohn Levon return (-1);
595ab618543SJohn Levon }
596ab618543SJohn Levon
597ab618543SJohn Levon if (P->state != PS_DEAD) {
598ab618543SJohn Levon if (getlwpfile(P, lwpid, "lwpname",
599ab618543SJohn Levon lwpname, sizeof (lwpname)) != 0)
600ab618543SJohn Levon return (-1);
601ab618543SJohn Levon from = lwpname;
602ab618543SJohn Levon } else {
603ab618543SJohn Levon if ((lwp = getlwpcore(P, lwpid)) == NULL)
604ab618543SJohn Levon return (-1);
605ab618543SJohn Levon from = lwp->lwp_name;
606ab618543SJohn Levon }
607ab618543SJohn Levon
608ab618543SJohn Levon if (strlcpy(buf, from, bufsize) >= bufsize) {
609ab618543SJohn Levon errno = ENAMETOOLONG;
610ab618543SJohn Levon return (-1);
611ab618543SJohn Levon }
612ab618543SJohn Levon
613ab618543SJohn Levon return (0);
614ab618543SJohn Levon }
615ab618543SJohn Levon
616ab618543SJohn Levon int
Plwp_getspymaster(struct ps_prochandle * P,lwpid_t lwpid,psinfo_t * ps)617f971a346SBryan Cantrill Plwp_getspymaster(struct ps_prochandle *P, lwpid_t lwpid, psinfo_t *ps)
618f971a346SBryan Cantrill {
619f971a346SBryan Cantrill lwpstatus_t lps;
620f971a346SBryan Cantrill
621f971a346SBryan Cantrill if (P->state == PS_IDLE) {
622f971a346SBryan Cantrill errno = ENODATA;
623f971a346SBryan Cantrill return (-1);
624f971a346SBryan Cantrill }
625f971a346SBryan Cantrill
626f971a346SBryan Cantrill if (getlwpstatus(P, lwpid, &lps) != 0)
627f971a346SBryan Cantrill return (-1);
628f971a346SBryan Cantrill
629f971a346SBryan Cantrill if (!(lps.pr_flags & PR_AGENT)) {
630f971a346SBryan Cantrill errno = EINVAL;
631f971a346SBryan Cantrill return (-1);
632f971a346SBryan Cantrill }
633f971a346SBryan Cantrill
634f971a346SBryan Cantrill if (P->state != PS_DEAD) {
635f971a346SBryan Cantrill return (getlwpfile(P, lwpid, "spymaster",
636f971a346SBryan Cantrill ps, sizeof (psinfo_t)));
637f971a346SBryan Cantrill }
638f971a346SBryan Cantrill
639f971a346SBryan Cantrill if (P->spymaster.pr_nlwp != 0) {
640f971a346SBryan Cantrill (void) memcpy(ps, &P->spymaster, sizeof (psinfo_t));
641f971a346SBryan Cantrill return (0);
642f971a346SBryan Cantrill }
643f971a346SBryan Cantrill
644f971a346SBryan Cantrill errno = ENODATA;
645f971a346SBryan Cantrill
646f971a346SBryan Cantrill return (-1);
647f971a346SBryan Cantrill }
648f971a346SBryan Cantrill
649f971a346SBryan Cantrill int
Plwp_stack(struct ps_prochandle * P,lwpid_t lwpid,stack_t * stkp)6507c478bd9Sstevel@tonic-gate Plwp_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp)
6517c478bd9Sstevel@tonic-gate {
6527c478bd9Sstevel@tonic-gate uintptr_t addr;
6537c478bd9Sstevel@tonic-gate
6547c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) {
6557c478bd9Sstevel@tonic-gate errno = ENODATA;
6567c478bd9Sstevel@tonic-gate return (-1);
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate
6597c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) {
6607c478bd9Sstevel@tonic-gate lwpstatus_t ls;
6617c478bd9Sstevel@tonic-gate if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)
6627c478bd9Sstevel@tonic-gate return (-1);
6637c478bd9Sstevel@tonic-gate addr = ls.pr_ustack;
6647c478bd9Sstevel@tonic-gate } else {
6657c478bd9Sstevel@tonic-gate lwp_info_t *lwp;
6667c478bd9Sstevel@tonic-gate if ((lwp = getlwpcore(P, lwpid)) == NULL)
6677c478bd9Sstevel@tonic-gate return (-1);
6687c478bd9Sstevel@tonic-gate addr = lwp->lwp_status.pr_ustack;
6697c478bd9Sstevel@tonic-gate }
6707c478bd9Sstevel@tonic-gate
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
6737c478bd9Sstevel@tonic-gate if (Pread(P, stkp, sizeof (*stkp), addr) != sizeof (*stkp))
6747c478bd9Sstevel@tonic-gate return (-1);
6757c478bd9Sstevel@tonic-gate #ifdef _LP64
6767c478bd9Sstevel@tonic-gate } else {
6777c478bd9Sstevel@tonic-gate stack32_t stk32;
6787c478bd9Sstevel@tonic-gate
6797c478bd9Sstevel@tonic-gate if (Pread(P, &stk32, sizeof (stk32), addr) != sizeof (stk32))
6807c478bd9Sstevel@tonic-gate return (-1);
6817c478bd9Sstevel@tonic-gate
6827c478bd9Sstevel@tonic-gate stack_32_to_n(&stk32, stkp);
6837c478bd9Sstevel@tonic-gate #endif
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate return (0);
6877c478bd9Sstevel@tonic-gate }
6887c478bd9Sstevel@tonic-gate
6897c478bd9Sstevel@tonic-gate int
Plwp_main_stack(struct ps_prochandle * P,lwpid_t lwpid,stack_t * stkp)6907c478bd9Sstevel@tonic-gate Plwp_main_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp)
6917c478bd9Sstevel@tonic-gate {
6927c478bd9Sstevel@tonic-gate uintptr_t addr;
6937c478bd9Sstevel@tonic-gate lwpstatus_t ls;
6947c478bd9Sstevel@tonic-gate
6957c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) {
6967c478bd9Sstevel@tonic-gate errno = ENODATA;
6977c478bd9Sstevel@tonic-gate return (-1);
6987c478bd9Sstevel@tonic-gate }
6997c478bd9Sstevel@tonic-gate
7007c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) {
7017c478bd9Sstevel@tonic-gate if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)
7027c478bd9Sstevel@tonic-gate return (-1);
7037c478bd9Sstevel@tonic-gate } else {
7047c478bd9Sstevel@tonic-gate lwp_info_t *lwp;
7057c478bd9Sstevel@tonic-gate if ((lwp = getlwpcore(P, lwpid)) == NULL)
7067c478bd9Sstevel@tonic-gate return (-1);
7077c478bd9Sstevel@tonic-gate ls = lwp->lwp_status;
7087c478bd9Sstevel@tonic-gate }
7097c478bd9Sstevel@tonic-gate
7107c478bd9Sstevel@tonic-gate addr = ls.pr_ustack;
7117c478bd9Sstevel@tonic-gate
7127c478bd9Sstevel@tonic-gate /*
7137c478bd9Sstevel@tonic-gate * Read out the current stack; if the SS_ONSTACK flag is set then
7147c478bd9Sstevel@tonic-gate * this LWP is operating on the alternate signal stack. We can
7157c478bd9Sstevel@tonic-gate * recover the original stack from pr_oldcontext.
7167c478bd9Sstevel@tonic-gate */
7177c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
7187c478bd9Sstevel@tonic-gate if (Pread(P, stkp, sizeof (*stkp), addr) != sizeof (*stkp))
7197c478bd9Sstevel@tonic-gate return (-1);
7207c478bd9Sstevel@tonic-gate
7217c478bd9Sstevel@tonic-gate if (stkp->ss_flags & SS_ONSTACK)
7227c478bd9Sstevel@tonic-gate goto on_altstack;
7237c478bd9Sstevel@tonic-gate #ifdef _LP64
7247c478bd9Sstevel@tonic-gate } else {
7257c478bd9Sstevel@tonic-gate stack32_t stk32;
7267c478bd9Sstevel@tonic-gate
7277c478bd9Sstevel@tonic-gate if (Pread(P, &stk32, sizeof (stk32), addr) != sizeof (stk32))
7287c478bd9Sstevel@tonic-gate return (-1);
7297c478bd9Sstevel@tonic-gate
7307c478bd9Sstevel@tonic-gate if (stk32.ss_flags & SS_ONSTACK)
7317c478bd9Sstevel@tonic-gate goto on_altstack;
7327c478bd9Sstevel@tonic-gate
7337c478bd9Sstevel@tonic-gate stack_32_to_n(&stk32, stkp);
7347c478bd9Sstevel@tonic-gate #endif
7357c478bd9Sstevel@tonic-gate }
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gate return (0);
7387c478bd9Sstevel@tonic-gate
7397c478bd9Sstevel@tonic-gate on_altstack:
7407c478bd9Sstevel@tonic-gate
7417c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
7427c478bd9Sstevel@tonic-gate ucontext_t *ctxp = (void *)ls.pr_oldcontext;
7437c478bd9Sstevel@tonic-gate
7447c478bd9Sstevel@tonic-gate if (Pread(P, stkp, sizeof (*stkp),
7457c478bd9Sstevel@tonic-gate (uintptr_t)&ctxp->uc_stack) != sizeof (*stkp))
7467c478bd9Sstevel@tonic-gate return (-1);
7477c478bd9Sstevel@tonic-gate #ifdef _LP64
7487c478bd9Sstevel@tonic-gate } else {
7497c478bd9Sstevel@tonic-gate ucontext32_t *ctxp = (void *)ls.pr_oldcontext;
7507c478bd9Sstevel@tonic-gate stack32_t stk32;
7517c478bd9Sstevel@tonic-gate
7527c478bd9Sstevel@tonic-gate if (Pread(P, &stk32, sizeof (stk32),
7537c478bd9Sstevel@tonic-gate (uintptr_t)&ctxp->uc_stack) != sizeof (stk32))
7547c478bd9Sstevel@tonic-gate return (-1);
7557c478bd9Sstevel@tonic-gate
7567c478bd9Sstevel@tonic-gate stack_32_to_n(&stk32, stkp);
7577c478bd9Sstevel@tonic-gate #endif
7587c478bd9Sstevel@tonic-gate }
7597c478bd9Sstevel@tonic-gate
7607c478bd9Sstevel@tonic-gate return (0);
7617c478bd9Sstevel@tonic-gate }
7627c478bd9Sstevel@tonic-gate
7637c478bd9Sstevel@tonic-gate int
Plwp_alt_stack(struct ps_prochandle * P,lwpid_t lwpid,stack_t * stkp)7647c478bd9Sstevel@tonic-gate Plwp_alt_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp)
7657c478bd9Sstevel@tonic-gate {
7667c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) {
7677c478bd9Sstevel@tonic-gate errno = ENODATA;
7687c478bd9Sstevel@tonic-gate return (-1);
7697c478bd9Sstevel@tonic-gate }
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) {
7727c478bd9Sstevel@tonic-gate lwpstatus_t ls;
7737c478bd9Sstevel@tonic-gate
7747c478bd9Sstevel@tonic-gate if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)
7757c478bd9Sstevel@tonic-gate return (-1);
7767c478bd9Sstevel@tonic-gate
7777c478bd9Sstevel@tonic-gate if (ls.pr_altstack.ss_flags & SS_DISABLE) {
7787c478bd9Sstevel@tonic-gate errno = ENODATA;
7797c478bd9Sstevel@tonic-gate return (-1);
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate
7827c478bd9Sstevel@tonic-gate *stkp = ls.pr_altstack;
7837c478bd9Sstevel@tonic-gate } else {
7847c478bd9Sstevel@tonic-gate lwp_info_t *lwp;
7857c478bd9Sstevel@tonic-gate
7867c478bd9Sstevel@tonic-gate if ((lwp = getlwpcore(P, lwpid)) == NULL)
7877c478bd9Sstevel@tonic-gate return (-1);
7887c478bd9Sstevel@tonic-gate
7897c478bd9Sstevel@tonic-gate if (lwp->lwp_status.pr_altstack.ss_flags & SS_DISABLE) {
7907c478bd9Sstevel@tonic-gate errno = ENODATA;
7917c478bd9Sstevel@tonic-gate return (-1);
7927c478bd9Sstevel@tonic-gate }
7937c478bd9Sstevel@tonic-gate
7947c478bd9Sstevel@tonic-gate *stkp = lwp->lwp_status.pr_altstack;
7957c478bd9Sstevel@tonic-gate }
7967c478bd9Sstevel@tonic-gate
7977c478bd9Sstevel@tonic-gate return (0);
7987c478bd9Sstevel@tonic-gate }
799