Deleted Added
sdiff udiff text old ( 210775 ) new ( 211554 )
full compact
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#define IS_SYS_EXEC(w) (w == SYS_execve)
93#define IS_SYS_FORK(w) (w == SYS_vfork || w == SYS_forksys)
94
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}
117#endif
118
119static void
120dt_proc_bpdestroy(dt_proc_t *dpr, int delbkpts)
121{
122#if defined(sun)
123 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) {
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 }
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
146#ifdef DOODAD
147static void
148dt_proc_bpmatch(dtrace_hdl_t *dtp, dt_proc_t *dpr)
149{
150 const lwpstatus_t *psp = &Pstatus(dpr->dpr_proc)->pr_lwp;
151 dt_bkpt_t *dbp;
152
153 assert(DT_MUTEX_HELD(&dpr->dpr_lock));
154
155 for (dbp = dt_list_next(&dpr->dpr_bps);
156 dbp != NULL; dbp = dt_list_next(dbp)) {
157 if (psp->pr_reg[R_PC] == dbp->dbp_addr)
158 break;
159 }
160
161 if (dbp == NULL) {
162 dt_dprintf("pid %d: spurious breakpoint wakeup for %lx\n",
163 (int)dpr->dpr_pid, (ulong_t)psp->pr_reg[R_PC]);
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}
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)) {
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;
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)) {
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;
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
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,
339 (dt_bkpt_f *)dt_proc_rdevent, (void *)evname);
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{
349 const pstatus_t *psp = Pstatus(dpr->dpr_proc);
350 rd_err_e err;
351 GElf_Sym sym;
352
353 assert(DT_MUTEX_HELD(&dpr->dpr_lock));
354
355 if (exec) {
356 if (psp->pr_lwp.pr_errno != 0)
357 return; /* exec failed: nothing needs to be done */
358
359 dt_proc_bpdestroy(dpr, B_FALSE);
360 Preset_maps(dpr->dpr_proc);
361 }
362
363 if ((dpr->dpr_rtld = Prd_agent(dpr->dpr_proc)) != NULL &&
364 (err = rd_event_enable(dpr->dpr_rtld, B_TRUE)) == RD_OK) {
365 dt_proc_rdwatch(dpr, RD_PREINIT, "RD_PREINIT");
366 dt_proc_rdwatch(dpr, RD_POSTINIT, "RD_POSTINIT");
367 dt_proc_rdwatch(dpr, RD_DLACTIVITY, "RD_DLACTIVITY");
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{
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);
458}
459#endif
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 */
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 */
542 if (Pstatus(P)->pr_flags & PR_KLC)
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 }
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
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) {
578#if defined(sun)
579 const lwpstatus_t *psp;
580
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);
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
598#if defined(sun)
599 switch (Pstate(P)) {
600#else
601 switch (proc_state(P)) {
602#endif
603 case PS_STOP:
604#ifdef DOODAD
605 psp = &Pstatus(P)->pr_lwp;
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);
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
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 }
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)
715#if defined(sun)
716 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
807 (void) 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);
856#if defined(sun)
857 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;
915#endif
916 int pid = dpr->dpr_pid;
917
918#if defined(sun)
919 if (Pstate(dpr->dpr_proc) == PS_LOST) {
920#else
921 if (proc_state(dpr->dpr_proc) == PS_LOST) {
922#endif
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);
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));
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) {
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;
973 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 (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
987#if defined(sun)
988 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) {
1049 return (dt_proc_error(dtp, dpr,
1050 "failed to grab pid %d: %s\n", (int)pid, Pgrab_error(err)));
1051 }
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
1061#if defined(sun)
1062 (void) Punsetflags(dpr->dpr_proc, PR_KLC);
1063 (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
1188 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
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 ---