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

📄 plwpregs.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
字号:
/* * Copyright 2005 Sun Microsystems, Inc.  All rights reserved. * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only. * See the file usr/src/LICENSING.NOTICE in this distribution or * http://www.opensolaris.org/license/ for details. */#pragma ident	"@(#)Plwpregs.c	1.5	03/07/09 SMI"#include <sys/types.h>#include <sys/uio.h>#include <string.h>#include <errno.h>#include "Pcontrol.h"#include "P32ton.h"/* * This file implements the routines to read and write per-lwp register * information from either a live process or core file opened with libproc. * We build up a few common routines for reading and writing register * information, and then the public functions are all trivial calls to these. *//* * Utility function to return a pointer to the structure of cached information * about an lwp in the core file, given its lwpid. */static lwp_info_t *getlwpcore(struct ps_prochandle *P, lwpid_t lwpid){	lwp_info_t *lwp = list_next(&P->core->core_lwp_head);	uint_t i;	for (i = 0; i < P->core->core_nlwp; i++, lwp = list_next(lwp)) {		if (lwp->lwp_id == lwpid)			return (lwp);	}	errno = EINVAL;	return (NULL);}/* * Utility function to open and read the contents of a per-lwp /proc file. * This function is used to slurp in lwpstatus, xregs, and asrs. */static intgetlwpfile(struct ps_prochandle *P, lwpid_t lwpid,    const char *fbase, void *rp, size_t n){	char fname[64];	int fd;	if (P->state != PS_STOP) {		errno = EBUSY;		return (-1);	}	(void) snprintf(fname, sizeof (fname), "/proc/%d/lwp/%d/%s",		(int)P->status.pr_pid, (int)lwpid, fbase);	if ((fd = open(fname, O_RDONLY)) >= 0) {		if (read(fd, rp, n) > 0) {			(void) close(fd);			return (0);		}		(void) close(fd);	}	return (-1);}/* * Get the lwpstatus_t for an lwp from either the live process or our * cached information from the core file.  This is used to get the * general-purpose registers or floating point registers. */intgetlwpstatus(struct ps_prochandle *P, lwpid_t lwpid, lwpstatus_t *lps){	lwp_info_t *lwp;	/*	 * For both live processes and cores, our job is easy if the lwpid	 * matches that of the representative lwp:	 */	if (P->status.pr_lwp.pr_lwpid == lwpid) {		(void) memcpy(lps, &P->status.pr_lwp, sizeof (lwpstatus_t));		return (0);	}	/*	 * If this is a live process, then just read the information out	 * of the per-lwp status file:	 */	if (P->state != PS_DEAD) {		return (getlwpfile(P, lwpid, "lwpstatus",		    lps, sizeof (lwpstatus_t)));	}	/*	 * If this is a core file, we need to iterate through our list of	 * cached lwp information and then copy out the status.	 */	if (P->core != NULL && (lwp = getlwpcore(P, lwpid)) != NULL) {		(void) memcpy(lps, &lwp->lwp_status, sizeof (lwpstatus_t));		return (0);	}	return (-1);}/* * Utility function to modify lwp registers.  This is done using either the * process control file or per-lwp control file as necessary. */static intsetlwpregs(struct ps_prochandle *P, lwpid_t lwpid, long cmd,    const void *rp, size_t n){	iovec_t iov[2];	char fname[64];	int fd;	if (P->state != PS_STOP) {		errno = EBUSY;		return (-1);	}	iov[0].iov_base = (caddr_t)&cmd;	iov[0].iov_len = sizeof (long);	iov[1].iov_base = (caddr_t)rp;	iov[1].iov_len = n;	/*	 * Writing the process control file writes the representative lwp.	 * Psync before we write to make sure we are consistent with the	 * primary interfaces.  Similarly, make sure to update P->status	 * afterward if we are modifying one of its register sets.	 */	if (P->status.pr_lwp.pr_lwpid == lwpid) {		Psync(P);		if (writev(P->ctlfd, iov, 2) == -1)			return (-1);		if (cmd == PCSREG)			(void) memcpy(P->status.pr_lwp.pr_reg, rp, n);		else if (cmd == PCSFPREG)			(void) memcpy(&P->status.pr_lwp.pr_fpreg, rp, n);		return (0);	}	/*	 * If the lwp we want is not the representative lwp, we need to	 * open the ctl file for that specific lwp.	 */	(void) snprintf(fname, sizeof (fname), "/proc/%d/lwp/%d/lwpctl",	    (int)P->status.pr_pid, (int)lwpid);	if ((fd = open(fname, O_WRONLY)) >= 0) {		if (writev(fd, iov, 2) > 0) {			(void) close(fd);			return (0);		}		(void) close(fd);	}	return (-1);}intPlwp_getregs(struct ps_prochandle *P, lwpid_t lwpid, prgregset_t gregs){	lwpstatus_t lps;	if (getlwpstatus(P, lwpid, &lps) == -1)		return (-1);	(void) memcpy(gregs, lps.pr_reg, sizeof (prgregset_t));	return (0);}intPlwp_setregs(struct ps_prochandle *P, lwpid_t lwpid, const prgregset_t gregs){	return (setlwpregs(P, lwpid, PCSREG, gregs, sizeof (prgregset_t)));}intPlwp_getfpregs(struct ps_prochandle *P, lwpid_t lwpid, prfpregset_t *fpregs){	lwpstatus_t lps;	if (getlwpstatus(P, lwpid, &lps) == -1)		return (-1);	(void) memcpy(fpregs, &lps.pr_fpreg, sizeof (prfpregset_t));	return (0);}int Plwp_setfpregs(struct ps_prochandle *P, lwpid_t lwpid,    const prfpregset_t *fpregs){	return (setlwpregs(P, lwpid, PCSFPREG, fpregs, sizeof (prfpregset_t)));}#if defined(sparc) || defined(__sparc)intPlwp_getxregs(struct ps_prochandle *P, lwpid_t lwpid, prxregset_t *xregs){	lwp_info_t *lwp;	if (P->state == PS_IDLE) {		errno = ENODATA;		return (-1);	}	if (P->state != PS_DEAD) {		return (getlwpfile(P, lwpid, "xregs",		    xregs, sizeof (prxregset_t)));	}	if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_xregs != NULL) {		(void) memcpy(xregs, lwp->lwp_xregs, sizeof (prxregset_t));		return (0);	}	if (lwp != NULL)		errno = ENODATA;	return (-1);}intPlwp_setxregs(struct ps_prochandle *P, lwpid_t lwpid, const prxregset_t *xregs){	return (setlwpregs(P, lwpid, PCSXREG, xregs, sizeof (prxregset_t)));}intPlwp_getgwindows(struct ps_prochandle *P, lwpid_t lwpid, gwindows_t *gwins){	lwp_info_t *lwp;	if (P->state == PS_IDLE) {		errno = ENODATA;		return (-1);	}	if (P->state != PS_DEAD)		return (getlwpfile(P, lwpid, "gwindows",		    gwins, sizeof (gwindows_t)));	if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_gwins != NULL) {		*gwins = *lwp->lwp_gwins;		return (0);	}	if (lwp != NULL)		errno = ENODATA;	return (-1);}#if defined(__sparcv9)intPlwp_getasrs(struct ps_prochandle *P, lwpid_t lwpid, asrset_t asrs){	lwp_info_t *lwp;	if (P->state == PS_IDLE) {		errno = ENODATA;		return (-1);	}	if (P->state != PS_DEAD)		return (getlwpfile(P, lwpid, "asrs", asrs, sizeof (asrset_t)));	if ((lwp = getlwpcore(P, lwpid)) != NULL && lwp->lwp_asrs != NULL) {		(void) memcpy(asrs, lwp->lwp_asrs, sizeof (asrset_t));		return (0);	}	if (lwp != NULL)		errno = ENODATA;	return (-1);}intPlwp_setasrs(struct ps_prochandle *P, lwpid_t lwpid, const asrset_t asrs){	return (setlwpregs(P, lwpid, PCSASRS, asrs, sizeof (asrset_t)));}#endif	/* __sparcv9 */#endif	/* __sparc */intPlwp_getpsinfo(struct ps_prochandle *P, lwpid_t lwpid, lwpsinfo_t *lps){	lwp_info_t *lwp;	if (P->state == PS_IDLE) {		errno = ENODATA;		return (-1);	}	if (P->state != PS_DEAD) {		return (getlwpfile(P, lwpid, "lwpsinfo",		    lps, sizeof (lwpsinfo_t)));	}	if ((lwp = getlwpcore(P, lwpid)) != NULL) {		(void) memcpy(lps, &lwp->lwp_psinfo, sizeof (lwpsinfo_t));		return (0);	}	return (-1);}intPlwp_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp){	uintptr_t addr;	if (P->state == PS_IDLE) {		errno = ENODATA;		return (-1);	}	if (P->state != PS_DEAD) {		lwpstatus_t ls;		if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)			return (-1);		addr = ls.pr_ustack;	} else {		lwp_info_t *lwp;		if ((lwp = getlwpcore(P, lwpid)) == NULL)			return (-1);		addr = lwp->lwp_status.pr_ustack;	}	if (P->status.pr_dmodel == PR_MODEL_NATIVE) {		if (Pread(P, stkp, sizeof (*stkp), addr) != sizeof (*stkp))			return (-1);#ifdef _LP64	} else {		stack32_t stk32;		if (Pread(P, &stk32, sizeof (stk32), addr) != sizeof (stk32))			return (-1);		stack_32_to_n(&stk32, stkp);#endif	}	return (0);}intPlwp_main_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp){	uintptr_t addr;	lwpstatus_t ls;	if (P->state == PS_IDLE) {		errno = ENODATA;		return (-1);	}	if (P->state != PS_DEAD) {		if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)			return (-1);	} else {		lwp_info_t *lwp;		if ((lwp = getlwpcore(P, lwpid)) == NULL)			return (-1);		ls = lwp->lwp_status;	}	addr = ls.pr_ustack;	/*	 * Read out the current stack; if the SS_ONSTACK flag is set then	 * this LWP is operating on the alternate signal stack. We can	 * recover the original stack from pr_oldcontext.	 */	if (P->status.pr_dmodel == PR_MODEL_NATIVE) {		if (Pread(P, stkp, sizeof (*stkp), addr) != sizeof (*stkp))			return (-1);		if (stkp->ss_flags & SS_ONSTACK)			goto on_altstack;#ifdef _LP64	} else {		stack32_t stk32;		if (Pread(P, &stk32, sizeof (stk32), addr) != sizeof (stk32))			return (-1);		if (stk32.ss_flags & SS_ONSTACK)			goto on_altstack;		stack_32_to_n(&stk32, stkp);#endif	}	return (0);on_altstack:	if (P->status.pr_dmodel == PR_MODEL_NATIVE) {		ucontext_t *ctxp = (void *)ls.pr_oldcontext;		if (Pread(P, stkp, sizeof (*stkp),		    (uintptr_t)&ctxp->uc_stack) != sizeof (*stkp))			return (-1);#ifdef _LP64	} else {		ucontext32_t *ctxp = (void *)ls.pr_oldcontext;		stack32_t stk32;		if (Pread(P, &stk32, sizeof (stk32),		    (uintptr_t)&ctxp->uc_stack) != sizeof (stk32))			return (-1);		stack_32_to_n(&stk32, stkp);#endif	}	return (0);}intPlwp_alt_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp){	if (P->state == PS_IDLE) {		errno = ENODATA;		return (-1);	}	if (P->state != PS_DEAD) {		lwpstatus_t ls;		if (getlwpfile(P, lwpid, "lwpstatus", &ls, sizeof (ls)) != 0)			return (-1);		if (ls.pr_altstack.ss_flags & SS_DISABLE) {			errno = ENODATA;			return (-1);		}		*stkp = ls.pr_altstack;	} else {		lwp_info_t *lwp;		if ((lwp = getlwpcore(P, lwpid)) == NULL)			return (-1);		if (lwp->lwp_status.pr_altstack.ss_flags & SS_DISABLE) {			errno = ENODATA;			return (-1);		}		*stkp = lwp->lwp_status.pr_altstack;	}	return (0);}

⌨️ 快捷键说明

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