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