@@ -74,6 +74,12 @@ public IDebugInfoProvider DebugInfo {
74
74
75
75
public bool ExpandMemberDefinitions { get ; set ; }
76
76
77
+ /// <summary>
78
+ /// Gets or sets whether custom attribute blobs should be decoded or dumped as raw bytes. Default is <see langword="false"/>.
79
+ /// Setting this value to <see langword="true"/> (roughly) corresponds to the <c>/CAVERBAL</c> switch of <c>ildasm</c>.
80
+ /// </summary>
81
+ public bool DecodeCustomAttributeBlobs { get ; set ; }
82
+
77
83
public IAssemblyResolver AssemblyResolver { get ; set ; }
78
84
79
85
public IEntityProcessor EntityProcessor { get ; set ; }
@@ -476,7 +482,7 @@ void WriteSecurityDeclarations(MetadataFile module, DeclarativeSecurityAttribute
476
482
}
477
483
}
478
484
479
- class SecurityDeclarationDecoder : ICustomAttributeTypeProvider < ( PrimitiveTypeCode , string ) >
485
+ class SecurityDeclarationDecoder : ICustomAttributeTypeProvider < ( PrimitiveTypeCode Code , string Name ) >
480
486
{
481
487
readonly ITextOutput output ;
482
488
readonly IAssemblyResolver resolver ;
@@ -506,12 +512,54 @@ public SecurityDeclarationDecoder(ITextOutput output, IAssemblyResolver resolver
506
512
507
513
public ( PrimitiveTypeCode , string ) GetTypeFromDefinition ( MetadataReader reader , TypeDefinitionHandle handle , byte rawTypeKind )
508
514
{
509
- throw new NotImplementedException ( ) ;
515
+ string fullTypeName = handle . GetFullTypeName ( reader ) . FullName ;
516
+ if ( handle . IsEnum ( reader , out var typeCode ) )
517
+ return ( typeCode , "enum " + fullTypeName ) ;
518
+ return ( 0 , fullTypeName ) ;
510
519
}
511
520
512
521
public ( PrimitiveTypeCode , string ) GetTypeFromReference ( MetadataReader reader , TypeReferenceHandle handle , byte rawTypeKind )
513
522
{
514
- throw new NotImplementedException ( ) ;
523
+ string fullTypeName = handle . GetFullTypeName ( reader ) . FullName ;
524
+ var containingModule = GetDeclaringModule ( handle ) ;
525
+
526
+ string assemblyQualifiedTypeName = containingModule != null
527
+ ? fullTypeName + ", " + containingModule
528
+ : fullTypeName ;
529
+
530
+ PrimitiveTypeCode typeCode = 0 ;
531
+ var ( targetModule , resolvedType ) = ResolveType ( assemblyQualifiedTypeName , module ) ;
532
+ if ( targetModule != null )
533
+ {
534
+ if ( ! resolvedType . IsEnum ( targetModule . Metadata , out typeCode ) )
535
+ {
536
+ typeCode = 0 ;
537
+ }
538
+ else
539
+ {
540
+ assemblyQualifiedTypeName = "enum " + assemblyQualifiedTypeName ;
541
+ }
542
+ }
543
+
544
+ return ( typeCode , assemblyQualifiedTypeName ) ;
545
+
546
+ string GetDeclaringModule ( TypeReferenceHandle handle )
547
+ {
548
+ var tr = reader . GetTypeReference ( handle ) ;
549
+ switch ( tr . ResolutionScope . Kind )
550
+ {
551
+ case HandleKind . TypeReference :
552
+ return GetDeclaringModule ( ( TypeReferenceHandle ) tr . ResolutionScope ) ;
553
+ case HandleKind . AssemblyReference :
554
+ var asmRef = reader . GetAssemblyReference ( ( AssemblyReferenceHandle ) tr . ResolutionScope ) ;
555
+ return asmRef . TryGetFullAssemblyName ( reader , out var assemblyName ) ? assemblyName : null ;
556
+ case HandleKind . ModuleReference :
557
+ var modRef = reader . GetModuleReference ( ( ModuleReferenceHandle ) tr . ResolutionScope ) ;
558
+ return reader . GetString ( modRef . Name ) ;
559
+ default :
560
+ return null ;
561
+ }
562
+ }
515
563
}
516
564
517
565
public ( PrimitiveTypeCode , string ) GetTypeFromSerializedName ( string name )
@@ -608,17 +656,6 @@ TypeDefinitionHandle FindType(MetadataFile currentModule, string[] name)
608
656
}
609
657
}
610
658
611
- PrimitiveTypeCode ResolveEnumUnderlyingType ( string typeName , PEFile module )
612
- {
613
- if ( typeName . StartsWith ( "enum " , StringComparison . Ordinal ) )
614
- typeName = typeName . Substring ( 5 ) ;
615
- var ( containingModule , typeDefHandle ) = ResolveType ( typeName , module ) ;
616
-
617
- if ( typeDefHandle . IsNil || ! typeDefHandle . IsEnum ( containingModule . Metadata , out var typeCode ) )
618
- throw new EnumUnderlyingTypeResolveException ( ) ;
619
- return typeCode ;
620
- }
621
-
622
659
MetadataFile mscorlib ;
623
660
624
661
bool TryResolveMscorlib ( out MetadataFile mscorlib )
@@ -704,7 +741,7 @@ void TryDecodeSecurityDeclaration(TextOutputWithRollback output, BlobReader blob
704
741
}
705
742
706
743
output . Write ( argument . Type . Name ?? PrimitiveTypeCodeToString ( argument . Type . Code ) ) ;
707
- output . Write ( " " + argument . Name + " = " ) ;
744
+ output . Write ( " " + DisassemblerHelpers . Escape ( argument . Name ) + " = " ) ;
708
745
709
746
WriteValue ( output , argument . Type , argument . Value ) ;
710
747
output . WriteLine ( ) ;
@@ -1824,12 +1861,62 @@ void WriteAttributes(MetadataFile module, CustomAttributeHandleCollection attrib
1824
1861
if ( ! attr . Value . IsNil )
1825
1862
{
1826
1863
output . Write ( " = " ) ;
1827
- WriteBlob ( attr . Value , metadata ) ;
1864
+ if ( DecodeCustomAttributeBlobs )
1865
+ WriteDecodedCustomAttributeBlob ( attr , module ) ;
1866
+ else
1867
+ WriteBlob ( attr . Value , metadata ) ;
1828
1868
}
1829
1869
output . WriteLine ( ) ;
1830
1870
}
1831
1871
}
1832
1872
1873
+ void WriteDecodedCustomAttributeBlob ( CustomAttribute attr , MetadataFile module )
1874
+ {
1875
+ CustomAttributeValue < ( PrimitiveTypeCode Code , string Name ) > value ;
1876
+ try
1877
+ {
1878
+ var provider = new SecurityDeclarationDecoder ( output , AssemblyResolver , module ) ;
1879
+ value = attr . DecodeValue ( provider ) ;
1880
+ }
1881
+ catch ( BadImageFormatException )
1882
+ {
1883
+ output . Write ( "/* Could not decode attribute value */ " ) ;
1884
+ WriteBlob ( attr . Value , module . Metadata ) ;
1885
+ return ;
1886
+ }
1887
+
1888
+ output . Write ( "{" ) ;
1889
+ output . Indent ( ) ;
1890
+
1891
+ foreach ( var arg in value . FixedArguments )
1892
+ {
1893
+ output . WriteLine ( ) ;
1894
+ WriteValue ( output , arg . Type , arg . Value ) ;
1895
+ }
1896
+
1897
+ foreach ( var arg in value . NamedArguments )
1898
+ {
1899
+ output . WriteLine ( ) ;
1900
+ switch ( arg . Kind )
1901
+ {
1902
+ case CustomAttributeNamedArgumentKind . Field :
1903
+ output . Write ( "field " ) ;
1904
+ break ;
1905
+ case CustomAttributeNamedArgumentKind . Property :
1906
+ output . Write ( "property " ) ;
1907
+ break ;
1908
+ }
1909
+
1910
+ output . Write ( arg . Type . Name ?? PrimitiveTypeCodeToString ( arg . Type . Code ) ) ;
1911
+ output . Write ( " " + DisassemblerHelpers . Escape ( arg . Name ) + " = " ) ;
1912
+ WriteValue ( output , arg . Type , arg . Value ) ;
1913
+ }
1914
+
1915
+ output . WriteLine ( ) ;
1916
+ output . Unindent ( ) ;
1917
+ output . Write ( "}" ) ;
1918
+ }
1919
+
1833
1920
void WriteBlob ( BlobHandle blob , MetadataReader metadata )
1834
1921
{
1835
1922
var reader = metadata . GetBlobReader ( blob ) ;
@@ -1839,23 +1926,26 @@ void WriteBlob(BlobHandle blob, MetadataReader metadata)
1839
1926
void WriteBlob ( BlobReader reader )
1840
1927
{
1841
1928
output . Write ( "(" ) ;
1842
- output . Indent ( ) ;
1843
-
1844
- for ( int i = 0 ; i < reader . Length ; i ++ )
1929
+ if ( reader . Length > 0 )
1845
1930
{
1846
- if ( i % 16 == 0 && i < reader . Length - 1 )
1847
- {
1848
- output . WriteLine ( ) ;
1849
- }
1850
- else
1931
+ output . Indent ( ) ;
1932
+
1933
+ for ( int i = 0 ; i < reader . Length ; i ++ )
1851
1934
{
1852
- output . Write ( ' ' ) ;
1935
+ if ( i % 16 == 0 && i < reader . Length - 1 )
1936
+ {
1937
+ output . WriteLine ( ) ;
1938
+ }
1939
+ else
1940
+ {
1941
+ output . Write ( ' ' ) ;
1942
+ }
1943
+ output . Write ( reader . ReadByte ( ) . ToString ( "x2" ) ) ;
1853
1944
}
1854
- output . Write ( reader . ReadByte ( ) . ToString ( "x2" ) ) ;
1855
- }
1856
1945
1857
- output . WriteLine ( ) ;
1858
- output . Unindent ( ) ;
1946
+ output . WriteLine ( ) ;
1947
+ output . Unindent ( ) ;
1948
+ }
1859
1949
output . Write ( ")" ) ;
1860
1950
}
1861
1951
0 commit comments