ref: c1b943384c1cf8bddbad7df63319d597710f943d
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, u32int len, 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;
}
print("off: %d, len: %d\n", off, len);
for(i = off/8; i <= (off+len+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
checkaccess(Segment *seg, u32int off, u32int len, int chk)
{
static int never;
u32int end, bits;
/*
* 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;
end = off+len;
if(end > seg->size){
print("read past end of segment: %#x at %#x\n", seg->start+off, P->R[15] - 4);
rendezvous(&never, nil);
exits("bad access");
}
for(; off != end; off++){
bits = chk << (2*(off&3));;
if((seg->shadow[off>>2] & bits) != bits){
print("invalid read: %#x at %#x (%x != %x)\n", seg->start+off, P->R[15] - 4, bits, (seg->shadow[off>>2] & bits));
rendezvous(&never, nil);
exits("bad access");
}
}
}
void
markvalid(Segment *seg, u32int off, u32int len, int chk)
{
u32int end;
end = off+len;
if(end > seg->size)
end = seg->size;
for(; off != end; off++)
seg->shadow[off>>2] |= chk<<(2*(off&3));
}
void
markinvalid(Segment *seg, u32int off, u32int len, int chk)
{
u32int end;
end = off+len;
if(end > seg->size)
end = seg->size;
for(; off != end; off++)
seg->shadow[off>>2] &= ~(chk<<(2*(off&3)));
}
void
hookmalloc(u32int *av)
{
Segment *seg;
uchar *p;
p = vaddr(P->R[0], 0, 0, &seg);
markvalid(seg, p - (uchar*)seg->data, av[0], MARKALLOC);
segunlock(seg);
}
void
hookrealloc(u32int *av)
{
uchar *oldp, *newp;
u32int oldsz, newsz, sz;
u32int oldoff, newoff;
Segment *seg0, *seg1;
seg0 = nil;
seg1 = nil;
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(oldp != newp && oldsz > 0){
memcpy(seg1->shadow+oldoff/4, seg0->shadow+newoff/4, (sz+3)/4);
markinvalid(seg0, oldoff, oldsz, MARKALLOC|MARKINIT);
}
if(newsz > oldsz){
markvalid(seg1, newoff+oldsz, newsz-oldsz, MARKALLOC);
markinvalid(seg1, newoff+oldsz, newsz-oldsz, MARKINIT);
}
if(seg0 != nil)
segunlock(seg0);
if(seg1 != nil)
segunlock(seg1);
}
void
hookfree(u32int *av)
{
Segment *seg;
uchar *p;
p = vaddr(av[0], 0, 0, &seg);
markinvalid(seg, p - (uchar*)seg->data, av[1], MARKALLOC|MARKINIT);
segunlock(seg);
}