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 = {
"./",