From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26201 invoked by alias); 14 May 2008 17:10:54 -0000 Received: (qmail 26172 invoked by uid 367); 14 May 2008 17:10:54 -0000 Date: Wed, 14 May 2008 17:10:00 -0000 Message-ID: <20080514171053.26157.qmail@sourceware.org> From: cagney@sourceware.org To: frysk-cvs@sourceware.org Subject: [SCM] master: Implement frysk.sys.ptrace in jni. X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: 9da8189a51b382e4d3e46fbf770808d8592e357e X-Git-Newrev: 9e07b5e5c951f582ed2e466295376bafc6c46df3 Mailing-List: contact frysk-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: frysk-cvs-owner@sourceware.org Reply-To: frysk@sourceware.org X-SW-Source: 2008-q2/txt/msg00238.txt.bz2 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 Date: Wed May 14 13:09:40 2008 -0400 Implement frysk.sys.ptrace in jni. frysk-sys/ChangeLog 2008-05-14 Andrew Cagney * Makefile.am (JNIXX_CLASSES): Add java.lang.ArrayIndexOutOfBoundsException. frysk-sys/frysk/jnixx/ChangeLog 2008-05-14 Andrew Cagney * 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 * 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 + + * Makefile.am (JNIXX_CLASSES): Add + java.lang.ArrayIndexOutOfBoundsException. + 2008-05-13 Andrew Cagney * 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 # 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 + + * chars.hxx (class ByteArrayElements): New. + * bounds.hxx: New. + * JniBindings.java: Generate GetArrayLength, and Throw. + 2008-05-13 Andrew Cagney * 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 + + * 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 * 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 +#include +#include +#include "linux.ptrace.h" +#include + #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 +#include +#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 ""; +#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; +} + +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