public void GetInfoAddress() { var contextInfo = new CONTEXT_INFO[1]; Assert.AreEqual(VSConstants.S_OK, memoryContext.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS, contextInfo)); Assert.AreEqual(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS, contextInfo[0].dwFields); Assert.AreEqual(TEST_PC_STR, contextInfo[0].bstrAddress); }
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 int ReadAt(IDebugMemoryContext2 pStartContext, uint dwCount, byte [] rgbMemory, out uint pdwRead, ref uint pdwUnreadable) { // // Reads a sequence of bytes, starting at a given location. // LoggingUtils.PrintFunction(); try { CONTEXT_INFO [] contextInfoArray = new CONTEXT_INFO [1]; LoggingUtils.RequireOk(pStartContext.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE, contextInfoArray)); string command = string.Format("-data-read-memory-bytes {0} {1}", contextInfoArray [0].bstrAddressAbsolute, dwCount); MiResultRecord resultRecord = m_debugger.GdbClient.SendSyncCommand(command); MiResultRecord.RequireOk(resultRecord, command); MiResultValueList memoryStreamList = (MiResultValueList)resultRecord ["memory"] [0]; for (int s = 0; s < memoryStreamList.Values.Count; ++s) { if (!memoryStreamList [s].HasField("contents")) { throw new InvalidOperationException("-data-read-memory-bytes result missing 'contents' field"); } string hexValue = memoryStreamList [s] ["contents"] [0].GetString(); if ((hexValue.Length / 2) != dwCount) { throw new InvalidOperationException(); } for (int i = 0; i < dwCount; ++i) { rgbMemory [i] = byte.Parse(hexValue.Substring(i * 2, 2), NumberStyles.HexNumber); } } pdwRead = dwCount; pdwUnreadable = 0; return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); pdwRead = 0; pdwUnreadable = dwCount; return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int ReadAt (IDebugMemoryContext2 pStartContext, uint dwCount, byte [] rgbMemory, out uint pdwRead, ref uint pdwUnreadable) { // // Reads a sequence of bytes, starting at a given location. // LoggingUtils.PrintFunction (); try { CONTEXT_INFO [] contextInfoArray = new CONTEXT_INFO [1]; LoggingUtils.RequireOk (pStartContext.GetInfo (enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE, contextInfoArray)); string command = string.Format ("-data-read-memory-bytes {0} {1}", contextInfoArray [0].bstrAddressAbsolute, dwCount); MiResultRecord resultRecord = m_debugger.GdbClient.SendSyncCommand (command); MiResultRecord.RequireOk (resultRecord, command); MiResultValueList memoryStreamList = (MiResultValueList) resultRecord ["memory"] [0]; for (int s = 0; s < memoryStreamList.Values.Count; ++s) { if (!memoryStreamList [s].HasField ("contents")) { throw new InvalidOperationException ("-data-read-memory-bytes result missing 'contents' field"); } string hexValue = memoryStreamList [s] ["contents"] [0].GetString (); if ((hexValue.Length / 2) != dwCount) { throw new InvalidOperationException (); } for (int i = 0; i < dwCount; ++i) { rgbMemory [i] = byte.Parse (hexValue.Substring (i * 2, 2), NumberStyles.HexNumber); } } pdwRead = dwCount; pdwUnreadable = 0; return Constants.S_OK; } catch (Exception e) { LoggingUtils.HandleException (e); pdwRead = 0; pdwUnreadable = dwCount; return Constants.E_FAIL; } }
public static ulong GetAddress(this IDebugMemoryContext2 context) { var contextInfo = new CONTEXT_INFO[1]; int res = context.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS, contextInfo); Debug.Assert(res == VSConstants.S_OK); return(System.Convert.ToUInt64(contextInfo[0].bstrAddress, 16)); }
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); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 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); } }
int IDebugCodeContext2.GetInfo(enum_CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO[] pinfo) { return(IDebugMemoryContext2.GetInfo(dwFields, pinfo)); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 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; } }