diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs index 0c3e15d465..b995baf9ee 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs @@ -170,9 +170,9 @@ namespace Debugger #region Convenience methods /// Synchronously calls a function and returns its return value - public static Value InvokeMethod(Process process, System.Type type, string name, Value thisValue, Value[] args) + public static Value InvokeMethod(Process process, uint? domainID, System.Type type, string name, Value thisValue, Value[] args) { - return InvokeMethod(MethodInfo.GetFromName(process, type, name, args.Length), thisValue, args); + return InvokeMethod(MethodInfo.GetFromName(process, domainID, type, name, args.Length), thisValue, args); } #endregion diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType-Helpers.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType-Helpers.cs index 99db1d44c4..7186301d04 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType-Helpers.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType-Helpers.cs @@ -55,6 +55,11 @@ namespace Debugger.MetaData return QueryMembers(bindingFlags, null, null); } + List QueryMembers(string name) where T:MemberInfo + { + return QueryMembers(BindingFlags.All, name, null); + } + T QueryMember(string name) where T:MemberInfo { List result = QueryMembers(BindingFlags.All, name, null); @@ -145,6 +150,18 @@ namespace Debugger.MetaData return QueryMembers(BindingFlags.Public); } + /// Return all members with the given name. + public IList GetMembers(string name) + { + return QueryMembers(name); + } + + /// Return all members satisfing binding flags. + public IList GetMembers(string name, BindingFlags bindingFlags) + { + return QueryMembers(bindingFlags, name, null); + } + /// Return all members satisfing binding flags. public IList GetMembers(BindingFlags bindingFlags) { @@ -182,6 +199,12 @@ namespace Debugger.MetaData return QueryMember(name); } + /// Return fields with the given name + public IList GetFields(string name) + { + return QueryMembers(name); + } + /// Return first field with the given token public FieldInfo GetField(uint token) { @@ -207,6 +230,12 @@ namespace Debugger.MetaData return QueryMember(name); } + /// Return methods with the given name + public IList GetMethods(string name) + { + return QueryMembers(name); + } + /// Return first method with the given token public MethodInfo GetMethod(uint token) { @@ -232,6 +261,12 @@ namespace Debugger.MetaData return QueryMember(name); } + /// Return propertyies with the given name + public IList GetProperties(string name) + { + return QueryMembers(name); + } + /// Return first property with the given token public PropertyInfo GetProperty(uint token) { diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs index fbf62675a2..03e3872f32 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs @@ -16,7 +16,10 @@ namespace Debugger.MetaData /// Represents a type in a debugee. That is, a class, array, value type or a primitive type. /// This class mimics the class. /// - /// If two types are identical, the references to DebugType will also be identical + /// + /// If two types are identical, the references to DebugType will also be identical + /// Type will be loaded once per each appdomain. + /// public partial class DebugType: DebuggerObject { Process process; @@ -209,6 +212,16 @@ namespace Debugger.MetaData } } + internal uint? AppDomainID { + get { + if (IsClass || IsValueType) { + return this.Module.CorModule.Assembly.AppDomain.ID; + } else { + return null; + } + } + } + /// /// Gets the type from which this type inherits. /// @@ -219,11 +232,11 @@ namespace Debugger.MetaData get { // corType.Base does not work for arrays if (this.IsArray) { - return DebugType.GetType(this.Process, "System.Array"); + return DebugType.GetType(this.Process, AppDomainID, "System.Array"); } // corType.Base does not work for primitive types if (this.IsPrimitive) { - return DebugType.GetType(this.Process, "System.Object"); + return DebugType.GetType(this.Process, AppDomainID, "System.Object"); } ICorDebugType baseType = corType.Base; if (baseType != null) { @@ -429,9 +442,7 @@ namespace Debugger.MetaData } if (this.IsClass || this.IsValueType) { return (other.IsClass || other.IsValueType) && - // Test fullpath since module can be loaded multiple times to different appdomains - // eg during unit testing - other.Module.FullPath == this.Module.FullPath && + other.Module == this.Module && other.MetadataToken == this.MetadataToken; } throw new DebuggerException("Unknown type"); @@ -440,14 +451,16 @@ namespace Debugger.MetaData } } - public static DebugType GetType(Process process, string fullTypeName) + public static DebugType GetType(Process process, uint? domainID, string fullTypeName) { foreach(Module module in process.Modules) { - try { - uint token = module.MetaData.FindTypeDefByName(fullTypeName, 0).Token; - return Create(process, module.CorModule.GetClassFromToken(token)); - } catch { - continue; + if (!domainID.HasValue || domainID == module.CorModule.Assembly.AppDomain.ID) { + try { + uint token = module.MetaData.FindTypeDefByName(fullTypeName, 0 /* enclosing class for nested */).Token; + return Create(process, module.CorModule.GetClassFromToken(token)); + } catch { + continue; + } } } return null; diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/MethodInfo.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/MethodInfo.cs index 95c3343a70..71373c8590 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/MethodInfo.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/MethodInfo.cs @@ -163,26 +163,23 @@ namespace Debugger.MetaData /// /// Get a method from a managed type, method name and argument count /// - public static MethodInfo GetFromName(Process process, System.Type type, string name, int paramCount) + public static MethodInfo GetFromName(Process process, uint? domainID, System.Type type, string methodName, int paramCount) { if (type.IsNested) throw new DebuggerException("Not implemented for nested types"); if (type.IsGenericType) throw new DebuggerException("Not implemented for generic types"); if (type.IsGenericParameter) throw new DebuggerException("Type can not be generic parameter"); - foreach(Module module in process.Modules) { - TypeDefProps typeDefProps = module.MetaData.FindTypeDefByName(type.FullName, 0 /* enclosing class for nested */); - foreach(MethodProps methodProps in module.MetaData.EnumMethodsWithName(typeDefProps.Token, name)) { - if (module.MetaData.GetParamCount(methodProps.Token) == paramCount) { - ICorDebugFunction corFunction = module.CorModule.GetFunctionFromToken(methodProps.Token); - ICorDebugClass2 corClass = corFunction.Class.As(); - ICorDebugType corType = corClass.GetParameterizedType(type.IsValueType ? (uint)CorElementType.VALUETYPE : (uint)CorElementType.CLASS, - 0, - new ICorDebugType[] {}); - return DebugType.Create(process, corType).GetMethod(methodProps.Token); - } + DebugType debugType = DebugType.GetType(process, domainID, type.FullName); + if (debugType == null) { + throw new DebuggerException("Type " + type.FullName + " not found"); + } + + foreach(MethodInfo methodInfo in debugType.GetMethods(methodName)) { + if (methodInfo.ParameterCount == paramCount) { + return methodInfo; } } - throw new DebuggerException("Not found"); + throw new DebuggerException("Method " + methodName + " not found"); } internal ISymUnmanagedMethod SymMethod { diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.Object.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.Object.cs index 3cf2aea35e..727b0af025 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.Object.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.Object.cs @@ -238,7 +238,7 @@ namespace Debugger { if (IsPrimitive) return AsString; // if (!IsObject) // Can invoke on primitives - return Eval.InvokeMethod(Process, typeof(object), "ToString", this, new Value[] {}).AsString; + return Eval.InvokeMethod(Process, this.Type.AppDomainID, typeof(object), "ToString", this, new Value[] {}).AsString; } #region Convenience overload methods diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs index 674ba5700a..b5bbe5fd04 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs @@ -132,9 +132,10 @@ namespace Debugger this.rawCorValue_pauseSession = process.PauseSession; if (this.CorValue == null) { - type = DebugType.GetType(this.Process, "System.Object"); + type = DebugType.GetType(this.Process, null, "System.Object"); } else { - type = DebugType.Create(process, this.CorValue.CastTo().ExactType); + ICorDebugType exactType = this.CorValue.CastTo().ExactType; + type = DebugType.Create(this.Process, exactType); } }