shithub: 5v

Download patch

ref: d6a35f12c5156009d35534fb9bb3d59a541d2e2c
parent: c0fef42e25d7b90e3982d6be1d571d631b895ef6
author: Ori Bernstein <[email protected]>
date: Sat Sep 9 16:51:41 EDT 2023

5e: add alloc bit

--- a/arm.c
+++ b/arm.c
@@ -21,6 +21,13 @@
 
 int vtrace;
 
+u32int mallocaddr;
+u32int freeaddr;
+u32int reallocaddr;
+u32int setmalloctagaddr;
+u32int setrealloctagaddr;
+u32int vtraceaddr;
+
 static u32int
 arg(int n)
 {
@@ -337,6 +344,10 @@
 				P->hookarg[1] = asize(1);
 				P->hookfn = hookfree;
 				P->hookpc = P->R[15];
+			}else if(npc == setmalloctagaddr){
+				P->hookpc = P->R[15];
+			}else if(npc == setrealloctagaddr){
+				P->hookpc = P->R[15];
 			}else if(npc == vtraceaddr){
 				vtrace = arg(0);
 			}
@@ -575,7 +586,8 @@
 			);
 	}
 	if(P->R[15] == P->hookpc){
-		P->hookfn(P->hookarg);
+		if(P->hookfn)
+			P->hookfn(P->hookarg);
 		P->hookpc = 0;
 		P->hookfn = nil;
 	}
--- a/chk.c
+++ b/chk.c
@@ -7,7 +7,7 @@
 #include "fns.h"
 
 void
-dumpmap(Segment *seg, u32int off, char *fmt, ...)
+dumpmap(Segment *seg, u32int off, u32int len, char *fmt, ...)
 {
 	char buf[16*1024], *p, *e;
 	va_list ap;
@@ -22,7 +22,8 @@
 		print("not tracing\n");
 		return;
 	}
-	for(i = 0; i <= (seg->size + 7)/8; i++){
+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
@@ -43,10 +44,10 @@
 }
 
 void
-validmem(Segment *seg, u32int off, u32int len)
+checkaccess(Segment *seg, u32int off, u32int len, int chk)
 {
 	static int never;
-	u32int end;
+	u32int end, bits;
 
 	/*
 	 * when we're within a malloc or free operation, we're looking at
@@ -55,30 +56,44 @@
 	 */
 	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);
+	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)
+markvalid(Segment *seg, u32int off, u32int len, int chk)
 {
 	u32int end;
 
-	for(end = off+len; off != end; off++)
-		seg->shadow[off>>3] |= (1<<(off&7));
+	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 *s, u32int off, u32int len)
+markinvalid(Segment *seg, u32int off, u32int len, int chk)
 {
 	u32int end;
 
-	for(end = off+len; off != end; off++)
-		s->shadow[off>>3] &= ~(1<<(off&7));
+	end = off+len;
+	if(end > seg->size)
+		end = seg->size;
+	for(; off != end; off++)
+		seg->shadow[off>>2] &= ~(chk<<(2*(off&3)));
 }
 
 void
@@ -88,11 +103,7 @@
 	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");
+	markvalid(seg, p - (uchar*)seg->data, av[0], MARKALLOC);
 	segunlock(seg);
 }
 
@@ -105,6 +116,8 @@
 	u32int oldoff, newoff;
 	Segment *seg0, *seg1;
 
+	seg0 = nil;
+	seg1 = nil;
 	oldp = nil;
 	newp = nil;
 	oldsz = 0;
@@ -122,18 +135,19 @@
 		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(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)
-		markinvalid(seg1, newoff+oldsz, newsz-oldsz);
-	if(mallocverbose)
-		dumpmap(seg1, newp-(uchar*)seg1->start, "postrealloc");
-	segunlock(seg0);
-	segunlock(seg1);
+	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
@@ -143,10 +157,6 @@
 	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");
+	markinvalid(seg, p - (uchar*)seg->data, av[1], MARKALLOC|MARKINIT);
 	segunlock(seg);
 }
--- a/dat.h
+++ b/dat.h
@@ -29,6 +29,11 @@
 	AWR	= 1<<1,
 };
 
+enum {
+	MARKALLOC	= 1<<0,
+	MARKINIT	= 1<<1,
+};
+
 struct Process {
 	Process *prev, *next;	/* linked list (for fs) */
 	int pid;
@@ -70,10 +75,12 @@
 extern Process plist;
 extern Lock plistlock;
 extern int check;
-u32int mallocaddr;
-u32int freeaddr;
-u32int reallocaddr;
-u32int vtraceaddr;
+extern u32int mallocaddr;
+extern u32int freeaddr;
+extern u32int reallocaddr;
+extern u32int setmalloctagaddr;
+extern u32int setrealloctagaddr;
+extern u32int vtraceaddr;
 
 enum {
 	SEGFLLOCK = 1,
@@ -98,5 +105,4 @@
 
 #define fulltrace 0
 #define ultraverbose 0
-#define mallocverbose 0
 #define systrace 0
--- a/fns.h
+++ b/fns.h
@@ -31,7 +31,7 @@
 void donote(char *, ulong);
 void addnote(char *);
 void dump(void);
-void dumpmap(Segment *, u32int, char *, ...);
+void dumpmap(Segment *, u32int, u32int, char *, ...);
 void resetfpa(void);
 void invalid(u32int);
 u32int evenaddr(u32int,u32int);
@@ -44,9 +44,9 @@
 void vfpoperation(u32int);
 void inittos(void);
 void initmem(void);
-void validmem(Segment*, u32int, u32int);
-void markvalid(Segment*, u32int, u32int);
-void markinvalid(Segment*, u32int, u32int);
+void checkaccess(Segment*, u32int, u32int, int);
+void markvalid(Segment*, u32int, u32int, int);
+void markinvalid(Segment*, u32int, u32int, int);
 void hookmalloc(u32int*);
 void hookrealloc(u32int*);
 void hookfree(u32int*);
--- a/proc.c
+++ b/proc.c
@@ -195,35 +195,33 @@
 	return -1;
 }
 
-static void
-inithooks(void)
+u32int
+hookaddr(char *name)
 {
 	Symbol s;
 
-	if(lookup("poolalloc", nil, &s) == -1)
-		mallocaddr = -1;
-	else
-		mallocaddr = s.value;
-	if(lookup("poolrealloc", nil, &s) == -1)
-		reallocaddr = -1;
-	else
-		reallocaddr = s.value;
-	if(lookup("poolfree", nil, &s) == -1)
-		freeaddr = -1;
-	else
-		freeaddr = s.value;
-	if(lookup("vtrace", nil, &s) == -1)
-		vtraceaddr = -1;
-	else
-		vtraceaddr = s.value;
+	if(lookup(name, nil, &s) == -1)
+		return -1;
+	return s.value;
 }
 
+static void
+inithooks(void)
+{
+	mallocaddr = hookaddr("poolalloc");
+	reallocaddr = hookaddr("poolrealloc");
+	freeaddr = hookaddr("poolfree");
+	setmalloctagaddr = hookaddr("setmalloctag");
+	setrealloctagaddr = hookaddr("setrealloctag");
+	vtraceaddr = hookaddr("vtrace");
+}
+
 int
 loadtext(char *file, int argc, char **argv)
 {
 	int fd;
 	Fhdr fp;
-	Segment *text, *data, *bss;
+	Segment *text, *data, *bss, *stk;
 	char buf[2];
 	
 	fd = open(file, OREAD);
@@ -243,12 +241,13 @@
 	text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT);
 	data = newseg(fp.dataddr, fp.datsz, SEGDATA);
 	bss = newseg(fp.dataddr + fp.datsz, fp.bsssz, SEGBSS);
+	stk = newseg((mach->utop & ~7) - STACKSIZE, STACKSIZE, SEGSTACK);
 	if(check){
-		markvalid(text, 0, fp.txtsz+fp.hdrsz);
-		markvalid(data, 0, fp.datsz);
-		markvalid(bss, 0, fp.bsssz);
+		markvalid(text, 0, fp.txtsz+fp.hdrsz, MARKALLOC|MARKINIT);
+		markvalid(data, 0, fp.datsz, MARKALLOC|MARKINIT);
+		markvalid(bss, 0, fp.bsssz, MARKALLOC|MARKINIT);
+		markvalid(stk, 0, stk->size, MARKALLOC|MARKINIT);
 	}
-	newseg((mach->utop & ~7) - STACKSIZE, STACKSIZE, SEGSTACK);
 	seek(fd, fp.txtoff - fp.hdrsz, 0);
 	if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz)
 		sysfatal("%r");
--- a/seg.c
+++ b/seg.c
@@ -18,7 +18,7 @@
 	incref(s->dref);
 	s->data = s->dref + 1;
 	if(check)
-		s->shadow = emallocz((size+7)/8);
+		s->shadow = emallocz((size+3)/4);
 	if(idx == SEGBSS)
 		s->flags = SEGFLLOCK;
 	P->S[idx] = s;
@@ -46,6 +46,7 @@
 {
 	Segment **ss, *s;
 	u32int off;
+	int bits;
 
 	for(ss = P->S; ss < P->S + SEGNUM; ss++) {
 		if(*ss == nil)
@@ -58,9 +59,11 @@
 				rlock(&s->rw);
 			*seg = s;
 			off = (addr - s->start);
-			if(check){
-				if(op&ARD) validmem(s, off, len);
-				if(op&AWR) markvalid(s, off, len);
+			if(check && op != 0){
+				bits = MARKALLOC;
+				if(op & ARD) bits |= MARKINIT;
+				checkaccess(s, off, len, bits);
+				if(op & AWR) markvalid(s, off, len, MARKINIT);
 			}
 			return (char *)s->data + off;
 		}
--- a/sys.c
+++ b/sys.c
@@ -101,7 +101,8 @@
 		copyback(buf, P->R[0], targ);
 	if(check && (s32int)P->R[0] > 0){
 		vaddr(buf, 0, 0, &seg);
-		markvalid(seg, buf-seg->start, P->R[0]);
+		checkaccess(seg, buf-seg->start, P->R[0], MARKALLOC);
+		markvalid(seg, buf-seg->start, P->R[0], MARKINIT);
 		segunlock(seg);
 	}
 }
@@ -185,7 +186,8 @@
 		copyback(edir, P->R[0], edirt);
 	if(check && (s32int)P->R[0] > 0){
 		vaddr(edir, 0, 0, &seg);
-		markvalid(seg, edir-seg->start, P->R[0]);
+		checkaccess(seg, edir-seg->start, P->R[0], MARKALLOC);
+		markvalid(seg, edir-seg->start, P->R[0], MARKINIT);
 		segunlock(seg);
 	}
 }
@@ -209,7 +211,8 @@
 		copyback(edir, P->R[0], edirt);
 	if(check && (s32int)P->R[0] > 0){
 		vaddr(edir, 0, 0, &seg);
-		markvalid(seg, edir-seg->start, P->R[0]);
+		checkaccess(seg, edir-seg->start, P->R[0], MARKALLOC);
+		markvalid(seg, edir-seg->start, P->R[0], MARKINIT);
 		segunlock(seg);
 	}
 }
@@ -289,11 +292,11 @@
 	if(o < n)
 		memset((char*)s->data + o, 0, n - o);
 	if(s->shadow != nil){
-		s->shadow = realloc(s->shadow, n);
+		s->shadow = realloc(s->shadow, (n+3)/4);
 		if(s->shadow == nil)
 			sysfatal("error reallocating");
 		if(n - o > 0)
-			memset(s->shadow + o, 0, n - o);
+			memset(s->shadow + (o+3)/4, 0, (n - o + 3)/4);
 	}
 	s->size = v - s->start;
 	P->R[0] = 0;
--- a/test.c
+++ b/test.c
@@ -10,6 +10,7 @@
 
 	x = malloc(123);
 	x[1] = 123;
+	x[124] = 7;
 	y = x[1];
 	argv[0][0] = y;
 	free(x);