* 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