} // end constructor #region IEquatable stuff public override bool Equals(DbgTypeInfo other) { var eti = other as DbgEnumTypeInfo; if (null == eti) { return(false); } if ((Size != eti.Size) || (m_modBase != eti.m_modBase) || (0 != String.CompareOrdinal(Name, eti.Name)) || (Enumerands.Count != eti.Enumerands.Count)) { return(false); } for (int i = 0; i < Enumerands.Count; i++) { if (Enumerands[i] != eti.Enumerands[i]) { return(false); } } return(true); } // end Equals( DbgTypeInfo )
} // end WireUpChildren() /// <summary> /// Creates a new DbgLocalSymbol object. /// </summary> internal DbgLocalSymbol(DbgSymbolGroup symGroup, uint idx, string name, DEBUG_SYMBOL_PARAMETERS symParams, DEBUG_SYMBOL_ENTRY?dse, DbgTarget target) : base(_GetDebugger(symGroup), name, target) { if (null == symGroup) { throw new ArgumentNullException("symGroup"); } m_symGroup = symGroup; m_idx = idx; m_nativeParams = symParams; m_dse = dse; m_metaDataUnavailable = (null == dse); if (!m_metaDataUnavailable && DbgTypeInfo.IsDbgGeneratedType(m_dse.Value.TypeId)) { // HACK HACKALERT WORKAROUND // // This is a workaround for the fact that we can't get at the type // information that the debugger generates. It tends to do this to create // pointer types, pointing to UDTs (not sure why the pointer types don't // exist in the PDB). // // It of course knows what the pointee type is, but it isn't exposed in // any way. I'd like to add a new IDebugAdvancedN::Request request to grab // it out, but until I get to that, I'll cheat and parse it out of some // string output. // // I don't know how robust this is, because I've rarely seen it (only once // with this code). // _GenerateSyntheticTypeToMatchDbgEngGeneratedType(name, Debugger, m_dse.Value); } // end if( it's a debugger-generated type ) m_pointerAdjustment = 0; if (0 == Util.Strcmp_OI(name, "this")) { try { ulong displacementDontCare; var sym = Debugger.GetSymbolByAddress(symGroup.Frame.InstructionPointer, out displacementDontCare); var ftti = sym.Type as DbgFunctionTypeTypeInfo; Util.Assert(null != ftti); // if we made it this far, we should have the right type m_pointerAdjustment = ftti.ThisAdjust; } catch (DbgEngException dee) { LogManager.Trace("Could not get thisadjust: {0}", Util.GetExceptionMessages(dee)); } } } // end constructor
} // end constructor #region IEquatable stuff public override bool Equals(DbgTypeInfo other) { var ati = other as DbgArrayTypeInfo; if (null == ati) { return(false); } return((Count == ati.Count) && (ArrayElementType.Equals(ati.ArrayElementType))); } // end Equals( DbgTypeInfo )
} // end constructor #region IEquatable stuff public override bool Equals(DbgTypeInfo other) { var pti = other as DbgPointerTypeInfo; if (null == pti) { return(false); } return((IsReference == pti.IsReference) && (PointeeType.Equals(pti.PointeeType))); } // end Equals( DbgTypeInfo )
internal LayoutItem(int offset, DbgTypeInfo item, int origIdx) { Offset = offset; Item = item; m_origIdx = origIdx; if (IsVTable) { //Size = ((DbgVTableTypeInfo) Item) Size = Item.Debugger.TargetIs32Bit ? 4 : 8; // TODO: There should be a better way } else { Size = (int)((DbgNamedTypeInfo)Item).Size; } }
} // end constructor #region IEquatable stuff // // We'll consider two UDTs to be equal if they have the same size, modBase, name, // base classes (and virtual bases classes), and members. // // We have to be careful not to include /all/ children (like statics), because we // could get stuck in infinite recursion (such as if a class had a static member // of its own type). // public override bool Equals(DbgTypeInfo other) { var uti = other as DbgUdtTypeInfo; if (null == uti) { return(false); } if ((Size != uti.Size) || (m_modBase != uti.m_modBase) || (Members.Count != uti.Members.Count) || (BaseClasses.Count != uti.BaseClasses.Count) || (VirtualBaseClasses.Count != uti.VirtualBaseClasses.Count) || (0 != String.CompareOrdinal(Name, uti.Name))) { return(false); } for (int i = 0; i < Members.Count; i++) { if (Members[i] != uti.Members[i]) { return(false); } } for (int i = 0; i < BaseClasses.Count; i++) { if (BaseClasses[i] != uti.BaseClasses[i]) { return(false); } } for (int i = 0; i < VirtualBaseClasses.Count; i++) { if (VirtualBaseClasses[i] != uti.VirtualBaseClasses[i]) { return(false); } } return(true); } // end Equals( DbgTypeInfo )
} // end _ValidateFieldInfoAndGetName() internal DbgFieldInfo(UserModeDebugger debugger, DbgTypeInfo owningType, ClrMemDiag.Debugger.FieldInfo fieldInfo, ulong modBase) // TODO BUGBUG? There is no module base field in 'f'... is it not possible for a field to be of a type from some other module? : this(debugger, owningType, _ValidateFieldInfoAndGetName(fieldInfo), fieldInfo.FieldOffset, (fieldInfo.PointerFlag != ClrMemDiag.Debugger.PointerFlag.None) && (fieldInfo.PointerFlag != ClrMemDiag.Debugger.PointerFlag.Pointer64), fieldInfo.PointerFlag.HasFlag(ClrMemDiag.Debugger.PointerFlag.Pointer64), fieldInfo.IsArray, //fieldInfo.IsStruct, fieldInfo.IsConstant, fieldInfo.IsStatic, fieldInfo.Size, DbgTypeInfo.GetNamedTypeInfo(debugger, modBase, fieldInfo.TypeId)) { // nothing } // end constructor
public DbgFieldInfo(DbgEngDebugger debugger, DbgTypeInfo owningType, string fieldName, uint fieldOffset, bool is32BitPointer, bool is64BitPointer, bool isArray, //bool isStruct, bool isConstant, bool isStatic, uint size, DbgNamedTypeInfo fieldType) : base(debugger) { if (null == owningType) { throw new ArgumentNullException("owningType"); } if (String.IsNullOrEmpty(fieldName)) { throw new ArgumentException("You must supply a field name.", "fieldName"); } if (null == fieldType) { throw new ArgumentNullException("fieldType"); } OwningType = owningType; Type = fieldType; Offset = fieldOffset; Name = fieldName; Is32BitPointer = is32BitPointer; Is64BitPointer = is64BitPointer; IsArray = isArray; //IsStruct = isStruct; IsConstant = isConstant; IsStatic = isStatic; Size = size; } // end constructor
internal DbgPublicSymbol(DbgEngDebugger debugger, SymbolInfo symbolInfo, DbgTarget target) : base(debugger, _VerifySymInfo(symbolInfo), target) { m_debugSymbols = (WDebugSymbols)debugger.DebuggerInterface; m_symInfo = symbolInfo; var typeSymTag = DbgHelp.GetSymTag(debugger.DebuggerInterface, symbolInfo.ModBase, symbolInfo.TypeIndex); m_type = (DbgNamedTypeInfo)DbgTypeInfo.GetTypeInfo(debugger, symbolInfo.ModBase, symbolInfo.TypeIndex, typeSymTag, target); m_dmai = new DEBUG_MODULE_AND_ID() { Id = symbolInfo.Index, ModuleBase = symbolInfo.ModBase }; } // end constructor
} // end _ValidateFieldInfoAndGetName() internal DbgFieldInfo(DbgEngDebugger debugger, DbgTypeInfo owningType, Microsoft.Diagnostics.Runtime.Interop.FieldInfo fieldInfo, ulong modBase, DbgUModeProcess process) // TODO BUGBUG? There is no module base field in 'f'... is it not possible for a field to be of a type from some other module? : this(debugger, owningType, _ValidateFieldInfoAndGetName(fieldInfo), fieldInfo.FieldOffset, (fieldInfo.PointerFlag != Microsoft.Diagnostics.Runtime.Interop.PointerFlag.None) && (fieldInfo.PointerFlag != Microsoft.Diagnostics.Runtime.Interop.PointerFlag.Pointer64), fieldInfo.PointerFlag.HasFlag(Microsoft.Diagnostics.Runtime.Interop.PointerFlag.Pointer64), fieldInfo.IsArray, //fieldInfo.IsStruct, fieldInfo.IsConstant, fieldInfo.IsStatic, fieldInfo.Size, DbgTypeInfo.GetNamedTypeInfo(debugger, modBase, fieldInfo.TypeId, process)) { // nothing } // end constructor
private void _PopulateMembers() { Util.Assert(null == m_members); // shouldn't need to do this more than once var members = new NameIndexableList <DbgDataMemberTypeInfo>(); var statics = new NameIndexableList <DbgDataStaticMemberTypeInfo>(); var bases = new NameIndexableList <DbgBaseClassTypeInfo>(); var virtBases = new NameIndexableList <DbgVirtualBaseClassTypeInfo>(); var nestedTypes = new NameIndexableList <DbgUdtTypeInfo>(); var nestedEnums = new NameIndexableList <DbgEnumTypeInfo>(); var typedefs = new NameIndexableList <DbgTypedefTypeInfo>(); var functions = new NameIndexableList <DbgFunctionTypeInfo>(); var childrenIds = GetChildrenIds(m_numChildren); // _EnsureValid() called here var children = new List <DbgTypeInfo>(childrenIds.Length); foreach (var childId in childrenIds) { var child = DbgTypeInfo.GetTypeInfo(Debugger, Module, childId); children.Add(child); if (child is DbgDataMemberTypeInfo) { members.Add((DbgDataMemberTypeInfo)child); } else if (child is DbgDataStaticMemberTypeInfo) { statics.Add((DbgDataStaticMemberTypeInfo)child); } else if (child is DbgBaseClassTypeInfo) { DbgBaseClassTypeInfo bcti = (DbgBaseClassTypeInfo)child; bases.Add(bcti); bcti.AggregateMembers(members, statics); } else if (child is DbgVirtualBaseClassTypeInfo) { virtBases.Add((DbgVirtualBaseClassTypeInfo)child); } else if (child is DbgUdtTypeInfo) { nestedTypes.Add((DbgUdtTypeInfo)child); } else if (child is DbgEnumTypeInfo) { nestedEnums.Add((DbgEnumTypeInfo)child); } else if (child is DbgTypedefTypeInfo) { typedefs.Add((DbgTypedefTypeInfo)child); } else if (child is DbgFunctionTypeInfo) { functions.Add((DbgFunctionTypeInfo)child); } else if (child is DbgVTableTypeInfo) { m_vtable = (DbgVTableTypeInfo)child; } else { #if DEBUG string key = Util.Sprintf("{0}+{1}", Util.GetGenericTypeName(child), child.SymTag); if (sm_unhandledTypes.Add(key)) { LogManager.Trace("Need to handle children of type {0} ({1}, parent {2}, id {3}).", Util.GetGenericTypeName(child), child.SymTag, TypeId, child.TypeId); } #endif } } m_children = children.AsReadOnly(); members.Freeze(); statics.Freeze(); bases.Freeze(); virtBases.Freeze(); nestedTypes.Freeze(); nestedEnums.Freeze(); typedefs.Freeze(); functions.Freeze(); m_members = members; m_staticMembers = statics; m_baseClasses = bases; m_virtBaseClasses = virtBases; m_nestedTypes = nestedTypes; m_nestedEnums = nestedEnums; m_typedefs = typedefs; m_functions = functions; } // end _PopulateMembers()
private static void _GenerateSyntheticTypeToMatchDbgEngGeneratedType(string localSymName, DbgEngDebugger debugger, DEBUG_SYMBOL_ENTRY dse) { if (dse.Tag != SymTag.PointerType) { LogManager.Trace("It's a dbgeng-generated type that isn't a pointer! It's a {0} (id 0x{1:x}).", dse.Tag, dse.TypeId); return; } if (DbgHelp.PeekSyntheticTypeExists(debugger.DebuggerInterface, dse.ModuleBase, dse.TypeId)) { return; } // We'll run a command like this: // // dv /t "varname" // // And here's some sample output: // // struct Microsoft::CoreUI::Support::BufferInfo * message = 0x0000006f`81edd570 // string output = String.Empty; using (debugger.HandleDbgEngOutput( (x) => { x = x.Trim(); if (!String.IsNullOrEmpty(x)) { Util.Assert(String.IsNullOrEmpty(output)); output = x; } })) { debugger.InvokeDbgEngCommand(Util.Sprintf("dv /t \"{0}\"", localSymName), DEBUG_OUTCTL.THIS_CLIENT); } int matchCount = 0; foreach (Match match in sm_vartypeRegex.Matches(output)) { matchCount++; string typename = match.Groups["typename"].Value; // Console.WriteLine( "output: {0}", output ); // Console.WriteLine( "typename: {0}", typename ); // Console.WriteLine( "varname: {0}", match.Groups[ "varname" ].Value ); LogManager.Trace("DbgEng-generated type is a pointer, pointing to type: {0}", typename); var mod = debugger.GetModuleByAddress(dse.ModuleBase); DbgTypeInfo ti = debugger.GetTypeInfoByName(mod.Name + "!" + typename).FirstOrDefault(); if (null != ti) { Util.Assert(ti is DbgNamedTypeInfo); var nti = ti as DbgNamedTypeInfo; Util.Assert(nti.Module.BaseAddress == dse.ModuleBase); // We don't need to TryGetSynthPointerTypeIdByPointeeTypeId, because // we already know it's not there (because we did // PeekSyntheticTypeExists earlier). DbgHelp.AddSyntheticPointerTypeInfo(debugger.DebuggerInterface, nti.Module.BaseAddress, nti.TypeId, //debugger.TargetIs32Bit ? 4UL : 8UL, dse.Size, dse.TypeId); } // end if( we found the pointee type ) else { LogManager.Trace("(but we couldn't find the type!)"); } } // end foreach( match ) Util.Assert(matchCount <= 1); if (0 == matchCount) { LogManager.Trace("Failed to parse out type name from: {0}", output); } } // end _GenerateSyntheticTypeToMatchDbgEngGeneratedType()