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 /* 23 * Copyright 2007 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 * DTrace Process Control 31 * 32 * This file provides a set of routines that permit libdtrace and its clients 33 * to create and grab process handles using libproc, and to share these handles 34 * between library mechanisms that need libproc access, such as ustack(), and 35 * client mechanisms that need libproc access, such as dtrace(1M) -c and -p. 36 * The library provides several mechanisms in the libproc control layer: 37 * 38 * Reference Counting: The library code and client code can independently grab 39 * the same process handles without interfering with one another. Only when 40 * the reference count drops to zero and the handle is not being cached (see 41 * below for more information on caching) will Prelease() be called on it. 42 * 43 * Handle Caching: If a handle is grabbed PGRAB_RDONLY (e.g. by ustack()) and 44 * the reference count drops to zero, the handle is not immediately released. 45 * Instead, libproc handles are maintained on dph_lrulist in order from most- 46 * recently accessed to least-recently accessed. Idle handles are maintained 47 * until a pre-defined LRU cache limit is exceeded, permitting repeated calls 48 * to ustack() to avoid the overhead of releasing and re-grabbing processes. 49 * 50 * Process Control: For processes that are grabbed for control (~PGRAB_RDONLY) 51 * or created by dt_proc_create(), a control thread is created to provide 52 * callbacks on process exit and symbol table caching on dlopen()s. 53 * 54 * MT-Safety: Libproc is not MT-Safe, so dt_proc_lock() and dt_proc_unlock() 55 * are provided to synchronize access to the libproc handle between libdtrace 56 * code and client code and the control thread's use of the ps_prochandle. 57 * 58 * NOTE: MT-Safety is NOT provided for libdtrace itself, or for use of the 59 * dtrace_proc_grab/dtrace_proc_create mechanisms. Like all exported libdtrace 60 * calls, these are assumed to be MT-Unsafe. MT-Safety is ONLY provided for 61 * synchronization between libdtrace control threads and the client thread. 62 * 63 * The ps_prochandles themselves are maintained along with a dt_proc_t struct 64 * in a hash table indexed by PID. This provides basic locking and reference 65 * counting. The dt_proc_t is also maintained in LRU order on dph_lrulist. 66 * The dph_lrucnt and dph_lrulim count the number of cacheable processes and 67 * the current limit on the number of actively cached entries. 68 * 69 * The control thread for a process establishes breakpoints at the rtld_db 70 * locations of interest, updates mappings and symbol tables at these points, 71 * and handles exec and fork (by always following the parent). The control 72 * thread automatically exits when the process dies or control is lost. 73 * 74 * A simple notification mechanism is provided for libdtrace clients using 75 * dtrace_handle_proc() for notification of PS_UNDEAD or PS_LOST events. If 76 * such an event occurs, the dt_proc_t itself is enqueued on a notification 77 * list and the control thread broadcasts to dph_cv. dtrace_sleep() will wake 78 * up using this condition and will then call the client handler as necessary. 79 */ 80 81 #include <sys/wait.h> 82 #if defined(sun) 83 #include <sys/lwp.h> 84 #endif 85 #include <strings.h> 86 #include <signal.h> 87 #include <assert.h> 88 #include <errno.h> 89 90 #include <dt_proc.h> 91 #include <dt_pid.h> 92 #include <dt_impl.h> 93 94 /* XXX TBD needs libproc */ 95 /* Stub proc functions for now */ 96 int 97 proc_setflags(struct proc_handle *phdl, int mask) 98 { 99 100 printf("dtrace: XXX %s not implemented\n", __func__); 101 return EINVAL; 102 } 103 104 int 105 proc_create(const char *file, char * const *argv, proc_child_func *pcf, 106 void *child_arg, struct proc_handle **pphdl) 107 { 108 109 printf("dtrace: XXX %s not implemented\n", __func__); 110 return EINVAL; 111 } 112 113 int 114 proc_detach(struct proc_handle *phdl) 115 { 116 117 printf("dtrace: XXX %s not implemented\n", __func__); 118 return EINVAL; 119 } 120 121 int 122 proc_getflags(struct proc_handle *phdl) 123 { 124 125 printf("dtrace: XXX %s not implemented\n", __func__); 126 return -1; 127 } 128 129 int 130 proc_wait(struct proc_handle *phdl) 131 { 132 133 printf("dtrace: XXX %s not implemented\n", __func__); 134 return EINVAL; 135 } 136 137 pid_t 138 proc_getpid(struct proc_handle *phdl) 139 { 140 141 printf("dtrace: XXX %s not implemented\n", __func__); 142 return -1; 143 } 144 145 int 146 proc_attach(pid_t pid, int flags, struct proc_handle **pphdl) 147 { 148 149 printf("dtrace: XXX %s not implemented\n", __func__); 150 return EINVAL; 151 } 152 153 int 154 proc_state(struct proc_handle *phdl) 155 { 156 157 printf("dtrace: XXX %s not implemented\n", __func__); 158 return -1; 159 } 160 161 int 162 proc_clearflags(struct proc_handle *phdl, int mask) 163 { 164 165 printf("dtrace: XXX %s not implemented\n", __func__); 166 return EINVAL; 167 } 168 169 int 170 proc_continue(struct proc_handle *phdl) 171 { 172 173 printf("dtrace: XXX %s not implemented\n", __func__); 174 return EINVAL; 175 } 176 177 #define IS_SYS_EXEC(w) (w == SYS_exec || w == SYS_execve) 178 #define IS_SYS_FORK(w) (w == SYS_vfork || w == SYS_fork1 || \ 179 w == SYS_forkall || w == SYS_forksys) 180 181 #ifdef DOODAD 182 static dt_bkpt_t * 183 dt_proc_bpcreate(dt_proc_t *dpr, uintptr_t addr, dt_bkpt_f *func, void *data) 184 { 185 struct ps_prochandle *P = dpr->dpr_proc; 186 dt_bkpt_t *dbp; 187 188 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 189 190 if ((dbp = dt_zalloc(dpr->dpr_hdl, sizeof (dt_bkpt_t))) != NULL) { 191 dbp->dbp_func = func; 192 dbp->dbp_data = data; 193 dbp->dbp_addr = addr; 194 195 if (Psetbkpt(P, dbp->dbp_addr, &dbp->dbp_instr) == 0) 196 dbp->dbp_active = B_TRUE; 197 198 dt_list_append(&dpr->dpr_bps, dbp); 199 } 200 201 return (dbp); 202 } 203 #endif 204 205 static void 206 dt_proc_bpdestroy(dt_proc_t *dpr, int delbkpts) 207 { 208 #if defined(sun) 209 int state = Pstate(dpr->dpr_proc); 210 #else 211 int state = proc_state(dpr->dpr_proc); 212 #endif 213 dt_bkpt_t *dbp, *nbp; 214 215 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 216 217 for (dbp = dt_list_next(&dpr->dpr_bps); dbp != NULL; dbp = nbp) { 218 printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__); 219 #ifdef DOODAD 220 if (delbkpts && dbp->dbp_active && 221 state != PS_LOST && state != PS_UNDEAD) { 222 (void) Pdelbkpt(dpr->dpr_proc, 223 dbp->dbp_addr, dbp->dbp_instr); 224 } 225 #endif 226 nbp = dt_list_next(dbp); 227 dt_list_delete(&dpr->dpr_bps, dbp); 228 dt_free(dpr->dpr_hdl, dbp); 229 } 230 } 231 232 #ifdef DOODAD 233 static void 234 dt_proc_bpmatch(dtrace_hdl_t *dtp, dt_proc_t *dpr) 235 { 236 const lwpstatus_t *psp = &Pstatus(dpr->dpr_proc)->pr_lwp; 237 dt_bkpt_t *dbp; 238 239 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 240 241 for (dbp = dt_list_next(&dpr->dpr_bps); 242 dbp != NULL; dbp = dt_list_next(dbp)) { 243 if (psp->pr_reg[R_PC] == dbp->dbp_addr) 244 break; 245 } 246 247 if (dbp == NULL) { 248 dt_dprintf("pid %d: spurious breakpoint wakeup for %lx\n", 249 (int)dpr->dpr_pid, (ulong_t)psp->pr_reg[R_PC]); 250 return; 251 } 252 253 dt_dprintf("pid %d: hit breakpoint at %lx (%lu)\n", 254 (int)dpr->dpr_pid, (ulong_t)dbp->dbp_addr, ++dbp->dbp_hits); 255 256 dbp->dbp_func(dtp, dpr, dbp->dbp_data); 257 (void) Pxecbkpt(dpr->dpr_proc, dbp->dbp_instr); 258 } 259 #endif 260 261 static void 262 dt_proc_bpenable(dt_proc_t *dpr) 263 { 264 dt_bkpt_t *dbp; 265 266 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 267 268 for (dbp = dt_list_next(&dpr->dpr_bps); 269 dbp != NULL; dbp = dt_list_next(dbp)) { 270 printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__); 271 #ifdef DOODAD 272 if (!dbp->dbp_active && Psetbkpt(dpr->dpr_proc, 273 dbp->dbp_addr, &dbp->dbp_instr) == 0) 274 dbp->dbp_active = B_TRUE; 275 #endif 276 } 277 278 dt_dprintf("breakpoints enabled\n"); 279 } 280 281 static void 282 dt_proc_bpdisable(dt_proc_t *dpr) 283 { 284 dt_bkpt_t *dbp; 285 286 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 287 288 for (dbp = dt_list_next(&dpr->dpr_bps); 289 dbp != NULL; dbp = dt_list_next(dbp)) { 290 printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__); 291 #ifdef DOODAD 292 if (dbp->dbp_active && Pdelbkpt(dpr->dpr_proc, 293 dbp->dbp_addr, dbp->dbp_instr) == 0) 294 dbp->dbp_active = B_FALSE; 295 #endif 296 } 297 298 dt_dprintf("breakpoints disabled\n"); 299 } 300 301 static void 302 dt_proc_notify(dtrace_hdl_t *dtp, dt_proc_hash_t *dph, dt_proc_t *dpr, 303 const char *msg) 304 { 305 dt_proc_notify_t *dprn = dt_alloc(dtp, sizeof (dt_proc_notify_t)); 306 307 if (dprn == NULL) { 308 dt_dprintf("failed to allocate notification for %d %s\n", 309 (int)dpr->dpr_pid, msg); 310 } else { 311 dprn->dprn_dpr = dpr; 312 if (msg == NULL) 313 dprn->dprn_errmsg[0] = '\0'; 314 else 315 (void) strlcpy(dprn->dprn_errmsg, msg, 316 sizeof (dprn->dprn_errmsg)); 317 318 (void) pthread_mutex_lock(&dph->dph_lock); 319 320 dprn->dprn_next = dph->dph_notify; 321 dph->dph_notify = dprn; 322 323 (void) pthread_cond_broadcast(&dph->dph_cv); 324 (void) pthread_mutex_unlock(&dph->dph_lock); 325 } 326 } 327 328 /* 329 * Check to see if the control thread was requested to stop when the victim 330 * process reached a particular event (why) rather than continuing the victim. 331 * If 'why' is set in the stop mask, we wait on dpr_cv for dt_proc_continue(). 332 * If 'why' is not set, this function returns immediately and does nothing. 333 */ 334 static void 335 dt_proc_stop(dt_proc_t *dpr, uint8_t why) 336 { 337 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 338 assert(why != DT_PROC_STOP_IDLE); 339 340 if (dpr->dpr_stop & why) { 341 dpr->dpr_stop |= DT_PROC_STOP_IDLE; 342 dpr->dpr_stop &= ~why; 343 344 (void) pthread_cond_broadcast(&dpr->dpr_cv); 345 346 /* 347 * We disable breakpoints while stopped to preserve the 348 * integrity of the program text for both our own disassembly 349 * and that of the kernel. 350 */ 351 dt_proc_bpdisable(dpr); 352 353 while (dpr->dpr_stop & DT_PROC_STOP_IDLE) 354 (void) pthread_cond_wait(&dpr->dpr_cv, &dpr->dpr_lock); 355 356 dt_proc_bpenable(dpr); 357 } 358 } 359 360 /*ARGSUSED*/ 361 static void 362 dt_proc_bpmain(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *fname) 363 { 364 dt_dprintf("pid %d: breakpoint at %s()\n", (int)dpr->dpr_pid, fname); 365 dt_proc_stop(dpr, DT_PROC_STOP_MAIN); 366 } 367 368 #if defined(sun) 369 static void 370 dt_proc_rdevent(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *evname) 371 { 372 rd_event_msg_t rdm; 373 rd_err_e err; 374 375 if ((err = rd_event_getmsg(dpr->dpr_rtld, &rdm)) != RD_OK) { 376 dt_dprintf("pid %d: failed to get %s event message: %s\n", 377 (int)dpr->dpr_pid, evname, rd_errstr(err)); 378 return; 379 } 380 381 dt_dprintf("pid %d: rtld event %s type=%d state %d\n", 382 (int)dpr->dpr_pid, evname, rdm.type, rdm.u.state); 383 384 switch (rdm.type) { 385 case RD_DLACTIVITY: 386 if (rdm.u.state != RD_CONSISTENT) 387 break; 388 389 Pupdate_syms(dpr->dpr_proc); 390 if (dt_pid_create_probes_module(dtp, dpr) != 0) 391 dt_proc_notify(dtp, dtp->dt_procs, dpr, 392 dpr->dpr_errmsg); 393 394 break; 395 case RD_PREINIT: 396 Pupdate_syms(dpr->dpr_proc); 397 dt_proc_stop(dpr, DT_PROC_STOP_PREINIT); 398 break; 399 case RD_POSTINIT: 400 Pupdate_syms(dpr->dpr_proc); 401 dt_proc_stop(dpr, DT_PROC_STOP_POSTINIT); 402 break; 403 } 404 } 405 406 static void 407 dt_proc_rdwatch(dt_proc_t *dpr, rd_event_e event, const char *evname) 408 { 409 rd_notify_t rdn; 410 rd_err_e err; 411 412 if ((err = rd_event_addr(dpr->dpr_rtld, event, &rdn)) != RD_OK) { 413 dt_dprintf("pid %d: failed to get event address for %s: %s\n", 414 (int)dpr->dpr_pid, evname, rd_errstr(err)); 415 return; 416 } 417 418 if (rdn.type != RD_NOTIFY_BPT) { 419 dt_dprintf("pid %d: event %s has unexpected type %d\n", 420 (int)dpr->dpr_pid, evname, rdn.type); 421 return; 422 } 423 424 (void) dt_proc_bpcreate(dpr, rdn.u.bptaddr, 425 (dt_bkpt_f *)dt_proc_rdevent, (void *)evname); 426 } 427 428 /* 429 * Common code for enabling events associated with the run-time linker after 430 * attaching to a process or after a victim process completes an exec(2). 431 */ 432 static void 433 dt_proc_attach(dt_proc_t *dpr, int exec) 434 { 435 const pstatus_t *psp = Pstatus(dpr->dpr_proc); 436 rd_err_e err; 437 GElf_Sym sym; 438 439 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 440 441 if (exec) { 442 if (psp->pr_lwp.pr_errno != 0) 443 return; /* exec failed: nothing needs to be done */ 444 445 dt_proc_bpdestroy(dpr, B_FALSE); 446 Preset_maps(dpr->dpr_proc); 447 } 448 449 if ((dpr->dpr_rtld = Prd_agent(dpr->dpr_proc)) != NULL && 450 (err = rd_event_enable(dpr->dpr_rtld, B_TRUE)) == RD_OK) { 451 dt_proc_rdwatch(dpr, RD_PREINIT, "RD_PREINIT"); 452 dt_proc_rdwatch(dpr, RD_POSTINIT, "RD_POSTINIT"); 453 dt_proc_rdwatch(dpr, RD_DLACTIVITY, "RD_DLACTIVITY"); 454 } else { 455 dt_dprintf("pid %d: failed to enable rtld events: %s\n", 456 (int)dpr->dpr_pid, dpr->dpr_rtld ? rd_errstr(err) : 457 "rtld_db agent initialization failed"); 458 } 459 460 Pupdate_maps(dpr->dpr_proc); 461 462 if (Pxlookup_by_name(dpr->dpr_proc, LM_ID_BASE, 463 "a.out", "main", &sym, NULL) == 0) { 464 (void) dt_proc_bpcreate(dpr, (uintptr_t)sym.st_value, 465 (dt_bkpt_f *)dt_proc_bpmain, "a.out`main"); 466 } else { 467 dt_dprintf("pid %d: failed to find a.out`main: %s\n", 468 (int)dpr->dpr_pid, strerror(errno)); 469 } 470 } 471 472 /* 473 * Wait for a stopped process to be set running again by some other debugger. 474 * This is typically not required by /proc-based debuggers, since the usual 475 * model is that one debugger controls one victim. But DTrace, as usual, has 476 * its own needs: the stop() action assumes that prun(1) or some other tool 477 * will be applied to resume the victim process. This could be solved by 478 * adding a PCWRUN directive to /proc, but that seems like overkill unless 479 * other debuggers end up needing this functionality, so we implement a cheap 480 * equivalent to PCWRUN using the set of existing kernel mechanisms. 481 * 482 * Our intent is really not just to wait for the victim to run, but rather to 483 * wait for it to run and then stop again for a reason other than the current 484 * PR_REQUESTED stop. Since PCWSTOP/Pstopstatus() can be applied repeatedly 485 * to a stopped process and will return the same result without affecting the 486 * victim, we can just perform these operations repeatedly until Pstate() 487 * changes, the representative LWP ID changes, or the stop timestamp advances. 488 * dt_proc_control() will then rediscover the new state and continue as usual. 489 * When the process is still stopped in the same exact state, we sleep for a 490 * brief interval before waiting again so as not to spin consuming CPU cycles. 491 */ 492 static void 493 dt_proc_waitrun(dt_proc_t *dpr) 494 { 495 struct ps_prochandle *P = dpr->dpr_proc; 496 const lwpstatus_t *psp = &Pstatus(P)->pr_lwp; 497 498 int krflag = psp->pr_flags & (PR_KLC | PR_RLC); 499 timestruc_t tstamp = psp->pr_tstamp; 500 lwpid_t lwpid = psp->pr_lwpid; 501 502 const long wstop = PCWSTOP; 503 int pfd = Pctlfd(P); 504 505 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 506 assert(psp->pr_flags & PR_STOPPED); 507 assert(Pstate(P) == PS_STOP); 508 509 /* 510 * While we are waiting for the victim to run, clear PR_KLC and PR_RLC 511 * so that if the libdtrace client is killed, the victim stays stopped. 512 * dt_proc_destroy() will also observe this and perform PRELEASE_HANG. 513 */ 514 (void) Punsetflags(P, krflag); 515 Psync(P); 516 517 (void) pthread_mutex_unlock(&dpr->dpr_lock); 518 519 while (!dpr->dpr_quit) { 520 if (write(pfd, &wstop, sizeof (wstop)) == -1 && errno == EINTR) 521 continue; /* check dpr_quit and continue waiting */ 522 523 (void) pthread_mutex_lock(&dpr->dpr_lock); 524 (void) Pstopstatus(P, PCNULL, 0); 525 psp = &Pstatus(P)->pr_lwp; 526 527 /* 528 * If we've reached a new state, found a new representative, or 529 * the stop timestamp has changed, restore PR_KLC/PR_RLC to its 530 * original setting and then return with dpr_lock held. 531 */ 532 if (Pstate(P) != PS_STOP || psp->pr_lwpid != lwpid || 533 bcmp(&psp->pr_tstamp, &tstamp, sizeof (tstamp)) != 0) { 534 (void) Psetflags(P, krflag); 535 Psync(P); 536 return; 537 } 538 539 (void) pthread_mutex_unlock(&dpr->dpr_lock); 540 (void) poll(NULL, 0, MILLISEC / 2); 541 } 542 543 (void) pthread_mutex_lock(&dpr->dpr_lock); 544 } 545 #endif 546 547 typedef struct dt_proc_control_data { 548 dtrace_hdl_t *dpcd_hdl; /* DTrace handle */ 549 dt_proc_t *dpcd_proc; /* proccess to control */ 550 } dt_proc_control_data_t; 551 552 /* 553 * Main loop for all victim process control threads. We initialize all the 554 * appropriate /proc control mechanisms, and then enter a loop waiting for 555 * the process to stop on an event or die. We process any events by calling 556 * appropriate subroutines, and exit when the victim dies or we lose control. 557 * 558 * The control thread synchronizes the use of dpr_proc with other libdtrace 559 * threads using dpr_lock. We hold the lock for all of our operations except 560 * waiting while the process is running: this is accomplished by writing a 561 * PCWSTOP directive directly to the underlying /proc/<pid>/ctl file. If the 562 * libdtrace client wishes to exit or abort our wait, SIGCANCEL can be used. 563 */ 564 static void * 565 dt_proc_control(void *arg) 566 { 567 dt_proc_control_data_t *datap = arg; 568 dtrace_hdl_t *dtp = datap->dpcd_hdl; 569 dt_proc_t *dpr = datap->dpcd_proc; 570 dt_proc_hash_t *dph = dpr->dpr_hdl->dt_procs; 571 struct ps_prochandle *P = dpr->dpr_proc; 572 int pid = dpr->dpr_pid; 573 574 #if defined(sun) 575 int pfd = Pctlfd(P); 576 577 const long wstop = PCWSTOP; 578 #endif 579 int notify = B_FALSE; 580 581 /* 582 * We disable the POSIX thread cancellation mechanism so that the 583 * client program using libdtrace can't accidentally cancel our thread. 584 * dt_proc_destroy() uses SIGCANCEL explicitly to simply poke us out 585 * of PCWSTOP with EINTR, at which point we will see dpr_quit and exit. 586 */ 587 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 588 589 /* 590 * Set up the corresponding process for tracing by libdtrace. We want 591 * to be able to catch breakpoints and efficiently single-step over 592 * them, and we need to enable librtld_db to watch libdl activity. 593 */ 594 (void) pthread_mutex_lock(&dpr->dpr_lock); 595 596 #if defined(sun) 597 (void) Punsetflags(P, PR_ASYNC); /* require synchronous mode */ 598 (void) Psetflags(P, PR_BPTADJ); /* always adjust eip on x86 */ 599 (void) Punsetflags(P, PR_FORK); /* do not inherit on fork */ 600 601 (void) Pfault(P, FLTBPT, B_TRUE); /* always trace breakpoints */ 602 (void) Pfault(P, FLTTRACE, B_TRUE); /* always trace single-step */ 603 604 /* 605 * We must trace exit from exec() system calls so that if the exec is 606 * successful, we can reset our breakpoints and re-initialize libproc. 607 */ 608 (void) Psysexit(P, SYS_exec, B_TRUE); 609 (void) Psysexit(P, SYS_execve, B_TRUE); 610 611 /* 612 * We must trace entry and exit for fork() system calls in order to 613 * disable our breakpoints temporarily during the fork. We do not set 614 * the PR_FORK flag, so if fork succeeds the child begins executing and 615 * does not inherit any other tracing behaviors or a control thread. 616 */ 617 (void) Psysentry(P, SYS_vfork, B_TRUE); 618 (void) Psysexit(P, SYS_vfork, B_TRUE); 619 (void) Psysentry(P, SYS_fork1, B_TRUE); 620 (void) Psysexit(P, SYS_fork1, B_TRUE); 621 (void) Psysentry(P, SYS_forkall, B_TRUE); 622 (void) Psysexit(P, SYS_forkall, B_TRUE); 623 (void) Psysentry(P, SYS_forksys, B_TRUE); 624 (void) Psysexit(P, SYS_forksys, B_TRUE); 625 626 Psync(P); /* enable all /proc changes */ 627 dt_proc_attach(dpr, B_FALSE); /* enable rtld breakpoints */ 628 629 /* 630 * If PR_KLC is set, we created the process; otherwise we grabbed it. 631 * Check for an appropriate stop request and wait for dt_proc_continue. 632 */ 633 if (Pstatus(P)->pr_flags & PR_KLC) 634 dt_proc_stop(dpr, DT_PROC_STOP_CREATE); 635 else 636 dt_proc_stop(dpr, DT_PROC_STOP_GRAB); 637 638 if (Psetrun(P, 0, 0) == -1) { 639 dt_dprintf("pid %d: failed to set running: %s\n", 640 (int)dpr->dpr_pid, strerror(errno)); 641 } 642 #else 643 /* 644 * If PR_KLC is set, we created the process; otherwise we grabbed it. 645 * Check for an appropriate stop request and wait for dt_proc_continue. 646 */ 647 if (proc_getflags(P) & PR_KLC) 648 dt_proc_stop(dpr, DT_PROC_STOP_CREATE); 649 else 650 dt_proc_stop(dpr, DT_PROC_STOP_GRAB); 651 652 if (proc_continue(P) != 0) 653 dt_dprintf("pid %d: failed to set running: %s\n", 654 (int)dpr->dpr_pid, strerror(errno)); 655 #endif 656 657 (void) pthread_mutex_unlock(&dpr->dpr_lock); 658 659 /* 660 * Wait for the process corresponding to this control thread to stop, 661 * process the event, and then set it running again. We want to sleep 662 * with dpr_lock *unheld* so that other parts of libdtrace can use the 663 * ps_prochandle in the meantime (e.g. ustack()). To do this, we write 664 * a PCWSTOP directive directly to the underlying /proc/<pid>/ctl file. 665 * Once the process stops, we wake up, grab dpr_lock, and then call 666 * Pwait() (which will return immediately) and do our processing. 667 */ 668 while (!dpr->dpr_quit) { 669 #if defined(sun) 670 const lwpstatus_t *psp; 671 672 if (write(pfd, &wstop, sizeof (wstop)) == -1 && errno == EINTR) 673 continue; /* check dpr_quit and continue waiting */ 674 #else 675 /* Wait for the process to report status. */ 676 proc_wait(P); 677 #endif 678 679 (void) pthread_mutex_lock(&dpr->dpr_lock); 680 681 #if defined(sun) 682 pwait_locked: 683 if (Pstopstatus(P, PCNULL, 0) == -1 && errno == EINTR) { 684 (void) pthread_mutex_unlock(&dpr->dpr_lock); 685 continue; /* check dpr_quit and continue waiting */ 686 } 687 #endif 688 689 #if defined(sun) 690 switch (Pstate(P)) { 691 #else 692 switch (proc_state(P)) { 693 #endif 694 case PS_STOP: 695 #ifdef DOODAD 696 psp = &Pstatus(P)->pr_lwp; 697 698 dt_dprintf("pid %d: proc stopped showing %d/%d\n", 699 pid, psp->pr_why, psp->pr_what); 700 701 /* 702 * If the process stops showing PR_REQUESTED, then the 703 * DTrace stop() action was applied to it or another 704 * debugging utility (e.g. pstop(1)) asked it to stop. 705 * In either case, the user's intention is for the 706 * process to remain stopped until another external 707 * mechanism (e.g. prun(1)) is applied. So instead of 708 * setting the process running ourself, we wait for 709 * someone else to do so. Once that happens, we return 710 * to our normal loop waiting for an event of interest. 711 */ 712 if (psp->pr_why == PR_REQUESTED) { 713 dt_proc_waitrun(dpr); 714 (void) pthread_mutex_unlock(&dpr->dpr_lock); 715 continue; 716 } 717 718 /* 719 * If the process stops showing one of the events that 720 * we are tracing, perform the appropriate response. 721 * Note that we ignore PR_SUSPENDED, PR_CHECKPOINT, and 722 * PR_JOBCONTROL by design: if one of these conditions 723 * occurs, we will fall through to Psetrun() but the 724 * process will remain stopped in the kernel by the 725 * corresponding mechanism (e.g. job control stop). 726 */ 727 if (psp->pr_why == PR_FAULTED && psp->pr_what == FLTBPT) 728 dt_proc_bpmatch(dtp, dpr); 729 else if (psp->pr_why == PR_SYSENTRY && 730 IS_SYS_FORK(psp->pr_what)) 731 dt_proc_bpdisable(dpr); 732 else if (psp->pr_why == PR_SYSEXIT && 733 IS_SYS_FORK(psp->pr_what)) 734 dt_proc_bpenable(dpr); 735 else if (psp->pr_why == PR_SYSEXIT && 736 IS_SYS_EXEC(psp->pr_what)) 737 dt_proc_attach(dpr, B_TRUE); 738 #endif 739 break; 740 741 case PS_LOST: 742 #if defined(sun) 743 if (Preopen(P) == 0) 744 goto pwait_locked; 745 #endif 746 747 dt_dprintf("pid %d: proc lost: %s\n", 748 pid, strerror(errno)); 749 750 dpr->dpr_quit = B_TRUE; 751 notify = B_TRUE; 752 break; 753 754 case PS_UNDEAD: 755 dt_dprintf("pid %d: proc died\n", pid); 756 dpr->dpr_quit = B_TRUE; 757 notify = B_TRUE; 758 break; 759 } 760 761 #if defined(sun) 762 if (Pstate(P) != PS_UNDEAD && Psetrun(P, 0, 0) == -1) { 763 dt_dprintf("pid %d: failed to set running: %s\n", 764 (int)dpr->dpr_pid, strerror(errno)); 765 } 766 #endif 767 768 (void) pthread_mutex_unlock(&dpr->dpr_lock); 769 } 770 771 /* 772 * If the control thread detected PS_UNDEAD or PS_LOST, then enqueue 773 * the dt_proc_t structure on the dt_proc_hash_t notification list. 774 */ 775 if (notify) 776 dt_proc_notify(dtp, dph, dpr, NULL); 777 778 /* 779 * Destroy and remove any remaining breakpoints, set dpr_done and clear 780 * dpr_tid to indicate the control thread has exited, and notify any 781 * waiting thread in dt_proc_destroy() that we have succesfully exited. 782 */ 783 (void) pthread_mutex_lock(&dpr->dpr_lock); 784 785 dt_proc_bpdestroy(dpr, B_TRUE); 786 dpr->dpr_done = B_TRUE; 787 dpr->dpr_tid = 0; 788 789 (void) pthread_cond_broadcast(&dpr->dpr_cv); 790 (void) pthread_mutex_unlock(&dpr->dpr_lock); 791 792 return (NULL); 793 } 794 795 /*PRINTFLIKE3*/ 796 static struct ps_prochandle * 797 dt_proc_error(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *format, ...) 798 { 799 va_list ap; 800 801 va_start(ap, format); 802 dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap); 803 va_end(ap); 804 805 if (dpr->dpr_proc != NULL) 806 #if defined(sun) 807 Prelease(dpr->dpr_proc, 0); 808 #else 809 proc_detach(dpr->dpr_proc); 810 #endif 811 812 dt_free(dtp, dpr); 813 (void) dt_set_errno(dtp, EDT_COMPILER); 814 return (NULL); 815 } 816 817 dt_proc_t * 818 dt_proc_lookup(dtrace_hdl_t *dtp, struct ps_prochandle *P, int remove) 819 { 820 dt_proc_hash_t *dph = dtp->dt_procs; 821 #if defined(sun) 822 pid_t pid = Pstatus(P)->pr_pid; 823 #else 824 pid_t pid = proc_getpid(P); 825 #endif 826 dt_proc_t *dpr, **dpp = &dph->dph_hash[pid & (dph->dph_hashlen - 1)]; 827 828 for (dpr = *dpp; dpr != NULL; dpr = dpr->dpr_hash) { 829 if (dpr->dpr_pid == pid) 830 break; 831 else 832 dpp = &dpr->dpr_hash; 833 } 834 835 assert(dpr != NULL); 836 assert(dpr->dpr_proc == P); 837 838 if (remove) 839 *dpp = dpr->dpr_hash; /* remove from pid hash chain */ 840 841 return (dpr); 842 } 843 844 static void 845 dt_proc_destroy(dtrace_hdl_t *dtp, struct ps_prochandle *P) 846 { 847 dt_proc_t *dpr = dt_proc_lookup(dtp, P, B_FALSE); 848 dt_proc_hash_t *dph = dtp->dt_procs; 849 dt_proc_notify_t *npr, **npp; 850 int rflag; 851 852 assert(dpr != NULL); 853 854 /* 855 * If neither PR_KLC nor PR_RLC is set, then the process is stopped by 856 * an external debugger and we were waiting in dt_proc_waitrun(). 857 * Leave the process in this condition using PRELEASE_HANG. 858 */ 859 #if defined(sun) 860 if (!(Pstatus(dpr->dpr_proc)->pr_flags & (PR_KLC | PR_RLC))) { 861 #else 862 if (!(proc_getflags(dpr->dpr_proc) & (PR_KLC | PR_RLC))) { 863 #endif 864 dt_dprintf("abandoning pid %d\n", (int)dpr->dpr_pid); 865 #if defined(sun) 866 rflag = PRELEASE_HANG; 867 #else 868 rflag = 0 /* XXX */; 869 #endif 870 } else { 871 dt_dprintf("releasing pid %d\n", (int)dpr->dpr_pid); 872 rflag = 0; /* apply kill or run-on-last-close */ 873 } 874 875 if (dpr->dpr_tid) { 876 /* 877 * Set the dpr_quit flag to tell the daemon thread to exit. We 878 * send it a SIGCANCEL to poke it out of PCWSTOP or any other 879 * long-term /proc system call. Our daemon threads have POSIX 880 * cancellation disabled, so EINTR will be the only effect. We 881 * then wait for dpr_done to indicate the thread has exited. 882 * 883 * We can't use pthread_kill() to send SIGCANCEL because the 884 * interface forbids it and we can't use pthread_cancel() 885 * because with cancellation disabled it won't actually 886 * send SIGCANCEL to the target thread, so we use _lwp_kill() 887 * to do the job. This is all built on evil knowledge of 888 * the details of the cancellation mechanism in libc. 889 */ 890 (void) pthread_mutex_lock(&dpr->dpr_lock); 891 dpr->dpr_quit = B_TRUE; 892 #if defined(sun) 893 (void) _lwp_kill(dpr->dpr_tid, SIGCANCEL); 894 #else 895 (void) pthread_kill(dpr->dpr_tid, SIGUSR1); 896 #endif 897 898 /* 899 * If the process is currently idling in dt_proc_stop(), re- 900 * enable breakpoints and poke it into running again. 901 */ 902 if (dpr->dpr_stop & DT_PROC_STOP_IDLE) { 903 dt_proc_bpenable(dpr); 904 dpr->dpr_stop &= ~DT_PROC_STOP_IDLE; 905 (void) pthread_cond_broadcast(&dpr->dpr_cv); 906 } 907 908 while (!dpr->dpr_done) 909 (void) pthread_cond_wait(&dpr->dpr_cv, &dpr->dpr_lock); 910 911 (void) pthread_mutex_unlock(&dpr->dpr_lock); 912 } 913 914 /* 915 * Before we free the process structure, remove this dt_proc_t from the 916 * lookup hash, and then walk the dt_proc_hash_t's notification list 917 * and remove this dt_proc_t if it is enqueued. 918 */ 919 (void) pthread_mutex_lock(&dph->dph_lock); 920 (void) dt_proc_lookup(dtp, P, B_TRUE); 921 npp = &dph->dph_notify; 922 923 while ((npr = *npp) != NULL) { 924 if (npr->dprn_dpr == dpr) { 925 *npp = npr->dprn_next; 926 dt_free(dtp, npr); 927 } else { 928 npp = &npr->dprn_next; 929 } 930 } 931 932 (void) pthread_mutex_unlock(&dph->dph_lock); 933 934 /* 935 * Remove the dt_proc_list from the LRU list, release the underlying 936 * libproc handle, and free our dt_proc_t data structure. 937 */ 938 if (dpr->dpr_cacheable) { 939 assert(dph->dph_lrucnt != 0); 940 dph->dph_lrucnt--; 941 } 942 943 dt_list_delete(&dph->dph_lrulist, dpr); 944 #if defined(sun) 945 Prelease(dpr->dpr_proc, rflag); 946 #else 947 proc_detach(dpr->dpr_proc); 948 #endif 949 dt_free(dtp, dpr); 950 } 951 952 static int 953 dt_proc_create_thread(dtrace_hdl_t *dtp, dt_proc_t *dpr, uint_t stop) 954 { 955 dt_proc_control_data_t data; 956 sigset_t nset, oset; 957 pthread_attr_t a; 958 int err; 959 960 (void) pthread_mutex_lock(&dpr->dpr_lock); 961 dpr->dpr_stop |= stop; /* set bit for initial rendezvous */ 962 963 (void) pthread_attr_init(&a); 964 (void) pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED); 965 966 (void) sigfillset(&nset); 967 (void) sigdelset(&nset, SIGABRT); /* unblocked for assert() */ 968 #if defined(sun) 969 (void) sigdelset(&nset, SIGCANCEL); /* see dt_proc_destroy() */ 970 #else 971 (void) sigdelset(&nset, SIGUSR1); /* see dt_proc_destroy() */ 972 #endif 973 974 data.dpcd_hdl = dtp; 975 data.dpcd_proc = dpr; 976 977 (void) pthread_sigmask(SIG_SETMASK, &nset, &oset); 978 err = pthread_create(&dpr->dpr_tid, &a, dt_proc_control, &data); 979 (void) pthread_sigmask(SIG_SETMASK, &oset, NULL); 980 981 /* 982 * If the control thread was created, then wait on dpr_cv for either 983 * dpr_done to be set (the victim died or the control thread failed) 984 * or DT_PROC_STOP_IDLE to be set, indicating that the victim is now 985 * stopped by /proc and the control thread is at the rendezvous event. 986 * On success, we return with the process and control thread stopped: 987 * the caller can then apply dt_proc_continue() to resume both. 988 */ 989 if (err == 0) { 990 while (!dpr->dpr_done && !(dpr->dpr_stop & DT_PROC_STOP_IDLE)) 991 (void) pthread_cond_wait(&dpr->dpr_cv, &dpr->dpr_lock); 992 993 /* 994 * If dpr_done is set, the control thread aborted before it 995 * reached the rendezvous event. This is either due to PS_LOST 996 * or PS_UNDEAD (i.e. the process died). We try to provide a 997 * small amount of useful information to help figure it out. 998 */ 999 if (dpr->dpr_done) { 1000 #if defined(sun) 1001 const psinfo_t *prp = Ppsinfo(dpr->dpr_proc); 1002 int stat = prp ? prp->pr_wstat : 0; 1003 #endif 1004 int pid = dpr->dpr_pid; 1005 1006 #if defined(sun) 1007 if (Pstate(dpr->dpr_proc) == PS_LOST) { 1008 #else 1009 if (proc_state(dpr->dpr_proc) == PS_LOST) { 1010 #endif 1011 (void) dt_proc_error(dpr->dpr_hdl, dpr, 1012 "failed to control pid %d: process exec'd " 1013 "set-id or unobservable program\n", pid); 1014 #if defined(sun) 1015 } else if (WIFSIGNALED(stat)) { 1016 (void) dt_proc_error(dpr->dpr_hdl, dpr, 1017 "failed to control pid %d: process died " 1018 "from signal %d\n", pid, WTERMSIG(stat)); 1019 } else { 1020 (void) dt_proc_error(dpr->dpr_hdl, dpr, 1021 "failed to control pid %d: process exited " 1022 "with status %d\n", pid, WEXITSTATUS(stat)); 1023 #endif 1024 } 1025 1026 err = ESRCH; /* cause grab() or create() to fail */ 1027 } 1028 } else { 1029 (void) dt_proc_error(dpr->dpr_hdl, dpr, 1030 "failed to create control thread for process-id %d: %s\n", 1031 (int)dpr->dpr_pid, strerror(err)); 1032 } 1033 1034 (void) pthread_mutex_unlock(&dpr->dpr_lock); 1035 (void) pthread_attr_destroy(&a); 1036 1037 return (err); 1038 } 1039 1040 struct ps_prochandle * 1041 dt_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv, 1042 proc_child_func *pcf, void *child_arg) 1043 { 1044 dt_proc_hash_t *dph = dtp->dt_procs; 1045 dt_proc_t *dpr; 1046 int err; 1047 1048 if ((dpr = dt_zalloc(dtp, sizeof (dt_proc_t))) == NULL) 1049 return (NULL); /* errno is set for us */ 1050 1051 (void) pthread_mutex_init(&dpr->dpr_lock, NULL); 1052 (void) pthread_cond_init(&dpr->dpr_cv, NULL); 1053 1054 #if defined(sun) 1055 if ((dpr->dpr_proc = Pcreate(file, argv, &err, NULL, 0)) == NULL) { 1056 return (dt_proc_error(dtp, dpr, 1057 "failed to execute %s: %s\n", file, Pcreate_error(err))); 1058 } 1059 1060 dpr->dpr_hdl = dtp; 1061 dpr->dpr_pid = Pstatus(dpr->dpr_proc)->pr_pid; 1062 1063 (void) Punsetflags(dpr->dpr_proc, PR_RLC); 1064 (void) Psetflags(dpr->dpr_proc, PR_KLC); 1065 #else 1066 (void) proc_clearflags(dpr->dpr_proc, PR_RLC); 1067 (void) proc_setflags(dpr->dpr_proc, PR_KLC); 1068 if ((err = proc_create(file, argv, pcf, child_arg, &dpr->dpr_proc)) != 0) 1069 return (dt_proc_error(dtp, dpr, 1070 "failed to execute %s: %s\n", file, strerror(err))); 1071 dpr->dpr_hdl = dtp; 1072 dpr->dpr_pid = proc_getpid(dpr->dpr_proc); 1073 #endif 1074 1075 #if defined(sun) 1076 if (dt_proc_create_thread(dtp, dpr, dtp->dt_prcmode) != 0) 1077 #else 1078 if (dt_proc_create_thread(dtp, dpr, DT_PROC_STOP_IDLE) != 0) 1079 #endif 1080 return (NULL); /* dt_proc_error() has been called for us */ 1081 1082 dpr->dpr_hash = dph->dph_hash[dpr->dpr_pid & (dph->dph_hashlen - 1)]; 1083 dph->dph_hash[dpr->dpr_pid & (dph->dph_hashlen - 1)] = dpr; 1084 dt_list_prepend(&dph->dph_lrulist, dpr); 1085 1086 dt_dprintf("created pid %d\n", (int)dpr->dpr_pid); 1087 dpr->dpr_refs++; 1088 1089 return (dpr->dpr_proc); 1090 } 1091 1092 struct ps_prochandle * 1093 dt_proc_grab(dtrace_hdl_t *dtp, pid_t pid, int flags, int nomonitor) 1094 { 1095 dt_proc_hash_t *dph = dtp->dt_procs; 1096 uint_t h = pid & (dph->dph_hashlen - 1); 1097 dt_proc_t *dpr, *opr; 1098 int err; 1099 1100 /* 1101 * Search the hash table for the pid. If it is already grabbed or 1102 * created, move the handle to the front of the lrulist, increment 1103 * the reference count, and return the existing ps_prochandle. 1104 */ 1105 for (dpr = dph->dph_hash[h]; dpr != NULL; dpr = dpr->dpr_hash) { 1106 if (dpr->dpr_pid == pid && !dpr->dpr_stale) { 1107 /* 1108 * If the cached handle was opened read-only and 1109 * this request is for a writeable handle, mark 1110 * the cached handle as stale and open a new handle. 1111 * Since it's stale, unmark it as cacheable. 1112 */ 1113 if (dpr->dpr_rdonly && !(flags & PGRAB_RDONLY)) { 1114 dt_dprintf("upgrading pid %d\n", (int)pid); 1115 dpr->dpr_stale = B_TRUE; 1116 dpr->dpr_cacheable = B_FALSE; 1117 dph->dph_lrucnt--; 1118 break; 1119 } 1120 1121 dt_dprintf("grabbed pid %d (cached)\n", (int)pid); 1122 dt_list_delete(&dph->dph_lrulist, dpr); 1123 dt_list_prepend(&dph->dph_lrulist, dpr); 1124 dpr->dpr_refs++; 1125 return (dpr->dpr_proc); 1126 } 1127 } 1128 1129 if ((dpr = dt_zalloc(dtp, sizeof (dt_proc_t))) == NULL) 1130 return (NULL); /* errno is set for us */ 1131 1132 (void) pthread_mutex_init(&dpr->dpr_lock, NULL); 1133 (void) pthread_cond_init(&dpr->dpr_cv, NULL); 1134 1135 #if defined(sun) 1136 if ((dpr->dpr_proc = Pgrab(pid, flags, &err)) == NULL) { 1137 return (dt_proc_error(dtp, dpr, 1138 "failed to grab pid %d: %s\n", (int)pid, Pgrab_error(err))); 1139 } 1140 #else 1141 if ((err = proc_attach(pid, flags, &dpr->dpr_proc)) != 0) 1142 return (dt_proc_error(dtp, dpr, 1143 "failed to grab pid %d: %s\n", (int) pid, strerror(err))); 1144 #endif 1145 1146 dpr->dpr_hdl = dtp; 1147 dpr->dpr_pid = pid; 1148 1149 #if defined(sun) 1150 (void) Punsetflags(dpr->dpr_proc, PR_KLC); 1151 (void) Psetflags(dpr->dpr_proc, PR_RLC); 1152 #else 1153 (void) proc_clearflags(dpr->dpr_proc, PR_KLC); 1154 (void) proc_setflags(dpr->dpr_proc, PR_RLC); 1155 #endif 1156 1157 /* 1158 * If we are attempting to grab the process without a monitor 1159 * thread, then mark the process cacheable only if it's being 1160 * grabbed read-only. If we're currently caching more process 1161 * handles than dph_lrulim permits, attempt to find the 1162 * least-recently-used handle that is currently unreferenced and 1163 * release it from the cache. Otherwise we are grabbing the process 1164 * for control: create a control thread for this process and store 1165 * its ID in dpr->dpr_tid. 1166 */ 1167 if (nomonitor || (flags & PGRAB_RDONLY)) { 1168 if (dph->dph_lrucnt >= dph->dph_lrulim) { 1169 for (opr = dt_list_prev(&dph->dph_lrulist); 1170 opr != NULL; opr = dt_list_prev(opr)) { 1171 if (opr->dpr_cacheable && opr->dpr_refs == 0) { 1172 dt_proc_destroy(dtp, opr->dpr_proc); 1173 break; 1174 } 1175 } 1176 } 1177 1178 if (flags & PGRAB_RDONLY) { 1179 dpr->dpr_cacheable = B_TRUE; 1180 dpr->dpr_rdonly = B_TRUE; 1181 dph->dph_lrucnt++; 1182 } 1183 1184 } else if (dt_proc_create_thread(dtp, dpr, DT_PROC_STOP_GRAB) != 0) 1185 return (NULL); /* dt_proc_error() has been called for us */ 1186 1187 dpr->dpr_hash = dph->dph_hash[h]; 1188 dph->dph_hash[h] = dpr; 1189 dt_list_prepend(&dph->dph_lrulist, dpr); 1190 1191 dt_dprintf("grabbed pid %d\n", (int)pid); 1192 dpr->dpr_refs++; 1193 1194 return (dpr->dpr_proc); 1195 } 1196 1197 void 1198 dt_proc_release(dtrace_hdl_t *dtp, struct ps_prochandle *P) 1199 { 1200 dt_proc_t *dpr = dt_proc_lookup(dtp, P, B_FALSE); 1201 dt_proc_hash_t *dph = dtp->dt_procs; 1202 1203 assert(dpr != NULL); 1204 assert(dpr->dpr_refs != 0); 1205 1206 if (--dpr->dpr_refs == 0 && 1207 (!dpr->dpr_cacheable || dph->dph_lrucnt > dph->dph_lrulim)) 1208 dt_proc_destroy(dtp, P); 1209 } 1210 1211 void 1212 dt_proc_continue(dtrace_hdl_t *dtp, struct ps_prochandle *P) 1213 { 1214 dt_proc_t *dpr = dt_proc_lookup(dtp, P, B_FALSE); 1215 1216 (void) pthread_mutex_lock(&dpr->dpr_lock); 1217 1218 if (dpr->dpr_stop & DT_PROC_STOP_IDLE) { 1219 dpr->dpr_stop &= ~DT_PROC_STOP_IDLE; 1220 (void) pthread_cond_broadcast(&dpr->dpr_cv); 1221 } 1222 1223 (void) pthread_mutex_unlock(&dpr->dpr_lock); 1224 } 1225 1226 void 1227 dt_proc_lock(dtrace_hdl_t *dtp, struct ps_prochandle *P) 1228 { 1229 dt_proc_t *dpr = dt_proc_lookup(dtp, P, B_FALSE); 1230 int err = pthread_mutex_lock(&dpr->dpr_lock); 1231 assert(err == 0); /* check for recursion */ 1232 } 1233 1234 void 1235 dt_proc_unlock(dtrace_hdl_t *dtp, struct ps_prochandle *P) 1236 { 1237 dt_proc_t *dpr = dt_proc_lookup(dtp, P, B_FALSE); 1238 int err = pthread_mutex_unlock(&dpr->dpr_lock); 1239 assert(err == 0); /* check for unheld lock */ 1240 } 1241 1242 void 1243 dt_proc_hash_create(dtrace_hdl_t *dtp) 1244 { 1245 if ((dtp->dt_procs = dt_zalloc(dtp, sizeof (dt_proc_hash_t) + 1246 sizeof (dt_proc_t *) * _dtrace_pidbuckets - 1)) != NULL) { 1247 1248 (void) pthread_mutex_init(&dtp->dt_procs->dph_lock, NULL); 1249 (void) pthread_cond_init(&dtp->dt_procs->dph_cv, NULL); 1250 1251 dtp->dt_procs->dph_hashlen = _dtrace_pidbuckets; 1252 dtp->dt_procs->dph_lrulim = _dtrace_pidlrulim; 1253 } 1254 } 1255 1256 void 1257 dt_proc_hash_destroy(dtrace_hdl_t *dtp) 1258 { 1259 dt_proc_hash_t *dph = dtp->dt_procs; 1260 dt_proc_t *dpr; 1261 1262 while ((dpr = dt_list_next(&dph->dph_lrulist)) != NULL) 1263 dt_proc_destroy(dtp, dpr->dpr_proc); 1264 1265 dtp->dt_procs = NULL; 1266 dt_free(dtp, dph); 1267 } 1268 1269 struct ps_prochandle * 1270 dtrace_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv, 1271 proc_child_func *pcf, void *child_arg) 1272 { 1273 dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target"); 1274 struct ps_prochandle *P = dt_proc_create(dtp, file, argv, pcf, child_arg); 1275 1276 if (P != NULL && idp != NULL && idp->di_id == 0) 1277 #if defined(sun) 1278 idp->di_id = Pstatus(P)->pr_pid; /* $target = created pid */ 1279 #else 1280 idp->di_id = proc_getpid(P); /* $target = created pid */ 1281 #endif 1282 1283 return (P); 1284 } 1285 1286 struct ps_prochandle * 1287 dtrace_proc_grab(dtrace_hdl_t *dtp, pid_t pid, int flags) 1288 { 1289 dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target"); 1290 struct ps_prochandle *P = dt_proc_grab(dtp, pid, flags, 0); 1291 1292 if (P != NULL && idp != NULL && idp->di_id == 0) 1293 idp->di_id = pid; /* $target = grabbed pid */ 1294 1295 return (P); 1296 } 1297 1298 void 1299 dtrace_proc_release(dtrace_hdl_t *dtp, struct ps_prochandle *P) 1300 { 1301 dt_proc_release(dtp, P); 1302 } 1303 1304 void 1305 dtrace_proc_continue(dtrace_hdl_t *dtp, struct ps_prochandle *P) 1306 { 1307 dt_proc_continue(dtp, P); 1308 } 1309