Browse Source

Replace BlobDecoder with solution not relying on TypeSystem

pull/1198/head
Siegfried Pammer 7 years ago
parent
commit
6065030a24
  1. 219
      ICSharpCode.Decompiler/Disassembler/BlobDecoder.cs
  2. 317
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  3. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  4. 20
      ICSharpCode.Decompiler/SRMExtensions.cs

219
ICSharpCode.Decompiler/Disassembler/BlobDecoder.cs

@ -1,219 +0,0 @@ @@ -1,219 +0,0 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.Disassembler
{
sealed class BlobDecoder
{
SRM.BlobReader blob;
static readonly ITypeResolveContext context = new SimpleTypeResolveContext(MinimalCorlib.Instance.CreateCompilation());
public BlobDecoder(SRM.BlobReader blob)
{
this.blob = blob;
}
public int Offset => blob.Offset;
public ResolveResult ReadFixedArg(IType argType)
{
if (argType.Kind == TypeKind.Array) {
if (((ArrayType)argType).Dimensions != 1) {
// Only single-dimensional arrays are supported
return ErrorResolveResult.UnknownError;
}
IType elementType = ((ArrayType)argType).ElementType;
uint numElem = blob.ReadUInt32();
if (numElem == 0xffffffff) {
// null reference
return new ConstantResolveResult(argType, null);
} else {
ResolveResult[] elements = new ResolveResult[numElem];
for (int i = 0; i < elements.Length; i++) {
elements[i] = ReadElem(elementType);
// Stop decoding when encountering an error:
if (elements[i].IsError)
return ErrorResolveResult.UnknownError;
}
IType int32 = context.Compilation.FindType(KnownTypeCode.Int32);
ResolveResult[] sizeArgs = { new ConstantResolveResult(int32, elements.Length) };
return new ArrayCreateResolveResult(argType, sizeArgs, elements);
}
} else {
return ReadElem(argType);
}
}
public ResolveResult ReadElem(IType elementType)
{
ITypeDefinition underlyingType;
if (elementType.Kind == TypeKind.Enum) {
underlyingType = elementType.GetDefinition().EnumUnderlyingType.GetDefinition();
} else {
underlyingType = elementType.GetDefinition();
}
if (underlyingType == null)
return ErrorResolveResult.UnknownError;
KnownTypeCode typeCode = underlyingType.KnownTypeCode;
if (typeCode == KnownTypeCode.Object) {
// boxed value type
IType boxedTyped = ReadCustomAttributeFieldOrPropType();
ResolveResult elem = ReadFixedArg(boxedTyped);
if (elem.IsCompileTimeConstant && elem.ConstantValue == null)
return new ConstantResolveResult(elementType, null);
else
return new ConversionResolveResult(elementType, elem, Conversion.BoxingConversion);
} else if (typeCode == KnownTypeCode.Type) {
var type = ReadType();
if (type != null) {
return new TypeOfResolveResult(underlyingType, type);
} else {
return new ConstantResolveResult(underlyingType, null);
}
} else {
return new ConstantResolveResult(elementType, ReadElemValue(typeCode));
}
}
object ReadElemValue(KnownTypeCode typeCode)
{
switch (typeCode) {
case KnownTypeCode.Boolean:
return blob.ReadBoolean();
case KnownTypeCode.Char:
return blob.ReadChar();
case KnownTypeCode.SByte:
return blob.ReadSByte();
case KnownTypeCode.Byte:
return blob.ReadByte();
case KnownTypeCode.Int16:
return blob.ReadInt16();
case KnownTypeCode.UInt16:
return blob.ReadUInt16();
case KnownTypeCode.Int32:
return blob.ReadInt32();
case KnownTypeCode.UInt32:
return blob.ReadUInt32();
case KnownTypeCode.Int64:
return blob.ReadInt64();
case KnownTypeCode.UInt64:
return blob.ReadUInt64();
case KnownTypeCode.Single:
return blob.ReadSingle();
case KnownTypeCode.Double:
return blob.ReadDouble();
case KnownTypeCode.String:
return blob.ReadSerializedString();
default:
throw new NotSupportedException();
}
}
public KeyValuePair<string, ResolveResult> ReadNamedArg()
{
var b = blob.ReadByte();
switch (b) {
case 0x53:
case 0x54:
break;
default:
throw new NotSupportedException(string.Format("Custom member type 0x{0:x} is not supported.", b));
}
IType type = ReadCustomAttributeFieldOrPropType();
string name = blob.ReadSerializedString();
ResolveResult val = ReadFixedArg(type);
return new KeyValuePair<string, ResolveResult>(name, val);
}
IType ReadCustomAttributeFieldOrPropType()
{
ICompilation compilation = context.Compilation;
var b = blob.ReadByte();
switch (b) {
case 0x02:
return compilation.FindType(KnownTypeCode.Boolean);
case 0x03:
return compilation.FindType(KnownTypeCode.Char);
case 0x04:
return compilation.FindType(KnownTypeCode.SByte);
case 0x05:
return compilation.FindType(KnownTypeCode.Byte);
case 0x06:
return compilation.FindType(KnownTypeCode.Int16);
case 0x07:
return compilation.FindType(KnownTypeCode.UInt16);
case 0x08:
return compilation.FindType(KnownTypeCode.Int32);
case 0x09:
return compilation.FindType(KnownTypeCode.UInt32);
case 0x0a:
return compilation.FindType(KnownTypeCode.Int64);
case 0x0b:
return compilation.FindType(KnownTypeCode.UInt64);
case 0x0c:
return compilation.FindType(KnownTypeCode.Single);
case 0x0d:
return compilation.FindType(KnownTypeCode.Double);
case 0x0e:
return compilation.FindType(KnownTypeCode.String);
case 0x1d:
return new ArrayType(compilation, ReadCustomAttributeFieldOrPropType());
case 0x50:
return compilation.FindType(KnownTypeCode.Type);
case 0x51: // boxed value type
return compilation.FindType(KnownTypeCode.Object);
case 0x55: // enum
var type = ReadType();
if (type == null) {
throw new NotSupportedException("Enum type should not be null.");
}
return type;
default:
throw new NotSupportedException(string.Format("Custom attribute type 0x{0:x} is not supported.", b));
}
}
IType ReadType()
{
string typeName = blob.ReadSerializedString();
if (typeName == null) {
return null;
}
ITypeReference typeReference = ReflectionHelper.ParseReflectionName(typeName);
IType typeInCurrentAssembly = typeReference.Resolve(context);
if (typeInCurrentAssembly.Kind != TypeKind.Unknown)
return typeInCurrentAssembly;
// look for the type in mscorlib
ITypeDefinition systemObject = context.Compilation.FindType(KnownTypeCode.Object).GetDefinition();
if (systemObject != null) {
return typeReference.Resolve(new SimpleTypeResolveContext(systemObject.ParentAssembly));
} else {
// couldn't find corlib - return the unknown IType for the current assembly
return typeInCurrentAssembly;
}
}
}
}

317
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -197,7 +197,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -197,7 +197,8 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine();
output.Indent();
var declaringType = methodDefinition.GetDeclaringType();
var signature = methodDefinition.DecodeSignature(new DisassemblerSignatureProvider(method.Module, output), new GenericContext(method));
var signatureProvider = new DisassemblerSignatureProvider(method.Module, output);
var signature = methodDefinition.DecodeSignature(signatureProvider, new GenericContext(method));
if (signature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (signature.Header.IsInstance) {
@ -212,7 +213,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -212,7 +213,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(' ');
var parameters = methodDefinition.GetParameters().ToArray();
if (parameters.Length > 0) {
if (parameters.Length > 0 && parameters.Length > signature.ParameterTypes.Length) {
var marshallingDesc = metadata.GetParameter(parameters[0]).GetMarshallingDescriptor();
if (!marshallingDesc.IsNil) {
@ -340,12 +341,21 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -340,12 +341,21 @@ namespace ICSharpCode.Decompiler.Disassembler
int count = blob.ReadCompressedInteger();
for (int i = 0; i < count; i++) {
var typeName = blob.ReadSerializedString();
if (secdecl.Parent == EntityHandle.AssemblyDefinition) {
string[] nameParts = typeName.Split(new[] { ", " }, 2, StringSplitOptions.None);
if (nameParts.Length != 2)
throw new NotImplementedException();
var referencedModule = module.AssemblyResolver.Resolve(AssemblyNameReference.Parse(nameParts[1]));
if (referencedModule == module) {
output.Write("class ");
output.Write(DisassemblerHelpers.Escape(typeName));
} else {
throw new NotImplementedException();
//sa.AttributeType.WriteTo(output, ILNameSyntax.TypeName);
string[] typeNameParts = typeName.Split(new[] { ", " }, StringSplitOptions.None);
if (typeNameParts.Length < 2)
throw new NotImplementedException();
output.Write('[');
output.Write(typeNameParts[1]);
output.Write(']');
output.WriteReference(typeNameParts[0], null); // TODO : hyperlink!
}
output.Write(" = {");
blob.ReadCompressedInteger(); // ?
@ -356,7 +366,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -356,7 +366,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Indent();
for (int j = 0; j < argCount; j++) {
WriteSecurityDeclarationArgument(ref blob);
WriteSecurityDeclarationArgument(module, ref blob);
output.WriteLine();
}
@ -373,10 +383,200 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -373,10 +383,200 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
void WriteSecurityDeclarationArgument(ref BlobReader blob)
enum TypeKind
{
Primitive,
Type,
Boxed,
Enum
}
(PrimitiveSerializationTypeCode TypeCode, TypeKind Kind, bool IsArray, string TypeName) ReadArgumentType(ref BlobReader blob)
{
var b = blob.ReadByte();
if (2 <= b && b <= 14) {
return ((PrimitiveSerializationTypeCode)b, TypeKind.Primitive, false, null);
}
switch (b) {
case 0x1d:
var result = ReadArgumentType(ref blob);
return (result.TypeCode, result.Kind, true, result.TypeName);
case 0x50:
return (0, TypeKind.Type, false, null);
case 0x51: // boxed value type
return (0, TypeKind.Boxed, false, null);
case 0x55: // enum
return (0, TypeKind.Enum, false, blob.ReadSerializedString());
default:
throw new NotSupportedException($"Custom attribute type 0x{b:x} is not supported.");
}
}
object ReadSimpleArgumentValue(ref BlobReader blob, PrimitiveSerializationTypeCode typeCode, TypeKind kind, string typeName)
{
switch (kind) {
case TypeKind.Enum:
case TypeKind.Primitive:
switch (typeCode) {
case PrimitiveSerializationTypeCode.Boolean: return blob.ReadBoolean();
case PrimitiveSerializationTypeCode.Byte: return blob.ReadByte();
case PrimitiveSerializationTypeCode.SByte: return blob.ReadSByte();
case PrimitiveSerializationTypeCode.Char: return blob.ReadChar();
case PrimitiveSerializationTypeCode.Int16: return blob.ReadInt16();
case PrimitiveSerializationTypeCode.UInt16: return blob.ReadUInt16();
case PrimitiveSerializationTypeCode.Int32: return blob.ReadInt32();
case PrimitiveSerializationTypeCode.UInt32: return blob.ReadUInt32();
case PrimitiveSerializationTypeCode.Int64: return blob.ReadInt64();
case PrimitiveSerializationTypeCode.UInt64: return blob.ReadUInt64();
case PrimitiveSerializationTypeCode.Single: return blob.ReadSingle();
case PrimitiveSerializationTypeCode.Double: return blob.ReadDouble();
case PrimitiveSerializationTypeCode.String: return blob.ReadSerializedString();
default: throw new NotSupportedException();
}
case TypeKind.Type:
return blob.ReadSerializedString();
case TypeKind.Boxed:
var typeInfo = ReadArgumentType(ref blob);
return ReadArgumentValue(ref blob, typeInfo.TypeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName);
default:
throw new NotSupportedException();
}
}
PrimitiveSerializationTypeCode ResolveEnumUnderlyingType(string typeName, PEFile module, out Metadata.TypeDefinition typeDefinition)
{
typeDefinition = default(Metadata.TypeDefinition);
TypeDefinitionHandle FindType(PEFile currentModule, string[] name)
{
var metadata = currentModule.GetMetadataReader();
var currentNamespace = metadata.GetNamespaceDefinitionRoot();
ImmutableArray<TypeDefinitionHandle> typeDefinitions = default(ImmutableArray<TypeDefinitionHandle>);
for (int i = 0; i < name.Length; i++) {
string identifier = name[i];
if (!typeDefinitions.IsDefault) {
restart:
foreach (var type in typeDefinitions) {
var typeDef = metadata.GetTypeDefinition(type);
var currentTypeName = metadata.GetString(typeDef.Name);
if (identifier == currentTypeName) {
if (i + 1 == name.Length)
return type;
typeDefinitions = typeDef.GetNestedTypes();
goto restart;
}
}
} else {
var next = currentNamespace.NamespaceDefinitions.FirstOrDefault(ns => metadata.GetString(metadata.GetNamespaceDefinition(ns).Name) == identifier);
if (!next.IsNil) {
currentNamespace = metadata.GetNamespaceDefinition(next);
} else {
typeDefinitions = currentNamespace.TypeDefinitions;
i--;
}
}
}
return default(TypeDefinitionHandle);
}
string[] nameParts = typeName.Split(new[] { ", " }, 2, StringSplitOptions.None);
string[] typeNameParts = nameParts[0].Split('.');
PEFile containingModule = null;
// if we deal with an assembly-qualified name, resolve the assembly
if (nameParts.Length == 2)
containingModule = module.AssemblyResolver.Resolve(AssemblyNameReference.Parse(nameParts[1]));
if (containingModule != null) {
// try to find the type in the assembly
var handle = FindType(containingModule, typeNameParts);
var metadata = containingModule.GetMetadataReader();
if (handle.IsNil || !handle.IsEnum(metadata, out var typeCode))
throw new NotSupportedException();
typeDefinition = new Metadata.TypeDefinition(containingModule, handle);
return (PrimitiveSerializationTypeCode)typeCode;
} else {
// just fully-qualified name, try current assembly
var handle = FindType(module, typeNameParts);
if (handle.IsNil) {
// otherwise try mscorlib
var mscorlib = module.AssemblyResolver.Resolve(AssemblyNameReference.Parse("mscorlib"));
handle = FindType(mscorlib, typeNameParts);
if (handle.IsNil)
throw new NotImplementedException();
module = mscorlib;
}
var metadata = module.GetMetadataReader();
if (handle.IsNil || !handle.IsEnum(metadata, out var typeCode))
throw new NotSupportedException();
typeDefinition = new Metadata.TypeDefinition(module, handle);
return (PrimitiveSerializationTypeCode)typeCode;
}
}
object ReadArgumentValue(ref BlobReader blob, PrimitiveSerializationTypeCode typeCode, TypeKind kind, bool isArray, string typeName)
{
if (isArray) {
uint elementCount = blob.ReadUInt32();
if (elementCount == 0xFFFF_FFFF) {
return null;
} else {
var array = new object[elementCount];
for (int i = 0; i < elementCount; i++) {
array[i] = ReadSimpleArgumentValue(ref blob, typeCode, kind, typeName);
}
return array;
}
} else {
return ReadSimpleArgumentValue(ref blob, typeCode, kind, typeName);
}
}
void WritePrimitiveTypeCode(PrimitiveSerializationTypeCode typeCode)
{
switch (typeCode) {
case PrimitiveSerializationTypeCode.Boolean:
output.Write("bool");
break;
case PrimitiveSerializationTypeCode.Byte:
output.Write("uint8");
break;
case PrimitiveSerializationTypeCode.SByte:
output.Write("int8");
break;
case PrimitiveSerializationTypeCode.Char:
output.Write("char");
break;
case PrimitiveSerializationTypeCode.Int16:
output.Write("int16");
break;
case PrimitiveSerializationTypeCode.UInt16:
output.Write("uint16");
break;
case PrimitiveSerializationTypeCode.Int32:
output.Write("int32");
break;
case PrimitiveSerializationTypeCode.UInt32:
output.Write("uint32");
break;
case PrimitiveSerializationTypeCode.Int64:
output.Write("int64");
break;
case PrimitiveSerializationTypeCode.UInt64:
output.Write("uint64");
break;
case PrimitiveSerializationTypeCode.Single:
output.Write("float32");
break;
case PrimitiveSerializationTypeCode.Double:
output.Write("float64");
break;
case PrimitiveSerializationTypeCode.String:
output.Write("string");
break;
}
}
void WriteSecurityDeclarationArgument(PEFile module, ref BlobReader blob)
{
var decoder = new BlobDecoder(blob);
var namedArg = decoder.ReadNamedArg();
switch (blob.ReadByte()) {
case 0x53:
output.Write("field ");
@ -385,31 +585,70 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -385,31 +585,70 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write("property ");
break;
}
blob.Offset = decoder.Offset;
var value = namedArg.Value.ConstantValue;
string typeName = DisassemblerHelpers.PrimitiveTypeName(value.GetType().FullName);
if (typeName != null) {
output.Write(typeName);
} else {
namedArg.Value.Type.WriteTo(output);
var typeInfo = ReadArgumentType(ref blob);
var typeCode = typeInfo.TypeCode;
var typeDefinition = default(Metadata.TypeDefinition);
if (typeInfo.Kind == TypeKind.Enum) {
typeCode = ResolveEnumUnderlyingType(typeInfo.TypeName, module, out typeDefinition);
}
var name = blob.ReadSerializedString();
object value = ReadArgumentValue(ref blob, typeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName);
WriteTypeInfo(typeInfo.TypeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName, typeDefinition, module);
output.Write(' ');
output.Write(DisassemblerHelpers.Escape(namedArg.Key));
output.Write(DisassemblerHelpers.Escape(name));
output.Write(" = ");
if (value is string) {
// secdecls use special syntax for strings
output.Write("string('{0}')", DisassemblerHelpers.EscapeString((string)value).Replace("'", "\'"));
} else {
if (typeName != null) {
output.Write(typeName);
if (typeInfo.Kind == TypeKind.Enum || typeInfo.Kind == TypeKind.Primitive) {
WritePrimitiveTypeCode(typeCode);
} else {
namedArg.Value.Type.WriteTo(output);
WriteTypeInfo(typeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName, typeDefinition, module);
}
output.Write('(');
DisassemblerHelpers.WriteOperand(output, value);
output.Write(')');
}
}
private void WriteTypeInfo(PrimitiveSerializationTypeCode typeCode, TypeKind kind, bool isArray, string typeName, Metadata.TypeDefinition type, PEFile currentModule)
{
switch (kind) {
case TypeKind.Primitive:
WritePrimitiveTypeCode(typeCode);
break;
case TypeKind.Type:
break;
case TypeKind.Boxed:
break;
case TypeKind.Enum:
output.Write("enum ");
if (type.IsNil) {
output.Write(DisassemblerHelpers.Escape(typeName));
break;
}
var referencedModule = type.Module;
if (referencedModule != currentModule) {
output.Write('[');
output.Write(referencedModule.Name);
output.Write(']');
output.WriteReference(type.Handle.GetFullTypeName(type.Module.GetMetadataReader()).ToString(), type);
} else {
output.Write(DisassemblerHelpers.Escape(typeName));
}
break;
default:
break;
}
if (isArray) {
output.Write("[]");
}
}
#endregion
#region WriteMarshalInfo
@ -585,8 +824,10 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -585,8 +824,10 @@ namespace ICSharpCode.Decompiler.Disassembler
case 0x1e: // FixedArray
output.Write("fixed array");
output.Write("[{0}]", blob.TryReadCompressedInteger(out value) ? value : 0);
output.Write(' ');
WriteNativeType(ref blob);
if (blob.RemainingBytes > 0) {
output.Write(' ');
WriteNativeType(ref blob);
}
break;
case 0x22: // ByValStr
output.Write("byvalstr");
@ -650,7 +891,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -650,7 +891,7 @@ namespace ICSharpCode.Decompiler.Disassembler
WriteMarshalInfo(metadata.GetBlobReader(md));
}
output.WriteDefinition(DisassemblerHelpers.Escape(metadata.GetString(p.Name)), p);
if (i < parameters.Length - 1)
if (i < signature.ParameterTypes.Length - 1)
output.Write(',');
output.WriteLine();
}
@ -743,7 +984,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -743,7 +984,8 @@ namespace ICSharpCode.Decompiler.Disassembler
signature(ILNameSyntax.Signature);
output.Write(' ');
output.Write(DisassemblerHelpers.Escape(metadata.GetString(fieldDefinition.Name)));
var fieldName = metadata.GetString(fieldDefinition.Name);
output.Write(DisassemblerHelpers.Escape(fieldName));
if (fieldDefinition.HasFlag(FieldAttributes.HasFieldRVA)) {
output.Write(" at I_{0:x8}", fieldDefinition.GetRelativeVirtualAddress());
}
@ -786,15 +1028,17 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -786,15 +1028,17 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(' ');
output.Write(DisassemblerHelpers.Escape(metadata.GetString(propertyDefinition.Name)));
output.Write("(");
var parameters = metadata.GetMethodDefinition(accessors.Getter).GetParameters();
if (parameters.Count > 0) {
output.Write('(');
if (signature.ParameterTypes.Length > 0) {
var parameters = metadata.GetMethodDefinition(accessors.GetAny()).GetParameters();
int parametersCount = accessors.Getter.IsNil ? parameters.Count - 1 : parameters.Count;
output.WriteLine();
output.Indent();
WriteParameters(metadata, parameters.ToArray(), signature);
WriteParameters(metadata, parameters.Take(parametersCount).ToArray(), signature);
output.Unindent();
}
output.Write(")");
output.Write(')');
OpenBlock(false);
WriteAttributes(property.Module, propertyDefinition.GetCustomAttributes());
@ -1275,8 +1519,13 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1275,8 +1519,13 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine(".module {0}", metadata.GetString(moduleDefinition.Name));
output.WriteLine("// MVID: {0}", metadata.GetGuid(moduleDefinition.Mvid).ToString("B").ToUpperInvariant());
// TODO: imagebase, file alignment, stackreserve, subsystem
output.WriteLine(".corflags 0x{0:x} // {1}", module.Reader.PEHeaders.CorHeader.Flags, module.Reader.PEHeaders.CorHeader.Flags.ToString());
var headers = module.Reader.PEHeaders;
output.WriteLine(".imagebase 0x{0:x8}", headers.PEHeader.ImageBase);
output.WriteLine(".file alignment 0x{0:x8}", headers.PEHeader.FileAlignment);
output.WriteLine(".stackreserve 0x{0:x8}", headers.PEHeader.SizeOfStackReserve);
output.WriteLine(".subsystem 0x{0:x} // {1}", headers.PEHeader.Subsystem, headers.PEHeader.Subsystem.ToString());
output.WriteLine(".corflags 0x{0:x} // {1}", headers.CorHeader.Flags, headers.CorHeader.Flags.ToString());
WriteAttributes(module, metadata.GetCustomAttributes(EntityHandle.ModuleDefinition));
}
@ -1391,7 +1640,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1391,7 +1640,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (param.Name.IsNil)
output.Write(param.Index.ToString());
else
output.Write(DisassemblerHelpers.EscapeString(metadata.GetString(param.Name)));
output.Write(DisassemblerHelpers.Escape(metadata.GetString(param.Name)));
}
}
@ -1462,6 +1711,10 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1462,6 +1711,10 @@ namespace ICSharpCode.Decompiler.Disassembler
return syntax => output.Write("object");
case PrimitiveTypeCode.IntPtr:
return syntax => output.Write("native int");
case PrimitiveTypeCode.UIntPtr:
return syntax => output.Write("native uint");
case PrimitiveTypeCode.TypedReference:
return syntax => output.Write("typedref");
default:
throw new ArgumentOutOfRangeException();
}

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -268,7 +268,6 @@ @@ -268,7 +268,6 @@
<Compile Include="CSharp\Transforms\ReplaceMethodCallsWithOperators.cs" />
<Compile Include="CSharp\WholeProjectDecompiler.cs" />
<Compile Include="CSharp\Transforms\AddXmlDocumentationTransform.cs" />
<Compile Include="Disassembler\BlobDecoder.cs" />
<Compile Include="Disassembler\DomExtensions.cs" />
<Compile Include="Disassembler\OpCodeInfo.cs" />
<Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" />

20
ICSharpCode.Decompiler/SRMExtensions.cs

@ -44,6 +44,26 @@ namespace ICSharpCode.Decompiler @@ -44,6 +44,26 @@ namespace ICSharpCode.Decompiler
return typeDefinition.BaseType.GetFullTypeName(reader).ToString() == "System.Enum";
}
public static bool IsEnum(this TypeDefinitionHandle handle, MetadataReader reader, out PrimitiveTypeCode underlyingType)
{
return reader.GetTypeDefinition(handle).IsEnum(reader, out underlyingType);
}
public static bool IsEnum(this TypeDefinition typeDefinition, MetadataReader reader, out PrimitiveTypeCode underlyingType)
{
underlyingType = 0;
if (typeDefinition.BaseType.IsNil)
return false;
if (typeDefinition.BaseType.GetFullTypeName(reader).ToString() != "System.Enum")
return false;
var field = reader.GetFieldDefinition(typeDefinition.GetFields().First());
var blob = reader.GetBlobReader(field.Signature);
if (blob.ReadSignatureHeader().Kind != SignatureKind.Field)
return false;
underlyingType = (PrimitiveTypeCode)blob.ReadByte();
return true;
}
public static bool IsDelegate(this TypeDefinitionHandle handle, MetadataReader reader)
{
return reader.GetTypeDefinition(handle).IsDelegate(reader);

Loading…
Cancel
Save