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#if !defined(sun)
93#include <sys/syscall.h>
94#include <libproc_compat.h>
95#define SYS_forksys SYS_fork
96#endif
97
98#define IS_SYS_EXEC(w) (w == SYS_execve)
99#define IS_SYS_FORK(w) (w == SYS_vfork || w == SYS_forksys)
100
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}
122
123static void
124dt_proc_bpdestroy(dt_proc_t *dpr, int delbkpts)
125{
126 int state = Pstate(dpr->dpr_proc);
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) {
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 }
137 nbp = dt_list_next(dbp);
138 dt_list_delete(&dpr->dpr_bps, dbp);
139 dt_free(dpr->dpr_hdl, dbp);
140 }
141}
142
143static void
144dt_proc_bpmatch(dtrace_hdl_t *dtp, dt_proc_t *dpr)
145{
146#if defined(sun)
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
155#if !defined(sun)
156 proc_regget(dpr->dpr_proc, REG_PC, &pc);
157 proc_bkptregadj(&pc);
158#endif
159
160 for (dbp = dt_list_next(&dpr->dpr_bps);
161 dbp != NULL; dbp = dt_list_next(dbp)) {
162#if defined(sun)
163 if (psp->pr_reg[R_PC] == dbp->dbp_addr)
164 break;
165#else
166 if (pc == dbp->dbp_addr)
167 break;
168#endif
169 }
170
171 if (dbp == NULL) {
172 dt_dprintf("pid %d: spurious breakpoint wakeup for %lx\n",
173#if defined(sun)
174 (int)dpr->dpr_pid, (ulong_t)psp->pr_reg[R_PC]);
175#else
176 (int)dpr->dpr_pid, pc);
177#endif
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}
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)) {
197 if (!dbp->dbp_active && Psetbkpt(dpr->dpr_proc,
198 dbp->dbp_addr, &dbp->dbp_instr) == 0)
199 dbp->dbp_active = B_TRUE;
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)) {
214 if (dbp->dbp_active && Pdelbkpt(dpr->dpr_proc,
215 dbp->dbp_addr, dbp->dbp_instr) == 0)
216 dbp->dbp_active = B_FALSE;
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
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)
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
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)
361 const pstatus_t *psp = Pstatus(dpr->dpr_proc);
362#endif
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)
370 if (psp->pr_lwp.pr_errno != 0)
371 return; /* exec failed: nothing needs to be done */
372#endif
373
374 dt_proc_bpdestroy(dpr, B_FALSE);
375#if defined(sun)
376 Preset_maps(dpr->dpr_proc);
377#endif
378 }
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)
382 dt_proc_rdwatch(dpr, RD_PREINIT, "RD_PREINIT");
383#endif
384 dt_proc_rdwatch(dpr, RD_POSTINIT, "RD_POSTINIT");
385#if defined(sun)
386 dt_proc_rdwatch(dpr, RD_DLACTIVITY, "RD_DLACTIVITY");
387#endif
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
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);
480#endif
481}
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
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)
566 if (Pstatus(P)->pr_flags & PR_KLC)
567#else
568 if (proc_getflags(P) & PR_KLC)
569#endif
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 }
578
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) {
591 const lwpstatus_t *psp;
592
593#if defined(sun)
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 */
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
613 switch (Pstate(P)) {
614 case PS_STOP:
615#if defined(sun)
616 psp = &Pstatus(P)->pr_lwp;
617#else
618 psp = proc_getlwpstatus(P);
619#endif
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);
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
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 }
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)
726 Prelease(dpr->dpr_proc, 0);
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
814 pthread_kill(dpr->dpr_tid, SIGUSR1);
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);
863 Prelease(dpr->dpr_proc, rflag);
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;
918 int pid = dpr->dpr_pid;
919#else
920 int stat = proc_getwstat(dpr->dpr_proc);
921 int pid = proc_getpid(dpr->dpr_proc);
922#endif
923 if (proc_state(dpr->dpr_proc) == PS_LOST) {
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);
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 }
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
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)
977 dpr->dpr_pid = Pstatus(dpr->dpr_proc)->pr_pid;
978#else
979 dpr->dpr_pid = proc_getpid(dpr->dpr_proc);
980#endif
981
982 (void) Punsetflags(dpr->dpr_proc, PR_RLC);
983 (void) Psetflags(dpr->dpr_proc, PR_KLC);
984
985 if (dt_proc_create_thread(dtp, dpr, dtp->dt_prcmode) != 0)
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
1046 return (dt_proc_error(dtp, dpr,
1047 "failed to grab pid %d: %s\n", (int)pid, Pgrab_error(err)));
1048 }
1049
1050 dpr->dpr_hdl = dtp;
1051 dpr->dpr_pid = pid;
1052
1053 (void) Punsetflags(dpr->dpr_proc, PR_KLC);
1054 (void) Psetflags(dpr->dpr_proc, PR_RLC);
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
1175 if (P != NULL && idp != NULL && idp->di_id == 0) {
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 }
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 ---