-
Notifications
You must be signed in to change notification settings - Fork 47
Expand file tree
/
Copy pathSymWriterMetadataAdapter.cs
More file actions
145 lines (125 loc) · 5.08 KB
/
SymWriterMetadataAdapter.cs
File metadata and controls
145 lines (125 loc) · 5.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// 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;
}
}
}