dt_proc.c (210775) | dt_proc.c (211554) |
---|---|
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 --- 75 unchanged lines hidden (view full) --- 84#include <signal.h> 85#include <assert.h> 86#include <errno.h> 87 88#include <dt_proc.h> 89#include <dt_pid.h> 90#include <dt_impl.h> 91 | 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 --- 75 unchanged lines hidden (view full) --- 84#include <signal.h> 85#include <assert.h> 86#include <errno.h> 87 88#include <dt_proc.h> 89#include <dt_pid.h> 90#include <dt_impl.h> 91 |
92#if !defined(sun) 93#include <sys/syscall.h> 94#include <libproc_compat.h> 95#define SYS_forksys SYS_fork 96#endif 97 |
|
92#define IS_SYS_EXEC(w) (w == SYS_execve) 93#define IS_SYS_FORK(w) (w == SYS_vfork || w == SYS_forksys) 94 | 98#define IS_SYS_EXEC(w) (w == SYS_execve) 99#define IS_SYS_FORK(w) (w == SYS_vfork || w == SYS_forksys) 100 |
95#ifdef DOODAD | |
96static dt_bkpt_t * 97dt_proc_bpcreate(dt_proc_t *dpr, uintptr_t addr, dt_bkpt_f *func, void *data) 98{ 99 struct ps_prochandle *P = dpr->dpr_proc; 100 dt_bkpt_t *dbp; 101 102 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 103 --- 5 unchanged lines hidden (view full) --- 109 if (Psetbkpt(P, dbp->dbp_addr, &dbp->dbp_instr) == 0) 110 dbp->dbp_active = B_TRUE; 111 112 dt_list_append(&dpr->dpr_bps, dbp); 113 } 114 115 return (dbp); 116} | 101static dt_bkpt_t * 102dt_proc_bpcreate(dt_proc_t *dpr, uintptr_t addr, dt_bkpt_f *func, void *data) 103{ 104 struct ps_prochandle *P = dpr->dpr_proc; 105 dt_bkpt_t *dbp; 106 107 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 108 --- 5 unchanged lines hidden (view full) --- 114 if (Psetbkpt(P, dbp->dbp_addr, &dbp->dbp_instr) == 0) 115 dbp->dbp_active = B_TRUE; 116 117 dt_list_append(&dpr->dpr_bps, dbp); 118 } 119 120 return (dbp); 121} |
117#endif | |
118 119static void 120dt_proc_bpdestroy(dt_proc_t *dpr, int delbkpts) 121{ | 122 123static void 124dt_proc_bpdestroy(dt_proc_t *dpr, int delbkpts) 125{ |
122#if defined(sun) | |
123 int state = Pstate(dpr->dpr_proc); | 126 int state = Pstate(dpr->dpr_proc); |
124#else 125 int state = proc_state(dpr->dpr_proc); 126#endif | |
127 dt_bkpt_t *dbp, *nbp; 128 129 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 130 131 for (dbp = dt_list_next(&dpr->dpr_bps); dbp != NULL; dbp = nbp) { | 127 dt_bkpt_t *dbp, *nbp; 128 129 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 130 131 for (dbp = dt_list_next(&dpr->dpr_bps); dbp != NULL; dbp = nbp) { |
132printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__); 133#ifdef DOODAD | |
134 if (delbkpts && dbp->dbp_active && 135 state != PS_LOST && state != PS_UNDEAD) { 136 (void) Pdelbkpt(dpr->dpr_proc, 137 dbp->dbp_addr, dbp->dbp_instr); 138 } | 132 if (delbkpts && dbp->dbp_active && 133 state != PS_LOST && state != PS_UNDEAD) { 134 (void) Pdelbkpt(dpr->dpr_proc, 135 dbp->dbp_addr, dbp->dbp_instr); 136 } |
139#endif | |
140 nbp = dt_list_next(dbp); 141 dt_list_delete(&dpr->dpr_bps, dbp); 142 dt_free(dpr->dpr_hdl, dbp); 143 } 144} 145 | 137 nbp = dt_list_next(dbp); 138 dt_list_delete(&dpr->dpr_bps, dbp); 139 dt_free(dpr->dpr_hdl, dbp); 140 } 141} 142 |
146#ifdef DOODAD | |
147static void 148dt_proc_bpmatch(dtrace_hdl_t *dtp, dt_proc_t *dpr) 149{ | 143static void 144dt_proc_bpmatch(dtrace_hdl_t *dtp, dt_proc_t *dpr) 145{ |
146#if defined(sun) |
|
150 const lwpstatus_t *psp = &Pstatus(dpr->dpr_proc)->pr_lwp; | 147 const lwpstatus_t *psp = &Pstatus(dpr->dpr_proc)->pr_lwp; |
148#else 149 unsigned long pc; 150#endif |
|
151 dt_bkpt_t *dbp; 152 153 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 154 | 151 dt_bkpt_t *dbp; 152 153 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 154 |
155#if !defined(sun) 156 proc_regget(dpr->dpr_proc, REG_PC, &pc); 157 proc_bkptregadj(&pc); 158#endif 159 |
|
155 for (dbp = dt_list_next(&dpr->dpr_bps); 156 dbp != NULL; dbp = dt_list_next(dbp)) { | 160 for (dbp = dt_list_next(&dpr->dpr_bps); 161 dbp != NULL; dbp = dt_list_next(dbp)) { |
162#if defined(sun) |
|
157 if (psp->pr_reg[R_PC] == dbp->dbp_addr) 158 break; | 163 if (psp->pr_reg[R_PC] == dbp->dbp_addr) 164 break; |
165#else 166 if (pc == dbp->dbp_addr) 167 break; 168#endif |
|
159 } 160 161 if (dbp == NULL) { 162 dt_dprintf("pid %d: spurious breakpoint wakeup for %lx\n", | 169 } 170 171 if (dbp == NULL) { 172 dt_dprintf("pid %d: spurious breakpoint wakeup for %lx\n", |
173#if defined(sun) |
|
163 (int)dpr->dpr_pid, (ulong_t)psp->pr_reg[R_PC]); | 174 (int)dpr->dpr_pid, (ulong_t)psp->pr_reg[R_PC]); |
175#else 176 (int)dpr->dpr_pid, pc); 177#endif |
|
164 return; 165 } 166 167 dt_dprintf("pid %d: hit breakpoint at %lx (%lu)\n", 168 (int)dpr->dpr_pid, (ulong_t)dbp->dbp_addr, ++dbp->dbp_hits); 169 170 dbp->dbp_func(dtp, dpr, dbp->dbp_data); 171 (void) Pxecbkpt(dpr->dpr_proc, dbp->dbp_instr); 172} | 178 return; 179 } 180 181 dt_dprintf("pid %d: hit breakpoint at %lx (%lu)\n", 182 (int)dpr->dpr_pid, (ulong_t)dbp->dbp_addr, ++dbp->dbp_hits); 183 184 dbp->dbp_func(dtp, dpr, dbp->dbp_data); 185 (void) Pxecbkpt(dpr->dpr_proc, dbp->dbp_instr); 186} |
173#endif | |
174 175static void 176dt_proc_bpenable(dt_proc_t *dpr) 177{ 178 dt_bkpt_t *dbp; 179 180 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 181 182 for (dbp = dt_list_next(&dpr->dpr_bps); 183 dbp != NULL; dbp = dt_list_next(dbp)) { | 187 188static void 189dt_proc_bpenable(dt_proc_t *dpr) 190{ 191 dt_bkpt_t *dbp; 192 193 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 194 195 for (dbp = dt_list_next(&dpr->dpr_bps); 196 dbp != NULL; dbp = dt_list_next(dbp)) { |
184printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__); 185#ifdef DOODAD | |
186 if (!dbp->dbp_active && Psetbkpt(dpr->dpr_proc, 187 dbp->dbp_addr, &dbp->dbp_instr) == 0) 188 dbp->dbp_active = B_TRUE; | 197 if (!dbp->dbp_active && Psetbkpt(dpr->dpr_proc, 198 dbp->dbp_addr, &dbp->dbp_instr) == 0) 199 dbp->dbp_active = B_TRUE; |
189#endif | |
190 } 191 192 dt_dprintf("breakpoints enabled\n"); 193} 194 195static void 196dt_proc_bpdisable(dt_proc_t *dpr) 197{ 198 dt_bkpt_t *dbp; 199 200 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 201 202 for (dbp = dt_list_next(&dpr->dpr_bps); 203 dbp != NULL; dbp = dt_list_next(dbp)) { | 200 } 201 202 dt_dprintf("breakpoints enabled\n"); 203} 204 205static void 206dt_proc_bpdisable(dt_proc_t *dpr) 207{ 208 dt_bkpt_t *dbp; 209 210 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 211 212 for (dbp = dt_list_next(&dpr->dpr_bps); 213 dbp != NULL; dbp = dt_list_next(dbp)) { |
204printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__); 205#ifdef DOODAD | |
206 if (dbp->dbp_active && Pdelbkpt(dpr->dpr_proc, 207 dbp->dbp_addr, dbp->dbp_instr) == 0) 208 dbp->dbp_active = B_FALSE; | 214 if (dbp->dbp_active && Pdelbkpt(dpr->dpr_proc, 215 dbp->dbp_addr, dbp->dbp_instr) == 0) 216 dbp->dbp_active = B_FALSE; |
209#endif | |
210 } 211 212 dt_dprintf("breakpoints disabled\n"); 213} 214 215static void 216dt_proc_notify(dtrace_hdl_t *dtp, dt_proc_hash_t *dph, dt_proc_t *dpr, 217 const char *msg) --- 56 unchanged lines hidden (view full) --- 274/*ARGSUSED*/ 275static void 276dt_proc_bpmain(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *fname) 277{ 278 dt_dprintf("pid %d: breakpoint at %s()\n", (int)dpr->dpr_pid, fname); 279 dt_proc_stop(dpr, DT_PROC_STOP_MAIN); 280} 281 | 217 } 218 219 dt_dprintf("breakpoints disabled\n"); 220} 221 222static void 223dt_proc_notify(dtrace_hdl_t *dtp, dt_proc_hash_t *dph, dt_proc_t *dpr, 224 const char *msg) --- 56 unchanged lines hidden (view full) --- 281/*ARGSUSED*/ 282static void 283dt_proc_bpmain(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *fname) 284{ 285 dt_dprintf("pid %d: breakpoint at %s()\n", (int)dpr->dpr_pid, fname); 286 dt_proc_stop(dpr, DT_PROC_STOP_MAIN); 287} 288 |
282#if defined(sun) | |
283static void 284dt_proc_rdevent(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *evname) 285{ 286 rd_event_msg_t rdm; 287 rd_err_e err; 288 289 if ((err = rd_event_getmsg(dpr->dpr_rtld, &rdm)) != RD_OK) { 290 dt_dprintf("pid %d: failed to get %s event message: %s\n", --- 40 unchanged lines hidden (view full) --- 331 332 if (rdn.type != RD_NOTIFY_BPT) { 333 dt_dprintf("pid %d: event %s has unexpected type %d\n", 334 (int)dpr->dpr_pid, evname, rdn.type); 335 return; 336 } 337 338 (void) dt_proc_bpcreate(dpr, rdn.u.bptaddr, | 289static void 290dt_proc_rdevent(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *evname) 291{ 292 rd_event_msg_t rdm; 293 rd_err_e err; 294 295 if ((err = rd_event_getmsg(dpr->dpr_rtld, &rdm)) != RD_OK) { 296 dt_dprintf("pid %d: failed to get %s event message: %s\n", --- 40 unchanged lines hidden (view full) --- 337 338 if (rdn.type != RD_NOTIFY_BPT) { 339 dt_dprintf("pid %d: event %s has unexpected type %d\n", 340 (int)dpr->dpr_pid, evname, rdn.type); 341 return; 342 } 343 344 (void) dt_proc_bpcreate(dpr, rdn.u.bptaddr, |
345#if defined(sun) |
|
339 (dt_bkpt_f *)dt_proc_rdevent, (void *)evname); | 346 (dt_bkpt_f *)dt_proc_rdevent, (void *)evname); |
347#else 348 /* XXX ugly */ 349 (dt_bkpt_f *)dt_proc_rdevent, __DECONST(void *, evname)); 350#endif |
|
340} 341 342/* 343 * Common code for enabling events associated with the run-time linker after 344 * attaching to a process or after a victim process completes an exec(2). 345 */ 346static void 347dt_proc_attach(dt_proc_t *dpr, int exec) 348{ | 351} 352 353/* 354 * Common code for enabling events associated with the run-time linker after 355 * attaching to a process or after a victim process completes an exec(2). 356 */ 357static void 358dt_proc_attach(dt_proc_t *dpr, int exec) 359{ |
360#if defined(sun) |
|
349 const pstatus_t *psp = Pstatus(dpr->dpr_proc); | 361 const pstatus_t *psp = Pstatus(dpr->dpr_proc); |
362#endif |
|
350 rd_err_e err; 351 GElf_Sym sym; 352 353 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 354 355 if (exec) { | 363 rd_err_e err; 364 GElf_Sym sym; 365 366 assert(DT_MUTEX_HELD(&dpr->dpr_lock)); 367 368 if (exec) { |
369#if defined(sun) |
|
356 if (psp->pr_lwp.pr_errno != 0) 357 return; /* exec failed: nothing needs to be done */ | 370 if (psp->pr_lwp.pr_errno != 0) 371 return; /* exec failed: nothing needs to be done */ |
372#endif |
|
358 359 dt_proc_bpdestroy(dpr, B_FALSE); | 373 374 dt_proc_bpdestroy(dpr, B_FALSE); |
375#if defined(sun) |
|
360 Preset_maps(dpr->dpr_proc); | 376 Preset_maps(dpr->dpr_proc); |
377#endif |
|
361 } | 378 } |
362 | |
363 if ((dpr->dpr_rtld = Prd_agent(dpr->dpr_proc)) != NULL && 364 (err = rd_event_enable(dpr->dpr_rtld, B_TRUE)) == RD_OK) { | 379 if ((dpr->dpr_rtld = Prd_agent(dpr->dpr_proc)) != NULL && 380 (err = rd_event_enable(dpr->dpr_rtld, B_TRUE)) == RD_OK) { |
381#if defined(sun) |
|
365 dt_proc_rdwatch(dpr, RD_PREINIT, "RD_PREINIT"); | 382 dt_proc_rdwatch(dpr, RD_PREINIT, "RD_PREINIT"); |
383#endif |
|
366 dt_proc_rdwatch(dpr, RD_POSTINIT, "RD_POSTINIT"); | 384 dt_proc_rdwatch(dpr, RD_POSTINIT, "RD_POSTINIT"); |
385#if defined(sun) |
|
367 dt_proc_rdwatch(dpr, RD_DLACTIVITY, "RD_DLACTIVITY"); | 386 dt_proc_rdwatch(dpr, RD_DLACTIVITY, "RD_DLACTIVITY"); |
387#endif |
|
368 } else { 369 dt_dprintf("pid %d: failed to enable rtld events: %s\n", 370 (int)dpr->dpr_pid, dpr->dpr_rtld ? rd_errstr(err) : 371 "rtld_db agent initialization failed"); 372 } 373 374 Pupdate_maps(dpr->dpr_proc); 375 --- 25 unchanged lines hidden (view full) --- 401 * changes, the representative LWP ID changes, or the stop timestamp advances. 402 * dt_proc_control() will then rediscover the new state and continue as usual. 403 * When the process is still stopped in the same exact state, we sleep for a 404 * brief interval before waiting again so as not to spin consuming CPU cycles. 405 */ 406static void 407dt_proc_waitrun(dt_proc_t *dpr) 408{ | 388 } else { 389 dt_dprintf("pid %d: failed to enable rtld events: %s\n", 390 (int)dpr->dpr_pid, dpr->dpr_rtld ? rd_errstr(err) : 391 "rtld_db agent initialization failed"); 392 } 393 394 Pupdate_maps(dpr->dpr_proc); 395 --- 25 unchanged lines hidden (view full) --- 421 * changes, the representative LWP ID changes, or the stop timestamp advances. 422 * dt_proc_control() will then rediscover the new state and continue as usual. 423 * When the process is still stopped in the same exact state, we sleep for a 424 * brief interval before waiting again so as not to spin consuming CPU cycles. 425 */ 426static void 427dt_proc_waitrun(dt_proc_t *dpr) 428{ |
429printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__); 430#ifdef DOODAD |
|
409 struct ps_prochandle *P = dpr->dpr_proc; 410 const lwpstatus_t *psp = &Pstatus(P)->pr_lwp; 411 412 int krflag = psp->pr_flags & (PR_KLC | PR_RLC); 413 timestruc_t tstamp = psp->pr_tstamp; 414 lwpid_t lwpid = psp->pr_lwpid; 415 416 const long wstop = PCWSTOP; --- 33 unchanged lines hidden (view full) --- 450 return; 451 } 452 453 (void) pthread_mutex_unlock(&dpr->dpr_lock); 454 (void) poll(NULL, 0, MILLISEC / 2); 455 } 456 457 (void) pthread_mutex_lock(&dpr->dpr_lock); | 431 struct ps_prochandle *P = dpr->dpr_proc; 432 const lwpstatus_t *psp = &Pstatus(P)->pr_lwp; 433 434 int krflag = psp->pr_flags & (PR_KLC | PR_RLC); 435 timestruc_t tstamp = psp->pr_tstamp; 436 lwpid_t lwpid = psp->pr_lwpid; 437 438 const long wstop = PCWSTOP; --- 33 unchanged lines hidden (view full) --- 472 return; 473 } 474 475 (void) pthread_mutex_unlock(&dpr->dpr_lock); 476 (void) poll(NULL, 0, MILLISEC / 2); 477 } 478 479 (void) pthread_mutex_lock(&dpr->dpr_lock); |
458} | |
459#endif | 480#endif |
481} |
|
460 461typedef struct dt_proc_control_data { 462 dtrace_hdl_t *dpcd_hdl; /* DTrace handle */ 463 dt_proc_t *dpcd_proc; /* proccess to control */ 464} dt_proc_control_data_t; 465 466/* 467 * Main loop for all victim process control threads. We initialize all the --- 60 unchanged lines hidden (view full) --- 528 * does not inherit any other tracing behaviors or a control thread. 529 */ 530 (void) Psysentry(P, SYS_vfork, B_TRUE); 531 (void) Psysexit(P, SYS_vfork, B_TRUE); 532 (void) Psysentry(P, SYS_forksys, B_TRUE); 533 (void) Psysexit(P, SYS_forksys, B_TRUE); 534 535 Psync(P); /* enable all /proc changes */ | 482 483typedef struct dt_proc_control_data { 484 dtrace_hdl_t *dpcd_hdl; /* DTrace handle */ 485 dt_proc_t *dpcd_proc; /* proccess to control */ 486} dt_proc_control_data_t; 487 488/* 489 * Main loop for all victim process control threads. We initialize all the --- 60 unchanged lines hidden (view full) --- 550 * does not inherit any other tracing behaviors or a control thread. 551 */ 552 (void) Psysentry(P, SYS_vfork, B_TRUE); 553 (void) Psysexit(P, SYS_vfork, B_TRUE); 554 (void) Psysentry(P, SYS_forksys, B_TRUE); 555 (void) Psysexit(P, SYS_forksys, B_TRUE); 556 557 Psync(P); /* enable all /proc changes */ |
558#endif |
|
536 dt_proc_attach(dpr, B_FALSE); /* enable rtld breakpoints */ 537 538 /* 539 * If PR_KLC is set, we created the process; otherwise we grabbed it. 540 * Check for an appropriate stop request and wait for dt_proc_continue. 541 */ | 559 dt_proc_attach(dpr, B_FALSE); /* enable rtld breakpoints */ 560 561 /* 562 * If PR_KLC is set, we created the process; otherwise we grabbed it. 563 * Check for an appropriate stop request and wait for dt_proc_continue. 564 */ |
565#if defined(sun) |
|
542 if (Pstatus(P)->pr_flags & PR_KLC) | 566 if (Pstatus(P)->pr_flags & PR_KLC) |
567#else 568 if (proc_getflags(P) & PR_KLC) 569#endif |
|
543 dt_proc_stop(dpr, DT_PROC_STOP_CREATE); 544 else 545 dt_proc_stop(dpr, DT_PROC_STOP_GRAB); 546 547 if (Psetrun(P, 0, 0) == -1) { 548 dt_dprintf("pid %d: failed to set running: %s\n", 549 (int)dpr->dpr_pid, strerror(errno)); 550 } | 570 dt_proc_stop(dpr, DT_PROC_STOP_CREATE); 571 else 572 dt_proc_stop(dpr, DT_PROC_STOP_GRAB); 573 574 if (Psetrun(P, 0, 0) == -1) { 575 dt_dprintf("pid %d: failed to set running: %s\n", 576 (int)dpr->dpr_pid, strerror(errno)); 577 } |
551#else 552 /* 553 * If PR_KLC is set, we created the process; otherwise we grabbed it. 554 * Check for an appropriate stop request and wait for dt_proc_continue. 555 */ 556 if (proc_getflags(P) & PR_KLC) 557 dt_proc_stop(dpr, DT_PROC_STOP_CREATE); 558 else 559 dt_proc_stop(dpr, DT_PROC_STOP_GRAB); | |
560 | 578 |
561 if (proc_continue(P) != 0) 562 dt_dprintf("pid %d: failed to set running: %s\n", 563 (int)dpr->dpr_pid, strerror(errno)); 564#endif 565 | |
566 (void) pthread_mutex_unlock(&dpr->dpr_lock); 567 568 /* 569 * Wait for the process corresponding to this control thread to stop, 570 * process the event, and then set it running again. We want to sleep 571 * with dpr_lock *unheld* so that other parts of libdtrace can use the 572 * ps_prochandle in the meantime (e.g. ustack()). To do this, we write 573 * a PCWSTOP directive directly to the underlying /proc/<pid>/ctl file. 574 * Once the process stops, we wake up, grab dpr_lock, and then call 575 * Pwait() (which will return immediately) and do our processing. 576 */ 577 while (!dpr->dpr_quit) { | 579 (void) pthread_mutex_unlock(&dpr->dpr_lock); 580 581 /* 582 * Wait for the process corresponding to this control thread to stop, 583 * process the event, and then set it running again. We want to sleep 584 * with dpr_lock *unheld* so that other parts of libdtrace can use the 585 * ps_prochandle in the meantime (e.g. ustack()). To do this, we write 586 * a PCWSTOP directive directly to the underlying /proc/<pid>/ctl file. 587 * Once the process stops, we wake up, grab dpr_lock, and then call 588 * Pwait() (which will return immediately) and do our processing. 589 */ 590 while (!dpr->dpr_quit) { |
578#if defined(sun) | |
579 const lwpstatus_t *psp; 580 | 591 const lwpstatus_t *psp; 592 |
593#if defined(sun) |
|
581 if (write(pfd, &wstop, sizeof (wstop)) == -1 && errno == EINTR) 582 continue; /* check dpr_quit and continue waiting */ 583#else 584 /* Wait for the process to report status. */ 585 proc_wstatus(P); | 594 if (write(pfd, &wstop, sizeof (wstop)) == -1 && errno == EINTR) 595 continue; /* check dpr_quit and continue waiting */ 596#else 597 /* Wait for the process to report status. */ 598 proc_wstatus(P); |
599 if (errno == EINTR) 600 continue; /* check dpr_quit and continue waiting */ |
|
586#endif 587 588 (void) pthread_mutex_lock(&dpr->dpr_lock); 589 590#if defined(sun) 591pwait_locked: 592 if (Pstopstatus(P, PCNULL, 0) == -1 && errno == EINTR) { 593 (void) pthread_mutex_unlock(&dpr->dpr_lock); 594 continue; /* check dpr_quit and continue waiting */ 595 } 596#endif 597 | 601#endif 602 603 (void) pthread_mutex_lock(&dpr->dpr_lock); 604 605#if defined(sun) 606pwait_locked: 607 if (Pstopstatus(P, PCNULL, 0) == -1 && errno == EINTR) { 608 (void) pthread_mutex_unlock(&dpr->dpr_lock); 609 continue; /* check dpr_quit and continue waiting */ 610 } 611#endif 612 |
598#if defined(sun) | |
599 switch (Pstate(P)) { | 613 switch (Pstate(P)) { |
600#else 601 switch (proc_state(P)) { 602#endif | |
603 case PS_STOP: | 614 case PS_STOP: |
604#ifdef DOODAD | 615#if defined(sun) |
605 psp = &Pstatus(P)->pr_lwp; | 616 psp = &Pstatus(P)->pr_lwp; |
617#else 618 psp = proc_getlwpstatus(P); 619#endif |
|
606 607 dt_dprintf("pid %d: proc stopped showing %d/%d\n", 608 pid, psp->pr_why, psp->pr_what); 609 610 /* 611 * If the process stops showing PR_REQUESTED, then the 612 * DTrace stop() action was applied to it or another 613 * debugging utility (e.g. pstop(1)) asked it to stop. --- 25 unchanged lines hidden (view full) --- 639 IS_SYS_FORK(psp->pr_what)) 640 dt_proc_bpdisable(dpr); 641 else if (psp->pr_why == PR_SYSEXIT && 642 IS_SYS_FORK(psp->pr_what)) 643 dt_proc_bpenable(dpr); 644 else if (psp->pr_why == PR_SYSEXIT && 645 IS_SYS_EXEC(psp->pr_what)) 646 dt_proc_attach(dpr, B_TRUE); | 620 621 dt_dprintf("pid %d: proc stopped showing %d/%d\n", 622 pid, psp->pr_why, psp->pr_what); 623 624 /* 625 * If the process stops showing PR_REQUESTED, then the 626 * DTrace stop() action was applied to it or another 627 * debugging utility (e.g. pstop(1)) asked it to stop. --- 25 unchanged lines hidden (view full) --- 653 IS_SYS_FORK(psp->pr_what)) 654 dt_proc_bpdisable(dpr); 655 else if (psp->pr_why == PR_SYSEXIT && 656 IS_SYS_FORK(psp->pr_what)) 657 dt_proc_bpenable(dpr); 658 else if (psp->pr_why == PR_SYSEXIT && 659 IS_SYS_EXEC(psp->pr_what)) 660 dt_proc_attach(dpr, B_TRUE); |
647#endif | |
648 break; 649 650 case PS_LOST: 651#if defined(sun) 652 if (Preopen(P) == 0) 653 goto pwait_locked; 654#endif 655 --- 6 unchanged lines hidden (view full) --- 662 663 case PS_UNDEAD: 664 dt_dprintf("pid %d: proc died\n", pid); 665 dpr->dpr_quit = B_TRUE; 666 notify = B_TRUE; 667 break; 668 } 669 | 661 break; 662 663 case PS_LOST: 664#if defined(sun) 665 if (Preopen(P) == 0) 666 goto pwait_locked; 667#endif 668 --- 6 unchanged lines hidden (view full) --- 675 676 case PS_UNDEAD: 677 dt_dprintf("pid %d: proc died\n", pid); 678 dpr->dpr_quit = B_TRUE; 679 notify = B_TRUE; 680 break; 681 } 682 |
670#if defined(sun) | |
671 if (Pstate(P) != PS_UNDEAD && Psetrun(P, 0, 0) == -1) { 672 dt_dprintf("pid %d: failed to set running: %s\n", 673 (int)dpr->dpr_pid, strerror(errno)); 674 } | 683 if (Pstate(P) != PS_UNDEAD && Psetrun(P, 0, 0) == -1) { 684 dt_dprintf("pid %d: failed to set running: %s\n", 685 (int)dpr->dpr_pid, strerror(errno)); 686 } |
675#endif | |
676 677 (void) pthread_mutex_unlock(&dpr->dpr_lock); 678 } 679 680 /* 681 * If the control thread detected PS_UNDEAD or PS_LOST, then enqueue 682 * the dt_proc_t structure on the dt_proc_hash_t notification list. 683 */ --- 23 unchanged lines hidden (view full) --- 707{ 708 va_list ap; 709 710 va_start(ap, format); 711 dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap); 712 va_end(ap); 713 714 if (dpr->dpr_proc != NULL) | 687 688 (void) pthread_mutex_unlock(&dpr->dpr_lock); 689 } 690 691 /* 692 * If the control thread detected PS_UNDEAD or PS_LOST, then enqueue 693 * the dt_proc_t structure on the dt_proc_hash_t notification list. 694 */ --- 23 unchanged lines hidden (view full) --- 718{ 719 va_list ap; 720 721 va_start(ap, format); 722 dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap); 723 va_end(ap); 724 725 if (dpr->dpr_proc != NULL) |
715#if defined(sun) | |
716 Prelease(dpr->dpr_proc, 0); | 726 Prelease(dpr->dpr_proc, 0); |
717#else 718 proc_detach(dpr->dpr_proc, 0); 719#endif | |
720 721 dt_free(dtp, dpr); 722 (void) dt_set_errno(dtp, EDT_COMPILER); 723 return (NULL); 724} 725 726dt_proc_t * 727dt_proc_lookup(dtrace_hdl_t *dtp, struct ps_prochandle *P, int remove) --- 71 unchanged lines hidden (view full) --- 799 * to do the job. This is all built on evil knowledge of 800 * the details of the cancellation mechanism in libc. 801 */ 802 (void) pthread_mutex_lock(&dpr->dpr_lock); 803 dpr->dpr_quit = B_TRUE; 804#if defined(sun) 805 (void) _lwp_kill(dpr->dpr_tid, SIGCANCEL); 806#else | 727 728 dt_free(dtp, dpr); 729 (void) dt_set_errno(dtp, EDT_COMPILER); 730 return (NULL); 731} 732 733dt_proc_t * 734dt_proc_lookup(dtrace_hdl_t *dtp, struct ps_prochandle *P, int remove) --- 71 unchanged lines hidden (view full) --- 806 * to do the job. This is all built on evil knowledge of 807 * the details of the cancellation mechanism in libc. 808 */ 809 (void) pthread_mutex_lock(&dpr->dpr_lock); 810 dpr->dpr_quit = B_TRUE; 811#if defined(sun) 812 (void) _lwp_kill(dpr->dpr_tid, SIGCANCEL); 813#else |
807 (void) pthread_kill(dpr->dpr_tid, SIGUSR1); | 814 pthread_kill(dpr->dpr_tid, SIGUSR1); |
808#endif 809 810 /* 811 * If the process is currently idling in dt_proc_stop(), re- 812 * enable breakpoints and poke it into running again. 813 */ 814 if (dpr->dpr_stop & DT_PROC_STOP_IDLE) { 815 dt_proc_bpenable(dpr); --- 32 unchanged lines hidden (view full) --- 848 * libproc handle, and free our dt_proc_t data structure. 849 */ 850 if (dpr->dpr_cacheable) { 851 assert(dph->dph_lrucnt != 0); 852 dph->dph_lrucnt--; 853 } 854 855 dt_list_delete(&dph->dph_lrulist, dpr); | 815#endif 816 817 /* 818 * If the process is currently idling in dt_proc_stop(), re- 819 * enable breakpoints and poke it into running again. 820 */ 821 if (dpr->dpr_stop & DT_PROC_STOP_IDLE) { 822 dt_proc_bpenable(dpr); --- 32 unchanged lines hidden (view full) --- 855 * libproc handle, and free our dt_proc_t data structure. 856 */ 857 if (dpr->dpr_cacheable) { 858 assert(dph->dph_lrucnt != 0); 859 dph->dph_lrucnt--; 860 } 861 862 dt_list_delete(&dph->dph_lrulist, dpr); |
856#if defined(sun) | |
857 Prelease(dpr->dpr_proc, rflag); | 863 Prelease(dpr->dpr_proc, rflag); |
858#else 859 proc_detach(dpr->dpr_proc, rflag); 860#endif | |
861 dt_free(dtp, dpr); 862} 863 864static int 865dt_proc_create_thread(dtrace_hdl_t *dtp, dt_proc_t *dpr, uint_t stop) 866{ 867 dt_proc_control_data_t data; 868 sigset_t nset, oset; --- 38 unchanged lines hidden (view full) --- 907 * reached the rendezvous event. This is either due to PS_LOST 908 * or PS_UNDEAD (i.e. the process died). We try to provide a 909 * small amount of useful information to help figure it out. 910 */ 911 if (dpr->dpr_done) { 912#if defined(sun) 913 const psinfo_t *prp = Ppsinfo(dpr->dpr_proc); 914 int stat = prp ? prp->pr_wstat : 0; | 864 dt_free(dtp, dpr); 865} 866 867static int 868dt_proc_create_thread(dtrace_hdl_t *dtp, dt_proc_t *dpr, uint_t stop) 869{ 870 dt_proc_control_data_t data; 871 sigset_t nset, oset; --- 38 unchanged lines hidden (view full) --- 910 * reached the rendezvous event. This is either due to PS_LOST 911 * or PS_UNDEAD (i.e. the process died). We try to provide a 912 * small amount of useful information to help figure it out. 913 */ 914 if (dpr->dpr_done) { 915#if defined(sun) 916 const psinfo_t *prp = Ppsinfo(dpr->dpr_proc); 917 int stat = prp ? prp->pr_wstat : 0; |
915#endif | |
916 int pid = dpr->dpr_pid; | 918 int pid = dpr->dpr_pid; |
917 918#if defined(sun) 919 if (Pstate(dpr->dpr_proc) == PS_LOST) { | |
920#else | 919#else |
921 if (proc_state(dpr->dpr_proc) == PS_LOST) { | 920 int stat = proc_getwstat(dpr->dpr_proc); 921 int pid = proc_getpid(dpr->dpr_proc); |
922#endif | 922#endif |
923 if (proc_state(dpr->dpr_proc) == PS_LOST) { |
|
923 (void) dt_proc_error(dpr->dpr_hdl, dpr, 924 "failed to control pid %d: process exec'd " 925 "set-id or unobservable program\n", pid); | 924 (void) dt_proc_error(dpr->dpr_hdl, dpr, 925 "failed to control pid %d: process exec'd " 926 "set-id or unobservable program\n", pid); |
926#if defined(sun) | |
927 } else if (WIFSIGNALED(stat)) { 928 (void) dt_proc_error(dpr->dpr_hdl, dpr, 929 "failed to control pid %d: process died " 930 "from signal %d\n", pid, WTERMSIG(stat)); 931 } else { 932 (void) dt_proc_error(dpr->dpr_hdl, dpr, 933 "failed to control pid %d: process exited " 934 "with status %d\n", pid, WEXITSTATUS(stat)); | 927 } else if (WIFSIGNALED(stat)) { 928 (void) dt_proc_error(dpr->dpr_hdl, dpr, 929 "failed to control pid %d: process died " 930 "from signal %d\n", pid, WTERMSIG(stat)); 931 } else { 932 (void) dt_proc_error(dpr->dpr_hdl, dpr, 933 "failed to control pid %d: process exited " 934 "with status %d\n", pid, WEXITSTATUS(stat)); |
935#endif | |
936 } 937 938 err = ESRCH; /* cause grab() or create() to fail */ 939 } 940 } else { 941 (void) dt_proc_error(dpr->dpr_hdl, dpr, 942 "failed to create control thread for process-id %d: %s\n", 943 (int)dpr->dpr_pid, strerror(err)); --- 16 unchanged lines hidden (view full) --- 960 if ((dpr = dt_zalloc(dtp, sizeof (dt_proc_t))) == NULL) 961 return (NULL); /* errno is set for us */ 962 963 (void) pthread_mutex_init(&dpr->dpr_lock, NULL); 964 (void) pthread_cond_init(&dpr->dpr_cv, NULL); 965 966#if defined(sun) 967 if ((dpr->dpr_proc = Pcreate(file, argv, &err, NULL, 0)) == NULL) { | 935 } 936 937 err = ESRCH; /* cause grab() or create() to fail */ 938 } 939 } else { 940 (void) dt_proc_error(dpr->dpr_hdl, dpr, 941 "failed to create control thread for process-id %d: %s\n", 942 (int)dpr->dpr_pid, strerror(err)); --- 16 unchanged lines hidden (view full) --- 959 if ((dpr = dt_zalloc(dtp, sizeof (dt_proc_t))) == NULL) 960 return (NULL); /* errno is set for us */ 961 962 (void) pthread_mutex_init(&dpr->dpr_lock, NULL); 963 (void) pthread_cond_init(&dpr->dpr_cv, NULL); 964 965#if defined(sun) 966 if ((dpr->dpr_proc = Pcreate(file, argv, &err, NULL, 0)) == NULL) { |
967#else 968 if ((err = proc_create(file, argv, pcf, child_arg, 969 &dpr->dpr_proc)) != 0) { 970#endif |
|
968 return (dt_proc_error(dtp, dpr, 969 "failed to execute %s: %s\n", file, Pcreate_error(err))); 970 } 971 972 dpr->dpr_hdl = dtp; | 971 return (dt_proc_error(dtp, dpr, 972 "failed to execute %s: %s\n", file, Pcreate_error(err))); 973 } 974 975 dpr->dpr_hdl = dtp; |
976#if defined(sun) |
|
973 dpr->dpr_pid = Pstatus(dpr->dpr_proc)->pr_pid; | 977 dpr->dpr_pid = Pstatus(dpr->dpr_proc)->pr_pid; |
974 975 (void) Punsetflags(dpr->dpr_proc, PR_RLC); 976 (void) Psetflags(dpr->dpr_proc, PR_KLC); | |
977#else | 978#else |
978 (void) proc_clearflags(dpr->dpr_proc, PR_RLC); 979 (void) proc_setflags(dpr->dpr_proc, PR_KLC); 980 if ((err = proc_create(file, argv, pcf, child_arg, &dpr->dpr_proc)) != 0) 981 return (dt_proc_error(dtp, dpr, 982 "failed to execute %s: %s\n", file, strerror(err))); 983 dpr->dpr_hdl = dtp; | |
984 dpr->dpr_pid = proc_getpid(dpr->dpr_proc); 985#endif 986 | 979 dpr->dpr_pid = proc_getpid(dpr->dpr_proc); 980#endif 981 |
987#if defined(sun) | 982 (void) Punsetflags(dpr->dpr_proc, PR_RLC); 983 (void) Psetflags(dpr->dpr_proc, PR_KLC); 984 |
988 if (dt_proc_create_thread(dtp, dpr, dtp->dt_prcmode) != 0) | 985 if (dt_proc_create_thread(dtp, dpr, dtp->dt_prcmode) != 0) |
989#else 990 if (dt_proc_create_thread(dtp, dpr, DT_PROC_STOP_IDLE) != 0) 991#endif | |
992 return (NULL); /* dt_proc_error() has been called for us */ 993 994 dpr->dpr_hash = dph->dph_hash[dpr->dpr_pid & (dph->dph_hashlen - 1)]; 995 dph->dph_hash[dpr->dpr_pid & (dph->dph_hashlen - 1)] = dpr; 996 dt_list_prepend(&dph->dph_lrulist, dpr); 997 998 dt_dprintf("created pid %d\n", (int)dpr->dpr_pid); 999 dpr->dpr_refs++; --- 41 unchanged lines hidden (view full) --- 1041 if ((dpr = dt_zalloc(dtp, sizeof (dt_proc_t))) == NULL) 1042 return (NULL); /* errno is set for us */ 1043 1044 (void) pthread_mutex_init(&dpr->dpr_lock, NULL); 1045 (void) pthread_cond_init(&dpr->dpr_cv, NULL); 1046 1047#if defined(sun) 1048 if ((dpr->dpr_proc = Pgrab(pid, flags, &err)) == NULL) { | 986 return (NULL); /* dt_proc_error() has been called for us */ 987 988 dpr->dpr_hash = dph->dph_hash[dpr->dpr_pid & (dph->dph_hashlen - 1)]; 989 dph->dph_hash[dpr->dpr_pid & (dph->dph_hashlen - 1)] = dpr; 990 dt_list_prepend(&dph->dph_lrulist, dpr); 991 992 dt_dprintf("created pid %d\n", (int)dpr->dpr_pid); 993 dpr->dpr_refs++; --- 41 unchanged lines hidden (view full) --- 1035 if ((dpr = dt_zalloc(dtp, sizeof (dt_proc_t))) == NULL) 1036 return (NULL); /* errno is set for us */ 1037 1038 (void) pthread_mutex_init(&dpr->dpr_lock, NULL); 1039 (void) pthread_cond_init(&dpr->dpr_cv, NULL); 1040 1041#if defined(sun) 1042 if ((dpr->dpr_proc = Pgrab(pid, flags, &err)) == NULL) { |
1043#else 1044 if ((err = proc_attach(pid, flags, &dpr->dpr_proc)) != 0) { 1045#endif |
|
1049 return (dt_proc_error(dtp, dpr, 1050 "failed to grab pid %d: %s\n", (int)pid, Pgrab_error(err))); 1051 } | 1046 return (dt_proc_error(dtp, dpr, 1047 "failed to grab pid %d: %s\n", (int)pid, Pgrab_error(err))); 1048 } |
1052#else 1053 if ((err = proc_attach(pid, flags, &dpr->dpr_proc)) != 0) 1054 return (dt_proc_error(dtp, dpr, 1055 "failed to grab pid %d: %s\n", (int) pid, strerror(err))); 1056#endif | |
1057 1058 dpr->dpr_hdl = dtp; 1059 dpr->dpr_pid = pid; 1060 | 1049 1050 dpr->dpr_hdl = dtp; 1051 dpr->dpr_pid = pid; 1052 |
1061#if defined(sun) | |
1062 (void) Punsetflags(dpr->dpr_proc, PR_KLC); 1063 (void) Psetflags(dpr->dpr_proc, PR_RLC); | 1053 (void) Punsetflags(dpr->dpr_proc, PR_KLC); 1054 (void) Psetflags(dpr->dpr_proc, PR_RLC); |
1064#else 1065 (void) proc_clearflags(dpr->dpr_proc, PR_KLC); 1066 (void) proc_setflags(dpr->dpr_proc, PR_RLC); 1067#endif | |
1068 1069 /* 1070 * If we are attempting to grab the process without a monitor 1071 * thread, then mark the process cacheable only if it's being 1072 * grabbed read-only. If we're currently caching more process 1073 * handles than dph_lrulim permits, attempt to find the 1074 * least-recently-used handle that is currently unreferenced and 1075 * release it from the cache. Otherwise we are grabbing the process --- 104 unchanged lines hidden (view full) --- 1180 1181struct ps_prochandle * 1182dtrace_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv, 1183 proc_child_func *pcf, void *child_arg) 1184{ 1185 dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target"); 1186 struct ps_prochandle *P = dt_proc_create(dtp, file, argv, pcf, child_arg); 1187 | 1055 1056 /* 1057 * If we are attempting to grab the process without a monitor 1058 * thread, then mark the process cacheable only if it's being 1059 * grabbed read-only. If we're currently caching more process 1060 * handles than dph_lrulim permits, attempt to find the 1061 * least-recently-used handle that is currently unreferenced and 1062 * release it from the cache. Otherwise we are grabbing the process --- 104 unchanged lines hidden (view full) --- 1167 1168struct ps_prochandle * 1169dtrace_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv, 1170 proc_child_func *pcf, void *child_arg) 1171{ 1172 dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target"); 1173 struct ps_prochandle *P = dt_proc_create(dtp, file, argv, pcf, child_arg); 1174 |
1188 if (P != NULL && idp != NULL && idp->di_id == 0) | 1175 if (P != NULL && idp != NULL && idp->di_id == 0) { |
1189#if defined(sun) 1190 idp->di_id = Pstatus(P)->pr_pid; /* $target = created pid */ 1191#else 1192 idp->di_id = proc_getpid(P); /* $target = created pid */ 1193#endif | 1176#if defined(sun) 1177 idp->di_id = Pstatus(P)->pr_pid; /* $target = created pid */ 1178#else 1179 idp->di_id = proc_getpid(P); /* $target = created pid */ 1180#endif |
1181 } |
|
1194 1195 return (P); 1196} 1197 1198struct ps_prochandle * 1199dtrace_proc_grab(dtrace_hdl_t *dtp, pid_t pid, int flags) 1200{ 1201 dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target"); --- 19 unchanged lines hidden --- | 1182 1183 return (P); 1184} 1185 1186struct ps_prochandle * 1187dtrace_proc_grab(dtrace_hdl_t *dtp, pid_t pid, int flags) 1188{ 1189 dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target"); --- 19 unchanged lines hidden --- |