Browse Source

Move PEFile and other classes to different files, cleanup

pull/1198/head
Siegfried Pammer 7 years ago
parent
commit
e6e03a40d4
  1. 2
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  2. 198
      ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs
  3. 349
      ICSharpCode.Decompiler/Metadata/Dom.cs
  4. 20
      ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs
  5. 20
      ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs
  6. 5
      ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
  7. 20
      ICSharpCode.Decompiler/Metadata/MetadataResolver.cs
  8. 194
      ICSharpCode.Decompiler/Metadata/PEFile.cs
  9. 26
      ICSharpCode.Decompiler/Metadata/SequencePoint.cs
  10. 20
      ICSharpCode.Decompiler/Metadata/SignatureBlobComparer.cs
  11. 23
      ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
  12. 20
      ICSharpCode.Decompiler/Metadata/UnresolvedAssemblyNameReference.cs

2
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -269,6 +269,7 @@ @@ -269,6 +269,7 @@
<Compile Include="CSharp\Transforms\AddXmlDocumentationTransform.cs" />
<Compile Include="DecompileRun.cs" />
<Compile Include="Disassembler\DomExtensions.cs" />
<Compile Include="Metadata\AssemblyReferences.cs" />
<Compile Include="Metadata\MetadataTokenHelpers.cs" />
<Compile Include="Disassembler\OpCodeInfo.cs" />
<Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" />
@ -295,6 +296,7 @@ @@ -295,6 +296,7 @@
<Compile Include="Metadata\LightJson\Serialization\TextScanner.cs" />
<Compile Include="Metadata\MethodSemanticsLookup.cs" />
<Compile Include="Metadata\OperandType.cs" />
<Compile Include="Metadata\PEFile.cs" />
<Compile Include="Metadata\SignatureBlobComparer.cs" />
<Compile Include="Metadata\UniversalAssemblyResolver.cs" />
<Compile Include="Metadata\UnresolvedAssemblyNameReference.cs" />

198
ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs

@ -0,0 +1,198 @@ @@ -0,0 +1,198 @@
// Copyright (c) 2018 Siegfried Pammer
//
// 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 System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Security.Cryptography;
using System.Text;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Metadata
{
public sealed class AssemblyResolutionException : FileNotFoundException
{
public IAssemblyReference Reference { get; }
public AssemblyResolutionException(IAssemblyReference reference)
: this(reference, null)
{
}
public AssemblyResolutionException(IAssemblyReference reference, Exception innerException)
: base($"Failed to resolve assembly: '{reference}'", innerException)
{
this.Reference = reference;
}
}
public interface IAssemblyResolver
{
PEFile Resolve(IAssemblyReference reference);
}
public interface IAssemblyReference
{
string Name { get; }
string FullName { get; }
Version Version { get; }
string Culture { get; }
byte[] PublicKeyToken { get; }
bool IsWindowsRuntime { get; }
bool IsRetargetable { get; }
}
public class AssemblyNameReference : IAssemblyReference
{
string fullName;
public string Name { get; private set; }
public string FullName {
get {
if (fullName != null)
return fullName;
const string sep = ", ";
var builder = new StringBuilder();
builder.Append(Name);
builder.Append(sep);
builder.Append("Version=");
builder.Append(Version.ToString(fieldCount: 4));
builder.Append(sep);
builder.Append("Culture=");
builder.Append(string.IsNullOrEmpty(Culture) ? "neutral" : Culture);
builder.Append(sep);
builder.Append("PublicKeyToken=");
var pk_token = PublicKeyToken;
if (pk_token != null && pk_token.Length > 0) {
for (int i = 0; i < pk_token.Length; i++) {
builder.Append(pk_token[i].ToString("x2"));
}
} else
builder.Append("null");
if (IsRetargetable) {
builder.Append(sep);
builder.Append("Retargetable=Yes");
}
return fullName = builder.ToString();
}
}
public Version Version { get; private set; }
public string Culture { get; private set; }
public byte[] PublicKeyToken { get; private set; }
public bool IsWindowsRuntime { get; private set; }
public bool IsRetargetable { get; private set; }
public static AssemblyNameReference Parse(string fullName)
{
if (fullName == null)
throw new ArgumentNullException("fullName");
if (fullName.Length == 0)
throw new ArgumentException("Name can not be empty");
var name = new AssemblyNameReference();
var tokens = fullName.Split(',');
for (int i = 0; i < tokens.Length; i++) {
var token = tokens[i].Trim();
if (i == 0) {
name.Name = token;
continue;
}
var parts = token.Split('=');
if (parts.Length != 2)
throw new ArgumentException("Malformed name");
switch (parts[0].ToLowerInvariant()) {
case "version":
name.Version = new Version(parts[1]);
break;
case "culture":
name.Culture = parts[1] == "neutral" ? "" : parts[1];
break;
case "publickeytoken":
var pk_token = parts[1];
if (pk_token == "null")
break;
name.PublicKeyToken = new byte[pk_token.Length / 2];
for (int j = 0; j < name.PublicKeyToken.Length; j++)
name.PublicKeyToken[j] = Byte.Parse(pk_token.Substring(j * 2, 2), System.Globalization.NumberStyles.HexNumber);
break;
}
}
return name;
}
}
public class AssemblyReference : IAssemblyReference
{
static readonly SHA1 sha1 = SHA1.Create();
public PEFile Module { get; }
public AssemblyReferenceHandle Handle { get; }
System.Reflection.Metadata.AssemblyReference This() => Module.Metadata.GetAssemblyReference(Handle);
public bool IsWindowsRuntime => (This().Flags & AssemblyFlags.WindowsRuntime) != 0;
public bool IsRetargetable => (This().Flags & AssemblyFlags.Retargetable) != 0;
public string Name => Module.Metadata.GetString(This().Name);
public string FullName => This().GetFullAssemblyName(Module.Metadata);
public Version Version => This().Version;
public string Culture => Module.Metadata.GetString(This().Culture);
byte[] IAssemblyReference.PublicKeyToken => GetPublicKeyToken();
public byte[] GetPublicKeyToken()
{
var inst = This();
if (inst.PublicKeyOrToken.IsNil)
return Empty<byte>.Array;
var bytes = Module.Metadata.GetBlobBytes(inst.PublicKeyOrToken);
if ((inst.Flags & AssemblyFlags.PublicKey) != 0) {
return sha1.ComputeHash(bytes).Skip(12).ToArray();
}
return bytes;
}
public AssemblyReference(PEFile module, AssemblyReferenceHandle handle)
{
Module = module ?? throw new ArgumentNullException(nameof(module));
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
Handle = handle;
}
}
}

349
ICSharpCode.Decompiler/Metadata/Dom.cs

@ -26,38 +26,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -26,38 +26,7 @@ namespace ICSharpCode.Decompiler.Metadata
using SRMTypeSpec = System.Reflection.Metadata.TypeSpecification;
using SRMAssemblyReference = System.Reflection.Metadata.AssemblyReference;
public sealed class AssemblyResolutionException : FileNotFoundException
{
public IAssemblyReference Reference { get; }
public AssemblyResolutionException(IAssemblyReference reference)
: this(reference, null)
{
}
public AssemblyResolutionException(IAssemblyReference reference, Exception innerException)
: base($"Failed to resolve assembly: '{reference}'", innerException)
{
this.Reference = reference;
}
}
public interface IAssemblyResolver
{
PEFile Resolve(IAssemblyReference reference);
}
public interface IAssemblyReference
{
string Name { get; }
string FullName { get; }
Version Version { get; }
string Culture { get; }
byte[] PublicKeyToken { get; }
bool IsWindowsRuntime { get; }
bool IsRetargetable { get; }
}
public interface IAssemblyDocumentationResolver
{
@ -92,170 +61,6 @@ namespace ICSharpCode.Decompiler.Metadata @@ -92,170 +61,6 @@ namespace ICSharpCode.Decompiler.Metadata
Net_4_0
}
public class PEFile : IDisposable, TypeSystem.IAssemblyReference
{
public string FileName { get; }
public PEReader Reader { get; }
public MetadataReader Metadata { get; }
public IAssemblyResolver AssemblyResolver { get; }
public IAssemblyDocumentationResolver DocumentationResolver { get; set; }
public IDebugInfoProvider DebugInfo { get; set; }
public PEFile(string fileName, Stream stream, bool throwOnResolveError = false, PEStreamOptions options = PEStreamOptions.Default)
{
this.FileName = fileName;
this.Reader = new PEReader(stream, options);
this.Metadata = Reader.GetMetadataReader();
this.AssemblyResolver = new UniversalAssemblyResolver(fileName, throwOnResolveError, Reader.DetectTargetFrameworkId(), options);
}
public PEFile(string fileName, Stream stream, IAssemblyResolver assemblyResolver, PEStreamOptions options = PEStreamOptions.Default)
{
this.FileName = fileName;
this.Reader = new PEReader(stream, options);
this.Metadata = Reader.GetMetadataReader();
this.AssemblyResolver = assemblyResolver;
}
public bool IsAssembly => Metadata.IsAssembly;
public string Name => GetName();
public string FullName => IsAssembly ? Metadata.GetFullAssemblyName() : Name;
public TargetRuntime GetRuntime()
{
string version = Metadata.MetadataVersion;
switch (version[1]) {
case '1':
if (version[3] == 1)
return TargetRuntime.Net_1_0;
else
return TargetRuntime.Net_1_1;
case '2':
return TargetRuntime.Net_2_0;
case '4':
return TargetRuntime.Net_4_0;
default:
return TargetRuntime.Unknown;
}
}
string GetName()
{
var metadata = Metadata;
if (metadata.IsAssembly)
return metadata.GetString(metadata.GetAssemblyDefinition().Name);
return metadata.GetString(metadata.GetModuleDefinition().Name);
}
public ImmutableArray<AssemblyReference> AssemblyReferences => Metadata.AssemblyReferences.Select(r => new AssemblyReference(this, r)).ToImmutableArray();
public ImmutableArray<ModuleReferenceHandle> ModuleReferences => Metadata.GetModuleReferences().ToImmutableArray();
public ImmutableArray<TypeDefinition> TopLevelTypeDefinitions => Metadata.GetTopLevelTypeDefinitions().Select(t => new TypeDefinition(this, t)).ToImmutableArray();
public ImmutableArray<Resource> Resources => GetResources().ToImmutableArray();
IEnumerable<Resource> GetResources()
{
var metadata = Metadata;
foreach (var h in metadata.ManifestResources) {
yield return new Resource(this, h);
}
}
public void Dispose()
{
Reader.Dispose();
}
Dictionary<TopLevelTypeName, TypeDefinitionHandle> typeLookup;
/// <summary>
/// Finds the top-level-type with the specified name.
/// </summary>
public TypeDefinitionHandle GetTypeDefinition(TopLevelTypeName typeName)
{
var lookup = LazyInit.VolatileRead(ref typeLookup);
if (lookup == null) {
lookup = new Dictionary<TopLevelTypeName, TypeDefinitionHandle>();
foreach (var handle in Metadata.TypeDefinitions) {
var td = Metadata.GetTypeDefinition(handle);
if (!td.GetDeclaringType().IsNil) {
continue; // nested type
}
var nsHandle = td.Namespace;
string ns = nsHandle.IsNil ? string.Empty : Metadata.GetString(nsHandle);
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(Metadata.GetString(td.Name), out int typeParameterCount);
lookup[new TopLevelTypeName(ns, name, typeParameterCount)] = handle;
}
lookup = LazyInit.GetOrSet(ref typeLookup, lookup);
}
if (lookup.TryGetValue(typeName, out var resultHandle))
return resultHandle;
else
return default;
}
Dictionary<FullTypeName, ExportedTypeHandle> typeForwarderLookup;
/// <summary>
/// Finds the type forwarder with the specified name.
/// </summary>
public ExportedTypeHandle GetTypeForwarder(FullTypeName typeName)
{
var lookup = LazyInit.VolatileRead(ref typeForwarderLookup);
if (lookup == null) {
lookup = new Dictionary<FullTypeName, ExportedTypeHandle>();
foreach (var handle in Metadata.ExportedTypes) {
var td = Metadata.GetExportedType(handle);
lookup[td.GetFullTypeName(Metadata)] = handle;
}
lookup = LazyInit.GetOrSet(ref typeForwarderLookup, lookup);
}
if (lookup.TryGetValue(typeName, out var resultHandle))
return resultHandle;
else
return default;
}
MethodSemanticsLookup methodSemanticsLookup;
internal MethodSemanticsLookup MethodSemanticsLookup {
get {
var r = LazyInit.VolatileRead(ref methodSemanticsLookup);
if (r != null)
return r;
else
return LazyInit.GetOrSet(ref methodSemanticsLookup, new MethodSemanticsLookup(Metadata));
}
}
public TypeSystem.IAssemblyReference WithOptions(TypeSystemOptions options)
{
return new PEFileWithOptions(this, options);
}
IAssembly TypeSystem.IAssemblyReference.Resolve(ITypeResolveContext context)
{
return new MetadataAssembly(context.Compilation, this, TypeSystemOptions.Default);
}
private class PEFileWithOptions : TypeSystem.IAssemblyReference
{
readonly PEFile peFile;
readonly TypeSystemOptions options;
public PEFileWithOptions(PEFile peFile, TypeSystemOptions options)
{
this.peFile = peFile;
this.options = options;
}
IAssembly TypeSystem.IAssemblyReference.Resolve(ITypeResolveContext context)
{
return new MetadataAssembly(context.Compilation, peFile, options);
}
}
}
public enum ResourceType
{
Linked,
@ -331,160 +136,6 @@ namespace ICSharpCode.Decompiler.Metadata @@ -331,160 +136,6 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
public class AssemblyNameReference : IAssemblyReference
{
string fullName;
public string Name { get; private set; }
public string FullName {
get {
if (fullName != null)
return fullName;
const string sep = ", ";
var builder = new StringBuilder();
builder.Append(Name);
builder.Append(sep);
builder.Append("Version=");
builder.Append(Version.ToString(fieldCount: 4));
builder.Append(sep);
builder.Append("Culture=");
builder.Append(string.IsNullOrEmpty(Culture) ? "neutral" : Culture);
builder.Append(sep);
builder.Append("PublicKeyToken=");
var pk_token = PublicKeyToken;
if (pk_token != null && pk_token.Length > 0) {
for (int i = 0; i < pk_token.Length; i++) {
builder.Append(pk_token[i].ToString("x2"));
}
} else
builder.Append("null");
if (IsRetargetable) {
builder.Append(sep);
builder.Append("Retargetable=Yes");
}
return fullName = builder.ToString();
}
}
public Version Version { get; private set; }
public string Culture { get; private set; }
public byte[] PublicKeyToken { get; private set; }
public bool IsWindowsRuntime { get; private set; }
public bool IsRetargetable { get; private set; }
public static AssemblyNameReference Parse(string fullName)
{
if (fullName == null)
throw new ArgumentNullException("fullName");
if (fullName.Length == 0)
throw new ArgumentException("Name can not be empty");
var name = new AssemblyNameReference();
var tokens = fullName.Split(',');
for (int i = 0; i < tokens.Length; i++) {
var token = tokens[i].Trim();
if (i == 0) {
name.Name = token;
continue;
}
var parts = token.Split('=');
if (parts.Length != 2)
throw new ArgumentException("Malformed name");
switch (parts[0].ToLowerInvariant()) {
case "version":
name.Version = new Version(parts[1]);
break;
case "culture":
name.Culture = parts[1] == "neutral" ? "" : parts[1];
break;
case "publickeytoken":
var pk_token = parts[1];
if (pk_token == "null")
break;
name.PublicKeyToken = new byte[pk_token.Length / 2];
for (int j = 0; j < name.PublicKeyToken.Length; j++)
name.PublicKeyToken[j] = Byte.Parse(pk_token.Substring(j * 2, 2), System.Globalization.NumberStyles.HexNumber);
break;
}
}
return name;
}
}
public struct AssemblyReference : IAssemblyReference, IEquatable<AssemblyReference>
{
static readonly SHA1 sha1 = SHA1.Create();
public PEFile Module { get; }
public AssemblyReferenceHandle Handle { get; }
public bool IsNil => Handle.IsNil;
SRMAssemblyReference This() => Module.Metadata.GetAssemblyReference(Handle);
public bool IsWindowsRuntime => (This().Flags & AssemblyFlags.WindowsRuntime) != 0;
public bool IsRetargetable => (This().Flags & AssemblyFlags.Retargetable) != 0;
public string Name => Module.Metadata.GetString(This().Name);
public string FullName => This().GetFullAssemblyName(Module.Metadata);
public Version Version => This().Version;
public string Culture => Module.Metadata.GetString(This().Culture);
byte[] IAssemblyReference.PublicKeyToken => GetPublicKeyToken();
public byte[] GetPublicKeyToken()
{
var inst = This();
if (inst.PublicKeyOrToken.IsNil)
return Empty<byte>.Array;
var bytes = Module.Metadata.GetBlobBytes(inst.PublicKeyOrToken);
if ((inst.Flags & AssemblyFlags.PublicKey) != 0) {
return sha1.ComputeHash(bytes).Skip(12).ToArray();
}
return bytes;
}
public bool Equals(AssemblyReference other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is AssemblyReference reference)
return Equals(reference);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(AssemblyReference lhs, AssemblyReference rhs) => lhs.Equals(rhs);
public static bool operator !=(AssemblyReference lhs, AssemblyReference rhs) => !lhs.Equals(rhs);
public AssemblyReference(PEFile module, AssemblyReferenceHandle handle)
{
Module = module;
Handle = handle;
}
}
public struct Entity : IEquatable<Entity>, IMetadataEntity
{
public PEFile Module { get; }

20
ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System;
// Copyright (c) 2018 Siegfried Pammer
//
// 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 System.Diagnostics;
using System.IO;

20
ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System;
// Copyright (c) 2018 Siegfried Pammer
//
// 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 System.Linq;
using System.Reflection.Metadata;

5
ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs

@ -18,11 +18,6 @@ namespace ICSharpCode.Decompiler.Metadata @@ -18,11 +18,6 @@ namespace ICSharpCode.Decompiler.Metadata
{
public static class MetadataExtensions
{
public static bool IsNil(this IAssemblyReference reference)
{
return reference == null || (reference is Metadata.AssemblyReference ar && ar.IsNil);
}
public static string GetFullAssemblyName(this MetadataReader reader)
{
if (!reader.IsAssembly)

20
ICSharpCode.Decompiler/Metadata/MetadataResolver.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System;
// Copyright (c) 2018 Siegfried Pammer
//
// 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 System.Collections.Immutable;
using System.Diagnostics;

194
ICSharpCode.Decompiler/Metadata/PEFile.cs

@ -0,0 +1,194 @@ @@ -0,0 +1,194 @@
// Copyright (c) 2018 Siegfried Pammer
//
// 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 System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Metadata
{
public class PEFile : IDisposable, TypeSystem.IAssemblyReference
{
public string FileName { get; }
public PEReader Reader { get; }
public MetadataReader Metadata { get; }
public IAssemblyResolver AssemblyResolver { get; }
public IAssemblyDocumentationResolver DocumentationResolver { get; set; }
public IDebugInfoProvider DebugInfo { get; set; }
public PEFile(string fileName, Stream stream, bool throwOnResolveError = false, PEStreamOptions options = PEStreamOptions.Default)
{
this.FileName = fileName;
this.Reader = new PEReader(stream, options);
this.Metadata = Reader.GetMetadataReader();
this.AssemblyResolver = new UniversalAssemblyResolver(fileName, throwOnResolveError, Reader.DetectTargetFrameworkId(), options);
}
public PEFile(string fileName, Stream stream, IAssemblyResolver assemblyResolver, PEStreamOptions options = PEStreamOptions.Default)
{
this.FileName = fileName;
this.Reader = new PEReader(stream, options);
this.Metadata = Reader.GetMetadataReader();
this.AssemblyResolver = assemblyResolver;
}
public bool IsAssembly => Metadata.IsAssembly;
public string Name => GetName();
public string FullName => IsAssembly ? Metadata.GetFullAssemblyName() : Name;
public TargetRuntime GetRuntime()
{
string version = Metadata.MetadataVersion;
switch (version[1]) {
case '1':
if (version[3] == 1)
return TargetRuntime.Net_1_0;
else
return TargetRuntime.Net_1_1;
case '2':
return TargetRuntime.Net_2_0;
case '4':
return TargetRuntime.Net_4_0;
default:
return TargetRuntime.Unknown;
}
}
string GetName()
{
var metadata = Metadata;
if (metadata.IsAssembly)
return metadata.GetString(metadata.GetAssemblyDefinition().Name);
return metadata.GetString(metadata.GetModuleDefinition().Name);
}
public ImmutableArray<AssemblyReference> AssemblyReferences => Metadata.AssemblyReferences.Select(r => new AssemblyReference(this, r)).ToImmutableArray();
public ImmutableArray<ModuleReferenceHandle> ModuleReferences => Metadata.GetModuleReferences().ToImmutableArray();
public ImmutableArray<TypeDefinition> TopLevelTypeDefinitions => Metadata.GetTopLevelTypeDefinitions().Select(t => new TypeDefinition(this, t)).ToImmutableArray();
public ImmutableArray<Resource> Resources => GetResources().ToImmutableArray();
IEnumerable<Resource> GetResources()
{
var metadata = Metadata;
foreach (var h in metadata.ManifestResources) {
yield return new Resource(this, h);
}
}
public void Dispose()
{
Reader.Dispose();
}
Dictionary<TopLevelTypeName, TypeDefinitionHandle> typeLookup;
/// <summary>
/// Finds the top-level-type with the specified name.
/// </summary>
public TypeDefinitionHandle GetTypeDefinition(TopLevelTypeName typeName)
{
var lookup = LazyInit.VolatileRead(ref typeLookup);
if (lookup == null) {
lookup = new Dictionary<TopLevelTypeName, TypeDefinitionHandle>();
foreach (var handle in Metadata.TypeDefinitions) {
var td = Metadata.GetTypeDefinition(handle);
if (!td.GetDeclaringType().IsNil) {
continue; // nested type
}
var nsHandle = td.Namespace;
string ns = nsHandle.IsNil ? string.Empty : Metadata.GetString(nsHandle);
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(Metadata.GetString(td.Name), out int typeParameterCount);
lookup[new TopLevelTypeName(ns, name, typeParameterCount)] = handle;
}
lookup = LazyInit.GetOrSet(ref typeLookup, lookup);
}
if (lookup.TryGetValue(typeName, out var resultHandle))
return resultHandle;
else
return default;
}
Dictionary<FullTypeName, ExportedTypeHandle> typeForwarderLookup;
/// <summary>
/// Finds the type forwarder with the specified name.
/// </summary>
public ExportedTypeHandle GetTypeForwarder(FullTypeName typeName)
{
var lookup = LazyInit.VolatileRead(ref typeForwarderLookup);
if (lookup == null) {
lookup = new Dictionary<FullTypeName, ExportedTypeHandle>();
foreach (var handle in Metadata.ExportedTypes) {
var td = Metadata.GetExportedType(handle);
lookup[td.GetFullTypeName(Metadata)] = handle;
}
lookup = LazyInit.GetOrSet(ref typeForwarderLookup, lookup);
}
if (lookup.TryGetValue(typeName, out var resultHandle))
return resultHandle;
else
return default;
}
MethodSemanticsLookup methodSemanticsLookup;
internal MethodSemanticsLookup MethodSemanticsLookup {
get {
var r = LazyInit.VolatileRead(ref methodSemanticsLookup);
if (r != null)
return r;
else
return LazyInit.GetOrSet(ref methodSemanticsLookup, new MethodSemanticsLookup(Metadata));
}
}
public TypeSystem.IAssemblyReference WithOptions(TypeSystemOptions options)
{
return new PEFileWithOptions(this, options);
}
IAssembly TypeSystem.IAssemblyReference.Resolve(ITypeResolveContext context)
{
return new MetadataAssembly(context.Compilation, this, TypeSystemOptions.Default);
}
private class PEFileWithOptions : TypeSystem.IAssemblyReference
{
readonly PEFile peFile;
readonly TypeSystemOptions options;
public PEFileWithOptions(PEFile peFile, TypeSystemOptions options)
{
this.peFile = peFile;
this.options = options;
}
IAssembly TypeSystem.IAssemblyReference.Resolve(ITypeResolveContext context)
{
return new MetadataAssembly(context.Compilation, peFile, options);
}
}
}
}

26
ICSharpCode.Decompiler/Metadata/SequencePoint.cs

@ -1,13 +1,25 @@ @@ -1,13 +1,25 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
// Copyright (c) 2018 Daniel Grunwald
//
// 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;
namespace ICSharpCode.Decompiler.Metadata
{
using SRMDocument = System.Reflection.Metadata.Document;
/// <summary>
/// A sequence point read from a PDB file or produced by the decompiler.
/// </summary>

20
ICSharpCode.Decompiler/Metadata/SignatureBlobComparer.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System.Reflection.Metadata;
// Copyright (c) 2018 Siegfried Pammer
//
// 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.Reflection.Metadata;
namespace ICSharpCode.Decompiler.Metadata
{

23
ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System;
// Copyright (c) 2018 Siegfried Pammer
//
// 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 System.IO;
using System.Linq;
@ -7,6 +25,7 @@ using System.Text; @@ -7,6 +25,7 @@ using System.Text;
namespace ICSharpCode.Decompiler.Metadata
{
// This inspired by Mono.Cecil's BaseAssemblyResolver/DefaultAssemblyResolver.
public class UniversalAssemblyResolver : IAssemblyResolver
{
DotNetCorePathFinder dotNetCorePathFinder;
@ -141,7 +160,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -141,7 +160,7 @@ namespace ICSharpCode.Decompiler.Metadata
string ResolveInternal(IAssemblyReference name)
{
if (name.IsNil())
if (name == null)
throw new ArgumentNullException(nameof(name));
var assembly = SearchDirectory(name, directories);

20
ICSharpCode.Decompiler/Metadata/UnresolvedAssemblyNameReference.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System;
// Copyright (c) 2018 Siegfried Pammer
//
// 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 System.Linq;
using System.Text;

Loading…
Cancel
Save