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