⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcontrol.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 5 页
字号:
					errstr = "Pstopstatus PCDSTOP"; break;				case PCWSTOP:					errstr = "Pstopstatus PCWSTOP"; break;				default:					errstr = "Pstopstatus PC???"; break;				}				dprintf("%s: %s\n", errstr, strerror(err));			}			deadcheck(P);			break;		}		if (err != EINTR && err != ERESTART) {			errno = err;			return (-1);		}	}	if (!(P->status.pr_flags & PR_STOPPED)) {		P->state = PS_RUN;		if (request == PCNULL || request == PCDSTOP || msec != 0)			return (0);		dprintf("Pstopstatus: process is not stopped\n");		errno = EPROTO;		return (-1);	}	P->state = PS_STOP;	if (_libproc_debug)	/* debugging */		prdump(P);	/*	 * If the process was already stopped coming into Pstopstatus(),	 * then don't use its PC to set P->sysaddr since it may have been	 * changed since the time the process originally stopped.	 */	if (old_state == PS_STOP)		return (0);	switch (P->status.pr_lwp.pr_why) {	case PR_SYSENTRY:	case PR_SYSEXIT:		if (Pissyscall_prev(P, P->status.pr_lwp.pr_reg[R_PC],		    &P->sysaddr) == 0)			P->sysaddr = P->status.pr_lwp.pr_reg[R_PC];		break;	case PR_REQUESTED:	case PR_SIGNALLED:	case PR_FAULTED:	case PR_JOBCONTROL:	case PR_SUSPENDED:		break;	default:		errno = EPROTO;		return (-1);	}	return (0);}/* * Wait for the process to stop for any reason. */intPwait(struct ps_prochandle *P, uint_t msec){	return (Pstopstatus(P, PCWSTOP, msec));}/* * Direct the process to stop; wait for it to stop. */intPstop(struct ps_prochandle *P, uint_t msec){	return (Pstopstatus(P, PCSTOP, msec));}/* * Direct the process to stop; don't wait. */intPdstop(struct ps_prochandle *P){	return (Pstopstatus(P, PCDSTOP, 0));}static voiddeadcheck(struct ps_prochandle *P){	int fd;	void *buf;	size_t size;	if (P->statfd < 0)		P->state = PS_UNDEAD;	else {		if (P->agentstatfd < 0) {			fd = P->statfd;			buf = &P->status;			size = sizeof (P->status);		} else {			fd = P->agentstatfd;			buf = &P->status.pr_lwp;			size = sizeof (P->status.pr_lwp);		}		while (pread(fd, buf, size, (off_t)0) != size) {			switch (errno) {			default:				P->state = PS_UNDEAD;				break;			case EINTR:			case ERESTART:				continue;			case EAGAIN:				P->state = PS_LOST;				break;			}			break;		}		P->status.pr_flags = P->status.pr_lwp.pr_flags;	}}/* * Get the value of one register from stopped process. */intPgetareg(struct ps_prochandle *P, int regno, prgreg_t *preg){	if (regno < 0 || regno >= NPRGREG) {		errno = EINVAL;		return (-1);	}	if (P->state == PS_IDLE) {		errno = ENODATA;		return (-1);	}	if (P->state != PS_STOP && P->state != PS_DEAD) {		errno = EBUSY;		return (-1);	}	*preg = P->status.pr_lwp.pr_reg[regno];	return (0);}/* * Put value of one register into stopped process. */intPputareg(struct ps_prochandle *P, int regno, prgreg_t reg){	if (regno < 0 || regno >= NPRGREG) {		errno = EINVAL;		return (-1);	}	if (P->state != PS_STOP) {		errno = EBUSY;		return (-1);	}	P->status.pr_lwp.pr_reg[regno] = reg;	P->flags |= SETREGS;	/* set registers before continuing */	return (0);}intPsetrun(struct ps_prochandle *P,	int sig,	/* signal to pass to process */	int flags)	/* PRSTEP|PRSABORT|PRSTOP|PRCSIG|PRCFAULT */{	int ctlfd = (P->agentctlfd >= 0) ? P->agentctlfd : P->ctlfd;	int sbits = (PR_DSTOP | PR_ISTOP | PR_ASLEEP);	long ctl[1 +					/* PCCFAULT	*/		1 + sizeof (siginfo_t)/sizeof (long) +	/* PCSSIG/PCCSIG */		2 ];					/* PCRUN	*/	long *ctlp = ctl;	size_t size;	if (P->state != PS_STOP && (P->status.pr_lwp.pr_flags & sbits) == 0) {		errno = EBUSY;		return (-1);	}	Psync(P);	/* flush tracing flags and registers */	if (flags & PRCFAULT) {		/* clear current fault */		*ctlp++ = PCCFAULT;		flags &= ~PRCFAULT;	}	if (flags & PRCSIG) {		/* clear current signal */		*ctlp++ = PCCSIG;		flags &= ~PRCSIG;	} else if (sig && sig != P->status.pr_lwp.pr_cursig) {		/* make current signal */		siginfo_t *infop;		*ctlp++ = PCSSIG;		infop = (siginfo_t *)ctlp;		(void) memset(infop, 0, sizeof (*infop));		infop->si_signo = sig;		ctlp += sizeof (siginfo_t) / sizeof (long);	}	*ctlp++ = PCRUN;	*ctlp++ = flags;	size = (char *)ctlp - (char *)ctl;	P->info_valid = 0;	/* will need to update map and file info */	/*	 * If we've cached ucontext-list information while we were stopped,	 * free it now.	 */	if (P->ucaddrs != NULL) {		free(P->ucaddrs);		P->ucaddrs = NULL;		P->ucnelems = 0;	}	if (write(ctlfd, ctl, size) != size) {		/* If it is dead or lost, return the real status, not PS_RUN */		if (errno == ENOENT || errno == EAGAIN) {			(void) Pstopstatus(P, PCNULL, 0);			return (0);		}		/* If it is not in a jobcontrol stop, issue an error message */		if (errno != EBUSY ||		    P->status.pr_lwp.pr_why != PR_JOBCONTROL) {			dprintf("Psetrun: %s\n", strerror(errno));			return (-1);		}		/* Otherwise pretend that the job-stopped process is running */	}	P->state = PS_RUN;	return (0);}ssize_tPread(struct ps_prochandle *P,	void *buf,		/* caller's buffer */	size_t nbyte,		/* number of bytes to read */	uintptr_t address)	/* address in process */{	return (P->ops->p_pread(P, buf, nbyte, address));}ssize_tPread_string(struct ps_prochandle *P,	char *buf, 		/* caller's buffer */	size_t size,		/* upper limit on bytes to read */	uintptr_t addr)		/* address in process */{	enum { STRSZ = 40 };	char string[STRSZ + 1];	ssize_t leng = 0;	int nbyte;	if (size < 2) {		errno = EINVAL;		return (-1);	}	size--;			/* ensure trailing null fits in buffer */	*buf = '\0';	string[STRSZ] = '\0';	for (nbyte = STRSZ; nbyte == STRSZ && leng < size; addr += STRSZ) {		if ((nbyte = P->ops->p_pread(P, string, STRSZ, addr)) <= 0) {			buf[leng] = '\0';			return (leng ? leng : -1);		}		if ((nbyte = strlen(string)) > 0) {			if (leng + nbyte > size)				nbyte = size - leng;			(void) strncpy(buf + leng, string, nbyte);			leng += nbyte;		}	}	buf[leng] = '\0';	return (leng);}ssize_tPwrite(struct ps_prochandle *P,	const void *buf,	/* caller's buffer */	size_t nbyte,		/* number of bytes to write */	uintptr_t address)	/* address in process */{	return (P->ops->p_pwrite(P, buf, nbyte, address));}intPclearsig(struct ps_prochandle *P){	int ctlfd = (P->agentctlfd >= 0)? P->agentctlfd : P->ctlfd;	long ctl = PCCSIG;	if (write(ctlfd, &ctl, sizeof (ctl)) != sizeof (ctl))		return (-1);	P->status.pr_lwp.pr_cursig = 0;	return (0);}intPclearfault(struct ps_prochandle *P){	int ctlfd = (P->agentctlfd >= 0)? P->agentctlfd : P->ctlfd;	long ctl = PCCFAULT;	if (write(ctlfd, &ctl, sizeof (ctl)) != sizeof (ctl))		return (-1);	return (0);}/* * Set a breakpoint trap, return original instruction. */intPsetbkpt(struct ps_prochandle *P, uintptr_t address, ulong_t *saved){	long ctl[1 + sizeof (priovec_t) / sizeof (long) +	/* PCREAD */		1 + sizeof (priovec_t) / sizeof (long)];	/* PCWRITE */	long *ctlp = ctl;	size_t size;	priovec_t *iovp;	instr_t bpt = BPT;	instr_t old;	if (P->state == PS_DEAD || P->state == PS_UNDEAD ||	    P->state == PS_IDLE) {		errno = ENOENT;		return (-1);	}	/* fetch the old instruction */	*ctlp++ = PCREAD;	iovp = (priovec_t *)ctlp;	iovp->pio_base = &old;	iovp->pio_len = sizeof (old);	iovp->pio_offset = address;	ctlp += sizeof (priovec_t) / sizeof (long);	/* write the BPT instruction */	*ctlp++ = PCWRITE;	iovp = (priovec_t *)ctlp;	iovp->pio_base = &bpt;	iovp->pio_len = sizeof (bpt);	iovp->pio_offset = address;	ctlp += sizeof (priovec_t) / sizeof (long);	size = (char *)ctlp - (char *)ctl;	if (write(P->ctlfd, ctl, size) != size)		return (-1);	/*	 * Fail if there was already a breakpoint there from another debugger	 * or DTrace's user-level tracing on x86.	 */	if (old == BPT)		return (EBUSY);	*saved = (ulong_t)old;	return (0);}/* * Restore original instruction where a breakpoint was set. */intPdelbkpt(struct ps_prochandle *P, uintptr_t address, ulong_t saved){	instr_t old = (instr_t)saved;	instr_t cur;	if (P->state == PS_DEAD || P->state == PS_UNDEAD ||	    P->state == PS_IDLE) {		errno = ENOENT;		return (-1);	}	/*	 * If the breakpoint instruction we had placed has been overwritten	 * with a new instruction, then don't try to replace it with the	 * old instruction. Doing do can cause problems with self-modifying	 * code -- PLTs for example. If the Pread() fails, we assume that we	 * should proceed though most likely the Pwrite() will also fail.	 */	if (Pread(P, &cur, sizeof (cur), address) == sizeof (cur) &&	    cur != BPT)		return (0);	if (Pwrite(P, &old, sizeof (old), address) != sizeof (old))		return (-1);	return (0);}/* * Common code for Pxecbkpt() and Lxecbkpt(). * Develop the array of requests that will do the job, then * write them to the specified control file descriptor. * Return the non-zero errno if the write fails. */static intexecute_bkpt(	int ctlfd,		/* process or LWP control file descriptor */	const fltset_t *faultset,	/* current set of traced faults */	const sigset_t *sigmask,	/* current signal mask */	uintptr_t address,		/* address of breakpint */	ulong_t saved)			/* the saved instruction */{	long ctl[		1 + sizeof (sigset_t) / sizeof (long) +		/* PCSHOLD */		1 + sizeof (fltset_t) / sizeof (long) +		/* PCSFAULT */		1 + sizeof (priovec_t) / sizeof (long) +	/* PCWRITE */		2 +						/* PCRUN */		1 +						/* PCWSTOP */		1 +						/* PCCFAULT */		1 + sizeof (priovec_t) / sizeof (long) +	/* PCWRITE */		1 + sizeof (fltset_t) / sizeof (long) +		/* PCSFAULT */		1 + sizeof (sigset_t) / sizeof (long)];		/* PCSHOLD */	long *ctlp = ctl;	sigset_t unblock;	size_t size;	ssize_t ssize;	priovec_t *iovp;	sigset_t *holdp;	fltset_t *faultp;	instr_t old = (instr_t)saved;	instr_t bpt = BPT;	int error = 0;	/* block our signals for the duration */	(void) sigprocmask(SIG_BLOCK, &blockable_sigs, &unblock);	/* hold posted signals */	*ctlp++ = PCSHOLD;	holdp = (sigset_t *)ctlp;	prfillset(holdp);	prdelset(holdp, SIGKILL);	prdelset(holdp, SIGSTOP);	ctlp += sizeof (sigset_t) / sizeof (long);	/* force tracing of FLTTRACE */	if (!(prismember(faultset, FLTTRACE))) {		*ctlp++ = PCSFAULT;		faultp = (fltset_t *)ctlp;		*faultp = *faultset;		praddset(faultp, FLTTRACE);		ctlp += sizeof (fltset_t) / sizeof (long);	}	/* restore the old instruction */	*ctlp++ = PCWRITE;	iovp = (priovec_t *)ctlp;	iovp->pio_base = &old;	iovp->pio_len = sizeof (old);	iovp->pio_offset = address;	ctlp += sizeof (priovec_t) / sizeof (long);	/* clear current signal and fault; set running w/ single-step */	*ctlp++ = PCRUN;	*ctlp++ = PRCSIG | PRCFAULT | PRSTEP;	/* wait for stop, cancel the fault */	*ctlp++ = PCWSTOP;	*ctlp++ = PCCFAULT;	/* restore the breakpoint trap */	*ctlp++ = PCWRITE;	iovp = (priovec_t *)ctlp;	iovp->pio_base = &bpt;	iovp->pio_len = sizeof (bpt);	iovp->pio_offset = address;	ctlp += sizeof (priovec_t) / sizeof (long);	/* restore fault tracing set */	if (!(prismember(faultset, FLTTRACE))) {		*ctlp++ = PCSFAULT;		*(fltset_t *)ctlp = *faultset;		ctlp += sizeof (fltset_t) / sizeof (long);	}	/* restore the hold mask */	*ctlp++ = PCSHOLD;	*(sigset_t *)ctlp = *sigmask;	ctlp += sizeof (sigset_t) / sizeof (long);	size = (char *)ctlp - (char *)ctl;	if ((ssize = write(ctlfd, ctl, size)) != size)		error = (ssize == -1)? errno : EINTR;	(void) sigprocmask(SIG_SETMASK, &unblock, NULL);	return (error);}/* * Step over a breakpoint, i.e., execute the instruction that * really belongs at the breakpoint location (the current %pc) * and leave the process stopped at the next instruction. */intPxecbkpt(struct ps_prochandle *P, ulong_t saved){	int ctlfd = (P->agentctlfd >= 0)? P->agentctlfd : P->ctlfd;	int rv, error;	if (P->state != PS_STOP) {		errno = EBUSY;		return (-1);	}	Psync(P);	error = execute_bkpt(ctlfd,		&P->status.pr_flttrace, &P->status.pr_lwp.pr_lwphold,		P->status.pr_lwp.pr_reg[R_PC], saved);	rv = Pstopstatus(P, PCNULL, 0);	if (error != 0) {		if (P->status.pr_lwp.pr_why == PR_JOBCONTROL &&		    error == EBUSY) {	/* jobcontrol stop -- back off */			P->state = PS_RUN;			return (0);		}		if (error == ENOENT)			return (0);		errno = error;		return (-1);	}	return (rv);}/* * Install the watchpoint described by wp. */intPsetwapt(struct ps_prochandle *P, const prwatch_t *wp){	long ctl[1 + sizeof (prwatch_t) / sizeof (long)];	prwatch_t *cwp = (prwatch_t *)&ctl[1];	if (P->state == PS_DEAD || P->state == PS_UNDEAD ||	    P->state == PS_IDLE) {		errno = ENOENT;		return (-1);	}	ctl[0] = PCWATCH;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -