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

📄 util.c

📁 linux进程跟踪的工具和源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifndef USE_PROCFSintsetbpt(tcp)struct tcb *tcp;{#ifdef LINUX#ifdef SPARC	/* We simply use the SunOS breakpoint code. */	struct regs regs;#define LOOPA	0x30800000	/* ba,a	0 */	if (tcp->flags & TCB_BPTSET) {		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);		return -1;	}	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {		perror("setbpt: ptrace(PTRACE_GETREGS, ...)");		return -1;	}	tcp->baddr = regs.r_o7 + 8;	errno = 0;	tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0);	if(errno) {		perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");		return -1;	}	/*	 * XXX - BRUTAL MODE ON	 * We cannot set a real BPT in the child, since it will not be	 * traced at the moment it will reach the trap and would probably	 * die with a core dump.	 * Thus, we are force our way in by taking out two instructions	 * and insert an eternal loop instead, in expectance of the SIGSTOP	 * generated by out PTRACE_ATTACH.	 * Of cause, if we evaporate ourselves in the middle of all this...	 */	errno = 0;	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA);	if(errno) {		perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");		return -1;	}	tcp->flags |= TCB_BPTSET;#else /* !SPARC */#ifdef IA64	/*	 * Our strategy here is to replace the bundle that contained	 * the clone() syscall with a bundle of the form:	 *	 *	{ 1: br 1b; br 1b; br 1b }	 *	 * This ensures that the newly forked child will loop	 * endlessly until we've got a chance to attach to it.	 */	{#		define LOOP0	0x0000100000000017#		define LOOP1	0x4000000000200000		unsigned long addr, ipsr;		pid_t pid;		pid = tcp->pid;		if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)			return -1;		if (upeek(pid, PT_CR_IIP, &addr) < 0)			return -1;		tcp->baddr = addr | ((ipsr >> 41) & 0x3);	/* store "ri" in low two bits */		errno = 0;		tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0, 0);		tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8, 0);		if (errno) {			perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");			return -1;		}		errno = 0;		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0);		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1);		if (errno) {			perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");			return -1;		}		tcp->flags |= TCB_BPTSET;	}#else /* !IA64 */#if defined (I386)#define LOOP	0x0000feeb#elif defined (M68K)#define LOOP	0x60fe0000#elif defined (ALPHA)#define LOOP	0xc3ffffff#elif defined (POWERPC)#define LOOP	0x0000feeb#elif defined(ARM)#define LOOP	0xEAFFFFFE#elif defined(MIPS)#define LOOP	0x1000ffff#elif defined(S390)#define LOOP	0xa7f40000	/* BRC 15,0 */#elif defined(HPPA)#define LOOP	0xe81f1ff7	/* b,l,n <loc>,r0 */#else#error unknown architecture#endif	if (tcp->flags & TCB_BPTSET) {		fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid);		return -1;	}#if defined (I386)	if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0)		return -1;#elif defined (M68K)	if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0)	  return -1;#elif defined (ALPHA)	return -1;#elif defined (ARM)	return -1;#elif defined (MIPS)	return -1;		/* FIXME: I do not know what i do - Flo */#elif defined (POWERPC)	if (upeek(tcp->pid, 4*PT_NIP, &tcp->baddr) < 0)		return -1;#elif defined(S390)	if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0)		return -1;#elif defined(HPPA)	if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0)		return -1;	tcp->baddr &= ~0x03;#else#error unknown architecture#endif	if (debug)		fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr);	tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0);	if (errno) {		perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)");		return -1;	}	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP);	if (errno) {		perror("setbpt: ptrace(PTRACE_POKETEXT, ...)");		return -1;	}	tcp->flags |= TCB_BPTSET;#endif /* !IA64 */#endif /* SPARC */#endif /* LINUX */#ifdef SUNOS4#ifdef SPARC	/* This code is slightly sparc specific */	struct regs regs;#define BPT	0x91d02001	/* ta	1 */#define LOOP	0x10800000	/* ba	0 */#define LOOPA	0x30800000	/* ba,a	0 */#define NOP	0x01000000#if LOOPA	static int loopdeloop[1] = {LOOPA};#else	static int loopdeloop[2] = {LOOP, NOP};#endif	if (tcp->flags & TCB_BPTSET) {		fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid);		return -1;	}	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {		perror("setbpt: ptrace(PTRACE_GETREGS, ...)");		return -1;	}	tcp->baddr = regs.r_o7 + 8;	if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr,				sizeof tcp->inst, (char *)tcp->inst) < 0) {		perror("setbpt: ptrace(PTRACE_READTEXT, ...)");		return -1;	}	/*	 * XXX - BRUTAL MODE ON	 * We cannot set a real BPT in the child, since it will not be	 * traced at the moment it will reach the trap and would probably	 * die with a core dump.	 * Thus, we are force our way in by taking out two instructions	 * and insert an eternal loop in stead, in expectance of the SIGSTOP	 * generated by out PTRACE_ATTACH.	 * Of cause, if we evaporate ourselves in the middle of all this...	 */	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,			sizeof loopdeloop, (char *) loopdeloop) < 0) {		perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)");		return -1;	}	tcp->flags |= TCB_BPTSET;#endif /* SPARC */#endif /* SUNOS4 */	return 0;}intclearbpt(tcp)struct tcb *tcp;{#ifdef LINUX#if defined(I386)	long eip;#elif defined(POWERPC)	long pc;#elif defined(M68K)	long pc;#elif defined(ALPHA)	long pc;#elif defined(HPPA)	long iaoq;#endif /* architecture */#ifdef SPARC	/* Again, we borrow the SunOS breakpoint code. */	if (!(tcp->flags & TCB_BPTSET)) {		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);		return -1;	}	errno = 0;	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);	if(errno) {		perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");		return -1;	}	tcp->flags &= ~TCB_BPTSET;#elif defined(IA64)	{		unsigned long addr, ipsr;		pid_t pid;		pid = tcp->pid;		if (upeek(pid, PT_CR_IPSR, &ipsr) < 0)			return -1;		if (upeek(pid, PT_CR_IIP, &addr) < 0)			return -1;		/* restore original bundle: */		errno = 0;		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]);		ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]);		if (errno) {			perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)");			return -1;		}		/* restore original "ri" in ipsr: */		ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41);		errno = 0;		ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr);		if (errno) {			perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)");			return -1;		}		tcp->flags &= ~TCB_BPTSET;		if (addr != (tcp->baddr & ~0x3)) {			/* the breakpoint has not been reached yet.  */			if (debug)				fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",					addr, tcp->baddr);			return 0;		}	}#else /* !IA64  && ! SPARC */	if (debug)		fprintf(stderr, "[%d] clearing bpt\n", tcp->pid);	if (!(tcp->flags & TCB_BPTSET)) {		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);		return -1;	}	errno = 0;	ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]);	if (errno) {		perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)");		return -1;	}	tcp->flags &= ~TCB_BPTSET;#ifdef I386	if (upeek(tcp->pid, 4*EIP, &eip) < 0)		return -1;	if (eip != tcp->baddr) {		/* The breakpoint has not been reached yet.  */		if (debug)			fprintf(stderr,				"NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",					eip, tcp->baddr);		return 0;	}#elif defined(POWERPC)	if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0)		return -1;	if (pc != tcp->baddr) {		/* The breakpoint has not been reached yet.  */		if (debug)			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",				pc, tcp->baddr);		return 0;	}#elif defined(M68K)	if (upeek(tcp->pid, 4*PT_PC, &pc) < 0)		return -1;	if (pc != tcp->baddr) {		/* The breakpoint has not been reached yet.  */		if (debug)			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",				pc, tcp->baddr);		return 0;	}#elif defined(ALPHA)	if (upeek(tcp->pid, REG_PC, &pc) < 0)		return -1;	if (pc != tcp->baddr) {		/* The breakpoint has not been reached yet.  */		if (debug)			fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n",				pc, tcp->baddr);		return 0;	}#elif defined(HPPA)	if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0)		return -1;	iaoq &= ~0x03;	if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) {		/* The breakpoint has not been reached yet.  */		if (debug)			fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n",				iaoq, tcp->baddr);		return 0;	}	iaoq = tcp->baddr | 3;	/* We should be pointing at a 'ldi -1000,r1' in glibc, so it is	 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit	 * has no significant effect.	 */	ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq);	ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq);#endif /* arch */#endif /* !SPARC && !IA64 */#endif /* LINUX */#ifdef SUNOS4#ifdef SPARC#if !LOOPA	struct regs regs;#endif	if (!(tcp->flags & TCB_BPTSET)) {		fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid);		return -1;	}	if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr,				sizeof tcp->inst, (char *) tcp->inst) < 0) {		perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)");		return -1;	}	tcp->flags &= ~TCB_BPTSET;#if !LOOPA	/*	 * Since we don't have a single instruction breakpoint, we may have	 * to adjust the program counter after removing the our `breakpoint'.	 */	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {		perror("clearbpt: ptrace(PTRACE_GETREGS, ...)");		return -1;	}	if ((regs.r_pc < tcp->baddr) ||				(regs.r_pc > tcp->baddr + 4)) {		/* The breakpoint has not been reached yet */		if (debug)			fprintf(stderr,				"NOTE: PC not at bpt (pc %#x baddr %#x)\n",					regs.r_pc, tcp->parent->baddr);		return 0;	}	if (regs.r_pc != tcp->baddr)		if (debug)			fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n",				regs.r_pc, tcp->baddr);	regs.r_pc = tcp->baddr;	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0) {		perror("clearbpt: ptrace(PTRACE_SETREGS, ...)");		return -1;	}#endif /* LOOPA */#endif /* SPARC */#endif /* SUNOS4 */	return 0;}#endif /* !USE_PROCFS */#ifdef SUNOS4static intgetex(pid, hdr)int pid;struct exec *hdr;{	int n;	for (n = 0; n < sizeof *hdr; n += 4) {		long res;		if (upeek(pid, uoff(u_exdata) + n, &res) < 0)			return -1;		memcpy(((char *) hdr) + n, &res, 4);	}	if (debug) {		fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n",			hdr->a_magic, hdr->a_toolversion, hdr->a_machtype);		fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n",			hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry);	}	return 0;}intfixvfork(tcp)struct tcb *tcp;{	int pid = tcp->pid;	/*	 * Change `vfork' in a freshly exec'ed dynamically linked	 * executable's (internal) symbol table to plain old `fork'	 */	struct exec hdr;	struct link_dynamic dyn;	struct link_dynamic_2 ld;	char *strtab, *cp;	if (getex(pid, &hdr) < 0)		return -1;	if (!hdr.a_dynamic)		return -1;	if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) {		fprintf(stderr, "Cannot read DYNAMIC\n");		return -1;	}	if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) {		fprintf(stderr, "Cannot read link_dynamic_2\n");		return -1;	}	if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) {		fprintf(stderr, "fixvfork: out of memory\n");		return -1;	}	if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),					(int)ld.ld_symb_size, strtab) < 0)		goto err;#if 0	for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {		fprintf(stderr, "[symbol: %s]\n", cp);		cp += strlen(cp)+1;	}	return 0;#endif	for (cp = strtab; cp < strtab + ld.ld_symb_size; ) {		if (strcmp(cp, "_vfork") == 0) {			if (debug)				fprintf(stderr, "fixvfork: FOUND _vfork\n");			strcpy(cp, "_fork");			break;		}		cp += strlen(cp)+1;	}	if (cp < strtab + ld.ld_symb_size)		/*		 * Write entire symbol table back to avoid		 * memory alignment bugs in ptrace		 */		if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr),					(int)ld.ld_symb_size, strtab) < 0)			goto err;	free(strtab);	return 0;err:	free(strtab);	return -1;}#endif /* SUNOS4 */

⌨️ 快捷键说明

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