public int WriteAt(IDebugMemoryContext2 startMemoryContext, uint count, byte[] buffer) { CONTEXT_INFO[] contextInfos = new CONTEXT_INFO[1]; startMemoryContext.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS, contextInfos); ulong address; if (!DebugEngineUtil.GetAddressFromString(contextInfos[0].bstrAddress, out address)) { Trace.WriteLine($"Failed to convert {contextInfos[0].bstrAddress} to address"); return(VSConstants.E_FAIL); } SbError error; var bytesWrote = _lldbProcess.WriteMemory(address, buffer, count, out error); if (error.Fail()) { Trace.WriteLine($"Error: {error.GetCString()}"); return(VSConstants.E_FAIL); } if (bytesWrote != count) { Trace.WriteLine( $"Warning: only written {bytesWrote} out of {count} bytes to memory."); return(VSConstants.S_FALSE); } return(VSConstants.S_OK); }
public void ParseAddressFromDecString() { const string INPUT = "12345"; const ulong EXPECTED = 12345; ulong output; Assert.AreEqual(true, DebugEngineUtil.GetAddressFromString(INPUT, out output)); Assert.AreEqual(EXPECTED, output); }
public void ParseAddressFromHexString() { const string INPUT = "0xdeadbeef"; const ulong EXPECTED = 0xdeadbeef; ulong output; Assert.AreEqual(true, DebugEngineUtil.GetAddressFromString(INPUT, out output)); Assert.AreEqual(EXPECTED, output); }
public int CanSetNextStatement(IDebugStackFrame2 stackFrameOrigin, IDebugCodeContext2 codeContextDestination) { stackFrameOrigin.GetThread(out IDebugThread2 threadOrigin); if (threadOrigin == null) { return(VSConstants.E_FAIL); } threadOrigin.GetThreadId(out uint threadIdOrigin); if (threadIdOrigin != _id) { return(VSConstants.S_FALSE); } var contextInfosDestination = new CONTEXT_INFO[1]; int result = codeContextDestination.GetInfo( enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS | enum_CONTEXT_INFO_FIELDS.CIF_FUNCTION, contextInfosDestination); if (result != VSConstants.S_OK) { return(result); } string functionNameOrigin; if (!DebugEngineUtil.GetAddressFromString(contextInfosDestination[0].bstrAddress, out ulong addressPc)) { return(VSConstants.E_FAIL); } if (stackFrameOrigin is IDebugStackFrame stackFrameOriginCast) { stackFrameOriginCast.GetNameWithSignature(out functionNameOrigin); } else { stackFrameOrigin.GetName(out functionNameOrigin); } if (addressPc != _remoteThread.GetFrameAtIndex(0).GetPC() && contextInfosDestination[0].bstrFunction != functionNameOrigin) { return(VSConstants.S_FALSE); } return(VSConstants.S_OK); }
public int ReadAt(IDebugMemoryContext2 startMemoryContext, uint countToRead, byte[] memory, out uint countRead, ref uint countUnreadable) { // |countUnreadable| can be null when calling from C++ according to Microsoft's doc. // However, countUnreadable == null will always return false in C# as an uint can never // be null. Accessing |countUnreadable| here might cause a NullReferenceException. // According to Microsoft's doc, |countUnreadable| is useful when there are // non -consecutive blocks of memory that are readable. For example, if we want to read // 100 bytes at a certain address and only the first 50 bytes and the last 20 bytes are // readable. |countRead| would be 50 and |countUnreadable| should be 30. However, // LLDB's ReadMemory() doesn't provide this kind of output, so this is not // straightforward to implement. // TODO We should estimate |countUnreadable| from page boundaries. // Otherwise, the memory view might be missing some valid contents in the beginnings // of mapped regions. // Note: We need to make sure we never return S_OK while setting countRead and // countUnreadable to zero. That can send the memory view into an infinite loop // and freeze Visual Studio ((internal)). CONTEXT_INFO[] contextInfo = new CONTEXT_INFO[1]; startMemoryContext.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS, contextInfo); ulong address; if (DebugEngineUtil.GetAddressFromString(contextInfo[0].bstrAddress, out address)) { SbError error; try { countRead = Convert.ToUInt32(_lldbProcess.ReadMemory(address, memory, countToRead, out error)); if (error.Fail() || countRead == 0) { countRead = 0; return(VSConstants.E_FAIL); } return(VSConstants.S_OK); } catch (OverflowException e) { Trace.WriteLine($"Warning: Failed to read memory.{Environment.NewLine}" + $"{e.ToString()}"); countRead = 0; return(VSConstants.E_FAIL); } } countRead = 0; return(VSConstants.E_FAIL); }