From 68cfc786ba6f956cb7e1210ee312f436ae69192b Mon Sep 17 00:00:00 2001 From: aiju Date: Mon, 12 Jun 2017 19:29:20 +0000 Subject: [PATCH] acid: watchpoint support --- sys/lib/acid/386 | 13 +++- sys/lib/acid/68020 | 2 + sys/lib/acid/amd64 | 15 +++-- sys/lib/acid/arm | 2 + sys/lib/acid/mips | 2 + sys/lib/acid/port | 145 +++++++++++++++++++++++++++++++++++++++++++ sys/lib/acid/power | 2 + sys/lib/acid/sparc | 2 + sys/lib/acid/sparc64 | 2 + 9 files changed, 178 insertions(+), 7 deletions(-) diff --git a/sys/lib/acid/386 b/sys/lib/acid/386 index 5ae46fd83..fb7a8ad29 100644 --- a/sys/lib/acid/386 +++ b/sys/lib/acid/386 @@ -4,6 +4,8 @@ defn acidinit() // Called after all the init modules are loaded { bplist = {}; bpfmt = 'b'; + wplist = {}; + wpflush(); srcpath = { "./", @@ -84,13 +86,18 @@ defn pstop(pid) 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 { diff --git a/sys/lib/acid/68020 b/sys/lib/acid/68020 index 4d19b0fb6..ae02d101e 100644 --- a/sys/lib/acid/68020 +++ b/sys/lib/acid/68020 @@ -4,6 +4,8 @@ defn acidinit() // Called after all the init modules are loaded { bplist = {}; bpfmt = 'x'; + wplist = {}; + wpflush(); srcpath = { "./", diff --git a/sys/lib/acid/amd64 b/sys/lib/acid/amd64 index 7d7ce4ba7..9a850cfca 100644 --- a/sys/lib/acid/amd64 +++ b/sys/lib/acid/amd64 @@ -4,7 +4,9 @@ defn acidinit() { bplist = {}; bpfmt = 'b'; - + wplist = {}; + wpflush(); + srcpath = { "./", "/sys/src/libc/port/", @@ -98,13 +100,18 @@ defn pstop(pid) 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 { diff --git a/sys/lib/acid/arm b/sys/lib/acid/arm index 0578da53f..18f88cf33 100644 --- a/sys/lib/acid/arm +++ b/sys/lib/acid/arm @@ -4,6 +4,8 @@ defn acidinit() // Called after all the init modules are loaded { bplist = {}; bpfmt = 'X'; + wplist = {}; + wpflush(); srcpath = { "./", diff --git a/sys/lib/acid/mips b/sys/lib/acid/mips index 5c267d1f0..79968b93f 100644 --- a/sys/lib/acid/mips +++ b/sys/lib/acid/mips @@ -4,6 +4,8 @@ defn acidinit() // Called after all the init modules are loaded { bplist = {}; bpfmt = 'X'; + wplist = {}; + wpflush(); srcpath = { "./", diff --git a/sys/lib/acid/port b/sys/lib/acid/port index 60cfa1adc..aa48ef3e7 100644 --- a/sys/lib/acid/port +++ b/sys/lib/acid/port @@ -267,6 +267,7 @@ defn step() // single step the process bput = fmt(*PC, bpfmt); *bput = @bput; } + wpupdate(0); lst = follow(*PC); @@ -336,6 +337,134 @@ defn bpdel(addr) // delete a breakpoint 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 @@ defn cont() // continue execution step(); // Step over *addr = bpinst; } + wpupdate(0); startstop(pid); // Run } @@ -405,6 +535,7 @@ defn win() local npid, estr; bplist = {}; + wplist = {}; notes = {}; estr = "/sys/lib/acid/window '0 0 600 400' "+textfile; @@ -425,6 +556,7 @@ defn win2() 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 win2() defn new() { bplist = {}; + wplist = {}; newproc(progargs); // Dont miss the delay slot calls bpset(follow(main)[0]); @@ -565,5 +698,17 @@ defn spsrch(len) } } +defn procattach() +{ + wpflush(); +} + +defn dying() +{ + wplist = {}; + wpflush(); + derp(); +} + progargs=""; print("/sys/lib/acid/port"); diff --git a/sys/lib/acid/power b/sys/lib/acid/power index 68aeacb18..6be4992b9 100644 --- a/sys/lib/acid/power +++ b/sys/lib/acid/power @@ -4,6 +4,8 @@ defn acidinit() // Called after all the init modules are loaded { bplist = {}; bpfmt = 'X'; + wplist = {}; + wpflush(); srcpath = { "./", diff --git a/sys/lib/acid/sparc b/sys/lib/acid/sparc index 76a1eba36..246d553b8 100644 --- a/sys/lib/acid/sparc +++ b/sys/lib/acid/sparc @@ -4,6 +4,8 @@ defn acidinit() // Called after all the init modules are loaded { bplist = {}; bpfmt = 'X'; + wplist = {}; + wpflush(); srcpath = { "./", diff --git a/sys/lib/acid/sparc64 b/sys/lib/acid/sparc64 index f1710bd86..2abb5fe14 100644 --- a/sys/lib/acid/sparc64 +++ b/sys/lib/acid/sparc64 @@ -4,6 +4,8 @@ defn acidinit() // Called after all the init modules are loaded { bplist = {}; bpfmt = 'X'; + wplist = {}; + wpflush(); srcpath = { "./",