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