public inbox for frysk@sourceware.org
 help / color / mirror / Atom feed
* [patch] LogicalMemoryBuffer
@ 2007-07-20 12:02 Mark Wielaard
  2007-07-30 12:42 ` Mark Wielaard
  2007-08-02 11:26 ` Mark Wielaard
  0 siblings, 2 replies; 5+ messages in thread
From: Mark Wielaard @ 2007-07-20 12:02 UTC (permalink / raw)
  To: frysk

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

Hi,

This implements the logical memory view for Task.getMemory(). It is now
possible to view the process memory as if frysk-core hadn't touched it
at all. Users can now choose whether to get the raw view (with all the
bits in it that frysk-core might have changed for private house keeping)
through getRawMemory() or the logical view (which is the default old
getMemory() that almost everything outside frysk-core now uses). The gui
and fhpd could give the user the option to also get a raw memory view,
but in general the user is probably interested in the logical view as
the (running) process should see it. fcore could also choose to either
dump the logical memory view (which it already does since it just reads
the section maps from disk) or include the raw view (but that doesn't
seem wise since the user wouldn't know why the "garbage" breakpoint
instructions that frysk-core inserted are there).

frysk-core/frysk/proc/ChangeLog
2007-07-20  Mark Wielaard  <mwielaard@redhat.com>

    * Breakpoint.java: Implements Comparable.
    (getInstruction): New method.
    (getProc): New method.
    (compareTo): New method.
    * BreakpointAddresses.java (breakpoints): New field.
    (BreakpointAddresses): Initialize breakpoints.
    (getBreakpoint): New method.
    (getBreakpoints): New method.
    * MemoryMap.java: Make immutable.
    * Task.java (getRawMemory): New method.
    * TestTaskObserverCode (testViewBreakpointMemory): New test.
    (testViewBreakpointMap): New test.
    (getFunctionDie): New method.
    (getFunctionEntryAddress): Use getFunctionDie.

frysk-core/frysk/proc/live/ChangeLog
2007-07-20  Mark Wielaard  <mwielaard@redhat.com>

    * AddressSpaceByteBuffer.java (addressSpace): Now protected.
    (pid): Likewise.
    (AddressSpaceByteBuffer): Likewise.
    * LinuxTask.java (getRawMemory): New method name for sendrecMemory.
    (sendrecMemory): Implement through LogicalMemoryBuffer.
    * LogicalMemoryBuffer.java: New class.

There are a couple of new tests added for this that now all pass. No
regressions on x86_64 Fedora Core 6 and x86 Fedora 7. Although that was
somewhat hard to see since there are a couple of always failing and a
couple of intermediately failing tests in the tree. It would be nice to
get back to zero fail again.

A couple of things to note, questions and upcoming work:

- Some of the work with our ByteBuffers is somewhat awkward since we
pretend everything is longs. But arrays in java cannot address anything
bigger than a (positive) int. So having offsets and lengths as longs is
somewhat cheating since it will never work in practise. So there is some
casting back and forth. Maybe just change the ByteBuffer methods that
work on arrays to just take ints for offset and length.

- I added some comments about Breakpoints not really being immutable
objects which affects the thread-safety of the code. There are some
extra checks here and there. But it would be good to go over this. Maybe
this isn't really an issue since memory reads should only be done in
observers after an event notification. Can observers for different Tasks
of the same Proc be signaled simultaneously?

- LogicalMemoryBuffer is a filter on top of AddressSpaceByteBuffer but
really should be on top of MemorySpaceByteBuffer which is more
effecient. The used to be interface compatible, but a recent change to
MemorySpaceByteBuffer changed that and made that it less easy to wrap.
MemorySpaceByteBuffer is really just an optimization of
AddressSpaceByteBuffer (in the case of AddressSpace.TEXT/DATA) and all
code should go through the optimized path (StateLessFile) for accessing
memory if the AddressSpace allows it. So I am going to merge the two
(and fix up the places that currently use the slow path). Then I'll also
add the ByteBuffer.get() optimization that Chris pointed out.

- It would be nice to have an fhpd examine (gdb's x) command to show the
above work to the user (the gui already has a memory view). I like to
add that. The hpd spec doesn't seem to have something like this, nor
does it seem to have a way for expressions to take the address of
functions or raw addresses. Do we already have extensions for that?
I haven't yet looked at Nurdin's recent fhpd work, but this might
already do most of what I want, and more. So maybe all I need to do is
strip stuff from that because I just don't need the more :)

Cheers,

Mark

[-- Attachment #2: logicalmem.patch --]
[-- Type: text/x-patch, Size: 25425 bytes --]

Index: frysk-core/frysk/proc/Breakpoint.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/Breakpoint.java,v
retrieving revision 1.13
diff -u -r1.13 Breakpoint.java
--- frysk-core/frysk/proc/Breakpoint.java	9 Jul 2007 08:18:59 -0000	1.13
+++ frysk-core/frysk/proc/Breakpoint.java	20 Jul 2007 10:53:37 -0000
@@ -46,9 +46,11 @@
 
 /**
  * Internal proc class that represents a Breakpoint at a certain
- * address in a Proc.
+ * 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 Breakpoint
+public class Breakpoint implements Comparable
 {
   // These two fields define a Breakpoint
   private final long address;
@@ -274,6 +276,34 @@
   }
 
   /**
+   * If this breakpoint is installed then the original instruction at
+   * the breakpoint address is returned. Otherwise null could be
+   * returned.
+   */
+  public Instruction getInstruction()
+  {
+    if (origInstruction == null)
+      {
+	// Try to get at the installed instance and sync with it.
+	synchronized(installed)
+	  {
+	    Breakpoint existing = (Breakpoint) installed.get(this);
+	    if (existing != null)
+	      this.origInstruction = existing.origInstruction;
+	  }
+      }
+    return origInstruction;
+  }
+
+  /**
+   * Returns the Proc to which this breakpoint belongs.
+   */
+  public Proc getProc()
+  {
+    return proc;
+  }
+
+  /**
    * Returns true if break point is installed and not yet removed.
    */
   public boolean isInstalled()
@@ -300,6 +330,15 @@
     return other.proc.equals(proc) && other.address == address;
   }
 
+  /**
+   * Uses natural ordering on address.
+   */
+  public int compareTo(Object o) 
+  {
+    Breakpoint other = (Breakpoint) o;
+    return (int) (this.address - other.address);
+  }
+
   public String toString()
   {
     return this.getClass().getName() + "[proc=" + proc
Index: frysk-core/frysk/proc/BreakpointAddresses.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/BreakpointAddresses.java,v
retrieving revision 1.6
diff -u -r1.6 BreakpointAddresses.java
--- frysk-core/frysk/proc/BreakpointAddresses.java	19 May 2007 13:01:45 -0000	1.6
+++ frysk-core/frysk/proc/BreakpointAddresses.java	20 Jul 2007 10:53:37 -0000
@@ -1,6 +1,6 @@
 // This file is part of the program FRYSK.
 //
-// Copyright 2006, Red Hat Inc.
+// Copyright 2006, 2007 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
@@ -70,7 +70,12 @@
    * will do.
    */
   private final HashMap map;
-  
+
+  /**
+   * A sorted set (on address) of Breakpoints, used for getBreakpoints().
+   */
+  private final TreeSet breakpoints;
+
   /**
    * Package private constructor used by the Proc when created.
    */
@@ -78,6 +83,7 @@
   {
     this.proc = proc;
     map = new HashMap();
+    breakpoints = new TreeSet();
   }
 
   /**
@@ -94,6 +100,7 @@
     ArrayList list = (ArrayList) map.get(breakpoint);
     if (list == null)
       {
+	breakpoints.add(breakpoint);
 	list = new ArrayList();
 	map.put(breakpoint, list);
 	list.add(observer);
@@ -126,6 +133,7 @@
     
     if (list.isEmpty())
       {
+	breakpoints.remove(breakpoint);
 	map.remove(breakpoint);
 	return true;
       }
@@ -153,6 +161,28 @@
     return observers;
   }
 
+  public Breakpoint getBreakpoint(long address)
+  {
+    Breakpoint breakpoint = Breakpoint.create(address, proc);
+    Object observer = map.get(breakpoint);
+    if (observer == null)
+      return null;
+    else
+      return breakpoint;
+  }
+
+  /**
+   * Returns an iterator that returns in address order all breakpoints
+   * (possibly) installed starting at the from address up to (but not
+   * including) the till address.
+   */
+  public Iterator getBreakpoints(long from, long till)
+  {
+    Breakpoint fromBreakpoint = Breakpoint.create(from, proc);
+    Breakpoint tillBreakpoint = Breakpoint.create(till, proc);
+    return breakpoints.subSet(fromBreakpoint, tillBreakpoint).iterator();
+  }
+
   /**
    * Called from TaskState when the Task gets an execed event which
    * clears the whole address space.
@@ -162,5 +192,6 @@
   public void removeAllCodeObservers()
   {
     map.clear();
+    breakpoints.clear();
   }
 }
Index: frysk-core/frysk/proc/MemoryMap.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/MemoryMap.java,v
retrieving revision 1.3
diff -u -r1.3 MemoryMap.java
--- frysk-core/frysk/proc/MemoryMap.java	13 Jun 2007 21:10:30 -0000	1.3
+++ frysk-core/frysk/proc/MemoryMap.java	20 Jul 2007 10:53:37 -0000
@@ -48,19 +48,19 @@
  */
 public class MemoryMap
 {
-  public long addressLow;
-  public long addressHigh;
-  public boolean permRead;
-  public boolean permWrite;
-  public boolean permExecute;
-  public boolean shared;
-  public long offset;
-  public int devMajor;
-  public int devMinor;
-  public int inode;       
-  public int pathnameOffset;
-  public int pathnameLength; 
-  public String name;
+  public final long addressLow;
+  public final long addressHigh;
+  public final boolean permRead;
+  public final boolean permWrite;
+  public final boolean permExecute;
+  public final boolean shared;
+  public final long offset;
+  public final int devMajor;
+  public final int devMinor;
+  public final int inode;       
+  public final int pathnameOffset;
+  public final int pathnameLength; 
+  public final String name;
 
   public MemoryMap(long addressLow, long addressHigh,
 	     boolean permRead, boolean permWrite,
Index: frysk-core/frysk/proc/Task.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/Task.java,v
retrieving revision 1.143
diff -u -r1.143 Task.java
--- frysk-core/frysk/proc/Task.java	5 Jul 2007 19:00:15 -0000	1.143
+++ frysk-core/frysk/proc/Task.java	20 Jul 2007 10:53:37 -0000
@@ -846,6 +846,21 @@
   }
 
   /**
+   * Returns the memory as seen by frysk-core. That includes things like
+   * inserted breakpoint instructions bytes which are filtered out by
+   * <code>getMemory()</code> (which is what you normally want unless
+   * you are interested in frysk-core specifics).
+   * <p>
+   * Default implementation calls <code>getMemory()</code>, need to be
+   * overriden by subclasses for which the raw memory view and the
+   * logical memory view are different.
+   */
+  public ByteBuffer getRawMemory()
+  {
+    return getMemory();
+  }
+
+  /**
    * Set of Code observers.
    *
    * XXX: Should not be public.
Index: frysk-core/frysk/proc/TestTaskObserverCode.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/TestTaskObserverCode.java,v
retrieving revision 1.4
diff -u -r1.4 TestTaskObserverCode.java
--- frysk-core/frysk/proc/TestTaskObserverCode.java	16 Jul 2007 22:11:35 -0000	1.4
+++ frysk-core/frysk/proc/TestTaskObserverCode.java	20 Jul 2007 10:53:38 -0000
@@ -39,6 +39,8 @@
 
 package frysk.proc;
 
+import inua.eio.*;
+
 import frysk.sys.*;
 
 import lib.dwfl.*;
@@ -139,6 +141,230 @@
     assertRunUntilStop("cleanup");
   }
 
+  // Tests that breakpoint instructions are not visible to
+  // normal users of task memory (only through raw memory view).
+  public void testViewBreakpointMemory() throws Exception
+  {
+    // Create a child.
+    child = new AckDaemonProcess();
+    task = child.findTaskUsingRefresh (true);
+    proc = task.getProc();
+
+    // Make sure we are attached.
+    AttachedObserver attachedObserver = new AttachedObserver();
+    task.requestAddAttachedObserver(attachedObserver);
+    assertRunUntilStop("adding AttachedObserver");
+
+    ByteBuffer memory = task.getMemory();
+    ByteBuffer raw_memory = task.getRawMemory();
+    long address = getFunctionEntryAddress("bp1_func");
+    DwarfDie func1_die = getFunctionDie("bp1_func");
+    long func1_start = func1_die.getLowPC();
+    long func1_end = func1_die.getHighPC();
+
+    // Get the original byte and byte[] for the breakpoint address and
+    // whole function. Raw and logical should be similar.
+    byte bp1_orig;
+    memory.position(address);
+    bp1_orig = memory.getByte();
+
+    byte bp1_orig_raw;
+    raw_memory.position(address);
+    bp1_orig_raw = raw_memory.getByte();
+    assertEquals("orig and raw", bp1_orig, bp1_orig_raw);
+
+    byte[] func1_orig = new byte[(int) (func1_end - func1_start)];
+    memory.position(func1_start);
+    memory.get(func1_orig);
+
+    byte[] func1_orig_raw = new byte[(int) (func1_end - func1_start)];
+    raw_memory.position(func1_start);
+    raw_memory.get(func1_orig_raw);
+    assertTrue("func_orig and func_raw",
+	       Arrays.equals(func1_orig, func1_orig_raw));
+
+    // Insert breakpoint and check that (non-raw) view is the same.
+    CodeObserver code = new CodeObserver(task, address);
+    task.requestAddCodeObserver(code, address);
+    assertRunUntilStop("add breakpoint observer");
+
+    // Get the byte and byte[] for the breakpoint address and
+    // whole function. Raw should show the breakpoint.
+    byte bp1_insert;
+    memory.position(address);
+    bp1_insert = memory.getByte();
+    assertEquals("orig and insert", bp1_orig, bp1_insert);
+
+    byte bp1_insert_raw;
+    raw_memory.position(address);
+    bp1_insert_raw = raw_memory.getByte();
+    assertTrue("insert and raw", bp1_insert != bp1_insert_raw);
+
+    byte[] func1_insert = new byte[(int) (func1_end - func1_start)];
+    memory.position(func1_start);
+    memory.get(func1_insert);
+    assertTrue("func_orig and func_insert",
+	       Arrays.equals(func1_orig, func1_insert));
+    
+    byte[] func1_insert_raw = new byte[(int) (func1_end - func1_start)];
+    raw_memory.position(func1_start);
+    raw_memory.get(func1_insert_raw);
+    assertFalse("func_insert and func_insert_raw",
+		Arrays.equals(func1_insert, func1_insert_raw));
+
+    // And remove it again.
+    task.requestDeleteCodeObserver(code, address);
+    assertRunUntilStop("remove code observer again");
+
+    // Get the byte and byte[] for the breakpoint address and
+    // whole function. Neither memory view should show the breakpoint.
+    byte bp1_new;
+    memory.position(address);
+    bp1_new = memory.getByte();
+    assertEquals("orig and new", bp1_orig, bp1_new);
+
+    byte[] func1_new = new byte[(int) (func1_end - func1_start)];
+    memory.position(func1_start);
+    memory.get(func1_new);
+    assertTrue("func_orig and func_new",
+	       Arrays.equals(func1_orig, func1_new));
+
+    byte bp1_new_raw;
+    raw_memory.position(address);
+    bp1_new_raw = raw_memory.getByte();
+    assertEquals("new and raw",
+		 bp1_new, bp1_new_raw);
+
+    byte[] func1_new_raw = new byte[(int) (func1_end - func1_start)];
+    raw_memory.position(func1_start);
+    raw_memory.get(func1_new_raw);
+    assertTrue("func_new and func_new_raw",
+	       Arrays.equals(func1_new, func1_new_raw));
+  }
+
+  // Tests that breakpoint instructions are not visible in the entire
+  // code text map of the program.
+  public void testViewBreakpointMap() throws Exception
+  {
+    // Create a child.
+    child = new AckDaemonProcess();
+    task = child.findTaskUsingRefresh (true);
+    proc = task.getProc();
+
+    // Make sure we are attached.
+    AttachedObserver attachedObserver = new AttachedObserver();
+    task.requestAddAttachedObserver(attachedObserver);
+    assertRunUntilStop("adding AttachedObserver");
+
+    ByteBuffer memory = task.getMemory();
+    ByteBuffer raw_memory = task.getRawMemory();
+
+    DwarfDie func1_die = getFunctionDie("bp1_func");
+    long func1_start = func1_die.getLowPC();
+    long func1_end = func1_die.getHighPC();
+
+    DwarfDie func2_die = getFunctionDie("bp2_func");
+    long func2_start = func2_die.getLowPC();
+    long func2_end = func2_die.getHighPC();
+
+    long address = func1_start;
+    MemoryMap map = proc.getMap(func1_start);
+
+    int map_len = (int) (map.addressHigh - map.addressLow);
+
+    byte[] mem_orig = new byte[map_len];
+    byte[] raw_orig = new byte[map_len];
+    
+    memory.position(map.addressLow);
+    memory.get(mem_orig);
+    raw_memory.position(map.addressLow);
+    raw_memory.get(raw_orig);
+
+    assertTrue("mem_orig and raw_orig",
+	       Arrays.equals(mem_orig, raw_orig));
+
+    // Put breakpoints inside the map and at the beginning and the end
+    // to test the corner cases.
+    address = func1_start;
+    CodeObserver code1 = new CodeObserver(task, address);
+    task.requestAddCodeObserver(code1, address);
+    assertRunUntilStop("add breakpoint observer func1 start");
+
+    address = func1_end;
+    CodeObserver code2 = new CodeObserver(task, address);
+    task.requestAddCodeObserver(code2, address);
+    assertRunUntilStop("add breakpoint observer func1 end");
+
+    address = func2_start;
+    CodeObserver code3 = new CodeObserver(task, address);
+    task.requestAddCodeObserver(code3, address);
+    assertRunUntilStop("add breakpoint observer func2 start");
+
+    address = func2_end;
+    CodeObserver code4 = new CodeObserver(task, address);
+    task.requestAddCodeObserver(code4, address);
+    assertRunUntilStop("add breakpoint observer func2 end");
+
+    address = map.addressLow;
+    CodeObserver code5 = new CodeObserver(task, address);
+    task.requestAddCodeObserver(code5, address);
+    assertRunUntilStop("add breakpoint observer addressLow");
+
+    address = map.addressHigh - 1;
+    CodeObserver code6 = new CodeObserver(task, address);
+    task.requestAddCodeObserver(code6, address);
+    assertRunUntilStop("add breakpoint observer addressHigh");
+
+    byte[] bp_mem = new byte[map_len];
+    byte[] bp_raw = new byte[map_len];
+    
+    memory.position(map.addressLow);
+    memory.get(bp_mem);
+    raw_memory.position(map.addressLow);
+    raw_memory.get(bp_raw);
+
+    assertTrue("mem_orig and bp_mem",
+	       Arrays.equals(mem_orig, bp_mem));
+    assertFalse("raw_orig and bp_raw",
+		Arrays.equals(raw_orig, bp_raw));
+
+    // See if only the breakpoint addresses were affected.
+    bp_raw[(int) (func1_start - map.addressLow)] = memory.getByte(func1_start);
+    bp_raw[(int) (func1_end - map.addressLow)] = memory.getByte(func1_end);
+    bp_raw[(int) (func2_start - map.addressLow)] = memory.getByte(func2_start);
+    bp_raw[(int) (func2_end - map.addressLow)] = memory.getByte(func2_end);
+    bp_raw[0] = memory.getByte(map.addressLow);
+    bp_raw[map_len - 1] = memory.getByte(map.addressHigh - 1);
+
+    assertTrue("bp_mem and bp_raw",
+	       Arrays.equals(bp_mem, bp_raw));
+
+    // Remove all breakpoints and all memory should revert to be the same.
+    task.requestDeleteCodeObserver(code1, code1.address);
+    assertRunUntilStop("delete 1");
+    task.requestDeleteCodeObserver(code2, code2.address);
+    assertRunUntilStop("delete 2");
+    task.requestDeleteCodeObserver(code3, code3.address);
+    assertRunUntilStop("delete 3");
+    task.requestDeleteCodeObserver(code4, code4.address);
+    assertRunUntilStop("delete 4");
+    task.requestDeleteCodeObserver(code5, code5.address);
+    assertRunUntilStop("delete 5");
+    task.requestDeleteCodeObserver(code6, code6.address);
+    assertRunUntilStop("delete 6");
+
+    memory.position(map.addressLow);
+    memory.get(bp_mem);
+    raw_memory.position(map.addressLow);
+    raw_memory.get(bp_raw);
+
+    assertTrue("deleted mem_orig and bp_mem",
+               Arrays.equals(mem_orig, bp_mem));
+    assertTrue("deleted bp_mem and bp_raw",
+	       Arrays.equals(bp_mem, bp_raw));
+
+  }
+
   // Tells the child to run the dummy () function
   // which calls bp1_func () and bp2_func ().
   static final Sig dummySig = Sig.PROF;
@@ -172,23 +398,26 @@
    */
   long getFunctionEntryAddress(String func) throws ElfException
   {
-    Elf elf = new Elf(proc.getExe(), ElfCommand.ELF_C_READ);
-    Dwarf dwarf = new Dwarf(elf, DwarfCommand.READ, null);
-    DwarfDie die = DwarfDie.getDecl(dwarf, func);
+    DwarfDie die = getFunctionDie(func);
     ArrayList entryAddrs = die.getEntryBreakpoints();
 
     // We really expect just one entry point.
     assertEquals(entryAddrs.size(), 1);
-
-    // Add a Code observer on the address.
     return ((Long) entryAddrs.get(0)).longValue();
   }
 
+  DwarfDie getFunctionDie(String func) throws ElfException
+  {
+    Elf elf = new Elf(proc.getExe(), ElfCommand.ELF_C_READ);
+    Dwarf dwarf = new Dwarf(elf, DwarfCommand.READ, null);
+    return DwarfDie.getDecl(dwarf, func);
+  }
+
   static class CodeObserver
     implements TaskObserver.Code
   {
     private final Task task;
-    private final long address;
+    final long address;
 
     boolean hit;
 
Index: frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java,v
retrieving revision 1.1
diff -u -r1.1 AddressSpaceByteBuffer.java
--- frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java	26 Jun 2007 22:12:52 -0000	1.1
+++ frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java	20 Jul 2007 10:53:38 -0000
@@ -47,10 +47,10 @@
 public class AddressSpaceByteBuffer
     extends ByteBuffer
 {
-    private final AddressSpace addressSpace;
-    private final int pid;
+    protected final AddressSpace addressSpace;
+    protected final int pid;
 
-    private AddressSpaceByteBuffer (int pid, AddressSpace addressSpace,
+    protected AddressSpaceByteBuffer (int pid, AddressSpace addressSpace,
 				    long lowerExtreem, long upperExtreem)
     {
 	super (lowerExtreem, upperExtreem);
Index: frysk-core/frysk/proc/live/LinuxTask.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/live/LinuxTask.java,v
retrieving revision 1.3
diff -u -r1.3 LinuxTask.java
--- frysk-core/frysk/proc/live/LinuxTask.java	18 Jul 2007 20:00:31 -0000	1.3
+++ frysk-core/frysk/proc/live/LinuxTask.java	20 Jul 2007 10:53:38 -0000
@@ -39,6 +39,7 @@
 
 package frysk.proc.live;
 
+import frysk.proc.BreakpointAddresses;
 import frysk.proc.TaskObserver;
 import frysk.proc.Proc;
 import frysk.proc.TaskId;
@@ -52,9 +53,11 @@
 import frysk.proc.Isa;
 import frysk.sys.Errno;
 import frysk.sys.Ptrace;
+import frysk.sys.Ptrace.AddressSpace;
 import frysk.sys.Sig;
 import frysk.sys.Signal;
 
+
 /**
  * A Linux Task tracked using PTRACE.
  */
@@ -88,9 +91,9 @@
 
 
     /**
-     * Return the memory byte-buffer.
+     * Return the raw memory byte-buffer.
      */
-    protected ByteBuffer sendrecMemory ()
+    public ByteBuffer getRawMemory ()
     {
 	logger.log(Level.FINE, "Begin fillMemory\n", this);
 	ByteOrder byteOrder = getIsa().getByteOrder();
@@ -99,7 +102,16 @@
 	logger.log(Level.FINE, "End fillMemory\n", this); 
 	return memory;
     }
-    
+
+    protected ByteBuffer sendrecMemory ()
+    {
+      int tid = getTid();
+      ByteOrder byteOrder = getIsa().getByteOrder();
+      BreakpointAddresses breakpoints = getProc().breakpoints;
+      return new LogicalMemoryBuffer(tid, AddressSpace.DATA,
+				     byteOrder, breakpoints);
+    }
+
     /**
      * Return the ISA's register-bank byte-buffers.
      */
Index: frysk-core/frysk/proc/live/LogicalMemoryBuffer.java
===================================================================
RCS file: frysk-core/frysk/proc/live/LogicalMemoryBuffer.java
diff -N frysk-core/frysk/proc/live/LogicalMemoryBuffer.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ frysk-core/frysk/proc/live/LogicalMemoryBuffer.java	20 Jul 2007 10:53:38 -0000
@@ -0,0 +1,152 @@
+// This file is part of the program FRYSK.
+//
+// Copyright 2007 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 frysk.proc.Breakpoint;
+import frysk.proc.BreakpointAddresses;
+import frysk.proc.Instruction;
+
+import java.util.Iterator;
+
+import inua.eio.ByteBuffer;
+import inua.eio.ByteOrder;
+
+import frysk.sys.Ptrace.AddressSpace;
+
+/**
+ * MemorySpaceByteBuffer that filters out anything the frysk core
+ * might have done to the underlying memory. It takes the breakpoints
+ * embedded in the process and on a peek will filter those out and
+ * replace the bytes with the logical bytes as the user would normally
+ * see them from the process.
+ */
+class LogicalMemoryBuffer extends AddressSpaceByteBuffer
+{
+  // Byte order set on the buffer (needed for creating a subBuffer).
+  private final ByteOrder order;
+
+  // The breakpoints associated with the process address space.
+  private final BreakpointAddresses breakpoints;
+
+  // Private constructor used by subBuffer()
+  private LogicalMemoryBuffer(int tid, AddressSpace addressSpace,
+			      ByteOrder order,
+			      BreakpointAddresses breakpoints,
+			      long lower, long upper)
+  {
+    super(tid, addressSpace, lower, upper);
+    order(order);
+    this.order = order;
+    this.breakpoints = breakpoints;
+  }
+  
+  // Package local contructor used by LinuxTask to create a logical
+  // memory space for a task when requested.
+  LogicalMemoryBuffer(int tid,
+		      AddressSpace addressSpace,
+		      ByteOrder order,
+		      BreakpointAddresses breakpoints)
+  {
+    super(tid, addressSpace);
+    order(order);
+    this.order = order;
+    this.breakpoints = breakpoints;
+  }
+  
+  protected int peek(long caret)
+  {
+    Breakpoint breakpoint = breakpoints.getBreakpoint(caret);
+    if (breakpoint != null)
+      {
+	// This really shouldn't happen, it means the breakpoint
+	// is already uninstalled.
+	Instruction instruction = breakpoint.getInstruction();
+	if (instruction != null)
+	  {
+	    byte[] ibs = instruction.getBytes();
+	    return ibs[0] & 0xff;
+	  }
+      }
+    return super.peek(caret);
+  }
+  
+  protected long peek(long index, byte[] bytes, long offset, long length)
+  {
+    synchronized (breakpoints)
+      {
+	Iterator it;
+	it = breakpoints.getBreakpoints(index, index + length);
+	long r = 0;
+	while (it.hasNext())
+	  {
+	    Breakpoint breakpoint = (Breakpoint) it.next();
+	    long l = breakpoint.getAddress() - (index + r);
+	    // Do we need to be worried about "short peeks"?
+	    r += super.peek(index + r, bytes, offset + r, l);
+
+	    byte b;
+	    Instruction instruction = breakpoint.getInstruction();
+	    // This really shouldn't happen, it means the breakpoint
+	    // is already uninstalled.
+	    if (instruction != null)
+	      b = instruction.getBytes()[0];
+	    else
+	      b = (byte) super.peek(index + r);
+	    // Since we are addressing a array both offset and r
+	    // cannot really be bigger than an int, they could still
+	    // overflow, but then we get a negative offset exception
+	    // which seems fine because in that case offset + r was
+	    // already larger than the array length.
+	    bytes[(int) (offset + r)] = b;
+	    r++;
+	  }
+	return super.peek(index + r, bytes, offset + r, length - r) + r;
+      }
+  }
+  
+  protected ByteBuffer subBuffer(ByteBuffer parent,
+				 long lower, long upper)
+  {
+    LogicalMemoryBuffer sub = (LogicalMemoryBuffer) parent;
+    return new LogicalMemoryBuffer (sub.pid, sub.addressSpace,
+				    sub.order, sub.breakpoints,
+				    lower, upper);
+  }
+}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] LogicalMemoryBuffer
  2007-07-20 12:02 [patch] LogicalMemoryBuffer Mark Wielaard
@ 2007-07-30 12:42 ` Mark Wielaard
  2007-08-02 11:26 ` Mark Wielaard
  1 sibling, 0 replies; 5+ messages in thread
From: Mark Wielaard @ 2007-07-30 12:42 UTC (permalink / raw)
  To: frysk

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

Hi,

On Fri, 2007-07-20 at 14:02 +0200, Mark Wielaard wrote:
> - Some of the work with our ByteBuffers is somewhat awkward since we
> pretend everything is longs. But arrays in java cannot address anything
> bigger than a (positive) int. So having offsets and lengths as longs is
> somewhat cheating since it will never work in practise. So there is some
> casting back and forth. Maybe just change the ByteBuffer methods that
> work on arrays to just take ints for offset and length.

The following patch does this for ByteBuffers, FileDescriptors and
StatelessFile. Now it is possible to catch such issues during compile
time instead of during runtime one day when some offset or length is
bigger than what fits into an array. This makes implementing the methods
that work on byte[] simpler and safer. It also fixes LogicalMemoryBuffer
to not set the order explicitly, but lets the caller determine the
order.

frysk-core/frysk/proc/live/ChangeLog
2007-07-30  Mark Wielaard  <mwielaard@redhat.com>

   * AddressSpaceByteBuffer.java (Request): Make length and offset ints.
   (peek): Likewise.
   * LinuxTask.java (sendrecMemory): Set memory order.
   * LogicalMemoryBuffer.java (order): Remove field.
   (LogicalMemoryBuffer): Don't set order.
   (peek): Make length and offset ints.
   (subBuffer): Don't pass order.
   * MemorySpaceByteBuffer.java (Request): Make length and offset ints.
   (peek): Likewise.
   * TestMemorySpaceByteBuffer.java (AsyncPeeks): Make length int.

frysk-sys/frysk/sys/ChangeLog
2007-07-30  Mark Wielaard  <mwielaard@redhat.com>

   * FileDescriptor.java (read): Make start and length ints.
   (write): Likewise.
   * Ptrace.java (peek): Make length and offset ints.
   * StatelessFile.java (pread): Make start and length ints.
   (pwrite): Likewise.
   * TestFileDescriptor.java (IO.op): Likewise.
   (assertArrayIndexOutOfBounds): Likewise.
   (testReadOutOfBounds): Likewise.
   (testWriteOutOfBounds): Likewise.
   * TestPtrace.java (verifyOutOfBounds): Make length and offset ints.
   * TestStatelessFile.java: Make start and length ints.
   * cni/Errno.cxx (verifyBounds): Make start and length ints.
   * cni/Errno.hxx: Likewise.
   * cni/FileDescriptor.cxx (read): Make start and length jints.
   (write): Likewise.
   * cni/Ptrace.cxx (peek): Make length and offset jints.
   * cni/StatelessFile.cxx (pread): Make start and length jints.
   (pwrite): Likewise.

frysk-sys/inua/ChangeLog
2007-07-30  Mark Wielaard  <mwielaard@redhat.com>

   * eio/ByteBuffer.java (peek): Make off and len ints.
   (poke): Likewise.
   (peekFully): Likewise.
   (pokeFully): Likewise.
   * eio/MmapByteBuffer.java (peek): Likewise.
   * eio/cni/MmapByteBuffer.cxx (peek): Likewise.

Tested on x86 and x86_64 without regressions.

Cheers,

Mark

[-- Attachment #2: eio-buffer.patch --]
[-- Type: text/x-patch, Size: 29555 bytes --]

Index: frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java,v
retrieving revision 1.2
diff -u -r1.2 AddressSpaceByteBuffer.java
--- frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java	20 Jul 2007 11:36:06 -0000	1.2
+++ frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java	30 Jul 2007 12:03:00 -0000
@@ -130,8 +130,8 @@
 	extends Request
     {
 	private long index;
-	private long length;
-	private long offset;
+	private int length;
+	private int offset;
 	private byte[] bytes;
 	PeeksRequest()
 	{
@@ -141,8 +141,8 @@
 	{
 	    length = addressSpace.peek(pid, index, length, bytes, offset);
 	}
-	public long request (long index, byte[] bytes,
-			     long offset, long length)
+	public int request (long index, byte[] bytes,
+			    int offset, int length)
 	{
 	    if (isEventLoopThread())
 		return addressSpace.peek(pid, index, length, bytes, offset);
@@ -157,7 +157,7 @@
 	}
     }
     private final PeeksRequest peeksRequest;
-    protected long peek (long index, byte[] bytes, long offset, long length)
+    protected int peek (long index, byte[] bytes, int offset, int length)
     {
 	return peeksRequest.request(index, bytes, offset, length);
     }
Index: frysk-core/frysk/proc/live/LinuxTask.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/live/LinuxTask.java,v
retrieving revision 1.4
diff -u -r1.4 LinuxTask.java
--- frysk-core/frysk/proc/live/LinuxTask.java	20 Jul 2007 11:36:06 -0000	1.4
+++ frysk-core/frysk/proc/live/LinuxTask.java	30 Jul 2007 12:03:00 -0000
@@ -108,8 +108,10 @@
       int tid = getTid();
       ByteOrder byteOrder = getIsa().getByteOrder();
       BreakpointAddresses breakpoints = getProc().breakpoints;
-      return new LogicalMemoryBuffer(tid, AddressSpace.DATA,
-				     byteOrder, breakpoints);
+      ByteBuffer memory = new LogicalMemoryBuffer(tid, AddressSpace.DATA,
+						  breakpoints);
+      memory.order(byteOrder);
+      return memory;
     }
 
     /**
Index: frysk-core/frysk/proc/live/LogicalMemoryBuffer.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/live/LogicalMemoryBuffer.java,v
retrieving revision 1.1
diff -u -r1.1 LogicalMemoryBuffer.java
--- frysk-core/frysk/proc/live/LogicalMemoryBuffer.java	20 Jul 2007 11:36:06 -0000	1.1
+++ frysk-core/frysk/proc/live/LogicalMemoryBuffer.java	30 Jul 2007 12:03:00 -0000
@@ -46,7 +46,6 @@
 import java.util.Iterator;
 
 import inua.eio.ByteBuffer;
-import inua.eio.ByteOrder;
 
 import frysk.sys.Ptrace.AddressSpace;
 
@@ -59,21 +58,15 @@
  */
 class LogicalMemoryBuffer extends AddressSpaceByteBuffer
 {
-  // Byte order set on the buffer (needed for creating a subBuffer).
-  private final ByteOrder order;
-
   // The breakpoints associated with the process address space.
   private final BreakpointAddresses breakpoints;
 
   // Private constructor used by subBuffer()
   private LogicalMemoryBuffer(int tid, AddressSpace addressSpace,
-			      ByteOrder order,
 			      BreakpointAddresses breakpoints,
 			      long lower, long upper)
   {
     super(tid, addressSpace, lower, upper);
-    order(order);
-    this.order = order;
     this.breakpoints = breakpoints;
   }
   
@@ -81,12 +74,9 @@
   // memory space for a task when requested.
   LogicalMemoryBuffer(int tid,
 		      AddressSpace addressSpace,
-		      ByteOrder order,
 		      BreakpointAddresses breakpoints)
   {
     super(tid, addressSpace);
-    order(order);
-    this.order = order;
     this.breakpoints = breakpoints;
   }
   
@@ -107,17 +97,19 @@
     return super.peek(caret);
   }
   
-  protected long peek(long index, byte[] bytes, long offset, long length)
+  protected int peek(long index, byte[] bytes, int offset, int length)
   {
     synchronized (breakpoints)
       {
 	Iterator it;
 	it = breakpoints.getBreakpoints(index, index + length);
-	long r = 0;
+	int r = 0;
 	while (it.hasNext())
 	  {
 	    Breakpoint breakpoint = (Breakpoint) it.next();
-	    long l = breakpoint.getAddress() - (index + r);
+	    // address - index falls inside the byte[] so will be at most
+	    // a positive int apart.
+	    int l = (int) (breakpoint.getAddress() - index) - r;
 	    // Do we need to be worried about "short peeks"?
 	    r += super.peek(index + r, bytes, offset + r, l);
 
@@ -129,12 +121,7 @@
 	      b = instruction.getBytes()[0];
 	    else
 	      b = (byte) super.peek(index + r);
-	    // Since we are addressing a array both offset and r
-	    // cannot really be bigger than an int, they could still
-	    // overflow, but then we get a negative offset exception
-	    // which seems fine because in that case offset + r was
-	    // already larger than the array length.
-	    bytes[(int) (offset + r)] = b;
+	    bytes[offset + r] = b;
 	    r++;
 	  }
 	return super.peek(index + r, bytes, offset + r, length - r) + r;
@@ -146,7 +133,7 @@
   {
     LogicalMemoryBuffer sub = (LogicalMemoryBuffer) parent;
     return new LogicalMemoryBuffer (sub.pid, sub.addressSpace,
-				    sub.order, sub.breakpoints,
+				    sub.breakpoints,
 				    lower, upper);
   }
 }
Index: frysk-core/frysk/proc/live/MemorySpaceByteBuffer.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/live/MemorySpaceByteBuffer.java,v
retrieving revision 1.4
diff -u -r1.4 MemorySpaceByteBuffer.java
--- frysk-core/frysk/proc/live/MemorySpaceByteBuffer.java	18 Jul 2007 20:00:31 -0000	1.4
+++ frysk-core/frysk/proc/live/MemorySpaceByteBuffer.java	30 Jul 2007 12:03:00 -0000
@@ -135,8 +135,8 @@
 	extends Request
     {
 	private long index;
-	private long length;
-	private long offset;
+	private int length;
+	private int offset;
 	private byte[] bytes;
 	private Mem mem;
 	private final int pid;
@@ -145,7 +145,7 @@
 	    mem = new Mem(pid);
 	    this.pid = pid;
 	}
-	private long peek(long index, byte[] bytes, long offset, long length) {
+	private int peek(long index, byte[] bytes, int offset, int length) {
 	    if (mem != null) {
 		try {
 		    return mem.pread (index, bytes, offset, length);
@@ -159,8 +159,8 @@
 	{
 	    length = peek(index, bytes, offset, length);
 	}
-	public long request (long index, byte[] bytes,
-			     long offset, long length)
+	public int request (long index, byte[] bytes,
+			     int offset, int length)
 	{
 	    if (isEventLoopThread()) {
 		return peek(index, bytes, offset, length);
@@ -176,7 +176,7 @@
 	}
     }
     private final PeeksRequest peeksRequest;
-    protected long peek (long index, byte[] bytes, long offset, long length)
+    protected int peek (long index, byte[] bytes, int offset, int length)
     {
 	return peeksRequest.request(index, bytes, offset, length);
     }
Index: frysk-core/frysk/proc/live/TestMemorySpaceByteBuffer.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/live/TestMemorySpaceByteBuffer.java,v
retrieving revision 1.2
diff -u -r1.2 TestMemorySpaceByteBuffer.java
--- frysk-core/frysk/proc/live/TestMemorySpaceByteBuffer.java	18 Jul 2007 20:00:31 -0000	1.2
+++ frysk-core/frysk/proc/live/TestMemorySpaceByteBuffer.java	30 Jul 2007 12:03:00 -0000
@@ -79,15 +79,15 @@
     {
 	private MemorySpaceByteBuffer buffer;
 	private long addr;
-	private long length;
+	private int length;
 	private byte[] bytes;
 	private Exception e;
-	AsyncPeeks (MemorySpaceByteBuffer buffer, long addr, long length)
+	AsyncPeeks (MemorySpaceByteBuffer buffer, long addr, int length)
 	{
 	    this.buffer = buffer;
 	    this.addr = addr;
 	    this.length = length;
-	    this.bytes = new byte[(int)length];
+	    this.bytes = new byte[length];
 	}
 	public void run ()
 	{
Index: frysk-sys/frysk/sys/FileDescriptor.java
===================================================================
RCS file: /cvs/frysk/frysk-sys/frysk/sys/FileDescriptor.java,v
retrieving revision 1.1
diff -u -r1.1 FileDescriptor.java
--- frysk-sys/frysk/sys/FileDescriptor.java	17 Jul 2007 18:01:41 -0000	1.1
+++ frysk-sys/frysk/sys/FileDescriptor.java	30 Jul 2007 12:03:00 -0000
@@ -168,7 +168,7 @@
      *
      * XXX: Since read is capped by byte[].length, int is returned.
      */
-    public native int read(byte[] bytes, long start, long length);
+    public native int read(byte[] bytes, int start, int length);
 
     /**
      * Write a single byte to the file descriptor.
@@ -179,7 +179,7 @@
      *
      * XXX: Since write is capped by byte[].lenght, int is returned.
      */
-    public native int write(byte[] bytes, long start, long length);
+    public native int write(byte[] bytes, int start, int length);
 
     /**
      * Close the file descriptor.
Index: frysk-sys/frysk/sys/Ptrace.java
===================================================================
RCS file: /cvs/frysk/frysk-sys/frysk/sys/Ptrace.java,v
retrieving revision 1.12
diff -u -r1.12 Ptrace.java
--- frysk-sys/frysk/sys/Ptrace.java	17 Jul 2007 18:01:42 -0000	1.12
+++ frysk-sys/frysk/sys/Ptrace.java	30 Jul 2007 12:03:00 -0000
@@ -190,8 +190,8 @@
 	 * Fetch up-to LENGTH bytes starting at ADDR of process PID,
 	 * store them in BYTES, starting at OFFSET.
 	 */
-	public native long peek (int pid, long addr, long length,
-				 byte[] bytes, long offset);
+	public native int peek (int pid, long addr, int length,
+				byte[] bytes, int offset);
 	private static native AddressSpace text ();
 	private static native AddressSpace data ();
 	private static native AddressSpace usr ();
Index: frysk-sys/frysk/sys/StatelessFile.java
===================================================================
RCS file: /cvs/frysk/frysk-sys/frysk/sys/StatelessFile.java,v
retrieving revision 1.1
diff -u -r1.1 StatelessFile.java
--- frysk-sys/frysk/sys/StatelessFile.java	17 Jul 2007 18:01:42 -0000	1.1
+++ frysk-sys/frysk/sys/StatelessFile.java	30 Jul 2007 12:03:00 -0000
@@ -63,10 +63,10 @@
 	this(new File(file));
     }
 
-    public native long pread (long fileOffset, byte[] bytes, long start,
-			      long length);
+    public native int pread (long fileOffset, byte[] bytes, int start,
+			     int length);
    
-    public native long pwrite (long fileOffset, byte[] bytes, long start,
-			       long length);
+    public native int pwrite (long fileOffset, byte[] bytes, int start,
+			      int length);
 }
 
Index: frysk-sys/frysk/sys/TestFileDescriptor.java
===================================================================
RCS file: /cvs/frysk/frysk-sys/frysk/sys/TestFileDescriptor.java,v
retrieving revision 1.1
diff -u -r1.1 TestFileDescriptor.java
--- frysk-sys/frysk/sys/TestFileDescriptor.java	17 Jul 2007 18:01:42 -0000	1.1
+++ frysk-sys/frysk/sys/TestFileDescriptor.java	30 Jul 2007 12:03:00 -0000
@@ -226,15 +226,15 @@
 	private IO(FileDescriptor fd) {
 	    this.fd = fd;
 	}
-	abstract void op(byte[] buf, long start, long length);
+	abstract void op(byte[] buf, int start, int length);
     }
 
     /**
      * Check that an IO operation throws an exception.
      */
     private void assertArrayIndexOutOfBounds(String what, IO io,
-					     byte[] buf, long start,
-					     long length)
+					     byte[] buf, int start,
+					     int length)
     {
 	boolean thrown = false;
 	try {
@@ -255,7 +255,7 @@
 	assertArrayIndexOutOfBounds("len + off > buf.length", io,
 				    new byte[1], 1, 1);
 	assertArrayIndexOutOfBounds("len + off < 0", io, new byte[1],
-				    0x7fffffffffffffffL, 1);
+				    Integer.MAX_VALUE, 1);
     }
 
     /**
@@ -264,7 +264,7 @@
     public void testReadOutOfBounds()
     {
 	verifyOutOfBounds(new IO(file) {
-		public void op(byte[] buf, long start, long length) {
+		public void op(byte[] buf, int start, int length) {
 		    fd.read(buf, start, length);
 		}
 	    });
@@ -272,7 +272,7 @@
     public void testWriteOutOfBounds()
     {
 	verifyOutOfBounds(new IO(file) {
-		public void op(byte[] buf, long start, long length) {
+		public void op(byte[] buf, int start, int length) {
 		    fd.write(buf, start, length);
 		}
 	    });
Index: frysk-sys/frysk/sys/TestPtrace.java
===================================================================
RCS file: /cvs/frysk/frysk-sys/frysk/sys/TestPtrace.java,v
retrieving revision 1.1
diff -u -r1.1 TestPtrace.java
--- frysk-sys/frysk/sys/TestPtrace.java	17 Jul 2007 18:01:42 -0000	1.1
+++ frysk-sys/frysk/sys/TestPtrace.java	30 Jul 2007 12:03:00 -0000
@@ -292,7 +292,7 @@
     }
 
     private void verifyOutOfBounds (String why, boolean expected,
-				    long length, byte[] bytes, int offset)
+				    int length, byte[] bytes, int offset)
     {
 	int pid = new AttachedSelf().hashCode();
 	boolean caught = false;
Index: frysk-sys/frysk/sys/TestStatelessFile.java
===================================================================
RCS file: /cvs/frysk/frysk-sys/frysk/sys/TestStatelessFile.java,v
retrieving revision 1.1
diff -u -r1.1 TestStatelessFile.java
--- frysk-sys/frysk/sys/TestStatelessFile.java	17 Jul 2007 18:01:42 -0000	1.1
+++ frysk-sys/frysk/sys/TestStatelessFile.java	30 Jul 2007 12:03:00 -0000
@@ -87,8 +87,8 @@
 	try {
 	    sfbad.pread(0,		// long fileOffset,
 		     bytes,	// byte[] bytes,
-		     0,		// long start,
-		     10);	// long length
+		     0,		// int start,
+		     10);	// int length
 	    assertTrue ("invalid file pread", false);
 	} catch (Errno ioe) {
 	    //	    System.out.println ("invalid file name");
@@ -98,8 +98,8 @@
 	try {
 	    sf.pread(-1,	// long fileOffset,
 		     bytes,	// byte[] bytes,
-		     0,		// long start,
-		     10);	// long length
+		     0,		// int start,
+		     10);	// int length
 	    assertTrue ("invalid file offset pread", false);
 	} catch (Errno ioe) {
 	    //	    System.out.println ("invalid file offset");
@@ -109,8 +109,8 @@
 	try {
 	    sf.pread(0,		// long fileOffset,
 		     bytes,	// byte[] bytes,
-		     -1,	// long start,
-		     10);	// long length
+		     -1,	// int start,
+		     10);	// int length
 	    assertTrue ("invalid buffer start pread", false);
 	} catch (ArrayIndexOutOfBoundsException ioe) {
 	    //	    System.out.println ("invalid buffer start");
@@ -120,7 +120,7 @@
 	try {
 	    sf.pread(0,		// long fileOffset,
 		     bytes,	// byte[] bytes,
-		     0,		// long start,
+		     0,		// int start,
 		     -1);	// long length
 	    assertTrue ("invalid length pread", false);
 	} catch (ArrayIndexOutOfBoundsException ioe) {
@@ -131,7 +131,7 @@
 	try {
 	    sf.pread(0,		// long fileOffset,
 		     bytes,	// byte[] bytes,
-		     0,		// long start,
+		     0,		// int start,
 		     BYTE_BUFFER_SIZE+1);	// long length
 	    assertTrue ("read overflow pread", false);
 	} catch (ArrayIndexOutOfBoundsException ioe) {
@@ -143,7 +143,7 @@
     
     public void testPread()
     {
-	long ilen;
+	int ilen;
 	final byte[] stb = st.getBytes();
 	TearDownFile tmp = TearDownFile.create ();
 	try {
@@ -155,6 +155,8 @@
 	    System.out.println ("TestStatelessFile() "  + ioe);
 	}
 
+	// Note cast to int, we cannot really read a file into a
+	// byte[] that is larger than a (unsigned) int.
 	byte[] bytes = new byte[(int)stlen];
 	StatelessFile sf = new StatelessFile(tmp);
 
@@ -163,8 +165,8 @@
 	try {
 	    ilen = sf.pread(0,		// long fileOffset,
 			    bytes,	// byte[] bytes,
-			    0,		// long start,
-			    tmp.length());	// long length
+			    0,		// int start,
+			    (int) tmp.length());	// int length
 	    assertEquals ("initial length pread", stlen, ilen);
 	    for (int i = 0; i < stlen; i++)
 		assertEquals ("initial bytes", stb[i], bytes[i]);
@@ -179,10 +181,10 @@
 	// StringBuffer than my way below, but I don't know what it is.  I'm a
 	// C guy.
 	final long fileOffset = 8;
-	final long start      = 6;
-	final long length     = 3;
+	final int start       = 6;
+	final int length      = 3;
 	StringBuffer sb = new StringBuffer (st);
-	sb.replace ((int)start, (int) (start + length),
+	sb.replace (start, start + length,
 		    st.substring ((int)fileOffset,
 				  (int) (fileOffset + length)));
 	String sbc = new String (sb);
@@ -190,8 +192,8 @@
 	try {
 	    ilen = sf.pread(fileOffset,	// long fileOffset,
 			    bytes,		// byte[] bytes,
-			    start,		// long start,
-			    length);	// long length
+			    start,		// int start,
+			    length);	// int length
 	    assertEquals ("sub-read length", length, ilen);
 	    for (int i = 0; i < stlen; i++)
 		assertEquals ("sub-read bytes", sbb[i], bytes[i]);
@@ -215,8 +217,8 @@
 	try {
 	    sfbad.pwrite(0,	// long fileOffset,
 			 bytes,	// byte[] bytes,
-			 0,	// long start,
-			 10);	// long length
+			 0,	// int start,
+			 10);	// int length
 	    assertTrue ("invalid file pread", false);
 	} catch (Errno ioe) {
 	    // System.out.println ("invalid file name");
@@ -226,8 +228,8 @@
 	try {
 	    sf.pwrite(-1,	// long fileOffset,
 		      bytes,	// byte[] bytes,
-		      0,	// long start,
-		      10);	// long length
+		      0,	// int start,
+		      10);	// int length
 	    assertTrue ("invalid file offset pwrite", false);
 	} catch (Errno ioe) {
 	    // System.out.println ("invalid file offset");
@@ -237,8 +239,8 @@
 	try {
 	    sf.pwrite(0,	// long fileOffset,
 		      bytes,	// byte[] bytes,
-		      -1,	// long start,
-		      10);	// long length
+		      -1,	// int start,
+		      10);	// int length
 	    assertTrue ("invalid buffer start pwrite", false);
 	} catch (ArrayIndexOutOfBoundsException ioe) {
 	    //System.out.println ("invalid buffer start");
@@ -248,8 +250,8 @@
 	try {
 	    sf.pwrite(0,	// long fileOffset,
 		      bytes,	// byte[] bytes,
-		      0,	// long start,
-		      -1);	// long length
+		      0,	// int start,
+		      -1);	// int length
 	    assertTrue ("invalid length pwrite", false);
 	} catch (ArrayIndexOutOfBoundsException ioe) {
 	    // System.out.println ("invalid length");
@@ -259,8 +261,8 @@
 	try {
 	    sf.pwrite(0,	// long fileOffset,
 		      bytes,	// byte[] bytes,
-		      0,	// long start,
-		      BYTE_BUFFER_SIZE+1);	// long length
+		      0,	// int start,
+		      BYTE_BUFFER_SIZE+1);	// int length
 	    assertTrue ("read overflow pwrite", false);
 	} catch (ArrayIndexOutOfBoundsException ioe) {
 	    // System.out.println ("read overflow");
@@ -272,7 +274,7 @@
     public void testPwriteHuge()
     {
 	try {
-	    long ilen;
+	    int ilen;
 	    //                        0123456789abcdef
 	    final long HugeOffset = 0x000000007fffffffL;
 	    File tmp = File.createTempFile("sftest", null);
@@ -284,8 +286,8 @@
 	    try {
 		ilen = sf.pwrite(HugeOffset,		// long fileOffset,
 				 stb,		// byte[] bytes,
-				 0,		// long start,
-				 stb.length);	// long length
+				 0,		// int start,
+				 stb.length);	// int length
 		stlen = tmp.length();
 		assertEquals ("initial length pwrite", stb.length, ilen);
 	    } catch (Errno ioe) {
@@ -303,7 +305,7 @@
 	//	final int BYTE_BUFFER_SIZE = 128;
 	//byte[] bytes = new byte[BYTE_BUFFER_SIZE];
 
-	long ilen;
+	int ilen;
 	long stlen = -1;
 	TearDownFile tmp = TearDownFile.create ();
 	StatelessFile sf = new StatelessFile(tmp);
@@ -313,8 +315,8 @@
 	try {
 	    ilen = sf.pwrite(0,			// long fileOffset,
 			     stb,		// byte[] bytes,
-			     0,			// long start,
-			     stb.length);	// long length
+			     0,			// int start,
+			     stb.length);	// int length
 	    stlen = tmp.length();
 	    assertEquals ("initial length pwrite", stb.length, ilen);
 	} catch (Errno ioe) {
@@ -337,20 +339,20 @@
 	// copy of the original string used to create the file.  Compare the
 	// results.
 	final long fileOffset = 8;
-	final long start      = 6;
-	final long length     = 3;
+	final int start       = 6;
+	final int  length     = 3;
 	StringBuffer sb = new StringBuffer (st);
 	sb.replace ((int)fileOffset, (int) (fileOffset + length),
-		    st.substring ((int)start,
-				  (int) (start + length)));
+		    st.substring (start,
+				  start + length));
 	byte[] scb = st.getBytes();
 	String sbc = new String (sb);
 
 	try {
 	    ilen = sf.pwrite(fileOffset,	// long fileOffset,
 			     scb,		// byte[] bytes,
-			     start,		// long start,
-			     length);	// long length
+			     start,		// int start,
+			     length);	// int length
 	    assertEquals ("sub-write length", length, ilen);
 	    //	    for (int i = 0; i < stlen; i++)
 	    //	assertEquals ("sub-read bytes", sbb[i], bytes[i]);
Index: frysk-sys/frysk/sys/cni/Errno.cxx
===================================================================
RCS file: /cvs/frysk/frysk-sys/frysk/sys/cni/Errno.cxx,v
retrieving revision 1.13
diff -u -r1.13 Errno.cxx
--- frysk-sys/frysk/sys/cni/Errno.cxx	26 Jul 2007 18:45:30 -0000	1.13
+++ frysk-sys/frysk/sys/cni/Errno.cxx	30 Jul 2007 12:03:00 -0000
@@ -444,7 +444,7 @@
 }
 
 void
-verifyBounds (jbyteArray bytes, jlong start, jlong length)
+verifyBounds (jbyteArray bytes, jint start, jint length)
 {
   if (start < 0)
     throw new java::lang::ArrayIndexOutOfBoundsException ();
Index: frysk-sys/frysk/sys/cni/Errno.hxx
===================================================================
RCS file: /cvs/frysk/frysk-sys/frysk/sys/cni/Errno.hxx,v
retrieving revision 1.10
diff -u -r1.10 Errno.hxx
--- frysk-sys/frysk/sys/cni/Errno.hxx	26 Jul 2007 18:45:30 -0000	1.10
+++ frysk-sys/frysk/sys/cni/Errno.hxx	30 Jul 2007 12:03:00 -0000
@@ -121,4 +121,4 @@
  * Throw an ArrayIndexOutOfBounds exception if START and LENGTH do not
  * fall within the byte array.
  */
-extern void verifyBounds (jbyteArray bytes, jlong start, jlong length);
+extern void verifyBounds (jbyteArray bytes, jint start, jint length);
Index: frysk-sys/frysk/sys/cni/FileDescriptor.cxx
===================================================================
RCS file: /cvs/frysk/frysk-sys/frysk/sys/cni/FileDescriptor.cxx,v
retrieving revision 1.3
diff -u -r1.3 FileDescriptor.cxx
--- frysk-sys/frysk/sys/cni/FileDescriptor.cxx	26 Jul 2007 18:45:30 -0000	1.3
+++ frysk-sys/frysk/sys/cni/FileDescriptor.cxx	30 Jul 2007 12:03:00 -0000
@@ -80,7 +80,7 @@
 }
 
 jint
-frysk::sys::FileDescriptor::write (jbyteArray bytes, jlong off, jlong len)
+frysk::sys::FileDescriptor::write (jbyteArray bytes, jint off, jint len)
 {
   verifyBounds (bytes, off, len);
   errno = 0;
@@ -147,7 +147,7 @@
 }
 
 jint
-frysk::sys::FileDescriptor::read (jbyteArray bytes, jlong off, jlong len)
+frysk::sys::FileDescriptor::read (jbyteArray bytes, jint off, jint len)
 {
   verifyBounds (bytes, off, len);
   return doRead (fd, elements(bytes) + off, len);
Index: frysk-sys/frysk/sys/cni/Ptrace.cxx
===================================================================
RCS file: /cvs/frysk/frysk-sys/frysk/sys/cni/Ptrace.cxx,v
retrieving revision 1.12
diff -u -r1.12 Ptrace.cxx
--- frysk-sys/frysk/sys/cni/Ptrace.cxx	17 Jul 2007 18:01:42 -0000	1.12
+++ frysk-sys/frysk/sys/cni/Ptrace.cxx	30 Jul 2007 12:03:00 -0000
@@ -220,9 +220,9 @@
   return byte;
 }
 
-jlong
-frysk::sys::Ptrace$AddressSpace::peek (jint pid, jlong addr, jlong length,
-				       jbyteArray bytes, jlong offset)
+jint
+frysk::sys::Ptrace$AddressSpace::peek (jint pid, jlong addr, jint length,
+				       jbyteArray bytes, jint offset)
 {
    if (offset < 0)
     throw new java::lang::ArrayIndexOutOfBoundsException (JvNewStringUTF("Offset < 0"));
Index: frysk-sys/frysk/sys/cni/StatelessFile.cxx
===================================================================
RCS file: /cvs/frysk/frysk-sys/frysk/sys/cni/StatelessFile.cxx,v
retrieving revision 1.2
diff -u -r1.2 StatelessFile.cxx
--- frysk-sys/frysk/sys/cni/StatelessFile.cxx	26 Jul 2007 18:45:30 -0000	1.2
+++ frysk-sys/frysk/sys/cni/StatelessFile.cxx	30 Jul 2007 12:03:00 -0000
@@ -52,11 +52,11 @@
 #include "frysk/sys/Errno$Esrch.h"
 #include "frysk/sys/cni/Errno.hxx"
 
-jlong
+jint
 frysk::sys::StatelessFile::pread (jlong fileOffset,
 				  jbyteArray bytes,
-				  jlong start,
-				  jlong length)
+				  jint start,
+				  jint length)
 {
   verifyBounds (bytes, start, length);
   
@@ -70,19 +70,19 @@
   if (rc < 0) {
     int savedErrno = errno;
     ::close (fd);
-    throwErrno (savedErrno, "pread", "fd %d, count %ld, offset %ld",
-    		fd, (long)length, (long)fileOffset);
+    throwErrno (savedErrno, "pread", "fd %d, count %d, offset %ld",
+    		fd, (int) length, (long)fileOffset);
   }
 
   ::close (fd);
   return rc;
 }
 
-jlong
+jint
 frysk::sys::StatelessFile::pwrite (jlong fileOffset,
 				   jbyteArray bytes,
-				   jlong start,
-				   jlong length)
+				   jint start,
+				   jint length)
 {
   verifyBounds (bytes, start, length);
   
@@ -96,8 +96,8 @@
   if (rc < 0) {
     int savedErrno = errno;
     ::close (fd);
-    throwErrno (savedErrno, "pwrite", "fd %d, count %ld, offset %ld",
-		fd, (long)length, (long)fileOffset);
+    throwErrno (savedErrno, "pwrite", "fd %d, count %d, offset %ld",
+		fd, (int) length, (long)fileOffset);
   }
   
   ::close (fd);
Index: frysk-sys/inua/eio/ByteBuffer.java
===================================================================
RCS file: /cvs/frysk/frysk-sys/inua/eio/ByteBuffer.java,v
retrieving revision 1.1
diff -u -r1.1 ByteBuffer.java
--- frysk-sys/inua/eio/ByteBuffer.java	17 Jul 2007 18:01:44 -0000	1.1
+++ frysk-sys/inua/eio/ByteBuffer.java	30 Jul 2007 12:03:00 -0000
@@ -1,4 +1,5 @@
 // This file is part of INUA.  Copyright 2004, 2005, Andrew Cagney
+// Copyright 2007, Red Hat Inc.
 //
 // INUA is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by
@@ -68,33 +69,33 @@
    */
   protected abstract void poke (long caret, int val);
 
-  protected long peek (long caret, byte[] bytes, long off, long len)
+  protected int peek (long caret, byte[] bytes, int off, int len)
   {
     logger.log(Level.FINE, "entering peek, caret: 0x{0}, off: 0x{1}, len: 0x{2}",
-               new Object[]{Long.toHexString(caret), Long.toHexString(off), 
-                            Long.toHexString(len)});
-    for (long i = 0; i < len; i++)
+               new Object[]{Long.toHexString(caret), Integer.toHexString(off), 
+                            Integer.toHexString(len)});
+    for (int i = 0; i < len; i++)
       {
 	logger.log(Level.FINEST, "on byte: 0x{0}", Long.toHexString(i));
-        bytes[(int) (off + i)] = (byte) peek(caret + i);
+        bytes[off + i] = (byte) peek(caret + i);
       }
     return len;
   }
 
-  protected long poke (long caret, byte[] bytes, long off, long len)
+  protected int poke (long caret, byte[] bytes, int off, int len)
   {
-    for (long i = 0; i < len; i++)
+    for (int i = 0; i < len; i++)
       {
-        poke(caret + i, bytes[(int) (off + i)]);
+        poke(caret + i, bytes[off + i]);
       }
     return len;
   }
 
-  protected final void peekFully (long caret, byte[] bytes, long off, long len)
+  protected final void peekFully (long caret, byte[] bytes, int off, int len)
   {
     logger.log(Level.FINE, "entering peekFully, caret: 0x{0}, off: 0x{1}, len: 0x{2}\n",
-               new Object[]{Long.toHexString(caret), Long.toHexString(off), 
-                            Long.toHexString(len)});
+               new Object[]{Long.toHexString(caret), Integer.toHexString(off), 
+                            Integer.toHexString(len)});
     while (len > 0)
       {
         long xfer = peek(caret, bytes, off, len);
@@ -105,7 +106,7 @@
     logger.log(Level.FINE, "exiting peekFully\n");
   }
 
-  protected final void pokeFully (long caret, byte[] bytes, long off, long len)
+  protected final void pokeFully (long caret, byte[] bytes, int off, int len)
   {
     while (len > 0)
       {
Index: frysk-sys/inua/eio/MmapByteBuffer.java
===================================================================
RCS file: /cvs/frysk/frysk-sys/inua/eio/MmapByteBuffer.java,v
retrieving revision 1.1
diff -u -r1.1 MmapByteBuffer.java
--- frysk-sys/inua/eio/MmapByteBuffer.java	17 Jul 2007 18:01:44 -0000	1.1
+++ frysk-sys/inua/eio/MmapByteBuffer.java	30 Jul 2007 12:03:00 -0000
@@ -1,4 +1,5 @@
 // This file is part of INUA.  Copyright 2004, 2005, Andrew Cagney
+// Copyright 2007, Red Hat Inc.
 //
 // INUA is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by
@@ -81,6 +82,6 @@
     native protected final int peek (long index);
     native protected final void poke (long index, int val);
     
-    native protected final long peek (long index, byte[] bytes,
-				      long off, long len);
+    native protected final int peek (long index, byte[] bytes,
+				      int off, int len);
 }
Index: frysk-sys/inua/eio/cni/MmapByteBuffer.cxx
===================================================================
RCS file: /cvs/frysk/frysk-sys/inua/eio/cni/MmapByteBuffer.cxx,v
retrieving revision 1.1
diff -u -r1.1 MmapByteBuffer.cxx
--- frysk-sys/inua/eio/cni/MmapByteBuffer.cxx	17 Jul 2007 18:01:44 -0000	1.1
+++ frysk-sys/inua/eio/cni/MmapByteBuffer.cxx	30 Jul 2007 12:03:00 -0000
@@ -1,4 +1,5 @@
 // This file is part of INUA.  Copyright 2004, 2005, Andrew Cagney
+// Copyright 2007, Red Hat Inc.
 //
 // INUA is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by
@@ -89,9 +90,9 @@
   p[caret] = value;
 }
 
-jlong
-inua::eio::MmapByteBuffer::peek (jlong caret, jbyteArray bytes, jlong off,
-			     jlong len)
+jint
+inua::eio::MmapByteBuffer::peek (jlong caret, jbyteArray bytes, jint off,
+				 jint len)
 {
   u_int8_t *p = (u_int8_t*) (long) this->map->byteData;
   memcpy (elements (bytes) + off, p + caret, len);

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] LogicalMemoryBuffer
  2007-07-20 12:02 [patch] LogicalMemoryBuffer Mark Wielaard
  2007-07-30 12:42 ` Mark Wielaard
@ 2007-08-02 11:26 ` Mark Wielaard
  2007-08-03 14:03   ` Phil Muldoon
  1 sibling, 1 reply; 5+ messages in thread
From: Mark Wielaard @ 2007-08-02 11:26 UTC (permalink / raw)
  To: frysk

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

Hi,

On Fri, 2007-07-20 at 14:02 +0200, Mark Wielaard wrote:
> - LogicalMemoryBuffer is a filter on top of AddressSpaceByteBuffer but
> really should be on top of MemorySpaceByteBuffer which is more
> effecient. The used to be interface compatible, but a recent change to
> MemorySpaceByteBuffer changed that and made that it less easy to wrap.
> MemorySpaceByteBuffer is really just an optimization of
> AddressSpaceByteBuffer (in the case of AddressSpace.TEXT/DATA) and all
> code should go through the optimized path (StateLessFile) for accessing
> memory if the AddressSpace allows it. So I am going to merge the two
> (and fix up the places that currently use the slow path). Then I'll also
> add the ByteBuffer.get() optimization that Chris pointed out.

This patch implements the above and fixes bug #4827 and #4760 by adding
a bulk put ByteBuffer method as Andrew suggested and using the
StateLessFile support for this as Chris implemented. It also updates
RegisterSetByteBuffer in the same way. LogicalMemoryBuffer is now marked
as read only to signal that to change memory you should go through the
raw memory view (if you need this, then you are probably interfering
with the breakpoint support, so need to update that code to deal with
other ways the underlying memory could change). Various methods have
been updated to use the bulk put methods now.

frysk-core/frysk/proc/live/ChangeLog
2007-08-02  Mark Wielaard  <mwielaard@redhat.com>

    * AddressSpaceByteBuffer.java (mem): New field.
    (pokesRequest): Likewise.
    (AddressSpaceByteBuffer): Initialize mem and pokesRequest.
    (PeeksRequest.peek): New method.
    (PeeksRequest.execute): use peek().
    (PeeksRequest.request): Likewise.
    (PokesRequest): New inner class.
    (poke): New method.
    * LinuxTask.java (getRawMemory): Use AddressSpaceByteBuffer.
    * LogicalMemoryBuffer.java (poke): New methods marked as
    unsupported.
    * MemorySpaceByteBuffer.java: Removed.
    * RegisterSetByteBuffer.java (peek): Use System.arraycopy().
    (poke): New method.
    * TestMemorySpaceByteBuffer.java: Removed.
    * TestByteBuffer.java: Merged in TestMemorySpaceByteBuffer tests,
    made test more generic to test all possible buffers, add bulk put
    tests.

frysk-core/frysk/proc/ChangeLog
2007-08-02  Mark Wielaard  <mwielaard@redhat.com>

    * Breakpoint.java (set): Use raw memory and bulk put method.
    (reset): Likewise.
    * BreakpointAddresses.java: Make public.
    * Instruction.java (setupExecuteOutOfLine): use raw memory and
    bulk put method.

frysk-sys/inua/ChangeLog
2007-08-02  Mark Wielaard  <mwielaard@redhat.com>

    * ByteBuffer.java (put(byte[],int,int)): New
    bulk put method.
    (put(byte[])): likewise.

The biggest part of the patch is actually the removal of now redundant
classes and the addition of more tests and making those tests more
generic to test all possible ByteBuffers. Yeah, less code, more
tests! :) All new ByteBuffer tests PASS and no new regressions as tested
on x86 (F7) and x86_64 (FC6).

Cheers,

Mark


[-- Attachment #2: buf.patch --]
[-- Type: text/x-patch, Size: 32643 bytes --]

Index: frysk-core/frysk/proc/Breakpoint.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/Breakpoint.java,v
retrieving revision 1.14
diff -u -r1.14 Breakpoint.java
--- frysk-core/frysk/proc/Breakpoint.java	20 Jul 2007 11:36:06 -0000	1.14
+++ frysk-core/frysk/proc/Breakpoint.java	2 Aug 2007 10:48:33 -0000
@@ -138,7 +138,7 @@
    */
   private void set(Task task)
   {
-    ByteBuffer buffer = task.getMemory();
+    ByteBuffer buffer = task.getRawMemory();
     Isa isa = task.getIsa();
     Instruction bpInstruction = isa.getBreakpointInstruction();
     
@@ -147,8 +147,7 @@
     // Put in the breakpoint.
     byte[] bs = bpInstruction.getBytes();
     buffer.position(address);
-    for (int index = 0; index < bs.length; index++)
-      buffer.putByte(bs[index]);
+    buffer.put(bs);
   }
 
   /**
@@ -174,7 +173,7 @@
    */
   private void reset(Task task)
   {
-    ByteBuffer buffer = task.getMemory();
+    ByteBuffer buffer = task.getRawMemory();
     buffer.position(address);
     
     Isa isa = task.getIsa();
@@ -185,8 +184,7 @@
 
     // Only need to put back the part of the original instruction
     // covered by the breakpoint instruction bytes.
-    for (int index = 0; index < bp.length; index++)
-      buffer.putByte(bs[index]);
+    buffer.put(bs, 0, bp.length);
   }
 
   /**
Index: frysk-core/frysk/proc/BreakpointAddresses.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/BreakpointAddresses.java,v
retrieving revision 1.7
diff -u -r1.7 BreakpointAddresses.java
--- frysk-core/frysk/proc/BreakpointAddresses.java	20 Jul 2007 11:36:06 -0000	1.7
+++ frysk-core/frysk/proc/BreakpointAddresses.java	2 Aug 2007 10:48:33 -0000
@@ -79,7 +79,7 @@
   /**
    * Package private constructor used by the Proc when created.
    */
-  BreakpointAddresses(Proc proc)
+  public BreakpointAddresses(Proc proc)
   {
     this.proc = proc;
     map = new HashMap();
Index: frysk-core/frysk/proc/Instruction.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/Instruction.java,v
retrieving revision 1.2
diff -u -r1.2 Instruction.java
--- frysk-core/frysk/proc/Instruction.java	2 Jul 2007 10:05:18 -0000	1.2
+++ frysk-core/frysk/proc/Instruction.java	2 Aug 2007 10:48:33 -0000
@@ -140,10 +140,9 @@
    */
   public void setupExecuteOutOfLine(Task task, long pc, long address)
   {
-    ByteBuffer buffer = task.getMemory();
+    ByteBuffer buffer = task.getRawMemory();
     buffer.position(address);
-    for (int i = 0; i < instr.length; i++)
-      buffer.putByte(instr[i]);
+    buffer.put(instr);
     task.getIsa().setPC(task, address);
   }
 
Index: frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java,v
retrieving revision 1.3
diff -u -r1.3 AddressSpaceByteBuffer.java
--- frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java	30 Jul 2007 12:42:08 -0000	1.3
+++ frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java	2 Aug 2007 10:48:33 -0000
@@ -40,7 +40,9 @@
 package frysk.proc.live;
 
 import inua.eio.ByteBuffer;
+import frysk.sys.Errno;
 import frysk.sys.Ptrace.AddressSpace;
+import frysk.sys.proc.Mem;
 import frysk.event.Request;
 import frysk.proc.Manager;
 
@@ -50,6 +52,9 @@
     protected final AddressSpace addressSpace;
     protected final int pid;
 
+    // Direct files access if possible, or null otherwise.
+    final Mem mem;
+
     protected AddressSpaceByteBuffer (int pid, AddressSpace addressSpace,
 				    long lowerExtreem, long upperExtreem)
     {
@@ -59,6 +64,13 @@
 	peekRequest = new PeekRequest();
 	pokeRequest = new PokeRequest();
 	peeksRequest = new PeeksRequest();
+	pokesRequest = new PokesRequest();
+
+	if (addressSpace == AddressSpace.TEXT
+	    || addressSpace == AddressSpace.DATA)
+	  mem = new Mem(pid);
+	else
+	  mem = null;
     }
     public AddressSpaceByteBuffer (int pid, AddressSpace addressSpace)
     {
@@ -137,15 +149,34 @@
 	{
 	    super(Manager.eventLoop);
 	}
+
+        private int peek(long index, byte[] bytes, int offset, int length)
+	{
+	  if (mem != null)
+	    {
+	      try
+		{
+		  return mem.pread(index, bytes, offset, length);
+		}
+	      catch (Errno e)
+		{
+		  // try again through address space.
+		}
+	    }
+
+	  return addressSpace.peek(pid, index, length, bytes, offset);
+	}
+
 	public void execute ()
 	{
-	    length = addressSpace.peek(pid, index, length, bytes, offset);
+	  length = peek(index, bytes, offset, length);
 	}
+
 	public int request (long index, byte[] bytes,
 			    int offset, int length)
 	{
 	    if (isEventLoopThread())
-		return addressSpace.peek(pid, index, length, bytes, offset);
+	      return peek(index, bytes, offset, length);
 	    else synchronized (this) {
 		this.index = index;
 		this.bytes = bytes;
@@ -162,6 +193,67 @@
 	return peeksRequest.request(index, bytes, offset, length);
     }
 
+ 
+    private class PokesRequest
+      extends Request
+    {
+      private long index;
+      private int length;
+      private int offset;
+      private byte[] bytes;
+
+      PokesRequest()
+      {
+	super(Manager.eventLoop);
+      }
+
+      private int poke(long index, byte[] bytes, int offset, int length)
+      {
+	if (mem != null)
+	  {
+	    try
+	      {
+		return mem.pwrite(index, bytes, offset, length);
+	      }
+	    catch (Errno e)
+	      {
+		// try again through address space.
+	      }
+	  }
+	
+	// We lose here since AddressSpace isn't optimized for bulk poke.
+	for (int i = offset; i < length; i++)
+	  addressSpace.poke(pid, index + i, bytes[i]);
+	return length;
+      }
+
+      public void execute ()
+      {
+	length = poke(index, bytes, offset, length);
+      }
+
+      public int request (long index, byte[] bytes,
+			  int offset, int length)
+      {
+	if (isEventLoopThread())
+	  return poke(index, bytes, offset, length);
+	else synchronized (this) {
+	  this.index = index;
+	  this.bytes = bytes;
+	  this.offset = offset;
+	  this.length = length;
+	  request();
+	  return length;
+	}
+      }
+    }
+
+    private final PokesRequest pokesRequest;
+    protected int poke(long index, byte[] bytes, int off, int len)
+    {
+      return pokesRequest.request(index, bytes, off, len);
+    }
+
     protected ByteBuffer subBuffer (ByteBuffer parent, long lowerExtreem,
 				    long upperExtreem)
     {
Index: frysk-core/frysk/proc/live/LinuxTask.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/live/LinuxTask.java,v
retrieving revision 1.5
diff -u -r1.5 LinuxTask.java
--- frysk-core/frysk/proc/live/LinuxTask.java	30 Jul 2007 12:42:08 -0000	1.5
+++ frysk-core/frysk/proc/live/LinuxTask.java	2 Aug 2007 10:48:33 -0000
@@ -91,13 +91,14 @@
 
 
     /**
-     * Return the raw memory byte-buffer.
+     * Return the raw memory byte-buffer. This is the TEXT/DATA area.
      */
     public ByteBuffer getRawMemory ()
     {
 	logger.log(Level.FINE, "Begin fillMemory\n", this);
 	ByteOrder byteOrder = getIsa().getByteOrder();
-	ByteBuffer memory = new MemorySpaceByteBuffer(getTid());
+	ByteBuffer memory = new AddressSpaceByteBuffer(getTid(),
+						       AddressSpace.DATA);
 	memory.order(byteOrder);
 	logger.log(Level.FINE, "End fillMemory\n", this); 
 	return memory;
Index: frysk-core/frysk/proc/live/LogicalMemoryBuffer.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/live/LogicalMemoryBuffer.java,v
retrieving revision 1.2
diff -u -r1.2 LogicalMemoryBuffer.java
--- frysk-core/frysk/proc/live/LogicalMemoryBuffer.java	30 Jul 2007 12:42:08 -0000	1.2
+++ frysk-core/frysk/proc/live/LogicalMemoryBuffer.java	2 Aug 2007 10:48:33 -0000
@@ -127,7 +127,17 @@
 	return super.peek(index + r, bytes, offset + r, length - r) + r;
       }
   }
+
+  protected void poke (long index, int value)
+  {
+    throw new UnsupportedOperationException("read only memory buffer");
+  }
   
+  protected int poke(long index, byte[] bytes, int offset, int length)
+  {
+    throw new UnsupportedOperationException("read only memory buffer");
+  }
+
   protected ByteBuffer subBuffer(ByteBuffer parent,
 				 long lower, long upper)
   {
Index: frysk-core/frysk/proc/live/MemorySpaceByteBuffer.java
===================================================================
RCS file: frysk-core/frysk/proc/live/MemorySpaceByteBuffer.java
diff -N frysk-core/frysk/proc/live/MemorySpaceByteBuffer.java
--- frysk-core/frysk/proc/live/MemorySpaceByteBuffer.java	30 Jul 2007 12:42:08 -0000	1.5
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,193 +0,0 @@
-// This file is part of the program FRYSK.
-// 
-// Copyright 2007 Oracle Corporation.
-// Copyright 2007, 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 inua.eio.ByteBuffer;
-import frysk.sys.Ptrace.AddressSpace;
-import frysk.sys.Errno;
-import frysk.sys.proc.Mem;
-import frysk.event.Request;
-import frysk.proc.Manager;
-
-public class MemorySpaceByteBuffer
-    extends ByteBuffer
-{
-    private MemorySpaceByteBuffer (long lowerExtreem,
-				   long upperExtreem,
-				   PeekRequest peekRequest,
-				   PokeRequest pokeRequest,
-				   PeeksRequest peeksRequest)
-    {
-	super (lowerExtreem, upperExtreem);
-	this.peekRequest = peekRequest;
-	this.pokeRequest = pokeRequest;
-	this.peeksRequest = peeksRequest;
-    }
-    public MemorySpaceByteBuffer (int pid)
-    {
-	this (0, AddressSpace.TEXT.length (), new PeekRequest(pid),
-	      new PokeRequest(pid), new PeeksRequest(pid));
-    }
-
-    private static class PeekRequest
-	extends Request
-    {
-	private long index;
-	private int value;
-	private final int pid;
-	PeekRequest(int pid)
-	{
-	    super(Manager.eventLoop);
-	    this.pid = pid;
-	}
-	public void execute ()
-	{
-	    value = AddressSpace.TEXT.peek(pid, index);
-	}
-	public int request (long index)
-	{
-	    if (isEventLoopThread())
-		return AddressSpace.TEXT.peek(pid, index);
-	    else synchronized (this) {
-		this.index = index;
-		request();
-		return value;
-	    }
-	}
-    }
-    private final PeekRequest peekRequest;
-    protected int peek (long index)
-    {
-	return peekRequest.request (index);
-    }
-
-    private static class PokeRequest
-	extends Request
-    {
-	private long index;
-	private int value;
-	private final int pid;
-	PokeRequest(int pid)
-	{
-	    super(Manager.eventLoop);
-	    this.pid = pid;
-	}
-	public void execute ()
-	{
-	    AddressSpace.TEXT.poke(pid, index, value);
-	}
-	public void request (long index, int value)
-	{
-	    if (isEventLoopThread())
-		AddressSpace.TEXT.poke(pid, index, value);
-	    else synchronized (this) {
-		this.index = index;
-		this.value = value;
-		request();
-	    }
-	}
-    }
-    private final PokeRequest pokeRequest;
-    protected void poke (long index, int value)
-    {
-	pokeRequest.request (index, value);
-    }
-
-    private static class PeeksRequest
-	extends Request
-    {
-	private long index;
-	private int length;
-	private int offset;
-	private byte[] bytes;
-	private Mem mem;
-	private final int pid;
-	PeeksRequest(int pid) {
-	    super(Manager.eventLoop);
-	    mem = new Mem(pid);
-	    this.pid = pid;
-	}
-	private int peek(long index, byte[] bytes, int offset, int length) {
-	    if (mem != null) {
-		try {
-		    return mem.pread (index, bytes, offset, length);
-		} catch (Errno ioe) {
-		    mem = null;
-		}
-	    }
-	    return AddressSpace.TEXT.peek(pid, index, length, bytes, offset);
-	}
-	public void execute ()
-	{
-	    length = peek(index, bytes, offset, length);
-	}
-	public int request (long index, byte[] bytes,
-			     int offset, int length)
-	{
-	    if (isEventLoopThread()) {
-		return peek(index, bytes, offset, length);
-	    }
-	    else synchronized (this) {
-		this.index = index;
-		this.bytes = bytes;
-		this.offset = offset;
-		this.length = length;
-		request();
-		return length;
-	    }
-	}
-    }
-    private final PeeksRequest peeksRequest;
-    protected int peek (long index, byte[] bytes, int offset, int length)
-    {
-	return peeksRequest.request(index, bytes, offset, length);
-    }
-
-    protected ByteBuffer subBuffer (ByteBuffer parent, long lowerExtreem,
-				    long upperExtreem)
-    {
-	MemorySpaceByteBuffer up = (MemorySpaceByteBuffer)parent;
-	return new MemorySpaceByteBuffer (lowerExtreem, upperExtreem,
-					  up.peekRequest,
-					  up.pokeRequest,
-					  up.peeksRequest);
-    }
-}
Index: frysk-core/frysk/proc/live/RegisterSetByteBuffer.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/live/RegisterSetByteBuffer.java,v
retrieving revision 1.1
diff -u -r1.1 RegisterSetByteBuffer.java
--- frysk-core/frysk/proc/live/RegisterSetByteBuffer.java	26 Jun 2007 22:12:52 -0000	1.1
+++ frysk-core/frysk/proc/live/RegisterSetByteBuffer.java	2 Aug 2007 10:48:33 -0000
@@ -137,14 +137,20 @@
 	setRegs();
     }
   
-    protected long peek (long index, byte[] bytes, long off, long len) 
+    protected int peek (long index, byte[] bytes, int off, int len) 
     {
 	getRegs();
-	for (int i = 0; i < len; i++) {
-	    bytes[(int)off + i] = this.bytes[(int)index + i];
-	}
+	System.arraycopy(this.bytes, (int) index, bytes, off, len);
 	return len;
     }
+
+    protected int poke (long index, byte[] bytes, int off, int len)
+    {
+      getRegs();
+      System.arraycopy(bytes, off, this.bytes, (int) index, len);
+      setRegs();
+      return len;
+    }
   
     protected ByteBuffer subBuffer (ByteBuffer parent, long lowerExtreem,
 				    long upperExtreem)
Index: frysk-core/frysk/proc/live/TestByteBuffer.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/live/TestByteBuffer.java,v
retrieving revision 1.2
diff -u -r1.2 TestByteBuffer.java
--- frysk-core/frysk/proc/live/TestByteBuffer.java	18 Jul 2007 20:00:31 -0000	1.2
+++ frysk-core/frysk/proc/live/TestByteBuffer.java	2 Aug 2007 10:48:33 -0000
@@ -41,64 +41,125 @@
 
 import inua.eio.ByteBuffer;
 import frysk.junit.TestCase;
-import frysk.testbed.TearDownProcess;
 import frysk.testbed.AttachedSelf;
 import frysk.testbed.LocalMemory;
 import frysk.sys.Ptrace.RegisterSet;
 import frysk.sys.Ptrace.AddressSpace;
 import frysk.proc.Manager;
+import frysk.proc.BreakpointAddresses;
+
+import java.util.Arrays;
 
 public class TestByteBuffer
     extends TestCase
 {
-    public void tearDown()
+    // There are 2 sets of byte buffers to check, those that hold memory
+    // and those that hold various register values.
+    private ByteBuffer[] addressBuffers;
+    private ByteBuffer[] registerBuffers;
+
+    public void setUp () throws Exception
     {
-	TearDownProcess.tearDown();
+      int pid;
+      ByteBuffer addressSpaceByteBufferText;
+      ByteBuffer addressSpaceByteBufferData;
+      ByteBuffer memorySpaceByteBuffer;
+      ByteBuffer usrByteBuffer;
+      ByteBuffer registerByteBuffer;
+      ByteBuffer fpregisterByteBuffer;
+      ByteBuffer fpxregisterByteBuffer;
+
+      // Watch for spawned processes, etc.
+      super.setUp();
+
+      pid = new AttachedSelf().hashCode();
+
+      // Text and Data are the same, but can be accessed independently.
+      addressSpaceByteBufferText
+	= new AddressSpaceByteBuffer (pid, AddressSpace.TEXT);
+      addressSpaceByteBufferData
+	= new AddressSpaceByteBuffer (pid, AddressSpace.DATA);
+
+      // Cheat with the proc, it is not actually used if no
+      // breakpoints are set (testing with breakpoints set is done through
+      // TestTaskObserverCode in the various BreakpointMemoryView tests).
+      // LogicalMemory isn't writable atm, so we exclude it from those
+      // tests (the raw variant is of course).
+      frysk.proc.Proc proc = new frysk.proc.dummy.Proc();
+      BreakpointAddresses breakpoints = new BreakpointAddresses(proc);
+      memorySpaceByteBuffer = new LogicalMemoryBuffer(pid,
+						      AddressSpace.TEXT,
+						      breakpoints);
+
+      addressBuffers = new ByteBuffer[] { addressSpaceByteBufferText,
+					  addressSpaceByteBufferData,
+					  memorySpaceByteBuffer };
+
+      // The USER area is seen as a register buffer.
+      usrByteBuffer = new AddressSpaceByteBuffer(pid, AddressSpace.USR);
+
+      // See how many other register sets there are.
+      if (RegisterSet.REGS != null)
+	{
+	  registerByteBuffer
+	    = new RegisterSetByteBuffer (pid, RegisterSet.REGS);
+	  if (RegisterSet.FPREGS != null)
+	    {
+	      fpregisterByteBuffer
+		= new RegisterSetByteBuffer (pid, RegisterSet.FPREGS);
+	      if (RegisterSet.FPXREGS != null)
+		{
+		  fpxregisterByteBuffer
+		    = new RegisterSetByteBuffer (pid, RegisterSet.FPXREGS);
+		  registerBuffers = new ByteBuffer[] { usrByteBuffer,
+						       registerByteBuffer,
+						       fpregisterByteBuffer,
+						       fpxregisterByteBuffer };
+		}
+	      else
+		registerBuffers = new ByteBuffer[] { usrByteBuffer,
+						     registerByteBuffer,
+						     fpregisterByteBuffer };
+	    }
+	  else
+	    registerBuffers = new ByteBuffer[] { usrByteBuffer,
+						 registerByteBuffer };
+	}
+      else
+	registerBuffers = new ByteBuffer[] { usrByteBuffer };
     }
-    private int pid;
-    private ByteBuffer addressSpaceByteBuffer;
-    private ByteBuffer memorySpaceByteBuffer;
-    private ByteBuffer registerByteBuffer;
 
-    public void setUp ()
+    public void tearDown() throws Exception
     {
-	pid = new AttachedSelf().hashCode();
-	addressSpaceByteBuffer
-	    = new AddressSpaceByteBuffer (pid, AddressSpace.TEXT);
-	memorySpaceByteBuffer = new MemorySpaceByteBuffer (pid);
-	if (RegisterSet.REGS != null) {
-	    registerByteBuffer
-		= new RegisterSetByteBuffer (pid, RegisterSet.REGS);
-	}
+      addressBuffers = null;
+      registerBuffers = null;
+
+      // Clean up any left stuff processes/open files/etc.
+      super.tearDown();
     }
 
-    public void verifySlice(ByteBuffer buffer, long addr, long length)
+    public void verifySlice(ByteBuffer buffer, long addr, int length)
     {
 	ByteBuffer slice = buffer.slice (addr, length);
-	byte bytes[] = new byte[ (int)length];
-	buffer.get (addr, bytes, 0, (int)length);
+	byte bytes[] = new byte[length];
+	buffer.get (addr, bytes, 0, length);
 	for (int i = 0; i < length; i++) {
 	    assertEquals ("byte at " + i, bytes[i],
 			  slice.get (i));
 	}
     }
-    public void testSliceAddressSpace()
-    {
-	verifySlice(addressSpaceByteBuffer, LocalMemory.getFuncAddr(),
-		    LocalMemory.getFuncBytes().length);
-    }
-    public void testSliceMemorySpace()
+
+    public void testSliceAddressBuffers()
     {
-	verifySlice(memorySpaceByteBuffer, LocalMemory.getFuncAddr(),
+      for (int i = 0; i < addressBuffers.length; i++)
+	verifySlice(addressBuffers[i], LocalMemory.getFuncAddr(),
 		    LocalMemory.getFuncBytes().length);
     }
-    public void testSliceRegisterSet()
+
+    public void testSliceRegisterBuffers()
     {
-	if (registerByteBuffer == null) {
-	    System.out.print("<<SKIP>>");
-	    return;
-	}
-	verifySlice(registerByteBuffer, 4, 4);
+      for (int i = 0; i < registerBuffers.length; i++)
+	verifySlice(registerBuffers[i], 4, 4);
     }
 
     private void verifyModify(ByteBuffer buffer, long addr)
@@ -108,21 +169,18 @@
 	buffer.putByte(addr, (byte)~oldByte);
 	assertEquals ("modified", (byte)~oldByte, buffer.get(addr));
     }
-    public void testModifyRegisterSet()
-    {
-	if (RegisterSet.REGS == null) {
-	    System.out.print("<<SKIP>>");
-	    return;
-	}
-	verifyModify(registerByteBuffer, 0);
-    }
-    public void testModifyAddressSpace()
+
+    public void testModifyRegisterBuffers()
     {
-	verifyModify(addressSpaceByteBuffer, LocalMemory.getFuncAddr());
+      for (int i = 0; i < registerBuffers.length; i++)
+	verifyModify(registerBuffers[i], 0);
     }
-    public void testModifyMemorySpace()
+
+    public void testModifyAddressBuffers()
     {
-	verifyModify(memorySpaceByteBuffer, LocalMemory.getFuncAddr());
+      for (int i = 0; i < addressBuffers.length; i++)
+	if (! (addressBuffers[i] instanceof LogicalMemoryBuffer))
+	  verifyModify(addressBuffers[i], LocalMemory.getFuncAddr());
     }
 
     private void verifyAsyncModify(ByteBuffer buffer, long addr) {
@@ -171,19 +229,137 @@
 			  asyncModify.newByte);
 	}
     }
-    public void testAsyncRegisterSet() {
-	if (registerByteBuffer == null) {
-	    System.out.print("<<SKIP>>");
-	    return;
-	}
-	verifyAsyncModify(registerByteBuffer, 0);
-    }
-    public void testAsyncAddressSpace() {
-	verifyAsyncModify(addressSpaceByteBuffer,
-			  LocalMemory.getFuncAddr());
-    }
-    public void testAsyncMemorySpace() {
-	verifyAsyncModify(memorySpaceByteBuffer,
-			  LocalMemory.getFuncAddr());
+    public void testAsyncRegisterBuffers() {
+      for (int i = 0; i < registerBuffers.length; i++)
+	verifyAsyncModify(registerBuffers[0], 0);
+    }
+
+    public void testAsyncAddressBuffers() {
+      for (int i = 0; i < addressBuffers.length; i++)
+	if (! (addressBuffers[i] instanceof LogicalMemoryBuffer))
+	  verifyAsyncModify(addressBuffers[i],
+			    LocalMemory.getFuncAddr());
+    }
+
+    public void verifyPeeks(ByteBuffer buffer, long addr, byte[] origBytes)
+    {
+      byte bytes[] = new byte[origBytes.length];
+      buffer.get(addr, bytes, 0, bytes.length);
+      for (int i = 0; i < bytes.length; i++)
+        assertEquals ("byte at " + i, bytes[i], origBytes[i]);
+    }
+  
+    public void testAddressBufferPeeks()
+    {
+      long addr = LocalMemory.getFuncAddr();
+      byte[] origBytes = LocalMemory.getFuncBytes();
+      for (int i = 0; i < addressBuffers.length; i++)
+	verifyPeeks(addressBuffers[i], addr, origBytes);
+    }
+
+    public void testRegisterBufferPeeks()
+    {
+      // Check that simple get loop is similar to bulk get.
+      long addr = 4;
+      byte[] origBytes = new byte[16];
+      for (int i = 0; i < registerBuffers.length; i++)
+	{
+	  for (int j = 0; j < origBytes.length; j++)
+	    origBytes[j] = registerBuffers[i].get(addr + j);
+	  verifyPeeks(registerBuffers[i], addr, origBytes);
+	}
+    }
+    private class AsyncPeeks
+	implements Runnable
+    {
+	private ByteBuffer buffer;
+	private long addr;
+	private int length;
+	private byte[] bytes;
+	private Exception e;
+	AsyncPeeks (ByteBuffer buffer, long addr, int length)
+	{
+	    this.buffer = buffer;
+	    this.addr = addr;
+	    this.length = length;
+	    this.bytes = new byte[length];
+	}
+	public void run ()
+	{
+	    try {
+		buffer.get (addr, bytes, 0, length);
+	    }
+	    catch (Exception e) {
+		this.e = e;
+	    }
+	    Manager.eventLoop.requestStop();
+	}
+	void call (byte[] origBytes)
+	{
+	    // Force the event loop to running on this thread.  Ugly, and is to
+	    // to be removed when bug #4688 is resolved.
+	    Manager.eventLoop.runPolling(1);
+	    new Thread (this).start();
+	    assertTrue("waiting for async peeks",
+		       Manager.eventLoop.runPolling(getTimeoutMilliseconds()));
+	    if (e != null)
+		throw new RuntimeException (e);
+	    for (int i = 0; i < length; i++) {
+		assertEquals ("byte at " + i, bytes[i], origBytes[i]);
+	    }
+	}
+    }
+
+    public void testAsyncPeeks ()
+    {
+      byte[] origBytes = LocalMemory.getFuncBytes();
+      for (int i = 0; i < addressBuffers.length; i++)
+	new AsyncPeeks(addressBuffers[i], LocalMemory.getFuncAddr(),
+		       LocalMemory.getFuncBytes().length).call(origBytes);
+    }
+
+    public void testAsycnPeeksRegisters()
+    {
+      // Check position() and (async) get()
+      int length = 8;
+      byte[] origBytes = new byte[length];
+      long address = 4;
+      for (int i = 0; i < registerBuffers.length; i++)
+	{
+	  registerBuffers[i].position(address);
+	  registerBuffers[i].get(origBytes);
+	  new AsyncPeeks(registerBuffers[i], address,
+			 length).call(origBytes);
+	}
     }
+
+  private void verifyBulkPut(ByteBuffer buffer, long addr, int len)
+  {
+    // Pasting the same bytes back over the old buffer in bulk
+    // and read it back in.
+    byte[] oldBytes = new byte[len];
+    buffer.position(addr);
+    buffer.get(oldBytes);
+    buffer.position(addr);
+    buffer.put(oldBytes);
+    byte[] newBytes = new byte[len];
+    buffer.position(addr);
+    buffer.get(newBytes);
+    assertTrue(Arrays.equals(oldBytes, newBytes));
+  }
+
+  public void testBulkPutRegisterBuffers()
+  {
+    for (int i = 0; i < registerBuffers.length; i++)
+      verifyBulkPut(registerBuffers[i], 4, 4);
+  }
+
+  public void testBulkPutAddressBuffers()
+  {
+    for (int i = 0; i < addressBuffers.length; i++)
+      if (! (addressBuffers[i] instanceof LogicalMemoryBuffer))
+	verifyBulkPut(addressBuffers[i], LocalMemory.getFuncAddr(),
+		      LocalMemory.getFuncBytes().length);
+  }
+
 }
Index: frysk-core/frysk/proc/live/TestMemorySpaceByteBuffer.java
===================================================================
RCS file: frysk-core/frysk/proc/live/TestMemorySpaceByteBuffer.java
diff -N frysk-core/frysk/proc/live/TestMemorySpaceByteBuffer.java
--- frysk-core/frysk/proc/live/TestMemorySpaceByteBuffer.java	30 Jul 2007 12:42:08 -0000	1.3
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,123 +0,0 @@
-// This file is part of the program FRYSK.
-// 
-// Copyright 2007 Oracle Corporation.
-// Copyright 2007, 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 frysk.junit.TestCase;
-import frysk.testbed.TearDownProcess;
-import frysk.testbed.AttachedSelf;
-import frysk.testbed.LocalMemory;
-import frysk.proc.Manager;
-
-public class TestMemorySpaceByteBuffer
-    extends TestCase
-{
-    public void tearDown()
-    {
-	TearDownProcess.tearDown();
-    }
-    private int pid;
-    private MemorySpaceByteBuffer memorySpaceByteBuffer;
-
-    public void setUp ()
-    {
-	pid = new AttachedSelf().hashCode();
-	memorySpaceByteBuffer = new MemorySpaceByteBuffer (pid);
-    }
-
-    public void testPeeks ()
-    {
-	long addr = LocalMemory.getFuncAddr();
-	int length = LocalMemory.getFuncBytes().length;
-	byte bytes[] = new byte[(int)length];
-	memorySpaceByteBuffer.peek (addr, bytes, 0, length);
-	byte[] origBytes = LocalMemory.getFuncBytes();
-	for (int i = 0; i < length; i++) {
-	    assertEquals ("byte at " + i, bytes[i], origBytes[i]);
-	}
-    }
-
-    private class AsyncPeeks
-	implements Runnable
-    {
-	private MemorySpaceByteBuffer buffer;
-	private long addr;
-	private int length;
-	private byte[] bytes;
-	private Exception e;
-	AsyncPeeks (MemorySpaceByteBuffer buffer, long addr, int length)
-	{
-	    this.buffer = buffer;
-	    this.addr = addr;
-	    this.length = length;
-	    this.bytes = new byte[length];
-	}
-	public void run ()
-	{
-	    try {
-		buffer.peek (addr, bytes, 0, length);
-	    }
-	    catch (Exception e) {
-		this.e = e;
-	    }
-	    Manager.eventLoop.requestStop();
-	}
-	void call ()
-	{
-	    // Force the event loop to running on this thread.  Ugly, and is to
-	    // to be removed when bug #4688 is resolved.
-	    Manager.eventLoop.runPolling(1);
-	    new Thread (this).start();
-	    assertTrue("waiting for async peeks",
-		       Manager.eventLoop.runPolling(getTimeoutMilliseconds()));
-	    if (e != null)
-		throw new RuntimeException (e);
-	    byte[] origBytes = LocalMemory.getFuncBytes();
-	    for (int i = 0; i < length; i++) {
-		assertEquals ("byte at " + i, bytes[i], origBytes[i]);
-	    }
-	}
-    }
-    public void testAsyncPeeks ()
-    {
-	new AsyncPeeks(memorySpaceByteBuffer, LocalMemory.getFuncAddr(),
-		       LocalMemory.getFuncBytes().length).call();
-    }
-}
Index: frysk-sys/inua/eio/ByteBuffer.java
===================================================================
RCS file: /cvs/frysk/frysk-sys/inua/eio/ByteBuffer.java,v
retrieving revision 1.2
diff -u -r1.2 ByteBuffer.java
--- frysk-sys/inua/eio/ByteBuffer.java	30 Jul 2007 12:42:09 -0000	1.2
+++ frysk-sys/inua/eio/ByteBuffer.java	2 Aug 2007 10:48:35 -0000
@@ -372,6 +372,21 @@
     return get(dst, 0, dst.length);
   }
 
+  public ByteBuffer put (byte[] src, int off, int len)
+    throws BufferUnderflowException
+  {
+    if (ULong.GT(len, remaining()))
+      throw new BufferUnderflowException();
+    poke(cursor, src, off, len);
+    cursor += len;
+    return this;
+  }
+
+  public final ByteBuffer put (byte[] src) throws BufferUnderflowException
+  {
+    return put(src, 0, src.length);
+  }
+
   protected ByteOrdered byteOrdered;
 
   public final ByteOrder order ()

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] LogicalMemoryBuffer
  2007-08-02 11:26 ` Mark Wielaard
@ 2007-08-03 14:03   ` Phil Muldoon
  2007-08-06  9:17     ` Mark Wielaard
  0 siblings, 1 reply; 5+ messages in thread
From: Phil Muldoon @ 2007-08-03 14:03 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: frysk

Mark Wielaard wrote:
> Hi,
>
> On Fri, 2007-07-20 at 14:02 +0200, Mark Wielaard wrote:
>   
>> - LogicalMemoryBuffer is a filter on top of AddressSpaceByteBuffer but
>> really should be on top of MemorySpaceByteBuffer which is more
>> effecient. The used to be interface compatible, but a recent change to
>> MemorySpaceByteBuffer changed that and made that it less easy to wrap.
>> MemorySpaceByteBuffer is really just an optimization of
>> AddressSpaceByteBuffer (in the case of AddressSpace.TEXT/DATA) and all
>> code should go through the optimized path (StateLessFile) for accessing
>> memory if the AddressSpace allows it. So I am going to merge the two
>> (and fix up the places that currently use the slow path). Then I'll also
>> add the ByteBuffer.get() optimization that Chris pointed out.
>>     

Can you write up the difference between Logical and Raw Memory? How is 
Raw memory exported? If a break-point has been added to memory 0x123434 
is the map marked as written in RawMemory?

Regards

Phil

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [patch] LogicalMemoryBuffer
  2007-08-03 14:03   ` Phil Muldoon
@ 2007-08-06  9:17     ` Mark Wielaard
  0 siblings, 0 replies; 5+ messages in thread
From: Mark Wielaard @ 2007-08-06  9:17 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: frysk

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

Hi Phil,

On Fri, 2007-08-03 at 09:03 -0500, Phil Muldoon wrote:
> Mark Wielaard wrote:
> > On Fri, 2007-07-20 at 14:02 +0200, Mark Wielaard wrote:
> >> - LogicalMemoryBuffer is a filter on top of AddressSpaceByteBuffer but
> >> really should be on top of MemorySpaceByteBuffer which is more
> >> effecient. The used to be interface compatible, but a recent change to
> >> MemorySpaceByteBuffer changed that and made that it less easy to wrap.
> >> MemorySpaceByteBuffer is really just an optimization of
> >> AddressSpaceByteBuffer (in the case of AddressSpace.TEXT/DATA) and all
> >> code should go through the optimized path (StateLessFile) for accessing
> >> memory if the AddressSpace allows it. So I am going to merge the two
> >> (and fix up the places that currently use the slow path). Then I'll also
> >> add the ByteBuffer.get() optimization that Chris pointed out.
> >>     
> 
> Can you write up the difference between Logical and Raw Memory? How is 
> Raw memory exported? If a break-point has been added to memory 0x123434 
> is the map marked as written in RawMemory?

Good questions. See also the Task getRawMemory() interface
documentation. getMemory() and getRawMemory() are somewhat independent
of the MemoryMaps returned by getMaps(). You can get the actual bytes of
the address ranges given in the MemoryMap through either the ByteBuffer
returned by getMemory(), which gives you the logical memory view
(without any "artificial" changes made by frysk-core) or through the
ByteBuffer returned by getRawMemory() that includes also any changes to
the memory made by frysk-core. Since there is only one getMaps() variant
the flags set on the returned MemoryMaps correspond to the "raw" memory
view. So a MemoryMap could be marked as written to, but if you access
its content through the getMemory() ByteBuffer you would still not see
the frysk-core change. If it is beneficial for your use case we could
add an extra flag to MemoryMap saying whether or not it (also) contains
changes were made by frysk-core. Note however that the kernel doesn't
track the "why" of a write to the map, so it doesn't distinguish between
whether a monitoring app like frysk did it, or whether the application
itself or the kernel wrote to the map. And as Roland said there is no
way to "reverse" a write, once written, even if you put back the
original contents later, it will always be marked as written by the
kernel.

Cheers,

Mark

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2007-08-06  9:17 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-07-20 12:02 [patch] LogicalMemoryBuffer Mark Wielaard
2007-07-30 12:42 ` Mark Wielaard
2007-08-02 11:26 ` Mark Wielaard
2007-08-03 14:03   ` Phil Muldoon
2007-08-06  9:17     ` Mark Wielaard

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