using System; using Cosmos.VS.DebugEngine.Engine.Impl; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Debugger.Interop; namespace Cosmos.VS.DebugEngine.AD7.Impl { // And implementation of IDebugCodeContext2 and IDebugMemoryContext2. // IDebugMemoryContext2 represents a position in the address space of the machine running the program being debugged. // IDebugCodeContext2 represents the starting position of a code instruction. // For most run-time architectures today, a code context can be thought of as an address in a program's execution stream. public class AD7MemoryAddress : IDebugCodeContext2 { readonly AD7Engine m_engine; readonly uint m_address; IDebugDocumentContext2 m_documentContext; public AD7MemoryAddress(AD7Engine engine, uint address) { m_engine = engine; m_address = address; } public void SetDocumentContext(IDebugDocumentContext2 docContext) { m_documentContext = docContext; } // Adds a specified value to the current context's address to create a new context. public int Add(ulong dwCount, out IDebugMemoryContext2 newAddress) { newAddress = new AD7MemoryAddress(m_engine, (uint)dwCount + m_address); return VSConstants.S_OK; } // Compares the memory context to each context in the given array in the manner indicated by compare flags, // returning an index of the first context that matches. public int Compare(enum_CONTEXT_COMPARE uContextCompare, IDebugMemoryContext2[] compareToItems, uint compareToLength, out uint foundIndex) { foundIndex = uint.MaxValue; try { enum_CONTEXT_COMPARE contextCompare = (enum_CONTEXT_COMPARE)uContextCompare; for (uint c = 0; c < compareToLength; c++) { AD7MemoryAddress compareTo = compareToItems[c] as AD7MemoryAddress; if (compareTo == null) { continue; } if (!AD7Engine.ReferenceEquals(this.m_engine, compareTo.m_engine)) { continue; } bool result; switch (contextCompare) { case enum_CONTEXT_COMPARE.CONTEXT_EQUAL: result = (this.m_address == compareTo.m_address); break; case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN: result = (this.m_address < compareTo.m_address); break; case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN: result = (this.m_address > compareTo.m_address); break; case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN_OR_EQUAL: result = (this.m_address <= compareTo.m_address); break; case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN_OR_EQUAL: result = (this.m_address >= compareTo.m_address); break; // The sample debug engine doesn't understand scopes or functions case enum_CONTEXT_COMPARE.CONTEXT_SAME_SCOPE: case enum_CONTEXT_COMPARE.CONTEXT_SAME_FUNCTION: result = (this.m_address == compareTo.m_address); break; case enum_CONTEXT_COMPARE.CONTEXT_SAME_MODULE: result = (this.m_address == compareTo.m_address); if (result == false) { //DebuggedModule module = m_engine.DebuggedProcess.ResolveAddress(m_address); //if (module != null) //{ // result = (compareTo.m_address >= module.BaseAddress) && // (compareTo.m_address < module.BaseAddress + module.Size); //} } break; case enum_CONTEXT_COMPARE.CONTEXT_SAME_PROCESS: result = true; break; default: // A new comparison was invented that we don't support return VSConstants.E_NOTIMPL; } if (result) { foundIndex = c; return VSConstants.S_OK; } } return VSConstants.S_FALSE; } //catch (ComponentException e) //{ // return e.HResult; //} catch (Exception e) { return EngineUtils.UnexpectedException(e); } } // Gets information that describes this context. public int GetInfo(enum_CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO[] pinfo) { try { pinfo[0].dwFields = 0; if (dwFields.HasFlag(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS)) { pinfo[0].bstrAddress = m_address.ToString(); pinfo[0].dwFields |= enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS; } // Fields not supported by the sample //if ((dwFields & (uint)enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSOFFSET) != 0){} //if ((dwFields & (uint)enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE) != 0){} //if ((dwFields & (uint)enum_CONTEXT_INFO_FIELDS.CIF_MODULEURL) != 0){} //if ((dwFields & (uint)enum_CONTEXT_INFO_FIELDS.CIF_FUNCTION) != 0) {} //if ((dwFields & (uint)enum_CONTEXT_INFO_FIELDS.CIF_FUNCTIONOFFSET) != 0) {} return VSConstants.S_OK; } //catch (ComponentException e) //{ // return e.HResult; //} catch (Exception e) { return EngineUtils.UnexpectedException(e); } } // Gets the user-displayable name for this context // This is not supported by the sample engine. public int GetName(out string pbstrName) { throw new Exception("The method or operation is not implemented."); } // Subtracts a specified value from the current context's address to create a new context. public int Subtract(ulong dwCount, out IDebugMemoryContext2 ppMemCxt) { ppMemCxt = new AD7MemoryAddress(m_engine, (uint)dwCount - m_address); return VSConstants.S_OK; } // Gets the document context for this code-context public int GetDocumentContext(out IDebugDocumentContext2 ppSrcCxt) { ppSrcCxt = m_documentContext; return VSConstants.S_OK; } // Gets the language information for this code context. public int GetLanguageInfo(ref string pbstrLanguage, ref Guid pguidLanguage) { if (m_documentContext != null) { m_documentContext.GetLanguageInfo(ref pbstrLanguage, ref pguidLanguage); return VSConstants.S_OK; } else { return VSConstants.S_FALSE; } } } }