public inbox for frysk@sourceware.org
 help / color / mirror / Atom feed
* Re: [SCM]  master: Add watchpoint interfaces.
       [not found] <20080220104622.3044.qmail@sourceware.org>
@ 2008-02-20 11:39 ` Phil Muldoon
  0 siblings, 0 replies; only message in thread
From: Phil Muldoon @ 2008-02-20 11:39 UTC (permalink / raw)
  To: frysk

Hi all

These interfaces constitute the form of the api calls for watchpoints. 
Keen observers will note they look just like the Code (breakpoint) 
observers, and are in fact a copy of them. I'd like to keep the 
interfaces the same. Maybe later we can look at see if there is need for 
two separate interfaces.

Anyway, a quick note that these are committed without tests.  Given that 
the the proc namespace is under constant development/refactoring, and I 
spend a lot of time just merging; and that I want to get as much 
code-to-eyes as early on as possible, I thought it prudent to commit the 
interface code.

Regards

Phil

pmuldoon@sourceware.org wrote:
> 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
>   

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2008-02-20 11:39 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20080220104622.3044.qmail@sourceware.org>
2008-02-20 11:39 ` [SCM] master: Add watchpoint interfaces Phil Muldoon

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).