The branch, master has been updated via dfa543f7189c681764596fc958a6d640a9558d46 (commit) from 1e6a205bbcbe119523df8e4a569a9aa3c9aa29b3 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit dfa543f7189c681764596fc958a6d640a9558d46 Author: Phil Muldoon <pmuldoon@redhat.com> Date: Fri Apr 4 15:37:31 2008 +0100 Implement top level interfaces. Test primary test case in TestWatchpoint. Add two modifications two stepping.handleTrappedEvent and running.handleTrappedEvent. 2008-04-04 Phil Muldoon <pmuldoon@redhat.com> * TestWatchpoint.java (testWatchpointTrigger): New. (WatchpointObserver): New. (TerminatedObserver): New. * WatchpointFunctionFactory.java (getWatchpointFunctions): Renamed from getWatchpoint. * TestWatchpoint: Update getWatchpoint -> getWatchpointFunctions. 2008-04-04 Phil Muldoon <pmuldoon@redhat.com> * LinuxPtraceProc.java (LinuxPtraceProc): Instatiate watchpoint address manager. (WatchpointAction): New. Install watchpoints. (requestAddWatchObserver): Implement. (requestDeleteWatchObserver): Ditto. * WatchpointAddresses.java (proc): Store a proc, not a task. (addWatchpoint): Take a length, and a write only flag. (removeWatchpoint): Ditto. (getWatchObservers): Ditto. (getWatchpoint): Ditto. * Watchpoint.java (Watchpoint): Take a task and a writeOnly flag. (create): Ditto (getLength): New. (isWriteOnly): New. (set): Actually set the watchpoint. (reset): Delete the watchpoint. * LinuxPtraceTaskState.java (Running.handleTrappedEvent): Add watchpoint catch/test. (Stepping.handleTrappedEvent): Ditto. ----------------------------------------------------------------------- Summary of changes: frysk-core/frysk/isa/watchpoints/ChangeLog | 9 ++ .../frysk/isa/watchpoints/TestWatchpoint.java | 87 +++++++++++++++++- .../isa/watchpoints/WatchpointFunctionFactory.java | 2 +- frysk-core/frysk/proc/live/ChangeLog | 24 +++++- frysk-core/frysk/proc/live/LinuxPtraceProc.java | 93 ++++++++++++++++++-- .../frysk/proc/live/LinuxPtraceTaskState.java | 34 +++++++- frysk-core/frysk/proc/live/Watchpoint.java | 91 +++++++++++++------ .../frysk/proc/live/WatchpointAddresses.java | 40 ++++----- 8 files changed, 315 insertions(+), 65 deletions(-) First 500 lines of diff: diff --git a/frysk-core/frysk/isa/watchpoints/ChangeLog b/frysk-core/frysk/isa/watchpoints/ChangeLog index 33613b2..4d0e585 100644 --- a/frysk-core/frysk/isa/watchpoints/ChangeLog +++ b/frysk-core/frysk/isa/watchpoints/ChangeLog @@ -1,3 +1,12 @@ +2008-04-04 Phil Muldoon <pmuldoon@redhat.com> + + * TestWatchpoint.java (testWatchpointTrigger): New. + (WatchpointObserver): New. + (TerminatedObserver): New. + * WatchpointFunctionFactory.java (getWatchpointFunctions): Renamed from + getWatchpoint. + * TestWatchpoint: Update getWatchpoint -> getWatchpointFunctions. + 2008-04-03 Phil Muldoon <pmuldoon@redhat.com> * WatchpointFunctions.java (readStatusRegister): Declare. diff --git a/frysk-core/frysk/isa/watchpoints/TestWatchpoint.java b/frysk-core/frysk/isa/watchpoints/TestWatchpoint.java index db52a10..b6f516b 100644 --- a/frysk-core/frysk/isa/watchpoints/TestWatchpoint.java +++ b/frysk-core/frysk/isa/watchpoints/TestWatchpoint.java @@ -51,13 +51,92 @@ import lib.dwfl.ElfSymbolVisibility; import lib.dwfl.SymbolBuilder; import frysk.config.Config; import frysk.dwfl.DwflCache; +import frysk.isa.signals.Signal; +import frysk.proc.Action; +import frysk.proc.Manager; import frysk.proc.Proc; import frysk.proc.Task; +import frysk.proc.TaskObserver; import frysk.testbed.DaemonBlockedAtEntry; import frysk.testbed.TestLib; + public class TestWatchpoint extends TestLib { + public void testWatchpointTrigger () { + if (unresolvedOnPPC(5991)) + return; + + DaemonBlockedAtEntry ackProc = new DaemonBlockedAtEntry( + Config.getPkgLibFile("funit-watchpoint")); + assertNotNull(ackProc); + + Proc proc = ackProc.getMainTask().getProc(); + Task task = proc.getMainTask(); + long address = getGlobalSymbolAddress(task,"source"); + + WatchpointObserver wpo = new WatchpointObserver(address,4); + task.requestAddWatchObserver(wpo, address, 4, true); + assertRunUntilStop("Add Observer"); + TerminatedObserver terminated = new TerminatedObserver(); + task.requestAddTerminatedObserver(terminated); + assertRunUntilStop("Add Observer"); + ackProc.requestUnblock(); + assertRunUntilStop("Test"); + } + + static class WatchpointObserver + implements TaskObserver.Watch + { + + long address; + int length; + + WatchpointObserver(long address, int length) { + this.address = address; + this.length = length; + + } + public Action updateHit(Task task, long address, int length) { + assertEquals("Triggered watchpoint address matches expected", this.address, address); + assertEquals("Triggered watchpoint length matches expected", this.length, length); + return Action.CONTINUE; + } + + public void addFailed(Object observable, Throwable w) { + fail("TaskOberer.Watch failed to be added to te task"); + } + + public void addedTo(Object observable) { + Manager.eventLoop.requestStop(); + } + + public void deletedFrom(Object observable) { + } + + } + + static class TerminatedObserver + implements TaskObserver.Terminated + { + + public void addFailed(Object observable, Throwable w) { + } + + public void addedTo(Object observable) { + Manager.eventLoop.requestStop(); + } + + public void deletedFrom(Object observable) { + } + + public Action updateTerminated(Task task, Signal signal, int value) { + Manager.eventLoop.requestStop(); + return Action.CONTINUE; + } + + } + public void testWatchFourBytesBitPattern() { // Test Four byte bit pattern in a cumulative fasion // across all WP registers. Assume global exact and @@ -69,7 +148,7 @@ public class TestWatchpoint extends TestLib { Task task = proc.getMainTask(); long address = getGlobalSymbolAddress(task,"source"); long debugControlRegister; - WatchpointFunctions wp = WatchpointFunctionFactory.getWatchpoint(task.getISA()); + WatchpointFunctions wp = WatchpointFunctionFactory.getWatchpointFunctions(task.getISA()); long savedDebugControlRegister = wp.readControlRegister(task); for (int i=0; i<4; i++) { @@ -122,7 +201,7 @@ public class TestWatchpoint extends TestLib { Task task = proc.getMainTask(); long address = getGlobalSymbolAddress(task,"source"); long debugControlRegister; - WatchpointFunctions wp = WatchpointFunctionFactory.getWatchpoint(task.getISA()); + WatchpointFunctions wp = WatchpointFunctionFactory.getWatchpointFunctions(task.getISA()); long savedDebugControlRegister = wp.readControlRegister(task); for (int i=0; i<4; i++) { @@ -177,7 +256,7 @@ public class TestWatchpoint extends TestLib { Task task = proc.getMainTask(); long address = getGlobalSymbolAddress(task,"source"); long debugControlRegister; - WatchpointFunctions wp = WatchpointFunctionFactory.getWatchpoint(task.getISA()); + WatchpointFunctions wp = WatchpointFunctionFactory.getWatchpointFunctions(task.getISA()); long savedDebugControlRegister = wp.readControlRegister(task); @@ -230,7 +309,7 @@ public class TestWatchpoint extends TestLib { Proc proc = giveMeABlockedProc(); Task task = proc.getMainTask(); long address = getGlobalSymbolAddress(task,"source"); - WatchpointFunctions wp = WatchpointFunctionFactory.getWatchpoint(task.getISA()); + WatchpointFunctions wp = WatchpointFunctionFactory.getWatchpointFunctions(task.getISA()); for (int i=0; i<wp.getWatchpointCount(); i++) wp.setWatchpoint(task, i, address, lengthSet[i], true); diff --git a/frysk-core/frysk/isa/watchpoints/WatchpointFunctionFactory.java b/frysk-core/frysk/isa/watchpoints/WatchpointFunctionFactory.java index bf8211f..da434ce 100644 --- a/frysk-core/frysk/isa/watchpoints/WatchpointFunctionFactory.java +++ b/frysk-core/frysk/isa/watchpoints/WatchpointFunctionFactory.java @@ -52,7 +52,7 @@ public class WatchpointFunctionFactory { .put(ISA.X8664, new X8664WatchpointFunctions()) ; - public static WatchpointFunctions getWatchpoint(ISA isa) { + public static WatchpointFunctions getWatchpointFunctions(ISA isa) { return (WatchpointFunctions) watchpointTables.get(isa); } } diff --git a/frysk-core/frysk/proc/live/ChangeLog b/frysk-core/frysk/proc/live/ChangeLog index fc1f503..2c1cacf 100644 --- a/frysk-core/frysk/proc/live/ChangeLog +++ b/frysk-core/frysk/proc/live/ChangeLog @@ -1,3 +1,25 @@ +2008-04-04 Phil Muldoon <pmuldoon@redhat.com> + + * LinuxPtraceProc.java (LinuxPtraceProc): Instatiate watchpoint + address manager. + (WatchpointAction): New. Install watchpoints. + (requestAddWatchObserver): Implement. + (requestDeleteWatchObserver): Ditto. + * WatchpointAddresses.java (proc): Store a proc, not a task. + (addWatchpoint): Take a length, and a write only flag. + (removeWatchpoint): Ditto. + (getWatchObservers): Ditto. + (getWatchpoint): Ditto. + * Watchpoint.java (Watchpoint): Take a task and a writeOnly flag. + (create): Ditto + (getLength): New. + (isWriteOnly): New. + (set): Actually set the watchpoint. + (reset): Delete the watchpoint. + * LinuxPtraceTaskState.java (Running.handleTrappedEvent): Add watchpoint + catch/test. + (Stepping.handleTrappedEvent): Ditto. + 2008-04-02 Phil Muldoon <pmuldoon@redhat.com> * LinuxPtraceProc.java (requestAddWatchObserver): Add writeOnly flag. @@ -9,8 +31,6 @@ (WatchpointAction): Delete. (requestAddWatchObserver): Delete private function. (requestDeleteWatchObserver): Delete private function. - - 2008-03-31 Stan Cox <scox@redhat.com> diff --git a/frysk-core/frysk/proc/live/LinuxPtraceProc.java b/frysk-core/frysk/proc/live/LinuxPtraceProc.java index 9f10c22..c4a6853 100644 --- a/frysk-core/frysk/proc/live/LinuxPtraceProc.java +++ b/frysk-core/frysk/proc/live/LinuxPtraceProc.java @@ -86,6 +86,7 @@ public class LinuxPtraceProc extends LiveProc { this.newState = LinuxPtraceProcState.initial(false); this.stat = stat; this.breakpoints = new BreakpointAddresses(this); + this.watchpoints = new WatchpointAddresses(this); ((LinuxPtraceHost)host).addProc(this); } @@ -97,6 +98,7 @@ public class LinuxPtraceProc extends LiveProc { super(task, fork); this.newState = LinuxPtraceProcState.initial(true); this.breakpoints = new BreakpointAddresses(this); + this.watchpoints = new WatchpointAddresses(this); ((LinuxPtraceHost)getHost()).addProc(this); } @@ -617,27 +619,105 @@ public class LinuxPtraceProc extends LiveProc { /** - * (Internal) Tell the process to add the specified Code + * Class describing the action to take on the suspended Task + * before adding or deleting a Code observer. + */ + final class WatchpointAction implements Runnable { + private final TaskObserver.Watch watch; + + private final Task task; + + private final long address; + + private final int length; + + private final boolean writeOnly; + + private final boolean addition; + + WatchpointAction(TaskObserver.Watch watch, Task task, long address, + int length, boolean writeOnly, boolean addition) { + this.watch = watch; + this.task = task; + this.address = address; + this.addition = addition; + this.length = length; + this.writeOnly = writeOnly; + + } + + public void run() { + if (addition) { + boolean mustInstall = watchpoints.addWatchpoint(watch, task, address, length, writeOnly); + if (mustInstall) { + Watchpoint watchpoint; + watchpoint = Watchpoint.create(address, length, writeOnly, task); + watchpoint.install(task); + } + } else { + boolean mustRemove = watchpoints.removeWatchpoint(watch, task, address, length, writeOnly); + if (mustRemove) { + Watchpoint watchpoint; + watchpoint = Watchpoint.create(address, length, writeOnly, task); + watchpoint.remove(task); + } + } + } + } + + + /** + * (Internal) Tell the process to add the specified Watch * Observation, attaching to the process if necessary. Adds a * TaskCodeObservation to the eventloop which instructs the task - * to install the breakpoint if necessary. + * to install the watchpoint if necessary. */ - void requestAddWatchObserver(Task task, TaskObservable observable, + void requestAddWatchObserver(final Task task, TaskObservable observable, TaskObserver.Watch observer, final long address, final int length, - boolean writeOnly) { + final boolean writeOnly) { + fine.log(this, "requestAddWatchObserver"); + WatchpointAction wpa = new WatchpointAction(observer, task, address, length, writeOnly, true); + TaskObservation to; + to = new TaskObservation((LinuxPtraceTask) task, observable, observer, wpa, true) { + public void execute() { + handleAddObservation(this); + } + public boolean needsSuspendedAction() { + return watchpoints.getWatchObservers(task, address, length, writeOnly) == null; + } + }; + Manager.eventLoop.add(to); + + } /** * (Internal) Tell the process to delete the specified Code * Observation, detaching from the process if necessary. */ - void requestDeleteWatchObserver(Task task, TaskObservable observable, + void requestDeleteWatchObserver(final Task task, TaskObservable observable, TaskObserver.Watch observer, final long address, final int length, - boolean writeOnly) { + final boolean writeOnly) { + + fine.log(this, "requestDeleteWatchObserver"); + WatchpointAction wpa = new WatchpointAction(observer, task, address, length, writeOnly, false); + TaskObservation to; + to = new TaskObservation((LinuxPtraceTask)task, observable, observer, wpa, false) { + public void execute() { + newState = oldState().handleDeleteObservation(LinuxPtraceProc.this, this); + } + + public boolean needsSuspendedAction() { + return watchpoints.getWatchObservers(task, address, length, writeOnly).size() == 1; + } + }; + + Manager.eventLoop.add(to); + } /** @@ -756,6 +836,7 @@ public class LinuxPtraceProc extends LiveProc { * XXX: Should not be public. */ public final BreakpointAddresses breakpoints; + public final WatchpointAddresses watchpoints; // List of available addresses for out of line stepping. // Used a lock in getOutOfLineAddress() and doneOutOfLine(). diff --git a/frysk-core/frysk/proc/live/LinuxPtraceTaskState.java b/frysk-core/frysk/proc/live/LinuxPtraceTaskState.java index 07c9bd5..c08ff72 100644 --- a/frysk-core/frysk/proc/live/LinuxPtraceTaskState.java +++ b/frysk-core/frysk/proc/live/LinuxPtraceTaskState.java @@ -41,6 +41,8 @@ package frysk.proc.live; import frysk.sys.SignalSet; import frysk.sys.proc.Status; +import frysk.isa.watchpoints.WatchpointFunctionFactory; +import frysk.isa.watchpoints.WatchpointFunctions; import frysk.proc.TaskObserver; import frysk.proc.Observer; import frysk.proc.Observable; @@ -942,9 +944,22 @@ abstract class LinuxPtraceTaskState extends State { LinuxPtraceTaskState handleTrappedEvent(LinuxPtraceTask task) { fine.log("handleTrappedEvent", task); + // First test if this is a watchpoint event. + WatchpointFunctions watchpointFunction = WatchpointFunctionFactory.getWatchpointFunctions(task.getISA()); + for (int i=0; i<watchpointFunction.getWatchpointCount(); i++) { + // Test if a watchpoint has fired + if (watchpointFunction.hasWatchpointTriggered(task, i)) { + frysk.isa.watchpoints.Watchpoint trigger = watchpointFunction.readWatchpoint(task, i); + int blockers = task.notifyWatchpoint(trigger.getAddress(), trigger.getRange()); + if (blockers == 0) + return sendContinue(task, Signal.NONE); + else + return blockedContinue; + } + } + Isa isa; isa = task.getIsaFIXME(); - // First see if this was just an indication the we stepped. // And see if we were stepping a breakpoint. Or whether we // installed a breakpoint at the address. Otherwise it is a @@ -1062,7 +1077,22 @@ abstract class LinuxPtraceTaskState extends State { */ LinuxPtraceTaskState handleTrappedEvent(LinuxPtraceTask task) { fine.log("handleTrappedEvent", task); - + + // First test if this is a watchpoint event. + WatchpointFunctions watchpointFunction = WatchpointFunctionFactory.getWatchpointFunctions(task.getISA()); + for (int i=0; i<watchpointFunction.getWatchpointCount(); i++) { + // Test if a watchpoint has fired + if (watchpointFunction.hasWatchpointTriggered(task, i)) { + frysk.isa.watchpoints.Watchpoint trigger = watchpointFunction.readWatchpoint(task, i); + int blockers = task.notifyWatchpoint(trigger.getAddress(), trigger.getRange()); + if (blockers == 0) + return sendContinue(task, Signal.NONE); + else + return blockedContinue; + } + } + + Isa isa; isa = task.getIsaFIXME(); diff --git a/frysk-core/frysk/proc/live/Watchpoint.java b/frysk-core/frysk/proc/live/Watchpoint.java index 7915d84..86d1e00 100644 --- a/frysk-core/frysk/proc/live/Watchpoint.java +++ b/frysk-core/frysk/proc/live/Watchpoint.java @@ -40,7 +40,9 @@ package frysk.proc.live; +import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import frysk.proc.Task; @@ -55,6 +57,7 @@ public class Watchpoint implements Comparable // These two fields define a Breakpoint private final long address; private final int length; + private final boolean writeOnly; private final Task task; @@ -67,7 +70,7 @@ public class Watchpoint implements Comparable * Private constructor called by create to record address and * proc. */ - private Watchpoint(long address, int length, Task task) + private Watchpoint(long address, int length, boolean writeOnly, Task task) { if (task == null) throw new NullPointerException("Cannot place a watchpoint when task == null."); @@ -75,7 +78,7 @@ public class Watchpoint implements Comparable this.address = address; this.task = task; this.length = length; - + this.writeOnly = writeOnly; if (this.length <= 0) throw new RuntimeException("Watchpoint length has to be > 0"); } @@ -86,9 +89,9 @@ public class Watchpoint implements Comparable * host type. If a Breakpoint for this address and proc is already * installed that Breakpoint will be returned. */ - public static Watchpoint create(long address, int length, Task task) + public static Watchpoint create(long address, int length, boolean writeOnly, Task task) { - Watchpoint watchpoint = new Watchpoint(address, length, task); + Watchpoint watchpoint = new Watchpoint(address, length, writeOnly, task); // If possible return an existing installed breakpoint. synchronized (installedWatchpoints) @@ -105,6 +108,15 @@ public class Watchpoint implements Comparable return address; } + public int getLength() + { + return length; + } + + public boolean isWriteOnly() + { + return writeOnly; + } /** * Installs breakpoint. Caller must make sure there is no breakpoint set @@ -130,16 +142,28 @@ public class Watchpoint implements Comparable */ private void set(Task task) { -// ByteBuffer buffer = ((LinuxPtraceTask)task).getRawMemory(); -// Isa isa = ((LinuxPtraceTask)task).getIsaFIXME(); -// Instruction bpInstruction = isa.getBreakpointInstruction(); -// -// origInstruction = isa.getInstruction(buffer, address); -// -// // Put in the breakpoint. -// byte[] bs = bpInstruction.getBytes(); -// buffer.position(address); -// buffer.put(bs); + // XXX: Need a get empty watchpoint locator. It's a bit + // much for the set() to find the empty watchpoint. Also + // question the value of optimizing at this point. + int watchpointIndex = -1; + frysk.isa.watchpoints.WatchpointFunctions wpf = + frysk.isa.watchpoints.WatchpointFunctionFactory. + getWatchpointFunctions(task.getISA()); + ArrayList watchpointList = (ArrayList) wpf.getAllWatchpoints(task); + Iterator i = watchpointList.iterator(); + while (i.hasNext()) { + frysk.isa.watchpoints.Watchpoint emptyTest = + ((frysk.isa.watchpoints.Watchpoint)i.next()); + if (emptyTest.getAddress() == 0) { + watchpointIndex = emptyTest.getRegister(); + break; hooks/post-receive -- frysk system monitor/debugger