xref: /titanic_52/usr/src/lib/libpctx/common/libpctx.c (revision b72c368a02e0464faeef362bc5a1cf0fc69981da)
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 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * This file contains a set of generic routines for periodically
29  * sampling the state of another process, or tree of processes.
30  *
31  * It is built upon the infrastructure provided by libproc.
32  */
33 
34 #include <sys/wait.h>
35 #include <sys/syscall.h>
36 #include <sys/time.h>
37 #include <libproc.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <errno.h>
41 #include <unistd.h>
42 #include <signal.h>
43 #include <string.h>
44 #include <strings.h>
45 #include <limits.h>
46 #include <ctype.h>
47 #include <libintl.h>
48 #include <libcpc.h>
49 #include <sys/cpc_impl.h>
50 
51 #include "libpctx.h"
52 
53 struct __pctx {
54 	pctx_errfn_t *errfn;
55 	struct ps_prochandle *Pr;
56 	void *uarg;
57 	pctx_sysc_execfn_t *exec;
58 	pctx_sysc_forkfn_t *fork;
59 	pctx_sysc_exitfn_t *exit;
60 	pctx_sysc_lwp_createfn_t *lwp_create;
61 	pctx_init_lwpfn_t *init_lwp;
62 	pctx_fini_lwpfn_t *fini_lwp;
63 	pctx_sysc_lwp_exitfn_t *lwp_exit;
64 	int verbose;
65 	int created;
66 	int sigblocked;
67 	int terminate;
68 	sigset_t savedset;
69 	cpc_t *cpc;
70 };
71 
72 static void (*pctx_cpc_callback)(cpc_t *cpc, struct __pctx *pctx);
73 
74 static void
75 pctx_default_errfn(const char *fn, const char *fmt, va_list ap)
76 {
77 	(void) fprintf(stderr, "libpctx: pctx_%s: ", fn);
78 	(void) vfprintf(stderr, fmt, ap);
79 }
80 
81 /*PRINTFLIKE3*/
82 static void
83 pctx_error(pctx_t *pctx, const char *fn, const char *fmt, ...)
84 {
85 	va_list ap;
86 
87 	va_start(ap, fmt);
88 	pctx->errfn(fn, fmt, ap);
89 	va_end(ap);
90 }
91 
92 /*
93  * Create a new process and bind the user args for it
94  */
95 pctx_t *
96 pctx_create(
97     const char *filename,
98     char *const *argv,
99     void *arg,
100     int verbose,
101     pctx_errfn_t *errfn)
102 {
103 	static const char fn[] = "create";
104 	int err;
105 	pctx_t *pctx;
106 
107 	pctx = calloc(1, sizeof (*pctx));
108 	pctx->uarg = arg;
109 	pctx->verbose = verbose;
110 	pctx->terminate = 0;
111 	pctx->errfn = errfn ? errfn : pctx_default_errfn;
112 
113 	if ((pctx->Pr = Pcreate(filename, argv, &err, 0, 0)) == NULL) {
114 		switch (err) {
115 		case C_PERM:
116 			pctx_error(pctx, fn, gettext("cannot trace set-id or "
117 			    "unreadable program '%s'\n"), filename);
118 			break;
119 		case C_LP64:
120 			pctx_error(pctx, fn, gettext("cannot control LP64 "
121 			    "program '%s'\n"), filename);
122 			break;
123 		case C_NOEXEC:
124 			pctx_error(pctx, fn, gettext("cannot execute "
125 			    "program '%s'\n"), filename);
126 			break;
127 		case C_NOENT:
128 			pctx_error(pctx, fn, gettext("cannot find"
129 			    "program '%s'\n"), filename);
130 			break;
131 		case C_FORK:
132 			pctx_error(pctx, fn, gettext("cannot fork, "
133 			    "program '%s'\n"), filename);
134 			break;
135 		default:
136 			pctx_error(pctx, fn, gettext("%s, program '%s'\n"),
137 			    Pcreate_error(err), filename);
138 			break;
139 		}
140 		free(pctx);
141 		return (NULL);
142 	}
143 
144 	if (Psysentry(pctx->Pr, SYS_exit, 1) == -1) {
145 		pctx_error(pctx, fn,
146 		    gettext("can't stop-on-exit() program '%s'\n"), filename);
147 		Prelease(pctx->Pr, PRELEASE_KILL);
148 		free(pctx);
149 		return (NULL);
150 	}
151 	/*
152 	 * Set kill-on-last-close so the controlled process
153 	 * dies if we die.
154 	 */
155 	pctx->created = 1;
156 	(void) Psetflags(pctx->Pr, PR_KLC);
157 	(void) pctx_set_events(pctx, PCTX_NULL_EVENT);
158 
159 	return (pctx);
160 }
161 
162 /*
163  * Capture an existing process and bind the user args for it
164  */
165 pctx_t *
166 pctx_capture(pid_t pid, void *arg, int verbose, pctx_errfn_t *errfn)
167 {
168 	static const char fn[] = "capture";
169 	int err;
170 	pctx_t *pctx;
171 
172 	pctx = calloc(1, sizeof (*pctx));
173 	pctx->uarg = arg;
174 	pctx->verbose = verbose;
175 	pctx->errfn = errfn ? errfn : pctx_default_errfn;
176 
177 	if ((pctx->Pr = Pgrab(pid, 0, &err)) == NULL) {
178 		switch (err) {
179 		case G_NOPROC:
180 			pctx_error(pctx, fn,
181 			    gettext("pid %d doesn't exist\n"), (int)pid);
182 			break;
183 		case G_ZOMB:
184 			pctx_error(pctx, fn,
185 			    gettext("pid %d is a zombie\n"), (int)pid);
186 			break;
187 		case G_PERM:
188 			pctx_error(pctx, fn,
189 			    gettext("pid %d: permission denied\n"), (int)pid);
190 			break;
191 		case G_BUSY:
192 			pctx_error(pctx, fn,
193 			    gettext("pid %d is already being traced\n"),
194 			    (int)pid);
195 			break;
196 		case G_SYS:
197 			pctx_error(pctx, fn,
198 			    gettext("pid %d is a system process\n"), (int)pid);
199 			break;
200 		case G_SELF:
201 			pctx_error(pctx, fn,
202 			    gettext("cannot capture self!\n"));
203 			break;
204 		case G_LP64:
205 			pctx_error(pctx, fn, gettext("cannot control LP64 "
206 			    "process, pid %d\n"), (int)pid);
207 			break;
208 		default:
209 			pctx_error(pctx, fn, gettext("%s: pid %d\n"),
210 			    Pgrab_error(err), (int)pid);
211 			break;
212 		}
213 		free(pctx);
214 		return (NULL);
215 	}
216 
217 	if (Psysentry(pctx->Pr, SYS_exit, 1) == -1) {
218 		pctx_error(pctx, fn,
219 		    gettext("can't stop-on-exit() pid %d\n"), (int)pid);
220 		Prelease(pctx->Pr, PRELEASE_CLEAR);
221 		free(pctx);
222 		return (NULL);
223 	}
224 
225 	/*
226 	 * Set run-on-last-close so the controlled process
227 	 * runs even if we die on a signal.  This is because
228 	 * we grabbed an existing process - it would be impolite
229 	 * to cause it to die if we exit prematurely.
230 	 */
231 	pctx->created = 0;
232 	(void) Psetflags(pctx->Pr, PR_RLC);
233 	(void) pctx_set_events(pctx, PCTX_NULL_EVENT);
234 
235 	return (pctx);
236 }
237 
238 /*ARGSUSED*/
239 static void
240 default_void(pctx_t *pctx)
241 {}
242 
243 /*ARGSUSED*/
244 static int
245 default_int(pctx_t *pctx)
246 {
247 	return (0);
248 }
249 
250 int
251 pctx_set_events(pctx_t *pctx, ...)
252 {
253 	static const char fn[] = "set_events";
254 	va_list pvar;
255 	int error = 0;
256 	pctx_event_t event;
257 
258 	va_start(pvar, pctx);
259 	do {
260 		switch (event = (pctx_event_t)va_arg(pvar, pctx_event_t)) {
261 		case PCTX_NULL_EVENT:
262 			break;
263 		case PCTX_SYSC_EXEC_EVENT:
264 			pctx->exec = (pctx_sysc_execfn_t *)
265 			    va_arg(pvar, pctx_sysc_execfn_t *);
266 			break;
267 		case PCTX_SYSC_FORK_EVENT:
268 			pctx->fork = (pctx_sysc_forkfn_t *)
269 			    va_arg(pvar, pctx_sysc_forkfn_t *);
270 			break;
271 		case PCTX_SYSC_EXIT_EVENT:	/* always intercepted */
272 			pctx->exit = (pctx_sysc_exitfn_t *)
273 			    va_arg(pvar, pctx_sysc_exitfn_t *);
274 			break;
275 		case PCTX_SYSC_LWP_CREATE_EVENT:
276 			pctx->lwp_create = (pctx_sysc_lwp_createfn_t *)
277 			    va_arg(pvar, pctx_sysc_lwp_createfn_t *);
278 			break;
279 		case PCTX_INIT_LWP_EVENT:
280 			pctx->init_lwp = (pctx_init_lwpfn_t *)
281 			    va_arg(pvar, pctx_init_lwpfn_t *);
282 			break;
283 		case PCTX_FINI_LWP_EVENT:
284 			pctx->fini_lwp = (pctx_fini_lwpfn_t *)
285 			    va_arg(pvar, pctx_fini_lwpfn_t *);
286 			break;
287 		case PCTX_SYSC_LWP_EXIT_EVENT:
288 			pctx->lwp_exit = (pctx_sysc_lwp_exitfn_t *)
289 			    va_arg(pvar, pctx_sysc_lwp_exitfn_t *);
290 			break;
291 		default:
292 			pctx_error(pctx, fn,
293 			    gettext("unknown event type %x\n"), event);
294 			error = -1;
295 			break;
296 		}
297 	} while (event != PCTX_NULL_EVENT && error == 0);
298 	va_end(pvar);
299 
300 	if (error != 0)
301 		return (error);
302 
303 	if (pctx->exec == NULL)
304 		pctx->exec = (pctx_sysc_execfn_t *)default_int;
305 	if (pctx->fork == NULL)
306 		pctx->fork = (pctx_sysc_forkfn_t *)default_void;
307 	if (pctx->exit == NULL)
308 		pctx->exit = (pctx_sysc_exitfn_t *)default_void;
309 	if (pctx->lwp_create == NULL)
310 		pctx->lwp_create = (pctx_sysc_lwp_createfn_t *)default_int;
311 	if (pctx->init_lwp == NULL)
312 		pctx->init_lwp = (pctx_init_lwpfn_t *)default_int;
313 	if (pctx->fini_lwp == NULL)
314 		pctx->fini_lwp = (pctx_fini_lwpfn_t *)default_int;
315 	if (pctx->lwp_exit == NULL)
316 		pctx->lwp_exit = (pctx_sysc_lwp_exitfn_t *)default_int;
317 
318 	if (pctx->fork != (pctx_sysc_forkfn_t *)default_void) {
319 		(void) Psysexit(pctx->Pr, SYS_forkall, 1);
320 		(void) Psysexit(pctx->Pr, SYS_vfork, 1);
321 		(void) Psysexit(pctx->Pr, SYS_fork1, 1);
322 		(void) Psysexit(pctx->Pr, SYS_forksys, 1);
323 		if (Psetflags(pctx->Pr, PR_FORK) == -1)
324 			error = -1;
325 	} else {
326 		(void) Psysexit(pctx->Pr, SYS_forkall, 0);
327 		(void) Psysexit(pctx->Pr, SYS_vfork, 0);
328 		(void) Psysexit(pctx->Pr, SYS_fork1, 0);
329 		(void) Psysexit(pctx->Pr, SYS_forksys, 0);
330 		if (Punsetflags(pctx->Pr, PR_FORK) == -1)
331 			error = -1;
332 	}
333 
334 	/*
335 	 * exec causes termination of all but the exec-ing lwp,
336 	 * and resets the lwpid to one in the new address space.
337 	 */
338 	if (pctx->exec != (pctx_sysc_execfn_t *)default_int ||
339 	    pctx->fini_lwp != (pctx_fini_lwpfn_t *)default_int ||
340 	    pctx->init_lwp != (pctx_init_lwpfn_t *)default_int) {
341 		(void) Psysexit(pctx->Pr, SYS_exec, 1);
342 		(void) Psysexit(pctx->Pr, SYS_execve, 1);
343 		(void) Psysentry(pctx->Pr, SYS_exec, 1);
344 		(void) Psysentry(pctx->Pr, SYS_execve, 1);
345 	} else {
346 		(void) Psysexit(pctx->Pr, SYS_exec, 0);
347 		(void) Psysexit(pctx->Pr, SYS_execve, 0);
348 		(void) Psysentry(pctx->Pr, SYS_exec, 0);
349 		(void) Psysentry(pctx->Pr, SYS_execve, 0);
350 	}
351 
352 	(void) Psysexit(pctx->Pr, SYS_lwp_create,
353 	    pctx->lwp_create != (pctx_sysc_lwp_createfn_t *)default_int ||
354 	    pctx->init_lwp != (pctx_init_lwpfn_t *)default_int);
355 
356 	(void) Psysentry(pctx->Pr, SYS_lwp_exit,
357 	    pctx->lwp_exit != (pctx_sysc_lwp_exitfn_t *)default_int ||
358 	    pctx->fini_lwp != (pctx_fini_lwpfn_t *)default_int);
359 
360 	return (0);
361 }
362 
363 static sigset_t termsig;
364 
365 static void
366 __libpctx_init(void)
367 {
368 	/*
369 	 * Initialize the signal set used to shield ourselves from
370 	 * death-by-terminal-signal while the agent lwp is running.
371 	 */
372 	(void) sigemptyset(&termsig);
373 	(void) sigaddset(&termsig, SIGHUP);
374 	(void) sigaddset(&termsig, SIGTERM);
375 	(void) sigaddset(&termsig, SIGINT);
376 	(void) sigaddset(&termsig, SIGQUIT);
377 }
378 
379 #pragma init(__libpctx_init)
380 
381 static void
382 pctx_begin_syscalls(pctx_t *pctx)
383 {
384 	if (pctx->Pr == NULL)
385 		return;
386 	if (pctx->sigblocked++ == 0) {
387 		(void) sigprocmask(SIG_BLOCK, &termsig, &pctx->savedset);
388 		(void) Pcreate_agent(pctx->Pr);
389 	}
390 }
391 
392 static void
393 pctx_end_syscalls(pctx_t *pctx)
394 {
395 	if (pctx->Pr == NULL)
396 		return;
397 	if (--pctx->sigblocked == 0) {
398 		(void) Pdestroy_agent(pctx->Pr);
399 		(void) sigprocmask(SIG_SETMASK, &pctx->savedset, NULL);
400 	}
401 }
402 
403 /*
404  * Iterate over the valid lwpids in the process, invoking the
405  * action function on each one.
406  */
407 static int
408 pctx_lwpiterate(pctx_t *pctx, int (*action)(pctx_t *, pid_t, id_t, void *))
409 {
410 	const pstatus_t *pstatus;
411 	char lstatus[64];
412 	struct stat statb;
413 	lwpstatus_t *lwps;
414 	prheader_t *prh;
415 	int fd, nlwp;
416 	int ret = 0;
417 
418 	if (action == (int (*)(pctx_t *, pid_t, id_t, void *))default_int)
419 		return (0);
420 
421 	pstatus = Pstatus(pctx->Pr);
422 	if (pstatus->pr_nlwp <= 1) {
423 		pctx_begin_syscalls(pctx);
424 		ret = action(pctx, pstatus->pr_pid, 1, pctx->uarg);
425 		pctx_end_syscalls(pctx);
426 		return (ret);
427 	}
428 
429 	(void) snprintf(lstatus, sizeof (lstatus),
430 	    "/proc/%d/lstatus", (int)pstatus->pr_pid);
431 
432 	if ((fd = open(lstatus, O_RDONLY)) < 0 ||
433 	    fstat(fd, &statb) != 0) {
434 		if (fd >= 0)
435 			(void) close(fd);
436 		return (-1);
437 	}
438 
439 	prh = malloc(statb.st_size);
440 	if (read(fd, prh, statb.st_size) <
441 	    sizeof (prheader_t) + sizeof (lwpstatus_t)) {
442 		(void) close(fd);
443 		free(prh);
444 		return (-1);
445 	}
446 	(void) close(fd);
447 
448 	/* LINTED pointer cast may result in improper alignment */
449 	lwps = (lwpstatus_t *)(prh + 1);
450 	pctx_begin_syscalls(pctx);
451 	for (nlwp = prh->pr_nent; nlwp > 0; nlwp--) {
452 		if (action(pctx,
453 		    pstatus->pr_pid, lwps->pr_lwpid, pctx->uarg) != 0)
454 			ret = -1;
455 		/* LINTED pointer cast may result in improper alignment */
456 		lwps = (lwpstatus_t *)((char *)lwps + prh->pr_entsize);
457 	}
458 	pctx_end_syscalls(pctx);
459 	free(prh);
460 	return (ret);
461 }
462 
463 /*
464  * Free any associated state, but leave the process stopped if it
465  * is still under our control.  (If it isn't under our control,
466  * it should just run to completion when we do our last close)
467  */
468 static void
469 pctx_free(pctx_t *pctx)
470 {
471 	if (pctx->cpc != NULL && pctx_cpc_callback != NULL)
472 		(*pctx_cpc_callback)(pctx->cpc, pctx);
473 	if (pctx->Pr) {
474 		Pfree(pctx->Pr);
475 		pctx->Pr = NULL;
476 	}
477 	pctx->errfn = pctx_default_errfn;
478 }
479 
480 /*
481  * Completely release the process from our control and discard all our state
482  */
483 void
484 pctx_release(pctx_t *pctx)
485 {
486 	if (pctx->Pr) {
487 		Prelease(pctx->Pr, PRELEASE_CLEAR);
488 		pctx->Pr = NULL;
489 	}
490 
491 	pctx_free(pctx);
492 	bzero(pctx, sizeof (*pctx));
493 	free(pctx);
494 }
495 
496 static void
497 msincr(struct timeval *tv, uint_t msec)
498 {
499 	tv->tv_sec += msec / MILLISEC;
500 	tv->tv_usec += (msec % MILLISEC) * MILLISEC;
501 	if (tv->tv_usec > MICROSEC) {
502 		tv->tv_sec++;
503 		tv->tv_usec -= MICROSEC;
504 	}
505 }
506 
507 static uint_t
508 msdiff(struct timeval *tva, struct timeval *tvb)
509 {
510 	time_t sdiff = tva->tv_sec - tvb->tv_sec;
511 	suseconds_t udiff = tva->tv_usec - tvb->tv_usec;
512 
513 	if (sdiff < 0)
514 		return (0);
515 	if (udiff < 0) {
516 		udiff += MICROSEC;
517 		sdiff--;
518 	}
519 	if (sdiff < 0)
520 		return (0);
521 	if (sdiff >= (INT_MAX / MILLISEC))
522 		return ((uint_t)INT_MAX);
523 	return ((uint_t)(sdiff * MILLISEC + udiff / MILLISEC));
524 }
525 
526 int
527 pctx_run(
528 	pctx_t *pctx,
529 	uint_t msec,
530 	uint_t nsamples,
531 	int (*tick)(pctx_t *, pid_t, id_t, void *))
532 {
533 	static const char fn[] = "run";
534 	struct timeval tvgoal, tvnow;
535 	uint_t mswait = 0;
536 	int running = 1;
537 	const pstatus_t *pstatus;
538 	psinfo_t psinfo;
539 	void (*sigsaved)();
540 	id_t lwpid;
541 	pid_t pid = Pstatus(pctx->Pr)->pr_pid;
542 	int pstate;
543 
544 	if (msec == 0)
545 		nsamples = 0;
546 	if (nsamples == 0)
547 		nsamples = UINT_MAX;
548 
549 	/*
550 	 * Casually discard any knowledge of the children we create
551 	 */
552 	sigsaved = signal(SIGCHLD, SIG_IGN);
553 
554 	/*
555 	 * Since we've just "discovered" this process which might have
556 	 * been running for weeks, deliver some init_lwp events so
557 	 * that our caller gets a handle on the process.
558 	 */
559 	if (pctx_lwpiterate(pctx, pctx->init_lwp) != 0) {
560 		if (pctx->verbose)
561 			pctx_error(pctx, fn,
562 			    gettext("%d: lwp discovery failed\n"), (int)pid);
563 		goto bailout;
564 	}
565 
566 	if (msec != 0) {
567 		/*
568 		 * tvgoal represents the time at which the sample
569 		 * should next be taken.
570 		 */
571 		(void) gettimeofday(&tvgoal, 0);
572 		msincr(&tvgoal, msec);
573 	}
574 
575 	/*
576 	 * The event handling loop continues while running is 1.
577 	 * running becomes 0 when either the controlled process has
578 	 * exited successfully or the number of time samples has expired.
579 	 * Otherwise, if an error has occurred, running becomes -1.
580 	 */
581 	while (running == 1 && !pctx->terminate) {
582 
583 		if (Psetrun(pctx->Pr, 0, 0) != 0) {
584 			if (pctx->verbose)
585 				pctx_error(pctx, fn,
586 				    gettext("%d: Psetrun\n"), (int)pid);
587 			break;
588 		}
589 
590 		if (msec != 0) {
591 			/*
592 			 * This timing loop attempts to estimate the number
593 			 * of milliseconds between our "goal" time (when
594 			 * we should stop the process and run the tick
595 			 * routine) and the current time.
596 			 *
597 			 * If we ever find ourselves running behind i.e. we
598 			 * missed our goal, then we skip ahead to the next
599 			 * goal instead.
600 			 */
601 			do {
602 				(void) gettimeofday(&tvnow, 0);
603 				if ((mswait = msdiff(&tvgoal, &tvnow)) == 0) {
604 					msincr(&tvgoal, msec);
605 					/*
606 					 * Skip ahead to the next goal, unless
607 					 * there is only one more sample left
608 					 * to take.
609 					 */
610 					if (nsamples != 1)
611 						nsamples--;
612 				}
613 			} while (mswait == 0 && !pctx->terminate);
614 		}
615 
616 		if (pctx->terminate)
617 			goto bailout;
618 		else
619 			(void) Pwait(pctx->Pr, mswait);
620 
621 checkstate:
622 		switch (pstate = Pstate(pctx->Pr)) {
623 		case PS_RUN:
624 			/*
625 			 * Try again, but wait for up to 5 seconds.
626 			 */
627 			if (Pstop(pctx->Pr, 5 * MILLISEC) == -1 ||
628 			    (pstate = Pstate(pctx->Pr)) != PS_STOP) {
629 				pctx_error(pctx, fn,
630 				    gettext("%d: won't stop\n"), (int)pid);
631 			}
632 			break;
633 		case PS_STOP:
634 			break;
635 		case PS_LOST:
636 			/*
637 			 * Lost control - probably execed a setuid/setgid
638 			 * executable.  Try and get control back again,
639 			 * else bail ..
640 			 */
641 			(void) Preopen(pctx->Pr);
642 			if ((pstate = Pstate(pctx->Pr)) != PS_LOST)
643 				goto checkstate;
644 			pctx_error(pctx, fn,
645 			    gettext("%d: execed a program that cannot "
646 			    "be tracked\n"), (int)pid);
647 			running = -1;
648 			break;
649 		case PS_UNDEAD:
650 		case PS_DEAD:
651 			if (pctx->verbose)
652 				pctx_error(pctx, fn,
653 				    gettext("%d: process terminated\n"),
654 				    (int)pid);
655 			running = -1;
656 			break;
657 		default:
658 			if (pctx->verbose)
659 				pctx_error(pctx, fn,
660 				    gettext("%d: process state 0x%x?\n"),
661 				    (int)pid, pstate);
662 			break;
663 		}
664 
665 		if (pstate != PS_STOP)
666 			break;
667 
668 		pstatus = Pstatus(pctx->Pr);
669 		lwpid = pstatus->pr_lwp.pr_lwpid;
670 		switch (pstatus->pr_lwp.pr_why) {
671 		case PR_REQUESTED:
672 			msincr(&tvgoal, msec);
673 			if (pstatus->pr_flags & PR_VFORKP) {
674 				/*
675 				 * The process is in a vfork stupor until
676 				 * its child releases it via an exec.
677 				 * Don't sample it while it's in this state
678 				 * - we won't be able to create the agent.
679 				 */
680 				break;
681 			}
682 			if (pctx_lwpiterate(pctx, tick) != 0)
683 				running = -1;
684 			if (running == 1 && --nsamples == 0)
685 				running = 0;
686 			break;
687 		case PR_SYSENTRY:
688 			switch (pstatus->pr_lwp.pr_what) {
689 			case SYS_lwp_exit:
690 				pctx_begin_syscalls(pctx);
691 				(void) pctx->fini_lwp(pctx,
692 				    pid, lwpid, pctx->uarg);
693 				(void) pctx->lwp_exit(pctx,
694 				    pid, lwpid, pctx->uarg);
695 				pctx_end_syscalls(pctx);
696 				break;
697 			case SYS_exit:
698 				if (pctx_lwpiterate(pctx, pctx->fini_lwp)
699 				    != 0)
700 					running = -1;
701 				pctx->exit(pctx, pid, lwpid,
702 				    (int)pstatus->pr_lwp.pr_sysarg[0],
703 				    pctx->uarg);
704 				if (running == 1)
705 					running = 0;
706 				break;
707 			case SYS_exec:
708 			case SYS_execve:
709 				(void) pctx_lwpiterate(pctx, pctx->fini_lwp);
710 				break;
711 			default:
712 				pctx_error(pctx, fn,
713 				    "warning - pid %d sysentry(%d)\n",
714 				    (int)pid, pstatus->pr_lwp.pr_what);
715 				break;
716 			}
717 			break;
718 		case PR_SYSEXIT:
719 			switch (pstatus->pr_lwp.pr_what) {
720 			case SYS_exec:
721 			case SYS_execve:
722 				if (pstatus->pr_lwp.pr_errno) {
723 					/*
724 					 * The exec failed completely.
725 					 * Reinstate the lwps we fini'd
726 					 * at exec entrance
727 					 */
728 					if (pctx_lwpiterate(pctx,
729 					    pctx->init_lwp) == 0)
730 						running = 1;
731 					else
732 						running = -1;
733 					break;
734 				}
735 				if (pctx->exec == (pctx_sysc_execfn_t *)
736 				    default_int) {
737 					running = 0;
738 					break;
739 				}
740 				(void) memcpy(&psinfo,
741 				    Ppsinfo(pctx->Pr), sizeof (psinfo));
742 				proc_unctrl_psinfo(&psinfo);
743 				pctx_begin_syscalls(pctx);
744 				if (pctx->exec(pctx, pid, lwpid,
745 				    psinfo.pr_psargs, pctx->uarg) != 0)
746 					running = -1;
747 				if (running == 1 && pctx->init_lwp(pctx,
748 				    pid, 1, pctx->uarg) != 0)
749 					running = -1;
750 				pctx_end_syscalls(pctx);
751 				break;
752 			case SYS_lwp_create:
753 				if (pstatus->pr_lwp.pr_errno ||
754 				    pstatus->pr_lwp.pr_rval1)
755 					break;
756 				pctx_begin_syscalls(pctx);
757 				if (pctx->init_lwp(pctx, pid, lwpid,
758 				    pctx->uarg) != 0)
759 					running = -1;
760 				if (running == 1 && pctx->lwp_create(pctx,
761 				    pid, lwpid, pctx->uarg) != 0)
762 					running = -1;
763 				pctx_end_syscalls(pctx);
764 				break;
765 			case SYS_forkall:
766 			case SYS_vfork:
767 			case SYS_fork1:
768 			case SYS_forksys:
769 				if (pstatus->pr_lwp.pr_errno)
770 					break;
771 				(void) fflush(NULL);
772 				switch (fork1()) {
773 					pid_t ppid;
774 					int wascreated;
775 					pctx_sysc_forkfn_t *forkfn;
776 				case 0:
777 					ppid = pid;
778 					pid = pstatus->pr_lwp.pr_rval1;
779 					wascreated = pctx->created;
780 					forkfn = pctx->fork;
781 					pctx_free(pctx);
782 					pctx = pctx_capture(pid, pctx->uarg,
783 					    pctx->verbose, pctx->errfn);
784 					if (pctx != NULL) {
785 						if (wascreated) {
786 							/*
787 							 * Set kill on last
788 							 * close so -all-
789 							 * children die.
790 							 */
791 							pctx->created = 1;
792 							(void) Psetflags(
793 							    pctx->Pr, PR_KLC);
794 						}
795 						(*forkfn)(pctx, ppid, pid,
796 						    lwpid, pctx->uarg);
797 						pctx_release(pctx);
798 						_exit(0);
799 					} else {
800 						_exit(1);
801 					}
802 					/*NOTREACHED*/
803 				case -1:
804 					pctx_error(pctx, fn,
805 					    "cannot follow pid %d: %s\n",
806 					    (int)pstatus->pr_lwp.pr_rval1,
807 					    strerror(errno));
808 					break;
809 				default:
810 					break;
811 				}
812 				break;
813 			default:
814 				pctx_error(pctx, fn, gettext(
815 				    "warning - pid %d sysexit(%d)\n"),
816 				    (int)pid, pstatus->pr_lwp.pr_what);
817 				break;
818 			}
819 			break;
820 		case PR_SIGNALLED:
821 			if (pctx->verbose)
822 				pctx_error(pctx, fn,
823 				    gettext("pid %d - signalled\n"), (int)pid);
824 			break;
825 		case PR_JOBCONTROL:
826 			if (pctx->verbose)
827 				pctx_error(pctx, fn,
828 				    gettext("pid %d - job control stop\n"),
829 				    (int)pid);
830 			running = -1;
831 			break;
832 		case PR_FAULTED:
833 			if (pctx->verbose)
834 				pctx_error(pctx, fn,
835 				    gettext("pid %d - faulted\n"), (int)pid);
836 			break;
837 		case PR_SUSPENDED:
838 			if (pctx->verbose)
839 				pctx_error(pctx, fn,
840 				    gettext("pid %d - suspended\n"), (int)pid);
841 			break;
842 		case PR_CHECKPOINT:
843 			if (pctx->verbose)
844 				pctx_error(pctx, fn,
845 				    gettext("pid %d - checkpoint\n"),
846 				    (int)pid);
847 			break;
848 		default:
849 			if (pctx->verbose)
850 				pctx_error(pctx, fn,
851 				    gettext("pid %d - reason %d\n"),
852 				    (int)pid, pstatus->pr_lwp.pr_why);
853 			running = -1;
854 			break;
855 		}
856 	}
857 
858 bailout:
859 	(void) signal(SIGCHLD, sigsaved);
860 
861 	if (pctx->terminate)
862 		return (0);
863 
864 	switch (running) {
865 	case 0:
866 		return (0);
867 	case -1:
868 		return (-1);
869 	default:
870 		pctx_error(pctx, fn, gettext("lost control of pid %d\n"),
871 		    (int)pid);
872 		pctx_free(pctx);
873 		return (-1);
874 	}
875 }
876 
877 /*
878  * Execute the private 'cpc' system call in the context of the
879  * controlled process.
880  */
881 int
882 __pctx_cpc(pctx_t *pctx, cpc_t *cpc,
883     int cmd, id_t lwpid, void *data1, void *data2, void *data3, int bufsize)
884 {
885 	sysret_t rval;
886 	argdes_t argd[5];
887 	argdes_t *adp = &argd[0];
888 	int error;
889 
890 	/*
891 	 * Keep track of the relationship between cpc_t and pctx_t here.
892 	 * We store the last cpc_t used by libpctx, so that when this pctx is
893 	 * destroyed, libpctx can notify libcpc.
894 	 */
895 
896 	if (pctx->cpc != NULL && pctx->cpc != cpc && pctx_cpc_callback != NULL)
897 		(*pctx_cpc_callback)(pctx->cpc, pctx);
898 	pctx->cpc = cpc;
899 
900 	/*
901 	 * cmd and lwpid are passed in by value no matter what the command is.
902 	 */
903 	adp->arg_value = cmd;
904 	adp->arg_object = NULL;
905 	adp->arg_type = AT_BYVAL;
906 	adp->arg_inout = AI_INPUT;
907 	adp->arg_size = 0;
908 	adp++;
909 
910 	adp->arg_value = lwpid;
911 	adp->arg_object = NULL;
912 	adp->arg_type = AT_BYVAL;
913 	adp->arg_inout = AI_INPUT;
914 	adp->arg_size = 0;
915 	adp++;
916 
917 	switch (cmd) {
918 	case CPC_BIND:
919 		adp->arg_value = 0;
920 		adp->arg_object = data1;
921 		adp->arg_type = AT_BYREF;
922 		adp->arg_inout = AI_INPUT;
923 		adp->arg_size = (size_t)data2;
924 		adp++;
925 
926 		adp->arg_value = (size_t)data2;
927 		adp->arg_object = NULL;
928 		adp->arg_type = AT_BYVAL;
929 		adp->arg_inout = AI_INPUT;
930 		adp->arg_size = 0;
931 		adp++;
932 
933 		adp->arg_value = 0;
934 		adp->arg_object = data3;
935 		adp->arg_type = AT_BYREF;
936 		adp->arg_inout = AI_INOUT;
937 		adp->arg_size = sizeof (int);
938 
939 		break;
940 	case CPC_SAMPLE:
941 		adp->arg_value = 0;
942 		adp->arg_object = data1;
943 		adp->arg_type = AT_BYREF;
944 		adp->arg_inout = AI_OUTPUT;
945 		adp->arg_size = bufsize;
946 		adp++;
947 
948 		adp->arg_value = 0;
949 		adp->arg_object = data2;
950 		adp->arg_type = AT_BYREF;
951 		adp->arg_inout = AI_OUTPUT;
952 		adp->arg_size = sizeof (hrtime_t);
953 		adp++;
954 
955 		adp->arg_value = 0;
956 		adp->arg_object = data3;
957 		adp->arg_type = AT_BYREF;
958 		adp->arg_inout = AI_OUTPUT;
959 		adp->arg_size = sizeof (uint64_t);
960 
961 		break;
962 	default:
963 		adp->arg_value = 0;
964 		adp->arg_object = 0;
965 		adp->arg_type = AT_BYVAL;
966 		adp->arg_inout = AI_INPUT;
967 		adp->arg_size = 0;
968 		adp++;
969 
970 		adp->arg_value = 0;
971 		adp->arg_object = 0;
972 		adp->arg_type = AT_BYVAL;
973 		adp->arg_inout = AI_INPUT;
974 		adp->arg_size = 0;
975 		adp++;
976 
977 		adp->arg_value = 0;
978 		adp->arg_object = 0;
979 		adp->arg_type = AT_BYVAL;
980 		adp->arg_inout = AI_INPUT;
981 		adp->arg_size = 0;
982 
983 		break;
984 	}
985 
986 	error = Psyscall(pctx->Pr, &rval, SYS_cpc, 5, &argd[0]);
987 
988 	if (error) {
989 		errno = error > 0 ? error : ENOSYS;
990 		return (-1);
991 	}
992 	return (rval.sys_rval1);
993 }
994 
995 /*
996  * libcpc-private hook used to register a callback. The callback is used to
997  * notify libcpc when a pctx handle is invalidated.
998  */
999 void
1000 __pctx_cpc_register_callback(void (*arg)(struct __cpc *, struct __pctx *))
1001 {
1002 	pctx_cpc_callback = arg;
1003 }
1004 
1005 /*
1006  * Tell pctx_run to bail out immediately
1007  */
1008 void
1009 pctx_terminate(struct __pctx *pctx)
1010 {
1011 	pctx->terminate = 1;
1012 }
1013