From f41667247d643ca379221e194d49ad65d1bf8527 Mon Sep 17 00:00:00 2001 From: Nurdin Premji Date: Tue, 29 Apr 2008 14:20:57 -0400 Subject: [PATCH] Stepping over signals --- frysk-core/frysk/hpd/StepCommand.java | 12 ++- frysk-core/frysk/rt/Breakpoint.java | 4 +- frysk-core/frysk/stepping/SteppingEngine.java | 87 ++++++++++++++-- frysk-core/frysk/stepping/TaskStepEngine.java | 7 +- frysk-core/frysk/stepping/TestStepping.java | 112 +++++++++++++++++++++ frysk-core/frysk/stepping/TestSteppingEngine.java | 3 +- 6 files changed, 204 insertions(+), 21 deletions(-) diff --git a/frysk-core/frysk/hpd/StepCommand.java b/frysk-core/frysk/hpd/StepCommand.java index a8cc3c0..7cd854e 100644 --- a/frysk-core/frysk/hpd/StepCommand.java +++ b/frysk-core/frysk/hpd/StepCommand.java @@ -60,10 +60,17 @@ public class StepCommand extends ParameterizedCommand { ((Options)options).instruction = true; } }); + + add(new CommandOption("stepoversignal", 's', "step over signals", null) { + void parse(String argument, Object options) { + ((Options) options).stepOverSignal = true; + } + }); } private class Options { boolean instruction = false; + boolean stepOverSignal = false; } Object options() { @@ -79,7 +86,10 @@ public class StepCommand extends ParameterizedCommand { taskList.add(taskIter.next()); } if (cli.steppingObserver != null) { - + if (((Options) options).stepOverSignal == true) { + cli.getSteppingEngine().setStepOverSignal(true); + } + if (((Options) options).instruction == false) { fine.log(this, "Stepping line"); cli.getSteppingEngine().stepLine(taskList); diff --git a/frysk-core/frysk/rt/Breakpoint.java b/frysk-core/frysk/rt/Breakpoint.java index f6214f4..74d0414 100644 --- a/frysk-core/frysk/rt/Breakpoint.java +++ b/frysk-core/frysk/rt/Breakpoint.java @@ -83,7 +83,6 @@ public class Breakpoint implements TaskObserver.Code { else { fine.log(this, "updateHit adding instruction observer", task, "address", address); - this.steppingEngine.blockedByActionPoint(task, this); task.requestUnblock(this); } @@ -107,7 +106,8 @@ public class Breakpoint implements TaskObserver.Code { monitor.notifyAll(); } // System.err.println("BreakPoint.addedTo"); - ((Task) observable).requestDeleteInstructionObserver(this.steppingEngine.getSteppingObserver()); + Task task = (Task) observable; + this.steppingEngine.requestRemoveSteppingObserver(task); } public boolean isAdded () { diff --git a/frysk-core/frysk/stepping/SteppingEngine.java b/frysk-core/frysk/stepping/SteppingEngine.java index c380dd3..13a5ec3 100644 --- a/frysk-core/frysk/stepping/SteppingEngine.java +++ b/frysk-core/frysk/stepping/SteppingEngine.java @@ -53,6 +53,7 @@ import frysk.sys.ProcessIdentifier; import frysk.sys.ProcessIdentifierFactory; import lib.dwfl.DwflLine; import frysk.debuginfo.DebugInfoFrame; +import frysk.debuginfo.DebugInfoStackFactory; import frysk.event.RequestStopEvent; import frysk.proc.Action; import frysk.proc.Manager; @@ -96,6 +97,18 @@ public class SteppingEngine { /* Observer used to block Tasks, as well as providing the mechanism to * step them, by an instruction each time. */ private SteppingObserver steppingObserver; + + public void requestAddSteppingObserver(Task task) + { + task.requestAddInstructionObserver(steppingObserver); + task.requestAddSignaledObserver(steppingObserver); + } + + public void requestRemoveSteppingObserver(Task task) + { + task.requestDeleteInstructionObserver(steppingObserver); + task.requestDeleteSignaledObserver(steppingObserver); + } /* Ensures that newly spawned Tasks are maintained by the SteppingEngine * class, and also makes sure that exiting Tasks are taken care of and cleaned @@ -448,6 +461,26 @@ public class SteppingEngine { this.steppingObserver.notifyNotBlocked(tse); } } + + public void stepOverSignal(Task task) { + DebugInfoFrame frame = DebugInfoStackFactory + .createDebugInfoStackTrace(task); + + long address = frame.getAddress(); + + fine.log(this, "Looking for address: 0x", Long.toHexString(address), "Line #: ", frame.getLine().getLine()); + + TaskStepEngine tse = (TaskStepEngine) this.taskStateMap.get(task); + tse.setState(new StepOutState(task)); + this.steppingObserver.notifyNotBlocked(tse); + + int i = ((Integer) this.contextMap.get(task.getProc())).intValue(); + this.contextMap.put(task.getProc(), new Integer(++i)); + + this.breakpoint = new SteppingBreakpoint(this, address); + this.breakpointMap.put(task, this.breakpoint); + task.requestAddCodeObserver(this.breakpoint, address); + } /** * Performs a step-over operation on a list of tasks; none of the given @@ -479,6 +512,13 @@ public class SteppingEngine { } } } + + + private boolean stepOverSignal = false; + public void setStepOverSignal(boolean bol) { + fine.log(this, "Setting stepOverSignal"); + stepOverSignal = bol; + } /** * Sets the stage for stepping out of a frame. Runs until a breakpoint on the @@ -596,7 +636,7 @@ public class SteppingEngine { this.steppingObserver.notifyNotBlocked(tse); } continueForStepping(t, false); - t.requestDeleteInstructionObserver(this.steppingObserver); + requestRemoveSteppingObserver(t); } } } @@ -715,7 +755,8 @@ public class SteppingEngine { tse = (TaskStepEngine) this.taskStateMap.get(t); tse.setState(new RunningState(t)); this.steppingObserver.notifyNotBlocked(tse); - t.requestDeleteInstructionObserver(this.steppingObserver); + + requestRemoveSteppingObserver(t); } return; } else @@ -735,7 +776,7 @@ public class SteppingEngine { tse = (TaskStepEngine) this.taskStateMap.get(t); tse.setState(new RunningState(t)); this.steppingObserver.notifyNotBlocked(tse); - t.requestDeleteInstructionObserver(this.steppingObserver); + requestRemoveSteppingObserver(t); } else { /* Put all threads back into a master list */ temp.add(t); @@ -829,7 +870,7 @@ public class SteppingEngine { t.requestDeleteTerminatingObserver(this.threadLifeObservable); t.requestDeleteTerminatedObserver(this.threadLifeObservable); t.requestDeleteClonedObserver(this.threadLifeObservable); - t.requestDeleteInstructionObserver(this.steppingObserver); + requestRemoveSteppingObserver(t); cleanTask(t); } } @@ -895,7 +936,8 @@ public class SteppingEngine { public SteppingObserver getSteppingObserver() { return this.steppingObserver; } - + + /** * Sets a SteppingBreakpoint on the given Task at the given address. * @@ -990,7 +1032,7 @@ public class SteppingEngine { // Requests the addition of the stepping observer to task if // not inserted already. if (!(task.isInstructionObserverAdded(this.steppingObserver))) { - task.requestAddInstructionObserver(this.steppingObserver); + requestAddSteppingObserver(task); } // Add the observer to the task's blockers list @@ -1053,7 +1095,7 @@ public class SteppingEngine { } protected class SteppingObserver extends Observable implements - TaskObserver.Instruction { + TaskObserver.Instruction, TaskObserver.Signaled{ /** * Callback for TaskObserver.Instruction. Each time a Task is blocked, either @@ -1069,6 +1111,14 @@ public class SteppingEngine { * @return Action.BLOCK Continue blocking this incoming Task */ public synchronized Action updateExecuted(Task task) { + + DebugInfoFrame frame = DebugInfoStackFactory + .createDebugInfoStackTrace(task); + + long address = frame.getAddress(); + + fine.log(this, "At address: 0x", Long.toHexString(address), "Line #: ", frame.getLine().getLine(), "stepOverSignal set to: " + stepOverSignal); + // System.err.println("SE.SO.updateEx: " + task); /* Check to see if acting upon this event produces a stopped state * change. If so, decrement the number of Tasks active in the Task's @@ -1131,6 +1181,19 @@ public class SteppingEngine { this.setChanged(); this.notifyObservers(tse); } + + public Action updateSignaled(Task task, Signal signal) { + fine.log(this, "updateSignaled called"); + if (stepOverSignal) { + fine.log(this, "updateSignaled, stepping over"); + + requestRemoveSteppingObserver(task); + stepOverSignal(task); + fine.log(this, "finished step over signal"); + return Action.BLOCK; + } + return Action.CONTINUE; + } } public void requestAdd() { @@ -1157,7 +1220,7 @@ public class SteppingEngine { Iterator i = list.iterator(); while (i.hasNext()) { t = (Task) i.next(); - t.requestAddInstructionObserver(this.steppingObserver); + requestAddSteppingObserver(t); } } @@ -1189,8 +1252,8 @@ public class SteppingEngine { offspring, SteppingEngine.this)); SteppingEngine.this.threadsList.addLast(offspring); - offspring.requestAddInstructionObserver(SteppingEngine.this.steppingObserver); - + requestAddSteppingObserver(offspring); + offspring.requestAddClonedObserver(this); offspring.requestAddTerminatingObserver(this); offspring.requestAddTerminatedObserver(this); @@ -1329,7 +1392,7 @@ public class SteppingEngine { addy = address; fine.log(this, "updateHit task", task, "address", address, "adding instruction observer"); - task.requestAddInstructionObserver(SteppingEngine.this.steppingObserver); + requestAddSteppingObserver(task); } ++triggered; @@ -1353,7 +1416,7 @@ public class SteppingEngine { } Task t = (Task) observable; - t.requestDeleteInstructionObserver(steppingObserver); + requestRemoveSteppingObserver(t); continueForStepping(t, false); } diff --git a/frysk-core/frysk/stepping/TaskStepEngine.java b/frysk-core/frysk/stepping/TaskStepEngine.java index be1cf4b..9120fd5 100644 --- a/frysk-core/frysk/stepping/TaskStepEngine.java +++ b/frysk-core/frysk/stepping/TaskStepEngine.java @@ -183,17 +183,16 @@ public class TaskStepEngine { } /** - * Returns the current State of this TaskStepEngine's Task. + * Sets the current State of this TaskStepEngine's Task. * - * @param newState - * The current State of this TaskStepEngine's Task + * @param newState The new State of this TaskStepEngine's Task */ public void setState(State newState) { this.state = newState; } /** - * Sets the current State of this TaskStepEngine's Task. + * Returns the current State of this TaskStepEngine's Task. * * @return state The current State of this TaskStepEngine's Task. */ diff --git a/frysk-core/frysk/stepping/TestStepping.java b/frysk-core/frysk/stepping/TestStepping.java index 188a27f..ca069e8 100644 --- a/frysk-core/frysk/stepping/TestStepping.java +++ b/frysk-core/frysk/stepping/TestStepping.java @@ -49,9 +49,11 @@ import frysk.testbed.SynchronizedOffspring; import frysk.config.Prefix; import frysk.debuginfo.DebugInfoFrame; import frysk.debuginfo.DebugInfoStackFactory; +import frysk.proc.Action; import frysk.proc.Manager; import frysk.proc.Proc; import frysk.proc.Task; +import frysk.proc.TaskObserver.Terminated; import frysk.rt.BreakpointManager; import frysk.rt.LineBreakpoint; import frysk.rt.SourceBreakpoint; @@ -134,6 +136,9 @@ public class TestStepping extends TestLib { assertTrue("Line information present", frame.getLine() != SourceLocation.UNKNOWN); /** The stepping operation */ + + //Send a signal to myTask + this.se.stepLine(theTask); this.testStarted = true; @@ -431,6 +436,112 @@ public class TestStepping extends TestLib { assertRunUntilStop("Running test"); cleanup(); } + + public void testStepThroughSignal() { + /** Variable setup */ + + File source = Prefix.sourceFile("frysk-core/frysk/pkglibdir/funit-signal.c"); + + this.scanner = new TestfileTokenScanner(source); + + /* The line number where the test begins */ + int start = this.scanner.findTokenLine("_signalRaiseCall_"); + + /* The line number the test should end up at */ + int end = this.scanner.findTokenLine("_signalHandlerEntry_"); + + /* The test process */ + SynchronizedOffspring process + = new SynchronizedOffspring(Signal.USR1, + new String[] { + getExecPath("funit-signal"), + Integer.toString(Pid.get().intValue()), + Integer.toString(Signal.USR1.intValue()) + }); + this.testStarted = false; + + /** Test initialization */ + Task myTask = initTask(process, source, start, end); + + this.currentTest = new AssertLine(end, myTask); + + DebugInfoFrame frame = DebugInfoStackFactory + .createDebugInfoStackTrace(myTask); + assertTrue("Line information present", frame.getLine() != SourceLocation.UNKNOWN); + + /** The stepping operation */ + this.se.stepLine(myTask); + + this.testStarted = true; + + /** Run to completion */ + assertRunUntilStop("Running test"); + cleanup(); + } + + public void testStepOverSignal() { + /** Variable setup */ + + File source = Prefix.sourceFile("frysk-core/frysk/pkglibdir/funit-signal.c"); + + this.scanner = new TestfileTokenScanner(source); + + /* The line number where the test begins */ + int start = this.scanner.findTokenLine("_signalRaiseCall_"); + + /* The test process */ + SynchronizedOffspring process + = new SynchronizedOffspring(Signal.USR1, + new String[] { + getExecPath("funit-signal"), + Integer.toString(Pid.get().intValue()), + Integer.toString(Signal.USR1.intValue()) + }); + this.testStarted = false; + + /** Test initialization */ + Task myTask = initTask(process, source, start, start); + + myTask.requestAddTerminatedObserver(new Terminated(){ + + public Action updateTerminated(Task task, + frysk.isa.signals.Signal signal, int value) { + // TODO Auto-generated method stub + return null; + } + + public void addFailed(Object observable, Throwable w) { + // TODO Auto-generated method stub + + } + + public void addedTo(Object observable) { + // TODO Auto-generated method stub + + } + + public void deletedFrom(Object observable) { + // TODO Auto-generated method stub + + }}); + + this.se.setStepOverSignal(true); + + this.currentTest = new AssertLine(start, myTask); + + DebugInfoFrame frame = DebugInfoStackFactory + .createDebugInfoStackTrace(myTask); + assertTrue("Line information present", frame.getLine() != SourceLocation.UNKNOWN); + + /** The stepping operation */ + this.se.stepLine(myTask); + + this.testStarted = true; + + /** Run to completion */ + assertRunUntilStop("Running test"); + cleanup(); + } public void testASMSingleStep() { @@ -1125,6 +1236,7 @@ public class TestStepping extends TestLib { DebugInfoFrame frame = DebugInfoStackFactory .createDebugInfoStackTrace(task); int lineNr = frame.getLine().getLine(); + assertEquals("line number", success, lineNr); Manager.eventLoop.requestStop(); } diff --git a/frysk-core/frysk/stepping/TestSteppingEngine.java b/frysk-core/frysk/stepping/TestSteppingEngine.java index bbe5ad1..62ce036 100644 --- a/frysk-core/frysk/stepping/TestSteppingEngine.java +++ b/frysk-core/frysk/stepping/TestSteppingEngine.java @@ -330,8 +330,7 @@ public class TestSteppingEngine extends TestLib { assertTrue("Line information present", frame.getLine() != SourceLocation.UNKNOWN); /** The stepping operation */ - this.se.stepOver(theTask, DebugInfoStackFactory - .createDebugInfoStackTrace(theTask)); + this.se.stepOver(theTask, frame); this.testStarted = true; // System.err.println("waiting for finish"); -- 1.5.4.1