ref: c0fef42e25d7b90e3982d6be1d571d631b895ef6
dir: /chk.c/
#include <u.h> #include <libc.h> #include <thread.h> #include <bio.h> #include <mach.h> #include "dat.h" #include "fns.h" void dumpmap(Segment *seg, u32int off, char *fmt, ...) { char buf[16*1024], *p, *e; va_list ap; int i, c; 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 = 0; i <= (seg->size + 7)/8; i++){ if(i >= off/8 && i+40 < off/8) c = '*'; else c = ' '; if(i % 40 == 0) p = seprint(p, e, "\n[%04x]%c", seg->start+i*8, c); 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); rendezvous(&never, nil); exits("bad access"); } } } void markvalid(Segment *seg, u32int off, u32int len) { u32int end; 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 = nil; newp = nil; oldsz = 0; newsz = 0; oldoff = 0; newoff = 0; if(av[0] != 0){ oldp = vaddr(av[0], 0, 0, &seg0); oldsz = av[1]; oldoff = oldp - (uchar*)seg0->data; } if(P->R[0] != 0){ newp = vaddr(P->R[0], 0, 0, &seg1); newsz = av[2]; 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); markinvalid(seg0, oldoff, oldsz); } if(newsz > oldsz) markinvalid(seg1, newoff+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); }