| File: Metadata\SymWriterMetadataAdapter.cs | Web Access |
| Project: src\symreader\src\Microsoft.DiaSymReader\Microsoft.DiaSymReader.csproj (Microsoft.DiaSymReader) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the License.txt file in the project root for more information. using System; using System.Runtime.InteropServices; using System.Reflection; using System.Diagnostics; #if NET9_0_OR_GREATER using System.Runtime.InteropServices.Marshalling; #endif namespace Microsoft.DiaSymReader { /// <summary> /// Minimal implementation of IMetadataImport that implements APIs used by SymReader and SymWriter. /// </summary> #if NET9_0_OR_GREATER [GeneratedComClass] #endif internal unsafe sealed partial class SymWriterMetadataAdapter : MetadataAdapterBase { private readonly ISymWriterMetadataProvider _metadataProvider; public SymWriterMetadataAdapter(ISymWriterMetadataProvider metadataProvider) { Debug.Assert(metadataProvider != null); _metadataProvider = metadataProvider; } public override int GetTokenFromSig(byte* voidPointerSig, int byteCountSig) { // Only used when building constant signature. // We trick SymWriter into embedding NIL token into the PDB if // we don't have a real signature token matching the constant type. return 0x11000000; } public override int GetTypeDefProps( int typeDef, [Out]char* qualifiedName, int qualifiedNameBufferLength, [Out]int* qualifiedNameLength, [Out]TypeAttributes* attributes, [Out]int* baseType) { Debug.Assert(baseType == null); if (!_metadataProvider.TryGetTypeDefinitionInfo(typeDef, out var namespaceName, out var typeName, out var attrib)) { return HResult.E_INVALIDARG; } if (qualifiedNameLength != null || qualifiedName != null) { InteropUtilities.CopyQualifiedTypeName( qualifiedName, qualifiedNameBufferLength, qualifiedNameLength, namespaceName, typeName); } if (attributes != null) { *attributes = attrib; } return HResult.S_OK; } public override int GetTypeRefProps( int typeRef, [Out]int* resolutionScope, // ModuleRef or AssemblyRef [Out]char* qualifiedName, int qualifiedNameBufferLength, [Out]int* qualifiedNameLength) => throw new NotImplementedException(); public override int GetNestedClassProps(int nestedClass, out int enclosingClass) { return _metadataProvider.TryGetEnclosingType(nestedClass, out enclosingClass) ? HResult.S_OK : HResult.E_FAIL; } // The only purpose of this method is to get type name of the method and declaring type token (opaque for SymWriter), everything else is ignored by the SymWriter. // "mb" is the token passed to OpenMethod. The token is remembered until the corresponding CloseMethod, which passes it to GetMethodProps. // It's opaque for SymWriter. public override int GetMethodProps( int methodDef, [Out] int* declaringTypeDef, [Out] char* name, int nameBufferLength, [Out] int* nameLength, [Out] MethodAttributes* attributes, [Out] byte** signature, [Out] int* signatureLength, [Out] int* relativeVirtualAddress, [Out] MethodImplAttributes* implAttributes) { Debug.Assert(attributes == null); Debug.Assert(signature == null); Debug.Assert(signatureLength == null); Debug.Assert(relativeVirtualAddress == null); Debug.Assert(implAttributes == null); if (!_metadataProvider.TryGetMethodInfo(methodDef, out var nameStr, out var declaringTypeToken)) { return HResult.E_INVALIDARG; } if (name != null || nameLength != null) { // if the buffer is too small to fit the name, truncate the name. // -1 to account for a NUL terminator. int adjustedLength = Math.Min(nameStr.Length, nameBufferLength - 1); if (nameLength != null) { // return the length of the possibly truncated name not including NUL *nameLength = adjustedLength; } if (name != null && nameBufferLength > 0) { char* dst = name; for (int i = 0; i < adjustedLength; i++) { *dst = nameStr[i]; dst++; } *dst = '\0'; } } if (declaringTypeDef != null) { *declaringTypeDef = declaringTypeToken; } return HResult.S_OK; } } }