//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int GetProgramName(out string pbstrProgramName) { // // Gets the name of the program. // LoggingUtils.PrintFunction(); try { LoggingUtils.RequireOk(DebugProcess.GetName(enum_GETNAME_TYPE.GN_NAME, out pbstrProgramName)); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); pbstrProgramName = string.Empty; return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #endregion //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region IDebugProgram3 Members //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int ExecuteOnThread(IDebugThread2 pThread) { // // ExecuteOnThread is called when the Session Debug Manager (SDM) wants execution to continue and have stepping state cleared. // LoggingUtils.PrintFunction(); try { LoggingUtils.RequireOk(AttachedEngine.NativeDebugger.NativeProgram.ExecuteOnThread(pThread)); //LoggingUtils.RequireOk (AttachedEngine.JavaDebugger.JavaProgram.ExecuteOnThread (pThread)); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int WriteDump(enum_DUMPTYPE DUMPTYPE, string pszDumpUrl) { // // Writes a dump to a file. // LoggingUtils.PrintFunction(); try { LoggingUtils.RequireOk(AttachedEngine.NativeDebugger.NativeProgram.WriteDump(DUMPTYPE, pszDumpUrl)); LoggingUtils.RequireOk(AttachedEngine.JavaDebugger.JavaProgram.WriteDump(DUMPTYPE, pszDumpUrl)); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int Step(IDebugThread2 pThread, enum_STEPKIND sk, enum_STEPUNIT Step) { // // Performs a step. // LoggingUtils.PrintFunction(); try { LoggingUtils.RequireOk(AttachedEngine.NativeDebugger.NativeProgram.Step(pThread, sk, Step)); //LoggingUtils.RequireOk (AttachedEngine.JavaDebugger.JavaProgram.Step (pThread, sk, Step)); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int Execute() { // // Continues running this program from a stopped state. Any previous execution state is cleared. // LoggingUtils.PrintFunction(); try { LoggingUtils.RequireOk(AttachedEngine.NativeDebugger.NativeProgram.Execute()); LoggingUtils.RequireOk(AttachedEngine.JavaDebugger.JavaProgram.Execute()); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int GetCurrentLocation(out ulong puCodeLocationId) { // // Returns a code location identifier that represents the current code location. // LoggingUtils.PrintFunction(); try { LoggingUtils.RequireOk(GetCodeLocationId(m_codeContext, out puCodeLocationId)); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); puCodeLocationId = 0ul; return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int EnumCodeContexts(IDebugDocumentPosition2 pDocPos, out IEnumDebugCodeContexts2 ppEnum) { // // Enumerates the code contexts for a given position in a source file. // LoggingUtils.PrintFunction(); try { TEXT_POSITION [] startPos = new TEXT_POSITION [1]; TEXT_POSITION [] endPos = new TEXT_POSITION [1]; LoggingUtils.RequireOk(pDocPos.GetFileName(out string fileName)); LoggingUtils.RequireOk(pDocPos.GetRange(startPos, endPos)); DebuggeeDocumentContext documentContext = new DebuggeeDocumentContext(m_debugger.Engine, fileName, startPos [0], endPos [0]); CLangDebuggeeCodeContext codeContext = CLangDebuggeeCodeContext.GetCodeContextForDocumentContext(m_debugger, documentContext) ?? throw new InvalidOperationException("Failed evaluating code-context for location."); CLangDebuggeeCodeContext [] codeContexts = new CLangDebuggeeCodeContext [] { codeContext }; ppEnum = new DebuggeeCodeContext.Enumerator(codeContexts); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); ppEnum = null; return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #endregion //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region IDebugProgram3 Members //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int ExecuteOnThread(IDebugThread2 pThread) { // // Executes the debugger program. The thread is returned to give the debugger information on which thread the user is viewing when executing the program. // LoggingUtils.PrintFunction(); try { #if false uint threadId; CLangDebuggeeThread thread = pThread as CLangDebuggeeThread; LoggingUtils.RequireOk(thread.GetThreadId(out threadId)); string command = "-thread-select " + threadId; MiResultRecord resultRecord = m_debugger.GdbClient.SendCommand(command); MiResultRecord.RequireOk(resultRecord, command); CurrentThreadId = threadId; #endif LoggingUtils.RequireOk(Execute()); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int Detach() { // // Detaches the debugger from this program. // LoggingUtils.PrintFunction(); Exception rethrowable = null; try { if (AttachedEngine == null) { throw new InvalidOperationException(); } LoggingUtils.RequireOk(AttachedEngine.Detach(this)); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); rethrowable = e; return(Constants.E_FAIL); } finally { if (rethrowable != null) { throw rethrowable; } } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int EnumFrameInfo(enum_FRAMEINFO_FLAGS requestedFields, uint radix, out IEnumDebugFrameInfo2 enumDebugFrame) { // // Retrieves a list of the stack frames for this thread. // For the sample engine, enumerating the stack frames requires walking the callstack in the debuggee for this thread // and converting that to an implementation of IEnumDebugFrameInfo2. // Real engines will most likely want to cache this information to avoid recomputing it each time it is asked for, // and or construct it on demand instead of walking the entire stack. // LoggingUtils.PrintFunction(); try { StackTrace(uint.MaxValue); FRAMEINFO [] frameInfo = new FRAMEINFO [m_threadStackFrames.Count]; for (int i = 0; i < m_threadStackFrames.Count; ++i) { LoggingUtils.RequireOk(m_threadStackFrames [i].SetFrameInfo(requestedFields, radix, ref frameInfo [i])); } enumDebugFrame = new DebuggeeStackFrame.Enumerator(frameInfo); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); enumDebugFrame = null; return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int SetCondition(BP_CONDITION bpCondition) { // // Sets or changes the condition associated with this pending breakpoint. // LoggingUtils.PrintFunction(); try { foreach (DebuggeeBreakpointBound boundBreakpoint in m_boundBreakpoints.ToArray()) { LoggingUtils.RequireOk(boundBreakpoint.SetCondition(bpCondition)); } return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebuggerEventListener(EnvDTE.DTE dteService, IVsDebugger debuggerService, IDebuggerConnectionService debuggerConnectionService) { m_dteService = dteService; m_debuggerService = debuggerService; m_debuggerConnectionService = debuggerConnectionService; LoggingUtils.RequireOk(m_debuggerService.AdviseDebuggerEvents(this, out m_debuggerServiceCookie)); LoggingUtils.RequireOk(m_debuggerService.AdviseDebugEventCallback(this)); // // Register required listener events and paired process function callbacks. // m_eventCallbacks = new Dictionary <Guid, DebuggerEventListenerDelegate> (); m_eventCallbacks.Add(ComUtils.GuidOf(typeof(DebugEngineEvent.SessionCreate)), OnSessionCreate); m_eventCallbacks.Add(ComUtils.GuidOf(typeof(DebugEngineEvent.SessionDestroy)), OnSessionDestroy); m_eventCallbacks.Add(ComUtils.GuidOf(typeof(DebugEngineEvent.EngineCreate)), OnEngineCreate); m_eventCallbacks.Add(ComUtils.GuidOf(typeof(DebugEngineEvent.ProgramCreate)), OnProgramCreate); m_eventCallbacks.Add(ComUtils.GuidOf(typeof(DebugEngineEvent.ProgramDestroy)), OnProgramDestroy); m_eventCallbacks.Add(ComUtils.GuidOf(typeof(DebugEngineEvent.AttachComplete)), OnAttachComplete); m_eventCallbacks.Add(ComUtils.GuidOf(typeof(DebugEngineEvent.Error)), OnError); m_eventCallbacks.Add(ComUtils.GuidOf(typeof(DebugEngineEvent.DebuggerConnectionEvent)), OnDebuggerConnectionEvent); m_eventCallbacks.Add(ComUtils.GuidOf(typeof(DebugEngineEvent.DebuggerLogcatEvent)), OnDebuggerLogcatEvent); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region IDebugPendingBreakpoint2 Members //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public virtual int Bind() { // // Binds this pending breakpoint to one or more code locations. // LoggingUtils.PrintFunction(); DebuggeeDocumentContext documentContext = null; DebuggeeCodeContext codeContext = null; string bindLocation = string.Empty; try { ClearErrorBreakpoints(); if (m_breakpointDeleted) { return(Constants.E_BP_DELETED); } LoggingUtils.RequireOk(EvaluateBreakpointLocation(out documentContext, out codeContext, out bindLocation)); LoggingUtils.RequireOk(CreateBoundBreakpoint(bindLocation, documentContext, codeContext)); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int WriteAt(IDebugMemoryContext2 pStartContext, uint dwCount, byte [] rgbMemory) { // // Writes the specified number of bytes of memory, starting at the specified address. // LoggingUtils.PrintFunction(); try { CONTEXT_INFO [] contextInfoArray = new CONTEXT_INFO [1]; LoggingUtils.RequireOk(pStartContext.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE, contextInfoArray)); StringBuilder stringBuilder = new StringBuilder((int)dwCount * 2); for (uint i = 0; i < dwCount; ++i) { stringBuilder.Append(rgbMemory [i].ToString("x")); } string command = string.Format("-data-write-memory-bytes {0} {1} {2}", contextInfoArray [0].bstrAddressAbsolute, stringBuilder.ToString(), dwCount); MiResultRecord resultRecord = m_debugger.GdbClient.SendSyncCommand(command); MiResultRecord.RequireOk(resultRecord, command); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// protected override int QueryRegisters() { LoggingUtils.PrintFunction(); try { // // Returns a list of registers for the current stack level. // if (!m_queriedRegisters) { uint threadId; LoggingUtils.RequireOk(m_thread.GetThreadId(out threadId)); string command = string.Format("-data-list-register-values --thread {0} --frame {1} r", threadId, StackLevel); m_debugger.GdbClient.SendCommand(command, delegate(MiResultRecord resultRecord) { MiResultRecord.RequireOk(resultRecord, command); if (!resultRecord.HasField("register-values")) { throw new InvalidOperationException("Failed to retrieve list of register values"); } MiResultValue registerValues = resultRecord ["register-values"] [0]; int registerValuesCount = registerValues.Values.Count; Dictionary <uint, string> registerIdMapping = m_debugger.GdbClient.GetRegisterIdMapping(); for (int i = 0; i < registerValuesCount; ++i) { uint registerId = registerValues [i] ["number"] [0].GetUnsignedInt(); string registerValue = registerValues [i] ["value"] [0].GetString(); string registerName = registerIdMapping [registerId]; string registerNamePrettified = "$" + registerName; CLangDebuggeeProperty property = new CLangDebuggeeProperty(m_debugger, this, registerNamePrettified, registerValue); m_stackRegisters.TryAdd(registerNamePrettified, property); LoggingUtils.RequireOk(m_property.AddChildren(new DebuggeeProperty [] { property })); } m_queriedRegisters = true; }); } return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// protected override int QueryArgumentsAndLocals() { LoggingUtils.PrintFunction(); try { if (!m_queriedArgumentsAndLocals) { uint threadId; LoggingUtils.RequireOk(m_thread.GetThreadId(out threadId)); string command = string.Format("-stack-list-variables --thread {0} --frame {1} --no-values", threadId, StackLevel); m_debugger.GdbClient.SendCommand(command, delegate(MiResultRecord resultRecord) { MiResultRecord.RequireOk(resultRecord, command); if (resultRecord.HasField("variables")) { MiResultValue localVariables = resultRecord ["variables"] [0]; for (int i = 0; i < localVariables.Values.Count; ++i) { string variableName = localVariables [i] ["name"] [0].GetString(); MiVariable variable = m_debugger.VariableManager.CreateVariableFromExpression(this, variableName); if (variable == null) { continue; } CLangDebuggeeProperty property = m_debugger.VariableManager.CreatePropertyFromVariable(this, variable); if (property == null) { throw new InvalidOperationException(); } if (localVariables [i].HasField("arg")) { m_stackArguments.TryAdd(variableName, property); LoggingUtils.RequireOk(m_property.AddChildren(new DebuggeeProperty [] { property })); } else { m_stackLocals.TryAdd(variableName, property); LoggingUtils.RequireOk(m_property.AddChildren(new DebuggeeProperty [] { property })); } //LoggingUtils.RequireOk (m_property.AddChildren (new DebuggeeProperty [] { property })); } m_queriedArgumentsAndLocals = true; } }); } return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public virtual int EvaluateBreakpointLocation(out DebuggeeDocumentContext documentContext, out DebuggeeCodeContext codeContext, out string location) { LoggingUtils.PrintFunction(); documentContext = null; codeContext = null; location = string.Empty; try { switch (m_breakpointRequestInfo.bpLocation.bpLocationType) { case (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE: { // // Specifies the location type of the breakpoint as a line of source code. // string fileName; IDebugDocumentPosition2 documentPostion = (IDebugDocumentPosition2)Marshal.GetObjectForIUnknown(m_breakpointRequestInfo.bpLocation.unionmember2); LoggingUtils.RequireOk(documentPostion.GetFileName(out fileName)); bool fileInCurrentProject = true; // TODO if (File.Exists(fileName) && fileInCurrentProject) { TEXT_POSITION [] startPos = new TEXT_POSITION [1]; TEXT_POSITION [] endPos = new TEXT_POSITION [1]; LoggingUtils.RequireOk(documentPostion.GetRange(startPos, endPos)); documentContext = new DebuggeeDocumentContext(m_breakpointManager.Engine, fileName, startPos [0], endPos [0]); location = string.Format("\"{0}:{1}\"", fileName, startPos [0].dwLine + 1); } else { throw new NotImplementedException(); } break; } case (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET: { // // Specifies the location type of the breakpoint as a code function offset. // string function = string.Empty; IDebugFunctionPosition2 functionPosition = (IDebugFunctionPosition2)Marshal.GetObjectForIUnknown(m_breakpointRequestInfo.bpLocation.unionmember2); TEXT_POSITION [] textPos = new TEXT_POSITION [1]; LoggingUtils.RequireOk(functionPosition.GetFunctionName(out function)); LoggingUtils.RequireOk(functionPosition.GetOffset(textPos)); if (!string.IsNullOrEmpty(function)) { location = function; } break; } case (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_CONTEXT: { // // Specifies the location type of the breakpoint as a code context. // codeContext = ((IDebugCodeContext2)Marshal.GetObjectForIUnknown(m_breakpointRequestInfo.bpLocation.unionmember1)) as DebuggeeCodeContext; if (codeContext != null) { location = codeContext.Address.ToString(); } break; } case (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_STRING: { // // Specifies the location type of the breakpoint as a code string. // throw new NotImplementedException(); } case (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_ADDRESS: { // // Specifies the location type of the breakpoint as a code address. // string address = Marshal.PtrToStringBSTR(m_breakpointRequestInfo.bpLocation.unionmember4); if (!string.IsNullOrEmpty(address)) { location = address; } break; } case (uint)enum_BP_LOCATION_TYPE.BPLT_DATA_STRING: { // // Specifies the location type of the breakpoint as a data string. // string dataExpression = Marshal.PtrToStringBSTR(m_breakpointRequestInfo.bpLocation.unionmember3); if (!string.IsNullOrEmpty(dataExpression)) { location = dataExpression; } break; } default: { break; } } return(Constants.S_OK); } catch (NotImplementedException e) { LoggingUtils.HandleException(e); return(Constants.E_NOTIMPL); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int CreatePendingBreakpoint(IDebugBreakpointRequest2 breakpointRequest, out IDebugPendingBreakpoint2 pendingBreakpoint) { // // Construct and register new pending breakpoint. // LoggingUtils.PrintFunction(); try { DebuggeeBreakpointPending breakpoint = null; BP_REQUEST_INFO [] requestInfo = new BP_REQUEST_INFO [1]; LoggingUtils.RequireOk(breakpointRequest.GetRequestInfo(enum_BPREQI_FIELDS.BPREQI_BPLOCATION, requestInfo)); long locationType = requestInfo [0].bpLocation.bpLocationType & (long)enum_BP_LOCATION_TYPE.BPLT_LOCATION_TYPE_MASK; if ((locationType & (long)enum_BP_LOCATION_TYPE.BPLT_FILE_LINE) != 0) { // // Query the associated document extension, and create a respective pending breakpoint type. // IDebugDocumentPosition2 documentPostion = (IDebugDocumentPosition2)Marshal.GetObjectForIUnknown(requestInfo[0].bpLocation.unionmember2); LoggingUtils.RequireOk(documentPostion.GetFileName(out string fileName)); string fileExtension = Path.GetExtension(fileName).ToLower(); switch (fileExtension) { case ".c": case ".cpp": case ".h": case ".hpp": case ".asm": case ".inl": { breakpoint = new CLangDebuggeeBreakpointPending(Engine.NativeDebugger, this, breakpointRequest); break; } case ".java": { throw new NotImplementedException(); } default: { breakpoint = new DebuggeeBreakpointPending(this, breakpointRequest); break; } } } else if ((locationType & (long)enum_BP_LOCATION_TYPE.BPLT_FUNC_OFFSET) != 0) { throw new NotImplementedException(); } else if ((locationType & (long)enum_BP_LOCATION_TYPE.BPLT_CONTEXT) != 0) { throw new NotImplementedException(); } else if ((locationType & (long)enum_BP_LOCATION_TYPE.BPLT_STRING) != 0) { throw new NotImplementedException(); } else if ((locationType & (long)enum_BP_LOCATION_TYPE.BPLT_ADDRESS) != 0) { throw new NotImplementedException(); } else if ((locationType & (long)enum_BP_LOCATION_TYPE.BPLT_RESOLUTION) != 0) { throw new NotImplementedException(); } else { throw new NotImplementedException(); } lock (m_pendingBreakpoints) { m_pendingBreakpoints.Add(breakpoint); } pendingBreakpoint = (IDebugPendingBreakpoint2)breakpoint; SetDirty(true); return(Constants.S_OK); } catch (NotImplementedException e) { LoggingUtils.HandleException(e); pendingBreakpoint = null; return(Constants.E_NOTIMPL); } catch (Exception e) { LoggingUtils.HandleException(e); pendingBreakpoint = null; return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int GetThreadProperties100(uint requestedFields, THREADPROPERTIES100 [] propertiesArray) { // // Gets properties that describe a thread. // LoggingUtils.PrintFunction(); try { // // 9.0 (2008) thread properties. // THREADPROPERTIES [] threadProperties9 = new THREADPROPERTIES [1]; enum_THREADPROPERTY_FIELDS requestedFields90 = (enum_THREADPROPERTY_FIELDS)0x3f;// (requestedFields & 0x3f); LoggingUtils.RequireOk(GetThreadProperties(requestedFields90, threadProperties9)); propertiesArray [0].bstrLocation = threadProperties9 [0].bstrLocation; propertiesArray [0].bstrName = threadProperties9 [0].bstrName; propertiesArray [0].bstrPriority = threadProperties9 [0].bstrPriority; propertiesArray [0].dwSuspendCount = threadProperties9 [0].dwSuspendCount; propertiesArray [0].dwThreadId = threadProperties9 [0].dwThreadId; propertiesArray [0].dwThreadState = threadProperties9 [0].dwThreadState; propertiesArray [0].dwFields |= (uint)threadProperties9 [0].dwFields; // // 10.0 (2010) thread properties. // if ((requestedFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_DISPLAY_NAME) != 0) { propertiesArray [0].bstrDisplayName = m_threadDisplayName; propertiesArray [0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_DISPLAY_NAME; propertiesArray [0].DisplayNamePriority = (uint)enum_DISPLAY_NAME_PRIORITY100.DISPLAY_NAM_PRI_DEFAULT_100; propertiesArray [0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_DISPLAY_NAME_PRIORITY; } if ((requestedFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_CATEGORY) != 0) { if (m_threadId == 1) { propertiesArray [0].dwThreadCategory = (uint)enum_THREADCATEGORY.THREADCATEGORY_Main; } else { propertiesArray [0].dwThreadCategory = (uint)enum_THREADCATEGORY.THREADCATEGORY_Worker; } propertiesArray [0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_CATEGORY; } if ((requestedFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_AFFINITY) != 0) { propertiesArray [0].AffinityMask = 0; propertiesArray [0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_AFFINITY; } if ((requestedFields & (uint)enum_THREADPROPERTY_FIELDS100.TPF100_PRIORITY_ID) != 0) { propertiesArray [0].priorityId = 0; propertiesArray [0].dwFields |= (uint)enum_THREADPROPERTY_FIELDS100.TPF100_PRIORITY_ID; } return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override int SetCondition(BP_CONDITION bpCondition) { // // Sets or changes the condition associated with this bound breakpoint. // LoggingUtils.PrintFunction(); try { int handle = base.SetCondition(bpCondition); if (handle == Constants.E_BP_DELETED) { return(handle); } LoggingUtils.RequireOk(handle); string condition = string.Empty; switch (bpCondition.styleCondition) { case enum_BP_COND_STYLE.BP_COND_WHEN_TRUE: { condition = bpCondition.bstrCondition; break; } case enum_BP_COND_STYLE.BP_COND_WHEN_CHANGED: { throw new NotImplementedException(); } } if (!string.IsNullOrEmpty(condition)) { m_debugger.RunInterruptOperation(delegate(CLangDebugger debugger) { string command = string.Format("-break-condition {0} \"{1}\"", GdbBreakpoint.ID, condition); debugger.GdbClient.SendCommand(command, delegate(MiResultRecord resultRecord) { MiResultRecord.RequireOk(resultRecord, command); }); }); } return(Constants.S_OK); } catch (NotImplementedException e) { LoggingUtils.HandleException(e); return(Constants.E_NOTIMPL); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int GetThreadProperties(enum_THREADPROPERTY_FIELDS requestedFields, THREADPROPERTIES [] propertiesArray) { // // Gets properties that describe a thread. // LoggingUtils.PrintFunction(); try { if ((requestedFields & enum_THREADPROPERTY_FIELDS.TPF_ID) != 0) { propertiesArray [0].dwThreadId = m_threadId; propertiesArray [0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_ID; } if ((requestedFields & enum_THREADPROPERTY_FIELDS.TPF_SUSPENDCOUNT) != 0) { propertiesArray [0].dwSuspendCount = m_threadSuspendCount; propertiesArray [0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_SUSPENDCOUNT; } if ((requestedFields & enum_THREADPROPERTY_FIELDS.TPF_STATE) != 0) { if (m_threadRunning) { propertiesArray [0].dwThreadState = (uint)enum_THREADSTATE.THREADSTATE_RUNNING; } else { propertiesArray [0].dwThreadState = (uint)enum_THREADSTATE.THREADSTATE_STOPPED; } propertiesArray [0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_STATE; } if ((requestedFields & enum_THREADPROPERTY_FIELDS.TPF_PRIORITY) != 0) { propertiesArray [0].bstrPriority = "<unknown priority>"; propertiesArray [0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_PRIORITY; } if ((requestedFields & enum_THREADPROPERTY_FIELDS.TPF_NAME) != 0) { propertiesArray [0].bstrName = m_threadName; propertiesArray [0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_NAME; } if ((requestedFields & enum_THREADPROPERTY_FIELDS.TPF_LOCATION) != 0) { // // The thread location (usually the topmost stack frame), typically expressed as the name of the method where execution is currently halted. // propertiesArray [0].bstrLocation = "[External Code]"; StackTrace(1); // single level depth if (m_threadStackFrames.Count > 0) { DebuggeeStackFrame stackFrame = m_threadStackFrames [0]; FRAMEINFO frameInfo = new FRAMEINFO(); LoggingUtils.RequireOk(stackFrame.SetFrameInfo(enum_FRAMEINFO_FLAGS.FIF_FUNCNAME, 0, ref frameInfo)); if (!string.IsNullOrEmpty(frameInfo.m_bstrFuncName)) { propertiesArray [0].bstrLocation = frameInfo.m_bstrFuncName; } } propertiesArray [0].dwFields |= enum_THREADPROPERTY_FIELDS.TPF_LOCATION; } return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int EnumCodePaths (string pszHint, IDebugCodeContext2 pStart, IDebugStackFrame2 pFrame, int fSource, out IEnumCodePaths2 ppEnum, out IDebugCodeContext2 ppSafety) { // // Enumerates the code paths of this program. // LoggingUtils.PrintFunction (); try { // // Get the entire call-stack for the current thread, and enumerate. // CLangDebuggeeStackFrame stackFrame = pFrame as CLangDebuggeeStackFrame; IDebugThread2 thread; LoggingUtils.RequireOk (stackFrame.GetThread (out thread)); CLangDebuggeeThread stackFrameThread = thread as CLangDebuggeeThread; List<DebuggeeStackFrame> threadCallStack = stackFrameThread.StackTrace (uint.MaxValue); List <CODE_PATH> threadCodePaths = new List <CODE_PATH> (); for (int i = 0; i < threadCallStack.Count; ++i) { string frameName; IDebugCodeContext2 codeContext; DebuggeeStackFrame frame = threadCallStack [i] as DebuggeeStackFrame; LoggingUtils.RequireOk (frame.GetName (out frameName)); LoggingUtils.RequireOk (frame.GetCodeContext (out codeContext)); if (codeContext != null) { CODE_PATH codePath = new CODE_PATH (); codePath.bstrName = frameName; codePath.pCode = codeContext; threadCodePaths.Add (codePath); } } ppEnum = new DebuggeeProgram.EnumeratorCodePaths (threadCodePaths); ppSafety = null; return Constants.S_OK; } catch (Exception e) { LoggingUtils.HandleException (e); ppEnum = null; ppSafety = null; return Constants.E_FAIL; } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public async Task <DebugLaunchSettings> StartWithDebugging(int launchOptions, LaunchConfiguration launchConfig, ICollection <LaunchProps> launchProps, IDictionary <string, string> projectProperties) { LoggingUtils.PrintFunction(); if (launchConfig == null) { throw new ArgumentNullException(nameof(launchConfig)); } if (launchProps == null) { throw new ArgumentNullException(nameof(launchProps)); } if (projectProperties == null) { throw new ArgumentNullException(nameof(projectProperties)); } // // Refresh ADB service and evaluate a list of connected devices or emulators. // AndroidAdb.Refresh(); AndroidDevice debuggingDevice = GetPrioritisedConnectedDevice() ?? throw new InvalidOperationException("No device/emulator found or connected. Check status using \"adb devices\"."); // // Enforce required device/emulator properties. // foreach (var prop in launchProps) { debuggingDevice.Shell("setprop", string.Format(CultureInfo.InvariantCulture, "{0} {1}", prop.Item1, prop.Item2)); } // // Construct VS launch settings to debug or attach to the specified target application. // bool shouldAttach = false; #if false AndroidProcess [] debuggingDeviceProcesses = debuggingDevice.GetProcesses(); foreach (AndroidProcess process in debuggingDeviceProcesses) { if (process.Name.Equals(applicationPackageName)) { shouldAttach = true; break; } } #endif launchOptions |= (int)DebugLaunchOptions.Silent; DebugLaunchSettings debugLaunchSettings = new DebugLaunchSettings((DebugLaunchOptions)launchOptions); debugLaunchSettings.LaunchDebugEngineGuid = new Guid("8310DAF9-1043-4C8E-85A0-FF68896E1922"); debugLaunchSettings.PortSupplierGuid = new Guid("3AEE417F-E5F9-4B89-BC31-20534C99B7F5"); debugLaunchSettings.PortName = debuggingDevice.ID; debugLaunchSettings.Options = launchConfig.ToString(); if (shouldAttach) { debugLaunchSettings.Executable = launchConfig ["PackageName"]; debugLaunchSettings.LaunchOperation = DebugLaunchOperation.AlreadyRunning; } else { // // Determine whether the application is currently installed, and if it is; // check last modified date to ensure we don't re-installed unchanged binaries. // bool upToDateCheck = launchConfig ["UpToDateCheck"].Equals("true"); bool appIsInstalled = false; bool appIsOutOfDate = true; if (upToDateCheck) { FileInfo targetApkFileInfo = new FileInfo(launchConfig ["TargetApk"]); try { var adbPmPathOutput = debuggingDevice.Shell("pm", "path " + launchConfig ["PackageName"]).Replace("\r", "").Split(new char [] { '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (string line in adbPmPathOutput) { if (line.StartsWith("package:", StringComparison.OrdinalIgnoreCase)) { appIsInstalled = true; LoggingUtils.RequireOk(await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "'{0}' already installed on target '{1}'.", launchConfig ["PackageName"], debuggingDevice.ID), false)); string path = line.Substring("package:".Length); // // Get the target device/emulator's UTC current time. // // This is done by specifying the '-u' argument to 'date'. Despite this though, // the returned string will always claim to be in GMT: // // i.e: "Fri Jan 9 14:35:23 GMT 2015" // DateTime debuggingDeviceUtcTime; try { var deviceDateOutput = debuggingDevice.Shell("date", "-u").Replace("\r", "").Split(new char [] { '\n' }, StringSplitOptions.RemoveEmptyEntries); string debuggingDeviceUtcTimestamp = deviceDateOutput [0]; var debuggingDeviceUtcTimestampComponents = debuggingDeviceUtcTimestamp.Split(new char [] { ' ' }, StringSplitOptions.RemoveEmptyEntries); debuggingDeviceUtcTimestampComponents [4] = "-00:00"; if (!DateTime.TryParseExact(string.Join(" ", debuggingDeviceUtcTimestampComponents), "ddd MMM d HH:mm:ss zzz yyyy", CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out debuggingDeviceUtcTime)) { break; } debuggingDeviceUtcTime = debuggingDeviceUtcTime.ToUniversalTime(); } catch (Exception e) { throw new InvalidOperationException("Failed to evaluate device local time.", e); } // // Convert current device/emulator time to UTC, and probe the working machine's time too. // DateTime thisMachineUtcTime = DateTime.UtcNow; TimeSpan thisMachineUtcVersusDeviceUtc = debuggingDeviceUtcTime - thisMachineUtcTime; await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "Current UTC time on '{0}': {1}", debuggingDevice.ID, debuggingDeviceUtcTime.ToString()), false); await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "Current UTC time on '{0}': {1}", System.Environment.MachineName, thisMachineUtcTime.ToString()), false); await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "Difference in UTC time between '{0}' and '{1}': {2}", System.Environment.MachineName, debuggingDevice.ID, thisMachineUtcVersusDeviceUtc.ToString()), false); // // Check the last modified date; ls output currently uses this format: // // -rw-r--r-- system system 11533274 2015-01-09 13:47 com.example.native_activity-2.apk // DateTime lastModifiedTimestampDeviceLocalTime; try { var extendedLsOutput = debuggingDevice.Shell("ls -l", path).Replace("\r", "").Split(new char [] { '\n' }, StringSplitOptions.RemoveEmptyEntries); var extendedLsOutputComponents = extendedLsOutput [0].Split(new char [] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string date = extendedLsOutputComponents [4]; string time = extendedLsOutputComponents [5]; if (!DateTime.TryParseExact(date + " " + time, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out lastModifiedTimestampDeviceLocalTime)) { break; } } catch (Exception e) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Failed to evaluate device local modified time of: {0}", path), e); } // // Calculate how long ago the APK was changed, according to the device's local time. // TimeSpan timeSinceLastModification = debuggingDeviceUtcTime - lastModifiedTimestampDeviceLocalTime; DateTime debuggingDeviceUtcTimeAtLastModification = debuggingDeviceUtcTime - timeSinceLastModification; DateTime thisMachineUtcTimeAtLastModification = thisMachineUtcTime - timeSinceLastModification; await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "'{0}' was last modified on '{1}' at: {2}.", launchConfig ["PackageName"], debuggingDevice.ID, debuggingDeviceUtcTimeAtLastModification.ToString()), false); await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "{0} (on {1}) was around {2} (on {3}).", debuggingDeviceUtcTimeAtLastModification.ToString(), debuggingDevice.ID, thisMachineUtcTimeAtLastModification.ToString(), System.Environment.MachineName), false); await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "'{0}' was last modified on '{1}' at: {2}.", Path.GetFileName(targetApkFileInfo.FullName), System.Environment.MachineName, targetApkFileInfo.LastWriteTime.ToString()), false); if ((targetApkFileInfo.LastWriteTime + thisMachineUtcVersusDeviceUtc) > thisMachineUtcTimeAtLastModification) { await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "'{0}' was determined to be out-of-date. Reinstalling...", launchConfig ["PackageName"]), false); } else { appIsOutOfDate = false; } break; } } } catch (Exception) { appIsInstalled = false; } } else { await m_debugConnectionService.LaunchDialogUpdate("Skipping up-to-date check.", false); } if (!appIsInstalled || appIsOutOfDate) { await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "Installing '{0}' to '{1}'...", launchConfig ["PackageName"], debuggingDevice.ID), false); InstallApplicationAsync(debuggingDevice, launchConfig); await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "'{0}' installed successfully.", launchConfig ["PackageName"]), false); } else { await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "'{0}' on '{1}' is up-to-date. Skipping installation...", launchConfig ["PackageName"], debuggingDevice.ID), false); } debugLaunchSettings.Executable = launchConfig ["TargetApk"]; debugLaunchSettings.LaunchOperation = DebugLaunchOperation.Custom; } return(debugLaunchSettings); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int GetInfo(enum_PROCESS_INFO_FIELDS Fields, PROCESS_INFO [] infoArray) { // // Gets a description of the process. // LoggingUtils.PrintFunction(); try { infoArray [0] = new PROCESS_INFO(); if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_FILE_NAME) != 0) { LoggingUtils.RequireOk(GetName(enum_GETNAME_TYPE.GN_FILENAME, out infoArray [0].bstrFileName)); infoArray [0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_FILE_NAME; } if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_BASE_NAME) != 0) { LoggingUtils.RequireOk(GetName(enum_GETNAME_TYPE.GN_BASENAME, out infoArray [0].bstrBaseName)); infoArray [0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_BASE_NAME; } if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_TITLE) != 0) { LoggingUtils.RequireOk(GetName(enum_GETNAME_TYPE.GN_TITLE, out infoArray [0].bstrTitle)); infoArray [0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_TITLE; } if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_PROCESS_ID) != 0) { AD_PROCESS_ID [] processId = new AD_PROCESS_ID [1]; LoggingUtils.RequireOk(GetPhysicalProcessId(processId)); infoArray [0].ProcessId = processId [0]; infoArray [0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_PROCESS_ID; } if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_SESSION_ID) != 0) { // We currently don't support multiple sessions, so all processes are in session 1. infoArray [0].dwSessionId = 1; infoArray [0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_SESSION_ID; } if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_ATTACHED_SESSION_NAME) != 0) { // Oddly enough, SESSION_NAME is requested... even though the docs clearly state that it's deprecated. infoArray [0].bstrAttachedSessionName = "[Attached session name is deprecated]"; infoArray [0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_ATTACHED_SESSION_NAME; } if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_CREATION_TIME) != 0) { // Not entirely clear how this should be implemented. /*Microsoft.VisualStudio.OLE.Interop.FILETIME filetime; * * infoArray [0].CreationTime = filetime; * * infoArray [0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_CREATION_TIME;*/ } if ((Fields & enum_PROCESS_INFO_FIELDS.PIF_FLAGS) != 0) { infoArray [0].Flags |= enum_PROCESS_INFO_FLAGS.PIFLAG_PROCESS_RUNNING; if (DebuggeeProgram.AttachedEngine != null) { infoArray [0].Flags |= enum_PROCESS_INFO_FLAGS.PIFLAG_DEBUGGER_ATTACHED; } //enum_PROCESS_INFO_FLAGS.PIFLAG_DEBUGGER_ATTACHED //enum_PROCESS_INFO_FLAGS.PIFLAG_PROCESS_STOPPED //enum_PROCESS_INFO_FLAGS.PIFLAG_PROCESS_RUNNING if (!NativeProcess.IsUserProcess) { infoArray [0].Flags |= enum_PROCESS_INFO_FLAGS.PIFLAG_SYSTEM_PROCESS; } infoArray [0].Fields |= enum_PROCESS_INFO_FIELDS.PIF_FLAGS; } return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebuggeeProperty EvaluateCustomExpression(enum_EVALFLAGS evaluateFlags, string expression, uint radix) { // // Evaluates a custom property lookup, and registers a new entry for this expression if one can't be found. // LoggingUtils.PrintFunction(); DebuggeeProperty property = null; try { if (m_stackRegisters.TryGetValue(expression, out property)) { return(property); } if (m_stackArguments.TryGetValue(expression, out property)) { return(property); } if (m_stackLocals.TryGetValue(expression, out property)) { return(property); } if (m_customExpressions.TryGetValue(expression, out property)) { return(property); } // // Check if this expression has already been queried via a child property. // // TODO. // // Couldn't find a pre-registered matching property for this expression, creating a new custom one. // MiVariable customExpressionVariable = m_debugger.VariableManager.CreateVariableFromExpression(this, expression); if (customExpressionVariable != null) { property = m_debugger.VariableManager.CreatePropertyFromVariable(this, customExpressionVariable); if (property != null) { m_customExpressions.TryAdd(expression, property); LoggingUtils.RequireOk(m_property.AddChildren(new DebuggeeProperty [] { property })); } } } catch (Exception e) { LoggingUtils.HandleException(e); } return(property); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region DebugEngineCallbackInterface Members //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int Event(IDebugEngine2 pEngine, IDebugProcess2 pProcess, IDebugProgram2 pProgram, IDebugThread2 pThread, IDebugEvent2 pEvent, ref Guid riidEvent, uint dwAttrib) { LoggingUtils.Print("[DebugEngineCallback] Event: " + riidEvent.ToString()); // // Process any registered function handler before passing the event to AD7 callback. // int handle = Constants.E_NOTIMPL; try { DebuggerEventDelegate eventCallback; if (m_debuggerCallback.TryGetValue(riidEvent, out eventCallback)) { handle = eventCallback(pEngine, pProcess, pProgram, pThread, pEvent, ref riidEvent, dwAttrib); } if (handle != Constants.E_NOTIMPL) { LoggingUtils.RequireOk(handle); } } catch (Exception e) { LoggingUtils.HandleException(e); throw; } finally { try { handle = m_ad7EventCallback.Event(pEngine, pProcess, pProgram, pThread, pEvent, ref riidEvent, dwAttrib); if (handle != Constants.E_NOTIMPL) { LoggingUtils.RequireOk(handle); } } catch (Exception e) { LoggingUtils.HandleException(e); throw; } } // // (Managed Code) It is strongly advised that ReleaseComObject be invoked on the various interfaces that are passed to IDebugEventCallback2::Event. // #if false Marshal.ReleaseComObject(pEngine); Marshal.ReleaseComObject(pProcess); Marshal.ReleaseComObject(pProgram); Marshal.ReleaseComObject(pThread); Marshal.ReleaseComObject(pEvent); #endif return(handle); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override int SetFrameInfo(enum_FRAMEINFO_FLAGS requestedFlags, uint radix, ref FRAMEINFO frameInfo) { LoggingUtils.PrintFunction(); try { frameInfo.m_dwValidFields = 0; if ((requestedFlags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME) != 0) { StringBuilder functionName = new StringBuilder(); functionName.Append("[" + m_locationAddress.ToString() + "] "); if (((requestedFlags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE) != 0) && (!string.IsNullOrEmpty(m_locationModule))) { functionName.Append(m_locationModule + "!"); } functionName.Append(m_locationFunction); /*if ((requestedFlags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS) != 0) * { * functionName.Append ("(...)"); * } * * if ((requestedFlags & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_LINES) != 0) * { * functionName.AppendFormat (" Line {0}", "?"); * }*/ frameInfo.m_bstrFuncName = functionName.ToString(); frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME; } if ((requestedFlags & enum_FRAMEINFO_FLAGS.FIF_RETURNTYPE) != 0) { frameInfo.m_bstrReturnType = "<return type>"; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_RETURNTYPE; } if ((requestedFlags & enum_FRAMEINFO_FLAGS.FIF_ARGS) != 0) { frameInfo.m_bstrArgs = m_stackArguments.Keys.ToString(); frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_ARGS; } if ((requestedFlags & enum_FRAMEINFO_FLAGS.FIF_LANGUAGE) != 0) { string languageName = string.Empty; Guid languageGuid = Guid.Empty; GetLanguageInfo(ref languageName, ref languageGuid); frameInfo.m_bstrLanguage = languageName; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_LANGUAGE; } if ((requestedFlags & enum_FRAMEINFO_FLAGS.FIF_MODULE) != 0) { frameInfo.m_bstrModule = m_locationModule; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_MODULE; } if ((requestedFlags & enum_FRAMEINFO_FLAGS.FIF_STACKRANGE) != 0) { frameInfo.m_addrMin = 0ul; frameInfo.m_addrMax = 0ul; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_STACKRANGE; } if ((requestedFlags & enum_FRAMEINFO_FLAGS.FIF_FRAME) != 0) { frameInfo.m_pFrame = this; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_FRAME; } if ((requestedFlags & enum_FRAMEINFO_FLAGS.FIF_DEBUGINFO) != 0) { frameInfo.m_fHasDebugInfo = (m_locationIsSymbolicated) ? 1 : 0; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_DEBUGINFO; } if ((requestedFlags & enum_FRAMEINFO_FLAGS.FIF_STALECODE) != 0) { frameInfo.m_fStaleCode = 0; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_STALECODE; } if ((requestedFlags & enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP) != 0) { if (!string.IsNullOrEmpty(m_locationModule)) { IDebugProgram2 debugProgram; IEnumDebugModules2 debugProgramModules; uint debugModulesCount = 0; LoggingUtils.RequireOk(m_thread.GetProgram(out debugProgram)); LoggingUtils.RequireOk(debugProgram.EnumModules(out debugProgramModules)); LoggingUtils.RequireOk(debugProgramModules.GetCount(out debugModulesCount)); DebuggeeModule [] debugModules = new DebuggeeModule [debugModulesCount]; LoggingUtils.RequireOk(debugProgramModules.Next(debugModulesCount, debugModules, ref debugModulesCount)); for (int i = 0; i < debugModulesCount; ++i) { if (m_locationModule.Equals(debugModules [i].Name)) { frameInfo.m_pModule = debugModules [i]; frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP; break; } } } } return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region IDebugProperty2 Members //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public virtual int EnumChildren(enum_DEBUGPROP_INFO_FLAGS dwFields, uint dwRadix, ref Guid guidFilter, enum_DBG_ATTRIB_FLAGS dwAttribFilter, string pszNameFilter, uint dwTimeout, out IEnumDebugPropertyInfo2 ppEnum) { // // Enumerates the children of a property. This provides support for dereferencing pointers, displaying members of an array, or fields of a class or struct. // LoggingUtils.PrintFunction(); try { List <DEBUG_PROPERTY_INFO> childPropertyInfo = new List <DEBUG_PROPERTY_INFO> (); List <DebuggeeProperty> childRegisterProperties = new List <DebuggeeProperty> (); foreach (DebuggeeProperty child in m_children) { bool displayProperty = false; DEBUG_PROPERTY_INFO [] infoArray = new DEBUG_PROPERTY_INFO [1]; LoggingUtils.RequireOk(child.GetPropertyInfo(dwFields, dwRadix, dwTimeout, null, 0, infoArray)); if ((guidFilter == DebuggeeProperty.Filters.guidFilterRegisters) || (guidFilter == DebuggeeProperty.Filters.guidFilterAutoRegisters)) { if ((infoArray [0].dwAttrib & enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_STORAGE_REGISTER) != 0) { childRegisterProperties.Add(child); } } else if ((guidFilter == DebuggeeProperty.Filters.guidFilterArgs) || (guidFilter == DebuggeeProperty.Filters.guidFilterAllLocalsPlusArgs) || (guidFilter == DebuggeeProperty.Filters.guidFilterLocalsPlusArgs)) { displayProperty |= ((infoArray [0].dwAttrib & enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_DATA) != 0); } else if ((guidFilter == DebuggeeProperty.Filters.guidFilterAllLocals) || (guidFilter == DebuggeeProperty.Filters.guidFilterAllLocalsPlusArgs) || (guidFilter == DebuggeeProperty.Filters.guidFilterLocals) || (guidFilter == DebuggeeProperty.Filters.guidFilterLocalsPlusArgs)) { displayProperty |= ((infoArray [0].dwAttrib & enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_DATA) != 0); } else { displayProperty = true; } /*if ((infoArray [0].dwAttrib & dwAttribFilter) != 0) * { * displayProperty = false; * }*/ if (displayProperty) { childPropertyInfo.Add(infoArray [0]); } } if ((guidFilter == DebuggeeProperty.Filters.guidFilterRegisters) || (guidFilter == DebuggeeProperty.Filters.guidFilterAutoRegisters)) { // // // Registers must be specified in a collection/list as children of a 'CPU' property. // // Other types documented: https://msdn.microsoft.com/en-us/library/aa290860(v=vs.71).aspx // DebuggeeProperty registersProperty = new DebuggeeProperty(m_debugEngine, m_stackFrame, "CPU", string.Empty); LoggingUtils.RequireOk(registersProperty.AddChildren(childRegisterProperties.ToArray())); DEBUG_PROPERTY_INFO [] infoArray = new DEBUG_PROPERTY_INFO [1]; LoggingUtils.RequireOk(registersProperty.GetPropertyInfo(dwFields, dwRadix, dwTimeout, null, 0, infoArray)); childPropertyInfo.Add(infoArray [0]); } ppEnum = new DebuggeeProperty.Enumerator(childPropertyInfo); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); ppEnum = null; return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region IDebugPortSupplier2 Members //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int AddPort(IDebugPortRequest2 pRequest, out IDebugPort2 ppPort) { // // Attempt to find a port matching the requested name, otherwise one is created. // LoggingUtils.PrintFunction(); try { string requestPortName; LoggingUtils.RequireOk(CanAddPort()); LoggingUtils.RequireOk(pRequest.GetPortName(out requestPortName)); if (string.IsNullOrWhiteSpace(requestPortName)) { throw new InvalidOperationException("Invalid/empty port name"); } ppPort = null; foreach (KeyValuePair <Guid, IDebugPort2> keyPair in m_registeredPorts) { string portName; IDebugPort2 registeredPort = keyPair.Value; LoggingUtils.RequireOk(registeredPort.GetPortName(out portName)); if (portName.Equals(requestPortName)) { ppPort = registeredPort; break; } } if (ppPort == null) { // // Create and track a new port for this request. // Guid portId; LoggingUtils.RequireOk(CreatePort(pRequest, out ppPort)); LoggingUtils.RequireOk(ppPort.GetPortId(out portId)); m_registeredPorts.Add(portId, ppPort); } return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); ppPort = null; return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override int SetPassCount(BP_PASSCOUNT bpPassCount) { // // Sets or change the pass count associated with this bound breakpoint. // LoggingUtils.PrintFunction(); try { int handle = base.SetPassCount(bpPassCount); if (handle == Constants.E_BP_DELETED) { return(handle); } LoggingUtils.RequireOk(handle); uint passCount = 0; switch (bpPassCount.stylePassCount) { case enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_EQUAL: { goto case enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_EQUAL_OR_GREATER; } case enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_EQUAL_OR_GREATER: { passCount = bpPassCount.dwPassCount - 1; break; } case enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_MOD: { throw new NotImplementedException(); } } m_debugger.RunInterruptOperation(delegate(CLangDebugger debugger) { string command = string.Format("-break-after {0} {1}", GdbBreakpoint.ID, passCount); debugger.GdbClient.SendCommand(command, delegate(MiResultRecord resultRecord) { MiResultRecord.RequireOk(resultRecord, command); }); }); return(Constants.S_OK); } catch (NotImplementedException e) { LoggingUtils.HandleException(e); return(Constants.E_NOTIMPL); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }