xref: /titanic_44/usr/src/lib/libpctx/common/libpctx.c (revision b7f45089ccbe01bab3d7c7377b49d80d2ae18a69)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * This file contains a set of generic routines for periodically
31  * sampling the state of another process, or tree of processes.
32  *
33  * It is built upon the infrastructure provided by libproc.
34  */
35 
36 #include <sys/wait.h>
37 #include <sys/syscall.h>
38 #include <sys/time.h>
39 #include <libproc.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <errno.h>
43 #include <unistd.h>
44 #include <signal.h>
45 #include <string.h>
46 #include <strings.h>
47 #include <limits.h>
48 #include <ctype.h>
49 #include <libintl.h>
50 #include <libcpc.h>
51 #include <sys/cpc_impl.h>
52 
53 #include "libpctx.h"
54 
55 struct __pctx {
56 	pctx_errfn_t *errfn;
57 	struct ps_prochandle *Pr;
58 	void *uarg;
59 	pctx_sysc_execfn_t *exec;
60 	pctx_sysc_forkfn_t *fork;
61 	pctx_sysc_exitfn_t *exit;
62 	pctx_sysc_lwp_createfn_t *lwp_create;
63 	pctx_init_lwpfn_t *init_lwp;
64 	pctx_fini_lwpfn_t *fini_lwp;
65 	pctx_sysc_lwp_exitfn_t *lwp_exit;
66 	int verbose;
67 	int created;
68 	int sigblocked;
69 	sigset_t savedset;
70 	cpc_t *cpc;
71 };
72 
73 static void (*pctx_cpc_callback)(cpc_t *cpc, struct __pctx *pctx);
74 
75 static void
76 pctx_default_errfn(const char *fn, const char *fmt, va_list ap)
77 {
78 	(void) fprintf(stderr, "libpctx: pctx_%s: ", fn);
79 	(void) vfprintf(stderr, fmt, ap);
80 }
81 
82 /*PRINTFLIKE3*/
83 static void
84 pctx_error(pctx_t *pctx, const char *fn, const char *fmt, ...)
85 {
86 	va_list ap;
87 
88 	va_start(ap, fmt);
89 	pctx->errfn(fn, fmt, ap);
90 	va_end(ap);
91 }
92 
93 /*
94  * Create a new process and bind the user args for it
95  */
96 pctx_t *
97 pctx_create(
98     const char *filename,
99     char *const *argv,
100     void *arg,
101     int verbose,
102     pctx_errfn_t *errfn)
103 {
104 	static const char fn[] = "create";
105 	int err;
106 	pctx_t *pctx;
107 
108 	pctx = calloc(1, sizeof (*pctx));
109 	pctx->uarg = arg;
110 	pctx->verbose = verbose;
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 		if (Psetflags(pctx->Pr, PR_FORK) == -1)
323 			error = -1;
324 	} else {
325 		(void) Psysexit(pctx->Pr, SYS_forkall, 0);
326 		(void) Psysexit(pctx->Pr, SYS_vfork, 0);
327 		(void) Psysexit(pctx->Pr, SYS_fork1, 0);
328 		if (Punsetflags(pctx->Pr, PR_FORK) == -1)
329 			error = -1;
330 	}
331 
332 	/*
333 	 * exec causes termination of all but the exec-ing lwp,
334 	 * and resets the lwpid to one in the new address space.
335 	 */
336 	if (pctx->exec != (pctx_sysc_execfn_t *)default_int ||
337 	    pctx->fini_lwp != (pctx_fini_lwpfn_t *)default_int ||
338 	    pctx->init_lwp != (pctx_init_lwpfn_t *)default_int) {
339 		(void) Psysexit(pctx->Pr, SYS_exec, 1);
340 		(void) Psysexit(pctx->Pr, SYS_execve, 1);
341 		(void) Psysentry(pctx->Pr, SYS_exec, 1);
342 		(void) Psysentry(pctx->Pr, SYS_execve, 1);
343 	} else {
344 		(void) Psysexit(pctx->Pr, SYS_exec, 0);
345 		(void) Psysexit(pctx->Pr, SYS_execve, 0);
346 		(void) Psysentry(pctx->Pr, SYS_exec, 0);
347 		(void) Psysentry(pctx->Pr, SYS_execve, 0);
348 	}
349 
350 	(void) Psysexit(pctx->Pr, SYS_lwp_create,
351 	    pctx->lwp_create != (pctx_sysc_lwp_createfn_t *)default_int ||
352 	    pctx->init_lwp != (pctx_init_lwpfn_t *)default_int);
353 
354 	(void) Psysentry(pctx->Pr, SYS_lwp_exit,
355 	    pctx->lwp_exit != (pctx_sysc_lwp_exitfn_t *)default_int ||
356 	    pctx->fini_lwp != (pctx_fini_lwpfn_t *)default_int);
357 
358 	return (0);
359 }
360 
361 static sigset_t termsig;
362 
363 static void
364 __libpctx_init(void)
365 {
366 	/*
367 	 * Initialize the signal set used to shield ourselves from
368 	 * death-by-terminal-signal while the agent lwp is running.
369 	 */
370 	(void) sigemptyset(&termsig);
371 	(void) sigaddset(&termsig, SIGHUP);
372 	(void) sigaddset(&termsig, SIGTERM);
373 	(void) sigaddset(&termsig, SIGINT);
374 	(void) sigaddset(&termsig, SIGQUIT);
375 }
376 
377 #pragma init(__libpctx_init)
378 
379 static void
380 pctx_begin_syscalls(pctx_t *pctx)
381 {
382 	if (pctx->Pr == NULL)
383 		return;
384 	if (pctx->sigblocked++ == 0) {
385 		(void) sigprocmask(SIG_BLOCK, &termsig, &pctx->savedset);
386 		(void) Pcreate_agent(pctx->Pr);
387 	}
388 }
389 
390 static void
391 pctx_end_syscalls(pctx_t *pctx)
392 {
393 	if (pctx->Pr == NULL)
394 		return;
395 	if (--pctx->sigblocked == 0) {
396 		(void) Pdestroy_agent(pctx->Pr);
397 		(void) sigprocmask(SIG_SETMASK, &pctx->savedset, NULL);
398 	}
399 }
400 
401 /*
402  * Iterate over the valid lwpids in the process, invoking the
403  * action function on each one.
404  */
405 static int
406 pctx_lwpiterate(pctx_t *pctx, int (*action)(pctx_t *, pid_t, id_t, void *))
407 {
408 	const pstatus_t *pstatus;
409 	char lstatus[64];
410 	struct stat statb;
411 	lwpstatus_t *lwps;
412 	prheader_t *prh;
413 	int fd, nlwp;
414 	int ret = 0;
415 
416 	if (action == (int (*)(pctx_t *, pid_t, id_t, void *))default_int)
417 		return (0);
418 
419 	pstatus = Pstatus(pctx->Pr);
420 	if (pstatus->pr_nlwp <= 1) {
421 		pctx_begin_syscalls(pctx);
422 		ret = action(pctx, pstatus->pr_pid, 1, pctx->uarg);
423 		pctx_end_syscalls(pctx);
424 		return (ret);
425 	}
426 
427 	(void) snprintf(lstatus, sizeof (lstatus),
428 	    "/proc/%d/lstatus", (int)pstatus->pr_pid);
429 
430 	if ((fd = open(lstatus, O_RDONLY)) < 0 ||
431 	    fstat(fd, &statb) != 0) {
432 		if (fd >= 0)
433 			(void) close(fd);
434 		return (-1);
435 	}
436 
437 	prh = malloc(statb.st_size);
438 	if (read(fd, prh, statb.st_size) <
439 	    sizeof (prheader_t) + sizeof (lwpstatus_t)) {
440 		(void) close(fd);
441 		free(prh);
442 		return (-1);
443 	}
444 	(void) close(fd);
445 
446 	/* LINTED pointer cast may result in improper alignment */
447 	lwps = (lwpstatus_t *)(prh + 1);
448 	pctx_begin_syscalls(pctx);
449 	for (nlwp = prh->pr_nent; nlwp > 0; nlwp--) {
450 		if (action(pctx,
451 		    pstatus->pr_pid, lwps->pr_lwpid, pctx->uarg) != 0)
452 			ret = -1;
453 		/* LINTED pointer cast may result in improper alignment */
454 		lwps = (lwpstatus_t *)((char *)lwps + prh->pr_entsize);
455 	}
456 	pctx_end_syscalls(pctx);
457 	free(prh);
458 	return (ret);
459 }
460 
461 /*
462  * Free any associated state, but leave the process stopped if it
463  * is still under our control.  (If it isn't under our control,
464  * it should just run to completion when we do our last close)
465  */
466 static void
467 pctx_free(pctx_t *pctx)
468 {
469 	if (pctx->cpc != NULL && pctx_cpc_callback != NULL)
470 		(*pctx_cpc_callback)(pctx->cpc, pctx);
471 	if (pctx->Pr) {
472 		Pfree(pctx->Pr);
473 		pctx->Pr = NULL;
474 	}
475 	pctx->errfn = pctx_default_errfn;
476 }
477 
478 /*
479  * Completely release the process from our control and discard all our state
480  */
481 void
482 pctx_release(pctx_t *pctx)
483 {
484 	if (pctx->Pr) {
485 		Prelease(pctx->Pr, PRELEASE_CLEAR);
486 		pctx->Pr = NULL;
487 	}
488 	pctx_free(pctx);
489 	bzero(pctx, sizeof (*pctx));
490 	free(pctx);
491 }
492 
493 static void
494 msincr(struct timeval *tv, uint_t msec)
495 {
496 	tv->tv_sec += msec / MILLISEC;
497 	tv->tv_usec += (msec % MILLISEC) * MILLISEC;
498 	if (tv->tv_usec > MICROSEC) {
499 		tv->tv_sec++;
500 		tv->tv_usec -= MICROSEC;
501 	}
502 }
503 
504 static uint_t
505 msdiff(struct timeval *tva, struct timeval *tvb)
506 {
507 	time_t sdiff = tva->tv_sec - tvb->tv_sec;
508 	suseconds_t udiff = tva->tv_usec - tvb->tv_usec;
509 
510 	if (sdiff < 0)
511 		return (0);
512 	if (udiff < 0) {
513 		udiff += MICROSEC;
514 		sdiff--;
515 	}
516 	if (sdiff < 0)
517 		return (0);
518 	if (sdiff >= (INT_MAX / MILLISEC))
519 		return ((uint_t)INT_MAX);
520 	return ((uint_t)(sdiff * MILLISEC + udiff / MILLISEC));
521 }
522 
523 int
524 pctx_run(
525 	pctx_t *pctx,
526 	uint_t msec,
527 	uint_t nsamples,
528 	int (*tick)(pctx_t *, pid_t, id_t, void *))
529 {
530 	static const char fn[] = "run";
531 	struct timeval tvgoal, tvnow;
532 	uint_t mswait = 0;
533 	int running = 1;
534 	const pstatus_t *pstatus;
535 	psinfo_t psinfo;
536 	void (*sigsaved)();
537 	id_t lwpid;
538 	pid_t pid = Pstatus(pctx->Pr)->pr_pid;
539 	int pstate;
540 
541 	if (msec == 0)
542 		nsamples = 0;
543 	if (nsamples == 0)
544 		nsamples = UINT_MAX;
545 
546 	/*
547 	 * Casually discard any knowledge of the children we create
548 	 */
549 	sigsaved = signal(SIGCHLD, SIG_IGN);
550 
551 	/*
552 	 * Since we've just "discovered" this process which might have
553 	 * been running for weeks, deliver some init_lwp events so
554 	 * that our caller gets a handle on the process.
555 	 */
556 	if (pctx_lwpiterate(pctx, pctx->init_lwp) != 0) {
557 		if (pctx->verbose)
558 			pctx_error(pctx, fn,
559 			    gettext("%d: lwp discovery failed\n"), (int)pid);
560 		goto bailout;
561 	}
562 
563 	if (msec != 0) {
564 		/*
565 		 * tvgoal represents the time at which the sample
566 		 * should next be taken.
567 		 */
568 		(void) gettimeofday(&tvgoal, 0);
569 		msincr(&tvgoal, msec);
570 	}
571 
572 	while (running) {
573 
574 		if (Psetrun(pctx->Pr, 0, 0) != 0) {
575 			if (pctx->verbose)
576 				pctx_error(pctx, fn,
577 				    gettext("%d: Psetrun\n"), (int)pid);
578 			break;
579 		}
580 
581 		if (msec != 0) {
582 			/*
583 			 * This timing loop attempts to estimate the number
584 			 * of milliseconds between our "goal" time (when
585 			 * we should stop the process and run the tick
586 			 * routine) and the current time.
587 			 *
588 			 * If we ever find ourselves running behind i.e. we
589 			 * missed our goal, then we skip ahead to the next
590 			 * goal instead.
591 			 */
592 			do {
593 				(void) gettimeofday(&tvnow, 0);
594 				if ((mswait = msdiff(&tvgoal, &tvnow)) == 0) {
595 					msincr(&tvgoal, msec);
596 					/*
597 					 * Skip ahead to the next goal, unless
598 					 * there is only one more sample left
599 					 * to take.
600 					 */
601 					if (nsamples != 1)
602 						nsamples--;
603 				}
604 			} while (mswait == 0);
605 		}
606 
607 		(void) Pwait(pctx->Pr, mswait);
608 
609 checkstate:
610 		switch (pstate = Pstate(pctx->Pr)) {
611 		case PS_RUN:
612 			/*
613 			 * Try again, but wait for up to 5 seconds.
614 			 */
615 			if (Pstop(pctx->Pr, 5 * MILLISEC) == -1 ||
616 			    (pstate = Pstate(pctx->Pr)) != PS_STOP) {
617 				pctx_error(pctx, fn,
618 				    gettext("%d: won't stop\n"), (int)pid);
619 			}
620 			break;
621 		case PS_STOP:
622 			break;
623 		case PS_LOST:
624 			/*
625 			 * Lost control - probably execed a setuid/setgid
626 			 * executable.  Try and get control back again,
627 			 * else bail ..
628 			 */
629 			(void) Preopen(pctx->Pr);
630 			if ((pstate = Pstate(pctx->Pr)) != PS_LOST)
631 				goto checkstate;
632 			pctx_error(pctx, fn,
633 			    gettext("%d: execed a program that cannot "
634 			    "be tracked\n"), (int)pid);
635 			running = 0;
636 			break;
637 		case PS_UNDEAD:
638 		case PS_DEAD:
639 			if (pctx->verbose)
640 				pctx_error(pctx, fn,
641 				    gettext("%d: process terminated\n"),
642 				    (int)pid);
643 			running = 0;
644 			break;
645 		default:
646 			if (pctx->verbose)
647 				pctx_error(pctx, fn,
648 				    gettext("%d: process state 0x%x?\n"),
649 				    (int)pid, pstate);
650 			break;
651 		}
652 
653 		if (pstate != PS_STOP)
654 			break;
655 
656 		pstatus = Pstatus(pctx->Pr);
657 		lwpid = pstatus->pr_lwp.pr_lwpid;
658 		switch (pstatus->pr_lwp.pr_why) {
659 		case PR_REQUESTED:
660 			msincr(&tvgoal, msec);
661 			if (pstatus->pr_flags & PR_VFORKP) {
662 				/*
663 				 * The process is in a vfork stupor until
664 				 * its child releases it via an exec.
665 				 * Don't sample it while it's in this state
666 				 * - we won't be able to create the agent.
667 				 */
668 				break;
669 			}
670 			if (pctx_lwpiterate(pctx, tick) != 0)
671 				running = 0;
672 			if (--nsamples == 0)
673 				running = 0;
674 			break;
675 		case PR_SYSENTRY:
676 			switch (pstatus->pr_lwp.pr_what) {
677 			case SYS_lwp_exit:
678 				pctx_begin_syscalls(pctx);
679 				(void) pctx->fini_lwp(pctx,
680 				    pid, lwpid, pctx->uarg);
681 				(void) pctx->lwp_exit(pctx,
682 				    pid, lwpid, pctx->uarg);
683 				pctx_end_syscalls(pctx);
684 				break;
685 			case SYS_exit:
686 				(void) pctx_lwpiterate(pctx, pctx->fini_lwp);
687 				pctx->exit(pctx, pid, lwpid,
688 				    (int)pstatus->pr_lwp.pr_sysarg[0],
689 				    pctx->uarg);
690 				running = 0;
691 				break;
692 			case SYS_exec:
693 			case SYS_execve:
694 				(void) pctx_lwpiterate(pctx, pctx->fini_lwp);
695 				break;
696 			default:
697 				pctx_error(pctx, fn,
698 				    "warning - pid %d sysentry(%d)\n",
699 				    (int)pid, pstatus->pr_lwp.pr_what);
700 				break;
701 			}
702 			break;
703 		case PR_SYSEXIT:
704 			switch (pstatus->pr_lwp.pr_what) {
705 			case SYS_exec:
706 			case SYS_execve:
707 				if (pstatus->pr_lwp.pr_errno) {
708 					/*
709 					 * The exec failed completely.
710 					 * Reinstate the lwps we fini'd
711 					 * at exec entrance
712 					 */
713 					running = pctx_lwpiterate(pctx,
714 					    pctx->init_lwp) == 0;
715 					break;
716 				}
717 				if (pctx->exec == (pctx_sysc_execfn_t *)
718 				    default_int) {
719 					running = 0;
720 					break;
721 				}
722 				(void) memcpy(&psinfo,
723 				    Ppsinfo(pctx->Pr), sizeof (psinfo));
724 				proc_unctrl_psinfo(&psinfo);
725 				pctx_begin_syscalls(pctx);
726 				running = pctx->exec(pctx, pid,
727 				    lwpid, psinfo.pr_psargs, pctx->uarg) == 0;
728 				running = running && pctx->init_lwp(pctx,
729 				    pid, 1, pctx->uarg) == 0;
730 				pctx_end_syscalls(pctx);
731 				break;
732 			case SYS_lwp_create:
733 				if (pstatus->pr_lwp.pr_errno ||
734 				    pstatus->pr_lwp.pr_rval1)
735 					break;
736 				pctx_begin_syscalls(pctx);
737 				running = pctx->init_lwp(pctx,
738 				    pid, lwpid, pctx->uarg) == 0;
739 				running = running && pctx->lwp_create(pctx,
740 				    pid, lwpid, pctx->uarg) == 0;
741 				pctx_end_syscalls(pctx);
742 				break;
743 			case SYS_forkall:
744 			case SYS_vfork:
745 			case SYS_fork1:
746 				if (pstatus->pr_lwp.pr_errno)
747 					break;
748 				(void) fflush(NULL);
749 				switch (fork1()) {
750 					pid_t ppid;
751 					int wascreated;
752 					pctx_sysc_forkfn_t *forkfn;
753 				case 0:
754 					ppid = pid;
755 					pid = pstatus->pr_lwp.pr_rval1;
756 					wascreated = pctx->created;
757 					forkfn = pctx->fork;
758 					pctx_free(pctx);
759 					pctx = pctx_capture(pid, pctx->uarg,
760 					    pctx->verbose, pctx->errfn);
761 					if (pctx != NULL) {
762 						if (wascreated) {
763 							/*
764 							 * Set kill on last
765 							 * close so -all-
766 							 * children die.
767 							 */
768 							pctx->created = 1;
769 							(void) Psetflags(
770 							    pctx->Pr, PR_KLC);
771 						}
772 						(*forkfn)(pctx, ppid, pid,
773 						    lwpid, pctx->uarg);
774 						pctx_release(pctx);
775 					}
776 					_exit(0);
777 					/*NOTREACHED*/
778 				case -1:
779 					pctx_error(pctx, fn,
780 					    "cannot follow pid %d: %s\n",
781 					    (int)pstatus->pr_lwp.pr_rval1,
782 					    strerror(errno));
783 					break;
784 				default:
785 					break;
786 				}
787 				break;
788 			default:
789 				pctx_error(pctx, fn, gettext(
790 				    "warning - pid %d sysexit(%d)\n"),
791 				    (int)pid, pstatus->pr_lwp.pr_what);
792 				break;
793 			}
794 			break;
795 		case PR_SIGNALLED:
796 			if (pctx->verbose)
797 				pctx_error(pctx, fn,
798 				    gettext("pid %d - signalled\n"), (int)pid);
799 			break;
800 		case PR_JOBCONTROL:
801 			if (pctx->verbose)
802 				pctx_error(pctx, fn,
803 				    gettext("pid %d - job control stop\n"),
804 				    (int)pid);
805 			running = 0;
806 			break;
807 		case PR_FAULTED:
808 			if (pctx->verbose)
809 				pctx_error(pctx, fn,
810 				    gettext("pid %d - faulted\n"), (int)pid);
811 			break;
812 		case PR_SUSPENDED:
813 			if (pctx->verbose)
814 				pctx_error(pctx, fn,
815 				    gettext("pid %d - suspended\n"), (int)pid);
816 			break;
817 		case PR_CHECKPOINT:
818 			if (pctx->verbose)
819 				pctx_error(pctx, fn,
820 				    gettext("pid %d - checkpoint\n"),
821 				    (int)pid);
822 			break;
823 		default:
824 			if (pctx->verbose)
825 				pctx_error(pctx, fn,
826 				    gettext("pid %d - reason %d\n"),
827 				    (int)pid, pstatus->pr_lwp.pr_why);
828 			running = 0;
829 			break;
830 		}
831 	}
832 
833 bailout:
834 	(void) signal(SIGCHLD, sigsaved);
835 	if (!running)
836 		return (0);
837 
838 	pctx_error(pctx, fn, gettext("lost control of pid %d\n"), (int)pid);
839 	pctx_free(pctx);
840 	return (-1);
841 }
842 
843 /*
844  * Execute the private 'cpc' system call in the context of the
845  * controlled process.
846  */
847 int
848 __pctx_cpc(pctx_t *pctx, cpc_t *cpc,
849     int cmd, id_t lwpid, void *data1, void *data2, void *data3, int bufsize)
850 {
851 	sysret_t rval;
852 	argdes_t argd[5];
853 	argdes_t *adp = &argd[0];
854 	int error;
855 
856 	/*
857 	 * Keep track of the relationship between cpc_t and pctx_t here.
858 	 * We store the last cpc_t used by libpctx, so that when this pctx is
859 	 * destroyed, libpctx can notify libcpc.
860 	 */
861 	if (pctx->cpc != NULL && pctx->cpc != cpc && pctx_cpc_callback != NULL)
862 		(*pctx_cpc_callback)(pctx->cpc, pctx);
863 	pctx->cpc = cpc;
864 
865 	/*
866 	 * cmd and lwpid are passed in by value no matter what the command is.
867 	 */
868 	adp->arg_value = cmd;
869 	adp->arg_object = NULL;
870 	adp->arg_type = AT_BYVAL;
871 	adp->arg_inout = AI_INPUT;
872 	adp->arg_size = 0;
873 	adp++;
874 
875 	adp->arg_value = lwpid;
876 	adp->arg_object = NULL;
877 	adp->arg_type = AT_BYVAL;
878 	adp->arg_inout = AI_INPUT;
879 	adp->arg_size = 0;
880 	adp++;
881 
882 	switch (cmd) {
883 	case CPC_BIND:
884 		adp->arg_value = 0;
885 		adp->arg_object = data1;
886 		adp->arg_type = AT_BYREF;
887 		adp->arg_inout = AI_INPUT;
888 		adp->arg_size = (size_t)data2;
889 		adp++;
890 
891 		adp->arg_value = (size_t)data2;
892 		adp->arg_object = NULL;
893 		adp->arg_type = AT_BYVAL;
894 		adp->arg_inout = AI_INPUT;
895 		adp->arg_size = 0;
896 		adp++;
897 
898 		adp->arg_value = 0;
899 		adp->arg_object = data3;
900 		adp->arg_type = AT_BYREF;
901 		adp->arg_inout = AI_INOUT;
902 		adp->arg_size = sizeof (int);
903 
904 		break;
905 	case CPC_SAMPLE:
906 		adp->arg_value = 0;
907 		adp->arg_object = data1;
908 		adp->arg_type = AT_BYREF;
909 		adp->arg_inout = AI_OUTPUT;
910 		adp->arg_size = bufsize;
911 		adp++;
912 
913 		adp->arg_value = 0;
914 		adp->arg_object = data2;
915 		adp->arg_type = AT_BYREF;
916 		adp->arg_inout = AI_OUTPUT;
917 		adp->arg_size = sizeof (hrtime_t);
918 		adp++;
919 
920 		adp->arg_value = 0;
921 		adp->arg_object = data3;
922 		adp->arg_type = AT_BYREF;
923 		adp->arg_inout = AI_OUTPUT;
924 		adp->arg_size = sizeof (uint64_t);
925 
926 		break;
927 	default:
928 		adp->arg_value = 0;
929 		adp->arg_object = 0;
930 		adp->arg_type = AT_BYVAL;
931 		adp->arg_inout = AI_INPUT;
932 		adp->arg_size = 0;
933 		adp++;
934 
935 		adp->arg_value = 0;
936 		adp->arg_object = 0;
937 		adp->arg_type = AT_BYVAL;
938 		adp->arg_inout = AI_INPUT;
939 		adp->arg_size = 0;
940 		adp++;
941 
942 		adp->arg_value = 0;
943 		adp->arg_object = 0;
944 		adp->arg_type = AT_BYVAL;
945 		adp->arg_inout = AI_INPUT;
946 		adp->arg_size = 0;
947 
948 		break;
949 	}
950 
951 	error = Psyscall(pctx->Pr, &rval, SYS_cpc, 5, &argd[0]);
952 
953 	if (error) {
954 		errno = error > 0 ? error : ENOSYS;
955 		return (-1);
956 	}
957 	return (rval.sys_rval1);
958 }
959 
960 /*
961  * libcpc-private hook used to register a callback. The callback is used to
962  * notify libcpc when a pctx handle is invalidated.
963  */
964 void
965 __pctx_cpc_register_callback(void (*arg)(struct __cpc *, struct __pctx *))
966 {
967 	pctx_cpc_callback = arg;
968 }
969