Hi,
Here is a first try of adding breakpointing support. It works for the
attached 3 testcases which simply test that a process can be stopped,
Code observers can be added (and removed) and the updateHit() method is
called whenever the process hits the breakpoint address the Code
Observer is interested in.
It isn't integrated with the state machine yet. Which means it contains
some small hacks to force the Task into the right State at times. Adding
Code Observers is currently only supported in a Blocked state and
removing them only in the Running state. See the various XXX comments in
the patch. This also means there is no support yet for returning BLOCK
from Code.updateHit(). Even though it is clearly not finished I wanted
to post what I have to get some feedback.
The idea is as follows:
- A Proc will have a new field that holds the BreakpointAddresses.
(breakpoints are shared between all Tasks of a Proc)
- BreakpointAddresses keep track of the actual Code Observers interested
in an breakpoint address and request to Proc to add or remove them
when necessary.
- A Breakpoint holds some state necessary for resetting, stepping and
continuing. When you create a Breakpoint for a task on an address that
is already installed you will get that instance back so it is easy to
reset, step or continue it. Currently interaction between the
Task/Proc is not based on the TaskState, but it obviously should. For
now the process is forced to stop when necessary. This should be
handled by the state machine.
- There is only support for LinuxIa32 simple INT3 breakpoints for now.
But it should be easy to create subclasses for other architectures.
(With a little luck I will get my hands on a x86-64/em64t style
machine this week and will try adding support for that then.)
Currently the stepping/continuing isn't thread/Task-safe. If there
is another Task running while resetting the LinuxIa32Breakpoint it
might miss hitting it temporarily.
Here are the ChangeLog entries:
2006-07-19 Mark Wielaard <mark@klomp.org>
* frysk/proc/Breakpoint.java: New file.
* frysk/proc/BreakpointAddresses.java: New file.
* frysk/proc/DummyProc.java (removeBreakpoint): Dummy
implementation.
(addBreakpoint): Likewise.
* frysk/proc/LinuxIa32Breakpoint.java: New file.
* frysk/proc/LinuxProc.java (removeBreakpoint): New method.
(addBreakpoint): New method.
* frysk/proc/Proc.java (breakpoints): New field.
(Proc(ProcId,Proc,Host,Task): Initialize breakpoints.
(requestUpdateBreakpoints): New method.
(addBreakpoint): New method.
(removeBreakpoint): New method.
* frysk/proc/Task.java (codeObservers): New field.
(requestAddCodeObserver): New method.
(requestDeleteCodeObserver): New method.
(notifyCodeBreakpoint): New method.
* frysk/proc/TaskObserver.java (updateHit): Update description.
* frysk/proc/TaskState.java (running.handleTrappedEvent): New
Method.
* frysk/proc/TestBreakpoints.java: New test.
2006-07-19 Mark Wielaard <mark@klomp.org>
* funit-breakpoints.c: New file.
The testcase depends on the the ForkedProcess support I suggested:
http://sourceware.org/ml/frysk/2006-q3/msg00065.html
Let me know if that is a good idea to add. Otherwise I can rewrite my
testcases of course. But I rather don't :)
When running by hand they always PASS:
$ ./TestRunner frysk.proc.TestBreakpoints
Running testHitAndRun(frysk.proc.TestBreakpoints) ...PASS
Running testInsertRemove(frysk.proc.TestBreakpoints) ...PASS
Running testAddLots(frysk.proc.TestBreakpoints) ...PASS
Time: 1.057
OK (3 tests)
But that depends on the PtraceByteBuffer vs errno patch that I
suggested: http://sourceware.org/ml/frysk/2006-q3/msg00077.html
Otherwise you will get some spurious interrupted system call
RuntimeExceptions.
When run with 'make check' they intermittently fail. I haven't tracked
this down yet. But it might very well be because of timing and my
failure to properly integrate this yet with the rest of the state
machine. This is my next task.
Comments and suggestions welcome.
Cheers,
Mark