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

📄 pisadep.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	"@(#)Pisadep.c	1.8	04/12/06 SMI"#include <sys/stack.h>#include <sys/regset.h>#include <sys/frame.h>#include <sys/sysmacros.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <errno.h>#include <string.h>#include "Pcontrol.h"#include "Pstack.h"#define	M_PLT_NRSV		1	/* reserved PLT entries */#define	M_PLT_ENTSIZE		16	/* size of each PLT entry */static uchar_t old_lcall[] = { 0x91, 0, 0, 0, 0, 0x7, 0 };static uchar_t lcall_instr[] = { 0x9a, 0, 0, 0, 0, 0x27, 0 };#ifdef _LP64static uchar_t sysenter_instr[] = { 0x0f, 0x05 };#endifconst char *Ppltdest(struct ps_prochandle *P, uintptr_t pltaddr){	map_info_t *mp = Paddr2mptr(P, pltaddr);	file_info_t *fp;	size_t i;	uintptr_t r_addr;	if (mp == NULL || (fp = mp->map_file) == NULL ||	    fp->file_plt_base == 0 ||	    pltaddr - fp->file_plt_base >= fp->file_plt_size) {		errno = EINVAL;		return (NULL);	}	i = (pltaddr - fp->file_plt_base) / M_PLT_ENTSIZE - M_PLT_NRSV;	if (P->status.pr_dmodel == PR_MODEL_LP64) {		Elf64_Rela r;		r_addr = fp->file_jmp_rel + i * sizeof (r);		if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&		    (i = ELF64_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {			Elf_Data *data = fp->file_dynsym.sym_data;			Elf64_Sym *symp = &(((Elf64_Sym *)data->d_buf)[i]);			return (fp->file_dynsym.sym_strs + symp->st_name);		}	} else {		Elf32_Rel r;		r_addr = fp->file_jmp_rel + i * sizeof (r);		if (Pread(P, &r, sizeof (r), r_addr) == sizeof (r) &&		    (i = ELF32_R_SYM(r.r_info)) < fp->file_dynsym.sym_symn) {			Elf_Data *data = fp->file_dynsym.sym_data;			Elf32_Sym *symp = &(((Elf32_Sym *)data->d_buf)[i]);			return (fp->file_dynsym.sym_strs + symp->st_name);		}	}	return (NULL);}intPissyscall(struct ps_prochandle *P, uintptr_t addr){	uchar_t instr[16];#if defined(_LP64)	if (P->status.pr_dmodel == PR_MODEL_LP64) {		if (Pread(P, instr, sizeof (sysenter_instr), addr) !=		    sizeof (sysenter_instr) ||		    memcmp(instr, sysenter_instr, sizeof (sysenter_instr)) != 0)			return (0);		else			return (1);	}#endif	if (Pread(P, instr, sizeof (lcall_instr), addr) !=	    sizeof (lcall_instr))		return (0);	if (memcmp(instr, old_lcall, sizeof (old_lcall)) == 0)		return (2);	if (memcmp(instr, lcall_instr, sizeof (lcall_instr)) == 0)		return (1);	return (0);}intPissyscall_prev(struct ps_prochandle *P, uintptr_t addr, uintptr_t *dst){	int ret;#if defined(_LP64)	if (P->status.pr_dmodel == PR_MODEL_LP64) {		if (Pissyscall(P, addr - sizeof (sysenter_instr))) {			if (dst)				*dst = addr - sizeof (sysenter_instr);			return (1);		}		return (0);	}#endif	if ((ret = Pissyscall(P, addr - sizeof (lcall_instr))) != 0) {		if (dst)			*dst = addr - sizeof (lcall_instr);		return (ret);	}	return (0);}intPissyscall_text(struct ps_prochandle *P, const void *buf, size_t buflen){#if defined(_LP64)	if (P->status.pr_dmodel == PR_MODEL_LP64) {		if (buflen >= sizeof (sysenter_instr) &&		    memcmp(buf, sysenter_instr, sizeof (sysenter_instr)) == 0)			return (1);		else			return (0);	}#endif	if (buflen < sizeof (lcall_instr))		return (0);	if (memcmp(buf, old_lcall, sizeof (old_lcall)) == 0)		return (2);	if (memcmp(buf, lcall_instr, sizeof (lcall_instr)) == 0)		return (1);	return (0);}#ifdef _LP64#define	TR_ARG_MAX 6	/* Max args to print, same as SPARC *//* * Given a return address, determine the likely number of arguments * that were pushed on the stack prior to its execution.  We do this by * expecting that a typical call sequence consists of pushing arguments on * the stack, executing a call instruction, and then performing an add * on %esp to restore it to the value prior to pushing the arguments for * the call.  We attempt to detect such an add, and divide the addend * by the size of a word to determine the number of pushed arguments. * * If we do not find such an add, this does not necessarily imply that the * function took no arguments. It is not possible to reliably detect such a * void function because hand-coded assembler does not always perform an add * to %esp immediately after the "call" instruction (eg. _sys_call()). * Because of this, we default to returning MIN(sz, TR_ARG_MAX) instead of 0 * in the absence of an add to %esp. */static ulong_targcount(struct ps_prochandle *P, uint32_t pc, ssize_t sz){	uchar_t instr[6];	ulong_t count, max;	max = MIN(sz / sizeof (uint32_t), TR_ARG_MAX);	/*	 * Read the instruction at the return location.	 */	if (Pread(P, instr, sizeof (instr), (uintptr_t)pc) != sizeof (instr))		return (max);	if (instr[1] != 0xc4)		return (max);	switch (instr[0]) {	case 0x81:	/* count is a longword */		count = instr[2]+(instr[3]<<8)+(instr[4]<<16)+(instr[5]<<24);		break;	case 0x83:	/* count is a byte */		count = instr[2];		break;	default:		return (max);	}	count /= sizeof (uint32_t);	return (MIN(count, max));}static voiducontext_32_to_prgregs(const ucontext32_t *uc, prgregset_t dst){	const greg32_t *src = &uc->uc_mcontext.gregs[0];	dst[REG_DS] = (uint16_t)src[DS];	dst[REG_ES] = (uint16_t)src[ES];	dst[REG_GS] = (uint16_t)src[GS];	dst[REG_FS] = (uint16_t)src[FS];	dst[REG_SS] = (uint16_t)src[SS];	dst[REG_RSP] = (uint32_t)src[UESP];	dst[REG_RFL] = src[EFL];	dst[REG_CS] = (uint16_t)src[CS];	dst[REG_RIP] = (uint32_t)src[EIP];	dst[REG_ERR] = (uint32_t)src[ERR];	dst[REG_TRAPNO] = (uint32_t)src[TRAPNO];	dst[REG_RAX] = (uint32_t)src[EAX];	dst[REG_RCX] = (uint32_t)src[ECX];	dst[REG_RDX] = (uint32_t)src[EDX];	dst[REG_RBX] = (uint32_t)src[EBX];	dst[REG_RBP] = (uint32_t)src[EBP];	dst[REG_RSI] = (uint32_t)src[ESI];	dst[REG_RDI] = (uint32_t)src[EDI];}static intPstack_iter32(struct ps_prochandle *P, const prgregset_t regs,    proc_stack_f *func, void *arg){	prgreg_t *prevfp = NULL;	uint_t pfpsize = 0;	int nfp = 0;	struct {		prgreg32_t fp;		prgreg32_t pc;		prgreg32_t args[32];	} frame;	uint_t argc;	ssize_t sz;	prgregset_t gregs;	uint32_t fp, pfp, pc;	long args[32];	int rv;	int i;	/*	 * Type definition for a structure corresponding to an IA32	 * signal frame.  Refer to the comments in Pstack.c for more info	 */	typedef struct {		prgreg32_t fp;		prgreg32_t pc;		int signo;		caddr32_t ucp;		caddr32_t sip;	} sf_t;	uclist_t ucl;	ucontext32_t uc;	uintptr_t uc_addr;	init_uclist(&ucl, P);	(void) memcpy(gregs, regs, sizeof (gregs));	fp = regs[R_FP];	pc = regs[R_PC];	while (fp != 0 || pc != 0) {		if (stack_loop(fp, &prevfp, &nfp, &pfpsize))			break;		if (fp != 0 &&		    (sz = Pread(P, &frame, sizeof (frame), (uintptr_t)fp)		    >= (ssize_t)(2* sizeof (uint32_t)))) {			/*			 * One more trick for signal frames: the kernel sets			 * the return pc of the signal frame to 0xffffffff on			 * Intel IA32, so argcount won't work.			 */			if (frame.pc != -1L) {				sz -= 2* sizeof (uint32_t);				argc = argcount(P, (uint32_t)frame.pc, sz);			} else				argc = 3; /* sighandler(signo, sip, ucp) */		} else {			(void) memset(&frame, 0, sizeof (frame));			argc = 0;		}		gregs[R_FP] = fp;		gregs[R_PC] = pc;		for (i = 0; i < argc; i++)			args[i] = (uint32_t)frame.args[i];		if ((rv = func(arg, gregs, argc, args)) != 0)			break;		/*		 * In order to allow iteration over java frames (which can have		 * their own frame pointers), we allow the iterator to change		 * the contents of gregs.  If we detect a change, then we assume		 * that the new values point to the next frame.		 */		if (gregs[R_FP] != fp || gregs[R_PC] != pc) {			fp = gregs[R_FP];			pc = gregs[R_PC];			continue;		}		pfp = fp;		fp = frame.fp;		pc = frame.pc;		if (find_uclink(&ucl, pfp + sizeof (sf_t)))			uc_addr = pfp + sizeof (sf_t);		else			uc_addr = NULL;		if (uc_addr != NULL &&		    Pread(P, &uc, sizeof (uc), uc_addr) == sizeof (uc)) {			ucontext_32_to_prgregs(&uc, gregs);			fp = gregs[R_FP];			pc = gregs[R_PC];		}	}	if (prevfp)		free(prevfp);	free_uclist(&ucl);	return (rv);}#endifstatic voiducontext_n_to_prgregs(const ucontext_t *src, prgregset_t dst){	(void) memcpy(dst, src->uc_mcontext.gregs, sizeof (gregset_t));}intPstack_iter(struct ps_prochandle *P, const prgregset_t regs,	proc_stack_f *func, void *arg){	struct {		uintptr_t fp;		uintptr_t pc;	} frame;	uint_t pfpsize = 0;	prgreg_t *prevfp = NULL;	prgreg_t fp, pfp;	prgreg_t pc;	prgregset_t gregs;	int nfp = 0;	uclist_t ucl;	int rv = 0;	int argc;	uintptr_t uc_addr;	ucontext_t uc;	/*	 * Type definition for a structure corresponding to an IA32	 * signal frame.  Refer to the comments in Pstack.c for more info	 */	typedef struct {		prgreg_t fp;		prgreg_t pc;		prgreg_t signo;		siginfo_t *sip;	} sigframe_t;	prgreg_t args[32];#ifdef _LP64	if (P->status.pr_dmodel != PR_MODEL_LP64)		return (Pstack_iter32(P, regs, func, arg));#endif	init_uclist(&ucl, P);	(void) memcpy(gregs, regs, sizeof (gregs));	fp = gregs[R_FP];	pc = gregs[R_PC];	while (fp != 0 || pc != 0) {		if (stack_loop(fp, &prevfp, &nfp, &pfpsize))			break;		if (fp != 0 &&		    Pread(P, &frame, sizeof (frame), (uintptr_t)fp) ==		    sizeof (frame)) {			if (frame.pc != -1) {				/*				 * Function arguments are not available on				 * amd64 without extensive DWARF processing.				 */				argc = 0;			} else {				argc = 3;				args[2] = fp + sizeof (sigframe_t);				if (Pread(P, &args, 2 * sizeof (prgreg_t),				    fp + 2 * sizeof (prgreg_t)) !=				    2 * sizeof (prgreg_t))					argc = 0;			}		} else {			(void) memset(&frame, 0, sizeof (frame));			argc = 0;		}		gregs[R_FP] = fp;		gregs[R_PC] = pc;		if ((rv = func(arg, gregs, argc, args)) != 0)			break;		pfp = fp;		fp = frame.fp;		pc = frame.pc;		if (pc == -1 && find_uclink(&ucl, pfp + sizeof (sigframe_t))) {			uc_addr = pfp + sizeof (sigframe_t);			if (Pread(P, &uc, sizeof (uc), uc_addr)			    == sizeof (uc)) {				ucontext_n_to_prgregs(&uc, gregs);				fp = gregs[R_FP];				pc = gregs[R_PC];			}		}	}	if (prevfp)		free(prevfp);	free_uclist(&ucl);	return (rv);}uintptr_tPsyscall_setup(struct ps_prochandle *P, int nargs, int sysindex, uintptr_t sp){	if (P->status.pr_dmodel == PR_MODEL_ILP32) {		sp -= sizeof (int) * (nargs+2);		P->status.pr_lwp.pr_reg[REG_RAX] = sysindex;		P->status.pr_lwp.pr_reg[REG_RSP] = sp;		P->status.pr_lwp.pr_reg[REG_RIP] = P->sysaddr;	} else {		int pusharg = (nargs > 6) ? nargs - 6: 0;		sp -= sizeof (int64_t) * (pusharg+2);		P->status.pr_lwp.pr_reg[REG_RAX] = sysindex;		P->status.pr_lwp.pr_reg[REG_RSP] = sp;		P->status.pr_lwp.pr_reg[REG_RIP] = P->sysaddr;	}	return (sp);}intPsyscall_copyinargs(struct ps_prochandle *P, int nargs, argdes_t *argp,    uintptr_t ap){	if (P->status.pr_dmodel == PR_MODEL_ILP32) {		int32_t arglist[MAXARGS+2];		int i;		argdes_t *adp;		for (i = 0, adp = argp; i < nargs; i++, adp++)			arglist[1 + i] = (int32_t)adp->arg_value;		arglist[0] = P->status.pr_lwp.pr_reg[REG_RIP];		if (Pwrite(P, &arglist[0], sizeof (int) * (nargs+1),		    (uintptr_t)ap) != sizeof (int) * (nargs+1))			return (-1);	} else {		int64_t arglist[MAXARGS+2];		int i;		argdes_t *adp;		int pusharg = (nargs > 6) ? nargs - 6: 0;		for (i = 0, adp = argp; i < nargs; i++, adp++) {			switch (i) {			case 0:				(void) Pputareg(P, REG_RDI, adp->arg_value);				break;			case 1:				(void) Pputareg(P, REG_RSI, adp->arg_value);				break;			case 2:				(void) Pputareg(P, REG_RDX, adp->arg_value);				break;			case 3:				(void) Pputareg(P, REG_RCX, adp->arg_value);				break;			case 4:				(void) Pputareg(P, REG_R8, adp->arg_value);				break;			case 5:				(void) Pputareg(P, REG_R9, adp->arg_value);				break;			default:				arglist[i - 5] = (uint64_t)adp->arg_value;				break;			}		}		arglist[0] = P->status.pr_lwp.pr_reg[REG_RIP];		if (Pwrite(P, &arglist[0],		    sizeof (int64_t) * (pusharg + 1), ap) !=		    sizeof (int64_t) * (pusharg + 1))			return (-1);	}	return (0);}intPsyscall_copyoutargs(struct ps_prochandle *P, int nargs, argdes_t *argp,    uintptr_t ap){	if (P->status.pr_dmodel == PR_MODEL_ILP32) {		uint32_t arglist[MAXARGS + 2];		int i;		argdes_t *adp;		if (Pread(P, &arglist[0], sizeof (int) * (nargs+1),		    (uintptr_t)ap) != sizeof (int) * (nargs+1))			return (-1);		for (i = 0, adp = argp; i < nargs; i++, adp++)			adp->arg_value = arglist[i];	} else {		int pusharg = (nargs > 6) ? nargs - 6: 0;		int64_t arglist[MAXARGS+2];		int i;		argdes_t *adp;		if (pusharg  > 0 &&		    Pread(P, &arglist[0], sizeof (int64_t) * (pusharg + 1),		    ap) != sizeof (int64_t) * (pusharg + 1))			return (-1);		for (i = 0, adp = argp; i < nargs; i++, adp++) {			switch (i) {			case 0:				adp->arg_value =				    P->status.pr_lwp.pr_reg[REG_RDI];				break;			case 1:				adp->arg_value =				    P->status.pr_lwp.pr_reg[REG_RSI];				break;			case 2:				adp->arg_value =				    P->status.pr_lwp.pr_reg[REG_RDX];				break;			case 3:				adp->arg_value =				    P->status.pr_lwp.pr_reg[REG_RCX];				break;			case 4:				adp->arg_value =				    P->status.pr_lwp.pr_reg[REG_R8];				break;			case 5:				adp->arg_value =				    P->status.pr_lwp.pr_reg[REG_R9];				break;			default:				adp->arg_value = arglist[i - 6];				break;			}		}		return (0);	}	return (0);}

⌨️ 快捷键说明

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