shithub: riscv

Download patch

ref: 68cfc786ba6f956cb7e1210ee312f436ae69192b
parent: 5dcb407add4013d7234dc248fb97c8a5d146e3d3
author: aiju <devnull@localhost>
date: Mon Jun 12 15:29:20 EDT 2017

acid: watchpoint support

--- a/sys/lib/acid/386
+++ b/sys/lib/acid/386
@@ -4,6 +4,8 @@
 {
 	bplist = {};
 	bpfmt = 'b';
+	wplist = {};
+	wpflush();
 
 	srcpath = {
 		"./",
@@ -84,13 +86,18 @@
 	local l;
 	local pc;
 
-	pc = *PC;
+	pc = (*PC)\i;
+	
+	if notes && regexp("^sys: watchpoint ", notes[0]) then
+		pc--;
 
 	print(pid,": ", reason(*TRAP), "\t");
-	print(fmt(pc, 'a'), "\t", fmt(pc, 'i'), "\n");
+	print(fmt(pc, 'a'), "\t", pc, "\n");
 
 	if notes then {
-		if notes[0] != "sys: breakpoint" then {
+		if regexp("^sys: watchpoint ", notes[0]) then
+			wpprocess();
+		else if notes[0] != "sys: breakpoint" then {
 			print("Notes pending:\n");
 			l = notes;
 			while l do {
--- a/sys/lib/acid/68020
+++ b/sys/lib/acid/68020
@@ -4,6 +4,8 @@
 {
 	bplist = {};
 	bpfmt = 'x';
+	wplist = {};
+	wpflush();
 
 	srcpath = {
 		"./",
--- a/sys/lib/acid/amd64
+++ b/sys/lib/acid/amd64
@@ -4,7 +4,9 @@
 {
 	bplist = {};
 	bpfmt = 'b';
-
+	wplist = {};
+	wpflush();
+	
 	srcpath = {
 		"./",
 		"/sys/src/libc/port/",
@@ -98,13 +100,18 @@
 	local l;
 	local pc;
 
-	pc = *PC;
+	pc = (*PC)\i;
+	
+	if notes && regexp("^sys: watchpoint ", notes[0]) then
+		pc--;
 
 	print(pid,": ", reason(*TRAP), "\t");
-	print(fmt(pc, 'a'), "\t", fmt(pc, 'i'), "\n");
+	print(fmt(pc, 'a'), "\t", pc, "\n");
 
 	if notes then {
-		if notes[0] != "sys: breakpoint" then {
+		if regexp("^sys: watchpoint ", notes[0]) then
+			wpprocess();
+		else if notes[0] != "sys: breakpoint" then {
 			print("Notes pending:\n");
 			l = notes;
 			while l do {
--- a/sys/lib/acid/arm
+++ b/sys/lib/acid/arm
@@ -4,6 +4,8 @@
 {
 	bplist = {};
 	bpfmt = 'X';
+	wplist = {};
+	wpflush();
 
 	srcpath = {
 		"./",
--- a/sys/lib/acid/mips
+++ b/sys/lib/acid/mips
@@ -4,6 +4,8 @@
 {
 	bplist = {};
 	bpfmt = 'X';
+	wplist = {};
+	wpflush();
 
 	srcpath = {
 		"./",
--- a/sys/lib/acid/port
+++ b/sys/lib/acid/port
@@ -267,6 +267,7 @@
 		bput = fmt(*PC, bpfmt);
 		*bput = @bput;
 	}
+	wpupdate(0);
 
 	lst = follow(*PC);
 
@@ -336,6 +337,134 @@
 	bplist = nbplist;			// delete from memory
 }
 
+defn wpflush()					// copy wplist to /proc/$pid/watchpt
+{
+	local s, lst, el;
+
+	lst = wplist;
+	s = "";
+	while lst do {
+		el = head lst;
+		s = s + (el[0] + " " + itoa(el[1]) + " " + itoa(el[2]) + "\n");
+		lst = tail lst;
+	}
+	lst = proclist;
+	while lst do {
+		if access("/proc/"+itoa(head lst)+"/watchpt") then
+			printto("/proc/"+itoa(head lst)+"/watchpt", s);
+		lst = tail lst;
+	}
+}
+
+defn wpset(type, addr, len)			// set a watchpoint
+{
+	local lst;
+
+	if status(pid) != "Stopped" then {
+		print("Waiting...\n");
+		stop(pid);
+	}
+	if !regexp("^[rwx\\-]+$", type) then {
+		print("invalid type\n");
+		return {};
+	}
+	lst = proclist;
+	while lst do {
+		if rc("echo '"+type+" "+itoa(addr)+" "+itoa(len)+"' >> /proc/"+itoa(head lst)+"/watchpt") != "" then
+			return {};
+		lst = tail lst;
+	}
+	wplist = append wplist, {type, addr, len, {}};
+}
+
+defn wptab()					// print a table of watchpoints
+{
+	local lst, el;
+
+	lst = wplist;
+	while lst do {
+		el = head lst;
+		print("\t", el[0], " ", fmt(el[1], 'A'), " ", fmt(el[1], 'a'), " ", fmt(el[2], 'd'), "\n");
+		lst = tail lst;
+	}
+}
+
+defn wpdel(addr)
+{
+	local lst, el, found, nwplist;
+	
+	lst = wplist;
+	found = 0;
+	nwplist = {};
+	while lst do {
+		el = head lst;
+		if el[1] == addr then
+			found = 1;
+		else
+			nwplist = append nwplist, el;
+		lst = tail lst;
+	}
+	if found == 0 then {
+		print("no watchpoint at ", fmt(addr, 'a'), "\n");
+		return {};
+	}
+	wplist = nwplist;
+	wpflush();
+}
+
+defn bytes(b)
+{
+	local s;
+	
+	s = "";
+	while b do {
+		s = s + itoa(head b, "%#.2x ");
+		b = tail b;
+	}
+	return s;
+}
+
+defn wpupdate(ch)				// update remembered values
+{
+	local el, nwplist, mem, lst, i;
+	
+	lst = wplist;
+	nwplist = {};
+	while lst do {
+		el = head lst;
+		i = 0;
+		mem = {};
+		while i < el[2] do {
+			mem = append mem, *((el[1] + i)\b);
+			i = i + 1;
+		}
+		if ch && el[3] != {} && el[3] != mem then {
+			print("\t", fmt(el[1], 'a'), "\twas ", bytes(el[3]), "\n");
+			print("\t", fmt(el[1], 'a'), "\tis  ", bytes(mem), "\n");
+		}
+		nwplist = append nwplist, {el[0], el[1], el[2], mem};
+		lst = tail lst;
+	}
+	wplist = nwplist;
+}
+
+defn wpprocess()				// trapped at watchpoint
+{
+	local pts;
+	local el;
+	
+	pts = getfields(getfields(notes[0], " ", 1)[2], ",", 1);
+	while pts do {
+		el = head pts;
+		el = wplist[atoi(el)];
+		if el != {} then {
+			print("\ttriggered ", el[0], " watchpoint at ", fmt(el[1], 'a'), " (", fmt(el[1], 'A'), ")\n");
+		}
+		pts = tail pts;
+	}
+	wpupdate(1);
+}
+
 defn cont()					// continue execution
 {
 	local addr;
@@ -346,6 +475,7 @@
 		step();				// Step over
 		*addr = bpinst;
 	}
+	wpupdate(0);
 	startstop(pid);				// Run
 }
 
@@ -405,6 +535,7 @@
 	local npid, estr;
 
 	bplist = {};
+	wplist = {};
 	notes = {};
 
 	estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;
@@ -425,6 +556,7 @@
 	local npid, estr;
 
 	bplist = {};
+	wplist = {};
 	notes = {};
 
 	estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;
@@ -443,6 +575,7 @@
 defn new()
 {
 	bplist = {};
+	wplist = {};
 	newproc(progargs);
 	// Dont miss the delay slot calls
 	bpset(follow(main)[0]);
@@ -563,6 +696,18 @@
 			pfl(a);
 		}			
 	}
+}
+
+defn procattach()
+{
+	wpflush();
+}
+
+defn dying()
+{
+	wplist = {};
+	wpflush();
+	derp();
 }
 
 progargs="";
--- a/sys/lib/acid/power
+++ b/sys/lib/acid/power
@@ -4,6 +4,8 @@
 {
 	bplist = {};
 	bpfmt = 'X';
+	wplist = {};
+	wpflush();
 
 	srcpath = {
 		"./",
--- a/sys/lib/acid/sparc
+++ b/sys/lib/acid/sparc
@@ -4,6 +4,8 @@
 {
 	bplist = {};
 	bpfmt = 'X';
+	wplist = {};
+	wpflush();
 
 	srcpath = {
 		"./",
--- a/sys/lib/acid/sparc64
+++ b/sys/lib/acid/sparc64
@@ -4,6 +4,8 @@
 {
 	bplist = {};
 	bpfmt = 'X';
+	wplist = {};
+	wpflush();
 
 	srcpath = {
 		"./",