From 6065030a24276bc046288d48aa29104c910d6469 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 18 Feb 2018 10:55:36 -0300 Subject: [PATCH] Replace BlobDecoder with solution not relying on TypeSystem --- .../Disassembler/BlobDecoder.cs | 219 ------------ .../Disassembler/ReflectionDisassembler.cs | 319 ++++++++++++++++-- .../ICSharpCode.Decompiler.csproj | 1 - ICSharpCode.Decompiler/SRMExtensions.cs | 20 ++ 4 files changed, 306 insertions(+), 253 deletions(-) delete mode 100644 ICSharpCode.Decompiler/Disassembler/BlobDecoder.cs diff --git a/ICSharpCode.Decompiler/Disassembler/BlobDecoder.cs b/ICSharpCode.Decompiler/Disassembler/BlobDecoder.cs deleted file mode 100644 index 3905464fc..000000000 --- a/ICSharpCode.Decompiler/Disassembler/BlobDecoder.cs +++ /dev/null @@ -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 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(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; - } - } - } -} \ No newline at end of file diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index e9f9592df..e7bdf23f1 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -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 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 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 output.Indent(); for (int j = 0; j < argCount; j++) { - WriteSecurityDeclarationArgument(ref blob); + WriteSecurityDeclarationArgument(module, ref blob); output.WriteLine(); } @@ -372,11 +382,201 @@ namespace ICSharpCode.Decompiler.Disassembler output.WriteLine("}"); } } - - 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 typeDefinitions = default(ImmutableArray); + + 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 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 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 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 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 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 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 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 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(); } diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 35971907b..cb3907708 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -268,7 +268,6 @@ - diff --git a/ICSharpCode.Decompiler/SRMExtensions.cs b/ICSharpCode.Decompiler/SRMExtensions.cs index 33cab8af3..666890b7e 100644 --- a/ICSharpCode.Decompiler/SRMExtensions.cs +++ b/ICSharpCode.Decompiler/SRMExtensions.cs @@ -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);