shithub: 5v

ref: 5a514a681e4c2ab86f76509203a0a96d371d51aa
dir: /chk.c/

View raw version
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <bio.h>
#include <mach.h>
#include "dat.h"
#include "fns.h"
extern int vtrace;

void
dumpmap(Segment *seg, u32int off, char *fmt, ...)
{
	char buf[16*1024], *p, *e;
	va_list ap;
	int i;

	p = buf;
	e = p + sizeof(buf)-1;
	va_start(ap, fmt);
	p = vseprint(p, e, fmt, ap);
	va_end(ap);
	if(seg->shadow == nil){
		print("not tracing\n");
		return;
	}
	for(i = (off&~0x4095)/8; i <= (seg->size + 7)/8; i++){
		if(i % 40 == 0)
			p = seprint(p, e, "\n[%04x] ", seg->start+i*8);
		p = seprint(p, e, "%02ux", seg->shadow[i]);
	}
	*p++ = '\n';
	write(1, buf, p - buf);
}

static u32int
arg(int n)
{
	/* no locking necessary, since we're on the stack */
	return *(u32int*) vaddrnol(P->R[13] + 4 + 4 * n, 4, ARD);
}

void
validmem(Segment *seg, u32int off, u32int len)
{
	static int never;
	u32int end;

	/*
	 * when we're within a malloc or free operation, we're looking at
	 * memory that we don't want to allow user programs to touch; skip
	 * the check here.
	 */
	if(P->hookpc != 0)
		return;
	for(end = off+len; off != end; off++){
		if((seg->shadow[off>>3] & 1<<(off&7)) == 0){
			print("invalid read of %#x at %#x\n", seg->start+off, P->R[15] - 4);
dumpmap(seg, off, "broken");
			rendezvous(&never, nil);
			exits("bad access");
		}
	}
}
void
markvalid(Segment *seg, u32int off, u32int len)
{
	u32int end;

//print("seg: %#p\n", seg);
//print("mark[shadow=%#p] %#x+%x [%#x+%#x]\n", seg->shadow, seg->start + off, len, seg->start, off);
	for(end = off+len; off != end; off++)
		seg->shadow[off>>3] |= (1<<(off&7));
}

void
markinvalid(Segment *s, u32int off, u32int len)
{
	u32int end;

	for(end = off+len; off != end; off++)
		s->shadow[off>>3] &= ~(1<<(off&7));
}

void
hookmalloc(u32int *av)
{
	Segment *seg;
	uchar *p;

	p = vaddr(P->R[0], 0, 0, &seg);
	if(mallocverbose)
		dumpmap(seg, p-(uchar*)seg->start, "malloced %#x+%d\n", P->R[0], av[0]);
	markinvalid(seg, p - (uchar*)seg->data, av[0]);
	if(mallocverbose)
		dumpmap(seg, p-(uchar*)seg->start, "postmalloc");
	segunlock(seg);
}


void
hookrealloc(u32int *av)
{
	uchar *oldp, *newp;
	u32int oldsz, newsz, sz;
	u32int oldoff, newoff;
	Segment *seg0, *seg1;

	oldp = vaddr(av[0], 0, 0, &seg0);
	newp = vaddr(P->R[0], 0, 0, &seg1);
	oldsz = av[1];
	newsz = av[2];
	oldoff = oldp - (uchar*)seg0->data;
	newoff = newp - (uchar*)seg1->data;
	sz = (oldsz < newsz) ? oldsz : newsz;
	if(mallocverbose)
		dumpmap(seg0, oldp-(uchar*)seg0->start, "realloc %#x+%d => %#x+%d\n", av[0], av[1], P->R[0], av[2]);
	if(oldp != newp)
		memcpy(seg1->shadow+oldoff/8, seg0->shadow+newoff/8, (sz+7)/8);
	if(newsz > oldsz)
		markinvalid(seg0, oldoff+oldsz, newsz-oldsz);
	if(mallocverbose)
		dumpmap(seg1, newp-(uchar*)seg1->start, "postrealloc");
	segunlock(seg0);
	segunlock(seg1);
}

void
hookfree(u32int *av)
{
	Segment *seg;
	uchar *p;

	p = vaddr(av[0], 0, 0, &seg);
	if(mallocverbose)
		dumpmap(seg, p-(uchar*)seg->start, "free %#x+%d\n", av[0], av[1]);
	markinvalid(seg, p - (uchar*)seg->data, av[1]);
	if(mallocverbose)
		dumpmap(seg, p-(uchar*)seg->start, "postfree");
	segunlock(seg);
}