public inbox for frysk-cvs@sourceware.org
help / color / mirror / Atom feed
* [SCM]  master: Implement frysk.sys.ptrace in jni.
@ 2008-05-14 17:10 cagney
  0 siblings, 0 replies; only message in thread
From: cagney @ 2008-05-14 17:10 UTC (permalink / raw)
  To: frysk-cvs

The branch, master has been updated
       via  9e07b5e5c951f582ed2e466295376bafc6c46df3 (commit)
      from  9da8189a51b382e4d3e46fbf770808d8592e357e (commit)

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

- Log -----------------------------------------------------------------
commit 9e07b5e5c951f582ed2e466295376bafc6c46df3
Author: Andrew Cagney <cagney@redhat.com>
Date:   Wed May 14 13:09:40 2008 -0400

    Implement frysk.sys.ptrace in jni.
    
    frysk-sys/ChangeLog
    2008-05-14  Andrew Cagney  <cagney@redhat.com>
    
    	* Makefile.am (JNIXX_CLASSES): Add
    	java.lang.ArrayIndexOutOfBoundsException.
    
    frysk-sys/frysk/jnixx/ChangeLog
    2008-05-14  Andrew Cagney  <cagney@redhat.com>
    
    	* chars.hxx (class ByteArrayElements): New.
    	* bounds.hxx: New.
    	* JniBindings.java: Generate GetArrayLength, and Throw.
    
    frysk-sys/frysk/sys/ptrace/ChangeLog
    2008-05-14  Andrew Cagney  <cagney@redhat.com>
    
    	* jni/Ptrace.cxx: Convert to JNI.
    	* jni/AddressSpace.cxx: Convert to JNI.
    	* jni/RegisterSet.cxx: Covert to JNI.
    	* jni/Utrace.cxx: Delete.

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

Summary of changes:
 frysk-sys/ChangeLog                                |    5 +
 frysk-sys/Makefile.am                              |    1 +
 frysk-sys/frysk/jnixx/ChangeLog                    |    6 +
 frysk-sys/frysk/jnixx/JniBindings.java             |   22 +++-
 .../jni/AddressSpace.cxx => jnixx/bounds.hxx}      |   29 ++++-
 frysk-sys/frysk/jnixx/chars.hxx                    |   26 ++++
 frysk-sys/frysk/sys/ptrace/ChangeLog               |    7 +
 frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx    |  155 +++++++++++++++++++-
 frysk-sys/frysk/sys/ptrace/jni/Ptrace.cxx          |  117 +++++++++++++++-
 .../ptrace/jni/{AddressSpace.cxx => Ptrace.hxx}    |    2 +-
 frysk-sys/frysk/sys/ptrace/jni/RegisterSet.cxx     |   55 +++++++-
 11 files changed, 419 insertions(+), 6 deletions(-)
 copy frysk-sys/frysk/{sys/ptrace/jni/AddressSpace.cxx => jnixx/bounds.hxx} (69%)
 copy frysk-sys/frysk/sys/ptrace/jni/{AddressSpace.cxx => Ptrace.hxx} (97%)

First 500 lines of diff:
diff --git a/frysk-sys/ChangeLog b/frysk-sys/ChangeLog
index 22e6cec..7fdfce7 100644
--- a/frysk-sys/ChangeLog
+++ b/frysk-sys/ChangeLog
@@ -1,3 +1,8 @@
+2008-05-14  Andrew Cagney  <cagney@redhat.com>
+
+	* Makefile.am (JNIXX_CLASSES): Add
+	java.lang.ArrayIndexOutOfBoundsException.
+
 2008-05-13  Andrew Cagney  <cagney@redhat.com>
 
 	* Makefile.am (JNIXX_CLASSES): Add
diff --git a/frysk-sys/Makefile.am b/frysk-sys/Makefile.am
index bb39422..cd10704 100644
--- a/frysk-sys/Makefile.am
+++ b/frysk-sys/Makefile.am
@@ -73,6 +73,7 @@ lib/unwind/Unwind%.java: lib/unwind/Unwind.java
 # jnixx's auto-detect algorithm misses hidden class references,
 # explicitly add them here.
 JNIXX_CLASSES += frysk.sys.ProcessIdentifierFactory
+JNIXX_CLASSES += java.lang.ArrayIndexOutOfBoundsException
 \f
 
 # Quick hack to get a test JNI program up-and-running; as a package is
diff --git a/frysk-sys/frysk/jnixx/ChangeLog b/frysk-sys/frysk/jnixx/ChangeLog
index 61f470a..84ffdc5 100644
--- a/frysk-sys/frysk/jnixx/ChangeLog
+++ b/frysk-sys/frysk/jnixx/ChangeLog
@@ -1,3 +1,9 @@
+2008-05-14  Andrew Cagney  <cagney@redhat.com>
+
+	* chars.hxx (class ByteArrayElements): New.
+	* bounds.hxx: New.
+	* JniBindings.java: Generate GetArrayLength, and Throw.
+
 2008-05-13  Andrew Cagney  <cagney@redhat.com>
 
 	* PrintDeclarations.java: Do not generate non-ENV wrappers.
diff --git a/frysk-sys/frysk/jnixx/JniBindings.java b/frysk-sys/frysk/jnixx/JniBindings.java
index 7464cb7..40026dc 100644
--- a/frysk-sys/frysk/jnixx/JniBindings.java
+++ b/frysk-sys/frysk/jnixx/JniBindings.java
@@ -207,6 +207,18 @@ class JniBindings {
 	     })
 
 	/**
+	 * java.lang.Throwable
+	 */
+	.put(Throwable.class, false,
+	     null, "Throw",
+	     new String[] {
+		 "::jnixx::env", "env",
+	     },
+	     new Object[] {
+		 "env.Throw((jthrowable) _object);"
+	     })
+
+	/**
 	 * java.lang.String
 	 */
 	// NewString
@@ -302,7 +314,7 @@ class JniBindings {
 			 "return " + type + "Array(env, env.New" + Type + "Array(length));",
 		     })
 		.put(types[i], false,
-		     "const j" + type + "*", "GetElements",
+		     "j" + type + "*", "GetElements",
 		     new String[] {
 			 "::jnixx::env", "env",
 			 "jboolean*", "isCopy",
@@ -311,6 +323,14 @@ class JniBindings {
 			 "return env.Get" + Type + "ArrayElements((j" + type + "Array) _object, isCopy);"
 		     })
 		.put(types[i], false,
+		     "jsize", "GetArrayLength",
+		     new String[] {
+			 "::jnixx::env", "env",
+		     },
+		     new Object[] {
+			 "return env.GetArrayLength((j" + type + "Array) _object);"
+		     })
+		.put(types[i], false,
 		     null, "ReleaseElements",
 		     new String[] {
 			 "::jnixx::env", "env",
diff --git a/frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx b/frysk-sys/frysk/jnixx/bounds.hxx
similarity index 69%
copy from frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx
copy to frysk-sys/frysk/jnixx/bounds.hxx
index b358932..9f84d5e 100644
--- a/frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx
+++ b/frysk-sys/frysk/jnixx/bounds.hxx
@@ -37,4 +37,31 @@
 // version and license this file solely under the GPL without
 // exception.
 
-#include "jni.hxx"
+/**
+ * Given an array, verify an attempt to access elements.  If the
+ * access is out-of-bounds throw an exception.
+ */
+
+inline void verifyBounds(::jnixx::env env, ::jnixx::byteArray data,
+			 jint stop) {
+  if (stop < 0) {
+    ::java::lang::ArrayIndexOutOfBoundsException::New(env, stop).Throw(env);
+  }
+  if (stop > data.GetArrayLength(env)) {
+    ::java::lang::ArrayIndexOutOfBoundsException::New(env, stop).Throw(env);
+  }
+}
+
+inline void verifyBounds(::jnixx::env env, ::jnixx::byteArray data,
+			 jint start, jint length) {
+  if (start < 0) {
+    ::java::lang::ArrayIndexOutOfBoundsException::New(env, start).Throw(env);
+  }
+  if (start >= data.GetArrayLength(env)) {
+    ::java::lang::ArrayIndexOutOfBoundsException::New(env, start).Throw(env);
+  }
+  if (length < 0) {
+    ::java::lang::ArrayIndexOutOfBoundsException::New(env, length).Throw(env);
+  }
+  verifyBounds(env, data, start + length);
+}
diff --git a/frysk-sys/frysk/jnixx/chars.hxx b/frysk-sys/frysk/jnixx/chars.hxx
index 5c44b81..f00cf2c 100644
--- a/frysk-sys/frysk/jnixx/chars.hxx
+++ b/frysk-sys/frysk/jnixx/chars.hxx
@@ -88,3 +88,29 @@ public:
     free();
   }
 };
+
+class ByteArrayElements {
+private:
+  ::jnixx::byteArray bytes;
+  ::jnixx::env env;
+public:
+  jbyte* p;
+  ByteArrayElements(::jnixx::env env, ::jnixx::byteArray bytes) {
+    this->bytes = bytes;
+    this->env = env;
+    if (bytes != NULL) {
+      this->p = bytes.GetElements(env, NULL);
+    } else {
+      this->p = NULL;
+    }
+  }
+  void release() {
+    if (p != NULL) {
+      bytes.ReleaseElements(env, p, 0);
+      p = NULL;
+    }
+  }
+  ~ByteArrayElements() {
+    release();
+  }
+};
diff --git a/frysk-sys/frysk/sys/ptrace/ChangeLog b/frysk-sys/frysk/sys/ptrace/ChangeLog
index 4e9675f..3fa5f68 100644
--- a/frysk-sys/frysk/sys/ptrace/ChangeLog
+++ b/frysk-sys/frysk/sys/ptrace/ChangeLog
@@ -1,3 +1,10 @@
+2008-05-14  Andrew Cagney  <cagney@redhat.com>
+
+	* jni/Ptrace.cxx: Convert to JNI.
+	* jni/AddressSpace.cxx: Convert to JNI.
+	* jni/RegisterSet.cxx: Covert to JNI.
+	* jni/Utrace.cxx: Delete.
+
 2008-05-07  Andrew Cagney  <cagney@redhat.com>
 
 	* jni/AddressSpace.cxx: Include jni.hxx.
diff --git a/frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx b/frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx
index b358932..4177164 100644
--- a/frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx
+++ b/frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx
@@ -1,6 +1,6 @@
 // This file is part of the program FRYSK.
 //
-// Copyright 2008, Red Hat Inc.
+// Copyright 2005, 2006, 2007, 2008, Red Hat Inc.
 //
 // FRYSK is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by
@@ -37,4 +37,157 @@
 // version and license this file solely under the GPL without
 // exception.
 
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include "linux.ptrace.h"
+#include <string.h>
+
 #include "jni.hxx"
+#include "frysk/jnixx/bounds.hxx"
+#include "frysk/jnixx/chars.hxx"
+
+#include "frysk/sys/ptrace/jni/Ptrace.hxx"
+
+using namespace java::lang;
+
+union word {
+  long l;
+  uint8_t b[sizeof (long)];
+};
+
+jint
+frysk::sys::ptrace::AddressSpace::peek(::jnixx::env env, jint pid, jlong addr) {
+  union word w;
+  long paddr = addr & -sizeof(long);
+#if DEBUG
+  fprintf(stderr, "peek 0x%lx paddr 0x%lx", (long)addr, paddr);
+#endif
+  w.l = ptraceOp(env, GetPtPeek(env), pid, (void*)paddr, 0);
+#if DEBUG
+  fprintf(stderr, " word 0x%lx", w.l);
+#endif
+  int index = addr & (sizeof(long) - 1);
+#if DEBUG
+  fprintf(stderr, " index %d", index);
+#endif
+  uint8_t byte = w.b[index];
+#if DEBUG
+  fprintf(stderr, " byte %d/0x%x\n", byte, byte);
+#endif
+  return byte;
+}
+
+void
+frysk::sys::ptrace::AddressSpace::poke(::jnixx::env env, jint pid, jlong addr, jint data) {
+  // Implement read-modify-write
+  union word w;
+#if DEBUG
+  fprintf(stderr, "poke 0x%x", (int)(data & 0xff));
+#endif
+  long paddr = addr & -sizeof(long);
+#if DEBUG
+  fprintf(stderr, " addr 0x%lx paddr 0x%lx", (long)addr, paddr);
+#endif
+  w.l = ptraceOp(env, GetPtPeek(env), pid, (void*)paddr, 0);
+#if DEBUG
+  fprintf(stderr, " word 0x%lx", w.l);
+#endif
+  int index = addr & (sizeof(long) - 1);
+#if DEBUG
+  fprintf (stderr, " index %d", index);
+#endif
+  w.b[index] = data;
+#if DEBUG
+  fprintf(stderr, " word 0x%lx\n", w.l);
+#endif
+  ptraceOp(env, GetPtPoke(env), pid, (void*)(addr & -sizeof(long)), w.l);
+}
+
+void
+frysk::sys::ptrace::AddressSpace::transfer(::jnixx::env env,
+					   jint op, jint pid, jlong addr,
+					   ::jnixx::byteArray bytes,
+					   jint offset, jint length) {
+  const int ptPeek = GetPtPeek(env);
+  const int ptPoke = GetPtPoke(env);
+  verifyBounds(env, bytes, offset, length);
+  // Somewhat more clueful implementation
+  for (jlong i = 0; i < length;) {
+#if DEBUG
+    fprintf(stderr,
+	     "transfer pid %d addr 0x%lx length %d offset %d op %d (%s)",
+	     (int)pid, (long)addr, (int)length, (int)offset,
+	     (int)op, op_as_string(op));
+#endif
+
+    union word w;
+    unsigned long waddr = addr & -sizeof(long);
+    unsigned long woff = (addr - waddr);
+    unsigned long remaining = length - i;
+    unsigned long wend;
+    if (remaining > sizeof(long) - woff)
+      wend = sizeof(long);
+    else
+      wend = woff + remaining;
+    long wlen = wend - woff;
+
+#if DEBUG
+    fprintf(stderr,
+	     " i %ld waddr 0x%lx woff %lu wend %lu remaining %lu wlen %lu",
+	     (long)i, waddr, woff, wend, remaining, wlen);
+#endif
+
+    // Either a peek; or a partial write requiring read/modify/write.
+    if (op == ptPeek || woff != 0 || wend != sizeof(long)) {
+	w.l = ptraceOp(env, ptPeek, pid, (void*)waddr, 0);
+#if DEBUG
+	fprintf(stderr, " peek 0x%lx", w.l);
+#endif
+      }
+
+    // extract or modify
+    ByteArrayElements elements = ByteArrayElements(env, bytes);
+    if (op == ptPeek)
+      memcpy(offset + i + elements.p, &w.b[woff], wlen);
+    else {
+      memcpy(&w.b[woff], offset + i + elements.p, wlen);
+#if DEBUG
+      fprintf(stderr, " poke 0x%lx", w.l);
+#endif
+      w.l = ptraceOp(env, ptPoke, pid, (void*)waddr, w.l);
+    }
+    elements.release();
+
+    i += wlen;
+    addr += wlen;
+
+#if DEBUG
+    fprintf(stderr, "\n");
+#endif
+  }
+}
+
+frysk::sys::ptrace::AddressSpace
+frysk::sys::ptrace::AddressSpace::text(::jnixx::env env) {
+  return frysk::sys::ptrace::AddressSpace::New(env, -1UL,
+					       String::NewStringUTF(env, "TEXT"),
+					       PTRACE_PEEKTEXT,
+					       PTRACE_POKETEXT);
+}
+
+frysk::sys::ptrace::AddressSpace
+frysk::sys::ptrace::AddressSpace::data(::jnixx::env env) {
+  return frysk::sys::ptrace::AddressSpace::New(env, -1UL,
+					       String::NewStringUTF(env, "DATA"),
+					       PTRACE_PEEKDATA,
+					       PTRACE_POKEDATA);
+}
+
+frysk::sys::ptrace::AddressSpace
+frysk::sys::ptrace::AddressSpace::usr(::jnixx::env env) {
+  return frysk::sys::ptrace::AddressSpace::New(env, -1UL,
+					       String::NewStringUTF(env, "USR"),
+					       PTRACE_PEEKUSR,
+					       PTRACE_POKEUSR);
+}
diff --git a/frysk-sys/frysk/sys/ptrace/jni/Ptrace.cxx b/frysk-sys/frysk/sys/ptrace/jni/Ptrace.cxx
index b358932..d6726ed 100644
--- a/frysk-sys/frysk/sys/ptrace/jni/Ptrace.cxx
+++ b/frysk-sys/frysk/sys/ptrace/jni/Ptrace.cxx
@@ -1,6 +1,6 @@
 // This file is part of the program FRYSK.
 //
-// Copyright 2008, Red Hat Inc.
+// Copyright 2005, 2006, 2007, 2008, Red Hat Inc.
 //
 // FRYSK is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by
@@ -37,4 +37,119 @@
 // version and license this file solely under the GPL without
 // exception.
 
+#include <errno.h>
+#include <sys/ptrace.h>
+#include "linux.ptrace.h"
+
 #include "jni.hxx"
+
+#include "frysk/sys/ptrace/jni/Ptrace.hxx"
+
+#include "frysk/jnixx/exceptions.hxx"
+
+static const char*
+op_as_string(int op) {
+  switch(op) {
+#define OP(NAME) case NAME: return #NAME
+    OP(PTRACE_ATTACH);
+    OP(PTRACE_DETACH);
+    OP(PTRACE_SINGLESTEP);
+    OP(PTRACE_CONT);
+    OP(PTRACE_SYSCALL);
+#if defined(__i386__) || defined(__x86_64__)
+    OP(PTRACE_GETREGS);
+    OP(PTRACE_SETREGS);
+    OP(PTRACE_GETFPREGS);
+    OP(PTRACE_SETFPREGS);
+#endif
+#if defined(__i386__)
+    OP(PTRACE_GETFPXREGS);
+    OP(PTRACE_SETFPXREGS);
+#endif
+    OP(PTRACE_GETEVENTMSG);
+    OP(PTRACE_SETOPTIONS);
+    OP(PTRACE_PEEKDATA);
+    OP(PTRACE_POKEDATA);
+    OP(PTRACE_PEEKTEXT);
+    OP(PTRACE_POKETEXT);
+    OP(PTRACE_PEEKUSR);
+    OP(PTRACE_POKEUSR);
+  default: return "<unknown>";
+#undef OP
+  }
+}
+
+long
+ptraceOp(::jnixx::env env, int op, int pid, void* addr, long data) {
+  errno = 0;
+  long result = ::ptrace ((enum __ptrace_request) op, pid, addr, data);
+  if (errno != 0)
+    errnoException(env, errno, "ptrace",
+		   "op 0x%x (%s), pid %d, addr 0x%lx, data 0x%lx",
+		   op, op_as_string(op), pid, (long)addr, data);
+  return result;
+}
+
+void
+frysk::sys::ptrace::Ptrace::attach(::jnixx::env env, jint pid) {
+  ptraceOp(env, PTRACE_ATTACH, pid, NULL, 0);
+}
+
+void
+frysk::sys::ptrace::Ptrace::detach(::jnixx::env env, jint pid, jint sig) {
+  ptraceOp(env, PTRACE_DETACH, pid, NULL, sig);
+} 
+
+void
+frysk::sys::ptrace::Ptrace::singleStep(::jnixx::env env, jint pid, jint sig) {
+  ptraceOp(env, PTRACE_SINGLESTEP, pid, NULL, sig);
+} 
+
+void
+frysk::sys::ptrace::Ptrace::cont(::jnixx::env env, jint pid, jint sig) {
+  ptraceOp(env, PTRACE_CONT, pid, NULL, sig);
+}
+
+void
+frysk::sys::ptrace::Ptrace::sysCall(::jnixx::env env, jint pid, jint sig) {
+  ptraceOp(env, PTRACE_SYSCALL, pid, NULL, sig);
+}
+
+jlong
+frysk::sys::ptrace::Ptrace::getEventMsg(::jnixx::env env, jint pid) {
+  /* Note: PTRACE_GETEVENTMSG ends up calling the function
+     kernel/ptrace.c: ptrace_ptraceOp(env, ) and that uses put_user to store
+     child->ptrace_message write sizeof(ptrace_message) bytes into the
+     MESSAGE parameter.  include/linux/sched.h declares ptrace_message
+     as a long.  */
+  long msg;
+  ptraceOp(env, PTRACE_GETEVENTMSG, pid, NULL, (long) &msg);
+  return msg;
+}
+\f
+void
+frysk::sys::ptrace::Ptrace::setOptions(::jnixx::env env,
+				       jint pid, jlong options) {
+  ptraceOp(env, PTRACE_SETOPTIONS, pid, 0, options);
+}
+
+jlong
+frysk::sys::ptrace::Ptrace::optionTraceClone(::jnixx::env env) {
+  return PTRACE_O_TRACECLONE;
+}
+jlong
+frysk::sys::ptrace::Ptrace::optionTraceFork(::jnixx::env env) {
+  return PTRACE_O_TRACEFORK;
+}
+jlong
+frysk::sys::ptrace::Ptrace::optionTraceExit(::jnixx::env env) {
+  return PTRACE_O_TRACEEXIT;
+}
+jlong
+frysk::sys::ptrace::Ptrace::optionTraceSysgood(::jnixx::env env) {
+  return PTRACE_O_TRACESYSGOOD;
+}
+jlong
+frysk::sys::ptrace::Ptrace::optionTraceExec(::jnixx::env env) {
+  return PTRACE_O_TRACEEXEC;
+}
diff --git a/frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx b/frysk-sys/frysk/sys/ptrace/jni/Ptrace.hxx
similarity index 97%
copy from frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx
copy to frysk-sys/frysk/sys/ptrace/jni/Ptrace.hxx
index b358932..be134ef 100644
--- a/frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx
+++ b/frysk-sys/frysk/sys/ptrace/jni/Ptrace.hxx
@@ -37,4 +37,4 @@
 // version and license this file solely under the GPL without
 // exception.
 
-#include "jni.hxx"
+extern long ptraceOp(::jnixx::env, int, int, void*, long);
diff --git a/frysk-sys/frysk/sys/ptrace/jni/RegisterSet.cxx b/frysk-sys/frysk/sys/ptrace/jni/RegisterSet.cxx
index b358932..d44b1df 100644
--- a/frysk-sys/frysk/sys/ptrace/jni/RegisterSet.cxx
+++ b/frysk-sys/frysk/sys/ptrace/jni/RegisterSet.cxx
@@ -1,6 +1,6 @@
 // This file is part of the program FRYSK.
 //
-// Copyright 2008, Red Hat Inc.
+// Copyright 2005, 2006, 2007, 2008, Red Hat Inc.
 //


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


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

only message in thread, other threads:[~2008-05-14 17:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-05-14 17:10 [SCM] master: Implement frysk.sys.ptrace in jni cagney

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