1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 31*7c478bd9Sstevel@tonic-gate #include <string.h> 32*7c478bd9Sstevel@tonic-gate #include <errno.h> 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include "Pcontrol.h" 35*7c478bd9Sstevel@tonic-gate #include "P32ton.h" 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate /* 38*7c478bd9Sstevel@tonic-gate * This file implements the routines to read and write per-lwp register 39*7c478bd9Sstevel@tonic-gate * information from either a live process or core file opened with libproc. 40*7c478bd9Sstevel@tonic-gate * We build up a few common routines for reading and writing register 41*7c478bd9Sstevel@tonic-gate * information, and then the public functions are all trivial calls to these. 42*7c478bd9Sstevel@tonic-gate */ 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate /* 45*7c478bd9Sstevel@tonic-gate * Utility function to return a pointer to the structure of cached information 46*7c478bd9Sstevel@tonic-gate * about an lwp in the core file, given its lwpid. 47*7c478bd9Sstevel@tonic-gate */ 48*7c478bd9Sstevel@tonic-gate static lwp_info_t * 49*7c478bd9Sstevel@tonic-gate getlwpcore(struct ps_prochandle *P, lwpid_t lwpid) 50*7c478bd9Sstevel@tonic-gate { 51*7c478bd9Sstevel@tonic-gate lwp_info_t *lwp = list_next(&P->core->core_lwp_head); 52*7c478bd9Sstevel@tonic-gate uint_t i; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate for (i = 0; i < P->core->core_nlwp; i++, lwp = list_next(lwp)) { 55*7c478bd9Sstevel@tonic-gate if (lwp->lwp_id == lwpid) 56*7c478bd9Sstevel@tonic-gate return (lwp); 57*7c478bd9Sstevel@tonic-gate } 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate errno = EINVAL; 60*7c478bd9Sstevel@tonic-gate return (NULL); 61*7c478bd9Sstevel@tonic-gate } 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate /* 64*7c478bd9Sstevel@tonic-gate * Utility function to open and read the contents of a per-lwp /proc file. 65*7c478bd9Sstevel@tonic-gate * This function is used to slurp in lwpstatus, xregs, and asrs. 66*7c478bd9Sstevel@tonic-gate */ 67*7c478bd9Sstevel@tonic-gate static int 68*7c478bd9Sstevel@tonic-gate getlwpfile(struct ps_prochandle *P, lwpid_t lwpid, 69*7c478bd9Sstevel@tonic-gate const char *fbase, void *rp, size_t n) 70*7c478bd9Sstevel@tonic-gate { 71*7c478bd9Sstevel@tonic-gate char fname[64]; 72*7c478bd9Sstevel@tonic-gate int fd; 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate (void) snprintf(fname, sizeof (fname), "/proc/%d/lwp/%d/%s", 75*7c478bd9Sstevel@tonic-gate (int)P->status.pr_pid, (int)lwpid, fbase); 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate if ((fd = open(fname, O_RDONLY)) >= 0) { 78*7c478bd9Sstevel@tonic-gate if (read(fd, rp, n) > 0) { 79*7c478bd9Sstevel@tonic-gate (void) close(fd); 80*7c478bd9Sstevel@tonic-gate return (0); 81*7c478bd9Sstevel@tonic-gate } 82*7c478bd9Sstevel@tonic-gate (void) close(fd); 83*7c478bd9Sstevel@tonic-gate } 84*7c478bd9Sstevel@tonic-gate return (-1); 85*7c478bd9Sstevel@tonic-gate } 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate /* 88*7c478bd9Sstevel@tonic-gate * Get the lwpstatus_t for an lwp from either the live process or our 89*7c478bd9Sstevel@tonic-gate * cached information from the core file. This is used to get the 90*7c478bd9Sstevel@tonic-gate * general-purpose registers or floating point registers. 91*7c478bd9Sstevel@tonic-gate */ 92*7c478bd9Sstevel@tonic-gate int 93*7c478bd9Sstevel@tonic-gate getlwpstatus(struct ps_prochandle *P, lwpid_t lwpid, lwpstatus_t *lps) 94*7c478bd9Sstevel@tonic-gate { 95*7c478bd9Sstevel@tonic-gate lwp_info_t *lwp; 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate /* 98*7c478bd9Sstevel@tonic-gate * For both live processes and cores, our job is easy if the lwpid 99*7c478bd9Sstevel@tonic-gate * matches that of the representative lwp: 100*7c478bd9Sstevel@tonic-gate */ 101*7c478bd9Sstevel@tonic-gate if (P->status.pr_lwp.pr_lwpid == lwpid) { 102*7c478bd9Sstevel@tonic-gate (void) memcpy(lps, &P->status.pr_lwp, sizeof (lwpstatus_t)); 103*7c478bd9Sstevel@tonic-gate return (0); 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate /* 107*7c478bd9Sstevel@tonic-gate * If this is a live process, then just read the information out 108*7c478bd9Sstevel@tonic-gate * of the per-lwp status file: 109*7c478bd9Sstevel@tonic-gate */ 110*7c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) { 111*7c478bd9Sstevel@tonic-gate return (getlwpfile(P, lwpid, "lwpstatus", 112*7c478bd9Sstevel@tonic-gate lps, sizeof (lwpstatus_t))); 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate /* 116*7c478bd9Sstevel@tonic-gate * If this is a core file, we need to iterate through our list of 117*7c478bd9Sstevel@tonic-gate * cached lwp information and then copy out the status. 118*7c478bd9Sstevel@tonic-gate */ 119*7c478bd9Sstevel@tonic-gate if (P->core != NULL && (lwp = getlwpcore(P, lwpid)) != NULL) { 120*7c478bd9Sstevel@tonic-gate (void) memcpy(lps, &lwp->lwp_status, sizeof (lwpstatus_t)); 121*7c478bd9Sstevel@tonic-gate return (0); 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate return (-1); 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* 128*7c478bd9Sstevel@tonic-gate * Utility function to modify lwp registers. This is done using either the 129*7c478bd9Sstevel@tonic-gate * process control file or per-lwp control file as necessary. 130*7c478bd9Sstevel@tonic-gate */ 131*7c478bd9Sstevel@tonic-gate static int 132*7c478bd9Sstevel@tonic-gate setlwpregs(struct ps_prochandle *P, lwpid_t lwpid, long cmd, 133*7c478bd9Sstevel@tonic-gate const void *rp, size_t n) 134*7c478bd9Sstevel@tonic-gate { 135*7c478bd9Sstevel@tonic-gate iovec_t iov[2]; 136*7c478bd9Sstevel@tonic-gate char fname[64]; 137*7c478bd9Sstevel@tonic-gate int fd; 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate if (P->state != PS_STOP) { 140*7c478bd9Sstevel@tonic-gate errno = EBUSY; 141*7c478bd9Sstevel@tonic-gate return (-1); 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate iov[0].iov_base = (caddr_t)&cmd; 145*7c478bd9Sstevel@tonic-gate iov[0].iov_len = sizeof (long); 146*7c478bd9Sstevel@tonic-gate iov[1].iov_base = (caddr_t)rp; 147*7c478bd9Sstevel@tonic-gate iov[1].iov_len = n; 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate /* 150*7c478bd9Sstevel@tonic-gate * Writing the process control file writes the representative lwp. 151*7c478bd9Sstevel@tonic-gate * Psync before we write to make sure we are consistent with the 152*7c478bd9Sstevel@tonic-gate * primary interfaces. Similarly, make sure to update P->status 153*7c478bd9Sstevel@tonic-gate * afterward if we are modifying one of its register sets. 154*7c478bd9Sstevel@tonic-gate */ 155*7c478bd9Sstevel@tonic-gate if (P->status.pr_lwp.pr_lwpid == lwpid) { 156*7c478bd9Sstevel@tonic-gate Psync(P); 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate if (writev(P->ctlfd, iov, 2) == -1) 159*7c478bd9Sstevel@tonic-gate return (-1); 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate if (cmd == PCSREG) 162*7c478bd9Sstevel@tonic-gate (void) memcpy(P->status.pr_lwp.pr_reg, rp, n); 163*7c478bd9Sstevel@tonic-gate else if (cmd == PCSFPREG) 164*7c478bd9Sstevel@tonic-gate (void) memcpy(&P->status.pr_lwp.pr_fpreg, rp, n); 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate return (0); 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate /* 170*7c478bd9Sstevel@tonic-gate * If the lwp we want is not the representative lwp, we need to 171*7c478bd9Sstevel@tonic-gate * open the ctl file for that specific lwp. 172*7c478bd9Sstevel@tonic-gate */ 173*7c478bd9Sstevel@tonic-gate (void) snprintf(fname, sizeof (fname), "/proc/%d/lwp/%d/lwpctl", 174*7c478bd9Sstevel@tonic-gate (int)P->status.pr_pid, (int)lwpid); 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate if ((fd = open(fname, O_WRONLY)) >= 0) { 177*7c478bd9Sstevel@tonic-gate if (writev(fd, iov, 2) > 0) { 178*7c478bd9Sstevel@tonic-gate (void) close(fd); 179*7c478bd9Sstevel@tonic-gate return (0); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate (void) close(fd); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate return (-1); 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate int 187*7c478bd9Sstevel@tonic-gate Plwp_getregs(struct ps_prochandle *P, lwpid_t lwpid, prgregset_t gregs) 188*7c478bd9Sstevel@tonic-gate { 189*7c478bd9Sstevel@tonic-gate lwpstatus_t lps; 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate if (getlwpstatus(P, lwpid, &lps) == -1) 192*7c478bd9Sstevel@tonic-gate return (-1); 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate (void) memcpy(gregs, lps.pr_reg, sizeof (prgregset_t)); 195*7c478bd9Sstevel@tonic-gate return (0); 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate int 199*7c478bd9Sstevel@tonic-gate Plwp_setregs(struct ps_prochandle *P, lwpid_t lwpid, const prgregset_t gregs) 200*7c478bd9Sstevel@tonic-gate { 201*7c478bd9Sstevel@tonic-gate return (setlwpregs(P, lwpid, PCSREG, gregs, sizeof (prgregset_t))); 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate int 205*7c478bd9Sstevel@tonic-gate Plwp_getfpregs(struct ps_prochandle *P, lwpid_t lwpid, prfpregset_t *fpregs) 206*7c478bd9Sstevel@tonic-gate { 207*7c478bd9Sstevel@tonic-gate lwpstatus_t lps; 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate if (getlwpstatus(P, lwpid, &lps) == -1) 210*7c478bd9Sstevel@tonic-gate return (-1); 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate (void) memcpy(fpregs, &lps.pr_fpreg, sizeof (prfpregset_t)); 213*7c478bd9Sstevel@tonic-gate return (0); 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate int Plwp_setfpregs(struct ps_prochandle *P, lwpid_t lwpid, 217*7c478bd9Sstevel@tonic-gate const prfpregset_t *fpregs) 218*7c478bd9Sstevel@tonic-gate { 219*7c478bd9Sstevel@tonic-gate return (setlwpregs(P, lwpid, PCSFPREG, fpregs, sizeof (prfpregset_t))); 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate #if defined(sparc) || defined(__sparc) 223*7c478bd9Sstevel@tonic-gate int 224*7c478bd9Sstevel@tonic-gate Plwp_getxregs(struct ps_prochandle *P, lwpid_t lwpid, prxregset_t *xregs) 225*7c478bd9Sstevel@tonic-gate { 226*7c478bd9Sstevel@tonic-gate lwp_info_t *lwp; 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) { 229*7c478bd9Sstevel@tonic-gate errno = ENODATA; 230*7c478bd9Sstevel@tonic-gate return (-1); 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) { 234*7c478bd9Sstevel@tonic-gate if (P->state != PS_STOP) { 235*7c478bd9Sstevel@tonic-gate errno = EBUSY; 236*7c478bd9Sstevel@tonic-gate return (-1); 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate return (getlwpfile(P, lwpid, "xregs", 240*7c478bd9Sstevel@tonic-gate xregs, sizeof (prxregset_t))); 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_xregs != NULL) { 244*7c478bd9Sstevel@tonic-gate (void) memcpy(xregs, lwp->lwp_xregs, sizeof (prxregset_t)); 245*7c478bd9Sstevel@tonic-gate return (0); 246*7c478bd9Sstevel@tonic-gate } 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate if (lwp != NULL) 249*7c478bd9Sstevel@tonic-gate errno = ENODATA; 250*7c478bd9Sstevel@tonic-gate return (-1); 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate int 254*7c478bd9Sstevel@tonic-gate Plwp_setxregs(struct ps_prochandle *P, lwpid_t lwpid, const prxregset_t *xregs) 255*7c478bd9Sstevel@tonic-gate { 256*7c478bd9Sstevel@tonic-gate return (setlwpregs(P, lwpid, PCSXREG, xregs, sizeof (prxregset_t))); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate int 260*7c478bd9Sstevel@tonic-gate Plwp_getgwindows(struct ps_prochandle *P, lwpid_t lwpid, gwindows_t *gwins) 261*7c478bd9Sstevel@tonic-gate { 262*7c478bd9Sstevel@tonic-gate lwp_info_t *lwp; 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) { 265*7c478bd9Sstevel@tonic-gate errno = ENODATA; 266*7c478bd9Sstevel@tonic-gate return (-1); 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) { 270*7c478bd9Sstevel@tonic-gate if (P->state != PS_STOP) { 271*7c478bd9Sstevel@tonic-gate errno = EBUSY; 272*7c478bd9Sstevel@tonic-gate return (-1); 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate return (getlwpfile(P, lwpid, "gwindows", 276*7c478bd9Sstevel@tonic-gate gwins, sizeof (gwindows_t))); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_gwins != NULL) { 280*7c478bd9Sstevel@tonic-gate *gwins = *lwp->lwp_gwins; 281*7c478bd9Sstevel@tonic-gate return (0); 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate if (lwp != NULL) 285*7c478bd9Sstevel@tonic-gate errno = ENODATA; 286*7c478bd9Sstevel@tonic-gate return (-1); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate #if defined(__sparcv9) 290*7c478bd9Sstevel@tonic-gate int 291*7c478bd9Sstevel@tonic-gate Plwp_getasrs(struct ps_prochandle *P, lwpid_t lwpid, asrset_t asrs) 292*7c478bd9Sstevel@tonic-gate { 293*7c478bd9Sstevel@tonic-gate lwp_info_t *lwp; 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) { 296*7c478bd9Sstevel@tonic-gate errno = ENODATA; 297*7c478bd9Sstevel@tonic-gate return (-1); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) { 301*7c478bd9Sstevel@tonic-gate if (P->state != PS_STOP) { 302*7c478bd9Sstevel@tonic-gate errno = EBUSY; 303*7c478bd9Sstevel@tonic-gate return (-1); 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate return (getlwpfile(P, lwpid, "asrs", asrs, sizeof (asrset_t))); 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_asrs != NULL) { 310*7c478bd9Sstevel@tonic-gate (void) memcpy(asrs, lwp->lwp_asrs, sizeof (asrset_t)); 311*7c478bd9Sstevel@tonic-gate return (0); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate if (lwp != NULL) 315*7c478bd9Sstevel@tonic-gate errno = ENODATA; 316*7c478bd9Sstevel@tonic-gate return (-1); 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate int 321*7c478bd9Sstevel@tonic-gate Plwp_setasrs(struct ps_prochandle *P, lwpid_t lwpid, const asrset_t asrs) 322*7c478bd9Sstevel@tonic-gate { 323*7c478bd9Sstevel@tonic-gate return (setlwpregs(P, lwpid, PCSASRS, asrs, sizeof (asrset_t))); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate #endif /* __sparcv9 */ 326*7c478bd9Sstevel@tonic-gate #endif /* __sparc */ 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate int 329*7c478bd9Sstevel@tonic-gate Plwp_getpsinfo(struct ps_prochandle *P, lwpid_t lwpid, lwpsinfo_t *lps) 330*7c478bd9Sstevel@tonic-gate { 331*7c478bd9Sstevel@tonic-gate lwp_info_t *lwp; 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) { 334*7c478bd9Sstevel@tonic-gate errno = ENODATA; 335*7c478bd9Sstevel@tonic-gate return (-1); 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) { 339*7c478bd9Sstevel@tonic-gate return (getlwpfile(P, lwpid, "lwpsinfo", 340*7c478bd9Sstevel@tonic-gate lps, sizeof (lwpsinfo_t))); 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate if ((lwp = getlwpcore(P, lwpid)) != NULL) { 344*7c478bd9Sstevel@tonic-gate (void) memcpy(lps, &lwp->lwp_psinfo, sizeof (lwpsinfo_t)); 345*7c478bd9Sstevel@tonic-gate return (0); 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate return (-1); 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate int 352*7c478bd9Sstevel@tonic-gate Plwp_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp) 353*7c478bd9Sstevel@tonic-gate { 354*7c478bd9Sstevel@tonic-gate uintptr_t addr; 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) { 357*7c478bd9Sstevel@tonic-gate errno = ENODATA; 358*7c478bd9Sstevel@tonic-gate return (-1); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) { 362*7c478bd9Sstevel@tonic-gate lwpstatus_t ls; 363*7c478bd9Sstevel@tonic-gate if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0) 364*7c478bd9Sstevel@tonic-gate return (-1); 365*7c478bd9Sstevel@tonic-gate addr = ls.pr_ustack; 366*7c478bd9Sstevel@tonic-gate } else { 367*7c478bd9Sstevel@tonic-gate lwp_info_t *lwp; 368*7c478bd9Sstevel@tonic-gate if ((lwp = getlwpcore(P, lwpid)) == NULL) 369*7c478bd9Sstevel@tonic-gate return (-1); 370*7c478bd9Sstevel@tonic-gate addr = lwp->lwp_status.pr_ustack; 371*7c478bd9Sstevel@tonic-gate } 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 375*7c478bd9Sstevel@tonic-gate if (Pread(P, stkp, sizeof (*stkp), addr) != sizeof (*stkp)) 376*7c478bd9Sstevel@tonic-gate return (-1); 377*7c478bd9Sstevel@tonic-gate #ifdef _LP64 378*7c478bd9Sstevel@tonic-gate } else { 379*7c478bd9Sstevel@tonic-gate stack32_t stk32; 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate if (Pread(P, &stk32, sizeof (stk32), addr) != sizeof (stk32)) 382*7c478bd9Sstevel@tonic-gate return (-1); 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate stack_32_to_n(&stk32, stkp); 385*7c478bd9Sstevel@tonic-gate #endif 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate return (0); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate int 392*7c478bd9Sstevel@tonic-gate Plwp_main_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp) 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate uintptr_t addr; 395*7c478bd9Sstevel@tonic-gate lwpstatus_t ls; 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) { 398*7c478bd9Sstevel@tonic-gate errno = ENODATA; 399*7c478bd9Sstevel@tonic-gate return (-1); 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) { 403*7c478bd9Sstevel@tonic-gate if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0) 404*7c478bd9Sstevel@tonic-gate return (-1); 405*7c478bd9Sstevel@tonic-gate } else { 406*7c478bd9Sstevel@tonic-gate lwp_info_t *lwp; 407*7c478bd9Sstevel@tonic-gate if ((lwp = getlwpcore(P, lwpid)) == NULL) 408*7c478bd9Sstevel@tonic-gate return (-1); 409*7c478bd9Sstevel@tonic-gate ls = lwp->lwp_status; 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate addr = ls.pr_ustack; 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate /* 415*7c478bd9Sstevel@tonic-gate * Read out the current stack; if the SS_ONSTACK flag is set then 416*7c478bd9Sstevel@tonic-gate * this LWP is operating on the alternate signal stack. We can 417*7c478bd9Sstevel@tonic-gate * recover the original stack from pr_oldcontext. 418*7c478bd9Sstevel@tonic-gate */ 419*7c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 420*7c478bd9Sstevel@tonic-gate if (Pread(P, stkp, sizeof (*stkp), addr) != sizeof (*stkp)) 421*7c478bd9Sstevel@tonic-gate return (-1); 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate if (stkp->ss_flags & SS_ONSTACK) 424*7c478bd9Sstevel@tonic-gate goto on_altstack; 425*7c478bd9Sstevel@tonic-gate #ifdef _LP64 426*7c478bd9Sstevel@tonic-gate } else { 427*7c478bd9Sstevel@tonic-gate stack32_t stk32; 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate if (Pread(P, &stk32, sizeof (stk32), addr) != sizeof (stk32)) 430*7c478bd9Sstevel@tonic-gate return (-1); 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate if (stk32.ss_flags & SS_ONSTACK) 433*7c478bd9Sstevel@tonic-gate goto on_altstack; 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate stack_32_to_n(&stk32, stkp); 436*7c478bd9Sstevel@tonic-gate #endif 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate return (0); 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate on_altstack: 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 444*7c478bd9Sstevel@tonic-gate ucontext_t *ctxp = (void *)ls.pr_oldcontext; 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate if (Pread(P, stkp, sizeof (*stkp), 447*7c478bd9Sstevel@tonic-gate (uintptr_t)&ctxp->uc_stack) != sizeof (*stkp)) 448*7c478bd9Sstevel@tonic-gate return (-1); 449*7c478bd9Sstevel@tonic-gate #ifdef _LP64 450*7c478bd9Sstevel@tonic-gate } else { 451*7c478bd9Sstevel@tonic-gate ucontext32_t *ctxp = (void *)ls.pr_oldcontext; 452*7c478bd9Sstevel@tonic-gate stack32_t stk32; 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate if (Pread(P, &stk32, sizeof (stk32), 455*7c478bd9Sstevel@tonic-gate (uintptr_t)&ctxp->uc_stack) != sizeof (stk32)) 456*7c478bd9Sstevel@tonic-gate return (-1); 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate stack_32_to_n(&stk32, stkp); 459*7c478bd9Sstevel@tonic-gate #endif 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate return (0); 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate int 466*7c478bd9Sstevel@tonic-gate Plwp_alt_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp) 467*7c478bd9Sstevel@tonic-gate { 468*7c478bd9Sstevel@tonic-gate if (P->state == PS_IDLE) { 469*7c478bd9Sstevel@tonic-gate errno = ENODATA; 470*7c478bd9Sstevel@tonic-gate return (-1); 471*7c478bd9Sstevel@tonic-gate } 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate if (P->state != PS_DEAD) { 474*7c478bd9Sstevel@tonic-gate lwpstatus_t ls; 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0) 477*7c478bd9Sstevel@tonic-gate return (-1); 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate if (ls.pr_altstack.ss_flags & SS_DISABLE) { 480*7c478bd9Sstevel@tonic-gate errno = ENODATA; 481*7c478bd9Sstevel@tonic-gate return (-1); 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate *stkp = ls.pr_altstack; 485*7c478bd9Sstevel@tonic-gate } else { 486*7c478bd9Sstevel@tonic-gate lwp_info_t *lwp; 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate if ((lwp = getlwpcore(P, lwpid)) == NULL) 489*7c478bd9Sstevel@tonic-gate return (-1); 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate if (lwp->lwp_status.pr_altstack.ss_flags & SS_DISABLE) { 492*7c478bd9Sstevel@tonic-gate errno = ENODATA; 493*7c478bd9Sstevel@tonic-gate return (-1); 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate *stkp = lwp->lwp_status.pr_altstack; 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate return (0); 500*7c478bd9Sstevel@tonic-gate } 501