public void ReadDataArray <T>(ref DEBUG_PROPERTY_INFO propertyInfo, string typeAsString) { byte[] xData; // Get handle xData = mProcess.mDbgConnector.GetStackData(OFFSET, 4); // Get actual pointer xData = mProcess.mDbgConnector.GetMemoryData(BitConverter.ToUInt32(xData, 0), 4); if (xData == null) { propertyInfo.bstrValue = String.Format("Error! Stack data received was null!"); } else { uint xPointer = BitConverter.ToUInt32(xData, 0); if (xPointer == 0) { propertyInfo.bstrValue = NULL; } else { xData = mProcess.mDbgConnector.GetMemoryData(xPointer + mArrayLengthOffset, 4, 4); if (xData == null) { propertyInfo.bstrValue = String.Format("Error! Memory data received was null!"); } else { uint xDataLength = BitConverter.ToUInt32(xData, 0); bool xIsTooLong = xDataLength > 512; if (xIsTooLong) { xDataLength = 512; } if (xDataLength > 0) { if (m_variableInformation.Children.Count == 0) { for (int i = 0; i < xDataLength; i++) { var inf = new DebugLocalInfo(); inf.IsReference = true; inf.Type = typeof(T).FullName; inf.Offset = (int)(mArrayFirstElementOffset + (System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)) * i)); inf.Pointer = (uint)(xPointer + mArrayFirstElementOffset + (System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)) * i)); inf.Name = "[" + i.ToString() + "]"; m_variableInformation.Children.Add(new AD7Property(inf, mProcess, mStackFrame)); } } } propertyInfo.bstrValue = String.Format(typeAsString + "[{0}] at 0x{1} ", xDataLength, xPointer.ToString("X")); } } } }
public AD7Property(DebugLocalInfo localInfo, AD7Process process, AD7StackFrame stackFrame) { m_variableInformation = localInfo; mProcess = process; mStackFrame = stackFrame; if (localInfo.IsLocal) { mDebugInfo = mStackFrame.mLocalInfos[m_variableInformation.Index]; } else if (localInfo.IsReference) { mDebugInfo = new LOCAL_ARGUMENT_INFO() { TYPENAME = localInfo.Type, NAME = localInfo.Name, OFFSET = localInfo.Offset }; } else { mDebugInfo = mStackFrame.mArgumentInfos[m_variableInformation.Index]; } }
public AD7StackFrame(AD7Engine aEngine, AD7Thread aThread, AD7Process aProcess) { mEngine = aEngine; mThread = aThread; mProcess = aProcess; var xProcess = mEngine.mProcess; if (mHasSource = xProcess.mCurrentAddress.HasValue) { var xAddress = xProcess.mCurrentAddress.Value; var xSourceInfos = xProcess.mDebugInfoDb.GetSourceInfos(xAddress); if (!xSourceInfos.ContainsKey(xAddress)) { //Attempt to find the ASM address of the first ASM line of the C# line that contains //the current ASM address line // Because of Asm breakpoints the address we have might be in the middle of a C# line. // So we find the closest address to ours that is less or equal to ours. var xQry = from x in xSourceInfos where x.Key <= xAddress orderby x.Key descending select x.Key; if (xQry.Count() > 0) { xAddress = xQry.First(); } } if (mHasSource = xSourceInfos.ContainsKey(xAddress)) { var xSourceInfo = xSourceInfos[xAddress]; mDocName = xSourceInfo.SourceFile; mFunctionName = xSourceInfo.MethodName; mLineNum = (uint)xSourceInfo.LineStart; // Multiple labels that point to a single address can happen because of exception handling exits etc. // Because of this given an address, we might find more than one label that matches the address. // Currently, the label we are looking for will always be the first one so we choose that one. // In the future this might "break", so be careful about this. In the future we may need to classify // labels in the output and mark them somehow. var xLabelsForAddr = xProcess.mDebugInfoDb.GetLabels(xAddress); if (xLabelsForAddr.Length > 0) { MethodIlOp xSymbolInfo; string xLabel = xLabelsForAddr[0]; // Necessary for LINQ xSymbolInfo = aProcess.mDebugInfoDb.TryGetFirstMethodIlOpByLabelName(xLabel); if (xSymbolInfo != null) { var xMethod = mProcess.mDebugInfoDb.GetMethod(xSymbolInfo.MethodID.Value); var xAllInfos = aProcess.mDebugInfoDb.GetAllLocalsAndArgumentsInfosByMethodLabelName(xMethod.LabelCall); mLocalInfos = xAllInfos.Where(q => !q.IsArgument).ToArray(); mArgumentInfos = xAllInfos.Where(q => q.IsArgument).ToArray(); if (mArgumentInfos.Length > 0) { mParams = new DebugLocalInfo[mArgumentInfos.Length]; for (int i = 0; i < mArgumentInfos.Length; i++) { mParams[i] = new DebugLocalInfo { Name = mArgumentInfos[i].NAME, Index = i, IsLocal = false }; } mParams = mParams.OrderBy(i => i.Name, StringComparer.OrdinalIgnoreCase).ToArray(); } if (mLocalInfos.Length > 0) { mLocals = new DebugLocalInfo[mLocalInfos.Length]; for (int i = 0; i < mLocalInfos.Length; i++) { mLocals[i] = new DebugLocalInfo { Name = mLocalInfos[i].NAME, Index = i, IsLocal = true }; } mLocals = mLocals.OrderBy(i => i.Name, StringComparer.OrdinalIgnoreCase).ToArray(); } } } else { AD7Util.ShowError("No Symbol found for address 0x" + xAddress.ToString("X8").ToUpper()); } xProcess.DebugMsg(String.Format("StackFrame: Returning: {0}#{1}[{2}]", mDocName, mFunctionName, mLineNum)); } } if (!mHasSource) { xProcess.DebugMsg("StackFrame: No Source available"); } // If source information is available, create the collections of locals and parameters and populate them with // values from the debuggee. //if (m_hasSource) { //if (mArgumentInfos.Length > 0) { //m_parameters = new VariableInformation[m_numParameters]; //m_engine.DebuggedProcess.GetFunctionArgumentsByIP(m_threadContext.eip, m_threadContext.ebp, m_parameters); //} //if (mLocalInfos.Length > 0) { //m_locals = new VariableInformation[m_numLocals]; //m_engine.DebuggedProcess.GetFunctionLocalsByIP(m_threadContext.eip, m_threadContext.ebp, m_locals); //} //} }
public AD7Expression(DebugLocalInfo pVar, AD7Process pProcess, AD7StackFrame pStackFrame) { m_var = pVar; Process = pProcess; StackFrame = pStackFrame; }
// Construct a DEBUG_PROPERTY_INFO representing this local or parameter. public DEBUG_PROPERTY_INFO ConstructDebugPropertyInfo(enum_DEBUGPROP_INFO_FLAGS dwFields) { var propertyInfo = new DEBUG_PROPERTY_INFO(); try { if (dwFields.HasFlag(enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_FULLNAME)) { propertyInfo.bstrFullName = m_variableInformation.Name; propertyInfo.dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_FULLNAME; } if (dwFields.HasFlag(enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_NAME)) { propertyInfo.bstrName = m_variableInformation.Name; propertyInfo.dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_NAME; } if (dwFields.HasFlag(enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_TYPE)) { propertyInfo.bstrType = mDebugInfo.TYPENAME; propertyInfo.dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_TYPE; } if (dwFields.HasFlag(enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE)) { byte[] xData; #region string if (mDebugInfo.TYPENAME == typeof(string).FullName) { const uint xStringLengthOffset = 12; const uint xStringFirstCharOffset = 16; // Get handle xData = mProcess.mDbgConnector.GetStackData(OFFSET, 4); // Get actual pointer xData = mProcess.mDbgConnector.GetMemoryData(BitConverter.ToUInt32(xData, 0), 4); if (xData == null) { propertyInfo.bstrValue = String.Format("Error! Stack data received was null!"); } else { uint xStrPointer = BitConverter.ToUInt32(xData, 0); if (xStrPointer == 0) { propertyInfo.bstrValue = NULL; } else { xData = mProcess.mDbgConnector.GetMemoryData(xStrPointer + xStringLengthOffset, 4, 4); if (xData == null) { propertyInfo.bstrValue = String.Format("Error! Memory data received was null!"); } else { uint xStringLength = BitConverter.ToUInt32(xData, 0); propertyInfo.bstrValue = "String of length: " + xStringLength; if (xStringLength > 100) { propertyInfo.bstrValue = "For now, strings larger than 100 chars are not supported.."; } else if (xStringLength == 0) { propertyInfo.bstrValue = "\"\""; } else { xData = mProcess.mDbgConnector.GetMemoryData(xStrPointer + xStringFirstCharOffset, xStringLength * 2, 2); if (xData == null) { propertyInfo.bstrValue = String.Format("Error! Memory data received was null!"); } else { propertyInfo.bstrValue = "\"" + Encoding.Unicode.GetString(xData) + "\""; } } } } } } #endregion #warning TODO: String[] #region byte // Byte else if (mDebugInfo.TYPENAME == typeof(byte).FullName) { ReadData <byte>(ref propertyInfo, new Func <byte[], int, byte>(delegate(byte[] barr, int ind) { return(barr[ind]); })); } else if (mDebugInfo.TYPENAME == typeof(byte[]).FullName) { ReadDataArray <byte>(ref propertyInfo, "byte"); } #endregion #region sbyte // SByte else if (mDebugInfo.TYPENAME == typeof(sbyte).FullName) { ReadData <sbyte>(ref propertyInfo, new Func <byte[], int, sbyte>(delegate(byte[] barr, int ind) { return(unchecked ((sbyte)barr[ind])); })); } else if (mDebugInfo.TYPENAME == typeof(sbyte[]).FullName) { ReadDataArray <sbyte>(ref propertyInfo, "sbyte"); } #endregion #region char else if (mDebugInfo.TYPENAME == typeof(char).FullName) { xData = mProcess.mDbgConnector.GetStackData(OFFSET, 2); if (xData == null) { propertyInfo.bstrValue = String.Format("Error! Stack data received was null!"); } else { var xTypedCharValue = BitConverter.ToChar(xData, 0); propertyInfo.bstrValue = String.Format("{0} '{1}'", (ushort)xTypedCharValue, xTypedCharValue); } } else if (mDebugInfo.TYPENAME == typeof(char[]).FullName) { // Get handle xData = mProcess.mDbgConnector.GetStackData(OFFSET, 4); // Get actual pointer xData = mProcess.mDbgConnector.GetMemoryData(BitConverter.ToUInt32(xData, 0), 4); if (xData == null) { propertyInfo.bstrValue = String.Format("Error! Stack data received was null!"); } else { uint xArrayPointer = BitConverter.ToUInt32(xData, 0); if (xArrayPointer == 0) { propertyInfo.bstrValue = NULL; } else { xData = mProcess.mDbgConnector.GetMemoryData(xArrayPointer + mArrayLengthOffset, 4, 4); if (xData == null) { propertyInfo.bstrValue = String.Format("Error! Memory data received was null!"); } else { uint xDataLength = BitConverter.ToUInt32(xData, 0); bool xIsTooLong = xDataLength > 512; var xSB = new StringBuilder(); xSB.AppendFormat("Char[{0}] at 0x{1} {{ ", xDataLength, xArrayPointer.ToString("X")); if (xIsTooLong) { xDataLength = 512; } if (xDataLength > 0) { xData = mProcess.mDbgConnector.GetMemoryData(xArrayPointer + mArrayFirstElementOffset, xDataLength * 2); if (xData == null) { xSB.Append(String.Format("Error! Memory data received was null!")); } else { bool first = true; for (int i = 0; (i / 2) < xDataLength; i += 2) { if (!first) { xSB.Append(", "); } char c = BitConverter.ToChar(xData, i); xSB.Append('\''); if (c == '\0') { xSB.Append("\\0"); } else { xSB.Append(c); } xSB.Append('\''); first = false; } } } if (xIsTooLong) { xSB.Append(", .."); } xSB.Append(" }"); propertyInfo.bstrValue = xSB.ToString(); } } } } #endregion #region short // Short else if (mDebugInfo.TYPENAME == typeof(short).FullName) { ReadData <short>(ref propertyInfo, new Func <byte[], int, short>(BitConverter.ToInt16)); } else if (mDebugInfo.TYPENAME == typeof(short[]).FullName) { ReadDataArray <short>(ref propertyInfo, "short"); } #endregion #region ushort // UShort else if (mDebugInfo.TYPENAME == typeof(ushort).FullName) { ReadData <ushort>(ref propertyInfo, new Func <byte[], int, ushort>(BitConverter.ToUInt16)); } else if (mDebugInfo.TYPENAME == typeof(ushort[]).FullName) { ReadDataArray <ushort>(ref propertyInfo, "ushort"); } #endregion #region int // Int32 else if (mDebugInfo.TYPENAME == typeof(int).FullName) { ReadData <int>(ref propertyInfo, new Func <byte[], int, int>(BitConverter.ToInt32)); } else if (mDebugInfo.TYPENAME == typeof(int[]).FullName) { ReadDataArray <int>(ref propertyInfo, "int"); } #endregion #region uint // UInt32 else if (mDebugInfo.TYPENAME == typeof(uint).FullName) { ReadData <uint>(ref propertyInfo, new Func <byte[], int, uint>(BitConverter.ToUInt32)); } else if (mDebugInfo.TYPENAME == typeof(uint[]).FullName) { ReadDataArray <uint>(ref propertyInfo, "uint"); } #endregion #region long // Long else if (mDebugInfo.TYPENAME == typeof(long).FullName) { ReadData <long>(ref propertyInfo, new Func <byte[], int, long>(BitConverter.ToInt64)); } else if (mDebugInfo.TYPENAME == typeof(long[]).FullName) { ReadDataArray <long>(ref propertyInfo, "long"); } #endregion #region ulong // ULong else if (mDebugInfo.TYPENAME == typeof(ulong).FullName) { ReadData <ulong>(ref propertyInfo, new Func <byte[], int, ulong>(BitConverter.ToUInt64)); } else if (mDebugInfo.TYPENAME == typeof(ulong[]).FullName) { ReadDataArray <ulong>(ref propertyInfo, "ulong"); } #endregion #region float // Float else if (mDebugInfo.TYPENAME == typeof(float).FullName) { ReadData <float>(ref propertyInfo, new Func <byte[], int, float>(BitConverter.ToSingle)); } else if (mDebugInfo.TYPENAME == typeof(float[]).FullName) { ReadDataArray <float>(ref propertyInfo, "float"); } #endregion #region double // Double else if (mDebugInfo.TYPENAME == typeof(double).FullName) { ReadData <double>(ref propertyInfo, new Func <byte[], int, double>(BitConverter.ToDouble)); } else if (mDebugInfo.TYPENAME == typeof(double[]).FullName) { ReadDataArray <double>(ref propertyInfo, "double"); } #endregion #region bool // Bool else if (mDebugInfo.TYPENAME == typeof(bool).FullName) { ReadData <bool>(ref propertyInfo, new Func <byte[], int, bool>(BitConverter.ToBoolean)); } else if (mDebugInfo.TYPENAME == typeof(bool[]).FullName) { ReadDataArray <bool>(ref propertyInfo, "bool"); } #endregion else { if (m_variableInformation.IsReference) { xData = mProcess.mDbgConnector.GetMemoryData(m_variableInformation.Pointer, 4, 4); } else { xData = mProcess.mDbgConnector.GetStackData(OFFSET, 4); } if (xData == null) { propertyInfo.bstrValue = String.Format("Error! Stack data received was null!"); } else { var xPointer = BitConverter.ToUInt32(xData, 0); if (xPointer == 0) { propertyInfo.bstrValue = NULL; } else { try { var mp = mProcess.mDebugInfoDb.GetFieldMap(mDebugInfo.TYPENAME); foreach (string str in mp.FieldNames) { FIELD_INFO xFieldInfo; xFieldInfo = mProcess.mDebugInfoDb.GetFieldInfoByName(str); var inf = new DebugLocalInfo(); inf.IsReference = true; inf.Type = xFieldInfo.TYPE; inf.Offset = xFieldInfo.OFFSET; inf.Pointer = (uint)(xPointer + xFieldInfo.OFFSET + 12); inf.Name = GetFieldName(xFieldInfo); m_variableInformation.Children.Add(new AD7Property(inf, mProcess, mStackFrame)); } propertyInfo.bstrValue = String.Format("{0} (0x{1})", xPointer, xPointer.ToString("X").ToUpper()); } catch (Exception ex) { if (ex.GetType().Name == "SQLiteException") { //Ignore but warn user propertyInfo.bstrValue = "SQLiteException. Could not get type information for " + mDebugInfo.TYPENAME; } else { throw new Exception("Unexpected error in AD7Property.cs:459", ex); } } } } } propertyInfo.dwFields |= enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_VALUE; } if (dwFields.HasFlag(enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_ATTRIB)) { // The sample does not support writing of values displayed in the debugger, so mark them all as read-only. propertyInfo.dwAttrib = enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_VALUE_READONLY; if (m_variableInformation.Children.Count > 0) { propertyInfo.dwAttrib |= enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_OBJ_IS_EXPANDABLE; } } propertyInfo.pProperty = (IDebugProperty2)this; propertyInfo.dwFields |= (enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_PROP); // If the debugger has asked for the property, or the property has children (meaning it is a pointer in the sample) // then set the pProperty field so the debugger can call back when the children are enumerated. //if (((dwFields & (uint)enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_PROP) != 0) //|| (this.m_variableInformation.child != null)) //{ // propertyInfo.pProperty = (IDebugProperty2)this; // propertyInfo.dwFields |= (enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_PROP); //} } catch { } return(propertyInfo); }