1
+ // Licensed to the.NET Foundation under one or more agreements.
2
+ // The .NET Foundation licenses this file to you under the MIT license.
3
+ // See the LICENSE file in the project root for more information.
4
+
5
+ using System . Collections . Generic ;
6
+ using Mono . Cecil ;
7
+ using Mono . Cecil . Cil ;
8
+ using Mono . Collections . Generic ;
9
+
10
+ namespace Mono . Linker
11
+ {
12
+ struct TypeReferenceMarker
13
+ {
14
+ readonly AssemblyDefinition assembly ;
15
+ readonly MarkingHelpers markingHelpers ;
16
+ HashSet < TypeReference > visited ;
17
+
18
+ public TypeReferenceMarker ( AssemblyDefinition assembly , MarkingHelpers markingHelpers )
19
+ {
20
+ this . assembly = assembly ;
21
+ this . markingHelpers = markingHelpers ;
22
+ visited = null ;
23
+ }
24
+
25
+ // Traverse the assembly and mark the scopes of discovered type references (but not exported types).
26
+ // This includes scopes referenced by Cecil TypeReference objects that don't represent rows in the typeref table,
27
+ // such as references to built-in types, or attribute arguments which encode type references as strings.
28
+ public void Process ( )
29
+ {
30
+ visited = new HashSet < TypeReference > ( ) ;
31
+
32
+ WalkCustomAttributesTypesScopes ( assembly ) ;
33
+ WalkSecurityAttributesTypesScopes ( assembly ) ;
34
+
35
+ foreach ( var module in assembly . Modules )
36
+ WalkCustomAttributesTypesScopes ( module ) ;
37
+
38
+ var mmodule = assembly . MainModule ;
39
+ if ( mmodule . HasTypes ) {
40
+ foreach ( var type in mmodule . Types ) {
41
+ WalkScopes ( type ) ;
42
+ }
43
+ }
44
+
45
+ visited = null ;
46
+ }
47
+
48
+ void WalkScopes ( TypeDefinition typeDefinition )
49
+ {
50
+ WalkCustomAttributesTypesScopes ( typeDefinition ) ;
51
+ WalkSecurityAttributesTypesScopes ( typeDefinition ) ;
52
+
53
+ if ( typeDefinition . BaseType != null )
54
+ WalkScopeOfTypeReference ( typeDefinition . BaseType ) ;
55
+
56
+ if ( typeDefinition . HasInterfaces ) {
57
+ foreach ( var iface in typeDefinition . Interfaces ) {
58
+ WalkCustomAttributesTypesScopes ( iface ) ;
59
+ WalkScopeOfTypeReference ( iface . InterfaceType ) ;
60
+ }
61
+ }
62
+
63
+ if ( typeDefinition . HasGenericParameters )
64
+ WalkTypeScope ( typeDefinition . GenericParameters ) ;
65
+
66
+ if ( typeDefinition . HasEvents ) {
67
+ foreach ( var e in typeDefinition . Events ) {
68
+ WalkCustomAttributesTypesScopes ( e ) ;
69
+ // e.EventType is not saved
70
+ }
71
+ }
72
+
73
+ if ( typeDefinition . HasFields ) {
74
+ foreach ( var f in typeDefinition . Fields ) {
75
+ WalkCustomAttributesTypesScopes ( f ) ;
76
+ WalkScopeOfTypeReference ( f . FieldType ) ;
77
+ WalkMarshalInfoTypeScope ( f ) ;
78
+ }
79
+ }
80
+
81
+ if ( typeDefinition . HasMethods ) {
82
+ foreach ( var m in typeDefinition . Methods ) {
83
+ WalkCustomAttributesTypesScopes ( m ) ;
84
+ WalkSecurityAttributesTypesScopes ( m ) ;
85
+ if ( m . HasGenericParameters )
86
+ WalkTypeScope ( m . GenericParameters ) ;
87
+
88
+ WalkCustomAttributesTypesScopes ( m . MethodReturnType ) ;
89
+ WalkScopeOfTypeReference ( m . MethodReturnType . ReturnType ) ;
90
+ WalkMarshalInfoTypeScope ( m . MethodReturnType ) ;
91
+ if ( m . HasOverrides ) {
92
+ foreach ( var mo in m . Overrides )
93
+ WalkMethodReference ( mo ) ;
94
+ }
95
+
96
+ if ( m . HasParameters )
97
+ WalkTypeScope ( m . Parameters ) ;
98
+
99
+ if ( m . HasBody )
100
+ WalkTypeScope ( m . Body ) ;
101
+ }
102
+ }
103
+
104
+ if ( typeDefinition . HasProperties ) {
105
+ foreach ( var p in typeDefinition . Properties ) {
106
+ WalkCustomAttributesTypesScopes ( p ) ;
107
+ // p.PropertyType is not saved
108
+ }
109
+ }
110
+
111
+ if ( typeDefinition . HasNestedTypes ) {
112
+ foreach ( var nestedType in typeDefinition . NestedTypes ) {
113
+ WalkScopes ( nestedType ) ;
114
+ }
115
+ }
116
+ }
117
+
118
+ void WalkTypeScope ( Collection < GenericParameter > genericParameters )
119
+ {
120
+ foreach ( var gp in genericParameters ) {
121
+ WalkCustomAttributesTypesScopes ( gp ) ;
122
+ if ( gp . HasConstraints )
123
+ WalkTypeScope ( gp . Constraints ) ;
124
+ }
125
+ }
126
+
127
+ void WalkTypeScope ( Collection < GenericParameterConstraint > constraints )
128
+ {
129
+ foreach ( var gc in constraints ) {
130
+ WalkCustomAttributesTypesScopes ( gc ) ;
131
+ WalkScopeOfTypeReference ( gc . ConstraintType ) ;
132
+ }
133
+ }
134
+
135
+ void WalkTypeScope ( Collection < ParameterDefinition > parameters )
136
+ {
137
+ foreach ( var p in parameters ) {
138
+ WalkCustomAttributesTypesScopes ( p ) ;
139
+ WalkScopeOfTypeReference ( p . ParameterType ) ;
140
+ WalkMarshalInfoTypeScope ( p ) ;
141
+ }
142
+ }
143
+
144
+ void WalkTypeScope ( MethodBody body )
145
+ {
146
+ if ( body . HasVariables ) {
147
+ foreach ( var v in body . Variables ) {
148
+ WalkScopeOfTypeReference ( v . VariableType ) ;
149
+ }
150
+ }
151
+
152
+ if ( body . HasExceptionHandlers ) {
153
+ foreach ( var eh in body . ExceptionHandlers ) {
154
+ if ( eh . CatchType != null )
155
+ WalkScopeOfTypeReference ( eh . CatchType ) ;
156
+ }
157
+ }
158
+
159
+ foreach ( var instr in body . Instructions ) {
160
+ switch ( instr . OpCode . OperandType ) {
161
+
162
+ case OperandType . InlineMethod : {
163
+ var mr = ( MethodReference ) instr . Operand ;
164
+ WalkMethodReference ( mr ) ;
165
+ break ;
166
+ }
167
+
168
+ case OperandType . InlineField : {
169
+ var fr = ( FieldReference ) instr . Operand ;
170
+ WalkFieldReference ( fr ) ;
171
+ break ;
172
+ }
173
+
174
+ case OperandType . InlineTok : {
175
+ switch ( instr . Operand ) {
176
+ case TypeReference tr :
177
+ WalkScopeOfTypeReference ( tr ) ;
178
+ break ;
179
+ case FieldReference fr :
180
+ WalkFieldReference ( fr ) ;
181
+ break ;
182
+ case MethodReference mr :
183
+ WalkMethodReference ( mr ) ;
184
+ break ;
185
+ }
186
+
187
+ break ;
188
+ }
189
+
190
+ case OperandType . InlineType : {
191
+ var tr = ( TypeReference ) instr . Operand ;
192
+ WalkScopeOfTypeReference ( tr ) ;
193
+ break ;
194
+ }
195
+ }
196
+ }
197
+ }
198
+
199
+ void WalkMethodReference ( MethodReference mr )
200
+ {
201
+ WalkScopeOfTypeReference ( mr . ReturnType ) ;
202
+ WalkScopeOfTypeReference ( mr . DeclaringType ) ;
203
+
204
+ if ( mr is GenericInstanceMethod gim ) {
205
+ foreach ( var tr in gim . GenericArguments )
206
+ WalkScopeOfTypeReference ( tr ) ;
207
+ }
208
+
209
+ if ( mr . HasParameters ) {
210
+ WalkTypeScope ( mr . Parameters ) ;
211
+ }
212
+ }
213
+
214
+ void WalkFieldReference ( FieldReference fr )
215
+ {
216
+ WalkScopeOfTypeReference ( fr . FieldType ) ;
217
+ WalkScopeOfTypeReference ( fr . DeclaringType ) ;
218
+ }
219
+
220
+ void WalkMarshalInfoTypeScope ( IMarshalInfoProvider provider )
221
+ {
222
+ if ( ! provider . HasMarshalInfo )
223
+ return ;
224
+
225
+ if ( provider . MarshalInfo is CustomMarshalInfo cmi )
226
+ WalkScopeOfTypeReference ( cmi . ManagedType ) ;
227
+ }
228
+
229
+ void WalkCustomAttributesTypesScopes ( ICustomAttributeProvider customAttributeProvider )
230
+ {
231
+ if ( ! customAttributeProvider . HasCustomAttributes )
232
+ return ;
233
+
234
+ foreach ( var ca in customAttributeProvider . CustomAttributes )
235
+ WalkForwardedTypesScope ( ca ) ;
236
+ }
237
+
238
+ void WalkSecurityAttributesTypesScopes ( ISecurityDeclarationProvider securityAttributeProvider )
239
+ {
240
+ if ( ! securityAttributeProvider . HasSecurityDeclarations )
241
+ return ;
242
+
243
+ foreach ( var ca in securityAttributeProvider . SecurityDeclarations ) {
244
+ if ( ! ca . HasSecurityAttributes )
245
+ continue ;
246
+
247
+ foreach ( var securityAttribute in ca . SecurityAttributes )
248
+ WalkForwardedTypesScope ( securityAttribute ) ;
249
+ }
250
+ }
251
+
252
+ void WalkForwardedTypesScope ( CustomAttribute attribute )
253
+ {
254
+ WalkMethodReference ( attribute . Constructor ) ;
255
+
256
+ if ( attribute . HasConstructorArguments ) {
257
+ foreach ( var ca in attribute . ConstructorArguments )
258
+ WalkForwardedTypesScope ( ca ) ;
259
+ }
260
+
261
+ if ( attribute . HasFields ) {
262
+ foreach ( var field in attribute . Fields )
263
+ WalkForwardedTypesScope ( field . Argument ) ;
264
+ }
265
+
266
+ if ( attribute . HasProperties ) {
267
+ foreach ( var property in attribute . Properties )
268
+ WalkForwardedTypesScope ( property . Argument ) ;
269
+ }
270
+ }
271
+
272
+ void WalkForwardedTypesScope ( SecurityAttribute attribute )
273
+ {
274
+ if ( attribute . HasFields ) {
275
+ foreach ( var field in attribute . Fields )
276
+ WalkForwardedTypesScope ( field . Argument ) ;
277
+ }
278
+
279
+ if ( attribute . HasProperties ) {
280
+ foreach ( var property in attribute . Properties )
281
+ WalkForwardedTypesScope ( property . Argument ) ;
282
+ }
283
+ }
284
+
285
+ void WalkForwardedTypesScope ( CustomAttributeArgument attributeArgument )
286
+ {
287
+ WalkScopeOfTypeReference ( attributeArgument . Type ) ;
288
+
289
+ switch ( attributeArgument . Value ) {
290
+ case TypeReference tr :
291
+ WalkScopeOfTypeReference ( tr ) ;
292
+ break ;
293
+ case CustomAttributeArgument caa :
294
+ WalkForwardedTypesScope ( caa ) ;
295
+ break ;
296
+ case CustomAttributeArgument [ ] array :
297
+ foreach ( var item in array )
298
+ WalkForwardedTypesScope ( item ) ;
299
+ break ;
300
+ }
301
+ }
302
+
303
+ void WalkScopeOfTypeReference ( TypeReference type )
304
+ {
305
+ if ( type == null )
306
+ return ;
307
+
308
+ if ( ! visited . Add ( type ) )
309
+ return ;
310
+
311
+ // Don't walk the scope of windows runtime projections
312
+ if ( type . IsWindowsRuntimeProjection )
313
+ return ;
314
+
315
+ switch ( type ) {
316
+ case GenericInstanceType git :
317
+ WalkScopeOfTypeReference ( git . ElementType ) ;
318
+ foreach ( var ga in git . GenericArguments )
319
+ WalkScopeOfTypeReference ( ga ) ;
320
+ return ;
321
+ case FunctionPointerType fpt :
322
+ WalkScopeOfTypeReference ( fpt . ReturnType ) ;
323
+ if ( fpt . HasParameters )
324
+ WalkTypeScope ( fpt . Parameters ) ;
325
+ return ;
326
+ case IModifierType imt :
327
+ WalkScopeOfTypeReference ( imt . ModifierType ) ;
328
+ WalkScopeOfTypeReference ( imt . ElementType ) ;
329
+ return ;
330
+ case TypeSpecification ts :
331
+ WalkScopeOfTypeReference ( ts . ElementType ) ;
332
+ return ;
333
+ case TypeDefinition :
334
+ case GenericParameter :
335
+ // Nothing to walk
336
+ return ;
337
+ }
338
+
339
+ markingHelpers . MarkForwardedScope ( type ) ;
340
+ }
341
+ }
342
+
343
+ }
0 commit comments