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.
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.
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]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * This file contains a set of generic routines for periodically
29 * sampling the state of another process, or tree of processes.
31 * It is built upon the infrastructure provided by libproc.
35 #include <sys/syscall.h>
49 #include <sys/cpc_impl.h>
55 struct ps_prochandle
*Pr
;
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
;
72 static void (*pctx_cpc_callback
)(cpc_t
*cpc
, struct __pctx
*pctx
);
75 pctx_default_errfn(const char *fn
, const char *fmt
, va_list ap
)
77 (void) fprintf(stderr
, "libpctx: pctx_%s: ", fn
);
78 (void) vfprintf(stderr
, fmt
, ap
);
83 pctx_error(pctx_t
*pctx
, const char *fn
, const char *fmt
, ...)
88 pctx
->errfn(fn
, fmt
, ap
);
93 * Create a new process and bind the user args for it
103 static const char fn
[] = "create";
107 pctx
= calloc(1, sizeof (*pctx
));
109 pctx
->verbose
= verbose
;
111 pctx
->errfn
= errfn
? errfn
: pctx_default_errfn
;
113 if ((pctx
->Pr
= Pcreate(filename
, argv
, &err
, 0, 0)) == NULL
) {
116 pctx_error(pctx
, fn
, gettext("cannot trace set-id or "
117 "unreadable program '%s'\n"), filename
);
120 pctx_error(pctx
, fn
, gettext("cannot control LP64 "
121 "program '%s'\n"), filename
);
124 pctx_error(pctx
, fn
, gettext("cannot execute "
125 "program '%s'\n"), filename
);
128 pctx_error(pctx
, fn
, gettext("cannot find"
129 "program '%s'\n"), filename
);
132 pctx_error(pctx
, fn
, gettext("cannot fork, "
133 "program '%s'\n"), filename
);
136 pctx_error(pctx
, fn
, gettext("%s, program '%s'\n"),
137 Pcreate_error(err
), filename
);
144 if (Psysentry(pctx
->Pr
, SYS_exit
, 1) == -1) {
146 gettext("can't stop-on-exit() program '%s'\n"), filename
);
147 Prelease(pctx
->Pr
, PRELEASE_KILL
);
152 * Set kill-on-last-close so the controlled process
156 (void) Psetflags(pctx
->Pr
, PR_KLC
);
157 (void) pctx_set_events(pctx
, PCTX_NULL_EVENT
);
163 * Capture an existing process and bind the user args for it
166 pctx_capture(pid_t pid
, void *arg
, int verbose
, pctx_errfn_t
*errfn
)
168 static const char fn
[] = "capture";
172 pctx
= calloc(1, sizeof (*pctx
));
174 pctx
->verbose
= verbose
;
175 pctx
->errfn
= errfn
? errfn
: pctx_default_errfn
;
177 if ((pctx
->Pr
= Pgrab(pid
, 0, &err
)) == NULL
) {
181 gettext("pid %d doesn't exist\n"), (int)pid
);
185 gettext("pid %d is a zombie\n"), (int)pid
);
189 gettext("pid %d: permission denied\n"), (int)pid
);
193 gettext("pid %d is already being traced\n"),
198 gettext("pid %d is a system process\n"), (int)pid
);
202 gettext("cannot capture self!\n"));
205 pctx_error(pctx
, fn
, gettext("cannot control LP64 "
206 "process, pid %d\n"), (int)pid
);
209 pctx_error(pctx
, fn
, gettext("%s: pid %d\n"),
210 Pgrab_error(err
), (int)pid
);
217 if (Psysentry(pctx
->Pr
, SYS_exit
, 1) == -1) {
219 gettext("can't stop-on-exit() pid %d\n"), (int)pid
);
220 Prelease(pctx
->Pr
, PRELEASE_CLEAR
);
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.
232 (void) Psetflags(pctx
->Pr
, PR_RLC
);
233 (void) pctx_set_events(pctx
, PCTX_NULL_EVENT
);
240 default_void(pctx_t
*pctx
)
245 default_int(pctx_t
*pctx
)
251 pctx_set_events(pctx_t
*pctx
, ...)
253 static const char fn
[] = "set_events";
258 va_start(pvar
, pctx
);
260 switch (event
= (pctx_event_t
)va_arg(pvar
, pctx_event_t
)) {
261 case PCTX_NULL_EVENT
:
263 case PCTX_SYSC_EXEC_EVENT
:
264 pctx
->exec
= (pctx_sysc_execfn_t
*)
265 va_arg(pvar
, pctx_sysc_execfn_t
*);
267 case PCTX_SYSC_FORK_EVENT
:
268 pctx
->fork
= (pctx_sysc_forkfn_t
*)
269 va_arg(pvar
, pctx_sysc_forkfn_t
*);
271 case PCTX_SYSC_EXIT_EVENT
: /* always intercepted */
272 pctx
->exit
= (pctx_sysc_exitfn_t
*)
273 va_arg(pvar
, pctx_sysc_exitfn_t
*);
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
*);
279 case PCTX_INIT_LWP_EVENT
:
280 pctx
->init_lwp
= (pctx_init_lwpfn_t
*)
281 va_arg(pvar
, pctx_init_lwpfn_t
*);
283 case PCTX_FINI_LWP_EVENT
:
284 pctx
->fini_lwp
= (pctx_fini_lwpfn_t
*)
285 va_arg(pvar
, pctx_fini_lwpfn_t
*);
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
*);
293 gettext("unknown event type %x\n"), event
);
297 } while (event
!= PCTX_NULL_EVENT
&& error
== 0);
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
;
318 if (pctx
->fork
!= (pctx_sysc_forkfn_t
*)default_void
) {
319 (void) Psysexit(pctx
->Pr
, SYS_vfork
, 1);
320 (void) Psysexit(pctx
->Pr
, SYS_forksys
, 1);
321 if (Psetflags(pctx
->Pr
, PR_FORK
) == -1)
324 (void) Psysexit(pctx
->Pr
, SYS_vfork
, 0);
325 (void) Psysexit(pctx
->Pr
, SYS_forksys
, 0);
326 if (Punsetflags(pctx
->Pr
, PR_FORK
) == -1)
331 * exec causes termination of all but the exec-ing lwp,
332 * and resets the lwpid to one in the new address space.
334 if (pctx
->exec
!= (pctx_sysc_execfn_t
*)default_int
||
335 pctx
->fini_lwp
!= (pctx_fini_lwpfn_t
*)default_int
||
336 pctx
->init_lwp
!= (pctx_init_lwpfn_t
*)default_int
) {
337 (void) Psysexit(pctx
->Pr
, SYS_execve
, 1);
338 (void) Psysentry(pctx
->Pr
, SYS_execve
, 1);
340 (void) Psysexit(pctx
->Pr
, SYS_execve
, 0);
341 (void) Psysentry(pctx
->Pr
, SYS_execve
, 0);
344 (void) Psysexit(pctx
->Pr
, SYS_lwp_create
,
345 pctx
->lwp_create
!= (pctx_sysc_lwp_createfn_t
*)default_int
||
346 pctx
->init_lwp
!= (pctx_init_lwpfn_t
*)default_int
);
348 (void) Psysentry(pctx
->Pr
, SYS_lwp_exit
,
349 pctx
->lwp_exit
!= (pctx_sysc_lwp_exitfn_t
*)default_int
||
350 pctx
->fini_lwp
!= (pctx_fini_lwpfn_t
*)default_int
);
355 static sigset_t termsig
;
361 * Initialize the signal set used to shield ourselves from
362 * death-by-terminal-signal while the agent lwp is running.
364 (void) sigemptyset(&termsig
);
365 (void) sigaddset(&termsig
, SIGHUP
);
366 (void) sigaddset(&termsig
, SIGTERM
);
367 (void) sigaddset(&termsig
, SIGINT
);
368 (void) sigaddset(&termsig
, SIGQUIT
);
371 #pragma init(__libpctx_init)
374 pctx_begin_syscalls(pctx_t
*pctx
)
376 if (pctx
->Pr
== NULL
)
378 if (pctx
->sigblocked
++ == 0) {
379 (void) sigprocmask(SIG_BLOCK
, &termsig
, &pctx
->savedset
);
380 (void) Pcreate_agent(pctx
->Pr
);
385 pctx_end_syscalls(pctx_t
*pctx
)
387 if (pctx
->Pr
== NULL
)
389 if (--pctx
->sigblocked
== 0) {
390 (void) Pdestroy_agent(pctx
->Pr
);
391 (void) sigprocmask(SIG_SETMASK
, &pctx
->savedset
, NULL
);
396 * Iterate over the valid lwpids in the process, invoking the
397 * action function on each one.
400 pctx_lwpiterate(pctx_t
*pctx
, int (*action
)(pctx_t
*, pid_t
, id_t
, void *))
402 const pstatus_t
*pstatus
;
410 if (action
== (int (*)(pctx_t
*, pid_t
, id_t
, void *))default_int
)
413 pstatus
= Pstatus(pctx
->Pr
);
414 if (pstatus
->pr_nlwp
<= 1) {
415 pctx_begin_syscalls(pctx
);
416 ret
= action(pctx
, pstatus
->pr_pid
, 1, pctx
->uarg
);
417 pctx_end_syscalls(pctx
);
421 (void) snprintf(lstatus
, sizeof (lstatus
),
422 "/proc/%d/lstatus", (int)pstatus
->pr_pid
);
424 if ((fd
= open(lstatus
, O_RDONLY
)) < 0 ||
425 fstat(fd
, &statb
) != 0) {
431 prh
= malloc(statb
.st_size
);
432 if (read(fd
, prh
, statb
.st_size
) <
433 sizeof (prheader_t
) + sizeof (lwpstatus_t
)) {
440 /* LINTED pointer cast may result in improper alignment */
441 lwps
= (lwpstatus_t
*)(prh
+ 1);
442 pctx_begin_syscalls(pctx
);
443 for (nlwp
= prh
->pr_nent
; nlwp
> 0; nlwp
--) {
445 pstatus
->pr_pid
, lwps
->pr_lwpid
, pctx
->uarg
) != 0)
447 /* LINTED pointer cast may result in improper alignment */
448 lwps
= (lwpstatus_t
*)((char *)lwps
+ prh
->pr_entsize
);
450 pctx_end_syscalls(pctx
);
456 * Free any associated state, but leave the process stopped if it
457 * is still under our control. (If it isn't under our control,
458 * it should just run to completion when we do our last close)
461 pctx_free(pctx_t
*pctx
)
463 if (pctx
->cpc
!= NULL
&& pctx_cpc_callback
!= NULL
)
464 (*pctx_cpc_callback
)(pctx
->cpc
, pctx
);
469 pctx
->errfn
= pctx_default_errfn
;
473 * Completely release the process from our control and discard all our state
476 pctx_release(pctx_t
*pctx
)
479 Prelease(pctx
->Pr
, PRELEASE_CLEAR
);
484 bzero(pctx
, sizeof (*pctx
));
489 msincr(struct timeval
*tv
, uint_t msec
)
491 tv
->tv_sec
+= msec
/ MILLISEC
;
492 tv
->tv_usec
+= (msec
% MILLISEC
) * MILLISEC
;
493 if (tv
->tv_usec
> MICROSEC
) {
495 tv
->tv_usec
-= MICROSEC
;
500 msdiff(struct timeval
*tva
, struct timeval
*tvb
)
502 time_t sdiff
= tva
->tv_sec
- tvb
->tv_sec
;
503 suseconds_t udiff
= tva
->tv_usec
- tvb
->tv_usec
;
513 if (sdiff
>= (INT_MAX
/ MILLISEC
))
514 return ((uint_t
)INT_MAX
);
515 return ((uint_t
)(sdiff
* MILLISEC
+ udiff
/ MILLISEC
));
523 int (*tick
)(pctx_t
*, pid_t
, id_t
, void *))
525 static const char fn
[] = "run";
526 struct timeval tvgoal
, tvnow
;
529 const pstatus_t
*pstatus
;
533 pid_t pid
= Pstatus(pctx
->Pr
)->pr_pid
;
542 * Casually discard any knowledge of the children we create
544 sigsaved
= signal(SIGCHLD
, SIG_IGN
);
547 * Since we've just "discovered" this process which might have
548 * been running for weeks, deliver some init_lwp events so
549 * that our caller gets a handle on the process.
551 if (pctx_lwpiterate(pctx
, pctx
->init_lwp
) != 0) {
554 gettext("%d: lwp discovery failed\n"), (int)pid
);
560 * tvgoal represents the time at which the sample
561 * should next be taken.
563 (void) gettimeofday(&tvgoal
, 0);
564 msincr(&tvgoal
, msec
);
568 * The event handling loop continues while running is 1.
569 * running becomes 0 when either the controlled process has
570 * exited successfully or the number of time samples has expired.
571 * Otherwise, if an error has occurred, running becomes -1.
573 while (running
== 1 && !pctx
->terminate
) {
575 if (Psetrun(pctx
->Pr
, 0, 0) != 0) {
578 gettext("%d: Psetrun\n"), (int)pid
);
584 * This timing loop attempts to estimate the number
585 * of milliseconds between our "goal" time (when
586 * we should stop the process and run the tick
587 * routine) and the current time.
589 * If we ever find ourselves running behind i.e. we
590 * missed our goal, then we skip ahead to the next
594 (void) gettimeofday(&tvnow
, 0);
595 if ((mswait
= msdiff(&tvgoal
, &tvnow
)) == 0) {
596 msincr(&tvgoal
, msec
);
598 * Skip ahead to the next goal, unless
599 * there is only one more sample left
605 } while (mswait
== 0 && !pctx
->terminate
);
611 (void) Pwait(pctx
->Pr
, mswait
);
614 switch (pstate
= Pstate(pctx
->Pr
)) {
617 * Try again, but wait for up to 5 seconds.
619 if (Pstop(pctx
->Pr
, 5 * MILLISEC
) == -1 ||
620 (pstate
= Pstate(pctx
->Pr
)) != PS_STOP
) {
622 gettext("%d: won't stop\n"), (int)pid
);
629 * Lost control - probably execed a setuid/setgid
630 * executable. Try and get control back again,
633 (void) Preopen(pctx
->Pr
);
634 if ((pstate
= Pstate(pctx
->Pr
)) != PS_LOST
)
637 gettext("%d: execed a program that cannot "
638 "be tracked\n"), (int)pid
);
645 gettext("%d: process terminated\n"),
652 gettext("%d: process state 0x%x?\n"),
657 if (pstate
!= PS_STOP
)
660 pstatus
= Pstatus(pctx
->Pr
);
661 lwpid
= pstatus
->pr_lwp
.pr_lwpid
;
662 switch (pstatus
->pr_lwp
.pr_why
) {
664 msincr(&tvgoal
, msec
);
665 if (pstatus
->pr_flags
& PR_VFORKP
) {
667 * The process is in a vfork stupor until
668 * its child releases it via an exec.
669 * Don't sample it while it's in this state
670 * - we won't be able to create the agent.
674 if (pctx_lwpiterate(pctx
, tick
) != 0)
676 if (running
== 1 && --nsamples
== 0)
680 switch (pstatus
->pr_lwp
.pr_what
) {
682 pctx_begin_syscalls(pctx
);
683 (void) pctx
->fini_lwp(pctx
,
684 pid
, lwpid
, pctx
->uarg
);
685 (void) pctx
->lwp_exit(pctx
,
686 pid
, lwpid
, pctx
->uarg
);
687 pctx_end_syscalls(pctx
);
690 if (pctx_lwpiterate(pctx
, pctx
->fini_lwp
)
693 pctx
->exit(pctx
, pid
, lwpid
,
694 (int)pstatus
->pr_lwp
.pr_sysarg
[0],
700 (void) pctx_lwpiterate(pctx
, pctx
->fini_lwp
);
704 "warning - pid %d sysentry(%d)\n",
705 (int)pid
, pstatus
->pr_lwp
.pr_what
);
710 switch (pstatus
->pr_lwp
.pr_what
) {
712 if (pstatus
->pr_lwp
.pr_errno
) {
714 * The exec failed completely.
715 * Reinstate the lwps we fini'd
718 if (pctx_lwpiterate(pctx
,
719 pctx
->init_lwp
) == 0)
725 if (pctx
->exec
== (pctx_sysc_execfn_t
*)
730 (void) memcpy(&psinfo
,
731 Ppsinfo(pctx
->Pr
), sizeof (psinfo
));
732 proc_unctrl_psinfo(&psinfo
);
733 pctx_begin_syscalls(pctx
);
734 if (pctx
->exec(pctx
, pid
, lwpid
,
735 psinfo
.pr_psargs
, pctx
->uarg
) != 0)
737 if (running
== 1 && pctx
->init_lwp(pctx
,
738 pid
, 1, pctx
->uarg
) != 0)
740 pctx_end_syscalls(pctx
);
743 if (pstatus
->pr_lwp
.pr_errno
||
744 pstatus
->pr_lwp
.pr_rval1
)
746 pctx_begin_syscalls(pctx
);
747 if (pctx
->init_lwp(pctx
, pid
, lwpid
,
750 if (running
== 1 && pctx
->lwp_create(pctx
,
751 pid
, lwpid
, pctx
->uarg
) != 0)
753 pctx_end_syscalls(pctx
);
757 if (pstatus
->pr_lwp
.pr_errno
)
763 pctx_sysc_forkfn_t
*forkfn
;
766 pid
= pstatus
->pr_lwp
.pr_rval1
;
767 wascreated
= pctx
->created
;
770 pctx
= pctx_capture(pid
, pctx
->uarg
,
771 pctx
->verbose
, pctx
->errfn
);
783 (*forkfn
)(pctx
, ppid
, pid
,
793 "cannot follow pid %d: %s\n",
794 (int)pstatus
->pr_lwp
.pr_rval1
,
802 pctx_error(pctx
, fn
, gettext(
803 "warning - pid %d sysexit(%d)\n"),
804 (int)pid
, pstatus
->pr_lwp
.pr_what
);
811 gettext("pid %d - signalled\n"), (int)pid
);
816 gettext("pid %d - job control stop\n"),
823 gettext("pid %d - faulted\n"), (int)pid
);
828 gettext("pid %d - suspended\n"), (int)pid
);
833 gettext("pid %d - checkpoint\n"),
839 gettext("pid %d - reason %d\n"),
840 (int)pid
, pstatus
->pr_lwp
.pr_why
);
847 (void) signal(SIGCHLD
, sigsaved
);
858 pctx_error(pctx
, fn
, gettext("lost control of pid %d\n"),
866 * Execute the private 'cpc' system call in the context of the
867 * controlled process.
870 __pctx_cpc(pctx_t
*pctx
, cpc_t
*cpc
,
871 int cmd
, id_t lwpid
, void *data1
, void *data2
, void *data3
, int bufsize
)
875 argdes_t
*adp
= &argd
[0];
879 * Keep track of the relationship between cpc_t and pctx_t here.
880 * We store the last cpc_t used by libpctx, so that when this pctx is
881 * destroyed, libpctx can notify libcpc.
884 if (pctx
->cpc
!= NULL
&& pctx
->cpc
!= cpc
&& pctx_cpc_callback
!= NULL
)
885 (*pctx_cpc_callback
)(pctx
->cpc
, pctx
);
889 * cmd and lwpid are passed in by value no matter what the command is.
891 adp
->arg_value
= cmd
;
892 adp
->arg_object
= NULL
;
893 adp
->arg_type
= AT_BYVAL
;
894 adp
->arg_inout
= AI_INPUT
;
898 adp
->arg_value
= lwpid
;
899 adp
->arg_object
= NULL
;
900 adp
->arg_type
= AT_BYVAL
;
901 adp
->arg_inout
= AI_INPUT
;
908 adp
->arg_object
= data1
;
909 adp
->arg_type
= AT_BYREF
;
910 adp
->arg_inout
= AI_INPUT
;
911 adp
->arg_size
= (size_t)data2
;
914 adp
->arg_value
= (size_t)data2
;
915 adp
->arg_object
= NULL
;
916 adp
->arg_type
= AT_BYVAL
;
917 adp
->arg_inout
= AI_INPUT
;
922 adp
->arg_object
= data3
;
923 adp
->arg_type
= AT_BYREF
;
924 adp
->arg_inout
= AI_INOUT
;
925 adp
->arg_size
= sizeof (int);
930 adp
->arg_object
= data1
;
931 adp
->arg_type
= AT_BYREF
;
932 adp
->arg_inout
= AI_OUTPUT
;
933 adp
->arg_size
= bufsize
;
937 adp
->arg_object
= data2
;
938 adp
->arg_type
= AT_BYREF
;
939 adp
->arg_inout
= AI_OUTPUT
;
940 adp
->arg_size
= sizeof (hrtime_t
);
944 adp
->arg_object
= data3
;
945 adp
->arg_type
= AT_BYREF
;
946 adp
->arg_inout
= AI_OUTPUT
;
947 adp
->arg_size
= sizeof (uint64_t);
953 adp
->arg_type
= AT_BYVAL
;
954 adp
->arg_inout
= AI_INPUT
;
960 adp
->arg_type
= AT_BYVAL
;
961 adp
->arg_inout
= AI_INPUT
;
967 adp
->arg_type
= AT_BYVAL
;
968 adp
->arg_inout
= AI_INPUT
;
974 error
= Psyscall(pctx
->Pr
, &rval
, SYS_cpc
, 5, &argd
[0]);
977 errno
= error
> 0 ? error
: ENOSYS
;
980 return (rval
.sys_rval1
);
984 * libcpc-private hook used to register a callback. The callback is used to
985 * notify libcpc when a pctx handle is invalidated.
988 __pctx_cpc_register_callback(void (*arg
)(struct __cpc
*, struct __pctx
*))
990 pctx_cpc_callback
= arg
;
994 * Tell pctx_run to bail out immediately
997 pctx_terminate(struct __pctx
*pctx
)