public inbox for frysk-cvs@sourceware.org
help / color / mirror / Atom feed
From: pmuldoon@sourceware.org
To: frysk-cvs@sourceware.org
Subject: [SCM]  master: Add watchpoint interfaces.
Date: Wed, 20 Feb 2008 10:46:00 -0000	[thread overview]
Message-ID: <20080220104622.3044.qmail@sourceware.org> (raw)

The branch, master has been updated
       via  a698552443da8465f68ad185f7760ef1c9dcdf2a (commit)
      from  312f766777c680ddc21a09ef364283882e1cfdac (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit a698552443da8465f68ad185f7760ef1c9dcdf2a
Author: Phil Muldoon <pmuldoon@redhat.com>
Date:   Wed Feb 20 10:46:12 2008 +0000

    Add watchpoint interfaces.
    
    2008-02-20  Phil Muldoon  <pmuldoon@redhat.com>
    
            * TaskObserver.java: Add watch interface.
    
    2008-02-20  Phil Muldoon  <pmuldoon@redhat.com>
    
            * LinuxPtraceProc.java (requestAddWatchObservers): New.
            (requestDeleteWatchObserver): New.
            * LinuxPtraceTask.java (requestAddWatchObservers): New.
            (requestDeleteWatchObserver): New.
            * Watchpoint.java: New.
            * WatchpointAddresses.java: New.

-----------------------------------------------------------------------

Summary of changes:
 frysk-core/frysk/proc/ChangeLog                    |    5 +
 frysk-core/frysk/proc/TaskObserver.java            |   12 +
 frysk-core/frysk/proc/live/ChangeLog               |    9 +
 frysk-core/frysk/proc/live/LinuxPtraceProc.java    |   26 +++-
 frysk-core/frysk/proc/live/LinuxPtraceTask.java    |  116 ++++++++++
 frysk-core/frysk/proc/live/Watchpoint.java         |  229 ++++++++++++++++++++
 ...ointAddresses.java => WatchpointAddresses.java} |   62 +++----
 7 files changed, 421 insertions(+), 38 deletions(-)
 create mode 100644 frysk-core/frysk/proc/live/Watchpoint.java
 copy frysk-core/frysk/proc/live/{BreakpointAddresses.java => WatchpointAddresses.java} (80%)

First 500 lines of diff:
diff --git a/frysk-core/frysk/proc/ChangeLog b/frysk-core/frysk/proc/ChangeLog
index 260a1b0..d0e9ac2 100644
--- a/frysk-core/frysk/proc/ChangeLog
+++ b/frysk-core/frysk/proc/ChangeLog
@@ -1,3 +1,8 @@
+2008-02-20  Phil Muldoon  <pmuldoon@redhat.com>
+
+	* TaskObserver.java: Add watch interface.
+
+
 2008-02-14  Andrew Cagney  <cagney@redhat.com>
 
 	* Proc.java (pid): New; Pass to constructors.
diff --git a/frysk-core/frysk/proc/TaskObserver.java b/frysk-core/frysk/proc/TaskObserver.java
index 2371e8a..14f47d6 100644
--- a/frysk-core/frysk/proc/TaskObserver.java
+++ b/frysk-core/frysk/proc/TaskObserver.java
@@ -212,6 +212,18 @@ public interface TaskObserver
       Action updateHit (Task task, long address);
     }
 
+    public interface Watch
+	extends TaskObserver
+    {
+	/**
+	 * The task has hit the breakpoint.  Return Action.BLOCK to
+	 * block the task's further execution.  Note that all Tasks of
+	 * a Proc share their breakpoints, so this method needs to
+	 * check the actual Task that got hit.
+	 */ 
+      Action updateHit (Task task, long address);
+    }
+
     /**
      * Interface used to notify of a Task that has has been attached,
      * and is about to resume execution in that state.  Only after a
diff --git a/frysk-core/frysk/proc/live/ChangeLog b/frysk-core/frysk/proc/live/ChangeLog
index 7647a09..f38b01c 100644
--- a/frysk-core/frysk/proc/live/ChangeLog
+++ b/frysk-core/frysk/proc/live/ChangeLog
@@ -1,3 +1,12 @@
+2008-02-20  Phil Muldoon  <pmuldoon@redhat.com>
+
+	* LinuxPtraceProc.java (requestAddWatchObservers): New.
+	(requestDeleteWatchObserver): New.
+	* LinuxPtraceTask.java (requestAddWatchObservers): New.
+	(requestDeleteWatchObserver): New.
+	* Watchpoint.java: New.
+	* WatchpointAddresses.java: New.
+
 2008-02-19  Andrew Cagney  <cagney@redhat.com>
 
 	* IsaFactory.java: Update to match lib.dwfl.
diff --git a/frysk-core/frysk/proc/live/LinuxPtraceProc.java b/frysk-core/frysk/proc/live/LinuxPtraceProc.java
index 6f59dd0..87c366a 100644
--- a/frysk-core/frysk/proc/live/LinuxPtraceProc.java
+++ b/frysk-core/frysk/proc/live/LinuxPtraceProc.java
@@ -597,6 +597,30 @@ public class LinuxPtraceProc extends LiveProc {
 	Manager.eventLoop.add(to);
     }
 
+    
+
+    /**
+     * (Internal) Tell the process to add the specified Code
+     * Observation, attaching to the process if necessary. Adds a
+     * TaskCodeObservation to the eventloop which instructs the task
+     * to install the breakpoint if necessary.
+     */
+    void requestAddWatchObserver(Task task, TaskObservable observable,
+				TaskObserver.Watch observer,
+				final long address,
+				final int length) {
+    }
+
+    /**
+     * (Internal) Tell the process to delete the specified Code
+     * Observation, detaching from the process if necessary.
+     */
+    void requestDeleteWatchObserver(Task task, TaskObservable observable,
+				   TaskObserver.Watch observer,
+				   final long address,
+				   final int length)    {
+    }
+
     /**
      * Class describing the action to take on the suspended Task
      * before adding or deleting an Instruction observer. No
@@ -680,7 +704,7 @@ public class LinuxPtraceProc extends LiveProc {
      * XXX: Should not be public.
      */
     public final BreakpointAddresses breakpoints;
-
+    
     // List of available addresses for out of line stepping.
     // Used a lock in getOutOfLineAddress() and doneOutOfLine().
     private final ArrayList outOfLineAddresses = new ArrayList();
diff --git a/frysk-core/frysk/proc/live/LinuxPtraceTask.java b/frysk-core/frysk/proc/live/LinuxPtraceTask.java
index 5f86dd6..40e14b5 100644
--- a/frysk-core/frysk/proc/live/LinuxPtraceTask.java
+++ b/frysk-core/frysk/proc/live/LinuxPtraceTask.java
@@ -82,6 +82,7 @@ public class LinuxPtraceTask extends LiveTask {
 	super(proc, pid);
 	((LinuxPtraceHost)proc.getHost()).putTask(tid, this);
 	newState = LinuxPtraceTaskState.detachedState();
+	this.watchpoints = new WatchpointAddresses(this);
     }
     /**
      * Create a new attached clone of Task.
@@ -91,6 +92,7 @@ public class LinuxPtraceTask extends LiveTask {
 	super(task, clone);
 	((LinuxPtraceHost)getProc().getHost()).putTask(tid, this);
 	newState = LinuxPtraceTaskState.clonedState(((LinuxPtraceTask)task).getState ());
+	this.watchpoints = new WatchpointAddresses(this);
     }
     /**
      * Create a new attached main Task of Proc.
@@ -109,6 +111,8 @@ public class LinuxPtraceTask extends LiveTask {
 		};
 	    proc.handleAddObservation(ob);
 	}
+	this.watchpoints = new WatchpointAddresses(this);
+
     }
 
     /**
@@ -519,6 +523,23 @@ public class LinuxPtraceTask extends LiveTask {
 	return blockers.size();
     }
     /**
+     * Add a TaskObserver.Watch observer
+     * (hardware only)
+     */
+    public void requestAddWatchObserver(TaskObserver.Watch o, long address, int length) {
+	fine.log(this,"requestAddWatchObserver");
+	requestAddWatchObserver(this, codeObservers, o, address, length);
+    }
+
+    /**
+     * Delete TaskObserver.Code for the TaskObserver pool.
+     */
+    public void requestDeleteWatchObserver(TaskObserver.Watch o, long address, int length) {
+	fine.log(this, "requestDeleteWatcheObserver");
+	requestDeleteWatchObserver(this, codeObservers, o, address, length);
+    }
+
+    /**
      * Add a TaskObserver.Cloned observer.
      */
     public void requestAddClonedObserver(TaskObserver.Cloned o) {
@@ -856,6 +877,101 @@ public class LinuxPtraceTask extends LiveTask {
 	}
 	return blockers.size();
     }
+    
+    /**
+     * Class describing the action to take on the suspended Task
+     * before adding or deleting a Watchpoint 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 addition;
+
+	WatchpointAction(TaskObserver.Watch watch, Task task, long address, int length,
+			 boolean addition) {
+	    this.watch = watch;
+	    this.task = task;
+	    this.address = address;
+	    this.addition = addition;
+	    this.length = length;
+	}
+
+	public void run() {
+	    if (addition) {
+		boolean mustInstall = watchpoints.addBreakpoint(watch, address, length);
+		if (mustInstall) {
+		    Watchpoint watchpoint;
+		    watchpoint = Watchpoint.create(address, length, LinuxPtraceTask.this);
+		    watchpoint.install(task);
+		}
+	    } else {
+		boolean mustRemove = watchpoints.removeBreakpoint(watch, address, length);
+		if (mustRemove) {
+		    Watchpoint watchpoint;
+		    watchpoint = Watchpoint.create(address, length, LinuxPtraceTask.this);
+		    watchpoint.remove(task);
+		}
+	    }
+	}
+    }
+
+    public final WatchpointAddresses watchpoints;
+
+    /**
+     * (Internal) Tell the task to add the specified Watchpoint
+     * observation, attaching to the task if necessary. Adds a
+     * TaskCodeObservation to the eventloop which instructs the task
+     * to install the breakpoint if necessary.
+     */
+    void requestAddWatchObserver(Task task, TaskObservable observable,
+				TaskObserver.Watch observer,
+				final long address,
+				final int length) {
+	WatchpointAction watchAction = new WatchpointAction(observer, task, address, length, true);
+	TaskObservation to;
+	to = new TaskObservation((LinuxPtraceTask) task, observable, observer,
+				 watchAction, true) {
+		public void execute() {
+		    handleAddObservation(this);
+		}
+		public boolean needsSuspendedAction() {
+		    return watchpoints.getCodeObservers(address, length) == null;
+		}
+	    };
+	Manager.eventLoop.add(to);
+    }
+
+    /**
+     * (Internal) Tell the process to delete the specified Watchpoint
+     * observation, detaching from the process if necessary.
+     */
+    void requestDeleteWatchObserver(Task task, TaskObservable observable,
+				   TaskObserver.Watch observer,
+				   final long address,
+				   final int length)    {
+	WatchpointAction watchAction = new WatchpointAction(observer, task, address, length, false);
+	TaskObservation to;
+	to = new TaskObservation((LinuxPtraceTask)task, observable, observer, 
+				 watchAction, false) {
+		public void execute() {
+		    newState = oldState().handleDeleteObservation(LinuxPtraceTask.this, this);
+		}
+
+		public boolean needsSuspendedAction() {
+		    return watchpoints.getCodeObservers(address, length).size() == 1;
+		}
+	    };
+
+	Manager.eventLoop.add(to);
+    }
+
+    
     /**
      * Add TaskObserver.Code to the TaskObserver pool.
      */
diff --git a/frysk-core/frysk/proc/live/Watchpoint.java b/frysk-core/frysk/proc/live/Watchpoint.java
new file mode 100644
index 0000000..59c25a4
--- /dev/null
+++ b/frysk-core/frysk/proc/live/Watchpoint.java
@@ -0,0 +1,229 @@
+// This file is part of the program FRYSK.
+//
+// Copyright 2006, 2007, 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 interfaces identified in the file named EXCEPTION found in
+// the source code files (the "Approved Interfaces"). The files of
+// Non-GPL Code may instantiate templates or use macros or inline
+// functions from the Approved 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 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.
+
+
+package frysk.proc.live;
+
+import java.util.HashMap;
+
+import frysk.proc.Task;
+
+/**
+ * Internal proc class that represents a Breakpoint at a certain
+ * address in a Proc. Some attempts are made to have synchronize
+ * different Breakpoint instances at the same address in the same
+ * Proc, but currently this isn't a full singleton.
+ */
+public class Watchpoint implements Comparable
+{
+  // These two fields define a Breakpoint
+  private final long address;
+  private final int length;
+  private final Task task;
+
+
+  // Static cache of installed break points.
+  private static HashMap installed = new HashMap();
+
+
+
+  /**
+   * Private constructor called by create to record address and
+   * proc.
+   */
+  private Watchpoint(long address, int length, Task task)
+  {
+    if (task == null)
+      throw new NullPointerException("Cannot place a watchpoint when task == null.");
+
+    this.address = address;
+    this.task = task;
+    this.length = length;
+
+    if (this.length <= 0)
+	throw new RuntimeException("Watchpoint length has to be > 0");
+  }
+
+  /**
+   * Creates a Breakpoint for the Proc at the given Address but does
+   * not set it yet.  Returns the appropriate Breakpoint depending on
+   * 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)
+  {
+    Watchpoint breakpoint = new Watchpoint(address, length, task);
+
+    // If possible return an existing installed breakpoint.
+    synchronized (installed)
+      {
+	Watchpoint existing = (Watchpoint) installed.get(breakpoint);
+	if (existing != null)
+	  return existing;
+      }
+    return breakpoint;
+  }
+
+  public long getAddress()
+  {
+    return address;
+  }
+
+
+  /**
+   * Installs breakpoint. Caller must make sure there is no breakpoint set
+   * at that address yet and that install() is not called again till remove()
+   * is called on it.
+   */
+  public void install(Task task)
+  {
+    synchronized (installed)
+      {
+	Watchpoint existing = (Watchpoint) installed.get(this);
+	if (existing != null)
+	  throw new IllegalStateException("Already installed: " + this);
+
+	installed.put(this, this);
+    
+	set(task);
+      }
+  }
+
+  /**
+   * Actually sets the breakpoint.
+   */
+  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);
+  }
+
+  /**
+   * Removes the breakpoint. Caller must make sure it is called only
+   * when it is installed and not in the middle of a step.
+   */
+  public void remove(Task task)
+  {
+    synchronized (installed)
+      {
+	if (! this.equals(installed.remove(this)))
+	  throw new IllegalStateException("Not installed: " + this);
+
+	reset(task);
+      }
+  }
+
+  /**
+   * Actually removes the breakpoint.
+   */
+  private void reset(Task task)
+  {
+//      ByteBuffer buffer = ((LinuxPtraceTask)task).getRawMemory();
+//    buffer.position(address);
+//    
+//    Isa isa = ((LinuxPtraceTask)task).getIsaFIXME();
+//    Instruction bpInstruction = isa.getBreakpointInstruction();
+//    byte[] bp = bpInstruction.getBytes();
+//
+//    byte[] bs = origInstruction.getBytes();
+//
+//    // Only need to put back the part of the original instruction
+//    // covered by the breakpoint instruction bytes.
+//    buffer.put(bs, 0, bp.length);
+  }
+
+
+  /**
+   * Returns the Proc to which this breakpoint belongs.
+   */
+  public Task getTask()
+  {
+    return this.task;
+  }
+
+  /**
+   * Returns true if break point is installed and not yet removed.
+   */
+  public boolean isInstalled()
+  {
+    synchronized(installed)
+      {
+	return this.equals(installed.get(this));
+      }
+  }
+
+  // Utility methods for keeping the map of breakpoints.
+
+  public int hashCode()
+  {
+    return (int) (address ^ (address >>> 32));
+  }
+
+  public boolean equals(Object o)
+  {
+    if (o == null || o.getClass() != this.getClass())
+      return false;
+
+    Watchpoint other = (Watchpoint) o;
+    return other.task.equals(task) && other.address == address;
+  }
+
+  /**
+   * Uses natural ordering on address.
+   */
+  public int compareTo(Object o) 
+  {
+    Watchpoint other = (Watchpoint) o;
+    return (int) (this.address - other.address);
+  }
+
+  public String toString()
+  {
+    return this.getClass().getName() + "[task=" + task
+      + ", address=0x" + Long.toHexString(address) + "]";
+  }
+}
diff --git a/frysk-core/frysk/proc/live/BreakpointAddresses.java b/frysk-core/frysk/proc/live/WatchpointAddresses.java
similarity index 80%
copy from frysk-core/frysk/proc/live/BreakpointAddresses.java
copy to frysk-core/frysk/proc/live/WatchpointAddresses.java
index dc59c34..aba7d16 100644
--- a/frysk-core/frysk/proc/live/BreakpointAddresses.java
+++ b/frysk-core/frysk/proc/live/WatchpointAddresses.java
@@ -40,13 +40,13 @@
 
 package frysk.proc.live;
 
-import frysk.proc.TaskObserver;
-import frysk.proc.Proc;


hooks/post-receive
--
frysk system monitor/debugger


                 reply	other threads:[~2008-02-20 10:46 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=20080220104622.3044.qmail@sourceware.org \
    --to=pmuldoon@sourceware.org \
    --cc=frysk-cvs@sourceware.org \
    --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).