public void Add(DmdType type) { if (recursionCounter > 100) { return; } recursionCounter++; while (type.GetElementType() is DmdType etype) { type = etype; } switch (type.TypeSignatureKind) { case DmdTypeSignatureKind.Type: modules.Add(type.Module); break; case DmdTypeSignatureKind.Pointer: case DmdTypeSignatureKind.ByRef: case DmdTypeSignatureKind.TypeGenericParameter: case DmdTypeSignatureKind.MethodGenericParameter: case DmdTypeSignatureKind.SZArray: case DmdTypeSignatureKind.MDArray: break; case DmdTypeSignatureKind.GenericInstance: modules.Add(type.GetGenericTypeDefinition().Module); foreach (var ga in type.GetGenericArguments()) { Add(ga); } break; case DmdTypeSignatureKind.FunctionPointer: var sig = type.GetFunctionPointerMethodSignature(); Add(sig.ReturnType); foreach (var t in sig.GetParameterTypes()) { Add(t); } foreach (var t in sig.GetVarArgsParameterTypes()) { Add(t); } break; default: Debug.Fail($"Unknown kind: {type.TypeSignatureKind}"); break; } recursionCounter--; }
void FormatReturnType(DmdType type, bool isReadOnly) { if (type.IsByRef && isReadOnly) { type = type.GetElementType(); OutputWrite(Keyword_ref, BoxedTextColor.Keyword); WriteSpace(); OutputWrite(Keyword_readonly, BoxedTextColor.Keyword); WriteSpace(); } FormatType(type); }
DbgDotNetValueNode CreateValue(DbgEvaluationInfo evalInfo, DbgDotNetText name, DbgDotNetValue value, ReadOnlyCollection <string>?formatSpecifiers, DbgValueNodeEvaluationOptions options, string expression, string imageName, bool isReadOnly, bool causesSideEffects, DmdType expectedType, bool isRootExpression, ColumnFormatter?columnFormatter) { // Could be a by-ref property, local, or parameter. if (expectedType.IsByRef) { if (value.Type.IsByRef) { var newValue = value.LoadIndirect(); value.Dispose(); if (newValue.HasError) { return(CreateError(evalInfo, name, newValue.ErrorMessage !, expression, causesSideEffects)); } value = newValue.Value !; } expectedType = expectedType.GetElementType() !; } options = PredefinedFormatSpecifiers.GetValueNodeEvaluationOptions(formatSpecifiers, options); var nodeInfo = new DbgDotNetValueNodeInfo(value, expression); bool addParens = isRootExpression && NeedsParentheses(expression); DbgDotNetValueNodeProviderResult info; bool useProvider = false; var specialViewOptions = (options & ~(DbgValueNodeEvaluationOptions.ResultsView | DbgValueNodeEvaluationOptions.DynamicView)); if ((options & DbgValueNodeEvaluationOptions.ResultsView) != 0) { info = valueNodeProviderFactory.CreateResultsView(evalInfo, addParens, expectedType, nodeInfo, specialViewOptions); useProvider = !(info.ErrorMessage is null); } else if ((options & DbgValueNodeEvaluationOptions.DynamicView) != 0) { info = valueNodeProviderFactory.CreateDynamicView(evalInfo, addParens, expectedType, nodeInfo, specialViewOptions); useProvider = true; } else { info = valueNodeProviderFactory.Create(evalInfo, addParens, expectedType, nodeInfo, options); } if (useProvider) { if (!(info.ErrorMessage is null)) { return(new DbgDotNetValueNodeImpl(this, info.Provider, name, nodeInfo, expression, PredefinedDbgValueNodeImageNames.Error, true, false, null, null, info.ErrorMessage, new DbgDotNetText(new DbgDotNetTextPart(DbgTextColor.Error, info.ErrorMessage)), formatSpecifiers, columnFormatter)); } Debug2.Assert(!(info.Provider is null)); return(new DbgDotNetValueNodeImpl(this, info.Provider, name, nodeInfo, expression, info.Provider?.ImageName ?? imageName, true, false, null, null, info.ErrorMessage, info.Provider?.ValueText ?? default, formatSpecifiers, columnFormatter)); } return(new DbgDotNetValueNodeImpl(this, info.Provider, name, nodeInfo, expression, imageName, isReadOnly, causesSideEffects, expectedType, value.Type, info.ErrorMessage, default, formatSpecifiers, columnFormatter));
DmdCustomAttributeTypedArgument ReadArrayArgument(DmdType arrayType) { if (!arrayType.IsSZArray) throw new ArgumentException(); if (!IncrementRecursionCounter()) throw new CABlobParserException("Stack overflow"); object argValue; int arrayCount = reader.ReadInt32(); if (arrayCount == -1)// -1 if it's null argValue = null; else if (arrayCount < 0) throw new CABlobParserException("Array is too big"); else { var array = new DmdCustomAttributeTypedArgument[arrayCount]; var elemType = FixTypeSig(arrayType.GetElementType()); for (int i = 0; i < array.Length; i++) array[i] = ReadFixedArg(elemType); argValue = ReadOnlyCollectionHelpers.Create(array); } DecrementRecursionCounter(); return new DmdCustomAttributeTypedArgument(arrayType, argValue); }
public CorType Create(DmdType type) { if ((object)type == null) { throw new ArgumentNullException(nameof(type)); } if (recursionCounter++ > 100) { throw new InvalidOperationException(); } CorType result; int i; ReadOnlyCollection <DmdType> types; CorType[] corTypes; DnModule dnModule; switch (type.TypeSignatureKind) { case DmdTypeSignatureKind.Type: if (!engine.TryGetDnModule(type.Module.GetDebuggerModule() ?? throw new InvalidOperationException(), out dnModule)) { throw new InvalidOperationException(); } Debug.Assert((type.MetadataToken >> 24) == 0x02); result = dnModule.CorModule.GetClassFromToken((uint)type.MetadataToken).GetParameterizedType(type.IsValueType ? CorElementType.ValueType : CorElementType.Class); break; case DmdTypeSignatureKind.Pointer: result = Create(type.GetElementType()); result = appDomain.GetPtr(result); break; case DmdTypeSignatureKind.ByRef: result = Create(type.GetElementType()); result = appDomain.GetByRef(result); break; case DmdTypeSignatureKind.TypeGenericParameter: case DmdTypeSignatureKind.MethodGenericParameter: throw new InvalidOperationException(); case DmdTypeSignatureKind.SZArray: result = Create(type.GetElementType()); result = appDomain.GetSZArray(result); break; case DmdTypeSignatureKind.MDArray: result = Create(type.GetElementType()); result = appDomain.GetArray(result, (uint)type.GetArrayRank()); break; case DmdTypeSignatureKind.GenericInstance: result = Create(type.GetGenericTypeDefinition()); types = type.GetGenericArguments(); corTypes = new CorType[types.Count]; for (i = 0; i < corTypes.Length; i++) { corTypes[i] = Create(types[i]); } result = result.Class.GetParameterizedType(type.IsValueType ? CorElementType.ValueType : CorElementType.Class, corTypes); break; case DmdTypeSignatureKind.FunctionPointer: var methodSig = type.GetFunctionPointerMethodSignature(); types = methodSig.GetParameterTypes(); corTypes = new CorType[1 + types.Count + methodSig.GetVarArgsParameterTypes().Count]; corTypes[0] = Create(methodSig.ReturnType); for (i = 0; i < types.Count; i++) { corTypes[i + 1] = Create(types[i]); } types = methodSig.GetVarArgsParameterTypes(); for (i = 0; i < types.Count; i++) { corTypes[i + 1 + methodSig.GetParameterTypes().Count] = Create(types[i]); } result = appDomain.GetFnPtr(corTypes); break; default: throw new InvalidOperationException(); } if (result == null) { throw new InvalidOperationException(); } recursionCounter--; return(result); }
public void Format(DmdType type, DbgDotNetValue value) { if ((object)type == null) { throw new ArgumentNullException(nameof(type)); } List <(DmdType type, DbgDotNetValue value)> arrayTypesList = null; try { if (recursionCounter++ >= MAX_RECURSION) { return; } switch (type.TypeSignatureKind) { case DmdTypeSignatureKind.SZArray: case DmdTypeSignatureKind.MDArray: // Array types are shown in reverse order arrayTypesList = new List <(DmdType type, DbgDotNetValue value)>(); do { arrayTypesList.Add((type, arrayTypesList.Count == 0 ? value : null)); type = type.GetElementType(); } while (type.IsArray); var t = arrayTypesList[arrayTypesList.Count - 1]; Format(t.type.GetElementType(), null); foreach (var tuple in arrayTypesList) { var aryType = tuple.type; var aryValue = tuple.value; uint elementCount; if (aryType.IsVariableBoundArray) { OutputWrite(ARRAY_OPEN_PAREN, BoxedTextColor.Punctuation); int rank = Math.Min(aryType.GetArrayRank(), MAX_ARRAY_RANK); if (rank <= 0) { OutputWrite("???", BoxedTextColor.Error); } else { if (rank == 1) { OutputWrite("*", BoxedTextColor.Operator); } if (aryValue == null || aryValue.IsNull || !aryValue.GetArrayInfo(out elementCount, out var dimensionInfos)) { dimensionInfos = null; } if (ShowArrayValueSizes && dimensionInfos != null && dimensionInfos.Length == rank) { for (int i = 0; i < rank; i++) { if (i > 0) { OutputWrite(",", BoxedTextColor.Punctuation); WriteSpace(); } if (dimensionInfos[i].BaseIndex == 0) { WriteUInt32(dimensionInfos[i].Length); } else { WriteInt32(dimensionInfos[i].BaseIndex); OutputWrite("..", BoxedTextColor.Operator); WriteInt32(dimensionInfos[i].BaseIndex + (int)dimensionInfos[i].Length - 1); } } } else { OutputWrite(TypeFormatterUtils.GetArrayCommas(rank), BoxedTextColor.Punctuation); } } OutputWrite(ARRAY_CLOSE_PAREN, BoxedTextColor.Punctuation); } else { Debug.Assert(aryType.IsSZArray); OutputWrite(ARRAY_OPEN_PAREN, BoxedTextColor.Punctuation); if (ShowArrayValueSizes && aryValue != null && !aryValue.IsNull) { if (aryValue.GetArrayCount(out elementCount)) { WriteUInt32(elementCount); } } OutputWrite(ARRAY_CLOSE_PAREN, BoxedTextColor.Punctuation); } } break; case DmdTypeSignatureKind.Pointer: Format(type.GetElementType(), null); OutputWrite("*", BoxedTextColor.Operator); break; case DmdTypeSignatureKind.ByRef: OutputWrite(BYREF_KEYWORD, BoxedTextColor.Keyword); WriteSpace(); Format(type.GetElementType(), value?.LoadIndirect()); break; case DmdTypeSignatureKind.TypeGenericParameter: WriteIdentifier(type.MetadataName, BoxedTextColor.TypeGenericParameter); break; case DmdTypeSignatureKind.MethodGenericParameter: WriteIdentifier(type.MetadataName, BoxedTextColor.MethodGenericParameter); break; case DmdTypeSignatureKind.Type: case DmdTypeSignatureKind.GenericInstance: if (type.IsNullable) { Format(type.GetNullableElementType(), null); OutputWrite("?", BoxedTextColor.Operator); } else if (TypeFormatterUtils.IsTupleType(type)) { OutputWrite(TUPLE_OPEN_PAREN, BoxedTextColor.Punctuation); var tupleType = type; int tupleIndex = 0; for (;;) { tupleType = WriteTupleFields(tupleType, ref tupleIndex); if ((object)tupleType != null) { WriteCommaSpace(); } else { break; } } OutputWrite(TUPLE_CLOSE_PAREN, BoxedTextColor.Punctuation); } else { var genericArgs = type.GetGenericArguments(); int genericArgsIndex = 0; KeywordType keywordType; if ((object)type.DeclaringType == null) { keywordType = GetKeywordType(type); if (keywordType == KeywordType.NoKeyword) { WriteNamespace(type); } WriteTypeName(type, keywordType); WriteGenericArguments(type, genericArgs, ref genericArgsIndex); } else { var typesList = new List <DmdType>(); typesList.Add(type); while (type.DeclaringType != null) { type = type.DeclaringType; typesList.Add(type); } keywordType = GetKeywordType(type); if (keywordType == KeywordType.NoKeyword) { WriteNamespace(type); } for (int i = typesList.Count - 1; i >= 0; i--) { WriteTypeName(typesList[i], i == 0 ? keywordType : KeywordType.NoKeyword); WriteGenericArguments(typesList[i], genericArgs, ref genericArgsIndex); if (i != 0) { OutputWrite(".", BoxedTextColor.Operator); } } } } break; case DmdTypeSignatureKind.FunctionPointer: //TODO: OutputWrite("fnptr", BoxedTextColor.Keyword); break; default: throw new InvalidOperationException(); } } finally { recursionCounter--; if (arrayTypesList != null) { foreach (var info in arrayTypesList) { if (info.value != value) { info.value?.Dispose(); } } } } }
public void Format(DmdType type, DbgDotNetValue?value) { if (type is null) { throw new ArgumentNullException(nameof(type)); } List <(DmdType type, DbgDotNetValue?value)>?arrayTypesList = null; DbgDotNetValue?disposeThisValue = null; try { if (recursionCounter++ >= MAX_RECURSION) { return; } switch (type.TypeSignatureKind) { case DmdTypeSignatureKind.SZArray: case DmdTypeSignatureKind.MDArray: // Array types are shown in reverse order arrayTypesList = new List <(DmdType type, DbgDotNetValue?value)>(); do { arrayTypesList.Add((type, arrayTypesList.Count == 0 ? value : null)); type = type.GetElementType() !; } while (type.IsArray); var t = arrayTypesList[arrayTypesList.Count - 1]; Format(t.type.GetElementType() !, null); foreach (var tuple in arrayTypesList) { var aryType = tuple.type; var aryValue = tuple.value; uint elementCount; if (aryType.IsVariableBoundArray) { OutputWrite(ARRAY_OPEN_PAREN, DbgTextColor.Punctuation); int rank = Math.Min(aryType.GetArrayRank(), MAX_ARRAY_RANK); if (rank <= 0) { OutputWrite("???", DbgTextColor.Error); } else { if (aryValue is null || aryValue.IsNull || !aryValue.GetArrayInfo(out elementCount, out var dimensionInfos)) { dimensionInfos = null; } if (ShowArrayValueSizes && dimensionInfos is not null && dimensionInfos.Length == rank) { for (int i = 0; i < rank; i++) { if (i > 0) { OutputWrite(",", DbgTextColor.Punctuation); WriteSpace(); } if (dimensionInfos[i].BaseIndex == 0) { WriteUInt32(dimensionInfos[i].Length); } else { WriteInt32(dimensionInfos[i].BaseIndex); OutputWrite("..", DbgTextColor.Operator); WriteInt32(dimensionInfos[i].BaseIndex + (int)dimensionInfos[i].Length - 1); } } } else { if (rank == 1) { OutputWrite("*", DbgTextColor.Operator); } OutputWrite(TypeFormatterUtils.GetArrayCommas(rank), DbgTextColor.Punctuation); } } OutputWrite(ARRAY_CLOSE_PAREN, DbgTextColor.Punctuation); } else { Debug.Assert(aryType.IsSZArray); OutputWrite(ARRAY_OPEN_PAREN, DbgTextColor.Punctuation); if (ShowArrayValueSizes && aryValue is not null && !aryValue.IsNull) { if (aryValue.GetArrayCount(out elementCount)) { WriteUInt32(elementCount); } } OutputWrite(ARRAY_CLOSE_PAREN, DbgTextColor.Punctuation); } }
(TypeMirror type, bool containsGenericParameters) Create(DmdType type) { if ((object)type == null) { throw new ArgumentNullException(nameof(type)); } if (typeCache.TryGetType(type, out var cachedType)) { return(cachedType, false); } if (recursionCounter++ > 100) { throw new InvalidOperationException(); } (TypeMirror type, bool containsGenericParameters)result; bool addType = true; switch (type.TypeSignatureKind) { case DmdTypeSignatureKind.Type: if (!engine.TryGetMonoModule(type.Module.GetDebuggerModule() ?? throw new InvalidOperationException(), out var monoModule)) { throw new InvalidOperationException(); } Debug.Assert((type.MetadataToken >> 24) == 0x02); //TODO: This can sometimes crash Unity's old mono fork //TODO: It's possible to resolve types, but it's an internal method and it requires a method in the module result = (monoModule.Assembly.GetType(type.FullName, false, false), false); if (result.type == null) { throw new InvalidOperationException(); } if (result.type.MetadataToken != type.MetadataToken) { throw new InvalidOperationException(); } break; case DmdTypeSignatureKind.Pointer: result = Create(type.GetElementType()); result = (TryResolveType(result.type, type), result.containsGenericParameters); if (result.type == null) { throw new InvalidOperationException(); } if (!result.type.IsPointer) { throw new InvalidOperationException(); } break; case DmdTypeSignatureKind.ByRef: result = Create(type.GetElementType()); result = (TryResolveType(result.type, type), result.containsGenericParameters); if (result.type == null) { throw new InvalidOperationException(); } // This currently always fails //TODO: We could func-eval MakeByRefType() if (!result.type.IsByRef) { throw new InvalidOperationException(); } break; case DmdTypeSignatureKind.TypeGenericParameter: case DmdTypeSignatureKind.MethodGenericParameter: result = (Create(type.AppDomain.System_Object).type, true); addType = false; break; case DmdTypeSignatureKind.SZArray: result = Create(type.GetElementType()); result = (TryResolveType(result.type, type), result.containsGenericParameters); if (result.type == null) { throw new InvalidOperationException(); } if (!result.type.IsArray || result.type.GetArrayRank() != 1 || !result.type.FullName.EndsWith("[]", StringComparison.Ordinal)) { throw new InvalidOperationException(); } break; case DmdTypeSignatureKind.MDArray: result = Create(type.GetElementType()); result = (TryResolveType(result.type, type), result.containsGenericParameters); if (result.type == null) { throw new InvalidOperationException(); } if (!result.type.IsArray || (result.type.GetArrayRank() == 1 && result.type.FullName.EndsWith("[]", StringComparison.Ordinal))) { throw new InvalidOperationException(); } break; case DmdTypeSignatureKind.GenericInstance: result = Create(type.GetGenericTypeDefinition()); result = (TryResolveType(result.type, type), result.containsGenericParameters); if (result.type == null) { throw new InvalidOperationException(); } // This fails on Unity (version < 2.12), since it doesn't have that info available //if (!result.type.IsGenericType) // throw new InvalidOperationException(); break; case DmdTypeSignatureKind.FunctionPointer: // It's not possible to create function pointers, so use a pointer type instead result = Create(type.AppDomain.System_Void.MakePointerType()); addType = false; break; default: throw new InvalidOperationException(); } if (result.type == null) { throw new InvalidOperationException(); } if (addType && !result.containsGenericParameters) { typeCache.Add(result.type, type); } recursionCounter--; return(result); }