+2006-11-01 Keith Seitz <keiths@redhat.com>
+
+ * gnu/gcj/jvmti/Location.java: New file.
+ * gnu/gcj/jvmti/BreakpointManager.java: New file.
+ * jvmti.cc (_Jv_JVMTI_SetBreakpoint): New function.
+ (_Jv_JVMTI_ClearBreakpoint): New function.
+ (_Jv_JVMTI_Interface): Define SetBreakpoint and ClearBreakpoint.
+ * sources.am: Regenerated.
+ * Makefile.in: Regenerated.
+
2006-10-28 Keith Seitz <keiths@redhat.com>
* Makefile.am (nat_source_files): Add natBreakpoint.cc.
gnu_gcj_io_header_files = $(patsubst %.java,%.h,$(gnu_gcj_io_source_files))
gnu_gcj_jvmti_source_files = \
-gnu/gcj/jvmti/Breakpoint.java
+gnu/gcj/jvmti/Breakpoint.java \
+gnu/gcj/jvmti/BreakpointManager.java \
+gnu/gcj/jvmti/Location.java
gnu_gcj_jvmti_header_files = $(patsubst %.java,%.h,$(gnu_gcj_jvmti_source_files))
gnu_gcj_runtime_source_files = \
--- /dev/null
+// BreakpointManager.java - A convenience class for dealing with breakpoints
+
+/* Copyright (C) 2006 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package gnu.gcj.jvmti;
+
+import java.util.Hashtable;
+
+/**
+ * A class which manages breakpoints in the VM interpreter engine.
+ *
+ * BreakpointManager is a location manager that the interpreter
+ * uses to lookup the original instruction for any given installed
+ * breakpoint. JVMTI does not allow multiple breakpoints to be set
+ * at any given location.
+ *
+ * @author Keith Seitz (keiths@redhat.com)
+ */
+public class BreakpointManager
+{
+ private static BreakpointManager _instance = new BreakpointManager ();
+
+ // List of breakpoints indexed by Location
+ private Hashtable _breakpoints;
+
+ private BreakpointManager ()
+ {
+ _breakpoints = new Hashtable ();
+ }
+
+ /**
+ * Creates a new breakpoint. SetBreakpoint will verify the validity
+ * of the arguments.
+ *
+ * @param method method in which to set breakpoint (a jmethodID)
+ * @param location index where the breakpoint is to be set (a jlocation)
+ */
+ public static Breakpoint newBreakpoint (long method, long location)
+ {
+ Breakpoint bp = new Breakpoint (method, location);
+ Location loc = new Location (method, location);
+ _instance._breakpoints.put (loc, bp);
+ return bp;
+ }
+
+ /**
+ * Deletes the breakpoint at the given Location
+ *
+ * @param method method in which to clear breakpoint
+ * @param location index of breakpoint in method
+ */
+ public static void deleteBreakpoint (long method, long location)
+ {
+ Location loc = new Location (method, location);
+ _instance._breakpoints.remove (loc);
+ }
+
+ /**
+ * Returns the breakpoint at the given location or null if none installed
+ * at location
+ *
+ * @param method the jmethodID of the breakpoint location
+ * @param location the index in the method
+ */
+ public static Breakpoint getBreakpoint (long method, long location)
+ {
+ Location loc = new Location (method, location);
+ return (Breakpoint) _instance._breakpoints.get (loc);
+ }
+}
--- /dev/null
+// Location.java - a wrapper class for breakpoint locations in JVMTI
+
+/* Copyright (C) 2006 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package gnu.gcj.jvmti;
+
+import java.lang.Long;
+
+/**
+ * This class represents a breakpoint location (pair<jmethodID,jlocation>).
+ * BreakpointManager uses this class as a key in the Map of installed
+ * breakpoints.
+ *
+ * @author Keith Seitz (keiths@redhat.com)
+ */
+public class Location
+{
+ // method (a jmethodID in JVMTI)
+ private long method;
+
+ // index (a jlocation in JVMTI)
+ private long location;
+
+ /**
+ * Constructor
+ *
+ * @param method the method defined by this location (a jmethodID)
+ * @param location the integer index of the insn in the method (a jlocation)
+ */
+ public Location (long method, long location)
+ {
+ this.method = method;
+ this.location = location;
+ }
+
+ public int hashCode ()
+ {
+ return toString ().hashCode ();
+ }
+
+ public boolean equals (Object obj)
+ {
+ Location loc = (Location) obj;
+ return (loc.method == method && loc.location == location);
+ }
+
+ /**
+ * Converts the Location to a String
+ */
+ public String toString ()
+ {
+ return Long.toHexString (method) + "." + Long.toString (location);
+ }
+}
#include <jvm.h>
#include <java-threads.h>
#include <java-gc.h>
+#include <java-interp.h>
#include <jvmti.h>
#include "jvmti-int.h"
#include <gnu/classpath/SystemProperties.h>
#include <gnu/gcj/runtime/BootClassLoader.h>
+#include <gnu/gcj/jvmti/Breakpoint.h>
+#include <gnu/gcj/jvmti/BreakpointManager.h>
+
#include <java/lang/Class.h>
#include <java/lang/ClassLoader.h>
#include <java/lang/Object.h>
}
static jvmtiError JNICALL
+_Jv_JVMTI_SetBreakpoint (jvmtiEnv *env, jmethodID method, jlocation location)
+{
+ REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
+
+ using namespace gnu::gcj::jvmti;
+ Breakpoint *bp
+ = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
+ location);
+ if (bp == NULL)
+ {
+ jclass klass;
+ jvmtiError err = env->GetMethodDeclaringClass (method, &klass);
+ if (err != JVMTI_ERROR_NONE)
+ return err;
+
+ if (!_Jv_IsInterpretedClass (klass))
+ return JVMTI_ERROR_INVALID_CLASS;
+
+ _Jv_MethodBase *base = _Jv_FindInterpreterMethod (klass, method);
+ if (base == NULL)
+ return JVMTI_ERROR_INVALID_METHODID;
+
+ jint flags;
+ err = env->GetMethodModifiers (method, &flags);
+ if (err != JVMTI_ERROR_NONE)
+ return err;
+
+ if (flags & java::lang::reflect::Modifier::NATIVE)
+ return JVMTI_ERROR_NATIVE_METHOD;
+
+ _Jv_InterpMethod *imeth = reinterpret_cast<_Jv_InterpMethod *> (base);
+ if (imeth->get_insn (location) == NULL)
+ return JVMTI_ERROR_INVALID_LOCATION;
+
+ // Now the breakpoint can be safely installed
+ bp = BreakpointManager::newBreakpoint (reinterpret_cast<jlong> (method),
+ location);
+ }
+ else
+ {
+ // Duplicate breakpoints are not permitted by JVMTI
+ return JVMTI_ERROR_DUPLICATE;
+ }
+
+ return JVMTI_ERROR_NONE;
+}
+
+static jvmtiError JNICALL
+_Jv_JVMTI_ClearBreakpoint (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
+ jlocation location)
+{
+ REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
+
+ using namespace gnu::gcj::jvmti;
+
+ Breakpoint *bp
+ = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method),
+ location);
+ if (bp == NULL)
+ return JVMTI_ERROR_NOT_FOUND;
+
+ BreakpointManager::deleteBreakpoint (reinterpret_cast<jlong> (method), location);
+ return JVMTI_ERROR_NONE;
+}
+
+static jvmtiError JNICALL
_Jv_JVMTI_Allocate (MAYBE_UNUSED jvmtiEnv *env, jlong size,
unsigned char **result)
{
_Jv_JVMTI_RawMonitorWait, // RawMonitorWait
_Jv_JVMTI_RawMonitorNotify, // RawMonitorNotify
_Jv_JVMTI_RawMonitorNotifyAll, // RawMonitorNotifyAll
- UNIMPLEMENTED, // SetBreakpoint
- UNIMPLEMENTED, // ClearBreakpoint
+ _Jv_JVMTI_SetBreakpoint, // SetBreakpoint
+ _Jv_JVMTI_ClearBreakpoint, // ClearBreakpoint
RESERVED, // reserved40
UNIMPLEMENTED, // SetFieldAccessWatch
UNIMPLEMENTED, // ClearFieldAccessWatch
gnu_gcj_jvmti_source_files = \
-gnu/gcj/jvmti/Breakpoint.java
+gnu/gcj/jvmti/Breakpoint.java \
+gnu/gcj/jvmti/BreakpointManager.java \
+gnu/gcj/jvmti/Location.java
gnu_gcj_jvmti_header_files = $(patsubst %.java,%.h,$(gnu_gcj_jvmti_source_files))