* Use FreeBSD's process library instead of the Solaris one.
* There are a few placeholders in here for which there isn't libproc support code yet. This is relevent to userland tracing. This set of commits is designed to get kernel tracing up and running, with the userland stuff to follow later.
This commit is contained in:
parent
d46d190310
commit
bbda5851ce
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=178565
@ -79,7 +79,9 @@
|
||||
*/
|
||||
|
||||
#include <sys/wait.h>
|
||||
#if defined(sun)
|
||||
#include <sys/lwp.h>
|
||||
#endif
|
||||
#include <strings.h>
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
@ -93,6 +95,7 @@
|
||||
#define IS_SYS_FORK(w) (w == SYS_vfork || w == SYS_fork1 || \
|
||||
w == SYS_forkall || w == SYS_forksys)
|
||||
|
||||
#ifdef DOODAD
|
||||
static dt_bkpt_t *
|
||||
dt_proc_bpcreate(dt_proc_t *dpr, uintptr_t addr, dt_bkpt_f *func, void *data)
|
||||
{
|
||||
@ -114,27 +117,36 @@ dt_proc_bpcreate(dt_proc_t *dpr, uintptr_t addr, dt_bkpt_f *func, void *data)
|
||||
|
||||
return (dbp);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
dt_proc_bpdestroy(dt_proc_t *dpr, int delbkpts)
|
||||
{
|
||||
#if defined(sun)
|
||||
int state = Pstate(dpr->dpr_proc);
|
||||
#else
|
||||
int state = proc_state(dpr->dpr_proc);
|
||||
#endif
|
||||
dt_bkpt_t *dbp, *nbp;
|
||||
|
||||
assert(DT_MUTEX_HELD(&dpr->dpr_lock));
|
||||
|
||||
for (dbp = dt_list_next(&dpr->dpr_bps); dbp != NULL; dbp = nbp) {
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
#ifdef DOODAD
|
||||
if (delbkpts && dbp->dbp_active &&
|
||||
state != PS_LOST && state != PS_UNDEAD) {
|
||||
(void) Pdelbkpt(dpr->dpr_proc,
|
||||
dbp->dbp_addr, dbp->dbp_instr);
|
||||
}
|
||||
#endif
|
||||
nbp = dt_list_next(dbp);
|
||||
dt_list_delete(&dpr->dpr_bps, dbp);
|
||||
dt_free(dpr->dpr_hdl, dbp);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DOODAD
|
||||
static void
|
||||
dt_proc_bpmatch(dtrace_hdl_t *dtp, dt_proc_t *dpr)
|
||||
{
|
||||
@ -161,6 +173,7 @@ dt_proc_bpmatch(dtrace_hdl_t *dtp, dt_proc_t *dpr)
|
||||
dbp->dbp_func(dtp, dpr, dbp->dbp_data);
|
||||
(void) Pxecbkpt(dpr->dpr_proc, dbp->dbp_instr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
dt_proc_bpenable(dt_proc_t *dpr)
|
||||
@ -171,9 +184,12 @@ dt_proc_bpenable(dt_proc_t *dpr)
|
||||
|
||||
for (dbp = dt_list_next(&dpr->dpr_bps);
|
||||
dbp != NULL; dbp = dt_list_next(dbp)) {
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
#ifdef DOODAD
|
||||
if (!dbp->dbp_active && Psetbkpt(dpr->dpr_proc,
|
||||
dbp->dbp_addr, &dbp->dbp_instr) == 0)
|
||||
dbp->dbp_active = B_TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
dt_dprintf("breakpoints enabled\n");
|
||||
@ -188,9 +204,12 @@ dt_proc_bpdisable(dt_proc_t *dpr)
|
||||
|
||||
for (dbp = dt_list_next(&dpr->dpr_bps);
|
||||
dbp != NULL; dbp = dt_list_next(dbp)) {
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
#ifdef DOODAD
|
||||
if (dbp->dbp_active && Pdelbkpt(dpr->dpr_proc,
|
||||
dbp->dbp_addr, dbp->dbp_instr) == 0)
|
||||
dbp->dbp_active = B_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
dt_dprintf("breakpoints disabled\n");
|
||||
@ -263,6 +282,7 @@ dt_proc_bpmain(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *fname)
|
||||
dt_proc_stop(dpr, DT_PROC_STOP_MAIN);
|
||||
}
|
||||
|
||||
#if defined(sun)
|
||||
static void
|
||||
dt_proc_rdevent(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *evname)
|
||||
{
|
||||
@ -439,6 +459,7 @@ dt_proc_waitrun(dt_proc_t *dpr)
|
||||
|
||||
(void) pthread_mutex_lock(&dpr->dpr_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct dt_proc_control_data {
|
||||
dtrace_hdl_t *dpcd_hdl; /* DTrace handle */
|
||||
@ -465,11 +486,13 @@ dt_proc_control(void *arg)
|
||||
dt_proc_t *dpr = datap->dpcd_proc;
|
||||
dt_proc_hash_t *dph = dpr->dpr_hdl->dt_procs;
|
||||
struct ps_prochandle *P = dpr->dpr_proc;
|
||||
|
||||
int pfd = Pctlfd(P);
|
||||
int pid = dpr->dpr_pid;
|
||||
|
||||
#if defined(sun)
|
||||
int pfd = Pctlfd(P);
|
||||
|
||||
const long wstop = PCWSTOP;
|
||||
#endif
|
||||
int notify = B_FALSE;
|
||||
|
||||
/*
|
||||
@ -487,6 +510,7 @@ dt_proc_control(void *arg)
|
||||
*/
|
||||
(void) pthread_mutex_lock(&dpr->dpr_lock);
|
||||
|
||||
#if defined(sun)
|
||||
(void) Punsetflags(P, PR_ASYNC); /* require synchronous mode */
|
||||
(void) Psetflags(P, PR_BPTADJ); /* always adjust eip on x86 */
|
||||
(void) Punsetflags(P, PR_FORK); /* do not inherit on fork */
|
||||
@ -532,6 +556,20 @@ dt_proc_control(void *arg)
|
||||
dt_dprintf("pid %d: failed to set running: %s\n",
|
||||
(int)dpr->dpr_pid, strerror(errno));
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* If PR_KLC is set, we created the process; otherwise we grabbed it.
|
||||
* Check for an appropriate stop request and wait for dt_proc_continue.
|
||||
*/
|
||||
if (proc_getflags(P) & PR_KLC)
|
||||
dt_proc_stop(dpr, DT_PROC_STOP_CREATE);
|
||||
else
|
||||
dt_proc_stop(dpr, DT_PROC_STOP_GRAB);
|
||||
|
||||
if (proc_continue(P) != 0)
|
||||
dt_dprintf("pid %d: failed to set running: %s\n",
|
||||
(int)dpr->dpr_pid, strerror(errno));
|
||||
#endif
|
||||
|
||||
(void) pthread_mutex_unlock(&dpr->dpr_lock);
|
||||
|
||||
@ -545,20 +583,33 @@ dt_proc_control(void *arg)
|
||||
* Pwait() (which will return immediately) and do our processing.
|
||||
*/
|
||||
while (!dpr->dpr_quit) {
|
||||
#if defined(sun)
|
||||
const lwpstatus_t *psp;
|
||||
|
||||
if (write(pfd, &wstop, sizeof (wstop)) == -1 && errno == EINTR)
|
||||
continue; /* check dpr_quit and continue waiting */
|
||||
#else
|
||||
/* Wait for the process to report status. */
|
||||
proc_wait(P);
|
||||
#endif
|
||||
|
||||
(void) pthread_mutex_lock(&dpr->dpr_lock);
|
||||
|
||||
#if defined(sun)
|
||||
pwait_locked:
|
||||
if (Pstopstatus(P, PCNULL, 0) == -1 && errno == EINTR) {
|
||||
(void) pthread_mutex_unlock(&dpr->dpr_lock);
|
||||
continue; /* check dpr_quit and continue waiting */
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(sun)
|
||||
switch (Pstate(P)) {
|
||||
#else
|
||||
switch (proc_state(P)) {
|
||||
#endif
|
||||
case PS_STOP:
|
||||
#ifdef DOODAD
|
||||
psp = &Pstatus(P)->pr_lwp;
|
||||
|
||||
dt_dprintf("pid %d: proc stopped showing %d/%d\n",
|
||||
@ -601,11 +652,14 @@ dt_proc_control(void *arg)
|
||||
else if (psp->pr_why == PR_SYSEXIT &&
|
||||
IS_SYS_EXEC(psp->pr_what))
|
||||
dt_proc_attach(dpr, B_TRUE);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PS_LOST:
|
||||
#if defined(sun)
|
||||
if (Preopen(P) == 0)
|
||||
goto pwait_locked;
|
||||
#endif
|
||||
|
||||
dt_dprintf("pid %d: proc lost: %s\n",
|
||||
pid, strerror(errno));
|
||||
@ -621,10 +675,12 @@ dt_proc_control(void *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(sun)
|
||||
if (Pstate(P) != PS_UNDEAD && Psetrun(P, 0, 0) == -1) {
|
||||
dt_dprintf("pid %d: failed to set running: %s\n",
|
||||
(int)dpr->dpr_pid, strerror(errno));
|
||||
}
|
||||
#endif
|
||||
|
||||
(void) pthread_mutex_unlock(&dpr->dpr_lock);
|
||||
}
|
||||
@ -664,7 +720,11 @@ dt_proc_error(dtrace_hdl_t *dtp, dt_proc_t *dpr, const char *format, ...)
|
||||
va_end(ap);
|
||||
|
||||
if (dpr->dpr_proc != NULL)
|
||||
#if defined(sun)
|
||||
Prelease(dpr->dpr_proc, 0);
|
||||
#else
|
||||
proc_detach(dpr->dpr_proc);
|
||||
#endif
|
||||
|
||||
dt_free(dtp, dpr);
|
||||
(void) dt_set_errno(dtp, EDT_COMPILER);
|
||||
@ -675,7 +735,11 @@ dt_proc_t *
|
||||
dt_proc_lookup(dtrace_hdl_t *dtp, struct ps_prochandle *P, int remove)
|
||||
{
|
||||
dt_proc_hash_t *dph = dtp->dt_procs;
|
||||
#if defined(sun)
|
||||
pid_t pid = Pstatus(P)->pr_pid;
|
||||
#else
|
||||
pid_t pid = proc_getpid(P);
|
||||
#endif
|
||||
dt_proc_t *dpr, **dpp = &dph->dph_hash[pid & (dph->dph_hashlen - 1)];
|
||||
|
||||
for (dpr = *dpp; dpr != NULL; dpr = dpr->dpr_hash) {
|
||||
@ -709,9 +773,17 @@ dt_proc_destroy(dtrace_hdl_t *dtp, struct ps_prochandle *P)
|
||||
* an external debugger and we were waiting in dt_proc_waitrun().
|
||||
* Leave the process in this condition using PRELEASE_HANG.
|
||||
*/
|
||||
#if defined(sun)
|
||||
if (!(Pstatus(dpr->dpr_proc)->pr_flags & (PR_KLC | PR_RLC))) {
|
||||
#else
|
||||
if (!(proc_getflags(dpr->dpr_proc) & (PR_KLC | PR_RLC))) {
|
||||
#endif
|
||||
dt_dprintf("abandoning pid %d\n", (int)dpr->dpr_pid);
|
||||
#if defined(sun)
|
||||
rflag = PRELEASE_HANG;
|
||||
#else
|
||||
rflag = 0 /* XXX */;
|
||||
#endif
|
||||
} else {
|
||||
dt_dprintf("releasing pid %d\n", (int)dpr->dpr_pid);
|
||||
rflag = 0; /* apply kill or run-on-last-close */
|
||||
@ -734,7 +806,11 @@ dt_proc_destroy(dtrace_hdl_t *dtp, struct ps_prochandle *P)
|
||||
*/
|
||||
(void) pthread_mutex_lock(&dpr->dpr_lock);
|
||||
dpr->dpr_quit = B_TRUE;
|
||||
#if defined(sun)
|
||||
(void) _lwp_kill(dpr->dpr_tid, SIGCANCEL);
|
||||
#else
|
||||
(void) pthread_kill(dpr->dpr_tid, SIGUSR1);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If the process is currently idling in dt_proc_stop(), re-
|
||||
@ -782,7 +858,11 @@ dt_proc_destroy(dtrace_hdl_t *dtp, struct ps_prochandle *P)
|
||||
}
|
||||
|
||||
dt_list_delete(&dph->dph_lrulist, dpr);
|
||||
#if defined(sun)
|
||||
Prelease(dpr->dpr_proc, rflag);
|
||||
#else
|
||||
proc_detach(dpr->dpr_proc);
|
||||
#endif
|
||||
dt_free(dtp, dpr);
|
||||
}
|
||||
|
||||
@ -802,7 +882,11 @@ dt_proc_create_thread(dtrace_hdl_t *dtp, dt_proc_t *dpr, uint_t stop)
|
||||
|
||||
(void) sigfillset(&nset);
|
||||
(void) sigdelset(&nset, SIGABRT); /* unblocked for assert() */
|
||||
#if defined(sun)
|
||||
(void) sigdelset(&nset, SIGCANCEL); /* see dt_proc_destroy() */
|
||||
#else
|
||||
(void) sigdelset(&nset, SIGUSR1); /* see dt_proc_destroy() */
|
||||
#endif
|
||||
|
||||
data.dpcd_hdl = dtp;
|
||||
data.dpcd_proc = dpr;
|
||||
@ -830,14 +914,21 @@ dt_proc_create_thread(dtrace_hdl_t *dtp, dt_proc_t *dpr, uint_t stop)
|
||||
* small amount of useful information to help figure it out.
|
||||
*/
|
||||
if (dpr->dpr_done) {
|
||||
#if defined(sun)
|
||||
const psinfo_t *prp = Ppsinfo(dpr->dpr_proc);
|
||||
int stat = prp ? prp->pr_wstat : 0;
|
||||
#endif
|
||||
int pid = dpr->dpr_pid;
|
||||
|
||||
#if defined(sun)
|
||||
if (Pstate(dpr->dpr_proc) == PS_LOST) {
|
||||
#else
|
||||
if (proc_state(dpr->dpr_proc) == PS_LOST) {
|
||||
#endif
|
||||
(void) dt_proc_error(dpr->dpr_hdl, dpr,
|
||||
"failed to control pid %d: process exec'd "
|
||||
"set-id or unobservable program\n", pid);
|
||||
#if defined(sun)
|
||||
} else if (WIFSIGNALED(stat)) {
|
||||
(void) dt_proc_error(dpr->dpr_hdl, dpr,
|
||||
"failed to control pid %d: process died "
|
||||
@ -846,6 +937,7 @@ dt_proc_create_thread(dtrace_hdl_t *dtp, dt_proc_t *dpr, uint_t stop)
|
||||
(void) dt_proc_error(dpr->dpr_hdl, dpr,
|
||||
"failed to control pid %d: process exited "
|
||||
"with status %d\n", pid, WEXITSTATUS(stat));
|
||||
#endif
|
||||
}
|
||||
|
||||
err = ESRCH; /* cause grab() or create() to fail */
|
||||
@ -875,6 +967,7 @@ dt_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv)
|
||||
(void) pthread_mutex_init(&dpr->dpr_lock, NULL);
|
||||
(void) pthread_cond_init(&dpr->dpr_cv, NULL);
|
||||
|
||||
#if defined(sun)
|
||||
if ((dpr->dpr_proc = Pcreate(file, argv, &err, NULL, 0)) == NULL) {
|
||||
return (dt_proc_error(dtp, dpr,
|
||||
"failed to execute %s: %s\n", file, Pcreate_error(err)));
|
||||
@ -885,8 +978,21 @@ dt_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv)
|
||||
|
||||
(void) Punsetflags(dpr->dpr_proc, PR_RLC);
|
||||
(void) Psetflags(dpr->dpr_proc, PR_KLC);
|
||||
#else
|
||||
(void) proc_clearflags(dpr->dpr_proc, PR_RLC);
|
||||
(void) proc_setflags(dpr->dpr_proc, PR_KLC);
|
||||
if ((err = proc_create(file, argv, &dpr->dpr_proc)) != 0)
|
||||
return (dt_proc_error(dtp, dpr,
|
||||
"failed to execute %s: %s\n", file, strerror(err)));
|
||||
dpr->dpr_hdl = dtp;
|
||||
dpr->dpr_pid = proc_getpid(dpr->dpr_proc);
|
||||
#endif
|
||||
|
||||
#if defined(sun)
|
||||
if (dt_proc_create_thread(dtp, dpr, dtp->dt_prcmode) != 0)
|
||||
#else
|
||||
if (dt_proc_create_thread(dtp, dpr, DT_PROC_STOP_IDLE) != 0)
|
||||
#endif
|
||||
return (NULL); /* dt_proc_error() has been called for us */
|
||||
|
||||
dpr->dpr_hash = dph->dph_hash[dpr->dpr_pid & (dph->dph_hashlen - 1)];
|
||||
@ -942,16 +1048,27 @@ dt_proc_grab(dtrace_hdl_t *dtp, pid_t pid, int flags, int nomonitor)
|
||||
(void) pthread_mutex_init(&dpr->dpr_lock, NULL);
|
||||
(void) pthread_cond_init(&dpr->dpr_cv, NULL);
|
||||
|
||||
#if defined(sun)
|
||||
if ((dpr->dpr_proc = Pgrab(pid, flags, &err)) == NULL) {
|
||||
return (dt_proc_error(dtp, dpr,
|
||||
"failed to grab pid %d: %s\n", (int)pid, Pgrab_error(err)));
|
||||
}
|
||||
#else
|
||||
if ((err = proc_attach(pid, flags, &dpr->dpr_proc)) != 0)
|
||||
return (dt_proc_error(dtp, dpr,
|
||||
"failed to grab pid %d: %s\n", (int) pid, strerror(err)));
|
||||
#endif
|
||||
|
||||
dpr->dpr_hdl = dtp;
|
||||
dpr->dpr_pid = pid;
|
||||
|
||||
#if defined(sun)
|
||||
(void) Punsetflags(dpr->dpr_proc, PR_KLC);
|
||||
(void) Psetflags(dpr->dpr_proc, PR_RLC);
|
||||
#else
|
||||
(void) proc_clearflags(dpr->dpr_proc, PR_KLC);
|
||||
(void) proc_setflags(dpr->dpr_proc, PR_RLC);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If we are attempting to grab the process without a monitor
|
||||
@ -1072,7 +1189,11 @@ dtrace_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv)
|
||||
struct ps_prochandle *P = dt_proc_create(dtp, file, argv);
|
||||
|
||||
if (P != NULL && idp != NULL && idp->di_id == 0)
|
||||
#if defined(sun)
|
||||
idp->di_id = Pstatus(P)->pr_pid; /* $target = created pid */
|
||||
#else
|
||||
idp->di_id = proc_getpid(P); /* $target = created pid */
|
||||
#endif
|
||||
|
||||
return (P);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user