diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
index 16bb69a13..47230c2b6 100644
--- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
+++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
@@ -74,6 +74,12 @@ namespace ICSharpCode.Decompiler.Disassembler
public bool ExpandMemberDefinitions { get; set; }
+ ///
+ /// Gets or sets whether custom attribute blobs should be decoded or dumped as raw bytes. Default is .
+ /// Setting this value to (roughly) corresponds to the /CAVERBAL switch of ildasm.
+ ///
+ public bool DecodeCustomAttributeBlobs { get; set; }
+
public IAssemblyResolver AssemblyResolver { get; set; }
public IEntityProcessor EntityProcessor { get; set; }
@@ -476,7 +482,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
- class SecurityDeclarationDecoder : ICustomAttributeTypeProvider<(PrimitiveTypeCode, string)>
+ class SecurityDeclarationDecoder : ICustomAttributeTypeProvider<(PrimitiveTypeCode Code, string Name)>
{
readonly ITextOutput output;
readonly IAssemblyResolver resolver;
@@ -506,12 +512,54 @@ namespace ICSharpCode.Decompiler.Disassembler
public (PrimitiveTypeCode, string) GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
- throw new NotImplementedException();
+ string fullTypeName = handle.GetFullTypeName(reader).FullName;
+ if (handle.IsEnum(reader, out var typeCode))
+ return (typeCode, "enum " + fullTypeName);
+ return (0, fullTypeName);
}
public (PrimitiveTypeCode, string) GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{
- throw new NotImplementedException();
+ string fullTypeName = handle.GetFullTypeName(reader).FullName;
+ var containingModule = GetDeclaringModule(handle);
+
+ string assemblyQualifiedTypeName = containingModule != null
+ ? fullTypeName + ", " + containingModule
+ : fullTypeName;
+
+ PrimitiveTypeCode typeCode = 0;
+ var (targetModule, resolvedType) = ResolveType(assemblyQualifiedTypeName, module);
+ if (targetModule != null)
+ {
+ if (!resolvedType.IsEnum(targetModule.Metadata, out typeCode))
+ {
+ typeCode = 0;
+ }
+ else
+ {
+ assemblyQualifiedTypeName = "enum " + assemblyQualifiedTypeName;
+ }
+ }
+
+ return (typeCode, assemblyQualifiedTypeName);
+
+ string GetDeclaringModule(TypeReferenceHandle handle)
+ {
+ var tr = reader.GetTypeReference(handle);
+ switch (tr.ResolutionScope.Kind)
+ {
+ case HandleKind.TypeReference:
+ return GetDeclaringModule((TypeReferenceHandle)tr.ResolutionScope);
+ case HandleKind.AssemblyReference:
+ var asmRef = reader.GetAssemblyReference((AssemblyReferenceHandle)tr.ResolutionScope);
+ return asmRef.TryGetFullAssemblyName(reader, out var assemblyName) ? assemblyName : null;
+ case HandleKind.ModuleReference:
+ var modRef = reader.GetModuleReference((ModuleReferenceHandle)tr.ResolutionScope);
+ return reader.GetString(modRef.Name);
+ default:
+ return null;
+ }
+ }
}
public (PrimitiveTypeCode, string) GetTypeFromSerializedName(string name)
@@ -608,17 +656,6 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
- PrimitiveTypeCode ResolveEnumUnderlyingType(string typeName, PEFile module)
- {
- if (typeName.StartsWith("enum ", StringComparison.Ordinal))
- typeName = typeName.Substring(5);
- var (containingModule, typeDefHandle) = ResolveType(typeName, module);
-
- if (typeDefHandle.IsNil || !typeDefHandle.IsEnum(containingModule.Metadata, out var typeCode))
- throw new EnumUnderlyingTypeResolveException();
- return typeCode;
- }
-
MetadataFile mscorlib;
bool TryResolveMscorlib(out MetadataFile mscorlib)
@@ -704,7 +741,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
output.Write(argument.Type.Name ?? PrimitiveTypeCodeToString(argument.Type.Code));
- output.Write(" " + argument.Name + " = ");
+ output.Write(" " + DisassemblerHelpers.Escape(argument.Name) + " = ");
WriteValue(output, argument.Type, argument.Value);
output.WriteLine();
@@ -1824,12 +1861,62 @@ namespace ICSharpCode.Decompiler.Disassembler
if (!attr.Value.IsNil)
{
output.Write(" = ");
- WriteBlob(attr.Value, metadata);
+ if (DecodeCustomAttributeBlobs)
+ WriteDecodedCustomAttributeBlob(attr, module);
+ else
+ WriteBlob(attr.Value, metadata);
}
output.WriteLine();
}
}
+ void WriteDecodedCustomAttributeBlob(CustomAttribute attr, MetadataFile module)
+ {
+ CustomAttributeValue<(PrimitiveTypeCode Code, string Name)> value;
+ try
+ {
+ var provider = new SecurityDeclarationDecoder(output, AssemblyResolver, module);
+ value = attr.DecodeValue(provider);
+ }
+ catch (BadImageFormatException)
+ {
+ output.Write("/* Could not decode attribute value */ ");
+ WriteBlob(attr.Value, module.Metadata);
+ return;
+ }
+
+ output.Write("{");
+ output.Indent();
+
+ foreach (var arg in value.FixedArguments)
+ {
+ output.WriteLine();
+ WriteValue(output, arg.Type, arg.Value);
+ }
+
+ foreach (var arg in value.NamedArguments)
+ {
+ output.WriteLine();
+ switch (arg.Kind)
+ {
+ case CustomAttributeNamedArgumentKind.Field:
+ output.Write("field ");
+ break;
+ case CustomAttributeNamedArgumentKind.Property:
+ output.Write("property ");
+ break;
+ }
+
+ output.Write(arg.Type.Name ?? PrimitiveTypeCodeToString(arg.Type.Code));
+ output.Write(" " + DisassemblerHelpers.Escape(arg.Name) + " = ");
+ WriteValue(output, arg.Type, arg.Value);
+ }
+
+ output.WriteLine();
+ output.Unindent();
+ output.Write("}");
+ }
+
void WriteBlob(BlobHandle blob, MetadataReader metadata)
{
var reader = metadata.GetBlobReader(blob);
@@ -1839,23 +1926,26 @@ namespace ICSharpCode.Decompiler.Disassembler
void WriteBlob(BlobReader reader)
{
output.Write("(");
- output.Indent();
-
- for (int i = 0; i < reader.Length; i++)
+ if (reader.Length > 0)
{
- if (i % 16 == 0 && i < reader.Length - 1)
- {
- output.WriteLine();
- }
- else
+ output.Indent();
+
+ for (int i = 0; i < reader.Length; i++)
{
- output.Write(' ');
+ if (i % 16 == 0 && i < reader.Length - 1)
+ {
+ output.WriteLine();
+ }
+ else
+ {
+ output.Write(' ');
+ }
+ output.Write(reader.ReadByte().ToString("x2"));
}
- output.Write(reader.ReadByte().ToString("x2"));
- }
- output.WriteLine();
- output.Unindent();
+ output.WriteLine();
+ output.Unindent();
+ }
output.Write(")");
}
diff --git a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
index b16fe4e4f..52452be12 100644
--- a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
+++ b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
@@ -210,25 +210,6 @@ namespace ICSharpCode.Decompiler.Metadata
return Disassembler.DisassemblerHelpers.Escape(name);
}
- [Obsolete("Use MetadataModule.GetDeclaringModule() instead")]
- public static IModuleReference GetDeclaringModule(this TypeReferenceHandle handle, MetadataReader reader)
- {
- var tr = reader.GetTypeReference(handle);
- switch (tr.ResolutionScope.Kind)
- {
- case HandleKind.TypeReference:
- return ((TypeReferenceHandle)tr.ResolutionScope).GetDeclaringModule(reader);
- case HandleKind.AssemblyReference:
- var asmRef = reader.GetAssemblyReference((AssemblyReferenceHandle)tr.ResolutionScope);
- return new DefaultAssemblyReference(reader.GetString(asmRef.Name));
- case HandleKind.ModuleReference:
- var modRef = reader.GetModuleReference((ModuleReferenceHandle)tr.ResolutionScope);
- return new DefaultAssemblyReference(reader.GetString(modRef.Name));
- default:
- return DefaultAssemblyReference.CurrentAssembly;
- }
- }
-
internal static readonly TypeProvider minimalCorlibTypeProvider =
new TypeProvider(new SimpleCompilation(MinimalCorlib.Instance));
diff --git a/ILSpy/Languages/CSharpILMixedLanguage.cs b/ILSpy/Languages/CSharpILMixedLanguage.cs
index ca349bbed..da06515fc 100644
--- a/ILSpy/Languages/CSharpILMixedLanguage.cs
+++ b/ILSpy/Languages/CSharpILMixedLanguage.cs
@@ -60,7 +60,8 @@ namespace ICSharpCode.ILSpy
ShowMetadataTokens = displaySettings.ShowMetadataTokens,
ShowMetadataTokensInBase10 = displaySettings.ShowMetadataTokensInBase10,
ShowRawRVAOffsetAndBytes = displaySettings.ShowRawOffsetsAndBytesBeforeInstruction,
- ExpandMemberDefinitions = options.DecompilerSettings.ExpandMemberDefinitions
+ ExpandMemberDefinitions = options.DecompilerSettings.ExpandMemberDefinitions,
+ DecodeCustomAttributeBlobs = displaySettings.DecodeCustomAttributeBlobs
};
}
diff --git a/ILSpy/Languages/ILLanguage.cs b/ILSpy/Languages/ILLanguage.cs
index 384728e36..748328b7e 100644
--- a/ILSpy/Languages/ILLanguage.cs
+++ b/ILSpy/Languages/ILLanguage.cs
@@ -67,7 +67,8 @@ namespace ICSharpCode.ILSpy
ShowMetadataTokens = displaySettings.ShowMetadataTokens,
ShowMetadataTokensInBase10 = displaySettings.ShowMetadataTokensInBase10,
ShowRawRVAOffsetAndBytes = displaySettings.ShowRawOffsetsAndBytesBeforeInstruction,
- ExpandMemberDefinitions = options.DecompilerSettings.ExpandMemberDefinitions
+ ExpandMemberDefinitions = options.DecompilerSettings.ExpandMemberDefinitions,
+ DecodeCustomAttributeBlobs = displaySettings.DecodeCustomAttributeBlobs
};
}
diff --git a/ILSpy/Options/DisplaySettings.cs b/ILSpy/Options/DisplaySettings.cs
index b77bf501e..95c9d02d1 100644
--- a/ILSpy/Options/DisplaySettings.cs
+++ b/ILSpy/Options/DisplaySettings.cs
@@ -156,6 +156,12 @@ namespace ICSharpCode.ILSpy.Options
set => SetProperty(ref enableSmoothScrolling, value);
}
+ private bool decodeCustomAttributeBlobs;
+ public bool DecodeCustomAttributeBlobs {
+ get => decodeCustomAttributeBlobs;
+ set => SetProperty(ref decodeCustomAttributeBlobs, value);
+ }
+
public XName SectionName => "DisplaySettings";
public void LoadFromXml(XElement section)
@@ -181,6 +187,7 @@ namespace ICSharpCode.ILSpy.Options
ShowRawOffsetsAndBytesBeforeInstruction = (bool?)section.Attribute("ShowRawOffsetsAndBytesBeforeInstruction") ?? false;
StyleWindowTitleBar = (bool?)section.Attribute("StyleWindowTitleBar") ?? false;
EnableSmoothScrolling = (bool?)section.Attribute("EnableSmoothScrolling") ?? true;
+ DecodeCustomAttributeBlobs = (bool?)section.Attribute("DecodeCustomAttributeBlobs") ?? false;
}
public XElement SaveToXml()
@@ -208,6 +215,7 @@ namespace ICSharpCode.ILSpy.Options
section.SetAttributeValue("ShowRawOffsetsAndBytesBeforeInstruction", ShowRawOffsetsAndBytesBeforeInstruction);
section.SetAttributeValue("StyleWindowTitleBar", StyleWindowTitleBar);
section.SetAttributeValue("EnableSmoothScrolling", EnableSmoothScrolling);
+ section.SetAttributeValue("DecodeCustomAttributeBlobs", DecodeCustomAttributeBlobs);
return section;
}
diff --git a/ILSpy/Options/DisplaySettingsPanel.xaml b/ILSpy/Options/DisplaySettingsPanel.xaml
index 0624bd444..58c7ae316 100644
--- a/ILSpy/Options/DisplaySettingsPanel.xaml
+++ b/ILSpy/Options/DisplaySettingsPanel.xaml
@@ -64,6 +64,7 @@
+
diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs
index ad46f836b..3ddca0ae2 100644
--- a/ILSpy/Properties/Resources.Designer.cs
+++ b/ILSpy/Properties/Resources.Designer.cs
@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
@@ -648,6 +648,15 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
+ ///
+ /// Looks up a localized string similar to Decode custom attribute blobs.
+ ///
+ public static string DecodeCustomAttributeBlobs {
+ get {
+ return ResourceManager.GetString("DecodeCustomAttributeBlobs", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Decompilation complete in {0:F1} seconds..
///
diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx
index bb0d12dde..ee03a4325 100644
--- a/ILSpy/Properties/Resources.resx
+++ b/ILSpy/Properties/Resources.resx
@@ -234,6 +234,9 @@ Are you sure you want to continue?
Debug this step
+
+ Decode custom attribute blobs
+
Decompilation complete in {0:F1} seconds.