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