public int GetThreadProperties(enum_THREADPROPERTY_FIELDS fields, THREADPROPERTIES[] ptp) { DLog.Debug(DContext.VSDebuggerComCall, "IDebugThread2.GetThreadProperties {0}", fields); var info = new THREADPROPERTIES(); if (fields.HasFlag(enum_THREADPROPERTY_FIELDS.TPF_ID)) { info.dwThreadId = (uint)tid; info.dwFields |= enum_THREADPROPERTY_FIELDS.TPF_ID; } if (fields.HasFlag(enum_THREADPROPERTY_FIELDS.TPF_NAME)) { info.bstrName = GetNameAsync().Await(DalvikProcess.VmTimeout); info.dwFields |= enum_THREADPROPERTY_FIELDS.TPF_NAME; } if (fields.HasFlag(enum_THREADPROPERTY_FIELDS.TPF_STATE)) { info.dwThreadState = (uint)State; info.dwFields |= enum_THREADPROPERTY_FIELDS.TPF_STATE; } if (fields.HasFlag(enum_THREADPROPERTY_FIELDS.TPF_SUSPENDCOUNT)) { info.dwSuspendCount = (uint)GetSuspendCountAsync().Await(DalvikProcess.VmTimeout); info.dwFields |= enum_THREADPROPERTY_FIELDS.TPF_SUSPENDCOUNT; } if (fields.HasFlag(enum_THREADPROPERTY_FIELDS.TPF_PRIORITY)) { info.bstrPriority = "Normal"; info.dwFields |= enum_THREADPROPERTY_FIELDS.TPF_PRIORITY; } ptp[0] = info; return(VSConstants.S_OK); }
/// <summary> /// Debugger has connected. /// </summary> private void OnDebuggerDalvikEvent(object sender, JdwpEvent e) { DLog.Debug(DContext.VSDebuggerEvent, "DalvikEvent {0}", e); var debugger = (XDebugger)sender; if (!debugger.Connected || token.IsCancellationRequested) { return; } if ((debugger.AppName == packageName) && !debuggerLaunched) { // Inform status debuggerLaunched = true; outputPane.LogLine("Found process to debug"); // We've found the process to debug. var currentMonitor = jdwpMonitor; jdwpMonitor = null; debugger.Attach(currentMonitor); DisposeOtherDebuggers(debugger); // Prepare the debugger stateUpdate(LauncherStates.Attaching, string.Empty); outputPane.LogLine("Preparing debugger launch"); try { LaunchVsDebugEngine(ide, apkPath, debugger, launchFlags, stateUpdate); } catch (Exception ex) { stateUpdate(LauncherStates.Error, ex.Message); } } }
/// <summary> /// Removes the specified exception so it is no longer handled by the debug engine. /// </summary> public int RemoveSetException(EXCEPTION_INFO[] pException) { DLog.Debug(DContext.VSDebuggerComCall, "IDebugEngine2.RemoveSetException"); var copyToProgram = false; foreach (var info in pException) { if (info.guidType == GuidList.Guids.guidDot42DebuggerId) { if (info.bstrExceptionName == ExceptionConstants.TopLevelName) { exceptionBehaviorMap.ResetDefaults(); copyToProgram = true; } else { exceptionBehaviorMap[info.bstrExceptionName] = null; copyToProgram = true; } } } if (copyToProgram) { CopyExceptionMapToProgram(); } return(VSConstants.S_OK); }
/// <summary> /// Specifies how the debug engine (DE) should handle a given exception. /// </summary> public int SetException(EXCEPTION_INFO[] pException) { DLog.Debug(DContext.VSDebuggerComCall, "IDebugEngine2.SetException"); var copyToProgram = false; foreach (var info in pException) { if (info.guidType == GuidList.Guids.guidDot42DebuggerId) { if (info.bstrExceptionName == ExceptionConstants.TopLevelName) { exceptionBehaviorMap.DefaultStopOnThrow = info.dwState.HasFlag(enum_EXCEPTION_STATE.EXCEPTION_STOP_FIRST_CHANCE); exceptionBehaviorMap.DefaultStopUncaught = info.dwState.HasFlag(enum_EXCEPTION_STATE.EXCEPTION_STOP_USER_UNCAUGHT); copyToProgram = true; } else { var behavior = new ExceptionBehavior( info.bstrExceptionName, info.dwState.HasFlag(enum_EXCEPTION_STATE.EXCEPTION_STOP_FIRST_CHANCE), info.dwState.HasFlag(enum_EXCEPTION_STATE.EXCEPTION_STOP_USER_UNCAUGHT)); exceptionBehaviorMap[info.bstrExceptionName] = behavior; copyToProgram = true; } } } if (copyToProgram) { CopyExceptionMapToProgram(); } return(VSConstants.S_OK); }
/// <summary> // Sets the value of one or more local variables. Each variable must be visible at the current frame code index. // For primitive values, the value's type must match the variable's type exactly. For object values, there must // be a widening reference conversion from the value's type to the variable's type and the variable's type must // be loaded. // Even if local variable information is not available, values can be set, if the front-end is able to determine // the correct local variable index. (Typically, this index can be determined for method arguments from the // method signature without access to the local variable table information.) /// </summary> public Task SetValuesAsync(ThreadId threadId, FrameId frameId, params SlotValue[] slotValues) { var conn = ConnectionOrError; DLog.Debug(DContext.DebuggerLibCommands, () => string.Format("StackFrame.SetValues {0}", string.Join(", ", slotValues.Select(x => x.ToString())))); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 2, 4000 /* we don't know how long the packet is going to be... */, x => { var data = x.Data; threadId.WriteTo(data); frameId.WriteTo(data); data.SetInt(slotValues.Length); foreach (var value in slotValues) { value.Write(data); } x.Length = data.Offset; })); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); })); }
/// <summary> /// Informs a debug engine (DE) that the program specified has been atypically terminated and that the DE should clean up all references /// to the program and send a program destroy event. /// </summary> public int DestroyProgram(IDebugProgram2 pProgram) { DLog.Debug(DContext.VSDebuggerComCall, "IDebugEngine2.DestroyProgram"); // Avoid recursion if (destroying) { return(VSConstants.S_OK); } destroying = true; var program = pProgram as DebugProgram; if (program == null) { return(VSConstants.E_INVALIDARG); } var port = (IDebugPortNotify2)program.Process.Port; port.RemoveProgramNode(program); if (this.program == program) { // Detach this.program = null; } //eventCallback.Send(program, new ProgramDestroyEvent(0)); return(VSConstants.S_OK); }
public int GetPhysicalStackRange(out ulong paddrMin, out ulong paddrMax) { DLog.Debug(DContext.VSDebuggerComCall, "DebugStackFrame.GetPhysicalStackRange"); paddrMin = 0; paddrMax = 0; return(VSConstants.E_NOTIMPL); }
/// <summary> /// Step out of the current method /// </summary> public void StepOut(DebugThread thread) { DLog.Debug(DContext.VSDebuggerComCall, "Dot42Debugger.StepOut"); var stepDepth = Jdwp.StepDepth.Out; StepAsync(new StepRequest(thread, stepDepth)); }
/// <summary> /// Handle Thread Status messages /// </summary> internal static void HandleTHST(Chunk chunk, Action <DalvikEvent> onEvent) { var data = chunk.Data; var hdrLength = data.GetByte(); var entryLen = data.GetByte(); var count = data.GetInt16(); data.Skip(hdrLength - 4); var list = new List <ThreadStatusInfo>(); for (var i = 0; i < count; i++) { var id = new ThreadId(data, 4); var state = data.GetByte(); var tid = data.GetInt(); var utime = data.GetInt(); var stime = data.GetInt(); var isDaemon = data.GetByte(); data.Skip(entryLen - 18); DLog.Debug(DContext.DebuggerLibEvent, "THST id={0}, state={1}, tid={2}, utime={3}, stime={4}", id, state, tid, utime, stime); list.Add(new ThreadStatusInfo(id, (ThreadStates)state)); } onEvent(new ThreadStatus(list)); }
public int EnumBreakpoints(out IEnumDebugBoundBreakpoints2 ppEnum) { DLog.Debug(DContext.VSDebuggerEvent, "BreakpointEvent.EnumBreakpoints"); ppEnum = new BoundBreakpointsEnum(new[] { breakpoint }); return(VSConstants.S_OK); }
public int EnumProperties(enum_DEBUGPROP_INFO_FLAGS dwFields, uint nRadix, ref Guid guidFilter, uint dwTimeout, out uint pcelt, out IEnumDebugPropertyInfo2 ppEnum) { DLog.Debug(DContext.VSDebuggerComCall, "DebugStackFrame.EnumProperties"); var list = new List <DebugProperty>(); if (guidFilter == AD7Guids.guidFilterLocalsPlusArgs || guidFilter == AD7Guids.guidFilterAllLocalsPlusArgs || guidFilter == AD7Guids.guidFilterAllLocals) { AddLocalProperties(list); AddParameterProperties(list); } else if (guidFilter == AD7Guids.guidFilterLocals) { AddLocalProperties(list); } else if (guidFilter == AD7Guids.guidFilterArgs) { AddParameterProperties(list); } else { pcelt = 0; ppEnum = null; return(VSConstants.E_NOTIMPL); } pcelt = (uint)list.Count; ppEnum = new PropertyEnum(list.Select(x => x.ConstructDebugPropertyInfo(enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_STANDARD))); return(VSConstants.S_OK); }
public int EnumCodePaths(string pszHint, IDebugCodeContext2 pStart, IDebugStackFrame2 pFrame, int fSource, out IEnumCodePaths2 ppEnum, out IDebugCodeContext2 ppSafety) { DLog.Debug(DContext.VSDebuggerComCall, "IDebugProgram2.EnumCodePaths"); ppEnum = null; ppSafety = null; return(VSConstants.E_NOTIMPL); }
/// <summary> /// Send handshake packet. /// </summary> private void SendHandshake() { DLog.Debug(DContext.DebuggerLibJdwpConnection, "SendHandshake for pid {0}", pid); // Send handshape Write(Handshake); }
/// <summary> /// Performs a step. /// </summary> public int Step(IDebugThread2 pThread, enum_STEPKIND stepKind, enum_STEPUNIT stepUnit) { // This method is deprecated. Use the IDebugProcess3::Step method instead. DLog.Debug(DContext.VSDebuggerComCall, "IDebugProgram2.Step kind={0}, step={1}", stepKind, stepUnit); Jdwp.StepDepth stepDepth; switch (stepKind) { case enum_STEPKIND.STEP_INTO: stepDepth = Jdwp.StepDepth.Into; break; case enum_STEPKIND.STEP_BACKWARDS: return(VSConstants.E_NOTIMPL); case enum_STEPKIND.STEP_OVER: stepDepth = Jdwp.StepDepth.Over; break; case enum_STEPKIND.STEP_OUT: stepDepth = Jdwp.StepDepth.Out; break; default: return(VSConstants.E_INVALIDARG); } var stepMode = stepUnit == enum_STEPUNIT.STEP_INSTRUCTION ? StepMode.SingleInstruction : StepMode.Line; StepAsync(new StepRequest((DalvikThread)pThread, stepDepth, stepMode)); return(VSConstants.S_OK); }
/// <summary> /// Gets the name and identifier of the debug engine (DE) running a program. /// </summary> public int GetEngineInfo(out string pbstrEngine, out Guid pguidEngine) { DLog.Debug(DContext.VSDebuggerComCall, "IDebugProgram2.GetEngineInfo"); pbstrEngine = DebugEngine.Name; pguidEngine = new Guid(GuidList.Strings.guidDot42DebuggerId); return(VSConstants.S_OK); }
/// <summary> /// Notify visual studio of a trigger in this breakpoint. /// </summary> internal void OnTrigger(DebuggerLib.Events.Jdwp.Breakpoint @event) { DLog.Debug(DContext.VSDebuggerComCall, "DebugBoundBreakpoint.OnTrigger"); // Prepare var program = breakpointManager.Program; // Increment hitcount hitCount++; // Find thread DalvikThread thread; if (!program.ThreadManager.TryGet(@event.ThreadId, out thread)) { thread = program.ThreadManager.MainThread(); } // Set resolution info resolution.Thread = (DebugThread)thread; // Send event DLog.Debug(DContext.VSDebuggerComCall, "DebugBoundBreakpoint.OnTrigger.Send"); breakpointManager.Send((DebugThread)thread, new BreakpointEvent(this)); }
/// <summary> /// Continues running this program from a stopped state. Any previous execution state (such as a step) is preserved, and the program starts executing again. /// </summary> public int Continue(IDebugThread2 pThread) { // This method is deprecated. Use the IDebugProcess3::Continue method instead. DLog.Debug(DContext.VSDebuggerComCall, "IDebugProgram2.Continue"); Debugger.VirtualMachine.ResumeAsync(); return(VSConstants.S_OK); }
/// <summary> /// Handle non-reply chunks /// </summary> private void ChunkHandler(Chunk chunk) { DLog.Debug(DContext.DebuggerLibDebugger, "Handle Chunk {0}", chunk); var type = chunk.Type; if (type == DdmsCommandSet.HeloType) { var data = chunk.Data; var clientProtocolVersion = data.GetInt(); var pid = data.GetInt(); var vmIdentLen = data.GetInt(); var appNameLen = data.GetInt(); var vmIdent = data.GetString(vmIdentLen); var appName = data.GetString(appNameLen); SetAppName(appName); } else if (type == DdmsCommandSet.ApnmType) { var data = chunk.Data; var appNameLen = data.GetInt(); var appName = data.GetString(appNameLen); SetAppName(appName); } else if (type == DdmsCommandSet.WaitType) { var data = chunk.Data; var reason = data.GetByte(); OnEventAsync(new WaitForDebugger(reason)); } else if (type == DdmsCommandSet.ThstType) { ThreadStatus.HandleTHST(chunk, OnEventAsync); } }
/// <summary> /// Executes the program. The thread is returned to give the debugger information on which thread the user is viewing when executing. /// </summary> public int ExecuteOnThread(IDebugThread2 pThread) { DLog.Debug(DContext.VSDebuggerComCall, "IDebugProgram2.ExecuteOnThread"); // Resume VM ResumeAsync(); return(VSConstants.S_OK); }
/// <summary> /// Returns the value of one or more local variables in a given frame. Each variable must be visible at the frame's code index. /// Even if local variable information is not available, values can be retrieved if the front-end is able to determine the correct /// local variable index. (Typically, this index can be determined for method arguments from the method signature without access to /// the local variable table information.) /// </summary> public Task <List <Value> > GetValuesAsync(ThreadId threadId, FrameId frameId, SlotRequest[] slots) { var conn = ConnectionOrError; DLog.Debug(DContext.DebuggerLibCommands, () => string.Format("StackFrame.GetValues {0}", string.Join(", ", slots.Select(x => x.ToString())))); var t = conn.SendAsync(JdwpPacket.CreateCommand(conn, Nr, 1, threadId.Size + frameId.Size + 4 + (slots.Length * 5), x => { var data = x.Data; threadId.WriteTo(data); frameId.WriteTo(data); data.SetInt(slots.Length); foreach (var slot in slots) { data.SetInt(slot.Slot); data.SetByte((byte)slot.Tag); } })); return(t.ContinueWith(x => { x.ForwardException(); var result = x.Result; result.ThrowOnError(); var data = result.Data; var count = data.GetInt(); var list = new List <Value>(count); for (var i = 0; i < count; i++) { var value = new Value(data); list.Add(value); } return list; })); }
/// <summary> /// Gets the name of the session that is debugging this process. An IDE can display this information to a user who is debugging a particular process on a particular machine. /// </summary> public int GetAttachedSessionName(out string pbstrSessionName) { // This method is deprecated, and its implementation should always return E_NOTIMPL. DLog.Debug(DContext.VSDebuggerComCall, "IDebugProcess2.GetAttachedSessionName"); pbstrSessionName = null; return(VSConstants.E_NOTIMPL); }
/// <summary> /// Gets the title, friendly name, or file name of the process. /// </summary> public int GetName(enum_GETNAME_TYPE gnType, out string pbstrName) { DLog.Debug(DContext.VSDebuggerComCall, "IDebugProcess2.GetName"); switch (gnType) { case enum_GETNAME_TYPE.GN_FILENAME: case enum_GETNAME_TYPE.GN_MONIKERNAME: pbstrName = apkPath; break; case enum_GETNAME_TYPE.GN_NAME: case enum_GETNAME_TYPE.GN_BASENAME: case enum_GETNAME_TYPE.GN_TITLE: pbstrName = Path.GetFileName(apkPath); break; case enum_GETNAME_TYPE.GN_URL: pbstrName = "<url>"; break; case enum_GETNAME_TYPE.GN_STARTPAGEURL: pbstrName = "<startpageurl>"; break; default: pbstrName = null; return(VSConstants.S_FALSE); } return(VSConstants.S_OK); }
/// <summary> /// Process the given exception event. /// </summary> protected internal virtual void OnExceptionEvent(Events.Jdwp.Exception @event, DalvikThread thread) { // Log DLog.Debug(DContext.VSDebuggerEvent, "OnExceptionEvent location: {0}", @event.Location); // Save exception in thread thread.CurrentException = @event.ExceptionObject; }
public int SetPassCount(BP_PASSCOUNT bpPassCount) { DLog.Debug(DContext.VSDebuggerComCall, "DebugBoundBreakpoint.SetPassCount"); if (IsDeleted) { return(HResults.E_BP_DELETED); } return(pendingBreakpoint.SetPassCount(bpPassCount)); }
/// <summary> /// Sets or changes the condition associated with this pending breakpoint. /// </summary> public int SetCondition(BP_CONDITION bpCondition) { DLog.Debug(DContext.VSDebuggerComCall, "DebugPendingBreakpoint.SetCondition"); if (IsDeleted) { return(HResults.E_BP_DELETED); } throw new NotImplementedException(); }
/// <summary> /// Toggles the virtualized state of this pending breakpoint. /// </summary> public int Virtualize(int fVirtualize) { DLog.Debug(DContext.VSDebuggerComCall, "DebugPendingBreakpoint.Virtualize"); if (IsDeleted) { return(HResults.E_BP_DELETED); } return(VSConstants.S_OK); }
/// <summary> /// Gets the name of the stack frame, typically the method name. /// </summary> public int GetName(out string pbstrName) { DLog.Debug(DContext.VSDebuggerComCall, "DebugStackFrame.GetName"); FRAMEINFO info; SetFrameInfo(enum_FRAMEINFO_FLAGS.FIF_FUNCNAME, out info); pbstrName = info.m_bstrFuncName; return(VSConstants.S_OK); }
public int SetCondition(BP_CONDITION bpCondition) { DLog.Debug(DContext.VSDebuggerComCall, "DebugBoundBreakpoint.SetCondition"); if (IsDeleted) { return(HResults.E_BP_DELETED); } return(pendingBreakpoint.SetCondition(bpCondition)); }
/// <summary> /// Gets the system process identifier. /// </summary> public int GetPhysicalProcessId(AD_PROCESS_ID[] pProcessId) { DLog.Debug(DContext.VSDebuggerComCall, "IDebugProcess2.GetPhysicalProcessId"); pProcessId[0].ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID; //pProcessId[0].dwProcessId = (uint) processId; pProcessId[0].dwProcessId = 0; pProcessId[0].guidProcessId = guid; return(VSConstants.S_OK); }
/// <summary> /// Gets a port by it's guid. /// </summary> public int GetPort(ref Guid guidPort, out IDebugPort2 ppPort) { DLog.Debug(DContext.VSDebuggerComCall, "DebugPortSupplier.GetPort"); var guid = guidPort; var port = ports.Values.FirstOrDefault(x => x.Guid == guid); ppPort = port; return((port != null) ? VSConstants.S_OK : VSConstants.S_FALSE); }