118 lines · 2.0 KB · C
RawDownload
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"archtrace.h" #pragma	profile	0 /* * this is the wrong place for this, and a very large hammer, * but at least we are controlling access to kernel memory. * must match mmuinit() */static voidkmem(int write){	PTE x, *p; 	for(x = KTZERO; x < (ulong)etext; x += BY2PG){		p = mmuwalk(m->pdb, x, 2, 0);		if(p == nil)			panic("kmem");		if(write)			*p |= PTEWRITE;		else			*p &= ~PTEWRITE;	}} enum {	CALL	= 0xe8,	JMP	= 0xeb,	RET	= 0xc3,	NOP	= 0x90,}; char*archtracectlr(Archtrace *a, char *p, char *e){	int i; 	for(i = 0; i < a->nprobe; i++)		p = seprint(p, e, "#  tracept %c %#.8p\n",			a->probe[i]==NOP? 'X': 'E', a->text[i]);	return p;} voidarchtraceinstall(Archtrace *a){	int i; 	kmem(1);	for(i = 0; i < a->nprobe; i++)		*a->text[i] = a->probe[i];	kmem(0);} voidarchtraceuninstall(Archtrace *a){	int i; 	kmem(1);	for(i = 0; i < a->nprobe; i++)		*a->text[i] = a->orig[i];	kmem(0);} static intcall4(uchar *call, uchar *targ){	uchar buf[5];	ulong l; 	buf[0] = CALL;	l = targ - (call + 5);	buf[1] = l;	buf[2] = l>>8;	buf[3] = l>>16;	buf[4] = l>>24;	return memcmp(buf, call, 5);} static uchar startsig[] = {JMP, 0x05}; intmkarchtrace(Archtrace *a, uchar *start, uchar **endp){	uchar *p, *end; 	/*	 * search by signatures.  we don't really	 * care we get a whole function or not.	 */	end = *endp;	for(p = start; p + 6 <= end; p++)		if(memcmp(p, startsig, sizeof startsig) == 0){			if(call4(p + 2, (uchar*)_tracein) == 0){				a->text[a->nprobe] = start + 1;				a->orig[a->nprobe] = *a->text[a->nprobe];				a->probe[a->nprobe] = 0;		/* jmp 2f */				a->nprobe++;			}		}else  if(p[0] == RET && p[6] == RET){			if(call4(p + 1, (uchar*)_traceout) == 0){				if(a->nprobe == Maxprobe)					error("too many exits");				a->text[a->nprobe] = p;				a->orig[a->nprobe] = *a->text[a->nprobe];				a->probe[a->nprobe] = NOP;				a->nprobe++;			}		}//	*endp = a->text[a->nprobe - 1];	return 0;}