Browse Source

Starting support for multiple AppDomains.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2920 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 18 years ago
parent
commit
ac21176214
  1. 4
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs
  2. 35
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType-Helpers.cs
  3. 37
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs
  4. 23
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/MethodInfo.cs
  5. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.Object.cs
  6. 5
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs

4
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs

@ -170,9 +170,9 @@ namespace Debugger
#region Convenience methods #region Convenience methods
/// <summary> Synchronously calls a function and returns its return value </summary> /// <summary> Synchronously calls a function and returns its return value </summary>
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 #endregion

35
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType-Helpers.cs

@ -55,6 +55,11 @@ namespace Debugger.MetaData
return QueryMembers<T>(bindingFlags, null, null); return QueryMembers<T>(bindingFlags, null, null);
} }
List<T> QueryMembers<T>(string name) where T:MemberInfo
{
return QueryMembers<T>(BindingFlags.All, name, null);
}
T QueryMember<T>(string name) where T:MemberInfo T QueryMember<T>(string name) where T:MemberInfo
{ {
List<T> result = QueryMembers<T>(BindingFlags.All, name, null); List<T> result = QueryMembers<T>(BindingFlags.All, name, null);
@ -145,6 +150,18 @@ namespace Debugger.MetaData
return QueryMembers<MemberInfo>(BindingFlags.Public); return QueryMembers<MemberInfo>(BindingFlags.Public);
} }
/// <summary> Return all members with the given name.</summary>
public IList<MemberInfo> GetMembers(string name)
{
return QueryMembers<MemberInfo>(name);
}
/// <summary> Return all members satisfing binding flags.</summary>
public IList<MemberInfo> GetMembers(string name, BindingFlags bindingFlags)
{
return QueryMembers<MemberInfo>(bindingFlags, name, null);
}
/// <summary> Return all members satisfing binding flags.</summary> /// <summary> Return all members satisfing binding flags.</summary>
public IList<MemberInfo> GetMembers(BindingFlags bindingFlags) public IList<MemberInfo> GetMembers(BindingFlags bindingFlags)
{ {
@ -182,6 +199,12 @@ namespace Debugger.MetaData
return QueryMember<FieldInfo>(name); return QueryMember<FieldInfo>(name);
} }
/// <summary> Return fields with the given name</summary>
public IList<FieldInfo> GetFields(string name)
{
return QueryMembers<FieldInfo>(name);
}
/// <summary> Return first field with the given token</summary> /// <summary> Return first field with the given token</summary>
public FieldInfo GetField(uint token) public FieldInfo GetField(uint token)
{ {
@ -207,6 +230,12 @@ namespace Debugger.MetaData
return QueryMember<MethodInfo>(name); return QueryMember<MethodInfo>(name);
} }
/// <summary> Return methods with the given name</summary>
public IList<MethodInfo> GetMethods(string name)
{
return QueryMembers<MethodInfo>(name);
}
/// <summary> Return first method with the given token</summary> /// <summary> Return first method with the given token</summary>
public MethodInfo GetMethod(uint token) public MethodInfo GetMethod(uint token)
{ {
@ -232,6 +261,12 @@ namespace Debugger.MetaData
return QueryMember<PropertyInfo>(name); return QueryMember<PropertyInfo>(name);
} }
/// <summary> Return propertyies with the given name</summary>
public IList<PropertyInfo> GetProperties(string name)
{
return QueryMembers<PropertyInfo>(name);
}
/// <summary> Return first property with the given token</summary> /// <summary> Return first property with the given token</summary>
public PropertyInfo GetProperty(uint token) public PropertyInfo GetProperty(uint token)
{ {

37
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. /// Represents a type in a debugee. That is, a class, array, value type or a primitive type.
/// This class mimics the <see cref="System.Type"/> class. /// This class mimics the <see cref="System.Type"/> class.
/// </summary> /// </summary>
/// <remarks> If two types are identical, the references to DebugType will also be identical </remarks> /// <remarks>
/// If two types are identical, the references to DebugType will also be identical
/// Type will be loaded once per each appdomain.
/// </remarks>
public partial class DebugType: DebuggerObject public partial class DebugType: DebuggerObject
{ {
Process process; 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;
}
}
}
/// <summary> /// <summary>
/// Gets the type from which this type inherits. /// Gets the type from which this type inherits.
/// <para> /// <para>
@ -219,11 +232,11 @@ namespace Debugger.MetaData
get { get {
// corType.Base does not work for arrays // corType.Base does not work for arrays
if (this.IsArray) { 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 // corType.Base does not work for primitive types
if (this.IsPrimitive) { if (this.IsPrimitive) {
return DebugType.GetType(this.Process, "System.Object"); return DebugType.GetType(this.Process, AppDomainID, "System.Object");
} }
ICorDebugType baseType = corType.Base; ICorDebugType baseType = corType.Base;
if (baseType != null) { if (baseType != null) {
@ -429,9 +442,7 @@ namespace Debugger.MetaData
} }
if (this.IsClass || this.IsValueType) { if (this.IsClass || this.IsValueType) {
return (other.IsClass || other.IsValueType) && return (other.IsClass || other.IsValueType) &&
// Test fullpath since module can be loaded multiple times to different appdomains other.Module == this.Module &&
// eg during unit testing
other.Module.FullPath == this.Module.FullPath &&
other.MetadataToken == this.MetadataToken; other.MetadataToken == this.MetadataToken;
} }
throw new DebuggerException("Unknown type"); 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) { foreach(Module module in process.Modules) {
try { if (!domainID.HasValue || domainID == module.CorModule.Assembly.AppDomain.ID) {
uint token = module.MetaData.FindTypeDefByName(fullTypeName, 0).Token; try {
return Create(process, module.CorModule.GetClassFromToken(token)); uint token = module.MetaData.FindTypeDefByName(fullTypeName, 0 /* enclosing class for nested */).Token;
} catch { return Create(process, module.CorModule.GetClassFromToken(token));
continue; } catch {
continue;
}
} }
} }
return null; return null;

23
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/MethodInfo.cs

@ -163,26 +163,23 @@ namespace Debugger.MetaData
/// <summary> /// <summary>
/// Get a method from a managed type, method name and argument count /// Get a method from a managed type, method name and argument count
/// </summary> /// </summary>
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.IsNested) throw new DebuggerException("Not implemented for nested types");
if (type.IsGenericType) throw new DebuggerException("Not implemented for generic types"); if (type.IsGenericType) throw new DebuggerException("Not implemented for generic types");
if (type.IsGenericParameter) throw new DebuggerException("Type can not be generic parameter"); if (type.IsGenericParameter) throw new DebuggerException("Type can not be generic parameter");
foreach(Module module in process.Modules) { DebugType debugType = DebugType.GetType(process, domainID, type.FullName);
TypeDefProps typeDefProps = module.MetaData.FindTypeDefByName(type.FullName, 0 /* enclosing class for nested */); if (debugType == null) {
foreach(MethodProps methodProps in module.MetaData.EnumMethodsWithName(typeDefProps.Token, name)) { throw new DebuggerException("Type " + type.FullName + " not found");
if (module.MetaData.GetParamCount(methodProps.Token) == paramCount) { }
ICorDebugFunction corFunction = module.CorModule.GetFunctionFromToken(methodProps.Token);
ICorDebugClass2 corClass = corFunction.Class.As<ICorDebugClass2>(); foreach(MethodInfo methodInfo in debugType.GetMethods(methodName)) {
ICorDebugType corType = corClass.GetParameterizedType(type.IsValueType ? (uint)CorElementType.VALUETYPE : (uint)CorElementType.CLASS, if (methodInfo.ParameterCount == paramCount) {
0, return methodInfo;
new ICorDebugType[] {});
return DebugType.Create(process, corType).GetMethod(methodProps.Token);
}
} }
} }
throw new DebuggerException("Not found"); throw new DebuggerException("Method " + methodName + " not found");
} }
internal ISymUnmanagedMethod SymMethod { internal ISymUnmanagedMethod SymMethod {

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.Object.cs

@ -238,7 +238,7 @@ namespace Debugger
{ {
if (IsPrimitive) return AsString; if (IsPrimitive) return AsString;
// if (!IsObject) // Can invoke on primitives // 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 #region Convenience overload methods

5
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs

@ -132,9 +132,10 @@ namespace Debugger
this.rawCorValue_pauseSession = process.PauseSession; this.rawCorValue_pauseSession = process.PauseSession;
if (this.CorValue == null) { if (this.CorValue == null) {
type = DebugType.GetType(this.Process, "System.Object"); type = DebugType.GetType(this.Process, null, "System.Object");
} else { } else {
type = DebugType.Create(process, this.CorValue.CastTo<ICorDebugValue2>().ExactType); ICorDebugType exactType = this.CorValue.CastTo<ICorDebugValue2>().ExactType;
type = DebugType.Create(this.Process, exactType);
} }
} }

Loading…
Cancel
Save