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