public inbox for frysk@sourceware.org
 help / color / mirror / Atom feed
From: Nurdin Premji <npremji@redhat.com>
To: frysk@sourceware.org
Subject: [patch] initial attempt at getting step over signal working
Date: Sat, 12 Apr 2008 22:24:00 -0000	[thread overview]
Message-ID: <48012313.4000403@redhat.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 255 bytes --]

Hello everyone,

Attached is some initial work in trying to get stepping over signal 
working. It doesn't work yet as there seems to be a big race conditon. ( 
I managed to run it once and have it succeed, but all subsequent runs fail)

Thank you,
Nurdin

[-- Attachment #2: 0001-Initial-work-on-stepping-over-signal.patch --]
[-- Type: text/x-patch, Size: 18349 bytes --]

From a76ea826a50f9ce025b2935476c72b7e134fef25 Mon Sep 17 00:00:00 2001
From: Nurdin Premji <npremji@localhost.localdomain>
Date: Sat, 12 Apr 2008 16:54:14 -0400
Subject: [PATCH] Initial work on stepping over signal

---
 frysk-core/frysk/hpd/StepCommand.java             |   12 ++-
 frysk-core/frysk/pkglibdir/funit-signal.c         |  130 +++++++++++++++++++++
 frysk-core/frysk/rt/Breakpoint.java               |    5 +-
 frysk-core/frysk/stepping/SteppingEngine.java     |   83 ++++++++++++--
 frysk-core/frysk/stepping/TaskStepEngine.java     |    7 +-
 frysk-core/frysk/stepping/TestStepping.java       |   89 ++++++++++++++
 frysk-core/frysk/stepping/TestSteppingEngine.java |    3 +-
 7 files changed, 310 insertions(+), 19 deletions(-)
 create mode 100644 frysk-core/frysk/pkglibdir/funit-signal.c

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/pkglibdir/funit-signal.c b/frysk-core/frysk/pkglibdir/funit-signal.c
new file mode 100644
index 0000000..e2f11fd
--- /dev/null
+++ b/frysk-core/frysk/pkglibdir/funit-signal.c
@@ -0,0 +1,130 @@
+// This file is part of the program FRYSK.
+//
+// Copyright 2008, Red Hat Inc.
+//
+// FRYSK is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// FRYSK is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with FRYSK; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+// 
+// In addition, as a special exception, Red Hat, Inc. gives You the
+// additional right to link the code of FRYSK with code not covered
+// under the GNU General Public License ("Non-GPL Code") and to
+// distribute linked combinations including the two, subject to the
+// limitations in this paragraph. Non-GPL Code permitted under this
+// exception must only link to the code of FRYSK through those well
+// defined volatile interfaces identified in the file named EXCEPTION found in
+// the source code files (the "Approved volatile interfaces"). The files of
+// Non-GPL Code may instantiate templates or use macros or inline
+// functions from the Approved volatile interfaces without causing the
+// resulting work to be covered by the GNU General Public
+// License. Only Red Hat, Inc. may make changes or additions to the
+// list of Approved volatile interfaces. You must obey the GNU General Public
+// License in all respects for all of the FRYSK code and other code
+// used in conjunction with FRYSK except the Non-GPL Code covered by
+// this exception. If you modify this file, you may extend this
+// exception to your version of the file, but you are not obligated to
+// do so. If you do not wish to provide this exception without
+// modification, you must delete this exception statement from your
+// version and license this file solely under the GPL without
+// exception.
+
+#include <signal.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <errno.h>
+
+pthread_t tester_thread;
+
+
+volatile int j = 0;
+volatile int lock = 1;
+volatile int sig;
+volatile pid_t pid;
+
+void
+*signal_parent ()
+{
+	while (lock);
+
+	kill (pid, sig);
+
+	while(1);
+}
+
+void
+handler (int sig)
+{
+
+	if (sig == SIGUSR1)							// _signalHandlerEntry_
+	{
+		--j;
+		++j;
+	}
+	else
+		exit(EXIT_FAILURE);
+
+	return;
+	
+}
+
+int
+main (int argc, char ** argv)
+{
+
+	if (argc < 3)
+	{
+		printf("Usage: funit-signal <pid> <signal>\n");
+		exit(0);
+	}
+
+	errno = 0;
+	pid_t target_pid = (pid_t) strtoul(argv[1], (char **) NULL, 10);
+	if (errno)
+	{
+		perror ("Invalid pid");
+		exit (EXIT_FAILURE);
+	}
+
+	errno = 0;
+	int signal = (int) strtoul (argv[2], (char **) NULL, 10);
+	if (errno)
+	{
+		perror ("Invalid signal");
+	exit (EXIT_FAILURE);
+	}
+
+	pid = target_pid;
+	sig = signal;
+
+	struct sigaction sa;
+	sa.sa_handler = handler;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = SA_RESTART;
+	sigaction(SIGUSR1, &sa, NULL);
+
+	pthread_create (&tester_thread, NULL, signal_parent, NULL);
+
+	lock = 0;
+
+	while(1) 
+	{
+		--j;
+		++j;
+		--j;
+		++j;
+		raise(SIGUSR1);  						// _signalRaiseCall_
+	}	
+	return 0;
+
+}
diff --git a/frysk-core/frysk/rt/Breakpoint.java b/frysk-core/frysk/rt/Breakpoint.java
index 4066f6e..850bbb6 100644
--- a/frysk-core/frysk/rt/Breakpoint.java
+++ b/frysk-core/frysk/rt/Breakpoint.java
@@ -83,7 +83,7 @@ public class Breakpoint implements TaskObserver.Code {
         else {
 	    fine.log(this, "updateHit adding instruction observer", task,
 		     "address", address);
-            task.requestAddInstructionObserver(this.steppingEngine.getSteppingObserver());
+	    this.steppingEngine.requestAddSteppingObserver(task);
             this.steppingEngine.addBlocker(task, this);
         }
 
@@ -106,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 7ff86f1..c505407 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);
 	}
     }
@@ -1026,7 +1067,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
@@ -1042,6 +1083,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());
+	    
 	    //       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 
@@ -1104,6 +1153,20 @@ 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() {
@@ -1130,7 +1193,7 @@ public class SteppingEngine {
 	Iterator i = list.iterator();
 	while (i.hasNext()) {
 	    t = (Task) i.next();
-	    t.requestAddInstructionObserver(this.steppingObserver);
+	   requestAddSteppingObserver(t);
 	}
     }
 
@@ -1162,8 +1225,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);
@@ -1302,7 +1365,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;
@@ -1326,7 +1389,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 b14c4f3..059a7c6 100644
--- a/frysk-core/frysk/stepping/TestStepping.java
+++ b/frysk-core/frysk/stepping/TestStepping.java
@@ -135,6 +135,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;
@@ -443,6 +446,91 @@ public class TestStepping extends TestLib {
 	assertRunUntilStop("Running test");
 	cleanup();
     }
+    
+    public void testStepThroughSignal() {
+	/** Variable setup */
+
+	String source = Config.getRootSrcDir()
+	    + "frysk-core/frysk/pkglibdir/funit-signal.c";
+
+	this.scanner = new TestfileTokenScanner(new File(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 */
+
+	String source = Config.getRootSrcDir()
+	    + "frysk-core/frysk/pkglibdir/funit-signal.c";
+
+	this.scanner = new TestfileTokenScanner(new File(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);
+
+	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() {
 
@@ -1151,6 +1239,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 af0da7f..e4e49d3 100644
--- a/frysk-core/frysk/stepping/TestSteppingEngine.java
+++ b/frysk-core/frysk/stepping/TestSteppingEngine.java
@@ -335,8 +335,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


                 reply	other threads:[~2008-04-12 21:01 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=48012313.4000403@redhat.com \
    --to=npremji@redhat.com \
    --cc=frysk@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).