internal jvmtiError AddGlobalReference(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, jobject obj) { long tag; jvmtiError error = environment.GetTag(obj, out tag); if (error != jvmtiError.None) { return(error); } if (tag == 0) { return(jvmtiError.IllegalArgument); } _globalReferences.AddOrUpdate(tag, t => { return(Tuple.Create(nativeEnvironment.NewGlobalReference(obj), 1)); }, (t, v) => { if (v.Item2 == 0) { return(Tuple.Create(nativeEnvironment.NewGlobalReference(obj), 1)); } else { return(Tuple.Create(v.Item1, v.Item2 + 1)); } }); return(jvmtiError.None); }
public jvalue(JavaVM virtualMachine, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, Value value) : this() { if (value.Data == 0) return; switch (value.Tag) { case Tag.Byte: ByteValue = (byte)value.Data; break; case Tag.Char: CharValue = (char)value.Data; break; case Tag.Float: IntValue = (int)(uint)value.Data; break; case Tag.Int: IntValue = (int)value.Data; break; case Tag.Double: LongValue = (long)(ulong)value.Data; break; case Tag.Long: LongValue = value.Data; break; case Tag.Short: ShortValue = (short)value.Data; break; case Tag.Boolean: break; case Tag.Array: case Tag.Object: case Tag.String: case Tag.Thread: case Tag.ThreadGroup: case Tag.ClassLoader: case Tag.ClassObject: if (value.Data == 0) return; ObjectValue = virtualMachine.GetLocalReferenceForObject(nativeEnvironment, new ObjectId(value.Data)).Value; break; case Tag.Void: case Tag.Invalid: default: throw new ArgumentException(); } }
public static EventFilter CreateFilter(EventKind internalEventKind, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, RequestId requestId, SuspendPolicy suspendPolicy, ImmutableList<EventRequestModifier> modifiers) { if (modifiers.Count == 0) return new PassThroughEventFilter(internalEventKind, requestId, suspendPolicy, modifiers); EventFilter[] elements = modifiers.Select(modifier => CreateFilter(internalEventKind, environment, nativeEnvironment, requestId, suspendPolicy, modifiers, modifier)).ToArray(); if (elements.Length == 1) return elements[0]; return new AggregateEventFilter(internalEventKind, requestId, suspendPolicy, modifiers, elements); }
internal TaggedReferenceTypeId TrackLocalClassReference(jclass classHandle, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, bool freeLocalReference) { if (classHandle == jclass.Null) { return(default(TaggedReferenceTypeId)); } bool isArrayClass; JvmtiErrorHandler.ThrowOnFailure(environment.IsArrayClass(classHandle, out isArrayClass)); bool isInterface; JvmtiErrorHandler.ThrowOnFailure(environment.IsInterface(classHandle, out isInterface)); TypeTag typeTag = isArrayClass ? TypeTag.Array : (isInterface ? TypeTag.Interface : TypeTag.Class); int hashCode; JvmtiErrorHandler.ThrowOnFailure(environment.GetObjectHashCode(classHandle, out hashCode)); ReferenceTypeId typeId = new ReferenceTypeId(hashCode); TaggedReferenceTypeId taggedTypeId = new TaggedReferenceTypeId(typeTag, typeId); lock (_classes) { if (!_classes.ContainsKey(typeId)) { jweak weak = nativeEnvironment.NewWeakGlobalReference(classHandle); bool added = false; if (!_classes.ContainsKey(typeId)) { _classes.Add(typeId, new jclass(weak.Handle)); added = true; } if (!added) { nativeEnvironment.DeleteWeakGlobalReference(weak); } } } if (freeLocalReference) { nativeEnvironment.DeleteLocalReference(classHandle); } return(taggedTypeId); }
public int GetEnvironment(out JvmtiEnvironment environment) { jvmtiEnvHandle env; int error = RawInterface.GetEnv(this, out env, jvmtiVersion.Version1_1); if (error == 0) { environment = JvmtiEnvironment.GetOrCreateInstance(this, env); } else { environment = null; } return(error); }
private static EventFilter CreateFilter(EventKind internalEventKind, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, RequestId requestId, SuspendPolicy suspendPolicy, ImmutableList<EventRequestModifier> modifiers, EventRequestModifier modifier) { switch (modifier.Kind) { case ModifierKind.Count: return new CountEventFilter(internalEventKind, requestId, suspendPolicy, modifiers, modifier.Count); case ModifierKind.ThreadFilter: return new ThreadEventFilter(internalEventKind, requestId, suspendPolicy, modifiers, modifier.Thread); case ModifierKind.ClassTypeFilter: throw new NotImplementedException(); case ModifierKind.ClassMatchFilter: throw new NotImplementedException(); case ModifierKind.ClassExcludeFilter: throw new NotImplementedException(); case ModifierKind.LocationFilter: return new LocationEventFilter(internalEventKind, requestId, suspendPolicy, modifiers, modifier.Location); case ModifierKind.ExceptionFilter: return new ExceptionEventFilter(internalEventKind, requestId, suspendPolicy, modifiers, modifier.ExceptionOrNull, modifier.Caught, modifier.Uncaught); case ModifierKind.FieldFilter: throw new NotImplementedException(); case ModifierKind.Step: return new StepEventFilter(internalEventKind, requestId, suspendPolicy, modifiers, modifier.Thread, environment, nativeEnvironment, modifier.StepSize, modifier.StepDepth); case ModifierKind.InstanceFilter: throw new NotImplementedException(); case ModifierKind.SourceNameMatchFilter: throw new NotImplementedException(); case ModifierKind.Conditional: throw new NotImplementedException(); case ModifierKind.Invalid: default: throw new ArgumentException(); } }
public int AttachCurrentThreadAsDaemon(JvmtiEnvironment environment, out JniEnvironment nativeEnvironment, bool agentThread) { JavaVMAttachArgs args = new JavaVMAttachArgs(jniVersion.Version1_6, IntPtr.Zero, jthreadGroup.Null); bool alreadyAgent = IsAgentThread.Value; if (agentThread && !alreadyAgent) { IsAgentThread.Value = true; } JNIEnvHandle jniEnv; int error = RawInterface.AttachCurrentThreadAsDaemon(this, out jniEnv, ref args); if (error == 0) { bool created; nativeEnvironment = JniEnvironment.GetOrCreateInstance(jniEnv, out created); if (agentThread && !alreadyAgent) { if (environment == null) { GetEnvironment(out environment); } jthread thread; JvmtiErrorHandler.ThrowOnFailure(environment.RawInterface.GetCurrentThread(environment, out thread)); if (thread != jthread.Null) { ThreadId threadId = TrackLocalThreadReference(thread, environment, nativeEnvironment, true); lock (_agentThreads) { _agentThreads.Add(threadId); } } } } else { nativeEnvironment = null; } return(error); }
internal jvmtiError RemoveGlobalReference(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, jobject obj) { long tag; jvmtiError error = environment.GetTag(obj, out tag); if (error != jvmtiError.None) { return(error); } if (tag == 0) { return(jvmtiError.IllegalArgument); } var result = _globalReferences.AddOrUpdate(tag, t => { return(Tuple.Create(jobject.Null, 0)); }, (t, v) => { if (v.Item2 == 0) { return(Tuple.Create(jobject.Null, 0)); } else if (v.Item2 == 1) { nativeEnvironment.DeleteGlobalReference(v.Item1); return(Tuple.Create(jobject.Null, 0)); } else { return(Tuple.Create(v.Item1, v.Item2 - 1)); } }); return(jvmtiError.None); }
internal ThreadId TrackLocalThreadReference(jthread thread, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, bool freeLocalReference) { if (thread == jthread.Null) { return(default(ThreadId)); } int hashCode; JvmtiErrorHandler.ThrowOnFailure(environment.RawInterface.GetObjectHashCode(environment, thread, out hashCode)); ThreadId threadId = new ThreadId(hashCode); lock (_threads) { if (!_threads.ContainsKey(threadId)) { jweak weak = nativeEnvironment.NewWeakGlobalReference(thread); bool added = false; if (!_threads.ContainsKey(threadId)) { _threads.Add(threadId, new jthread(weak.Handle)); added = true; } if (!added) { nativeEnvironment.DeleteWeakGlobalReference(weak); } } } if (freeLocalReference) { nativeEnvironment.DeleteLocalReference(thread); } return(threadId); }
internal jclass FindBaseClass(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, jclass classHandle, string signature) { string currentSignature; string genericSignature; JvmtiErrorHandler.ThrowOnFailure(environment.GetClassSignature(classHandle, out currentSignature, out genericSignature)); if (currentSignature == signature) { return((jclass)nativeEnvironment.NewGlobalReference(classHandle)); } jclass superClass = nativeEnvironment.GetSuperclass(classHandle); if (superClass == jclass.Null) { return(jclass.Null); } jclass result = FindBaseClass(environment, nativeEnvironment, superClass, signature); nativeEnvironment.DeleteLocalReference(superClass); return(result); }
internal void HandleVMInit(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, jthread thread) { jclass threadClass = nativeEnvironment.GetObjectClass(thread); _threadClass = FindBaseClass(environment, nativeEnvironment, threadClass, "Ljava/lang/Thread;"); { jclass classClass = nativeEnvironment.GetObjectClass(threadClass); _classClass = FindBaseClass(environment, nativeEnvironment, classClass, "Ljava/lang/Class;"); nativeEnvironment.DeleteLocalReference(classClass); } { jvmtiThreadInfo threadInfo; JvmtiErrorHandler.ThrowOnFailure(environment.GetThreadInfo(thread, out threadInfo)); jclass threadGroupClass = nativeEnvironment.GetObjectClass(threadInfo._threadGroup); _threadGroupClass = FindBaseClass(environment, nativeEnvironment, threadGroupClass, "Ljava/lang/ThreadGroup;"); jclass classLoaderClass = nativeEnvironment.GetObjectClass(threadInfo._contextClassLoader); _classLoaderClass = FindBaseClass(environment, nativeEnvironment, classLoaderClass, "Ljava/lang/ClassLoader;"); nativeEnvironment.DeleteLocalReference(classLoaderClass); nativeEnvironment.DeleteLocalReference(threadGroupClass); nativeEnvironment.DeleteLocalReference(threadInfo._contextClassLoader); nativeEnvironment.DeleteLocalReference(threadInfo._threadGroup); environment.Deallocate(threadInfo._name); } nativeEnvironment.DeleteLocalReference(threadClass); jobject stringObject = nativeEnvironment.NewString(string.Empty); jclass stringClass = nativeEnvironment.GetObjectClass(stringObject); _stringClass = FindBaseClass(environment, nativeEnvironment, stringClass, "Ljava/lang/String;"); nativeEnvironment.DeleteLocalReference(stringObject); nativeEnvironment.DeleteLocalReference(stringClass); }
public override bool ProcessEvent(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, EventProcessor processor, ThreadId thread, TaggedReferenceTypeId @class, Location? location) { _current++; if (_current == _count) { _current = 0; return true; } return false; }
public override bool ProcessEvent(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, EventProcessor processor, ThreadId thread, TaggedReferenceTypeId @class, Location? location) { if (!location.HasValue) return false; return _location.Index == location.Value.Index && _location.Class == location.Value.Class && _location.Method == location.Value.Method; }
private bool ShouldSkipCurrentMethod(JavaVM virtualMachine, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, jthread thread, int stackDepth, Location location, out bool convertToFramePop) { Contract.Assert(_depth == StepDepth.Into || _depth == StepDepth.Over); convertToFramePop = false; if (!_hasMethodInfo || stackDepth < _stackDepth || (stackDepth == _stackDepth && (location.Method.Equals(_lastMethod)))) return false; /* * change this to a Frame Pop event if we're not in a native frame */ bool native; jvmtiError error = environment.IsMethodNative(location.Method, out native); if (error != jvmtiError.None) return false; convertToFramePop = !native; if (_depth == StepDepth.Over || native) return true; JvmAccessModifiers modifiers; error = environment.GetMethodModifiers(location.Method, out modifiers); if (error != jvmtiError.None || ((modifiers & JvmAccessModifiers.Static) != 0)) return false; jobject thisObject; error = environment.GetLocalObject(thread, 0, 0, out thisObject); if (error != jvmtiError.None) return false; try { bool classLoader = nativeEnvironment.IsInstanceOf(thisObject, virtualMachine.ClassLoaderClass); if (!classLoader) return false; string name; string signature; string genericSignature; error = environment.GetMethodName(location.Method, out name, out signature, out genericSignature); if (error != jvmtiError.None) return false; if (name == "loadClass" && signature == "(Ljava/lang/String;)Ljava/lang/Class;") return true; if (name == "checkPackageAccess" && signature == "(Ljava/lang/Class;Ljava/security/ProtectionDomain;)V") return true; return false; } finally { nativeEnvironment.DeleteLocalReference(thisObject); } }
private jvmtiError ApplySuspendPolicy(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, SuspendPolicy policy, ThreadId eventThread) { if (policy == SuspendPolicy.EventThread && eventThread == default(ThreadId)) { return jvmtiError.InvalidThread; } switch (policy) { case SuspendPolicy.None: return jvmtiError.None; case SuspendPolicy.EventThread: return environment.SuspendThread(nativeEnvironment, eventThread); case SuspendPolicy.All: ThreadId[] requestList; JvmtiErrorHandler.ThrowOnFailure(environment.GetAllThreads(nativeEnvironment, out requestList)); jvmtiError[] errors; return environment.SuspendThreads(nativeEnvironment, requestList, out errors); default: throw new ArgumentException("Invalid suspend policy."); } }
public Error SetEvent(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, EventKind eventKind, SuspendPolicy suspendPolicy, ImmutableList<EventRequestModifier> modifiers, bool internalRequest, out RequestId requestId) { Contract.Requires<ArgumentNullException>(modifiers != null, "modifiers"); requestId = default(RequestId); EventKind internalEventKind = eventKind; EventRequestModifier locationModifier = default(EventRequestModifier); EventRequestModifier stepModifier = default(EventRequestModifier); switch (eventKind) { case EventKind.Breakpoint: // we're going to need the location modifier to set the breakpoint if (modifiers.Count == 0 || modifiers[0].Kind != ModifierKind.LocationFilter) return Error.IllegalArgument; locationModifier = modifiers[0]; break; case EventKind.SingleStep: // the first modifier contains the step properties if (modifiers.Count == 0 || modifiers[0].Kind != ModifierKind.Step) return Error.IllegalArgument; stepModifier = modifiers[0]; if (stepModifier.StepDepth == StepDepth.Out) { // we want to attach the filter as a frame pop request instead of a step request eventKind = EventKind.FramePop; internalEventKind = EventKind.SingleStep; } break; default: break; } requestId = new RequestId(Interlocked.Increment(ref _nextRequestId)); if (internalRequest) requestId = new RequestId(-requestId.Id); EventFilter filter = EventFilter.CreateFilter(internalEventKind, environment, nativeEnvironment, requestId, suspendPolicy, modifiers); return SetEventInternal(environment, nativeEnvironment, eventKind, filter); }
private void SendClassPrepareEvent(JvmtiEnvironment environment, EventFilter filter, ThreadId threadId, TaggedReferenceTypeId classId, string signature, ClassStatus classStatus, bool preventSuspend) { if (!VirtualMachine.IsAgentThread.Value) { // ignore events before VMInit if (AgentEventDispatcher == null) return; // dispatch this call to an agent thread Action<JvmtiEnvironment, EventFilter, ThreadId, TaggedReferenceTypeId, string, ClassStatus, bool> method = SendClassPrepareEvent; AgentEventDispatcher.Invoke(method, environment, filter, threadId, classId, signature, classStatus, preventSuspend); return; } JniEnvironment nativeEnvironment; JniErrorHandler.ThrowOnFailure(VirtualMachine.AttachCurrentThreadAsDaemon(environment, out nativeEnvironment, true)); SuspendPolicy suspendPolicy = preventSuspend ? SuspendPolicy.None : filter.SuspendPolicy; if (!preventSuspend) ApplySuspendPolicy(environment, nativeEnvironment, filter.SuspendPolicy, threadId); Callback.ClassPrepare(suspendPolicy, filter.RequestId, threadId, classId.TypeTag, classId.TypeId, signature, classStatus); }
public override bool ProcessEvent(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, EventProcessor processor, ThreadId thread, TaggedReferenceTypeId @class, Location? location) { return true; }
private jvmtiError GetEnvironment(out JvmtiEnvironment environment, out JniEnvironment nativeEnvironment) { environment = null; nativeEnvironment = null; environment = _environment; int error = VirtualMachine.AttachCurrentThreadAsDaemon(environment, out nativeEnvironment, true); if (error != 0) return GetToolsErrorForJniError(error); //error = VirtualMachine.GetEnvironment(out environment); //if (error != 0) // return GetToolsErrorForJniError(error); return jvmtiError.None; }
public StepEventFilter(EventKind internalEventKind, RequestId requestId, SuspendPolicy suspendPolicy, IEnumerable<EventRequestModifier> modifiers, ThreadId thread, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, StepSize size, StepDepth depth) : base(internalEventKind, requestId, suspendPolicy, modifiers, thread) { if (size == StepSize.Statement && JavaVM.DisableStatementStepping) size = StepSize.Line; _size = size; _depth = depth; // gather reference information for the thread using (var threadHandle = environment.VirtualMachine.GetLocalReferenceForThread(nativeEnvironment, thread)) { if (threadHandle.IsAlive) { jvmtiError error = environment.GetFrameLocation(threadHandle.Value, 0, out _lastMethod, out _lastLocation); if (error == jvmtiError.None) error = environment.GetFrameCount(threadHandle.Value, out _stackDepth); if (error == jvmtiError.None) _hasMethodInfo = true; UpdateLastLine(environment); if (error == jvmtiError.None && size == StepSize.Statement && (depth == StepDepth.Over || depth == StepDepth.Into)) { byte[] bytecode; JvmtiErrorHandler.ThrowOnFailure(environment.GetBytecodes(_lastMethod, out bytecode)); _disassembledMethod = BytecodeDisassembler.Disassemble(bytecode); TaggedReferenceTypeId declaringClass; JvmtiErrorHandler.ThrowOnFailure(environment.GetMethodDeclaringClass(nativeEnvironment, _lastMethod, out declaringClass)); using (var classHandle = environment.VirtualMachine.GetLocalReferenceForClass(nativeEnvironment, declaringClass.TypeId)) { int constantPoolCount; byte[] data; JvmtiErrorHandler.ThrowOnFailure(environment.GetConstantPool(classHandle.Value, out constantPoolCount, out data)); List<ConstantPoolEntry> entryList = new List<ConstantPoolEntry>(); int currentPosition = 0; for (int i = 0; i < constantPoolCount - 1; i++) { entryList.Add(ConstantPoolEntry.FromBytes(data, ref currentPosition)); switch (entryList.Last().Type) { case ConstantType.Double: case ConstantType.Long: // these entries take 2 slots entryList.Add(ConstantPoolEntry.Reserved); i++; break; default: break; } } _constantPool = entryList.AsReadOnly(); string classSignature; string classGenericSignature; JvmtiErrorHandler.ThrowOnFailure(environment.GetClassSignature(classHandle.Value, out classSignature, out classGenericSignature)); string methodName; string methodSignature; string methodGenericSignature; JvmtiErrorHandler.ThrowOnFailure(environment.GetMethodName(_lastMethod, out methodName, out methodSignature, out methodGenericSignature)); jobject classLoader; JvmtiErrorHandler.ThrowOnFailure(environment.GetClassLoader(classHandle.Value, out classLoader)); long classLoaderTag; JvmtiErrorHandler.ThrowOnFailure(environment.TagClassLoader(classLoader, out classLoaderTag)); ReadOnlyCollection<ExceptionTableEntry> exceptionTable; JvmtiErrorHandler.ThrowOnFailure(environment.VirtualMachine.GetExceptionTable(classLoaderTag, classSignature, methodName, methodSignature, out exceptionTable)); _evaluationStackDepths = BytecodeDisassembler.GetEvaluationStackDepths(_disassembledMethod, _constantPool, exceptionTable); } } } } }
private void UpdateLastLine(JvmtiEnvironment environment) { _lastLine = null; if (!_hasMethodInfo) return; LineNumberData[] lines; jvmtiError error = environment.GetLineNumberTable(_lastMethod, out lines); if (error != jvmtiError.None) return; LineNumberData entry = lines.LastOrDefault(i => i.LineCodeIndex <= _lastLocation.Value); if (entry.LineNumber != 0) _lastLine = entry.LineNumber; }
public abstract bool ProcessEvent(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, EventProcessor processor, ThreadId thread, TaggedReferenceTypeId @class, Location? location);
public static unsafe int OnLoad(IntPtr vmPtr, IntPtr optionsPtr, IntPtr reserved) { _loaded = true; JavaVM vm = JavaVM.GetOrCreateInstance(new JavaVMHandle(vmPtr)); string optionsString = null; if (optionsPtr != IntPtr.Zero) { optionsString = ModifiedUTF8Encoding.GetString((byte *)optionsPtr); } string[] options = new string[0]; if (optionsString != null) { options = optionsString.Split(',', ';'); } #if false // quick test GetEnvironmentVersion(vm); Action <JavaVM> action = GetEnvironmentVersion; IAsyncResult result = action.BeginInvoke(vm, null, null); result.AsyncWaitHandle.WaitOne(); #endif AppDomain.CurrentDomain.AssemblyResolve += HandleAssemblyResolve; if (options.Contains("ShowAgentExceptions", StringComparer.OrdinalIgnoreCase)) { AppDomain.CurrentDomain.FirstChanceException += HandleFirstChanceException; AppDomain.CurrentDomain.UnhandledException += HandleUnhandledException; //AppDomain.CurrentDomain.ProcessExit += HandleProcessExit; } if (options.Contains("DisableStatementStepping", StringComparer.OrdinalIgnoreCase)) { JavaVM.DisableStatementStepping = true; } List <WaitHandle> waitHandles = new List <WaitHandle>(); Binding binding; /* * start the wcf services and wait for the client to connect */ #if false /* IJvmEventsService */ _jvmEventsPublisherHost = new ServiceHost(typeof(JvmEventsPublisher)); Binding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None) { ReceiveTimeout = TimeSpan.MaxValue, SendTimeout = TimeSpan.MaxValue }; _jvmEventsPublisherHost.AddServiceEndpoint(typeof(IJvmEventsService), binding, "net.pipe://localhost/Tvl.Java.DebugHost/JvmEventsService/"); IAsyncResult jvmEventsPublisherStartResult = _jvmEventsPublisherHost.BeginOpen(null, null); waitHandles.Add(jvmEventsPublisherStartResult.AsyncWaitHandle); /* IJvmToolsInterfaceService */ _jvmToolsInterfaceHost = new ServiceHost(typeof(JvmToolsInterfaceService)); binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None) { ReceiveTimeout = TimeSpan.MaxValue, SendTimeout = TimeSpan.MaxValue }; _jvmToolsInterfaceHost.AddServiceEndpoint(typeof(IJvmToolsInterfaceService), binding, "net.pipe://localhost/Tvl.Java.DebugHost/JvmToolsInterfaceService/"); IAsyncResult toolsInterfaceStartResult = _jvmToolsInterfaceHost.BeginOpen(null, null); waitHandles.Add(toolsInterfaceStartResult.AsyncWaitHandle); /* IJvmDebugSessionService */ _jvmDebugSessionHost = new ServiceHost(typeof(JvmDebugSessionService)); binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None) { ReceiveTimeout = TimeSpan.MaxValue, SendTimeout = TimeSpan.MaxValue }; _jvmDebugSessionHost.AddServiceEndpoint(typeof(IJvmDebugSessionService), binding, "net.pipe://localhost/Tvl.Java.DebugHost/JvmDebugSessionService/"); IAsyncResult debugSessionStartResult = _jvmDebugSessionHost.BeginOpen(null, null); waitHandles.Add(debugSessionStartResult.AsyncWaitHandle); #endif /* IDebugProtocolService */ var debugProtocolService = new DebugProtocolService(vm); _debugProtocolHost = new ServiceHost(debugProtocolService); binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None) { MaxReceivedMessageSize = 10 * 1024 * 1024, ReceiveTimeout = TimeSpan.MaxValue, SendTimeout = TimeSpan.MaxValue }; _debugProtocolHost.AddServiceEndpoint(typeof(IDebugProtocolService), binding, "net.pipe://localhost/Tvl.Java.DebugHost/DebugProtocolService/"); IAsyncResult debugProtocolStartResult = _debugProtocolHost.BeginOpen(null, null); waitHandles.Add(debugProtocolStartResult.AsyncWaitHandle); /* Wait for the services to finish opening */ WaitHandle.WaitAll(waitHandles.ToArray()); EventWaitHandle eventWaitHandle = null; try { eventWaitHandle = EventWaitHandle.OpenExisting(string.Format("JavaDebuggerInitHandle{0}", Process.GetCurrentProcess().Id)); } catch (WaitHandleCannotBeOpenedException) { // must have been launched without the debugger } if (eventWaitHandle != null) { eventWaitHandle.Set(); Action waitAction = _debuggerAttachComplete.Wait; IAsyncResult waitResult = waitAction.BeginInvoke(vm.HandleAsyncOperationComplete, null); DispatcherFrame frame = new DispatcherFrame(true); JvmtiEnvironment environment = debugProtocolService.Environment; vm.PushDispatcherFrame(frame, environment, waitResult); } return(0); }
public override bool ProcessEvent(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, EventProcessor processor, ThreadId thread, TaggedReferenceTypeId @class, Location? location) { foreach (EventFilter filter in _filters) { if (!filter.ProcessEvent(environment, nativeEnvironment, processor, thread, @class, location)) return false; } return true; }
public Error SetEventInternal(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, EventKind eventKind, EventFilter filter) { EventRequestModifier locationModifier = default(EventRequestModifier); EventRequestModifier stepModifier = default(EventRequestModifier); switch (eventKind) { case EventKind.Breakpoint: // we're going to need the location modifier to set the breakpoint if (filter.Modifiers.Count == 0 || filter.Modifiers[0].Kind != ModifierKind.LocationFilter) return Error.IllegalArgument; locationModifier = filter.Modifiers[0]; break; case EventKind.SingleStep: // the first modifier contains the step properties if (filter.Modifiers.Count == 0 || filter.Modifiers[0].Kind != ModifierKind.Step) return Error.IllegalArgument; stepModifier = filter.Modifiers[0]; break; case EventKind.FramePop: if (filter.InternalEventKind == EventKind.SingleStep) goto case EventKind.SingleStep; break; default: break; } lock (_eventRequests) { Dictionary<RequestId, EventFilter> requests; if (!_eventRequests.TryGetValue(eventKind, out requests)) { requests = new Dictionary<RequestId, EventFilter>(); _eventRequests.Add(eventKind, requests); } requests.Add(filter.RequestId, filter); if (requests.Count == 1) { JvmEventType? eventToEnable = GetJvmEventType(eventKind); if (eventToEnable != null) { jvmtiError error = Environment.SetEventNotificationMode(JvmEventMode.Enable, eventToEnable.Value); if (error != jvmtiError.None) return GetStandardError(error); } } } switch (eventKind) { case EventKind.Breakpoint: { Contract.Assert(locationModifier.Kind == ModifierKind.LocationFilter); jmethodID methodId = locationModifier.Location.Method; jlocation location = new jlocation((long)locationModifier.Location.Index); jvmtiError error = Environment.SetBreakpoint(methodId, location); if (error != jvmtiError.None) return GetStandardError(error); break; } case EventKind.FramePop: if (filter.InternalEventKind == EventKind.SingleStep) { using (var thread = VirtualMachine.GetLocalReferenceForThread(nativeEnvironment, stepModifier.Thread)) { if (!thread.IsAlive) return Error.InvalidThread; jvmtiError error = environment.RawInterface.NotifyFramePop(environment, thread.Value, 0); if (error != jvmtiError.None) return GetStandardError(error); } } break; default: break; } return Error.None; }
internal TaggedObjectId TrackLocalObjectReference(jobject @object, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, bool freeLocalReference) { if (@object == jobject.Null) { return(new TaggedObjectId(Tag.Object, new ObjectId(0), default(TaggedReferenceTypeId))); } long tag; JvmtiErrorHandler.ThrowOnFailure(environment.GetTag(@object, out tag)); TaggedReferenceTypeId type = default(TaggedReferenceTypeId); Tag objectKind; if (tag == 0) { long uniqueTag = Interlocked.Increment(ref _nextTag); /* first figure out what type of object we're dealing with. could be: * - String * - Thread * - ThreadGroup * - ClassLoader * - ClassObject * - Array * - Object */ // check for array jclass objectClass = nativeEnvironment.GetObjectClass(@object); try { type = TrackLocalClassReference(objectClass, environment, nativeEnvironment, false); bool isArray = type.TypeTag == TypeTag.Array; if (isArray) { objectKind = Tag.Array; } else { if (_stringClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _stringClass)) { objectKind = Tag.String; } else if (_threadClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _threadClass)) { objectKind = Tag.Thread; } else if (_threadGroupClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _threadGroupClass)) { objectKind = Tag.ThreadGroup; } else if (_classClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _classClass)) { objectKind = Tag.ClassObject; } else if (_classLoaderClass != jclass.Null && nativeEnvironment.IsInstanceOf(@object, _classLoaderClass)) { objectKind = Tag.ClassLoader; } else { objectKind = Tag.Object; } } } finally { nativeEnvironment.DeleteLocalReference(objectClass); } tag = (uniqueTag << 8) | (uint)objectKind; JvmtiErrorHandler.ThrowOnFailure(environment.SetTag(@object, tag)); lock (_objects) { _objects.Add(new ObjectId(tag), nativeEnvironment.NewWeakGlobalReference(@object)); } } else { jclass objectClass = nativeEnvironment.GetObjectClass(@object); type = TrackLocalClassReference(objectClass, environment, nativeEnvironment, true); } if (freeLocalReference) { nativeEnvironment.DeleteLocalReference(@object); } objectKind = (Tag)(tag & 0xFF); return(new TaggedObjectId(objectKind, new ObjectId(tag), type)); }
private void InitializeAgentThread(JvmtiEnvironment environment, JniEnvironment nativeEnvironment) { _agentStartedEvent = new ManualResetEventSlim(false); _agentThread = CreateAgentThread(nativeEnvironment); _agentCallbackDelegate = AgentDispatcherThread; JvmtiErrorHandler.ThrowOnFailure(environment.RawInterface.RunAgentThread(environment, _agentThread, _agentCallbackDelegate, IntPtr.Zero, JvmThreadPriority.Maximum)); _agentStartedEvent.Wait(); }
public override bool ProcessEvent(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, EventProcessor processor, ThreadId thread, TaggedReferenceTypeId @class, Location? location) { if (!base.ProcessEvent(environment, nativeEnvironment, processor, thread, @class, location)) return false; // Step Out is implemented with Frame Pop events set at the correct depth if (_depth == StepDepth.Out) { if (location.HasValue && !location.Value.Method.Equals(_lastMethod)) { _lastLocation = new jlocation((long)location.Value.Index); _lastMethod = location.Value.Method; UpdateLastLine(environment); } return true; } using (var threadHandle = environment.VirtualMachine.GetLocalReferenceForThread(nativeEnvironment, thread)) { int stackDepth; JvmtiErrorHandler.ThrowOnFailure(environment.GetFrameCount(threadHandle.Value, out stackDepth)); if (_hasMethodInfo && stackDepth > _stackDepth) { bool convertToFramePop; if (location.HasValue && (!_convertedToFramePop || !_framePopMethod.Equals(location.Value.Method)) && ShouldSkipCurrentMethod(processor.VirtualMachine, environment, nativeEnvironment, threadHandle.Value, stackDepth, location.Value, out convertToFramePop)) { if (convertToFramePop) { // remove the single step event JvmtiErrorHandler.ThrowOnFailure((jvmtiError)processor.ClearEventInternal(EventKind.FramePop, this.RequestId)); JvmtiErrorHandler.ThrowOnFailure((jvmtiError)processor.ClearEventInternal(EventKind.SingleStep, this.RequestId)); // set an actual step filter to respond when the thread arrives back in this frame JvmtiErrorHandler.ThrowOnFailure((jvmtiError)processor.SetEventInternal(environment, nativeEnvironment, EventKind.FramePop, this)); _convertedToFramePop = true; _framePopMethod = location.Value.Method; } return false; } else { _convertedToFramePop = false; return true; } } else if (stackDepth == _stackDepth) { if (_size == StepSize.Statement && _disassembledMethod != null) { int instructionIndex = _disassembledMethod.Instructions.FindIndex(i => (uint)i.Offset == location.Value.Index); if (instructionIndex >= 0 && _evaluationStackDepths != null && (_evaluationStackDepths[instructionIndex] ?? 0) != 0) { return false; } else if (instructionIndex >= 0 && _disassembledMethod.Instructions[instructionIndex].OpCode.FlowControl == JavaFlowControl.Branch) { // follow branch instructions before stopping return false; } } else if (_lastLine != null) { // see if we're on the same line LineNumberData[] lines; jvmtiError error = environment.GetLineNumberTable(location.Value.Method, out lines); if (error == jvmtiError.None) { LineNumberData entry = lines.LastOrDefault(i => i.LineCodeIndex <= (long)location.Value.Index); if (entry.LineNumber == _lastLine) return false; } } } if (location.HasValue) { _lastLocation = new jlocation((long)location.Value.Index); _lastMethod = location.Value.Method; UpdateLastLine(environment); } _stackDepth = stackDepth; return true; } }
private void SendSingleStepEvent(JvmtiEnvironment environment, EventFilter filter, ThreadId threadId, Location location) { if (!VirtualMachine.IsAgentThread.Value) { // ignore events before VMInit if (AgentEventDispatcher == null) return; // dispatch this call to an agent thread Action<JvmtiEnvironment, EventFilter, ThreadId, Location> invokeMethod = SendSingleStepEvent; AgentEventDispatcher.Invoke(invokeMethod, environment, filter, threadId, location); return; } JniEnvironment nativeEnvironment; JniErrorHandler.ThrowOnFailure(VirtualMachine.AttachCurrentThreadAsDaemon(environment, out nativeEnvironment, false)); ApplySuspendPolicy(environment, nativeEnvironment, filter.SuspendPolicy, threadId); Callback.SingleStep(filter.SuspendPolicy, filter.RequestId, threadId, location); }
public jvalue(JavaVM virtualMachine, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, Value value) : this() { if (value.Data == 0) { return; } switch (value.Tag) { case Tag.Byte: ByteValue = (byte)value.Data; break; case Tag.Char: CharValue = (char)value.Data; break; case Tag.Float: IntValue = (int)(uint)value.Data; break; case Tag.Int: IntValue = (int)value.Data; break; case Tag.Double: LongValue = (long)(ulong)value.Data; break; case Tag.Long: LongValue = value.Data; break; case Tag.Short: ShortValue = (short)value.Data; break; case Tag.Boolean: break; case Tag.Array: case Tag.Object: case Tag.String: case Tag.Thread: case Tag.ThreadGroup: case Tag.ClassLoader: case Tag.ClassObject: if (value.Data == 0) { return; } ObjectValue = virtualMachine.GetLocalReferenceForObject(nativeEnvironment, new ObjectId(value.Data)).Value; break; case Tag.Void: case Tag.Invalid: default: throw new ArgumentException(); } }